dc21285.c (5547B)
1/* 2 * MTD map driver for flash on the DC21285 (the StrongARM-110 companion chip) 3 * 4 * (C) 2000 Nicolas Pitre <nico@fluxnic.net> 5 * 6 * This code is GPL 7 */ 8#include <linux/module.h> 9#include <linux/types.h> 10#include <linux/kernel.h> 11#include <linux/init.h> 12#include <linux/delay.h> 13#include <linux/slab.h> 14 15#include <linux/mtd/mtd.h> 16#include <linux/mtd/map.h> 17#include <linux/mtd/partitions.h> 18 19#include <asm/io.h> 20#include <asm/hardware/dec21285.h> 21#include <asm/mach-types.h> 22 23 24static struct mtd_info *dc21285_mtd; 25 26#ifdef CONFIG_ARCH_NETWINDER 27/* 28 * This is really ugly, but it seams to be the only 29 * realiable way to do it, as the cpld state machine 30 * is unpredictible. So we have a 25us penalty per 31 * write access. 32 */ 33static void nw_en_write(void) 34{ 35 unsigned long flags; 36 37 /* 38 * we want to write a bit pattern XXX1 to Xilinx to enable 39 * the write gate, which will be open for about the next 2ms. 40 */ 41 raw_spin_lock_irqsave(&nw_gpio_lock, flags); 42 nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); 43 raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); 44 45 /* 46 * let the ISA bus to catch on... 47 */ 48 udelay(25); 49} 50#else 51#define nw_en_write() do { } while (0) 52#endif 53 54static map_word dc21285_read8(struct map_info *map, unsigned long ofs) 55{ 56 map_word val; 57 val.x[0] = *(uint8_t*)(map->virt + ofs); 58 return val; 59} 60 61static map_word dc21285_read16(struct map_info *map, unsigned long ofs) 62{ 63 map_word val; 64 val.x[0] = *(uint16_t*)(map->virt + ofs); 65 return val; 66} 67 68static map_word dc21285_read32(struct map_info *map, unsigned long ofs) 69{ 70 map_word val; 71 val.x[0] = *(uint32_t*)(map->virt + ofs); 72 return val; 73} 74 75static void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 76{ 77 memcpy(to, (void*)(map->virt + from), len); 78} 79 80static void dc21285_write8(struct map_info *map, const map_word d, unsigned long adr) 81{ 82 if (machine_is_netwinder()) 83 nw_en_write(); 84 *CSR_ROMWRITEREG = adr & 3; 85 adr &= ~3; 86 *(uint8_t*)(map->virt + adr) = d.x[0]; 87} 88 89static void dc21285_write16(struct map_info *map, const map_word d, unsigned long adr) 90{ 91 if (machine_is_netwinder()) 92 nw_en_write(); 93 *CSR_ROMWRITEREG = adr & 3; 94 adr &= ~3; 95 *(uint16_t*)(map->virt + adr) = d.x[0]; 96} 97 98static void dc21285_write32(struct map_info *map, const map_word d, unsigned long adr) 99{ 100 if (machine_is_netwinder()) 101 nw_en_write(); 102 *(uint32_t*)(map->virt + adr) = d.x[0]; 103} 104 105static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const void *from, ssize_t len) 106{ 107 while (len > 0) { 108 map_word d; 109 d.x[0] = *((uint32_t*)from); 110 dc21285_write32(map, d, to); 111 from += 4; 112 to += 4; 113 len -= 4; 114 } 115} 116 117static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len) 118{ 119 while (len > 0) { 120 map_word d; 121 d.x[0] = *((uint16_t*)from); 122 dc21285_write16(map, d, to); 123 from += 2; 124 to += 2; 125 len -= 2; 126 } 127} 128 129static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len) 130{ 131 map_word d; 132 d.x[0] = *((uint8_t*)from); 133 dc21285_write8(map, d, to); 134 from++; 135 to++; 136 len--; 137} 138 139static struct map_info dc21285_map = { 140 .name = "DC21285 flash", 141 .phys = NO_XIP, 142 .size = 16*1024*1024, 143 .copy_from = dc21285_copy_from, 144}; 145 146/* Partition stuff */ 147static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL }; 148 149static int __init init_dc21285(void) 150{ 151 /* Determine bankwidth */ 152 switch (*CSR_SA110_CNTL & (3<<14)) { 153 case SA110_CNTL_ROMWIDTH_8: 154 dc21285_map.bankwidth = 1; 155 dc21285_map.read = dc21285_read8; 156 dc21285_map.write = dc21285_write8; 157 dc21285_map.copy_to = dc21285_copy_to_8; 158 break; 159 case SA110_CNTL_ROMWIDTH_16: 160 dc21285_map.bankwidth = 2; 161 dc21285_map.read = dc21285_read16; 162 dc21285_map.write = dc21285_write16; 163 dc21285_map.copy_to = dc21285_copy_to_16; 164 break; 165 case SA110_CNTL_ROMWIDTH_32: 166 dc21285_map.bankwidth = 4; 167 dc21285_map.read = dc21285_read32; 168 dc21285_map.write = dc21285_write32; 169 dc21285_map.copy_to = dc21285_copy_to_32; 170 break; 171 default: 172 printk (KERN_ERR "DC21285 flash: undefined bankwidth\n"); 173 return -ENXIO; 174 } 175 printk (KERN_NOTICE "DC21285 flash support (%d-bit bankwidth)\n", 176 dc21285_map.bankwidth*8); 177 178 /* Let's map the flash area */ 179 dc21285_map.virt = ioremap(DC21285_FLASH, 16*1024*1024); 180 if (!dc21285_map.virt) { 181 printk("Failed to ioremap\n"); 182 return -EIO; 183 } 184 185 if (machine_is_ebsa285()) { 186 dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map); 187 } else { 188 dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map); 189 } 190 191 if (!dc21285_mtd) { 192 iounmap(dc21285_map.virt); 193 return -ENXIO; 194 } 195 196 dc21285_mtd->owner = THIS_MODULE; 197 198 mtd_device_parse_register(dc21285_mtd, probes, NULL, NULL, 0); 199 200 if(machine_is_ebsa285()) { 201 /* 202 * Flash timing is determined with bits 19-16 of the 203 * CSR_SA110_CNTL. The value is the number of wait cycles, or 204 * 0 for 16 cycles (the default). Cycles are 20 ns. 205 * Here we use 7 for 140 ns flash chips. 206 */ 207 /* access time */ 208 *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16)); 209 /* burst time */ 210 *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20)); 211 /* tristate time */ 212 *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24)); 213 } 214 215 return 0; 216} 217 218static void __exit cleanup_dc21285(void) 219{ 220 mtd_device_unregister(dc21285_mtd); 221 map_destroy(dc21285_mtd); 222 iounmap(dc21285_map.virt); 223} 224 225module_init(init_dc21285); 226module_exit(cleanup_dc21285); 227 228 229MODULE_LICENSE("GPL"); 230MODULE_AUTHOR("Nicolas Pitre <nico@fluxnic.net>"); 231MODULE_DESCRIPTION("MTD map driver for DC21285 boards");