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/io.h> 18#include <linux/kernel.h> 19#include <linux/module.h> 20#include <linux/mtd/mtd.h> 21#include <linux/mtd/map.h> 22#include <linux/mtd/partitions.h> 23#include <linux/mtd/physmap.h> 24#include <linux/platform_device.h> 25#include <linux/slab.h> 26#include <linux/types.h> 27 28#define pr_devinit(fmt, args...) \ 29 ({ static const char __fmt[] = fmt; printk(__fmt, ## args); }) 30 31#define DRIVER_NAME "gpio-addr-flash" 32#define PFX DRIVER_NAME ": " 33 34/** 35 * struct async_state - keep GPIO flash state 36 * @mtd: MTD state for this mapping 37 * @map: MTD map state for this flash 38 * @gpio_count: number of GPIOs used to address 39 * @gpio_addrs: array of GPIOs to twiddle 40 * @gpio_values: cached GPIO values 41 * @win_size: dedicated memory size (if no GPIOs) 42 */ 43struct async_state { 44 struct mtd_info *mtd; 45 struct map_info map; 46 size_t gpio_count; 47 unsigned *gpio_addrs; 48 int *gpio_values; 49 unsigned long win_size; 50}; 51#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1) 52 53/** 54 * gf_set_gpios() - set GPIO address lines to access specified flash offset 55 * @state: GPIO flash state 56 * @ofs: desired offset to access 57 * 58 * Rather than call the GPIO framework every time, cache the last-programmed 59 * value. This speeds up sequential accesses (which are by far the most common 60 * type). We rely on the GPIO framework to treat non-zero value as high so 61 * that we don't have to normalize the bits. 62 */ 63static void gf_set_gpios(struct async_state *state, unsigned long ofs) 64{ 65 size_t i = 0; 66 int value; 67 ofs /= state->win_size; 68 do { 69 value = ofs & (1 << i); 70 if (state->gpio_values[i] != value) { 71 gpio_set_value(state->gpio_addrs[i], value); 72 state->gpio_values[i] = value; 73 } 74 } while (++i < state->gpio_count); 75} 76 77/** 78 * gf_read() - read a word at the specified offset 79 * @map: MTD map state 80 * @ofs: desired offset to read 81 */ 82static map_word gf_read(struct map_info *map, unsigned long ofs) 83{ 84 struct async_state *state = gf_map_info_to_state(map); 85 uint16_t word; 86 map_word test; 87 88 gf_set_gpios(state, ofs); 89 90 word = readw(map->virt + (ofs % state->win_size)); 91 test.x[0] = word; 92 return test; 93} 94 95/** 96 * gf_copy_from() - copy a chunk of data from the flash 97 * @map: MTD map state 98 * @to: memory to copy to 99 * @from: flash offset to copy from 100 * @len: how much to copy 101 * 102 * The "from" region may straddle more than one window, so toggle the GPIOs for 103 * each window region before reading its data. 104 */ 105static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) 106{ 107 struct async_state *state = gf_map_info_to_state(map); 108 109 int this_len; 110 111 while (len) { 112 if ((from % state->win_size) + len > state->win_size) 113 this_len = state->win_size - (from % state->win_size); 114 else 115 this_len = len; 116 117 gf_set_gpios(state, from); 118 memcpy_fromio(to, map->virt + (from % state->win_size), 119 this_len); 120 len -= this_len; 121 from += this_len; 122 to += this_len; 123 } 124} 125 126/** 127 * gf_write() - write a word at the specified offset 128 * @map: MTD map state 129 * @ofs: desired offset to write 130 */ 131static void gf_write(struct map_info *map, map_word d1, unsigned long ofs) 132{ 133 struct async_state *state = gf_map_info_to_state(map); 134 uint16_t d; 135 136 gf_set_gpios(state, ofs); 137 138 d = d1.x[0]; 139 writew(d, map->virt + (ofs % state->win_size)); 140} 141 142/** 143 * gf_copy_to() - copy a chunk of data to the flash 144 * @map: MTD map state 145 * @to: flash offset to copy to 146 * @from: memory to copy from 147 * @len: how much to copy 148 * 149 * See gf_copy_from() caveat. 150 */ 151static void gf_copy_to(struct map_info *map, unsigned long to, 152 const void *from, ssize_t len) 153{ 154 struct async_state *state = gf_map_info_to_state(map); 155 156 int this_len; 157 158 while (len) { 159 if ((to % state->win_size) + len > state->win_size) 160 this_len = state->win_size - (to % state->win_size); 161 else 162 this_len = len; 163 164 gf_set_gpios(state, to); 165 memcpy_toio(map->virt + (to % state->win_size), from, len); 166 167 len -= this_len; 168 to += this_len; 169 from += this_len; 170 } 171} 172 173static const char * const part_probe_types[] = { 174 "cmdlinepart", "RedBoot", NULL }; 175 176/** 177 * gpio_flash_probe() - setup a mapping for a GPIO assisted flash 178 * @pdev: platform device 179 * 180 * The platform resource layout expected looks something like: 181 * struct mtd_partition partitions[] = { ... }; 182 * struct physmap_flash_data flash_data = { ... }; 183 * unsigned flash_gpios[] = { GPIO_XX, GPIO_XX, ... }; 184 * struct resource flash_resource[] = { 185 * { 186 * .name = "cfi_probe", 187 * .start = 0x20000000, 188 * .end = 0x201fffff, 189 * .flags = IORESOURCE_MEM, 190 * }, { 191 * .start = (unsigned long)flash_gpios, 192 * .end = ARRAY_SIZE(flash_gpios), 193 * .flags = IORESOURCE_IRQ, 194 * } 195 * }; 196 * struct platform_device flash_device = { 197 * .name = "gpio-addr-flash", 198 * .dev = { .platform_data = &flash_data, }, 199 * .num_resources = ARRAY_SIZE(flash_resource), 200 * .resource = flash_resource, 201 * ... 202 * }; 203 */ 204static int gpio_flash_probe(struct platform_device *pdev) 205{ 206 size_t i, arr_size; 207 struct physmap_flash_data *pdata; 208 struct resource *memory; 209 struct resource *gpios; 210 struct async_state *state; 211 212 pdata = dev_get_platdata(&pdev->dev); 213 memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); 214 gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 215 216 if (!memory || !gpios || !gpios->end) 217 return -EINVAL; 218 219 arr_size = sizeof(int) * gpios->end; 220 state = kzalloc(sizeof(*state) + arr_size, GFP_KERNEL); 221 if (!state) 222 return -ENOMEM; 223 224 /* 225 * We cast start/end to known types in the boards file, so cast 226 * away their pointer types here to the known types (gpios->xxx). 227 */ 228 state->gpio_count = gpios->end; 229 state->gpio_addrs = (void *)(unsigned long)gpios->start; 230 state->gpio_values = (void *)(state + 1); 231 state->win_size = resource_size(memory); 232 memset(state->gpio_values, 0xff, arr_size); 233 234 state->map.name = DRIVER_NAME; 235 state->map.read = gf_read; 236 state->map.copy_from = gf_copy_from; 237 state->map.write = gf_write; 238 state->map.copy_to = gf_copy_to; 239 state->map.bankwidth = pdata->width; 240 state->map.size = state->win_size * (1 << state->gpio_count); 241 state->map.virt = ioremap_nocache(memory->start, state->map.size); 242 state->map.phys = NO_XIP; 243 state->map.map_priv_1 = (unsigned long)state; 244 245 platform_set_drvdata(pdev, state); 246 247 i = 0; 248 do { 249 if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) { 250 pr_devinit(KERN_ERR PFX "failed to request gpio %d\n", 251 state->gpio_addrs[i]); 252 while (i--) 253 gpio_free(state->gpio_addrs[i]); 254 kfree(state); 255 return -EBUSY; 256 } 257 gpio_direction_output(state->gpio_addrs[i], 0); 258 } while (++i < state->gpio_count); 259 260 pr_devinit(KERN_NOTICE PFX "probing %d-bit flash bus\n", 261 state->map.bankwidth * 8); 262 state->mtd = do_map_probe(memory->name, &state->map); 263 if (!state->mtd) { 264 for (i = 0; i < state->gpio_count; ++i) 265 gpio_free(state->gpio_addrs[i]); 266 kfree(state); 267 return -ENXIO; 268 } 269 270 271 mtd_device_parse_register(state->mtd, part_probe_types, NULL, 272 pdata->parts, pdata->nr_parts); 273 274 return 0; 275} 276 277static int gpio_flash_remove(struct platform_device *pdev) 278{ 279 struct async_state *state = platform_get_drvdata(pdev); 280 size_t i = 0; 281 do { 282 gpio_free(state->gpio_addrs[i]); 283 } while (++i < state->gpio_count); 284 mtd_device_unregister(state->mtd); 285 map_destroy(state->mtd); 286 kfree(state); 287 return 0; 288} 289 290static struct platform_driver gpio_flash_driver = { 291 .probe = gpio_flash_probe, 292 .remove = gpio_flash_remove, 293 .driver = { 294 .name = DRIVER_NAME, 295 }, 296}; 297 298module_platform_driver(gpio_flash_driver); 299 300MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); 301MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios"); 302MODULE_LICENSE("GPL"); 303