1/* 2 * $Id: nora.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $ 3 * 4 * This is so simple I love it. 5 */ 6 7#include <linux/module.h> 8#include <linux/types.h> 9#include <linux/kernel.h> 10 11#include <linux/mtd/mtd.h> 12#include <linux/mtd/map.h> 13 14 15#define WINDOW_ADDR 0xd0000000 16#define WINDOW_SIZE 0x04000000 17 18static struct mtd_info *mymtd; 19 20__u8 nora_read8(struct map_info *map, unsigned long ofs) 21{ 22 return *(__u8 *)(WINDOW_ADDR + ofs); 23} 24 25__u16 nora_read16(struct map_info *map, unsigned long ofs) 26{ 27 return *(__u16 *)(WINDOW_ADDR + ofs); 28} 29 30__u32 nora_read32(struct map_info *map, unsigned long ofs) 31{ 32 return *(__u32 *)(WINDOW_ADDR + ofs); 33} 34 35void nora_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 36{ 37 memcpy(to, (void *)(WINDOW_ADDR + from), len); 38} 39 40void nora_write8(struct map_info *map, __u8 d, unsigned long adr) 41{ 42 *(__u8 *)(WINDOW_ADDR + adr) = d; 43} 44 45void nora_write16(struct map_info *map, __u16 d, unsigned long adr) 46{ 47 *(__u16 *)(WINDOW_ADDR + adr) = d; 48} 49 50void nora_write32(struct map_info *map, __u32 d, unsigned long adr) 51{ 52 *(__u32 *)(WINDOW_ADDR + adr) = d; 53} 54 55void nora_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 56{ 57 memcpy((void *)(WINDOW_ADDR + to), from, len); 58} 59 60struct map_info nora_map = { 61 name: "NORA", 62 size: WINDOW_SIZE, 63 buswidth: 2, 64 read8: nora_read8, 65 read16: nora_read16, 66 read32: nora_read32, 67 copy_from: nora_copy_from, 68 write8: nora_write8, 69 write16: nora_write16, 70 write32: nora_write32, 71 copy_to: nora_copy_to 72}; 73 74 75static int nora_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) 76{ 77 return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf); 78} 79 80static int nora_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) 81{ 82 return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf); 83} 84 85static int nora_mtd_erase (struct mtd_info *mtd, struct erase_info *instr) 86{ 87 instr->addr += (unsigned long)mtd->priv; 88 return mymtd->erase(mymtd, instr); 89} 90 91static void nora_mtd_sync (struct mtd_info *mtd) 92{ 93 mymtd->sync(mymtd); 94} 95 96static int nora_mtd_suspend (struct mtd_info *mtd) 97{ 98 return mymtd->suspend(mymtd); 99} 100 101static void nora_mtd_resume (struct mtd_info *mtd) 102{ 103 mymtd->resume(mymtd); 104} 105 106 107static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */ 108 { 109 type: MTD_NORFLASH, 110 flags: MTD_CAP_NORFLASH, 111 size: 0x60000, 112 erasesize: 0x20000, 113 name: "NORA boot firmware", 114 module: THIS_MODULE, 115 erase: nora_mtd_erase, 116 read: nora_mtd_read, 117 write: nora_mtd_write, 118 suspend: nora_mtd_suspend, 119 resume: nora_mtd_resume, 120 sync: nora_mtd_sync, 121 priv: (void *)0 122 }, 123 { 124 type: MTD_NORFLASH, 125 flags: MTD_CAP_NORFLASH, 126 size: 0x0a0000, 127 erasesize: 0x20000, 128 name: "NORA kernel", 129 module: THIS_MODULE, 130 erase: nora_mtd_erase, 131 read: nora_mtd_read, 132 write: nora_mtd_write, 133 suspend: nora_mtd_suspend, 134 resume: nora_mtd_resume, 135 sync: nora_mtd_sync, 136 priv: (void *)0x60000 137 }, 138 { 139 type: MTD_NORFLASH, 140 flags: MTD_CAP_NORFLASH, 141 size: 0x900000, 142 erasesize: 0x20000, 143 name: "NORA root filesystem", 144 module: THIS_MODULE, 145 erase: nora_mtd_erase, 146 read: nora_mtd_read, 147 write: nora_mtd_write, 148 suspend: nora_mtd_suspend, 149 resume: nora_mtd_resume, 150 sync: nora_mtd_sync, 151 priv: (void *)0x100000 152 }, 153 { 154 type: MTD_NORFLASH, 155 flags: MTD_CAP_NORFLASH, 156 size: 0x1600000, 157 erasesize: 0x20000, 158 name: "NORA second filesystem", 159 module: THIS_MODULE, 160 erase: nora_mtd_erase, 161 read: nora_mtd_read, 162 write: nora_mtd_write, 163 suspend: nora_mtd_suspend, 164 resume: nora_mtd_resume, 165 sync: nora_mtd_sync, 166 priv: (void *)0xa00000 167 } 168}; 169 170int __init init_nora(void) 171{ 172 printk(KERN_NOTICE "nora flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); 173 174 mymtd = do_map_probe("cfi_probe", &nora_map); 175 if (mymtd) { 176 mymtd->module = THIS_MODULE; 177 178 add_mtd_device(&nora_mtds[2]); 179 add_mtd_device(&nora_mtds[0]); 180 add_mtd_device(&nora_mtds[1]); 181 add_mtd_device(&nora_mtds[3]); 182 return 0; 183 } 184 185 return -ENXIO; 186} 187 188static void __exit cleanup_nora(void) 189{ 190 if (mymtd) { 191 del_mtd_device(&nora_mtds[3]); 192 del_mtd_device(&nora_mtds[1]); 193 del_mtd_device(&nora_mtds[0]); 194 del_mtd_device(&nora_mtds[2]); 195 map_destroy(mymtd); 196 } 197} 198 199module_init(init_nora); 200module_exit(cleanup_nora); 201 202MODULE_LICENSE("GPL"); 203MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>"); 204MODULE_DESCRIPTION("MTD map driver for Nora board"); 205