diff options
Diffstat (limited to 'drivers/pcmcia/pxa2xx_base.c')
-rw-r--r-- | drivers/pcmcia/pxa2xx_base.c | 94 |
1 files changed, 62 insertions, 32 deletions
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 0e35acb1366b..84dde7768ad5 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c | |||
@@ -228,9 +228,43 @@ static const char *skt_names[] = { | |||
228 | #define SKT_DEV_INFO_SIZE(n) \ | 228 | #define SKT_DEV_INFO_SIZE(n) \ |
229 | (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) | 229 | (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) |
230 | 230 | ||
231 | int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt) | ||
232 | { | ||
233 | skt->res_skt.start = _PCMCIA(skt->nr); | ||
234 | skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; | ||
235 | skt->res_skt.name = skt_names[skt->nr]; | ||
236 | skt->res_skt.flags = IORESOURCE_MEM; | ||
237 | |||
238 | skt->res_io.start = _PCMCIAIO(skt->nr); | ||
239 | skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; | ||
240 | skt->res_io.name = "io"; | ||
241 | skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
242 | |||
243 | skt->res_mem.start = _PCMCIAMem(skt->nr); | ||
244 | skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; | ||
245 | skt->res_mem.name = "memory"; | ||
246 | skt->res_mem.flags = IORESOURCE_MEM; | ||
247 | |||
248 | skt->res_attr.start = _PCMCIAAttr(skt->nr); | ||
249 | skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; | ||
250 | skt->res_attr.name = "attribute"; | ||
251 | skt->res_attr.flags = IORESOURCE_MEM; | ||
252 | |||
253 | return soc_pcmcia_add_one(skt); | ||
254 | } | ||
255 | |||
256 | void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) | ||
257 | { | ||
258 | /* Provide our PXA2xx specific timing routines. */ | ||
259 | ops->set_timing = pxa2xx_pcmcia_set_timing; | ||
260 | #ifdef CONFIG_CPU_FREQ | ||
261 | ops->frequency_change = pxa2xx_pcmcia_frequency_change; | ||
262 | #endif | ||
263 | } | ||
264 | |||
231 | int __pxa2xx_drv_pcmcia_probe(struct device *dev) | 265 | int __pxa2xx_drv_pcmcia_probe(struct device *dev) |
232 | { | 266 | { |
233 | int i, ret; | 267 | int i, ret = 0; |
234 | struct pcmcia_low_level *ops; | 268 | struct pcmcia_low_level *ops; |
235 | struct skt_dev_info *sinfo; | 269 | struct skt_dev_info *sinfo; |
236 | struct soc_pcmcia_socket *skt; | 270 | struct soc_pcmcia_socket *skt; |
@@ -240,6 +274,8 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev) | |||
240 | 274 | ||
241 | ops = (struct pcmcia_low_level *)dev->platform_data; | 275 | ops = (struct pcmcia_low_level *)dev->platform_data; |
242 | 276 | ||
277 | pxa2xx_drv_pcmcia_ops(ops); | ||
278 | |||
243 | sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL); | 279 | sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL); |
244 | if (!sinfo) | 280 | if (!sinfo) |
245 | return -ENOMEM; | 281 | return -ENOMEM; |
@@ -250,40 +286,25 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev) | |||
250 | for (i = 0; i < ops->nr; i++) { | 286 | for (i = 0; i < ops->nr; i++) { |
251 | skt = &sinfo->skt[i]; | 287 | skt = &sinfo->skt[i]; |
252 | 288 | ||
253 | skt->nr = ops->first + i; | 289 | skt->nr = ops->first + i; |
254 | skt->irq = NO_IRQ; | 290 | skt->ops = ops; |
255 | 291 | skt->socket.owner = ops->owner; | |
256 | skt->res_skt.start = _PCMCIA(skt->nr); | 292 | skt->socket.dev.parent = dev; |
257 | skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; | 293 | skt->socket.pci_irq = NO_IRQ; |
258 | skt->res_skt.name = skt_names[skt->nr]; | ||
259 | skt->res_skt.flags = IORESOURCE_MEM; | ||
260 | |||
261 | skt->res_io.start = _PCMCIAIO(skt->nr); | ||
262 | skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; | ||
263 | skt->res_io.name = "io"; | ||
264 | skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
265 | 294 | ||
266 | skt->res_mem.start = _PCMCIAMem(skt->nr); | 295 | ret = pxa2xx_drv_pcmcia_add_one(skt); |
267 | skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; | 296 | if (ret) |
268 | skt->res_mem.name = "memory"; | 297 | break; |
269 | skt->res_mem.flags = IORESOURCE_MEM; | ||
270 | |||
271 | skt->res_attr.start = _PCMCIAAttr(skt->nr); | ||
272 | skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; | ||
273 | skt->res_attr.name = "attribute"; | ||
274 | skt->res_attr.flags = IORESOURCE_MEM; | ||
275 | } | 298 | } |
276 | 299 | ||
277 | /* Provide our PXA2xx specific timing routines. */ | 300 | if (ret) { |
278 | ops->set_timing = pxa2xx_pcmcia_set_timing; | 301 | while (--i >= 0) |
279 | #ifdef CONFIG_CPU_FREQ | 302 | soc_pcmcia_remove_one(&sinfo->skt[i]); |
280 | ops->frequency_change = pxa2xx_pcmcia_frequency_change; | 303 | kfree(sinfo); |
281 | #endif | 304 | } else { |
282 | |||
283 | ret = soc_common_drv_pcmcia_probe(dev, ops, sinfo); | ||
284 | |||
285 | if (!ret) | ||
286 | pxa2xx_configure_sockets(dev); | 305 | pxa2xx_configure_sockets(dev); |
306 | dev_set_drvdata(dev, sinfo); | ||
307 | } | ||
287 | 308 | ||
288 | return ret; | 309 | return ret; |
289 | } | 310 | } |
@@ -297,7 +318,16 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev) | |||
297 | 318 | ||
298 | static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev) | 319 | static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev) |
299 | { | 320 | { |
300 | return soc_common_drv_pcmcia_remove(&dev->dev); | 321 | struct skt_dev_info *sinfo = platform_get_drvdata(dev); |
322 | int i; | ||
323 | |||
324 | platform_set_drvdata(dev, NULL); | ||
325 | |||
326 | for (i = 0; i < sinfo->nskt; i++) | ||
327 | soc_pcmcia_remove_one(&sinfo->skt[i]); | ||
328 | |||
329 | kfree(sinfo); | ||
330 | return 0; | ||
301 | } | 331 | } |
302 | 332 | ||
303 | static int pxa2xx_drv_pcmcia_suspend(struct device *dev) | 333 | static int pxa2xx_drv_pcmcia_suspend(struct device *dev) |