Commit f2216ade authored by Russell King's avatar Russell King

[ARM] Update SA1111 suspend/resume model.

The device_driver suspend/resume methods are no longer used.  Instead,
the bus_type contains the suspend/resume methods.  Fix the SA1111 bus
support for this change.

We place the probe/remove/suspend/resume methods inside struct
sa1111_driver and call them from the SA1111 bus driver (ie, how
Pat wants this stuff done.)

We leave the parent bus device suspend/resume methods in the device
driver until power management for platform devices works again.
However, we adjust these methods so they run only once, like the
other PM methods.
parent 4e666cea
......@@ -790,10 +790,13 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level)
struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save;
unsigned long flags;
unsigned int val;
char *base;
if (!dev->saved_state && level == SUSPEND_NOTIFY)
dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (level != SUSPEND_DISABLE)
return 0;
dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!dev->saved_state)
return -ENOMEM;
......@@ -804,36 +807,31 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level)
/*
* Save state.
*/
if (level == SUSPEND_SAVE_STATE) {
base = sachip->base;
save->skcr = sa1111_readl(base + SA1111_SKCR);
save->skpcr = sa1111_readl(base + SA1111_SKPCR);
save->skcdr = sa1111_readl(base + SA1111_SKCDR);
save->skaud = sa1111_readl(base + SA1111_SKAUD);
save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0);
save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
save->intpol0 = sa1111_readl(base + SA1111_INTPOL0);
save->intpol1 = sa1111_readl(base + SA1111_INTPOL1);
save->inten0 = sa1111_readl(base + SA1111_INTEN0);
save->inten1 = sa1111_readl(base + SA1111_INTEN1);
save->wakepol0 = sa1111_readl(base + SA1111_WAKEPOL0);
save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0);
save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1);
}
base = sachip->base;
save->skcr = sa1111_readl(base + SA1111_SKCR);
save->skpcr = sa1111_readl(base + SA1111_SKPCR);
save->skcdr = sa1111_readl(base + SA1111_SKCDR);
save->skaud = sa1111_readl(base + SA1111_SKAUD);
save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0);
save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
save->intpol0 = sa1111_readl(base + SA1111_INTPOL0);
save->intpol1 = sa1111_readl(base + SA1111_INTPOL1);
save->inten0 = sa1111_readl(base + SA1111_INTEN0);
save->inten1 = sa1111_readl(base + SA1111_INTEN1);
save->wakepol0 = sa1111_readl(base + SA1111_WAKEPOL0);
save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0);
save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1);
/*
* Disable.
*/
if (level == SUSPEND_POWER_DOWN && state == 4) {
unsigned int val = sa1111_readl(sachip->base + SA1111_SKCR);
sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
sa1111_writel(0, sachip->base + SA1111_SKPWM0);
sa1111_writel(0, sachip->base + SA1111_SKPWM1);
}
val = sa1111_readl(sachip->base + SA1111_SKCR);
sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
sa1111_writel(0, sachip->base + SA1111_SKPWM0);
sa1111_writel(0, sachip->base + SA1111_SKPWM1);
spin_unlock_irqrestore(&sachip->lock, flags);
......@@ -857,6 +855,9 @@ static int sa1111_resume(struct device *dev, u32 level)
unsigned long flags, id;
char *base;
if (level != RESUME_ENABLE)
return 0;
save = (struct sa1111_save_data *)dev->saved_state;
if (!save)
return 0;
......@@ -878,39 +879,32 @@ static int sa1111_resume(struct device *dev, u32 level)
/*
* First of all, wake up the chip.
*/
if (level == RESUME_POWER_ON) {
sa1111_wake(sachip);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
}
if (level == RESUME_RESTORE_STATE) {
base = sachip->base;
sa1111_writel(save->skcr, base + SA1111_SKCR);
sa1111_writel(save->skpcr, base + SA1111_SKPCR);
sa1111_writel(save->skcdr, base + SA1111_SKCDR);
sa1111_writel(save->skaud, base + SA1111_SKAUD);
sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
sa1111_writel(save->inten0, base + SA1111_INTEN0);
sa1111_writel(save->inten1, base + SA1111_INTEN1);
sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
}
sa1111_wake(sachip);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
base = sachip->base;
sa1111_writel(save->skcr, base + SA1111_SKCR);
sa1111_writel(save->skpcr, base + SA1111_SKPCR);
sa1111_writel(save->skcdr, base + SA1111_SKCDR);
sa1111_writel(save->skaud, base + SA1111_SKAUD);
sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
sa1111_writel(save->inten0, base + SA1111_INTEN0);
sa1111_writel(save->inten1, base + SA1111_INTEN1);
sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
spin_unlock_irqrestore(&sachip->lock, flags);
if (level == RESUME_ENABLE) {
dev->saved_state = NULL;
kfree(save);
}
dev->saved_state = NULL;
kfree(save);
return 0;
}
......@@ -1135,9 +1129,55 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv)
return dev->devid == drv->devid;
}
static int sa1111_bus_suspend(struct device *dev, u32 state)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct sa1111_driver *drv = SA1111_DRV(dev->driver);
int ret = 0;
if (drv && drv->suspend)
ret = drv->suspend(sadev, state);
return ret;
}
static int sa1111_bus_resume(struct device *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct sa1111_driver *drv = SA1111_DRV(dev->driver);
int ret = 0;
if (drv && drv->resume)
ret = drv->resume(sadev);
return ret;
}
static int sa1111_bus_probe(struct device *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct sa1111_driver *drv = SA1111_DRV(dev->driver);
int ret = -ENODEV;
if (drv->probe)
ret = drv->probe(sadev);
return ret;
}
static int sa1111_bus_remove(struct device *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct sa1111_driver *drv = SA1111_DRV(dev->driver);
int ret = 0;
if (drv->remove)
ret = drv->remove(sadev);
return ret;
}
struct bus_type sa1111_bus_type = {
.name = "RAB",
.match = sa1111_match,
.name = "sa1111-rab",
.match = sa1111_match,
.suspend = sa1111_bus_suspend,
.resume = sa1111_bus_resume,
};
static int sa1111_rab_bus_init(void)
......@@ -1147,6 +1187,19 @@ static int sa1111_rab_bus_init(void)
postcore_initcall(sa1111_rab_bus_init);
int sa1111_driver_register(struct sa1111_driver *driver)
{
driver->drv.probe = sa1111_bus_probe;
driver->drv.remove = sa1111_bus_remove;
driver->drv.bus = &sa1111_bus_type;
return driver_register(&driver->drv);
}
void sa1111_driver_unregister(struct sa1111_driver *driver)
{
driver_unregister(&driver->drv);
}
EXPORT_SYMBOL(sa1111_check_dma_bug);
EXPORT_SYMBOL(sa1111_select_audio_mode);
EXPORT_SYMBOL(sa1111_set_audio_rate);
......@@ -1155,3 +1208,5 @@ EXPORT_SYMBOL(sa1111_enable_device);
EXPORT_SYMBOL(sa1111_disable_device);
EXPORT_SYMBOL(sa1111_pll_clock);
EXPORT_SYMBOL(sa1111_bus_type);
EXPORT_SYMBOL(sa1111_driver_register);
EXPORT_SYMBOL(sa1111_driver_unregister);
......@@ -62,9 +62,9 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
serio_interrupt(&ps2if->io, scancode, flag, regs);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
handled = IRQ_HANDLED;
handled = IRQ_HANDLED;
}
return handled;
......@@ -232,9 +232,8 @@ static int __init ps2_test(struct ps2if *ps2if)
/*
* Add one device to this driver.
*/
static int ps2_probe(struct device *dev)
static int ps2_probe(struct sa1111_dev *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct ps2if *ps2if;
int ret;
......@@ -249,20 +248,20 @@ static int ps2_probe(struct device *dev)
ps2if->io.write = ps2_write;
ps2if->io.open = ps2_open;
ps2if->io.close = ps2_close;
ps2if->io.name = dev->name;
ps2if->io.phys = dev->bus_id;
ps2if->io.name = dev->dev.bus_id;
ps2if->io.phys = dev->dev.bus_id;
ps2if->io.driver = ps2if;
ps2if->dev = sadev;
dev->driver_data = ps2if;
ps2if->dev = dev;
sa1111_set_drvdata(dev, ps2if);
spin_lock_init(&ps2if->lock);
/*
* Request the physical region for this PS2 port.
*/
if (!request_mem_region(sadev->res.start,
sadev->res.end - sadev->res.start + 1,
SA1111_DRIVER_NAME(sadev))) {
if (!request_mem_region(dev->res.start,
dev->res.end - dev->res.start + 1,
SA1111_DRIVER_NAME(dev))) {
ret = -EBUSY;
goto free;
}
......@@ -270,7 +269,7 @@ static int ps2_probe(struct device *dev)
/*
* Our parent device has already mapped the region.
*/
ps2if->base = (unsigned long)sadev->mapbase;
ps2if->base = (unsigned long)dev->mapbase;
sa1111_enable_device(ps2if->dev);
......@@ -301,10 +300,10 @@ static int ps2_probe(struct device *dev)
out:
sa1111_disable_device(ps2if->dev);
release_mem_region(sadev->res.start,
sadev->res.end - sadev->res.start + 1);
release_mem_region(dev->res.start,
dev->res.end - dev->res.start + 1);
free:
dev->driver_data = NULL;
sa1111_set_drvdata(dev, NULL);
kfree(ps2if);
return ret;
}
......@@ -312,31 +311,17 @@ static int ps2_probe(struct device *dev)
/*
* Remove one device from this driver.
*/
static int ps2_remove(struct device *dev)
static int ps2_remove(struct sa1111_dev *dev)
{
struct ps2if *ps2if = dev->driver_data;
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct ps2if *ps2if = sa1111_get_drvdata(dev);
serio_unregister_port(&ps2if->io);
release_mem_region(sadev->res.start,
sadev->res.end - sadev->res.start + 1);
kfree(ps2if);
dev->driver_data = NULL;
return 0;
}
release_mem_region(dev->res.start,
dev->res.end - dev->res.start + 1);
sa1111_set_drvdata(dev, NULL);
/*
* We should probably do something here, but what?
*/
static int ps2_suspend(struct device *dev, u32 state, u32 level)
{
return 0;
}
kfree(ps2if);
static int ps2_resume(struct device *dev, u32 level)
{
return 0;
}
......@@ -345,24 +330,21 @@ static int ps2_resume(struct device *dev, u32 level)
*/
static struct sa1111_driver ps2_driver = {
.drv = {
.name = "sa1111-ps2",
.bus = &sa1111_bus_type,
.probe = ps2_probe,
.remove = ps2_remove,
.suspend = ps2_suspend,
.resume = ps2_resume,
.name = "sa1111-ps2",
},
.devid = SA1111_DEVID_PS2,
.devid = SA1111_DEVID_PS2,
.probe = ps2_probe,
.remove = ps2_remove,
};
static int __init ps2_init(void)
{
return driver_register(&ps2_driver.drv);
return sa1111_driver_register(&ps2_driver);
}
static void __exit ps2_exit(void)
{
driver_unregister(&ps2_driver.drv);
sa1111_driver_unregister(&ps2_driver);
}
module_init(ps2_init);
......
......@@ -16,6 +16,7 @@
#include <asm/hardware.h>
#include <asm/hardware/sa1111.h>
#include <asm/io.h>
#include <asm/irq.h>
#include "sa1111_generic.h"
......@@ -118,16 +119,15 @@ void sa1111_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int pcmcia_probe(struct device *dev)
static int pcmcia_probe(struct sa1111_dev *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
char *base;
if (!request_mem_region(sadev->res.start, 512,
SA1111_DRIVER_NAME(sadev)))
if (!request_mem_region(dev->res.start, 512,
SA1111_DRIVER_NAME(dev)))
return -EBUSY;
base = sadev->mapbase;
base = dev->mapbase;
/*
* Initialise the suspend state.
......@@ -136,61 +136,68 @@ static int pcmcia_probe(struct device *dev)
sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR);
#ifdef CONFIG_SA1100_ADSBITSY
pcmcia_adsbitsy_init(dev);
pcmcia_adsbitsy_init(&dev->dev);
#endif
#ifdef CONFIG_SA1100_BADGE4
pcmcia_badge4_init(dev);
pcmcia_badge4_init(&dev->dev);
#endif
#ifdef CONFIG_SA1100_GRAPHICSMASTER
pcmcia_graphicsmaster_init(dev);
pcmcia_graphicsmaster_init(&dev->dev);
#endif
#ifdef CONFIG_SA1100_JORNADA720
pcmcia_jornada720_init(dev);
pcmcia_jornada720_init(&dev->dev);
#endif
#ifdef CONFIG_ASSABET_NEPONSET
pcmcia_neponset_init(dev);
pcmcia_neponset_init(&dev->dev);
#endif
#ifdef CONFIG_SA1100_PFS168
pcmcia_pfs_init(dev);
pcmcia_pfs_init(&dev->dev);
#endif
#ifdef CONFIG_SA1100_PT_SYSTEM3
pcmcia_system3_init(dev);
pcmcia_system3_init(&dev->dev);
#endif
#ifdef CONFIG_SA1100_XP860
pcmcia_xp860_init(dev);
pcmcia_xp860_init(&dev->dev);
#endif
return 0;
}
static int __devexit pcmcia_remove(struct device *dev)
static int __devexit pcmcia_remove(struct sa1111_dev *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
sa11xx_drv_pcmcia_remove(dev);
release_mem_region(sadev->res.start, 512);
sa11xx_drv_pcmcia_remove(&dev->dev);
release_mem_region(dev->res.start, 512);
return 0;
}
static int pcmcia_suspend(struct sa1111_dev *dev, u32 state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state, SUSPEND_SAVE_STATE);
}
static int pcmcia_resume(struct sa1111_dev *dev)
{
return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
}
static struct sa1111_driver pcmcia_driver = {
.drv = {
.name = "sa1111-pcmcia",
.bus = &sa1111_bus_type,
.probe = pcmcia_probe,
.remove = __devexit_p(pcmcia_remove),
.suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_socket_dev_resume,
.name = "sa1111-pcmcia",
},
.devid = SA1111_DEVID_PCMCIA,
.devid = SA1111_DEVID_PCMCIA,
.probe = pcmcia_probe,
.remove = __devexit_p(pcmcia_remove),
.suspend = pcmcia_suspend,
.resume = pcmcia_resume,
};
static int __init sa1111_drv_pcmcia_init(void)
{
return driver_register(&pcmcia_driver.drv);
return sa1111_driver_register(&pcmcia_driver);
}
static void __exit sa1111_drv_pcmcia_exit(void)
{
driver_unregister(&pcmcia_driver.drv);
sa1111_driver_unregister(&pcmcia_driver);
}
module_init(sa1111_drv_pcmcia_init);
......
......@@ -352,9 +352,8 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
/*-------------------------------------------------------------------------*/
static int ohci_hcd_sa1111_drv_probe(struct device *_dev)
static int ohci_hcd_sa1111_drv_probe(struct sa1111_dev *dev)
{
struct sa1111_dev *dev = SA1111_DEV(_dev);
struct usb_hcd *hcd = NULL;
int ret;
......@@ -364,43 +363,29 @@ static int ohci_hcd_sa1111_drv_probe(struct device *_dev)
ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &hcd, dev);
if (ret == 0)
dev->dev.driver_data = hcd;
sa1111_set_drvdata(dev, hcd);
return ret;
}
static int ohci_hcd_sa1111_drv_remove(struct device *_dev)
static int ohci_hcd_sa1111_drv_remove(struct sa1111_dev *dev)
{
struct sa1111_dev *dev = SA1111_DEV(_dev);
struct usb_hcd *hcd = dev->dev.driver_data;
struct usb_hcd *hcd = sa1111_get_drvdata(dev);
usb_hcd_sa1111_remove(hcd, dev);
dev->dev.driver_data = NULL;
sa1111_set_drvdata(dev, NULL);
return 0;
}
static int ohci_hcd_sa1111_drv_suspend(struct device *dev, u32 state, u32 level)
{
return 0;
}
static int ohci_hcd_sa1111_drv_resume(struct device *dev, u32 level)
{
return 0;
}
static struct sa1111_driver ohci_hcd_sa1111_driver = {
.drv = {
.name = "sa1111-ohci",
.bus = &sa1111_bus_type,
.probe = ohci_hcd_sa1111_drv_probe,
.remove = ohci_hcd_sa1111_drv_remove,
.suspend = ohci_hcd_sa1111_drv_suspend,
.resume = ohci_hcd_sa1111_drv_resume,
.name = "sa1111-ohci",
},
.devid = SA1111_DEVID_USB,
.devid = SA1111_DEVID_USB,
.probe = ohci_hcd_sa1111_drv_probe,
.remove = ohci_hcd_sa1111_drv_remove,
};
static int __init ohci_hcd_sa1111_init (void)
......@@ -409,12 +394,12 @@ static int __init ohci_hcd_sa1111_init (void)
dbg ("block sizes: ed %d td %d",
sizeof (struct ed), sizeof (struct td));
return driver_register(&ohci_hcd_sa1111_driver.drv);
return sa1111_driver_register(&ohci_hcd_sa1111_driver);
}
static void __exit ohci_hcd_sa1111_cleanup (void)
{
driver_unregister(&ohci_hcd_sa1111_driver.drv);
sa1111_driver_unregister(&ohci_hcd_sa1111_driver);
}
module_init (ohci_hcd_sa1111_init);
......
......@@ -542,9 +542,16 @@ struct sa1111_dev {
#define SA1111_DEV(_d) container_of((_d), struct sa1111_dev, dev)
#define sa1111_get_drvdata(d) dev_get_drvdata(&(d)->dev)
#define sa1111_set_drvdata(d,p) dev_get_drvdata(&(d)->dev, p)
struct sa1111_driver {
struct device_driver drv;
unsigned int devid;
int (*probe)(struct sa1111_dev *);
int (*remove)(struct sa1111_dev *);
int (*suspend)(struct sa1111_dev *, u32);
int (*resume)(struct sa1111_dev *);
};
#define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv)
......@@ -573,4 +580,7 @@ int sa1111_get_audio_rate(struct sa1111_dev *sadev);
int sa1111_check_dma_bug(dma_addr_t addr);
int sa1111_driver_register(struct sa1111_driver *);
void sa1111_driver_unregister(struct sa1111_driver *);
#endif /* _ASM_ARCH_SA1111 */
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