/* * ---------------------------------------------------------------------------- * * 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 #include #if (defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)) && defined(CONFIG_ARCH_GEN3) #define DO_MTD #include #include #include #include #include #include #include #include #include #include #include #define PUMA6_MTD_DEBUG #if defined(PUMA6_MTD_DEBUG) #define DEBUG_MTD(fmt,arg...) printk("[%s](%u): " fmt ,__FUNCTION__, __LINE__, ##arg); #else #define DEBUG_MTD(fmt,arg...) #endif #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define GUID_STRLEN 37 #define GUID_LEN 16 static unsigned int linux_fs_start = 0; static unsigned int HWRevision = 0; enum avm_part_types { GUID_SUBSYS0_KERNEL0, GUID_SUBSYS0_KERNEL1, GUID_SUBSYS1_KERNEL0, GUID_SUBSYS1_KERNEL1, GUID_SUBSYS0_FILESYS0, GUID_SUBSYS0_FILESYS1, GUID_SUBSYS1_FILESYS0, GUID_SUBSYS1_FILESYS1, GUID_SUBSYS0_COMBINED0, GUID_SUBSYS0_COMBINED1, GUID_SUBSYS1_COMBINED0, GUID_SUBSYS1_COMBINED1, GUID_SUBSYS0_CONFIG, GUID_SUBSYS1_CONFIG, GUID_USERDATA0, GUID_USERDATA1, GUID_USERDATA2, GUID_BOOT_SUBSYS0, GUID_BOOT_SUBSYS1, GUID_BOOT_CFG0, GUID_BOOT_CFG1, GUID_TFFS1, GUID_TFFS2, GUID_RAM_KERNEL, GUID_RAM_FILESYS, GUID_RAM_COMBINED, GUID_UPDATE_SPARE, GUID_INVALID, }; struct avm_part_entry { enum avm_part_types type; char *avm_part_uuid; char *logical_names[2]; }; struct avm_part_entry avm_part_table[] = { {GUID_SUBSYS0_KERNEL0 , "e7f6f76a-5b1d-5ddc-aa1b-686170c57dd3", {"kernel_ARM", "kernel_reserved_ARM"}}, {GUID_SUBSYS0_KERNEL1 , "79487568-938f-56f0-9e47-ef9c7a145619", {"kernel_reserved_ARM", "kernel_ARM"}}, {GUID_SUBSYS1_KERNEL0 , "0d19f765-c4f6-5565-8a02-6cac8bd749bb", {"kernel_ATOM", "kernel_reserved_ATOM"}}, {GUID_SUBSYS1_KERNEL1 , "1d0aa51e-09d2-5183-9ed2-ee1f21785157", {"kernel_reserved_ATOM", "kernel_ATOM"}}, {GUID_SUBSYS0_FILESYS0 , "d8a646f8-6fae-5021-940b-6c6770266506", {"filesystem_ARM", "filesystem_reserved_ARM"}}, {GUID_SUBSYS0_FILESYS1 , "dd786384-50a3-535a-9163-b78de3b3223d", {"filesystem_reserved_ARM", "filesystem_ARM"}}, {GUID_SUBSYS1_FILESYS0 , "247ed111-3eac-5756-849c-1d9a5409c9c4", {"filesystem_ATOM", "filesystem_reserved_ATOM"}}, {GUID_SUBSYS1_FILESYS1 , "f012560e-5261-5845-8a5f-8c77fd12927e", {"filesystem_reserved_ATOM", "filesystem_ATOM"}}, {GUID_SUBSYS0_COMBINED0 , "f62e9a94-de69-5428-8443-97d3a88947e8", {"extra_ARM", "extra_reserved_ARM"}}, {GUID_SUBSYS0_COMBINED1 , "7d9c8a9d-1827-5b1e-928a-e6d1ef33ddc5", {"extra_reserved_ARM", "extra_ARM"}}, {GUID_SUBSYS1_COMBINED0 , "b7514cf1-5261-5b78-a2d7-e89935760384", {"extra_ATOM", "extra_reserved_ATOM"}}, {GUID_SUBSYS1_COMBINED1 , "112c3f21-4ecf-5b0a-af0a-cf4963097d0d", {"extra_reserved_ATOM", "extra_ATOM"}}, {GUID_SUBSYS0_CONFIG , "c2c2fe1e-8139-5459-a9d6-a9e6d506ebe6", {"config-space", "config-space"}}, {GUID_SUBSYS1_CONFIG , "45d74feb-1346-5377-9b0c-5ac7055bab49", {"", ""}}, {GUID_USERDATA0 , "3a0c1d78-6d9d-5240-8e2c-617afda38fe1", {"media", "media"}}, {GUID_USERDATA1 , "6bb5ce24-2e2f-524e-a354-4db5b7bfd296", {"jffs2", "jffs2_reserved"}}, {GUID_USERDATA2 , "0c776b3e-9658-50ca-b12a-d3a0df7fd94b", {"jffs2_reserved", "jffs2"}}, {GUID_BOOT_SUBSYS0 , "135602e3-9a5f-5187-8f44-bf28f20e518a", {"urlader", "urlader"}}, {GUID_BOOT_SUBSYS1 , "d637e745-650d-5604-a1af-acf3ce412dd4", {"cefdk", "cefdk"}}, {GUID_BOOT_CFG0 , "68c75c8a-6803-58c9-a588-11b61e856b4d", {"cefdk_config", "cefdk_config"}}, {GUID_BOOT_CFG1 , "a9b260e6-d63f-578a-b043-08d3f3a3631d", {"gpt_backup", "gpt_backup"}}, {GUID_TFFS1 , "58f796b7-2cd3-5a0a-ba8c-e009dc6db3a7", {"tffs1", "tffs1"}}, {GUID_TFFS2 , "0efce4d9-230a-5fe7-a591-2c670766e7be", {"tffs2", "tffs2"}}, {GUID_RAM_KERNEL , "66358106-584e-501f-81db-e22453469a00", {"kernel_ram", "kernel_ram"}}, {GUID_RAM_FILESYS , "3f26af86-8863-5c15-a617-db90e4ce16a8", {"filesystem_ram", "filesystem_ram"}}, {GUID_RAM_COMBINED , "535d258a-0c84-5343-8c21-0c79ceccf861", {"extra_ram", "extra_ram"}}, {GUID_UPDATE_SPARE , "b7641aea-f089-53c4-8ccc-3deafb548180", {"update_tmp", "update_tmp"}}, }; struct blockdev_entry { struct list_head list; struct avm_part_entry entry; char logical_name[BDEVNAME_SIZE]; char dev_name[BDEVNAME_SIZE]; uint64_t size; }; static char *puma6_get_mtdname(enum avm_part_types type, unsigned int fs_start, char *uuid) { int i; struct avm_part_entry *entry; char *name; entry = NULL; name = NULL; for(i = 0; i < ARRAY_SIZE(avm_part_table); ++i){ if(avm_part_table[i].type == type){ entry = &(avm_part_table[i]); break; } } if(entry != NULL){ fs_start = (fs_start == 1) ? 1 : 0; name = entry->logical_names[fs_start]; if(uuid != NULL){ strlcpy(uuid, entry->avm_part_uuid, GUID_STRLEN); } } return name; } DEFINE_MUTEX(partition_mutex); LIST_HEAD(partition_list); static void puma6_blockdev_add(enum avm_part_types type, const char *name, uint64_t size) { unsigned int i; struct avm_part_entry *part_entry; struct blockdev_entry *list_entry, *new_entry; char *logical_name; int error; if(size == 0){ printk(KERN_ERR "[%s] no size set for device %s\n", __func__, name); } part_entry = NULL; for(i = 0; i < ARRAY_SIZE(avm_part_table); ++i){ if(type == avm_part_table[i].type){ part_entry = &(avm_part_table[i]); break; } } if(part_entry == NULL){ printk(KERN_ERR "[%s] unknown type, abort\n", __func__); return; } new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); if(new_entry == NULL){ return; } INIT_LIST_HEAD(&(new_entry->list)); new_entry->entry = *part_entry; strlcpy(new_entry->dev_name, name, sizeof(new_entry->dev_name)); new_entry->size = size; if(linux_fs_start == 1){ logical_name = part_entry->logical_names[1]; } else { logical_name = part_entry->logical_names[0]; } if(logical_name != NULL){ strlcpy(new_entry->logical_name, logical_name, sizeof(new_entry->logical_name)); printk(KERN_ERR "[%s] blockdev: %s logical: %s\n", __func__, new_entry->dev_name, new_entry->logical_name); } else { printk(KERN_ERR "[%s] no logical name defined, abort\n", __func__); kfree(new_entry); return; } mutex_lock(&partition_mutex); error = 0; list_for_each_entry(list_entry, &partition_list, list){ if(list_entry->entry.type == part_entry->type){ printk(KERN_ERR "[%s] type already known, abort\n", __func__); error = 1; break; } } if(error == 0){ list_add_tail(&(new_entry->list), &partition_list); } mutex_unlock(&partition_mutex); if(error){ kfree(new_entry); } return; } void puma6_partition_add(struct hd_struct *part) { unsigned int i; u8 unparsed_guid[GUID_STRLEN]; uint8_t my_uuid[GUID_LEN]; char bdev_name[BDEVNAME_SIZE]; struct avm_part_entry *part_entry; uint64_t size; printk(KERN_ERR "[%s] New device: %s\n", __func__, dev_name(&(part->__dev))); if(part->info == NULL){ printk(KERN_ERR "[%s] No partition info, abort\n", __func__); return; } sprintf(unparsed_guid, "%pUl", part->info->uuid); printk(KERN_ERR "[%s] UUID: %s\n", __func__, unparsed_guid); part_entry = NULL; for(i = 0; i < ARRAY_SIZE(avm_part_table); ++i){ part_pack_uuid(avm_part_table[i].avm_part_uuid, my_uuid); if(!memcmp(my_uuid, part->info->uuid, sizeof(my_uuid))){ part_entry = &(avm_part_table[i]); break; } } if(part_entry == NULL){ printk(KERN_ERR "[%s] unknown UUID, abort\n", __func__); return; } snprintf(bdev_name, sizeof(bdev_name), "/dev/%s", dev_name(&(part->__dev))); size = part->nr_sects * 512; // FIXME puma6_blockdev_add(part_entry->type, bdev_name, size); } #ifdef CONFIG_PROC_FS static int proc_avm_parts_show(struct seq_file *seq, void *data __attribute__ ((unused)) ) { struct blockdev_entry *list_entry; char logical_name[BDEVNAME_SIZE]; char *p; if(mutex_lock_interruptible(&partition_mutex)){ return 1; } list_for_each_entry(list_entry, &partition_list, list){ strlcpy(logical_name, list_entry->logical_name, sizeof(logical_name)); p = logical_name; while(*p && (p = strchr(p, '-')) != NULL){ *p = '_'; } seq_printf(seq, "%s=%s\n", logical_name, list_entry->dev_name); seq_printf(seq, "%s_SIZE=0x%08llx\n", logical_name, list_entry->size); } mutex_unlock(&partition_mutex); return 0; } static int proc_avm_parts_open(struct inode *inode, struct file *file) { return single_open(file, proc_avm_parts_show, NULL); } static const struct file_operations proc_avm_parts_fops = { .open = proc_avm_parts_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; static int __init proc_avm_parts_init(void) { proc_create("avm_partitions", 0, NULL, &proc_avm_parts_fops); return 0; } module_init(proc_avm_parts_init); #endif /* CONFIG_PROC_FS */ struct mtd_entry { uint32_t idx; uint32_t cs; char *urlader_name; enum avm_part_types type; }; struct mtd_entry mtd_names_spi[] = { {2, 0, "mtd2", GUID_BOOT_SUBSYS0}, {3, 0, "mtd3", GUID_TFFS1}, {4, 0, "mtd4", GUID_TFFS2}, {5, 0, "mtd5", GUID_SUBSYS0_CONFIG}, {8, 0, "mtd8", GUID_BOOT_SUBSYS1}, {9, 0, "mtd9", GUID_BOOT_CFG0}, {10, 0, "mtd10", GUID_BOOT_CFG1}, }; #define NUM_RAM_MTD 3 /*--- Kernel + Filesystem + extra---*/ #define NUM_SPI_MTD ARRAY_SIZE(mtd_names_spi) #define MAX_MTD_DEVICES (MAX_SPI_MTD + MAX_RAM_MTD) static struct mtd_partition puma6_spi_partitions[NUM_SPI_MTD]; static const char *probes[] = { "find_squashfs", NULL }; static unsigned int flash_erase_block_size = 0; static struct flash_platform_data puma_flash_data = { .name = "nmyx25", .parts = puma6_spi_partitions, .nr_parts = ARRAY_SIZE(puma6_spi_partitions), .probes = probes, }; static struct resource puma6_ramflash_resource[] = { { /* fuer ins RAM geladenes Filesystem */ .start = 0, /*--- werden beim Aufsetzen ausgefuellt ---*/ .end = 0 + (16 << 20), .flags = IORESOURCE_MEM, } }; void puma6_ram_mtd_set_rw(struct device *pdev, int); extern int __init root_dev_setup(char *line); #ifdef CONFIG_MTD_SPI struct spi_board_info puma6_sflash_devices[] = { { .modalias = "nmyx25", .chip_select = 0, .bus_num = 1, .platform_data = &puma_flash_data, }, }; #endif /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static struct mtd_partition puma6_ram_partitions[3]; static struct platdata_mtd_ram puma6_ram_data = { .mapname = "ram-filesystem", .bankwidth = 4, .partitions = puma6_ram_partitions, .set_rw = puma6_ram_mtd_set_rw, .probes = probes }; struct platform_device puma6_ram_device = { .name = "mtd-ram", .id = -1, .dev = { .platform_data = &puma6_ram_data, }, .num_resources = 1, .resource = &puma6_ramflash_resource[0], }; static unsigned int puma6_max_plattforms = 0; /*--- wird in mtdram_setup() ggf. auf 1 gesetzt ---*/ struct platform_device *puma6_platform_devices[] = { &puma6_ram_device }; /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ void puma6_init_platform_devices(void) { platform_add_devices(puma6_platform_devices, puma6_max_plattforms); spi_register_board_info(puma6_sflash_devices, ARRAY_SIZE(puma6_sflash_devices)); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void puma6_ram_mtd_set_rw(struct device *pdev, int mode) { if(mode == PLATRAM_RO){ DEBUG_MTD("PLATRAM_RO\n"); }else if(mode == PLATRAM_RW){ DEBUG_MTD("PLATRAM_RW\n"); } } enum _flash_map_enum { MAP_UNKNOWN, MAP_RAM, MAP_FLASH }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define pointer_fail_strcmp(a, b) __pointer_fail_strcmp(a, b, __FUNCTION__, __LINE__) int __pointer_fail_strcmp(const char *ptr, char *cmp, const char *func, int line) { if(!ptr || !cmp){ printk(KERN_ERR "[%s] line %d strcmp(%pF, %pF)\n", func, line, ptr, cmp); return -1; } return strcmp(ptr, cmp); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int puma6_squashfs_parser_function(struct mtd_info *mtd, struct mtd_partition **p_mtd_pat, unsigned long param) { unsigned maxcount = 0; struct mtd_partition *kernel_part, *filesys_part; unsigned int magic = 0, readlen = 0; loff_t pos, start_offset, end_offset; unsigned int i; DEBUG_MTD("mtd_info->name=%s, mtd_info->index=%u, param=%lu, p_mtd_pat=0x%x\n", mtd->name, mtd->index, param, (unsigned int)*p_mtd_pat); if(!pointer_fail_strcmp(mtd->name, "nmyx25")){ /*--- chip select CS0 ---*/ DEBUG_MTD("Detected nmyx25 with %d partitions\n", ARRAY_SIZE(puma6_spi_partitions)); flash_erase_block_size = mtd->erasesize; if(*p_mtd_pat == NULL ){ *p_mtd_pat = puma6_spi_partitions; } return ARRAY_SIZE(puma6_spi_partitions); } if(!pointer_fail_strcmp(mtd->name, "ram-filesystem")){ if(*p_mtd_pat == NULL ){ *p_mtd_pat = puma6_ram_partitions; } maxcount = ARRAY_SIZE(puma6_ram_partitions); }else{ DEBUG_MTD("with unknown mtd type %s\n", mtd->name); return 0; } if(p_mtd_pat){ if(*p_mtd_pat){ DEBUG_MTD("*p_mtd_pat->name %s\n", (*p_mtd_pat)->name); } #if defined(PUMA6_MTD_DEBUG) { int i; for(i = 0; i < maxcount; i++) DEBUG_MTD("[mtd%d] %20s: 0x%08llx - 0x%08llx (size 0x%llx)\n", i, (*p_mtd_pat)[i].name, (*p_mtd_pat)[i].offset, (*p_mtd_pat)[i].offset + (*p_mtd_pat)[i].size, (*p_mtd_pat)[i].size); } #endif kernel_part = NULL; filesys_part = NULL; for(i = 0; i < maxcount; ++i){ if(!strcmp("kernel_ram", (*p_mtd_pat)[i].name)){ kernel_part = &((*p_mtd_pat)[i]); continue; } if(!strcmp("filesystem_ram", (*p_mtd_pat)[i].name)){ filesys_part = &((*p_mtd_pat)[i]); continue; } } if(kernel_part == NULL ){ printk(KERN_ERR "[%s] Kernel MTD not found.\n", __func__); return 0; } if(filesys_part == NULL ){ printk(KERN_ERR "[%s] Filesystem MTD not found.\n", __func__); return 0; } start_offset = pos = kernel_part->offset; end_offset = start_offset + kernel_part->size; while(pos < end_offset){ mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &magic); if((magic == SQUASHFS_MAGIC) || (magic == SQUASHFS_MAGIC_SWAP)){ filesys_part->offset = pos; filesys_part->size = end_offset - pos; kernel_part->size = pos - start_offset; DEBUG_MTD("magic found @pos 0x%x\n", (unsigned int)pos); return maxcount; } pos += 256; } return maxcount; } return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int get_erase_block_size_on_ram_device(struct mtd_info *mtd) { unsigned int readlen = 0; loff_t pos = 0; unsigned int value1, value2; mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value1); if(readlen != sizeof(unsigned int)) return 0; /*--- DEBUG_MTD("name=%s pos=0x%x value=0x%x\n" , mtd->name, pos, value1); ---*/ pos += 0x10000ULL; mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value2); if(readlen != sizeof(unsigned int)) return 0; /*--- DEBUG_MTD("name=%s pos=0x%x value2=0x%x\n" , mtd->name, pos, value2); ---*/ if(value1 == value2){ pos += 0x10000ULL; mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value2); if(readlen != sizeof(unsigned int)) return 0; /*--- DEBUG_MTD("name=%s pos=0x%x value2=0x%x (check)\n" , mtd->name, pos, value2); ---*/ if(value1 == value2){ DEBUG_MTD("eraseblocksize=0x10000\n"); return 0x10000; } return 0; } pos += 0x10000ULL; mtd->read(mtd, pos, sizeof(unsigned int), &readlen, (u_char*) &value2); if(readlen != sizeof(unsigned int)) return 0; DEBUG_MTD("name=%s pos=0x%Lx value2=0x%x\n", mtd->name, pos, value2); if(value1 == value2){ DEBUG_MTD("eraseblocksize=0x20000\n"); return 0x20000; } return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct mtd_part_parser puma6_squashfs_parser = { .name = "find_squashfs", .parse_fn = puma6_squashfs_parser_function }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if defined(CONFIG_TFFS_DEV_LEGACY) extern int tffs_mtd[2]; #endif static int found_rootfs_ram = 0; static void puma6_mtd_add_notifier(struct mtd_info *mtd) { extern void __ref setup_root_dev_if_possible(char *); char root_device[64]; char bdev_name[BDEVNAME_SIZE]; enum avm_part_types type; DEBUG_MTD("name %s on /dev/mtdblock%d\n" , mtd->name, mtd->index); snprintf(bdev_name, sizeof(bdev_name), "/dev/mtdblock%d", mtd->index); type = GUID_INVALID; if(!pointer_fail_strcmp(mtd->name, "filesystem_ram")){ if(!found_rootfs_ram){ found_rootfs_ram = 1; /*--- signal that we found a rootfs in RAM ---*/ DEBUG_MTD("use %s\n", mtd->name); if(mtd->index >= 0){ sprintf(root_device, "/dev/mtdblock%d", mtd->index); DEBUG_MTD("root device: %s (%s)\n", root_device, mtd->name); setup_root_dev_if_possible(root_device); } } type = GUID_RAM_FILESYS; }else if(!pointer_fail_strcmp(mtd->name, "ram-filesystem")){ mtd->erasesize = get_erase_block_size_on_ram_device(mtd); if(mtd->erasesize == 0){ mtd->erasesize = flash_erase_block_size; } DEBUG_MTD("%s: set erasesize to 0x%x\n", mtd->name, flash_erase_block_size); }else if(!pointer_fail_strcmp(mtd->name, "tffs1")){ #if defined(CONFIG_TFFS_DEV_REMOTE) TFFS3_Register_REMOTE(AVM_EVENT_TFFS_NODE_ATOM); #endif if(mtd->index >= 0){ #if defined(CONFIG_TFFS_DEV_LEGACY) tffs_mtd[0] = mtd->index; #endif type = GUID_TFFS1; DEBUG_MTD("tffs (1) on Index %d\n", mtd->index); } mtd->name = "tffs (1)"; }else if(!pointer_fail_strcmp(mtd->name, "tffs2")){ if(mtd->index >= 0){ #if defined(CONFIG_TFFS_DEV_LEGACY) tffs_mtd[1] = mtd->index; #endif type = GUID_TFFS2; DEBUG_MTD("tffs (2) on Index %d\n", mtd->index); } mtd->name = "tffs (2)"; } else if(!pointer_fail_strcmp(mtd->name, "urlader")){ init_wlan_dect_config(mtd); type = GUID_BOOT_SUBSYS0; } else if(!pointer_fail_strcmp(mtd->name, "config-space")){ type = GUID_SUBSYS0_CONFIG; } else if(!pointer_fail_strcmp(mtd->name, "kernel_ram")){ type = GUID_RAM_KERNEL; } else if(!pointer_fail_strcmp(mtd->name, "extra_ram")){ type = GUID_RAM_COMBINED; } else if(!pointer_fail_strcmp(mtd->name, "cefdk")){ type = GUID_BOOT_SUBSYS1; } else if(!pointer_fail_strcmp(mtd->name, "cefdk_config")){ type = GUID_BOOT_CFG0; } else if(!pointer_fail_strcmp(mtd->name, "gpt_backup")){ type = GUID_BOOT_CFG1; }else{ DEBUG_MTD("skip %s\n", mtd->name); } if(type != GUID_INVALID){ puma6_blockdev_add(type, bdev_name, mtd->size); } } void puma6_mtd_rm_notifier(struct mtd_info *mtd) { DEBUG_MTD("[puma6_mtd_rm_notifier] ignore %s\n", mtd->name); } struct mtd_notifier puma6_mtd_notifier = { add: puma6_mtd_add_notifier, remove : puma6_mtd_rm_notifier }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int __init puma6_mtd_init(void) { char *p, *name, *ptest __attribute__((unused)); char root_string[64]; enum avm_part_types type; unsigned int i; uint64_t start, end, size; DEBUG_MTD("\n"); HWRevision = 0; p = prom_getenv("HWRevision"); if(p){ HWRevision = simple_strtoul(p, NULL, 10); } switch(HWRevision){ case 204: #if 0 // SPI-only boxes no longer supported mtd_table = mtd_names_spi; mtd_table_size = ARRAY_SIZE(mtd_names_spi); puma6_max_plattforms_spi = 2; #else panic("[%s] SPI-only boxes no longer supported!\n", __func__); #endif break; default: printk(KERN_EMERG "[%s] unknown HWRevision %d, assuming eMMC flash layout!\n", __func__, HWRevision); /* fall through */ case 199: case 213: case 231: break; } type = GUID_SUBSYS1_FILESYS0; p = prom_getenv("linux_fs_start"); if(p){ if(!pointer_fail_strcmp(p, "0")){ linux_fs_start = 0; type = GUID_SUBSYS1_FILESYS0; } else if(!pointer_fail_strcmp(p, "1")){ linux_fs_start = 1; type = GUID_SUBSYS1_FILESYS1; } else if(!pointer_fail_strcmp(p, "nfs")){ linux_fs_start = 2; } } DEBUG_MTD("linux_fs_start %d\n", linux_fs_start); switch(linux_fs_start){ case 0: case 1: strlcpy(root_string, "PARTUUID=", sizeof(root_string)); p = &(root_string[strlen(root_string)]); name = puma6_get_mtdname(type, linux_fs_start, p); if(name != NULL){ root_dev_setup(root_string); DEBUG_MTD("root=%s\n", root_string); } else { printk(KERN_EMERG "[%s] no root partition UUID found!\n", __func__); } break; default: break; } ptest = prom_getenv("ptest"); /*--- wenn ptest gesetzt ist das Urladermtd schreibbar ---*/ for(i = 0; i < ARRAY_SIZE(mtd_names_spi); i++){ p = prom_getenv(mtd_names_spi[i].urlader_name); name = puma6_get_mtdname(mtd_names_spi[i].type, linux_fs_start, NULL); if(p == NULL || name == NULL) { continue; } DEBUG_MTD("mtd[%u] = %s\n" , i, p); start = (uint64_t)simple_strtoul(p, NULL, 16); p = strchr(p, ','); if(p == NULL) { start = 0; continue; } p++; end = (uint64_t)simple_strtoul(p, NULL, 16); size = end - start; DEBUG_MTD("mtd[%u] = 0x%08llx - 0x%08llx %s\n" , i, start, end, name); puma6_spi_partitions[i].name = name; puma6_spi_partitions[i].offset = start; puma6_spi_partitions[i].size = size; puma6_spi_partitions[i].mask_flags = 0; switch(mtd_names_spi[i].idx){ case 2: if(ptest) puma6_spi_partitions[i].mask_flags = MTD_WRITEABLE; /*--- remove MTD_WRITEABLE from partition flags ---*/ break; default: break; } } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ DEBUG_MTD("special mtd_parser registered\n"); puma6_init_platform_devices(); register_mtd_user(&puma6_mtd_notifier); register_mtd_parser(&puma6_squashfs_parser); return 0; } fs_initcall(puma6_mtd_init); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int __init mtdram_setup(char *p) { int i; DEBUG_MTD("[mtdram_setup] str=\"%s\"\n", p); if(p){ DEBUG_MTD("mtdram7 %s\n", p); puma6_ramflash_resource[0].start = (unsigned int) simple_strtoul(p, NULL, 16); puma6_ramflash_resource[0].flags = IORESOURCE_MEM; p = strchr(p, ','); if(p){ p++; puma6_ramflash_resource[0].end = (unsigned int) simple_strtoul(p, NULL, 16); puma6_ramflash_resource[0].end -= 1; }else{ puma6_ramflash_resource[0].start = 0; } DEBUG_MTD("mtdram7 0x%08llx - 0x%08llx\n", puma6_ramflash_resource[0].start, puma6_ramflash_resource[0].end); puma6_ram_partitions[0].name = "filesystem_ram"; puma6_ram_partitions[0].offset = 0; puma6_ram_partitions[0].size = puma6_ramflash_resource[0].end - puma6_ramflash_resource[0].start + 1; puma6_ram_partitions[0].mask_flags = MTD_ROM; puma6_ram_partitions[1].name = "kernel_ram"; puma6_ram_partitions[1].offset = 0; puma6_ram_partitions[1].size = puma6_ram_partitions[0].size; puma6_ram_partitions[1].mask_flags = MTD_ROM; puma6_ram_partitions[2].name = "extra_ram"; puma6_ram_partitions[2].offset = 0; puma6_ram_partitions[2].size = puma6_ram_partitions[0].size; puma6_ram_partitions[2].mask_flags = MTD_ROM; for(i = 0; i < 3; ++i){ DEBUG_MTD("%s: offset: 0x%08llx size: 0x%08llx\n", puma6_ram_partitions[i].name, puma6_ram_partitions[i].offset, puma6_ram_partitions[i].size); } puma6_max_plattforms += 1; /*--- die RAM-Partition zu den Plattformdevices hinzufuegen ---*/ } DEBUG_MTD("mtdram7 0x%08llx - 0x%08llx\n", puma6_ramflash_resource[0].start, puma6_ramflash_resource[0].end); return 0; } __setup("mtdram7=", mtdram_setup); #endif