1/* 2 * Flash memory access on Alchemy Pb1xxx boards 3 * 4 * (C) 2001 Pete Popov <ppopov@mvista.com> 5 * 6 * $Id: pb1xxx-flash.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $ 7 */ 8 9#include <linux/config.h> 10#include <linux/module.h> 11#include <linux/types.h> 12#include <linux/kernel.h> 13 14#include <linux/mtd/mtd.h> 15#include <linux/mtd/map.h> 16#include <linux/mtd/partitions.h> 17 18#include <asm/io.h> 19#include <asm/au1000.h> 20 21#ifdef DEBUG_RW 22#define DBG(x...) printk(x) 23#else 24#define DBG(x...) 25#endif 26 27#ifdef CONFIG_MIPS_PB1000 28#define WINDOW_ADDR 0x1F800000 29#define WINDOW_SIZE 0x800000 30#endif 31 32__u8 physmap_read8(struct map_info *map, unsigned long ofs) 33{ 34 __u8 ret; 35 ret = __raw_readb(map->map_priv_1 + ofs); 36 DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); 37 return ret; 38} 39 40__u16 physmap_read16(struct map_info *map, unsigned long ofs) 41{ 42 __u16 ret; 43 ret = __raw_readw(map->map_priv_1 + ofs); 44 DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); 45 return ret; 46} 47 48__u32 physmap_read32(struct map_info *map, unsigned long ofs) 49{ 50 __u32 ret; 51 ret = __raw_readl(map->map_priv_1 + ofs); 52 DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret); 53 return ret; 54} 55 56void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 57{ 58 DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to); 59 memcpy_fromio(to, map->map_priv_1 + from, len); 60} 61 62void physmap_write8(struct map_info *map, __u8 d, unsigned long adr) 63{ 64 DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); 65 __raw_writeb(d, map->map_priv_1 + adr); 66 mb(); 67} 68 69void physmap_write16(struct map_info *map, __u16 d, unsigned long adr) 70{ 71 DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); 72 __raw_writew(d, map->map_priv_1 + adr); 73 mb(); 74} 75 76void physmap_write32(struct map_info *map, __u32 d, unsigned long adr) 77{ 78 DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d); 79 __raw_writel(d, map->map_priv_1 + adr); 80 mb(); 81} 82 83void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 84{ 85 DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from); 86 memcpy_toio(map->map_priv_1 + to, from, len); 87} 88 89 90 91static struct map_info pb1xxx_map = { 92 name: "Pb1xxx flash", 93 read8: physmap_read8, 94 read16: physmap_read16, 95 read32: physmap_read32, 96 copy_from: physmap_copy_from, 97 write8: physmap_write8, 98 write16: physmap_write16, 99 write32: physmap_write32, 100 copy_to: physmap_copy_to, 101}; 102 103 104#ifdef CONFIG_MIPS_PB1000 105 106static unsigned long flash_size = 0x00800000; 107static unsigned char flash_buswidth = 4; 108static struct mtd_partition pb1xxx_partitions[] = { 109 { 110 name: "yamon env", 111 size: 0x00020000, 112 offset: 0, 113 mask_flags: MTD_WRITEABLE 114 },{ 115 name: "User FS", 116 size: 0x003e0000, 117 offset: 0x20000, 118 },{ 119 name: "boot code", 120 size: 0x100000, 121 offset: 0x400000, 122 mask_flags: MTD_WRITEABLE 123 },{ 124 name: "raw/kernel", 125 size: 0x300000, 126 offset: 0x500000 127 } 128}; 129 130#elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) 131 132static unsigned char flash_buswidth = 4; 133#if defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER) 134/* both 32MB banks will be used. Combine the first 32MB bank and the 135 * first 28MB of the second bank together into a single jffs/jffs2 136 * partition. 137 */ 138static unsigned long flash_size = 0x04000000; 139#define WINDOW_ADDR 0x1C000000 140#define WINDOW_SIZE 0x4000000 141static struct mtd_partition pb1xxx_partitions[] = { 142 { 143 name: "User FS", 144 size: 0x3c00000, 145 offset: 0x0000000 146 },{ 147 name: "yamon", 148 size: 0x0100000, 149 offset: 0x3c00000, 150 mask_flags: MTD_WRITEABLE 151 },{ 152 name: "raw kernel", 153 size: 0x02c0000, 154 offset: 0x3d00000 155 } 156}; 157#elif defined(CONFIG_MTD_PB1500_BOOT) && !defined(CONFIG_MTD_PB1500_USER) 158static unsigned long flash_size = 0x02000000; 159#define WINDOW_ADDR 0x1E000000 160#define WINDOW_SIZE 0x2000000 161static struct mtd_partition pb1xxx_partitions[] = { 162 { 163 name: "User FS", 164 size: 0x1c00000, 165 offset: 0x0000000 166 },{ 167 name: "yamon", 168 size: 0x0100000, 169 offset: 0x1c00000, 170 mask_flags: MTD_WRITEABLE 171 },{ 172 name: "raw kernel", 173 size: 0x02c0000, 174 offset: 0x1d00000 175 } 176}; 177#elif !defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER) 178static unsigned long flash_size = 0x02000000; 179#define WINDOW_ADDR 0x1C000000 180#define WINDOW_SIZE 0x2000000 181static struct mtd_partition pb1xxx_partitions[] = { 182 { 183 name: "User FS", 184 size: 0x1e00000, 185 offset: 0x0000000 186 },{ 187 name: "raw kernel", 188 size: 0x0200000, 189 offset: 0x1e00000, 190 } 191}; 192#else 193#error MTD_PB1500 define combo error /* should never happen */ 194#endif 195#else 196#error Unsupported board 197#endif 198 199 200#define NB_OF(x) (sizeof(x)/sizeof(x[0])) 201 202static struct mtd_partition *parsed_parts; 203static struct mtd_info *mymtd; 204 205int __init pb1xxx_mtd_init(void) 206{ 207 struct mtd_partition *parts; 208 int nb_parts = 0; 209 char *part_type; 210 211 /* Default flash buswidth */ 212 pb1xxx_map.buswidth = flash_buswidth; 213 214 /* 215 * Static partition definition selection 216 */ 217 part_type = "static"; 218 parts = pb1xxx_partitions; 219 nb_parts = NB_OF(pb1xxx_partitions); 220 pb1xxx_map.size = flash_size; 221 222 /* 223 * Now let's probe for the actual flash. Do it here since 224 * specific machine settings might have been set above. 225 */ 226 printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n", 227 pb1xxx_map.buswidth*8); 228 pb1xxx_map.map_priv_1 = 229 (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); 230 mymtd = do_map_probe("cfi_probe", &pb1xxx_map); 231 if (!mymtd) return -ENXIO; 232 mymtd->module = THIS_MODULE; 233 234 add_mtd_partitions(mymtd, parts, nb_parts); 235 return 0; 236} 237 238static void __exit pb1xxx_mtd_cleanup(void) 239{ 240 if (mymtd) { 241 del_mtd_partitions(mymtd); 242 map_destroy(mymtd); 243 if (parsed_parts) 244 kfree(parsed_parts); 245 } 246} 247 248module_init(pb1xxx_mtd_init); 249module_exit(pb1xxx_mtd_cleanup); 250 251MODULE_AUTHOR("Pete Popov"); 252MODULE_DESCRIPTION("Pb1xxx CFI map driver"); 253MODULE_LICENSE("GPL"); 254