/* * linux/arch/arm/mach-davinci/board-evm.c * * TI DaVinci EVM board * * Copyright (C) 2006 Texas Instruments. * * ---------------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ---------------------------------------------------------------------------- * */ /************************************************************************** * Included Files **************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "clock.h" #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) #define DO_MTD #include #include #include #include #include /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int my_atoi(char *p); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define MAX_FLASH_MTD 5 static struct mtd_partition davinci_evm_partitions[MAX_FLASH_MTD]; static char *probes[] = { "find_squashfs" , NULL }; static struct physmap_flash_data davinci_evm_flash_data = { .width = 2, .parts = davinci_evm_partitions, .nr_parts = ARRAY_SIZE(davinci_evm_partitions), .probes = probes }; /* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF * limits addresses to 16M, so using addresses past 16M will wrap */ static struct resource davinci_evm_flash_resource[2] = { { .start = DAVINCI_CS0_PHYS, .end = DAVINCI_CS0_PHYS + SZ_32M - 1, .flags = IORESOURCE_MEM, }, { /* für ins RAM geladenes Filesystem */ .start = 0x10000000, .end = 0x10000000 + (32 << 20) - 1, .flags = IORESOURCE_IO, } }; void davinci_ram_mtd_set_rw(struct device *pdev, int); struct platform_device davinci_evm_flash_device = { .name = "unknown-flash", .id = 1, .dev = { .platform_data = &davinci_evm_flash_data, }, .num_resources = 1, .resource = &davinci_evm_flash_resource[0], }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void set_flash_architecture(unsigned paged) { if(paged) { davinci_evm_flash_device.name = "pagedmap-flash"; } else { davinci_evm_flash_device.name = "physmap-flash"; } printk("[set_flash_architecture] davinci_evm_flash_device.name = %s\n", davinci_evm_flash_device.name); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static struct mtd_partition davinci_evm_ram_partitions[2]; static struct platdata_mtd_ram davinci_evm_ram_data = { .mapname = "ram-filesystem", .bankwidth = 4, .partitions = davinci_evm_ram_partitions, .nr_partitions = ARRAY_SIZE(davinci_evm_ram_partitions), .set_rw = davinci_ram_mtd_set_rw, .probes = probes }; struct platform_device davinci_evm_ram_device = { .name = "mtd-ram", .id = 2, .dev = { .platform_data = &davinci_evm_ram_data, }, .num_resources = 1, .resource = &davinci_evm_flash_resource[1], }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void davinci_ram_mtd_set_rw(struct device *pdev, int mode) { if(mode == PLATRAM_RO) { printk(KERN_ERR "[davinci_ram_mtd_set_rw] PLATRAM_RO\n"); } else if(mode == PLATRAM_RW) { printk(KERN_ERR "[davinci_ram_mtd_set_rw] PLATRAM_RW\n"); } } enum _flash_map_enum { MAP_UNKNOWN, MAP_RAM, MAP_FLASH }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int davinci_squashfs_parser_function(struct mtd_info *mtd, struct mtd_partition **p_mtd_pat, unsigned long param) { enum _flash_map_enum maptype = MAP_UNKNOWN; unsigned count = 1, maxcount = 0; printk("[davinci_squashfs_parser_function] mtd_info->name %s mtd_info->index %u param=%lu p_mtd_pat=0x%p\n", mtd->name, mtd->index, param, p_mtd_pat); if (!strcmp(mtd->name, "ram-filesystem")) { maptype = MAP_RAM; } else if (!strncmp(mtd->name, "physmap-flash", sizeof("physmap-flash") - 1)) { maptype = MAP_FLASH; } else if (!strncmp(mtd->name, "pagedmap-flash", sizeof("physmap-flash") - 1)) { maptype = MAP_FLASH; } else { printk(KERN_WARNING "[davinci_squashfs_parser_function] with unknown mtd type %s\n", mtd->name); return 0; } if(p_mtd_pat) { unsigned int magic = 0, readlen = 0; loff_t pos = 0; if(*p_mtd_pat) printk("[davinci_squashfs_parser_function] *p_mtd_pat->name %s\n", (*p_mtd_pat)->name); if(*p_mtd_pat == NULL) { switch (maptype) { case MAP_FLASH: *p_mtd_pat = davinci_evm_partitions; maxcount = ARRAY_SIZE(davinci_evm_partitions); break; case MAP_RAM: *p_mtd_pat = davinci_evm_ram_partitions; maxcount = ARRAY_SIZE(davinci_evm_ram_partitions); break; default: break; } } printk("[davinci_squashfs_parser_function] try partition %s (offset 0x%x len %u)\n", (*p_mtd_pat)[count].name, (*p_mtd_pat)[count].offset, (*p_mtd_pat)[count].size); pos = (*p_mtd_pat)[count].offset; while(pos < (*p_mtd_pat)[count].offset + (*p_mtd_pat)[count].size) { mtd->read(mtd, (loff_t)pos, sizeof(unsigned int), &readlen, (u_char*)&magic); /*--- printk("[davinci_squashfs_parser_function] read %u bytes, magic = 0x%08x index %u pos 0x%x\n", readlen, magic, mtd->index, pos); ---*/ if(magic == 0x73717368) { (*p_mtd_pat)[0].offset = pos; (*p_mtd_pat)[0].size = (*p_mtd_pat)[1].size - pos; (*p_mtd_pat)[0].name = "rootfs"; (*p_mtd_pat)[1].size = pos; (*p_mtd_pat)[1].name = "kernel"; printk("[davinci_squashfs_parser_function] magic found @pos 0x%x\n", (unsigned)pos); return maxcount; } pos += 256; } } return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct mtd_part_parser davinci_squashfs_parser = { .name = "find_squashfs", .parse_fn = davinci_squashfs_parser_function }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int my_atoi(char *p) { unsigned int base, zahl; /*--- printk("[my_atoi] %s -> ", p); ---*/ if(p[0] == '0') { if((p[1] == 'x') || (p[1] == 'X')) { base = 16; p += 2; } else { p += 1; base = 8; } } else { base = 10; } zahl = 0; while(*p) { if((*p >= '0') && (*p <= '9')) { zahl *= base; zahl += *p - '0'; } else if((*p >= 'A') && (*p <= 'F')) { zahl *= base; zahl += *p - 'A' + 10; } else if((*p >= 'a') && (*p <= 'f')) { zahl *= base; zahl += *p - 'a' + 10; } else { break; } p++; } /*--- printk(" %u(0x%x)\n", zahl, zahl); ---*/ return zahl; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void davinci_mtd_add_notifier(struct mtd_info *mtd) { printk("[davinci_mtd_add_notifier] \n"); if(!strcmp(mtd->name, "rootfs")) { extern struct mtd_info *mtd_table[MAX_MTD_DEVICES]; unsigned int i; printk("[davinci_mtd_add_notifier] use %s\n", mtd->name); for(i = 0 ; i < MAX_MTD_DEVICES ; i++) { if(mtd_table[i] == mtd) { extern int __init root_dev_setup(char *line); static char root_device[64]; strcpy(root_device, "/dev/mtdblock_"); *strchr(root_device, '_') = '0' + i; printk("[davinci_mtd_add_notifier] root device: %s (%s)\n", root_device, mtd_table[i]->name); root_dev_setup(root_device); return; } else { printk("[davinci_mtd_add_notifier] %s is not my root device\n", mtd_table[i] ? mtd_table[i]->name : ""); } } } else { printk("[davinci_mtd_add_notifier] skip %s\n", mtd->name); } } void davinci_mtd_rm_notifier(struct mtd_info *mtd) { printk("[davinci_mtd_rm_notifier] ignore %s\n", mtd->name); } struct mtd_notifier davinci_mtd_notifier = { add: davinci_mtd_add_notifier, remove: davinci_mtd_rm_notifier /*--- void (*remove)(struct mtd_info *mtd); ---*/ /*--- struct list_head list; ---*/ }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int __init davinci_mtd_init(void) { char *p; unsigned int flashsize; struct _my_mtd { unsigned int start, end; char *Name; } mtd[5]; unsigned int i; printk("[davinci_mtd_init]\n"); p = prom_getenv((char *)"flashsize"); if(p) { flashsize = my_atoi(p); printk("[davinci_mtd_init] flashsize = %s Byte %u MBytes\n", p, flashsize >> 20); davinci_evm_flash_resource[0].end = davinci_evm_flash_resource[0].start + flashsize; /*--- printk("redurce flashsize to 512 KByte\n"); ---*/ /*--- flashsize = 512 * 1024; ---*/ /*--- davinci_evm_flash_resource.end = davinci_evm_flash_resource.start + flashsize; ---*/ } memset(&mtd[0], 0, sizeof(mtd)); for(i = 0 ; i < MAX_FLASH_MTD ; i++) { switch(i) { case 0: p = prom_getenv("mtd0"); mtd[i].Name = (char *)"filesystem"; break; case 1: p = prom_getenv("mtd1"); mtd[i].Name = (char *)"kernel"; break; case 2: p = prom_getenv("mtd2"); mtd[i].Name = (char *)"urlader"; break; case 3: p = prom_getenv("mtd3"); mtd[i].Name = (char *)"tffs (1)"; break; case 4: p = prom_getenv("mtd4"); mtd[i].Name = (char *)"tffs (2)"; break; } if(p == NULL) continue; /*--- printk("[davinci_mtd_init] mtd[%u] = %s\n", i, p); ---*/ mtd[i].start = my_atoi(p); mtd[i].start -= DAVINCI_CS0_PHYS; p = strchr(p, ','); if(p == NULL) { mtd[i].start = 0; continue; } p++; mtd[i].end = my_atoi(p); mtd[i].end -= DAVINCI_CS0_PHYS; printk("[davinci_mtd_init] mtd[%u] = 0x%08x - 0x%08x (base 0x%08x)\n", i, mtd[i].start, mtd[i].end, DAVINCI_CS0_PHYS); } for(i = 0 ; i < MAX_FLASH_MTD ; i++) { davinci_evm_partitions[i].name = mtd[i].Name; davinci_evm_partitions[i].offset = mtd[i].start; davinci_evm_partitions[i].size = mtd[i].end - mtd[i].start; davinci_evm_partitions[i].mask_flags = 0; } register_mtd_parser(&davinci_squashfs_parser); register_mtd_user(&davinci_mtd_notifier); return 0; } arch_initcall(davinci_mtd_init); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int __init mtdram_setup(char *p) { extern int __init root_dev_setup(char *line); printk("[mtdram_setup] str=\"%s\"\n", p); if(p) { printk("[davinci_mtd_init] mtdram1 %s\n", p); davinci_evm_flash_resource[1].start = my_atoi(p); davinci_evm_flash_resource[1].flags = IORESOURCE_MEM, p = strchr(p, ','); if(p) { p++; davinci_evm_flash_resource[1].end = my_atoi(p); davinci_evm_flash_resource[1].end -= 1; } else { davinci_evm_flash_resource[1].start = 0; } printk("[davinci_mtd_init] mtdram1 0x%08x - 0x%08x\n", davinci_evm_flash_resource[1].start, davinci_evm_flash_resource[1].end ); davinci_evm_ram_partitions[0].name = "filesystem"; davinci_evm_ram_partitions[0].offset = 0; davinci_evm_ram_partitions[0].size = davinci_evm_flash_resource[1].end - davinci_evm_flash_resource[1].start + 1; davinci_evm_ram_partitions[0].mask_flags = 0; davinci_evm_ram_partitions[1].name = "unused"; davinci_evm_ram_partitions[1].offset = 0; davinci_evm_ram_partitions[1].size = davinci_evm_flash_resource[1].end - davinci_evm_flash_resource[1].start + 1; davinci_evm_ram_partitions[1].mask_flags = 0; } /*--- register_mtd_user(&davinci_mtd_notifier); ---*/ /*--- root_dev_setup("/dev/mtdblock5"); ---*/ /*--- register_mtd_parser(&davinci_squashfs_parser); ---*/ return 0; } __setup("mtdram1=", mtdram_setup); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned char keys[3 * 16]; unsigned char *tffs_fs_key = &keys[0 * 16]; unsigned char *kernel_key = &keys[1 * 16]; unsigned char *squash_fs_key = &keys[2 * 16]; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ extern int find_key(void); subsys_initcall(find_key); #endif