diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-09-06 18:19:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:57:58 -0400 |
commit | 6bb3b2cd40973ca67c9c6ab26c34df61680f5f84 (patch) | |
tree | 0404a8f93f002a956728488bfb5a491472be2f19 /drivers/net/irda | |
parent | 80a9058924d66643b645dbf5ad92acdac6d1d134 (diff) |
[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: Dmitry Torokhov <dtor@mail.ru>
Cc: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/net/irda')
-rw-r--r-- | drivers/net/irda/smsc-ircc2.c | 121 |
1 files changed, 65 insertions, 56 deletions
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index ee5ab94124a1..0f651eeb24ca 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c | |||
@@ -73,7 +73,6 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>"); | |||
73 | MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); | 73 | MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); |
74 | MODULE_LICENSE("GPL"); | 74 | MODULE_LICENSE("GPL"); |
75 | 75 | ||
76 | |||
77 | static int ircc_dma = 255; | 76 | static int ircc_dma = 255; |
78 | module_param(ircc_dma, int, 0); | 77 | module_param(ircc_dma, int, 0); |
79 | MODULE_PARM_DESC(ircc_dma, "DMA channel"); | 78 | MODULE_PARM_DESC(ircc_dma, "DMA channel"); |
@@ -144,17 +143,20 @@ struct smsc_ircc_cb { | |||
144 | int tx_len; /* Number of frames in tx_buff */ | 143 | int tx_len; /* Number of frames in tx_buff */ |
145 | 144 | ||
146 | int transceiver; | 145 | int transceiver; |
147 | struct pm_dev *pmdev; | 146 | struct platform_device *pldev; |
148 | }; | 147 | }; |
149 | 148 | ||
150 | /* Constants */ | 149 | /* Constants */ |
151 | 150 | ||
152 | static const char *driver_name = "smsc-ircc2"; | 151 | #define SMSC_IRCC2_DRIVER_NAME "smsc-ircc2" |
152 | |||
153 | #define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600 | 153 | #define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600 |
154 | #define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1 | 154 | #define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1 |
155 | #define SMSC_IRCC2_C_NET_TIMEOUT 0 | 155 | #define SMSC_IRCC2_C_NET_TIMEOUT 0 |
156 | #define SMSC_IRCC2_C_SIR_STOP 0 | 156 | #define SMSC_IRCC2_C_SIR_STOP 0 |
157 | 157 | ||
158 | static const char *driver_name = SMSC_IRCC2_DRIVER_NAME; | ||
159 | |||
158 | /* Prototypes */ | 160 | /* Prototypes */ |
159 | 161 | ||
160 | static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq); | 162 | 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 | static void smsc_ircc_timeout(struct net_device *dev); | 189 | static void smsc_ircc_timeout(struct net_device *dev); |
188 | #endif | 190 | #endif |
189 | static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev); | 191 | static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev); |
190 | static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); | ||
191 | static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self); | 192 | static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self); |
192 | static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self); | 193 | static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self); |
193 | static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed); | 194 | 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 | 213 | ||
213 | /* Power Management */ | 214 | /* Power Management */ |
214 | 215 | ||
215 | static void smsc_ircc_suspend(struct smsc_ircc_cb *self); | 216 | static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level); |
216 | static void smsc_ircc_wakeup(struct smsc_ircc_cb *self); | 217 | static int smsc_ircc_resume(struct device *dev, u32 level); |
217 | static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); | ||
218 | 218 | ||
219 | static struct device_driver smsc_ircc_driver = { | ||
220 | .name = SMSC_IRCC2_DRIVER_NAME, | ||
221 | .bus = &platform_bus_type, | ||
222 | .suspend = smsc_ircc_suspend, | ||
223 | .resume = smsc_ircc_resume, | ||
224 | }; | ||
219 | 225 | ||
220 | /* Transceivers for SMSC-ircc */ | 226 | /* Transceivers for SMSC-ircc */ |
221 | 227 | ||
@@ -335,34 +341,42 @@ static inline void register_bank(int iobase, int bank) | |||
335 | */ | 341 | */ |
336 | static int __init smsc_ircc_init(void) | 342 | static int __init smsc_ircc_init(void) |
337 | { | 343 | { |
338 | int ret = -ENODEV; | 344 | int ret; |
339 | 345 | ||
340 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 346 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
341 | 347 | ||
348 | ret = driver_register(&smsc_ircc_driver); | ||
349 | if (ret) { | ||
350 | IRDA_ERROR("%s, Can't register driver!\n", driver_name); | ||
351 | return ret; | ||
352 | } | ||
353 | |||
342 | dev_count = 0; | 354 | dev_count = 0; |
343 | 355 | ||
344 | if (ircc_fir > 0 && ircc_sir > 0) { | 356 | if (ircc_fir > 0 && ircc_sir > 0) { |
345 | IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); | 357 | IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); |
346 | IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); | 358 | IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); |
347 | 359 | ||
348 | if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0) | 360 | if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq)) |
349 | return 0; | 361 | ret = -ENODEV; |
362 | } else { | ||
350 | 363 | ||
351 | return -ENODEV; | 364 | /* try user provided configuration register base address */ |
352 | } | 365 | if (ircc_cfg > 0) { |
366 | IRDA_MESSAGE(" Overriding configuration address " | ||
367 | "0x%04x\n", ircc_cfg); | ||
368 | if (!smsc_superio_fdc(ircc_cfg)) | ||
369 | ret = 0; | ||
370 | if (!smsc_superio_lpc(ircc_cfg)) | ||
371 | ret = 0; | ||
372 | } | ||
353 | 373 | ||
354 | /* try user provided configuration register base address */ | 374 | if (smsc_ircc_look_for_chips() > 0) |
355 | if (ircc_cfg > 0) { | ||
356 | IRDA_MESSAGE(" Overriding configuration address 0x%04x\n", | ||
357 | ircc_cfg); | ||
358 | if (!smsc_superio_fdc(ircc_cfg)) | ||
359 | ret = 0; | ||
360 | if (!smsc_superio_lpc(ircc_cfg)) | ||
361 | ret = 0; | 375 | ret = 0; |
362 | } | 376 | } |
363 | 377 | ||
364 | if (smsc_ircc_look_for_chips() > 0) | 378 | if (ret) |
365 | ret = 0; | 379 | driver_unregister(&smsc_ircc_driver); |
366 | 380 | ||
367 | return ret; | 381 | return ret; |
368 | } | 382 | } |
@@ -420,7 +434,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u | |||
420 | dev->irq = self->io.irq = irq; | 434 | dev->irq = self->io.irq = irq; |
421 | 435 | ||
422 | /* Need to store self somewhere */ | 436 | /* Need to store self somewhere */ |
423 | dev_self[dev_count++] = self; | 437 | dev_self[dev_count] = self; |
424 | spin_lock_init(&self->lock); | 438 | spin_lock_init(&self->lock); |
425 | 439 | ||
426 | self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; | 440 | 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 | goto err_out4; | 483 | goto err_out4; |
470 | } | 484 | } |
471 | 485 | ||
472 | self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc); | 486 | self->pldev = platform_device_register_simple(SMSC_IRCC2_DRIVER_NAME, |
473 | if (self->pmdev) | 487 | dev_count, NULL, 0); |
474 | self->pmdev->data = self; | 488 | if (IS_ERR(self->pldev)) { |
489 | err = PTR_ERR(self->pldev); | ||
490 | goto err_out5; | ||
491 | } | ||
492 | dev_set_drvdata(&self->pldev->dev, self); | ||
475 | 493 | ||
476 | IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); | 494 | IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); |
495 | dev_count++; | ||
477 | 496 | ||
478 | return 0; | 497 | return 0; |
479 | 498 | ||
499 | err_out5: | ||
500 | unregister_netdev(self->netdev); | ||
501 | |||
480 | err_out4: | 502 | err_out4: |
481 | dma_free_coherent(NULL, self->tx_buff.truesize, | 503 | dma_free_coherent(NULL, self->tx_buff.truesize, |
482 | self->tx_buff.head, self->tx_buff_dma); | 504 | 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 | self->rx_buff.head, self->rx_buff_dma); | 507 | self->rx_buff.head, self->rx_buff_dma); |
486 | err_out2: | 508 | err_out2: |
487 | free_netdev(self->netdev); | 509 | free_netdev(self->netdev); |
488 | dev_self[--dev_count] = NULL; | 510 | dev_self[dev_count] = NULL; |
489 | err_out1: | 511 | err_out1: |
490 | release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); | 512 | release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); |
491 | release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); | 513 | release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); |
@@ -1626,44 +1648,31 @@ static int smsc_ircc_net_close(struct net_device *dev) | |||
1626 | return 0; | 1648 | return 0; |
1627 | } | 1649 | } |
1628 | 1650 | ||
1629 | 1651 | static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level) | |
1630 | static void smsc_ircc_suspend(struct smsc_ircc_cb *self) | ||
1631 | { | 1652 | { |
1653 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); | ||
1654 | |||
1632 | IRDA_MESSAGE("%s, Suspending\n", driver_name); | 1655 | IRDA_MESSAGE("%s, Suspending\n", driver_name); |
1633 | 1656 | ||
1634 | if (!self->io.suspended) { | 1657 | if (level == SUSPEND_DISABLE && !self->io.suspended) { |
1635 | smsc_ircc_net_close(self->netdev); | 1658 | smsc_ircc_net_close(self->netdev); |
1636 | self->io.suspended = 1; | 1659 | self->io.suspended = 1; |
1637 | } | 1660 | } |
1661 | |||
1662 | return 0; | ||
1638 | } | 1663 | } |
1639 | 1664 | ||
1640 | static void smsc_ircc_wakeup(struct smsc_ircc_cb *self) | 1665 | static int smsc_ircc_resume(struct device *dev, u32 level) |
1641 | { | 1666 | { |
1642 | if (!self->io.suspended) | 1667 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); |
1643 | return; | ||
1644 | 1668 | ||
1645 | /* The code was doing a "cli()" here, but this can't be right. | 1669 | if (level == RESUME_ENABLE && self->io.suspended) { |
1646 | * If you need protection, do it in net_open with a spinlock | ||
1647 | * or give a good reason. - Jean II */ | ||
1648 | 1670 | ||
1649 | smsc_ircc_net_open(self->netdev); | 1671 | smsc_ircc_net_open(self->netdev); |
1672 | self->io.suspended = 0; | ||
1650 | 1673 | ||
1651 | IRDA_MESSAGE("%s, Waking up\n", driver_name); | 1674 | IRDA_MESSAGE("%s, Waking up\n", driver_name); |
1652 | } | 1675 | } |
1653 | |||
1654 | static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) | ||
1655 | { | ||
1656 | struct smsc_ircc_cb *self = (struct smsc_ircc_cb*) dev->data; | ||
1657 | if (self) { | ||
1658 | switch (rqst) { | ||
1659 | case PM_SUSPEND: | ||
1660 | smsc_ircc_suspend(self); | ||
1661 | break; | ||
1662 | case PM_RESUME: | ||
1663 | smsc_ircc_wakeup(self); | ||
1664 | break; | ||
1665 | } | ||
1666 | } | ||
1667 | return 0; | 1676 | return 0; |
1668 | } | 1677 | } |
1669 | 1678 | ||
@@ -1682,10 +1691,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | |||
1682 | 1691 | ||
1683 | IRDA_ASSERT(self != NULL, return -1;); | 1692 | IRDA_ASSERT(self != NULL, return -1;); |
1684 | 1693 | ||
1685 | iobase = self->io.fir_base; | 1694 | platform_device_unregister(self->pldev); |
1686 | |||
1687 | if (self->pmdev) | ||
1688 | pm_unregister(self->pmdev); | ||
1689 | 1695 | ||
1690 | /* Remove netdevice */ | 1696 | /* Remove netdevice */ |
1691 | unregister_netdev(self->netdev); | 1697 | unregister_netdev(self->netdev); |
@@ -1694,6 +1700,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | |||
1694 | spin_lock_irqsave(&self->lock, flags); | 1700 | spin_lock_irqsave(&self->lock, flags); |
1695 | 1701 | ||
1696 | /* Stop interrupts */ | 1702 | /* Stop interrupts */ |
1703 | iobase = self->io.fir_base; | ||
1697 | register_bank(iobase, 0); | 1704 | register_bank(iobase, 0); |
1698 | outb(0, iobase + IRCC_IER); | 1705 | outb(0, iobase + IRCC_IER); |
1699 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); | 1706 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); |
@@ -1740,6 +1747,8 @@ static void __exit smsc_ircc_cleanup(void) | |||
1740 | if (dev_self[i]) | 1747 | if (dev_self[i]) |
1741 | smsc_ircc_close(dev_self[i]); | 1748 | smsc_ircc_close(dev_self[i]); |
1742 | } | 1749 | } |
1750 | |||
1751 | driver_unregister(&smsc_ircc_driver); | ||
1743 | } | 1752 | } |
1744 | 1753 | ||
1745 | /* | 1754 | /* |