Commit a3c1d44d authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Russell King

[PCMCIA] generic suspend/resume capability

The socket drivers already offer suspend and resume
capability. Integrate this with the driver model, based on a
suggestion by Russell King.

Also, remove two never-used functions from the socket drivers (to_ns).

 drivers/pcmcia/cs.c             |   70 ++++++++++++++++++++--------------------
 drivers/pcmcia/cs_internal.h    |    1
 drivers/pcmcia/hd64465_ss.c     |    2 +
 drivers/pcmcia/i82092.c         |   17 ++++++---
 drivers/pcmcia/i82365.c         |    2 +
 drivers/pcmcia/pci_socket.c     |   15 +-------
 drivers/pcmcia/sa1100_generic.c |    2 +
 drivers/pcmcia/sa1111_generic.c |   14 +-------
 drivers/pcmcia/tcic.c           |    7 +---
 include/pcmcia/ss.h             |    5 ++
 10 files changed, 64 insertions(+), 71 deletions(-)
parent edad54dc
...@@ -111,13 +111,6 @@ INT_MODULE_PARM(cis_speed, 300); /* ns */ ...@@ -111,13 +111,6 @@ INT_MODULE_PARM(cis_speed, 300); /* ns */
/* Access speed for IO windows */ /* Access speed for IO windows */
INT_MODULE_PARM(io_speed, 0); /* ns */ INT_MODULE_PARM(io_speed, 0); /* ns */
/* Optional features */
#ifdef CONFIG_PM
INT_MODULE_PARM(do_apm, 1);
#else
INT_MODULE_PARM(do_apm, 0);
#endif
#ifdef PCMCIA_DEBUG #ifdef PCMCIA_DEBUG
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
static const char *version = static const char *version =
...@@ -348,7 +341,6 @@ int pcmcia_register_socket(struct device *dev) ...@@ -348,7 +341,6 @@ int pcmcia_register_socket(struct device *dev)
/* base address = 0, map = 0 */ /* base address = 0, map = 0 */
s->cis_mem.flags = 0; s->cis_mem.flags = 0;
s->cis_mem.speed = cis_speed; s->cis_mem.speed = cis_speed;
s->use_bus_pm = cls_d->use_bus_pm;
s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
spin_lock_init(&s->lock); spin_lock_init(&s->lock);
...@@ -756,33 +748,47 @@ void pcmcia_resume_socket (socket_info_t *s) ...@@ -756,33 +748,47 @@ void pcmcia_resume_socket (socket_info_t *s)
parse_events(s, SS_DETECT); parse_events(s, SS_DETECT);
} }
static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data)
int pcmcia_socket_dev_suspend(struct device * dev, u32 state, u32 level)
{ {
int i; struct pcmcia_socket_class_data *cls_d = to_class_data(dev);
socket_info_t *s; socket_info_t *s;
int i;
if ((!cls_d) || (level != SUSPEND_SAVE_STATE))
return 0;
/* only for busses that don't suspend/resume slots directly */ s = (socket_info_t *) cls_d->s_info;
switch (rqst) { for (i = 0; i < cls_d->nsock; i++) {
case PM_SUSPEND: pcmcia_suspend_socket(s);
DEBUG(1, "cs: received suspend notification\n"); s++;
for (i = 0; i < sockets; i++) {
s = socket_table [i];
if (!s->use_bus_pm)
pcmcia_suspend_socket (socket_table [i]);
} }
break;
case PM_RESUME: return 0;
DEBUG(1, "cs: received resume notification\n"); }
for (i = 0; i < sockets; i++) { EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
s = socket_table [i];
if (!s->use_bus_pm) int pcmcia_socket_dev_resume(struct device * dev, u32 level)
pcmcia_resume_socket (socket_table [i]); {
struct pcmcia_socket_class_data *cls_d = to_class_data(dev);
socket_info_t *s;
int i;
if ((!cls_d) || (level != RESUME_RESTORE_STATE))
return 0;
s = (socket_info_t *) cls_d->s_info;
for (i = 0; i < cls_d->nsock; i++) {
pcmcia_resume_socket(s);
s++;
} }
break;
} return 0;
return 0; }
} /* handle_pm_event */ EXPORT_SYMBOL(pcmcia_socket_dev_resume);
/*====================================================================== /*======================================================================
...@@ -2429,8 +2435,6 @@ static int __init init_pcmcia_cs(void) ...@@ -2429,8 +2435,6 @@ static int __init init_pcmcia_cs(void)
printk(KERN_INFO " %s\n", options); printk(KERN_INFO " %s\n", options);
DEBUG(0, "%s\n", version); DEBUG(0, "%s\n", version);
devclass_register(&pcmcia_socket_class); devclass_register(&pcmcia_socket_class);
if (do_apm)
pm_register(PM_SYS_DEV, PM_SYS_PCMCIA, handle_pm_event);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_pccard = proc_mkdir("pccard", proc_bus); proc_pccard = proc_mkdir("pccard", proc_bus);
#endif #endif
...@@ -2446,8 +2450,6 @@ static void __exit exit_pcmcia_cs(void) ...@@ -2446,8 +2450,6 @@ static void __exit exit_pcmcia_cs(void)
remove_proc_entry("pccard", proc_bus); remove_proc_entry("pccard", proc_bus);
} }
#endif #endif
if (do_apm)
pm_unregister_all(handle_pm_event);
release_resource_db(); release_resource_db();
devclass_unregister(&pcmcia_socket_class); devclass_unregister(&pcmcia_socket_class);
} }
......
...@@ -157,7 +157,6 @@ typedef struct socket_info_t { ...@@ -157,7 +157,6 @@ typedef struct socket_info_t {
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc; struct proc_dir_entry *proc;
#endif #endif
int use_bus_pm;
} socket_info_t; } socket_info_t;
/* Flags in config state */ /* Flags in config state */
......
...@@ -968,6 +968,8 @@ static struct device_driver hd64465_driver = { ...@@ -968,6 +968,8 @@ static struct device_driver hd64465_driver = {
.name = "hd64465-pcmcia", .name = "hd64465-pcmcia",
.bus = &platform_bus_type, .bus = &platform_bus_type,
.devclass = &pcmcia_socket_class, .devclass = &pcmcia_socket_class,
.suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_socket_dev_resume,
}; };
static struct platform_device hd64465_device = { static struct platform_device hd64465_device = {
......
...@@ -42,11 +42,23 @@ static struct pci_device_id i82092aa_pci_ids[] = { ...@@ -42,11 +42,23 @@ static struct pci_device_id i82092aa_pci_ids[] = {
}; };
MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
}
static int i82092aa_socket_resume (struct pci_dev *dev)
{
return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
}
static struct pci_driver i82092aa_pci_drv = { static struct pci_driver i82092aa_pci_drv = {
.name = "i82092aa", .name = "i82092aa",
.id_table = i82092aa_pci_ids, .id_table = i82092aa_pci_ids,
.probe = i82092aa_pci_probe, .probe = i82092aa_pci_probe,
.remove = __devexit_p(i82092aa_pci_remove), .remove = __devexit_p(i82092aa_pci_remove),
.suspend = i82092aa_socket_suspend,
.resume = i82092aa_socket_resume,
.driver = { .driver = {
.devclass = &pcmcia_socket_class, .devclass = &pcmcia_socket_class,
}, },
...@@ -302,11 +314,6 @@ static int to_cycles(int ns) ...@@ -302,11 +314,6 @@ static int to_cycles(int ns)
return 0; return 0;
} }
static int to_ns(int cycles)
{
return cycle_time*cycles;
}
/* Interrupt handler functionality */ /* Interrupt handler functionality */
......
...@@ -1511,6 +1511,8 @@ static struct device_driver i82365_driver = { ...@@ -1511,6 +1511,8 @@ static struct device_driver i82365_driver = {
.name = "i82365", .name = "i82365",
.bus = &platform_bus_type, .bus = &platform_bus_type,
.devclass = &pcmcia_socket_class, .devclass = &pcmcia_socket_class,
.suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_socket_dev_resume,
}; };
static struct platform_device i82365_device = { static struct platform_device i82365_device = {
......
...@@ -31,10 +31,6 @@ ...@@ -31,10 +31,6 @@
#include "pci_socket.h" #include "pci_socket.h"
extern void pcmcia_suspend_socket (struct socket_info_t *socket);
extern void pcmcia_resume_socket (struct socket_info_t *socket);
/* /*
* Arbitrary define. This is the array of active cardbus * Arbitrary define. This is the array of active cardbus
* entries. * entries.
...@@ -157,7 +153,6 @@ static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_sock ...@@ -157,7 +153,6 @@ static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_sock
socket->cls_d.nsock = 1; /* yenta is 1, no other low-level driver uses socket->cls_d.nsock = 1; /* yenta is 1, no other low-level driver uses
this yet */ this yet */
socket->cls_d.ops = &pci_socket_operations; socket->cls_d.ops = &pci_socket_operations;
socket->cls_d.use_bus_pm = 1;
dev->dev.class_data = &socket->cls_d; dev->dev.class_data = &socket->cls_d;
/* prepare pci_socket_t */ /* prepare pci_socket_t */
...@@ -204,18 +199,12 @@ static void __devexit cardbus_remove (struct pci_dev *dev) ...@@ -204,18 +199,12 @@ static void __devexit cardbus_remove (struct pci_dev *dev)
static int cardbus_suspend (struct pci_dev *dev, u32 state) static int cardbus_suspend (struct pci_dev *dev, u32 state)
{ {
pci_socket_t *socket = pci_get_drvdata(dev); return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
if (socket && socket->cls_d.s_info)
pcmcia_suspend_socket (socket->cls_d.s_info);
return 0;
} }
static int cardbus_resume (struct pci_dev *dev) static int cardbus_resume (struct pci_dev *dev)
{ {
pci_socket_t *socket = pci_get_drvdata(dev); return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
if (socket && socket->cls_d.s_info)
pcmcia_resume_socket (socket->cls_d.s_info);
return 0;
} }
......
...@@ -1020,6 +1020,8 @@ static struct device_driver sa1100_pcmcia_driver = { ...@@ -1020,6 +1020,8 @@ static struct device_driver sa1100_pcmcia_driver = {
.name = "sa11x0-pcmcia", .name = "sa11x0-pcmcia",
.bus = &platform_bus_type, .bus = &platform_bus_type,
.devclass = &pcmcia_socket_class, .devclass = &pcmcia_socket_class,
.suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_socket_dev_resume,
}; };
static struct platform_device sa1100_pcmcia_device = { static struct platform_device sa1100_pcmcia_device = {
......
...@@ -257,16 +257,6 @@ static int __devexit pcmcia_remove(struct device *dev) ...@@ -257,16 +257,6 @@ static int __devexit pcmcia_remove(struct device *dev)
return 0; return 0;
} }
static int pcmcia_suspend(struct device *dev, u32 state, u32 level)
{
return 0;
}
static int pcmcia_resume(struct device *dev, u32 level)
{
return 0;
}
static struct sa1111_driver pcmcia_driver = { static struct sa1111_driver pcmcia_driver = {
.drv = { .drv = {
.name = "sa1111-pcmcia", .name = "sa1111-pcmcia",
...@@ -274,8 +264,8 @@ static struct sa1111_driver pcmcia_driver = { ...@@ -274,8 +264,8 @@ static struct sa1111_driver pcmcia_driver = {
.devclass = &pcmcia_socket_class, .devclass = &pcmcia_socket_class,
.probe = pcmcia_probe, .probe = pcmcia_probe,
.remove = __devexit_p(pcmcia_remove), .remove = __devexit_p(pcmcia_remove),
.suspend = pcmcia_suspend, .suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_resume, .resume = pcmcia_socket_dev_resume,
}, },
.devid = SA1111_DEVID_PCMCIA, .devid = SA1111_DEVID_PCMCIA,
}; };
......
...@@ -225,11 +225,6 @@ static int to_cycles(int ns) ...@@ -225,11 +225,6 @@ static int to_cycles(int ns)
return 2*(ns-14)/cycle_time; return 2*(ns-14)/cycle_time;
} }
static int to_ns(int cycles)
{
return (cycles*cycle_time)/2 + 14;
}
/*====================================================================*/ /*====================================================================*/
static volatile u_int irq_hits; static volatile u_int irq_hits;
...@@ -384,6 +379,8 @@ static struct device_driver tcic_driver = { ...@@ -384,6 +379,8 @@ static struct device_driver tcic_driver = {
.name = "tcic-pcmcia", .name = "tcic-pcmcia",
.bus = &platform_bus_type, .bus = &platform_bus_type,
.devclass = &pcmcia_socket_class, .devclass = &pcmcia_socket_class,
.suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_socket_dev_resume,
}; };
static struct platform_device tcic_device = { static struct platform_device tcic_device = {
......
...@@ -148,9 +148,12 @@ struct pcmcia_socket_class_data { ...@@ -148,9 +148,12 @@ struct pcmcia_socket_class_data {
* returned to driver) = sock_offset + (0, 1, .. , (nsock-1) */ * returned to driver) = sock_offset + (0, 1, .. , (nsock-1) */
struct pccard_operations *ops; /* see above */ struct pccard_operations *ops; /* see above */
void *s_info; /* socket_info_t */ void *s_info; /* socket_info_t */
unsigned int use_bus_pm;
}; };
extern struct device_class pcmcia_socket_class; extern struct device_class pcmcia_socket_class;
/* socket drivers are expected to use these callbacks in their .drv struct */
int pcmcia_socket_dev_suspend(struct device * dev, u32 state, u32 level);
int pcmcia_socket_dev_resume(struct device * dev, u32 level);
#endif /* _LINUX_SS_H */ #endif /* _LINUX_SS_H */
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