Commit 593c5692 authored by Russell King's avatar Russell King Committed by Ben Hutchings

ARM: sa1111: fix pcmcia suspend/resume

commit 06dfe5cc upstream.

SA1111 PCMCIA was broken when PCMCIA switched to using dev_pm_ops for
the PCMCIA socket class.  PCMCIA used to handle suspend/resume via the
socket hosting device, which happened at normal device suspend/resume
time.

However, the referenced commit changed this: much of the resume now
happens much earlier, in the noirq resume handler of dev_pm_ops.

However, on SA1111, the PCMCIA device is not accessible as the SA1111
has not been resumed at _noirq time.  It's slightly worse than that,
because the SA1111 has already been put to sleep at _noirq time, so
suspend doesn't work properly.

Fix this by converting the core SA1111 code to use dev_pm_ops as well,
and performing its own suspend/resume at noirq time.

This fixes these errors in the kernel log:

pcmcia_socket pcmcia_socket0: time out after reset
pcmcia_socket pcmcia_socket1: time out after reset

and the resulting lack of PCMCIA cards after a S2RAM cycle.

Fixes: d7646f76 ("pcmcia: use dev_pm_ops for class pcmcia_socket_class")
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 8016df54
...@@ -872,9 +872,9 @@ struct sa1111_save_data { ...@@ -872,9 +872,9 @@ struct sa1111_save_data {
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int sa1111_suspend(struct platform_device *dev, pm_message_t state) static int sa1111_suspend_noirq(struct device *dev)
{ {
struct sa1111 *sachip = platform_get_drvdata(dev); struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save; struct sa1111_save_data *save;
unsigned long flags; unsigned long flags;
unsigned int val; unsigned int val;
...@@ -937,9 +937,9 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state) ...@@ -937,9 +937,9 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
* restored by their respective drivers, and must be called * restored by their respective drivers, and must be called
* via LDM after this function. * via LDM after this function.
*/ */
static int sa1111_resume(struct platform_device *dev) static int sa1111_resume_noirq(struct device *dev)
{ {
struct sa1111 *sachip = platform_get_drvdata(dev); struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save; struct sa1111_save_data *save;
unsigned long flags, id; unsigned long flags, id;
void __iomem *base; void __iomem *base;
...@@ -955,7 +955,7 @@ static int sa1111_resume(struct platform_device *dev) ...@@ -955,7 +955,7 @@ static int sa1111_resume(struct platform_device *dev)
id = sa1111_readl(sachip->base + SA1111_SKID); id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
__sa1111_remove(sachip); __sa1111_remove(sachip);
platform_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
kfree(save); kfree(save);
return 0; return 0;
} }
...@@ -1006,8 +1006,8 @@ static int sa1111_resume(struct platform_device *dev) ...@@ -1006,8 +1006,8 @@ static int sa1111_resume(struct platform_device *dev)
} }
#else #else
#define sa1111_suspend NULL #define sa1111_suspend_noirq NULL
#define sa1111_resume NULL #define sa1111_resume_noirq NULL
#endif #endif
static int sa1111_probe(struct platform_device *pdev) static int sa1111_probe(struct platform_device *pdev)
...@@ -1041,6 +1041,11 @@ static int sa1111_remove(struct platform_device *pdev) ...@@ -1041,6 +1041,11 @@ static int sa1111_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct dev_pm_ops sa1111_pm_ops = {
.suspend_noirq = sa1111_suspend_noirq,
.resume_noirq = sa1111_resume_noirq,
};
/* /*
* Not sure if this should be on the system bus or not yet. * Not sure if this should be on the system bus or not yet.
* We really want some way to register a system device at * We really want some way to register a system device at
...@@ -1053,11 +1058,10 @@ static int sa1111_remove(struct platform_device *pdev) ...@@ -1053,11 +1058,10 @@ static int sa1111_remove(struct platform_device *pdev)
static struct platform_driver sa1111_device_driver = { static struct platform_driver sa1111_device_driver = {
.probe = sa1111_probe, .probe = sa1111_probe,
.remove = sa1111_remove, .remove = sa1111_remove,
.suspend = sa1111_suspend,
.resume = sa1111_resume,
.driver = { .driver = {
.name = "sa1111", .name = "sa1111",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &sa1111_pm_ops,
}, },
}; };
......
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