/* * $Id: dbox2-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ * * es war einmal der .... D-Box 2 flash driver */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_MIPS #include #include #endif /*--- #ifdef CONFIG_MIPS ---*/ #include #include #ifdef CONFIG_ARCH_DAVINCI #include #include #include #endif /*--- #ifdef CONFIG_ARCH_DAVINCI ---*/ /*--- #define DEBUG_OHIO_FLASH ---*/ #if defined(DEBUG_OHIO_FLASH) #define DBG_FLASH(...) printk(KERN_NOTICE __VA_ARGS__) #else #define DBG_FLASH(...) #endif #if defined(CONFIG_MIPS_UR8) #define CONFIG_UR8_DIEGO_CEBIT_DEFINE #endif #define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START #define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) #define FLASH_BASE (CONFIG_MTD_PHYSMAP_START | 0xA0000000) #define RAM_BASE (0x94000000 | 0xA0000000) #define EMIF_ADDRESS #elif defined(CONFIG_ARCH_DAVINCI) #define FLASH_BASE (CONFIG_MTD_PHYSMAP_START) #define RAM_BASE (CONFIG_DAVINCI_PHY_MEMSTART) #endif/*--- #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) ---*/ static struct mtd_info *mymtd; static struct mtd_info *mymtdram; /*--- int debug_flag = 0; ---*/ struct map_info ohio_flash_map = { #if defined(CONFIG_MIPS_OHIO) .name = "Ohio flash memory", #elif defined(CONFIG_MIPS_AR7) .name = "AR7 flash memory", #elif defined(CONFIG_MIPS_UR8) .name = "UR8 flash memory", #elif defined(CONFIG_ARCH_DAVINCI) .name = "Davinci flash memory", #endif /*--- #if defined(CONFIG_MIPS_OHIO) ---*/ .size = WINDOW_SIZE, .bankwidth = 2, .phys = WINDOW_ADDR, }; struct map_info ohio_ram_map = { #if defined(CONFIG_MIPS_OHIO) .name = "Ohio virtual ROM memory", #elif defined(CONFIG_MIPS_AR7) .name = "Ar7 virtual ROM memory", #elif defined(CONFIG_MIPS_UR8) .name = "UR8 virtual ROM memory", #elif defined(CONFIG_ARCH_DAVINCI) .name = "Davinci virtual ROM memory", #endif /*--- #if defined(CONFIG_MIPS_OHIO) ---*/ .size = 0, .bankwidth = 2, .phys = 0, }; extern int root_dev_setup(char *line); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int ohio_find_hidden_filesystem(struct mtd_info *mtd, unsigned int *size, unsigned int *start, unsigned int *fs_size, unsigned int ram) { unsigned int first_start_pos; unsigned int end_pos; squashfs_super_block super; unsigned int retlen; char buffer[64]; unsigned int *pint; unsigned int kernel_len = 0; DBG_FLASH("[ohio_find_hidden_filesystem] start=0x%x size=0x%x\n", *start, *size); first_start_pos = *start; end_pos = *start + *size; DBG_FLASH("[ohio_find_hidden_filesystem] start=0x%x end=0x%x size=0x%x\n", *start, end_pos, *size); mtd->read(mtd, *start, 3*sizeof(unsigned int), &retlen, buffer); /*--- das filesystem folgt dem kernel, die Kernel_len steht im Header ---*/ pint = (unsigned int *)buffer; switch (*pint) { case 0xfeed1281: /*--- wir haben einen Kernel gefunden, dann müssen wir nicht so lange suchen ---*/ kernel_len = *(++pint); kernel_len &= ~(256-1); DBG_FLASH("[ohio_find_hidden_filesystem] kernel_len 0x%x\n", kernel_len); *start += kernel_len; break; case -1: /*--- flash ist leer ---*/ default: break; /*--- nichts gefunden ---*/ } DBG_FLASH("[ohio_find_hidden_filesystem] start=0x%x end=0x%x size=0x%x\n", *start, end_pos, *size); while(*start < end_pos) { /*--- if(debug_flag) ---*/ /*--- printk("[0x%x]", *start); ---*/ mtd->read(mtd, *start, sizeof(super), (size_t *)&retlen, (unsigned char *)&super); if(super.s_magic == SQUASHFS_MAGIC) { printk("[ohio_find_hidden_filesystem]: super block found: bytes_used: 0x%x/%u\n", super.bytes_used, super.bytes_used); if(fs_size) *fs_size = super.bytes_used + sizeof(super) + (*start - first_start_pos); *size = end_pos - *start; #ifdef CONFIG_ARCH_DAVINCI if(ram) { *start += first_start_pos; } #endif /*--- #ifdef CONFIG_ARCH_DAVINCI ---*/ return 0; } *start += 256; } return 1; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #define LOCAL_MTD_FILESYSTEM 0 #define LOCAL_MTD_KERNEL 1 #define LOCAL_MTD_URLADER 2 #define LOCAL_MTD_TFFS1 3 #define LOCAL_MTD_TFFS2 4 #define LOCAL_URLADER_MTDS 5 #define LOCAL_MTD_JFFS2 5 #define LOCAL_MTD_KERNEL_WITHOUT_JFFS2 6 #define LOCAL_MAX_MTDS 7 #define _NUM_PARTITIONS LOCAL_MAX_MTDS unsigned int NUM_PARTITIONS = _NUM_PARTITIONS; static struct mtd_partition partition_info[LOCAL_MAX_MTDS]; static struct mtd_partition partition_info_ram[2]; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ char *get_mtdram1_param(void) { #if defined(CONFIG_MIPS) char *cmdline = prom_getcmdline(); #else /*--- #ifdef CONFIG_MIPS ---*/ char *cmdline = getcmdline(); #endif /*--- #else ---*/ /*--- #ifdef CONFIG_MIPS ---*/ return strstr(cmdline, "mtdram1"); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #ifdef CONFIG_ARCH_DAVINCI void enable_flash(void) { extern struct system_regs *HW_SYSTEM; if(get_mtdram1_param() == NULL) { davinci_i2c_expander_op(0x3A, 2, 1); printk("[WARNING] vlync disabled [WARNING]\n"); HW_SYSTEM->pinmux0.Bits.aeaw = 0x1F; /*--- fuer alle Bits ---*/ } else { HW_SYSTEM->pinmux0.Bits.aeaw = 0x13; /*--- BA[1] + A[0..17] Bits ---*/ } HW_SYSTEM->pinmux0.Bits.vlynqwd = 0; HW_SYSTEM->pinmux0.Bits.vlscren = 0; HW_SYSTEM->pinmux0.Bits.vlynqen = 0; printk("pinmux0: 0x%x (0%o)\n", HW_SYSTEM->pinmux0.Reg, HW_SYSTEM->pinmux0.Reg); printk("pinmux1: 0x%x (0%o)\n", HW_SYSTEM->pinmux1.Reg, HW_SYSTEM->pinmux1.Reg); } #endif /*--- #ifdef CONFIG_ARCH_DAVINCI ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int ohio_init_mtd_partitions(unsigned int *flash_size) { unsigned int mtd_base[LOCAL_MAX_MTDS]; unsigned int mtd_size[LOCAL_MAX_MTDS]; unsigned int mtd_index; char *p; char name[10]; unsigned int flash_mask; DBG_FLASH("[ohio_init_mtd_partitions]\n"); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ p = prom_getenv("flashsize"); if(!p) { printk(KERN_ERR "[init_ohio_flash] %s not found\n", "flashsize"); return -ENXIO; } *flash_size = simple_strtol(p, NULL, 0); printk("flash_size=0x%x\n", *flash_size); ohio_flash_map.size = *flash_size; flash_mask = *flash_size * 2 - 1; printk("flash_mask=0x%x\n", flash_mask); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ partition_info[LOCAL_MTD_KERNEL_WITHOUT_JFFS2].name = "Kernel without jffs2"; partition_info[LOCAL_MTD_KERNEL_WITHOUT_JFFS2].offset = 0; partition_info[LOCAL_MTD_KERNEL_WITHOUT_JFFS2].size = 0; partition_info[LOCAL_MTD_KERNEL_WITHOUT_JFFS2].mask_flags = 0; partition_info[LOCAL_MTD_JFFS2].name = "jffs2"; partition_info[LOCAL_MTD_JFFS2].offset = 0; partition_info[LOCAL_MTD_JFFS2].size = 0; partition_info[LOCAL_MTD_JFFS2].mask_flags = 0; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ for(mtd_index = 0 ; mtd_index < LOCAL_URLADER_MTDS ; mtd_index++) { char *p1; char Buffer[64]; sprintf(name, "mtd%u", mtd_index); p = prom_getenv(name); if(!p) { printk(KERN_ERR "[init_ohio_flash] %s not found\n", name); return -ENXIO; } #if 0 printk("env=\"%s\"=\"%s\"\n", name, p); #endif strcpy(Buffer, p); p1 = p = Buffer; while(*p1 && *p1 != ',') p1++; if(*p1) { *p1++ = '\0'; /*----------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------*/ #ifdef CONFIG_MIPS mtd_base[mtd_index] = CPHYSADDR(simple_strtol(p, NULL, 0)) & flash_mask; mtd_size[mtd_index] = (CPHYSADDR(simple_strtol(p1, NULL, 0)) & flash_mask) - mtd_base[mtd_index]; #else /*--- #ifdef CONFIG_MIPS ---*/ mtd_base[mtd_index] = simple_strtol(p, NULL, 0) - WINDOW_ADDR; mtd_size[mtd_index] = (simple_strtol(p1, NULL, 0) - WINDOW_ADDR) - mtd_base[mtd_index]; #endif /*--- #else ---*/ /*--- #ifdef CONFIG_MIPS ---*/ DBG_FLASH("[init_ohio_flash]: %s base=0x%x size=0x%x\n", name, mtd_base[mtd_index], mtd_size[mtd_index]); partition_info[mtd_index].size = mtd_size[mtd_index]; partition_info[mtd_index].offset = mtd_base[mtd_index]; switch(mtd_index) { case 2: partition_info[mtd_index].name = "bootloader"; partition_info[mtd_index].mask_flags = 0; break; case 1: partition_info[mtd_index].name = "kernel"; partition_info[mtd_index].mask_flags = MTD_NO_VIRTBLOCKS; break; case 0: partition_info[mtd_index].name = "filesystem"; partition_info[mtd_index].mask_flags = MTD_NO_VIRTBLOCKS; break; case 3: partition_info[mtd_index].name = "tffs (1)"; partition_info[mtd_index].mask_flags = 0; break; case 4: partition_info[mtd_index].name = "tffs (2)"; partition_info[mtd_index].mask_flags = 0; break; } if(partition_info[mtd_index].size == 0) partition_info[mtd_index].offset = 0; #if defined(DEBUG_OHIO_FLASH) printk("partition_info[%u]: name=%s offset=%x size=%x\n", mtd_index, partition_info[mtd_index].name, partition_info[mtd_index].offset, partition_info[mtd_index].size); if (partition_info[LOCAL_MAX_MTDS + 0].name) { printk("partition_info[%u]: name=%s offset=%x size=%x\n", LOCAL_MAX_MTDS + 0, partition_info[LOCAL_MAX_MTDS + 0].name, partition_info[LOCAL_MAX_MTDS + 0].offset, partition_info[LOCAL_MAX_MTDS + 0].size); } if (partition_info[LOCAL_MAX_MTDS + 1].name) { printk("partition_info[%u]: name=%s offset=%x size=%x\n", LOCAL_MAX_MTDS + 1, partition_info[LOCAL_MAX_MTDS + 1].name, partition_info[LOCAL_MAX_MTDS + 1].offset, partition_info[LOCAL_MAX_MTDS + 1].size); } #endif } } return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int __init init_ohio_flash(void) { unsigned int flash_size = 0; unsigned int jffs2_size = 0; char *p; printk(KERN_NOTICE "Ohio flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR); #ifdef CONFIG_ARCH_DAVINCI enable_flash(); #endif /*--- #ifdef CONFIG_ARCH_DAVINCI ---*/ if (ohio_init_mtd_partitions(&flash_size)) { printk("[init_ohio_flash] failed to init partitions\n"); return -EIO; } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ ohio_flash_map.virt = ioremap(WINDOW_ADDR, flash_size); if (!ohio_flash_map.virt) { printk("Failed to ioremap\n"); return -EIO; } DBG_FLASH("[flash] WINDOW_ADDR = 0x%x\n", WINDOW_ADDR); DBG_FLASH("[flash] ohio_flash_map.virt = 0x%p\n", ohio_flash_map.virt); #if !defined(CONFIG_UR8_DIEGO_CEBIT_DEFINE) mymtd = do_map_probe("cfi_probe", &ohio_flash_map); #endif #if defined(CONFIG_MIPS_UR8) && defined(CONFIG_MTD_SPI) if (!mymtd) mymtd = do_map_probe("spi_probe", &ohio_flash_map); #endif /*--- #if defined(CONFIG_MIPS_UR8) && defined(CONFIG_MTD_SPI) ---*/ /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if (mymtd) { signed int i; unsigned int hidden_size = 0, hidden_start = 0; unsigned int fs_size = 0; mymtd->owner = THIS_MODULE; for(i = LOCAL_URLADER_MTDS - 1 ; i >= 0 ; i--) { DBG_FLASH("partition_info[%d].name = \"%s\"\n",i , partition_info[i].name); if(!strcmp(partition_info[i].name, "kernel")) { char *jffs2_ptr = prom_getenv("jffs2_size"); if(jffs2_ptr) { jffs2_size = simple_strtol(jffs2_ptr, NULL, 0) * (1 << 16); printk("[mtd]: jffs2_size = %s * 64KByte (0x%x Bytes)\n", jffs2_ptr, jffs2_size); } else { jffs2_size = 2 * (1 << 20); printk("[mtd]: set to default: jffs2_size = 0x%x * 64KByte (0x%x Bytes)\n", jffs2_size / (1 << 16), jffs2_size); } hidden_size = partition_info[i].size, hidden_start = partition_info[i].offset; if(ohio_find_hidden_filesystem(mymtd, &hidden_size, &hidden_start, &fs_size, 0)) { printk("[init_ohio_flash] find hidden root filesystem failed\n"); /*--- iounmap((void *)ohio_flash_map.virt); ---*/ hidden_size = 0, hidden_start = 0; if(get_mtdram1_param()) { printk("[mtdram]: no filesystem found in FLASH, use hole partition for posible jffs2\n"); hidden_size = partition_info[i].size, hidden_start = partition_info[i].offset; printk("[mtdram] filesystem size=0x%x offset=0x%x\n", hidden_size, hidden_start); fs_size = 1; /*--- dummy: klein, nur nicht 0 ---*/ } } else { printk("[init_ohio_flash] find hidden filesystem size=0x%x offset=0x%x\n", hidden_size, hidden_start); } if(jffs2_size && fs_size) { printk("[mtd] configure jffs2 partition\n"); fs_size |= (1 << 16) - 1; fs_size += 1; /* aufrunden auf naechstes 64K segment */ printk("[mtd] fs_size=0x%x max=0x%x is=0x%x max jffs2_size value %u\n", fs_size, partition_info[i].size - fs_size, jffs2_size, (partition_info[i].size - fs_size) / (1 << 16)); if(partition_info[i].size - fs_size < jffs2_size) { printk("[mtd] ERROR jffs2_size too big, reduce to max\n"); jffs2_size = partition_info[i].size - fs_size; } /*--- kernel without jffs ---*/ partition_info[LOCAL_MTD_KERNEL_WITHOUT_JFFS2].size = partition_info[i].size - jffs2_size; partition_info[LOCAL_MTD_KERNEL_WITHOUT_JFFS2].offset = partition_info[i].offset; /*--- jffs ---*/ partition_info[LOCAL_MTD_JFFS2].size = jffs2_size; partition_info[LOCAL_MTD_JFFS2].offset = partition_info[i].offset + partition_info[LOCAL_MTD_KERNEL_WITHOUT_JFFS2].size; } continue; } if(!strcmp(partition_info[i].name, "filesystem")) { char buff[64]; char *p; if((partition_info[i].size == 0) && (partition_info[i].offset == 0)) { partition_info[i].size = hidden_size; partition_info[i].offset = hidden_start; } p = prom_getenv("nfsroot"); if(p) { root_dev_setup(p); } else { int mtd_index = i; if (mymtd->type != MTD_SPIFLASH) mtd_index += 1; /*--- beim SPI-Flash gibt es eine Partition weniger (phys_mapped flash) ---*/ sprintf(buff, "/dev/mtdblock%u", mtd_index); root_dev_setup(buff); } } } if(jffs2_size == 0) NUM_PARTITIONS -= 2; printk("[mtd] ohio_flash_map: name=%s bankwidth=%u virt=0x%p phys=0x%lx size=0x%lx\n", ohio_flash_map.name, ohio_flash_map.bankwidth, ohio_flash_map.virt, ohio_flash_map.phys, ohio_flash_map.size); mymtd->flags = MTD_CLEAR_BITS | MTD_CAP_NORFLASH; /* Create MTD devices for each partition. */ add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); for(i = 0 ; i < NUM_PARTITIONS ; i++) { printk("partition_info[%u]: name=%s offset=%x size=%x\n", i, partition_info[i].name, partition_info[i].offset, partition_info[i].size); printk("partition_info[%u]: 0x%x: 0x%x 0x%x\n", i, (unsigned int)ohio_flash_map.virt + partition_info[i].offset, ((unsigned int *)((unsigned int)ohio_flash_map.virt + partition_info[i].offset))[0], ((unsigned int *)((unsigned int)ohio_flash_map.virt + partition_info[i].offset))[1]); } /*----------------------------------------------------------------------------------*\ * MTDRAM \*----------------------------------------------------------------------------------*/ { unsigned int mtdram_base, mtdram_size, ram_size, ram_mask; char *mtdram, *p1; mtdram = get_mtdram1_param(); if(mtdram == NULL) return 0; /*--- der "normalfall" ---*/ /*------------------------------------------------------------------------------*\ * Aus der memsize die RAM-Addr-Maske ermitteln \*------------------------------------------------------------------------------*/ p = prom_getenv("memsize"); if(!p) { return 0; } ram_size = simple_strtol(p, NULL, 0); printk("[mtdram] mem_size=0x%x\n", ram_size); ohio_ram_map.size = ram_size; ram_mask = ram_size & (((1 << 20) *64) - 1); /* funktioniert bis 64 MByte Speicher */ p1 = p = mtdram + sizeof("mtdram0=") - 1; while(*p1 && *p1 != ',') p1++; if(*p1 == '\0') { return 0; } *p1++ = '\0'; #ifdef CONFIG_MIPS mtdram_base = CPHYSADDR(simple_strtol(p, NULL, 0)); printk("[mtdram] mtdram_base=0x%x ", mtdram_base); mtdram_size = CPHYSADDR(simple_strtol(p1, NULL, 0)); printk(" mtdram_top=0x%x ", mtdram_size); #else /*--- #ifdef CONFIG_MIPS ---*/ mtdram_base = simple_strtol(p, NULL, 0); printk("[mtdram] mtdram_base=0x%x ", mtdram_base); mtdram_size = simple_strtol(p1, NULL, 0); printk(" mtdram_top=0x%x ", mtdram_size); #endif /*--- #else ---*/ /*--- #ifdef CONFIG_MIPS ---*/ mtdram_size -= mtdram_base; printk(" mtdram_size=0x%x\n", mtdram_size); /*------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------*/ printk("[mtdram]: ioremap(%x, %x)\n", mtdram_base, mtdram_size); #ifdef CONFIG_MIPS ohio_ram_map.virt = (void *)CKSEG0ADDR(ioremap(mtdram_base, mtdram_size)); #endif /*--- #ifdef CONFIG_MIPS ---*/ #if defined(CONFIG_ARCH_DAVINCI) ohio_ram_map.virt = ioremap(mtdram_base, mtdram_size); #endif /*--- #if defined(CONFIG_ARCH_DAVINCI) ---*/ ohio_ram_map.size = mtdram_size; #ifdef CONFIG_MIPS ohio_ram_map.phys = CPHYSADDR(mtdram_base); #else /*--- #ifdef CONFIG_MIPS ---*/ ohio_ram_map.phys = mtdram_base; #endif /*--- #else ---*/ /*--- #ifdef CONFIG_MIPS ---*/ mtdram_base &= ram_mask; printk("[mtdram] ohio_ram_map: name=%s bankwidth=%u virt=0x%p phys=0x%lx size=0x%lx\n", ohio_ram_map.name, ohio_ram_map.bankwidth, ohio_ram_map.virt, ohio_ram_map.phys, ohio_ram_map.size); printk("[mtdram]: do_map_probe\n"); mymtdram = do_map_probe("map_ram", &ohio_ram_map); if(mymtdram) { printk("[mtdram]: do_map_probe success\n"); mymtdram->owner = THIS_MODULE; mymtdram->flags = MTD_CAP_RAM; } partition_info_ram[0].name = "filesystem in ram"; partition_info_ram[0].mask_flags = 0; partition_info_ram[0].offset = 0; /* 0 ==> filesystem */ partition_info_ram[0].size = mtdram_size; partition_info_ram[1].name = "kernel in ram"; partition_info_ram[1].mask_flags = 0; partition_info_ram[1].offset = 0; /* kernel + filesystem ==> kernel */ partition_info_ram[1].size = mtdram_size; printk("[mtdram]: [0].offset=0x%x [0].size=0x%x [1].offset=0x%x [1].size=0x%x\n", partition_info_ram[0].offset, partition_info_ram[0].size, partition_info_ram[1].offset, partition_info_ram[1].size); /*--- debug_flag = 1; ---*/ if(ohio_find_hidden_filesystem(mymtdram, &(partition_info_ram[0].size), &(partition_info_ram[0].offset), NULL, 1)) { printk("[mtdram]: no hidden filesystem found\n"); iounmap((void *)ohio_ram_map.virt); return 0; } partition_info_ram[1].size -= partition_info_ram[0].size; printk("[mtdram] ohio_ram_map: name=%s bankwidth=%u virt=0x%p phys=0x%lx size=0x%lx\n", ohio_ram_map.name, ohio_ram_map.bankwidth, ohio_ram_map.virt, ohio_ram_map.phys, ohio_ram_map.size); printk("[mtdram]: [0].offset=0x%x [0].size=0x%x [1].offset=0x%x [1].size=0x%x\n", partition_info_ram[0].offset, partition_info_ram[0].size, partition_info_ram[1].offset, partition_info_ram[1].size); add_mtd_partitions(mymtdram, partition_info_ram, 2); for(i = 0 ; i < 2 ; i++) { printk("partition_info[%u]: name=%s offset=%x size=%x\n", i, partition_info_ram[i].name, partition_info_ram[i].offset, partition_info_ram[i].size); printk("partition_info[%u]: 0x%x: 0x%x 0x%x\n", i, (unsigned int)ohio_ram_map.virt + partition_info_ram[i].offset, ((unsigned int *)((unsigned int)ohio_ram_map.virt + partition_info_ram[i].offset))[0], ((unsigned int *)((unsigned int)ohio_ram_map.virt + partition_info_ram[i].offset))[1]); } { char buff[64]; sprintf(buff, "/dev/mtdblock%u", NUM_PARTITIONS + 1); root_dev_setup(buff); } } return 0; } iounmap((void *)ohio_flash_map.virt); return -ENXIO; } static void __exit cleanup_ohio_flash(void) { if (mymtd) { del_mtd_partitions(mymtd); map_destroy(mymtd); } if (ohio_flash_map.virt) { iounmap((void *)ohio_flash_map.virt); ohio_flash_map.virt = 0; } } module_init(init_ohio_flash); module_exit(cleanup_ohio_flash); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MTD map driver for ohio board (copied from dbox2 files)");