Blame view
drivers/mtd/maps/pmcmsp-flash.c
6.1 KB
68aa0fa87 [MTD] PMC MSP71xx... |
1 2 3 4 5 |
/* * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. * Config with both CFI and JEDEC device support. * * Basically physmap.c with the addition of partitions and |
25985edce Fix common misspe... |
6 |
* an array of mapping info to accommodate more than one flash type per board. |
68aa0fa87 [MTD] PMC MSP71xx... |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
* * Copyright 2005-2007 PMC-Sierra, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ |
5a0e3ad6a include cleanup: ... |
30 |
#include <linux/slab.h> |
68aa0fa87 [MTD] PMC MSP71xx... |
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> #include <asm/io.h> #include <msp_prom.h> #include <msp_regs.h> static struct mtd_info **msp_flash; static struct mtd_partition **msp_parts; static struct map_info *msp_maps; static int fcnt; |
cb53b3b99 [MTD] replace rem... |
48 49 |
#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d] ", __func__, __LINE__) |
68aa0fa87 [MTD] PMC MSP71xx... |
50 |
|
6127cfcd3 [MTD] Make init_m... |
51 |
static int __init init_msp_flash(void) |
68aa0fa87 [MTD] PMC MSP71xx... |
52 |
{ |
2c78c4436 mtd: pmcmsp-flash... |
53 |
int i, j, ret = -ENOMEM; |
68aa0fa87 [MTD] PMC MSP71xx... |
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
int offset, coff; char *env; int pcnt; char flash_name[] = "flash0"; char part_name[] = "flash0_0"; unsigned addr, size; /* If ELB is disabled by "ful-mux" mode, we can't get at flash */ if ((*DEV_ID_REG & DEV_ID_SINGLE_PC) && (*ELB_1PC_EN_REG & SINGLE_PCCARD)) { printk(KERN_NOTICE "Single PC Card mode: no flash access "); return -ENXIO; } /* examine the prom environment for flash devices */ for (fcnt = 0; (env = prom_getenv(flash_name)); fcnt++) flash_name[5] = '0' + fcnt + 1; if (fcnt < 1) return -ENXIO; printk(KERN_NOTICE "Found %d PMC flash devices ", fcnt); |
4fb4caa63 [MTD] pmcmsp-flas... |
78 79 |
msp_flash = kmalloc(fcnt * sizeof(struct map_info *), GFP_KERNEL); |
2c78c4436 mtd: pmcmsp-flash... |
80 81 |
if (!msp_flash) return -ENOMEM; |
4fb4caa63 [MTD] pmcmsp-flas... |
82 |
msp_parts = kmalloc(fcnt * sizeof(struct mtd_partition *), GFP_KERNEL); |
2c78c4436 mtd: pmcmsp-flash... |
83 84 |
if (!msp_parts) goto free_msp_flash; |
4fb4caa63 [MTD] pmcmsp-flas... |
85 |
msp_maps = kcalloc(fcnt, sizeof(struct mtd_info), GFP_KERNEL); |
2c78c4436 mtd: pmcmsp-flash... |
86 87 |
if (!msp_maps) goto free_msp_parts; |
68aa0fa87 [MTD] PMC MSP71xx... |
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
/* loop over the flash devices, initializing each */ for (i = 0; i < fcnt; i++) { /* examine the prom environment for flash partititions */ part_name[5] = '0' + i; part_name[7] = '0'; for (pcnt = 0; (env = prom_getenv(part_name)); pcnt++) part_name[7] = '0' + pcnt + 1; if (pcnt == 0) { printk(KERN_NOTICE "Skipping flash device %d " "(no partitions defined) ", i); continue; } |
4fb4caa63 [MTD] pmcmsp-flas... |
103 104 |
msp_parts[i] = kcalloc(pcnt, sizeof(struct mtd_partition), GFP_KERNEL); |
2c78c4436 mtd: pmcmsp-flash... |
105 106 |
if (!msp_parts[i]) goto cleanup_loop; |
68aa0fa87 [MTD] PMC MSP71xx... |
107 108 109 110 |
/* now initialize the devices proper */ flash_name[5] = '0' + i; env = prom_getenv(flash_name); |
2c78c4436 mtd: pmcmsp-flash... |
111 112 113 114 115 |
if (sscanf(env, "%x:%x", &addr, &size) < 2) { ret = -ENXIO; kfree(msp_parts[i]); goto cleanup_loop; } |
68aa0fa87 [MTD] PMC MSP71xx... |
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
addr = CPHYSADDR(addr); printk(KERN_NOTICE "MSP flash device \"%s\": 0x%08x at 0x%08x ", flash_name, size, addr); /* This must matchs the actual size of the flash chip */ msp_maps[i].size = size; msp_maps[i].phys = addr; /* * Platforms have a specific limit of the size of memory * which may be mapped for flash: */ if (size > CONFIG_MSP_FLASH_MAP_LIMIT) size = CONFIG_MSP_FLASH_MAP_LIMIT; |
2c78c4436 mtd: pmcmsp-flash... |
132 |
|
68aa0fa87 [MTD] PMC MSP71xx... |
133 |
msp_maps[i].virt = ioremap(addr, size); |
2c78c4436 mtd: pmcmsp-flash... |
134 135 136 137 138 |
if (msp_maps[i].virt == NULL) { ret = -ENXIO; kfree(msp_parts[i]); goto cleanup_loop; } |
68aa0fa87 [MTD] PMC MSP71xx... |
139 |
msp_maps[i].bankwidth = 1; |
2c78c4436 mtd: pmcmsp-flash... |
140 141 142 143 144 145 |
msp_maps[i].name = kmalloc(7, GFP_KERNEL); if (!msp_maps[i].name) { iounmap(msp_maps[i].virt); kfree(msp_parts[i]); goto cleanup_loop; } |
68aa0fa87 [MTD] PMC MSP71xx... |
146 |
|
2c78c4436 mtd: pmcmsp-flash... |
147 |
msp_maps[i].name = strncpy(msp_maps[i].name, flash_name, 7); |
68aa0fa87 [MTD] PMC MSP71xx... |
148 149 150 151 152 153 |
for (j = 0; j < pcnt; j++) { part_name[5] = '0' + i; part_name[7] = '0' + j; env = prom_getenv(part_name); |
2c78c4436 mtd: pmcmsp-flash... |
154 155 156 157 158 159 160 161 |
if (sscanf(env, "%x:%x:%n", &offset, &size, &coff) < 2) { ret = -ENXIO; kfree(msp_maps[i].name); iounmap(msp_maps[i].virt); kfree(msp_parts[i]); goto cleanup_loop; } |
68aa0fa87 [MTD] PMC MSP71xx... |
162 163 164 165 166 167 168 169 170 171 172 |
msp_parts[i][j].size = size; msp_parts[i][j].offset = offset; msp_parts[i][j].name = env + coff; } /* now probe and add the device */ simple_map_init(&msp_maps[i]); msp_flash[i] = do_map_probe("cfi_probe", &msp_maps[i]); if (msp_flash[i]) { msp_flash[i]->owner = THIS_MODULE; |
ee0e87b17 mtd: convert rema... |
173 |
mtd_device_register(msp_flash[i], msp_parts[i], pcnt); |
68aa0fa87 [MTD] PMC MSP71xx... |
174 175 176 |
} else { printk(KERN_ERR "map probe failed for flash "); |
2c78c4436 mtd: pmcmsp-flash... |
177 178 179 180 181 |
ret = -ENXIO; kfree(msp_maps[i].name); iounmap(msp_maps[i].virt); kfree(msp_parts[i]); goto cleanup_loop; |
68aa0fa87 [MTD] PMC MSP71xx... |
182 183 184 185 |
} } return 0; |
2c78c4436 mtd: pmcmsp-flash... |
186 187 188 |
cleanup_loop: while (i--) { |
ee0e87b17 mtd: convert rema... |
189 |
mtd_device_unregister(msp_flash[i]); |
2c78c4436 mtd: pmcmsp-flash... |
190 191 192 193 194 195 196 197 198 199 200 |
map_destroy(msp_flash[i]); kfree(msp_maps[i].name); iounmap(msp_maps[i].virt); kfree(msp_parts[i]); } kfree(msp_maps); free_msp_parts: kfree(msp_parts); free_msp_flash: kfree(msp_flash); return ret; |
68aa0fa87 [MTD] PMC MSP71xx... |
201 202 203 204 205 |
} static void __exit cleanup_msp_flash(void) { int i; |
2c78c4436 mtd: pmcmsp-flash... |
206 |
for (i = 0; i < fcnt; i++) { |
ee0e87b17 mtd: convert rema... |
207 |
mtd_device_unregister(msp_flash[i]); |
68aa0fa87 [MTD] PMC MSP71xx... |
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
map_destroy(msp_flash[i]); iounmap((void *)msp_maps[i].virt); /* free the memory */ kfree(msp_maps[i].name); kfree(msp_parts[i]); } kfree(msp_flash); kfree(msp_parts); kfree(msp_maps); } MODULE_AUTHOR("PMC-Sierra, Inc"); MODULE_DESCRIPTION("MTD map driver for PMC-Sierra MSP boards"); MODULE_LICENSE("GPL"); module_init(init_msp_flash); module_exit(cleanup_msp_flash); |