1 /* 2 * PISMO memory driver - http://www.pismoworld.org/ 3 * 4 * For ARM Realview and Versatile platforms 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License. 9 */ 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/i2c.h> 13 #include <linux/slab.h> 14 #include <linux/platform_device.h> 15 #include <linux/spinlock.h> 16 #include <linux/mutex.h> 17 #include <linux/mtd/physmap.h> 18 #include <linux/mtd/plat-ram.h> 19 #include <linux/mtd/pismo.h> 20 21 #define PISMO_NUM_CS 5 22 23 struct pismo_cs_block { 24 u8 type; 25 u8 width; 26 __le16 access; 27 __le32 size; 28 u32 reserved[2]; 29 char device[32]; 30 } __packed; 31 32 struct pismo_eeprom { 33 struct pismo_cs_block cs[PISMO_NUM_CS]; 34 char board[15]; 35 u8 sum; 36 } __packed; 37 38 struct pismo_mem { 39 phys_addr_t base; 40 u32 size; 41 u16 access; 42 u8 width; 43 u8 type; 44 }; 45 46 struct pismo_data { 47 struct i2c_client *client; 48 void (*vpp)(void *, int); 49 void *vpp_data; 50 struct platform_device *dev[PISMO_NUM_CS]; 51 }; 52 53 /* FIXME: set_vpp could do with a better calling convention */ 54 static struct pismo_data *vpp_pismo; 55 static DEFINE_MUTEX(pismo_mutex); 56 57 static int pismo_setvpp_probe_fix(struct pismo_data *pismo) 58 { 59 mutex_lock(&pismo_mutex); 60 if (vpp_pismo) { 61 mutex_unlock(&pismo_mutex); 62 kfree(pismo); 63 return -EBUSY; 64 } 65 vpp_pismo = pismo; 66 mutex_unlock(&pismo_mutex); 67 return 0; 68 } 69 70 static void pismo_setvpp_remove_fix(struct pismo_data *pismo) 71 { 72 mutex_lock(&pismo_mutex); 73 if (vpp_pismo == pismo) 74 vpp_pismo = NULL; 75 mutex_unlock(&pismo_mutex); 76 } 77 78 static void pismo_set_vpp(struct map_info *map, int on) 79 { 80 struct pismo_data *pismo = vpp_pismo; 81 82 pismo->vpp(pismo->vpp_data, on); 83 } 84 /* end of hack */ 85 86 87 static unsigned int __devinit pismo_width_to_bytes(unsigned int width) 88 { 89 width &= 15; 90 if (width > 2) 91 return 0; 92 return 1 << width; 93 } 94 95 static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf, 96 u8 addr, size_t size) 97 { 98 int ret; 99 struct i2c_msg msg[] = { 100 { 101 .addr = client->addr, 102 .len = sizeof(addr), 103 .buf = &addr, 104 }, { 105 .addr = client->addr, 106 .flags = I2C_M_RD, 107 .len = size, 108 .buf = buf, 109 }, 110 }; 111 112 ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 113 114 return ret == ARRAY_SIZE(msg) ? size : -EIO; 115 } 116 117 static int __devinit pismo_add_device(struct pismo_data *pismo, int i, 118 struct pismo_mem *region, const char *name, void *pdata, size_t psize) 119 { 120 struct platform_device *dev; 121 struct resource res = { }; 122 phys_addr_t base = region->base; 123 int ret; 124 125 if (base == ~0) 126 return -ENXIO; 127 128 res.start = base; 129 res.end = base + region->size - 1; 130 res.flags = IORESOURCE_MEM; 131 132 dev = platform_device_alloc(name, i); 133 if (!dev) 134 return -ENOMEM; 135 dev->dev.parent = &pismo->client->dev; 136 137 do { 138 ret = platform_device_add_resources(dev, &res, 1); 139 if (ret) 140 break; 141 142 ret = platform_device_add_data(dev, pdata, psize); 143 if (ret) 144 break; 145 146 ret = platform_device_add(dev); 147 if (ret) 148 break; 149 150 pismo->dev[i] = dev; 151 return 0; 152 } while (0); 153 154 platform_device_put(dev); 155 return ret; 156 } 157 158 static int __devinit pismo_add_nor(struct pismo_data *pismo, int i, 159 struct pismo_mem *region) 160 { 161 struct physmap_flash_data data = { 162 .width = region->width, 163 }; 164 165 if (pismo->vpp) 166 data.set_vpp = pismo_set_vpp; 167 168 return pismo_add_device(pismo, i, region, "physmap-flash", 169 &data, sizeof(data)); 170 } 171 172 static int __devinit pismo_add_sram(struct pismo_data *pismo, int i, 173 struct pismo_mem *region) 174 { 175 struct platdata_mtd_ram data = { 176 .bankwidth = region->width, 177 }; 178 179 return pismo_add_device(pismo, i, region, "mtd-ram", 180 &data, sizeof(data)); 181 } 182 183 static void __devinit pismo_add_one(struct pismo_data *pismo, int i, 184 const struct pismo_cs_block *cs, phys_addr_t base) 185 { 186 struct device *dev = &pismo->client->dev; 187 struct pismo_mem region; 188 189 region.base = base; 190 region.type = cs->type; 191 region.width = pismo_width_to_bytes(cs->width); 192 region.access = le16_to_cpu(cs->access); 193 region.size = le32_to_cpu(cs->size); 194 195 if (region.width == 0) { 196 dev_err(dev, "cs%u: bad width: %02x, ignoring\n", i, cs->width); 197 return; 198 } 199 200 /* 201 * FIXME: may need to the platforms memory controller here, but at 202 * the moment we assume that it has already been correctly setup. 203 * The memory controller can also tell us the base address as well. 204 */ 205 206 dev_info(dev, "cs%u: %.32s: type %02x access %u00ps size %uK\n", 207 i, cs->device, region.type, region.access, region.size / 1024); 208 209 switch (region.type) { 210 case 0: 211 break; 212 case 1: 213 /* static DOC */ 214 break; 215 case 2: 216 /* static NOR */ 217 pismo_add_nor(pismo, i, ®ion); 218 break; 219 case 3: 220 /* static RAM */ 221 pismo_add_sram(pismo, i, ®ion); 222 break; 223 } 224 } 225 226 static int __devexit pismo_remove(struct i2c_client *client) 227 { 228 struct pismo_data *pismo = i2c_get_clientdata(client); 229 int i; 230 231 for (i = 0; i < ARRAY_SIZE(pismo->dev); i++) 232 platform_device_unregister(pismo->dev[i]); 233 234 /* FIXME: set_vpp needs saner arguments */ 235 pismo_setvpp_remove_fix(pismo); 236 237 kfree(pismo); 238 239 return 0; 240 } 241 242 static int __devinit pismo_probe(struct i2c_client *client, 243 const struct i2c_device_id *id) 244 { 245 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 246 struct pismo_pdata *pdata = client->dev.platform_data; 247 struct pismo_eeprom eeprom; 248 struct pismo_data *pismo; 249 int ret, i; 250 251 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { 252 dev_err(&client->dev, "functionality mismatch\n"); 253 return -EIO; 254 } 255 256 pismo = kzalloc(sizeof(*pismo), GFP_KERNEL); 257 if (!pismo) 258 return -ENOMEM; 259 260 /* FIXME: set_vpp needs saner arguments */ 261 ret = pismo_setvpp_probe_fix(pismo); 262 if (ret) 263 return ret; 264 265 pismo->client = client; 266 if (pdata) { 267 pismo->vpp = pdata->set_vpp; 268 pismo->vpp_data = pdata->vpp_data; 269 } 270 i2c_set_clientdata(client, pismo); 271 272 ret = pismo_eeprom_read(client, &eeprom, 0, sizeof(eeprom)); 273 if (ret < 0) { 274 dev_err(&client->dev, "error reading EEPROM: %d\n", ret); 275 goto exit_free; 276 } 277 278 dev_info(&client->dev, "%.15s board found\n", eeprom.board); 279 280 for (i = 0; i < ARRAY_SIZE(eeprom.cs); i++) 281 if (eeprom.cs[i].type != 0xff) 282 pismo_add_one(pismo, i, &eeprom.cs[i], 283 pdata->cs_addrs[i]); 284 285 return 0; 286 287 exit_free: 288 kfree(pismo); 289 return ret; 290 } 291 292 static const struct i2c_device_id pismo_id[] = { 293 { "pismo" }, 294 { }, 295 }; 296 MODULE_DEVICE_TABLE(i2c, pismo_id); 297 298 static struct i2c_driver pismo_driver = { 299 .driver = { 300 .name = "pismo", 301 .owner = THIS_MODULE, 302 }, 303 .probe = pismo_probe, 304 .remove = __devexit_p(pismo_remove), 305 .id_table = pismo_id, 306 }; 307 308 static int __init pismo_init(void) 309 { 310 BUILD_BUG_ON(sizeof(struct pismo_cs_block) != 48); 311 BUILD_BUG_ON(sizeof(struct pismo_eeprom) != 256); 312 313 return i2c_add_driver(&pismo_driver); 314 } 315 module_init(pismo_init); 316 317 static void __exit pismo_exit(void) 318 { 319 i2c_del_driver(&pismo_driver); 320 } 321 module_exit(pismo_exit); 322 323 MODULE_AUTHOR("Russell King <linux@arm.linux.org.uk>"); 324 MODULE_DESCRIPTION("PISMO memory driver"); 325 MODULE_LICENSE("GPL"); 326