0001
0002
0003
0004
0005
0006
0007 #include <linux/init.h>
0008 #include <linux/module.h>
0009 #include <linux/i2c.h>
0010 #include <linux/slab.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/spinlock.h>
0013 #include <linux/mutex.h>
0014 #include <linux/mtd/physmap.h>
0015 #include <linux/mtd/plat-ram.h>
0016 #include <linux/mtd/pismo.h>
0017
0018 #define PISMO_NUM_CS 5
0019
0020 struct pismo_cs_block {
0021 u8 type;
0022 u8 width;
0023 __le16 access;
0024 __le32 size;
0025 u32 reserved[2];
0026 char device[32];
0027 } __packed;
0028
0029 struct pismo_eeprom {
0030 struct pismo_cs_block cs[PISMO_NUM_CS];
0031 char board[15];
0032 u8 sum;
0033 } __packed;
0034
0035 struct pismo_mem {
0036 phys_addr_t base;
0037 u32 size;
0038 u16 access;
0039 u8 width;
0040 u8 type;
0041 };
0042
0043 struct pismo_data {
0044 struct i2c_client *client;
0045 void (*vpp)(void *, int);
0046 void *vpp_data;
0047 struct platform_device *dev[PISMO_NUM_CS];
0048 };
0049
0050 static void pismo_set_vpp(struct platform_device *pdev, int on)
0051 {
0052 struct i2c_client *client = to_i2c_client(pdev->dev.parent);
0053 struct pismo_data *pismo = i2c_get_clientdata(client);
0054
0055 pismo->vpp(pismo->vpp_data, on);
0056 }
0057
0058 static unsigned int pismo_width_to_bytes(unsigned int width)
0059 {
0060 width &= 15;
0061 if (width > 2)
0062 return 0;
0063 return 1 << width;
0064 }
0065
0066 static int pismo_eeprom_read(struct i2c_client *client, void *buf, u8 addr,
0067 size_t size)
0068 {
0069 int ret;
0070 struct i2c_msg msg[] = {
0071 {
0072 .addr = client->addr,
0073 .len = sizeof(addr),
0074 .buf = &addr,
0075 }, {
0076 .addr = client->addr,
0077 .flags = I2C_M_RD,
0078 .len = size,
0079 .buf = buf,
0080 },
0081 };
0082
0083 ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
0084
0085 return ret == ARRAY_SIZE(msg) ? size : -EIO;
0086 }
0087
0088 static int pismo_add_device(struct pismo_data *pismo, int i,
0089 struct pismo_mem *region, const char *name,
0090 void *pdata, size_t psize)
0091 {
0092 struct platform_device *dev;
0093 struct resource res = { };
0094 phys_addr_t base = region->base;
0095 int ret;
0096
0097 if (base == ~0)
0098 return -ENXIO;
0099
0100 res.start = base;
0101 res.end = base + region->size - 1;
0102 res.flags = IORESOURCE_MEM;
0103
0104 dev = platform_device_alloc(name, i);
0105 if (!dev)
0106 return -ENOMEM;
0107 dev->dev.parent = &pismo->client->dev;
0108
0109 do {
0110 ret = platform_device_add_resources(dev, &res, 1);
0111 if (ret)
0112 break;
0113
0114 ret = platform_device_add_data(dev, pdata, psize);
0115 if (ret)
0116 break;
0117
0118 ret = platform_device_add(dev);
0119 if (ret)
0120 break;
0121
0122 pismo->dev[i] = dev;
0123 return 0;
0124 } while (0);
0125
0126 platform_device_put(dev);
0127 return ret;
0128 }
0129
0130 static int pismo_add_nor(struct pismo_data *pismo, int i,
0131 struct pismo_mem *region)
0132 {
0133 struct physmap_flash_data data = {
0134 .width = region->width,
0135 };
0136
0137 if (pismo->vpp)
0138 data.set_vpp = pismo_set_vpp;
0139
0140 return pismo_add_device(pismo, i, region, "physmap-flash",
0141 &data, sizeof(data));
0142 }
0143
0144 static int pismo_add_sram(struct pismo_data *pismo, int i,
0145 struct pismo_mem *region)
0146 {
0147 struct platdata_mtd_ram data = {
0148 .bankwidth = region->width,
0149 };
0150
0151 return pismo_add_device(pismo, i, region, "mtd-ram",
0152 &data, sizeof(data));
0153 }
0154
0155 static void pismo_add_one(struct pismo_data *pismo, int i,
0156 const struct pismo_cs_block *cs, phys_addr_t base)
0157 {
0158 struct device *dev = &pismo->client->dev;
0159 struct pismo_mem region;
0160
0161 region.base = base;
0162 region.type = cs->type;
0163 region.width = pismo_width_to_bytes(cs->width);
0164 region.access = le16_to_cpu(cs->access);
0165 region.size = le32_to_cpu(cs->size);
0166
0167 if (region.width == 0) {
0168 dev_err(dev, "cs%u: bad width: %02x, ignoring\n", i, cs->width);
0169 return;
0170 }
0171
0172
0173
0174
0175
0176
0177
0178 dev_info(dev, "cs%u: %.32s: type %02x access %u00ps size %uK\n",
0179 i, cs->device, region.type, region.access, region.size / 1024);
0180
0181 switch (region.type) {
0182 case 0:
0183 break;
0184 case 1:
0185
0186 break;
0187 case 2:
0188
0189 pismo_add_nor(pismo, i, ®ion);
0190 break;
0191 case 3:
0192
0193 pismo_add_sram(pismo, i, ®ion);
0194 break;
0195 }
0196 }
0197
0198 static int pismo_remove(struct i2c_client *client)
0199 {
0200 struct pismo_data *pismo = i2c_get_clientdata(client);
0201 int i;
0202
0203 for (i = 0; i < ARRAY_SIZE(pismo->dev); i++)
0204 platform_device_unregister(pismo->dev[i]);
0205
0206 kfree(pismo);
0207
0208 return 0;
0209 }
0210
0211 static int pismo_probe(struct i2c_client *client,
0212 const struct i2c_device_id *id)
0213 {
0214 struct pismo_pdata *pdata = client->dev.platform_data;
0215 struct pismo_eeprom eeprom;
0216 struct pismo_data *pismo;
0217 int ret, i;
0218
0219 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
0220 dev_err(&client->dev, "functionality mismatch\n");
0221 return -EIO;
0222 }
0223
0224 pismo = kzalloc(sizeof(*pismo), GFP_KERNEL);
0225 if (!pismo)
0226 return -ENOMEM;
0227
0228 pismo->client = client;
0229 if (pdata) {
0230 pismo->vpp = pdata->set_vpp;
0231 pismo->vpp_data = pdata->vpp_data;
0232 }
0233 i2c_set_clientdata(client, pismo);
0234
0235 ret = pismo_eeprom_read(client, &eeprom, 0, sizeof(eeprom));
0236 if (ret < 0) {
0237 dev_err(&client->dev, "error reading EEPROM: %d\n", ret);
0238 goto exit_free;
0239 }
0240
0241 dev_info(&client->dev, "%.15s board found\n", eeprom.board);
0242
0243 for (i = 0; i < ARRAY_SIZE(eeprom.cs); i++)
0244 if (eeprom.cs[i].type != 0xff)
0245 pismo_add_one(pismo, i, &eeprom.cs[i],
0246 pdata->cs_addrs[i]);
0247
0248 return 0;
0249
0250 exit_free:
0251 kfree(pismo);
0252 return ret;
0253 }
0254
0255 static const struct i2c_device_id pismo_id[] = {
0256 { "pismo" },
0257 { },
0258 };
0259 MODULE_DEVICE_TABLE(i2c, pismo_id);
0260
0261 static struct i2c_driver pismo_driver = {
0262 .driver = {
0263 .name = "pismo",
0264 },
0265 .probe = pismo_probe,
0266 .remove = pismo_remove,
0267 .id_table = pismo_id,
0268 };
0269
0270 static int __init pismo_init(void)
0271 {
0272 BUILD_BUG_ON(sizeof(struct pismo_cs_block) != 48);
0273 BUILD_BUG_ON(sizeof(struct pismo_eeprom) != 256);
0274
0275 return i2c_add_driver(&pismo_driver);
0276 }
0277 module_init(pismo_init);
0278
0279 static void __exit pismo_exit(void)
0280 {
0281 i2c_del_driver(&pismo_driver);
0282 }
0283 module_exit(pismo_exit);
0284
0285 MODULE_AUTHOR("Russell King <linux@arm.linux.org.uk>");
0286 MODULE_DESCRIPTION("PISMO memory driver");
0287 MODULE_LICENSE("GPL");