Commit 63159f81 authored by Russell King's avatar Russell King

[PCMCIA] Update SA11xx PCMCIA support for recent changes.

Re-enable the suspend and resume methods for SA11xx PCMCIA devices,
and update the initialisation/cleanup code for Dominik's recent
changes.
parent 9014144e
...@@ -106,8 +106,8 @@ static struct device_driver sa11x0_pcmcia_driver = { ...@@ -106,8 +106,8 @@ static struct device_driver sa11x0_pcmcia_driver = {
.remove = sa11xx_drv_pcmcia_remove, .remove = sa11xx_drv_pcmcia_remove,
.name = "sa11x0-pcmcia", .name = "sa11x0-pcmcia",
.bus = &platform_bus_type, .bus = &platform_bus_type,
/* .suspend = pcmcia_socket_dev_suspend,*/ .suspend = pcmcia_socket_dev_suspend,
/* .resume = pcmcia_socket_dev_resume,*/ .resume = pcmcia_socket_dev_resume,
}; };
/* sa11x0_pcmcia_init() /* sa11x0_pcmcia_init()
......
...@@ -178,8 +178,8 @@ static struct sa1111_driver pcmcia_driver = { ...@@ -178,8 +178,8 @@ static struct sa1111_driver pcmcia_driver = {
.bus = &sa1111_bus_type, .bus = &sa1111_bus_type,
.probe = pcmcia_probe, .probe = pcmcia_probe,
.remove = __devexit_p(pcmcia_remove), .remove = __devexit_p(pcmcia_remove),
/* .suspend = pcmcia_socket_dev_suspend,*/ .suspend = pcmcia_socket_dev_suspend,
/* .resume = pcmcia_socket_dev_resume,*/ .resume = pcmcia_socket_dev_resume,
}, },
.devid = SA1111_DEVID_PCMCIA, .devid = SA1111_DEVID_PCMCIA,
}; };
......
...@@ -800,9 +800,13 @@ static const char *skt_names[] = { ...@@ -800,9 +800,13 @@ static const char *skt_names[] = {
"PCMCIA socket 1", "PCMCIA socket 1",
}; };
struct skt_dev_info {
int nskt;
};
int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
{ {
struct pcmcia_socket_class_data *cls; struct skt_dev_info *sinfo;
unsigned int cpu_clock; unsigned int cpu_clock;
int ret, i; int ret, i;
...@@ -813,19 +817,14 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -813,19 +817,14 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
if (!ops->socket_get_timing) if (!ops->socket_get_timing)
ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing; ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
cls = kmalloc(sizeof(struct pcmcia_socket_class_data), GFP_KERNEL); sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
if (!cls) { if (!sinfo) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
memset(cls, 0, sizeof(struct pcmcia_socket_class_data)); memset(sinfo, 0, sizeof(struct skt_dev_info));
cls->ops = &sa11xx_pcmcia_operations; sinfo->nskt = nr;
cls->nsock = nr;
cls->class_dev.class = &pcmcia_socket_class;
cls->class_dev.dev = dev;
strlcpy(cls->class_dev.class_id, dev->bus_id, BUS_ID_SIZE);
class_set_devdata(&cls->class_dev, cls);
cpu_clock = cpufreq_get(0); cpu_clock = cpufreq_get(0);
...@@ -836,6 +835,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -836,6 +835,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
memset(skt, 0, sizeof(*skt)); memset(skt, 0, sizeof(*skt));
skt->socket.ss_entry = &sa11xx_pcmcia_operations;
skt->socket.dev.dev = dev;
INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt); INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt);
init_timer(&skt->poll_timer); init_timer(&skt->poll_timer);
...@@ -902,18 +904,26 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -902,18 +904,26 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
goto out_err_6; goto out_err_6;
skt->status = sa1100_pcmcia_skt_state(skt); skt->status = sa1100_pcmcia_skt_state(skt);
ret = pcmcia_register_socket(&skt->socket);
if (ret)
goto out_err_7;
WARN_ON(skt->socket.sock != i);
add_timer(&skt->poll_timer); add_timer(&skt->poll_timer);
} }
dev_set_drvdata(dev, cls); dev_set_drvdata(dev, sinfo);
class_device_register(&cls->class_dev);
return 0; return 0;
do { do {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
del_timer_sync(&skt->poll_timer); del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket);
out_err_7:
flush_scheduled_work(); flush_scheduled_work();
ops->hw_shutdown(skt); ops->hw_shutdown(skt);
...@@ -931,7 +941,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -931,7 +941,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
i--; i--;
} while (i > 0); } while (i > 0);
kfree(cls); kfree(sinfo);
out: out:
return ret; return ret;
...@@ -940,20 +950,22 @@ EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); ...@@ -940,20 +950,22 @@ EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
int sa11xx_drv_pcmcia_remove(struct device *dev) int sa11xx_drv_pcmcia_remove(struct device *dev)
{ {
struct pcmcia_socket_class_data *cls = dev_get_drvdata(dev); struct skt_dev_info *sinfo = dev_get_drvdata(dev);
int i; int i;
class_device_unregister(&cls->class_dev);
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
for (i = 0; i < cls->nsock; i++) { for (i = 0; i < sinfo->nskt; i++) {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(cls->sock_offset + i); struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
skt->ops->hw_shutdown(skt);
del_timer_sync(&skt->poll_timer); del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket);
flush_scheduled_work(); flush_scheduled_work();
skt->ops->hw_shutdown(skt);
sa1100_pcmcia_config_skt(skt, &dead_socket); sa1100_pcmcia_config_skt(skt, &dead_socket);
iounmap(skt->virt_io); iounmap(skt->virt_io);
...@@ -964,7 +976,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev) ...@@ -964,7 +976,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev)
release_resource(&skt->res_skt); release_resource(&skt->res_skt);
} }
kfree(cls); kfree(sinfo);
return 0; return 0;
} }
......
...@@ -44,6 +44,8 @@ struct pcmcia_state { ...@@ -44,6 +44,8 @@ struct pcmcia_state {
* use when responding to a Card Services query of some kind. * use when responding to a Card Services query of some kind.
*/ */
struct sa1100_pcmcia_socket { struct sa1100_pcmcia_socket {
struct pcmcia_socket socket;
/* /*
* Info from low level handler * Info from low level handler
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment