1/* 2 * Flash memory access on EPXA based devices 3 * 4 * (C) 2000 Nicolas Pitre <nico@cam.org> 5 * Copyright (C) 2001 Altera Corporation 6 * Copyright (C) 2001 Red Hat, Inc. 7 * 8 * $Id: epxa10db-flash.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $ 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25#include <linux/config.h> 26#include <linux/module.h> 27#include <linux/types.h> 28#include <linux/kernel.h> 29#include <asm/io.h> 30#include <linux/mtd/mtd.h> 31#include <linux/mtd/map.h> 32#include <linux/mtd/partitions.h> 33 34#include <asm/hardware.h> 35 36static int nr_parts = 0; 37static struct mtd_partition *parts; 38 39static struct mtd_info *mymtd; 40 41extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **); 42static int epxa10db_default_partitions(struct mtd_info *master, struct mtd_partition **pparts); 43 44static __u8 epxa10db_read8(struct map_info *map, unsigned long ofs) 45{ 46 return __raw_readb(map->map_priv_1 + ofs); 47} 48 49static __u16 epxa10db_read16(struct map_info *map, unsigned long ofs) 50{ 51 return __raw_readw(map->map_priv_1 + ofs); 52} 53 54static __u32 epxa10db_read32(struct map_info *map, unsigned long ofs) 55{ 56 return __raw_readl(map->map_priv_1 + ofs); 57} 58 59static void epxa10db_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 60{ 61 memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); 62} 63 64static void epxa10db_write8(struct map_info *map, __u8 d, unsigned long adr) 65{ 66 __raw_writeb(d, map->map_priv_1 + adr); 67 mb(); 68} 69 70static void epxa10db_write16(struct map_info *map, __u16 d, unsigned long adr) 71{ 72 __raw_writew(d, map->map_priv_1 + adr); 73 mb(); 74} 75 76static void epxa10db_write32(struct map_info *map, __u32 d, unsigned long adr) 77{ 78 __raw_writel(d, map->map_priv_1 + adr); 79 mb(); 80} 81 82static void epxa10db_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 83{ 84 memcpy_toio((void *)(map->map_priv_1 + to), from, len); 85} 86 87 88 89static struct map_info epxa10db_map = { 90 name: "EPXA10DB flash", 91 size: FLASH_SIZE, 92 buswidth: 2, 93 read8: epxa10db_read8, 94 read16: epxa10db_read16, 95 read32: epxa10db_read32, 96 copy_from: epxa10db_copy_from, 97 write8: epxa10db_write8, 98 write16: epxa10db_write16, 99 write32: epxa10db_write32, 100 copy_to: epxa10db_copy_to 101}; 102 103 104static int __init epxa10db_mtd_init(void) 105{ 106 int i; 107 printk(KERN_NOTICE "Epxa10db flash device: %x at %x\n", FLASH_SIZE, FLASH_START); 108 epxa10db_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); 109 if (!epxa10db_map.map_priv_1) { 110 printk("Failed to ioremap Epxa10db flash\n"); 111 return -EIO; 112 } 113 114 mymtd = do_map_probe("cfi_probe", &epxa10db_map); 115 if (!mymtd) { 116 iounmap((void *)epxa10db_map.map_priv_1); 117 return -ENXIO; 118 } 119 120 mymtd->module = THIS_MODULE; 121 122 /* Unlock the flash device. */ 123 for (i=0; i<mymtd->numeraseregions;i++){ 124 int j; 125 for(j=0;j<mymtd->eraseregions[i].numblocks;j++){ 126 mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,4); 127 } 128 } 129 130#ifdef CONFIG_MTD_REDBOOT_PARTS 131 nr_parts = parse_redboot_partitions(mymtd, &parts); 132 133 if (nr_parts > 0) { 134 add_mtd_partitions(mymtd, parts, nr_parts); 135 return 0; 136 } 137#endif 138#ifdef CONFIG_MTD_AFS_PARTS 139 nr_parts = parse_afs_partitions(mymtd, &parts); 140 141 if (nr_parts > 0) { 142 add_mtd_partitions(mymtd, parts, nr_parts); 143 return 0; 144 } 145#endif 146 147 /* No recognised partitioning schemes found - use defaults */ 148 nr_parts = epxa10db_default_partitions(mymtd, &parts); 149 if (nr_parts > 0) { 150 add_mtd_partitions(mymtd, parts, nr_parts); 151 return 0; 152 } 153 154 /* If all else fails... */ 155 add_mtd_device(mymtd); 156 return 0; 157} 158 159static void __exit epxa10db_mtd_cleanup(void) 160{ 161 if (mymtd) { 162 if (nr_parts) 163 del_mtd_partitions(mymtd); 164 else 165 del_mtd_device(mymtd); 166 map_destroy(mymtd); 167 } 168 if (epxa10db_map.map_priv_1) { 169 iounmap((void *)epxa10db_map.map_priv_1); 170 epxa10db_map.map_priv_1 = 0; 171 } 172} 173 174 175/* 176 * This will do for now, once we decide which bootldr we're finally 177 * going to use then we'll remove this function and do it properly 178 * 179 * Partions are currently (as offsets from base of flash): 180 * 0x00000000 - 0x003FFFFF - bootloader (!) 181 * 0x00400000 - 0x00FFFFFF - Flashdisk 182 */ 183 184static int __init epxa10db_default_partitions(struct mtd_info *master, struct mtd_partition **pparts) 185{ 186 struct mtd_partition *parts; 187 int ret, i; 188 int npartitions = 0; 189 char *names; 190 const char *name = "jffs"; 191 192 printk("Using default partitions for epxa10db\n"); 193 npartitions=1; 194 parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL); 195 if (!parts) { 196 ret = -ENOMEM; 197 goto out; 198 } 199 i=0; 200 names = (char *)&parts[npartitions]; 201 parts[i].name = names; 202 names += strlen(name) + 1; 203 strcpy(parts[i].name, name); 204 205 parts[i].size = FLASH_SIZE-0x00400000; 206 parts[i].offset = 0x00400000; 207 parts[i].mask_flags = 0; 208 209 out: 210 *pparts = parts; 211 return npartitions; 212} 213 214module_init(epxa10db_mtd_init); 215module_exit(epxa10db_mtd_cleanup); 216 217MODULE_AUTHOR("Clive Davies"); 218MODULE_DESCRIPTION("Altera epxa10db mtd flash map"); 219MODULE_LICENSE("GPL"); 220