Commit 6bb3b2cd authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Linus Torvalds

[PATCH] smsc-ircc2: add to sysfs as platform device, new PM

IRDA: smsc-ircc2 - add sysfs support (platform device and driver) and
      switch power management to the new scheme.
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
Cc: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 80a90589
...@@ -73,7 +73,6 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>"); ...@@ -73,7 +73,6 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int ircc_dma = 255; static int ircc_dma = 255;
module_param(ircc_dma, int, 0); module_param(ircc_dma, int, 0);
MODULE_PARM_DESC(ircc_dma, "DMA channel"); MODULE_PARM_DESC(ircc_dma, "DMA channel");
...@@ -144,17 +143,20 @@ struct smsc_ircc_cb { ...@@ -144,17 +143,20 @@ struct smsc_ircc_cb {
int tx_len; /* Number of frames in tx_buff */ int tx_len; /* Number of frames in tx_buff */
int transceiver; int transceiver;
struct pm_dev *pmdev; struct platform_device *pldev;
}; };
/* Constants */ /* Constants */
static const char *driver_name = "smsc-ircc2"; #define SMSC_IRCC2_DRIVER_NAME "smsc-ircc2"
#define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600 #define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600
#define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1 #define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1
#define SMSC_IRCC2_C_NET_TIMEOUT 0 #define SMSC_IRCC2_C_NET_TIMEOUT 0
#define SMSC_IRCC2_C_SIR_STOP 0 #define SMSC_IRCC2_C_SIR_STOP 0
static const char *driver_name = SMSC_IRCC2_DRIVER_NAME;
/* Prototypes */ /* Prototypes */
static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq); static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq);
...@@ -187,7 +189,6 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cm ...@@ -187,7 +189,6 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cm
static void smsc_ircc_timeout(struct net_device *dev); static void smsc_ircc_timeout(struct net_device *dev);
#endif #endif
static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev); static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev);
static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self); static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self);
static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self); static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self);
static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed); static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed);
...@@ -212,10 +213,15 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base); ...@@ -212,10 +213,15 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base);
/* Power Management */ /* Power Management */
static void smsc_ircc_suspend(struct smsc_ircc_cb *self); static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level);
static void smsc_ircc_wakeup(struct smsc_ircc_cb *self); static int smsc_ircc_resume(struct device *dev, u32 level);
static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
static struct device_driver smsc_ircc_driver = {
.name = SMSC_IRCC2_DRIVER_NAME,
.bus = &platform_bus_type,
.suspend = smsc_ircc_suspend,
.resume = smsc_ircc_resume,
};
/* Transceivers for SMSC-ircc */ /* Transceivers for SMSC-ircc */
...@@ -335,26 +341,30 @@ static inline void register_bank(int iobase, int bank) ...@@ -335,26 +341,30 @@ static inline void register_bank(int iobase, int bank)
*/ */
static int __init smsc_ircc_init(void) static int __init smsc_ircc_init(void)
{ {
int ret = -ENODEV; int ret;
IRDA_DEBUG(1, "%s\n", __FUNCTION__); IRDA_DEBUG(1, "%s\n", __FUNCTION__);
ret = driver_register(&smsc_ircc_driver);
if (ret) {
IRDA_ERROR("%s, Can't register driver!\n", driver_name);
return ret;
}
dev_count = 0; dev_count = 0;
if (ircc_fir > 0 && ircc_sir > 0) { if (ircc_fir > 0 && ircc_sir > 0) {
IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0) if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq))
return 0; ret = -ENODEV;
} else {
return -ENODEV;
}
/* try user provided configuration register base address */ /* try user provided configuration register base address */
if (ircc_cfg > 0) { if (ircc_cfg > 0) {
IRDA_MESSAGE(" Overriding configuration address 0x%04x\n", IRDA_MESSAGE(" Overriding configuration address "
ircc_cfg); "0x%04x\n", ircc_cfg);
if (!smsc_superio_fdc(ircc_cfg)) if (!smsc_superio_fdc(ircc_cfg))
ret = 0; ret = 0;
if (!smsc_superio_lpc(ircc_cfg)) if (!smsc_superio_lpc(ircc_cfg))
...@@ -363,6 +373,10 @@ static int __init smsc_ircc_init(void) ...@@ -363,6 +373,10 @@ static int __init smsc_ircc_init(void)
if (smsc_ircc_look_for_chips() > 0) if (smsc_ircc_look_for_chips() > 0)
ret = 0; ret = 0;
}
if (ret)
driver_unregister(&smsc_ircc_driver);
return ret; return ret;
} }
...@@ -420,7 +434,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u ...@@ -420,7 +434,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dev->irq = self->io.irq = irq; dev->irq = self->io.irq = irq;
/* Need to store self somewhere */ /* Need to store self somewhere */
dev_self[dev_count++] = self; dev_self[dev_count] = self;
spin_lock_init(&self->lock); spin_lock_init(&self->lock);
self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
...@@ -469,14 +483,22 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u ...@@ -469,14 +483,22 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
goto err_out4; goto err_out4;
} }
self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc); self->pldev = platform_device_register_simple(SMSC_IRCC2_DRIVER_NAME,
if (self->pmdev) dev_count, NULL, 0);
self->pmdev->data = self; if (IS_ERR(self->pldev)) {
err = PTR_ERR(self->pldev);
goto err_out5;
}
dev_set_drvdata(&self->pldev->dev, self);
IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
dev_count++;
return 0; return 0;
err_out5:
unregister_netdev(self->netdev);
err_out4: err_out4:
dma_free_coherent(NULL, self->tx_buff.truesize, dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma); self->tx_buff.head, self->tx_buff_dma);
...@@ -485,7 +507,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u ...@@ -485,7 +507,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
self->rx_buff.head, self->rx_buff_dma); self->rx_buff.head, self->rx_buff_dma);
err_out2: err_out2:
free_netdev(self->netdev); free_netdev(self->netdev);
dev_self[--dev_count] = NULL; dev_self[dev_count] = NULL;
err_out1: err_out1:
release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
...@@ -1626,43 +1648,30 @@ static int smsc_ircc_net_close(struct net_device *dev) ...@@ -1626,43 +1648,30 @@ static int smsc_ircc_net_close(struct net_device *dev)
return 0; return 0;
} }
static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level)
static void smsc_ircc_suspend(struct smsc_ircc_cb *self)
{ {
struct smsc_ircc_cb *self = dev_get_drvdata(dev);
IRDA_MESSAGE("%s, Suspending\n", driver_name); IRDA_MESSAGE("%s, Suspending\n", driver_name);
if (!self->io.suspended) { if (level == SUSPEND_DISABLE && !self->io.suspended) {
smsc_ircc_net_close(self->netdev); smsc_ircc_net_close(self->netdev);
self->io.suspended = 1; self->io.suspended = 1;
} }
return 0;
} }
static void smsc_ircc_wakeup(struct smsc_ircc_cb *self) static int smsc_ircc_resume(struct device *dev, u32 level)
{ {
if (!self->io.suspended) struct smsc_ircc_cb *self = dev_get_drvdata(dev);
return;
/* The code was doing a "cli()" here, but this can't be right. if (level == RESUME_ENABLE && self->io.suspended) {
* If you need protection, do it in net_open with a spinlock
* or give a good reason. - Jean II */
smsc_ircc_net_open(self->netdev); smsc_ircc_net_open(self->netdev);
self->io.suspended = 0;
IRDA_MESSAGE("%s, Waking up\n", driver_name); IRDA_MESSAGE("%s, Waking up\n", driver_name);
}
static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
{
struct smsc_ircc_cb *self = (struct smsc_ircc_cb*) dev->data;
if (self) {
switch (rqst) {
case PM_SUSPEND:
smsc_ircc_suspend(self);
break;
case PM_RESUME:
smsc_ircc_wakeup(self);
break;
}
} }
return 0; return 0;
} }
...@@ -1682,10 +1691,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) ...@@ -1682,10 +1691,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
IRDA_ASSERT(self != NULL, return -1;); IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.fir_base; platform_device_unregister(self->pldev);
if (self->pmdev)
pm_unregister(self->pmdev);
/* Remove netdevice */ /* Remove netdevice */
unregister_netdev(self->netdev); unregister_netdev(self->netdev);
...@@ -1694,6 +1700,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) ...@@ -1694,6 +1700,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
spin_lock_irqsave(&self->lock, flags); spin_lock_irqsave(&self->lock, flags);
/* Stop interrupts */ /* Stop interrupts */
iobase = self->io.fir_base;
register_bank(iobase, 0); register_bank(iobase, 0);
outb(0, iobase + IRCC_IER); outb(0, iobase + IRCC_IER);
outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER);
...@@ -1740,6 +1747,8 @@ static void __exit smsc_ircc_cleanup(void) ...@@ -1740,6 +1747,8 @@ static void __exit smsc_ircc_cleanup(void)
if (dev_self[i]) if (dev_self[i])
smsc_ircc_close(dev_self[i]); smsc_ircc_close(dev_self[i]);
} }
driver_unregister(&smsc_ircc_driver);
} }
/* /*
......
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