gpio-addr-flash.c revision f5bae56a501347671b18095731d78e13eee5205f
1/* 2 * drivers/mtd/maps/gpio-addr-flash.c 3 * 4 * Handle the case where a flash device is mostly addressed using physical 5 * line and supplemented by GPIOs. This way you can hook up say a 8MiB flash 6 * to a 2MiB memory range and use the GPIOs to select a particular range. 7 * 8 * Copyright © 2000 Nicolas Pitre <nico@cam.org> 9 * Copyright © 2005-2009 Analog Devices Inc. 10 * 11 * Enter bugs at http://blackfin.uclinux.org/ 12 * 13 * Licensed under the GPL-2 or later. 14 */ 15 16#include <linux/gpio.h> 17#include <linux/init.h> 18#include <linux/io.h> 19#include <linux/kernel.h> 20#include <linux/module.h> 21#include <linux/mtd/mtd.h> 22#include <linux/mtd/map.h> 23#include <linux/mtd/partitions.h> 24#include <linux/mtd/physmap.h> 25#include <linux/platform_device.h> 26#include <linux/types.h> 27 28#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) 29 30#define DRIVER_NAME "gpio-addr-flash" 31#define PFX DRIVER_NAME ": " 32 33/** 34 * struct async_state - keep GPIO flash state 35 * @mtd: MTD state for this mapping 36 * @map: MTD map state for this flash 37 * @gpio_count: number of GPIOs used to address 38 * @gpio_addrs: array of GPIOs to twiddle 39 * @gpio_values: cached GPIO values 40 * @win_size: dedicated memory size (if no GPIOs) 41 */ 42struct async_state { 43 struct mtd_info *mtd; 44 struct map_info map; 45 size_t gpio_count; 46 unsigned *gpio_addrs; 47 int *gpio_values; 48 unsigned long win_size; 49}; 50#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1) 51 52/** 53 * gf_set_gpios() - set GPIO address lines to access specified flash offset 54 * @state: GPIO flash state 55 * @ofs: desired offset to access 56 * 57 * Rather than call the GPIO framework every time, cache the last-programmed 58 * value. This speeds up sequential accesses (which are by far the most common 59 * type). We rely on the GPIO framework to treat non-zero value as high so 60 * that we don't have to normalize the bits. 61 */ 62static void gf_set_gpios(struct async_state *state, unsigned long ofs) 63{ 64 size_t i = 0; 65 int value; 66 ofs /= state->win_size; 67 do { 68 value = ofs & (1 << i); 69 if (state->gpio_values[i] != value) { 70 gpio_set_value(state->gpio_addrs[i], value); 71 state->gpio_values[i] = value; 72 } 73 } while (++i < state->gpio_count); 74} 75 76/** 77 * gf_read() - read a word at the specified offset 78 * @map: MTD map state 79 * @ofs: desired offset to read 80 */ 81static map_word gf_read(struct map_info *map, unsigned long ofs) 82{ 83 struct async_state *state = gf_map_info_to_state(map); 84 uint16_t word; 85 map_word test; 86 87 gf_set_gpios(state, ofs); 88 89 word = readw(map->virt + (ofs % state->win_size)); 90 test.x[0] = word; 91 return test; 92} 93 94/** 95 * gf_copy_from() - copy a chunk of data from the flash 96 * @map: MTD map state 97 * @to: memory to copy to 98 * @from: flash offset to copy from 99 * @len: how much to copy 100 * 101 * We rely on the MTD layer to chunk up copies such that a single request here 102 * will not cross a window size. This allows us to only wiggle the GPIOs once 103 * before falling back to a normal memcpy. Reading the higher layer code shows 104 * that this is indeed the case, but add a BUG_ON() to future proof. 105 */ 106static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 107{ 108 struct async_state *state = gf_map_info_to_state(map); 109 110 gf_set_gpios(state, from); 111 112 /* BUG if operation crosses the win_size */ 113 BUG_ON(!((from + len) % state->win_size <= (from + len))); 114 115 /* operation does not cross the win_size, so one shot it */ 116 memcpy_fromio(to, map->virt + (from % state->win_size), len); 117} 118 119/** 120 * gf_write() - write a word at the specified offset 121 * @map: MTD map state 122 * @ofs: desired offset to write 123 */ 124static void gf_write(struct map_info *map, map_word d1, unsigned long ofs) 125{ 126 struct async_state *state = gf_map_info_to_state(map); 127 uint16_t d; 128 129 gf_set_gpios(state, ofs); 130 131 d = d1.x[0]; 132 writew(d, map->virt + (ofs % state->win_size)); 133} 134 135/** 136 * gf_copy_to() - copy a chunk of data to the flash 137 * @map: MTD map state 138 * @to: flash offset to copy to 139 * @from: memory to copy from 140 * @len: how much to copy 141 * 142 * See gf_copy_from() caveat. 143 */ 144static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) 145{ 146 struct async_state *state = gf_map_info_to_state(map); 147 148 gf_set_gpios(state, to); 149 150 /* BUG if operation crosses the win_size */ 151 BUG_ON(!((to + len) % state->win_size <= (to + len))); 152 153 /* operation does not cross the win_size, so one shot it */ 154 memcpy_toio(map->virt + (to % state->win_size), from, len); 155} 156 157#ifdef CONFIG_MTD_PARTITIONS 158static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; 159#endif 160 161/** 162 * gpio_flash_probe() - setup a mapping for a GPIO assisted flash 163 * @pdev: platform device 164 * 165 * The platform resource layout expected looks something like: 166 * struct mtd_partition partitions[] = { ... }; 167 * struct physmap_flash_data flash_data = { ... }; 168 * unsigned flash_gpios[] = { GPIO_XX, GPIO_XX, ... }; 169 * struct resource flash_resource[] = { 170 * { 171 * .name = "cfi_probe", 172 * .start = 0x20000000, 173 * .end = 0x201fffff, 174 * .flags = IORESOURCE_MEM, 175 * }, { 176 * .start = (unsigned long)flash_gpios, 177 * .end = ARRAY_SIZE(flash_gpios), 178 * .flags = IORESOURCE_IRQ, 179 * } 180 * }; 181 * struct platform_device flash_device = { 182 * .name = "gpio-addr-flash", 183 * .dev = { .platform_data = &flash_data, }, 184 * .num_resources = ARRAY_SIZE(flash_resource), 185 * .resource = flash_resource, 186 * ... 187 * }; 188 */ 189static int __devinit gpio_flash_probe(struct platform_device *pdev) 190{ 191 int ret; 192 size_t i, arr_size; 193 struct physmap_flash_data *pdata; 194 struct resource *memory; 195 struct resource *gpios; 196 struct async_state *state; 197 198 pdata = pdev->dev.platform_data; 199 memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); 200 gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 201 202 if (!memory || !gpios || !gpios->end) 203 return -EINVAL; 204 205 arr_size = sizeof(int) * gpios->end; 206 state = kzalloc(sizeof(*state) + arr_size, GFP_KERNEL); 207 if (!state) 208 return -ENOMEM; 209 210 state->gpio_count = gpios->end; 211 state->gpio_addrs = (void *)gpios->start; 212 state->gpio_values = (void *)(state + 1); 213 state->win_size = memory->end - memory->start + 1; 214 memset(state->gpio_values, 0xff, arr_size); 215 216 state->map.name = DRIVER_NAME; 217 state->map.read = gf_read; 218 state->map.copy_from = gf_copy_from; 219 state->map.write = gf_write; 220 state->map.copy_to = gf_copy_to; 221 state->map.bankwidth = pdata->width; 222 state->map.size = state->win_size * (1 << state->gpio_count); 223 state->map.virt = (void __iomem *)memory->start; 224 state->map.phys = NO_XIP; 225 state->map.map_priv_1 = (unsigned long)state; 226 227 platform_set_drvdata(pdev, state); 228 229 i = 0; 230 do { 231 if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) { 232 pr_devinit(KERN_ERR PFX "failed to request gpio %d\n", 233 state->gpio_addrs[i]); 234 while (i--) 235 gpio_free(state->gpio_addrs[i]); 236 kfree(state); 237 return -EBUSY; 238 } 239 gpio_direction_output(state->gpio_addrs[i], 0); 240 } while (++i < state->gpio_count); 241 242 pr_devinit(KERN_NOTICE PFX "probing %d-bit flash bus\n", 243 state->map.bankwidth * 8); 244 state->mtd = do_map_probe(memory->name, &state->map); 245 if (!state->mtd) { 246 for (i = 0; i < state->gpio_count; ++i) 247 gpio_free(state->gpio_addrs[i]); 248 kfree(state); 249 return -ENXIO; 250 } 251 252#ifdef CONFIG_MTD_PARTITIONS 253 ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); 254 if (ret > 0) { 255 pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n"); 256 add_mtd_partitions(state->mtd, pdata->parts, ret); 257 kfree(pdata->parts); 258 259 } else if (pdata->nr_parts) { 260 pr_devinit(KERN_NOTICE PFX "Using board partition definition\n"); 261 add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts); 262 263 } else 264#endif 265 { 266 pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n"); 267 add_mtd_device(state->mtd); 268 } 269 270 return 0; 271} 272 273static int __devexit gpio_flash_remove(struct platform_device *pdev) 274{ 275 struct async_state *state = platform_get_drvdata(pdev); 276 size_t i = 0; 277 do { 278 gpio_free(state->gpio_addrs[i]); 279 } while (++i < state->gpio_count); 280#ifdef CONFIG_MTD_PARTITIONS 281 del_mtd_partitions(state->mtd); 282#endif 283 map_destroy(state->mtd); 284 kfree(state); 285 return 0; 286} 287 288static struct platform_driver gpio_flash_driver = { 289 .probe = gpio_flash_probe, 290 .remove = __devexit_p(gpio_flash_remove), 291 .driver = { 292 .name = DRIVER_NAME, 293 }, 294}; 295 296static int __init gpio_flash_init(void) 297{ 298 return platform_driver_register(&gpio_flash_driver); 299} 300module_init(gpio_flash_init); 301 302static void __exit gpio_flash_exit(void) 303{ 304 platform_driver_unregister(&gpio_flash_driver); 305} 306module_exit(gpio_flash_exit); 307 308MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); 309MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios"); 310MODULE_LICENSE("GPL"); 311