#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
#include <linux/pnp.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
-
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
static char *driver_name = "nsc-ircc";
+/* Power Management */
+#define NSC_IRCC_DRIVER_NAME "nsc-ircc"
+static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state);
+static int nsc_ircc_resume(struct platform_device *dev);
+
+static struct platform_driver nsc_ircc_driver = {
+ .suspend = nsc_ircc_suspend,
+ .resume = nsc_ircc_resume,
+ .driver = {
+ .name = NSC_IRCC_DRIVER_NAME,
+ },
+};
+
/* Module parameters */
static int qos_mtt_bits = 0x07; /* 1 ms or more */
static int dongle_id;
/* Use BIOS settions by default, but user may supply module parameters */
-static unsigned int io[] = { ~0, ~0, ~0, ~0 };
-static unsigned int irq[] = { 0, 0, 0, 0 };
-static unsigned int dma[] = { 0, 0, 0, 0 };
+static unsigned int io[] = { ~0, ~0, ~0, ~0, ~0 };
+static unsigned int irq[] = { 0, 0, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0, 0 };
static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info);
static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info);
/* Contributed by Jan Frey - IBM A30/A31 */
{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff,
nsc_ircc_probe_39x, nsc_ircc_init_39x },
+ /* IBM ThinkPads using PC8738x (T60/X60/Z60) */
+ { "IBM-PC8738x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
+ nsc_ircc_probe_39x, nsc_ircc_init_39x },
+ /* IBM ThinkPads using PC8394T (T43/R52/?) */
+ { "IBM-PC8394T", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf9, 0xff,
+ nsc_ircc_probe_39x, nsc_ircc_init_39x },
{ NULL }
};
-static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
+static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL };
static char *dongle_types[] = {
"Differential serial interface",
static int nsc_ircc_net_close(struct net_device *dev);
static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
-static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
/* Globals */
static int pnp_registered;
int reg;
int i = 0;
+ ret = platform_driver_register(&nsc_ircc_driver);
+ if (ret) {
+ IRDA_ERROR("%s, Can't register driver!\n", driver_name);
+ return ret;
+ }
+
/* Register with PnP subsystem to detect disable ports */
ret = pnp_register_driver(&nsc_ircc_pnp_driver);
- if (ret >= 0)
+ if (!ret)
pnp_registered = 1;
ret = -ENODEV;
}
if (ret) {
+ platform_driver_unregister(&nsc_ircc_driver);
pnp_unregister_driver(&nsc_ircc_pnp_driver);
pnp_registered = 0;
}
{
int i;
- pm_unregister_all(nsc_ircc_pmproc);
-
for (i = 0; i < ARRAY_SIZE(dev_self); i++) {
if (dev_self[i])
nsc_ircc_close(dev_self[i]);
}
+ platform_driver_unregister(&nsc_ircc_driver);
+
if (pnp_registered)
pnp_unregister_driver(&nsc_ircc_pnp_driver);
{
struct net_device *dev;
struct nsc_ircc_cb *self;
- struct pm_dev *pmdev;
void *ret;
int err, chip_index;
self->io.dongle_id = dongle_id;
nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
- pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc);
- if (pmdev)
- pmdev->data = self;
+ self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME,
+ self->index, NULL, 0);
+ if (IS_ERR(self->pldev)) {
+ err = PTR_ERR(self->pldev);
+ goto out5;
+ }
+ platform_set_drvdata(self->pldev, self);
return chip_index;
+
+ out5:
+ unregister_netdev(dev);
out4:
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
iobase = self->io.fir_base;
+ platform_device_unregister(self->pldev);
+
/* Remove netdevice */
unregister_netdev(self->netdev);
int cfg_base = info->cfg_base;
int enabled;
- /* User is shure about his config... accept it. */
+ /* User is sure about his config... accept it. */
IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): "
"io=0x%04x, irq=%d, dma=%d\n",
__FUNCTION__, info->fir_base, info->irq, info->dma);
return &self->stats;
}
-static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
+static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state)
{
- IRDA_MESSAGE("%s, Suspending\n", driver_name);
+ struct nsc_ircc_cb *self = platform_get_drvdata(dev);
+ int bank;
+ unsigned long flags;
+ int iobase = self->io.fir_base;
if (self->io.suspended)
- return;
+ return 0;
+
+ IRDA_DEBUG(1, "%s, Suspending\n", driver_name);
+
+ rtnl_lock();
+ if (netif_running(self->netdev)) {
+ netif_device_detach(self->netdev);
+ spin_lock_irqsave(&self->lock, flags);
+ /* Save current bank */
+ bank = inb(iobase+BSR);
- nsc_ircc_net_close(self->netdev);
+ /* Disable interrupts */
+ switch_bank(iobase, BANK0);
+ outb(0, iobase+IER);
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ spin_unlock_irqrestore(&self->lock, flags);
+ free_irq(self->io.irq, self->netdev);
+ disable_dma(self->io.dma);
+ }
self->io.suspended = 1;
+ rtnl_unlock();
+
+ return 0;
}
-static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
+static int nsc_ircc_resume(struct platform_device *dev)
{
+ struct nsc_ircc_cb *self = platform_get_drvdata(dev);
+ unsigned long flags;
+
if (!self->io.suspended)
- return;
+ return 0;
+
+ IRDA_DEBUG(1, "%s, Waking up\n", driver_name);
+ rtnl_lock();
nsc_ircc_setup(&self->io);
- nsc_ircc_net_open(self->netdev);
-
- IRDA_MESSAGE("%s, Waking up\n", driver_name);
+ nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id);
+
+ if (netif_running(self->netdev)) {
+ if (request_irq(self->io.irq, nsc_ircc_interrupt, 0,
+ self->netdev->name, self->netdev)) {
+ IRDA_WARNING("%s, unable to allocate irq=%d\n",
+ driver_name, self->io.irq);
+
+ /*
+ * Don't fail resume process, just kill this
+ * network interface
+ */
+ unregister_netdevice(self->netdev);
+ } else {
+ spin_lock_irqsave(&self->lock, flags);
+ nsc_ircc_change_speed(self, self->io.speed);
+ spin_unlock_irqrestore(&self->lock, flags);
+ netif_device_attach(self->netdev);
+ }
+ } else {
+ spin_lock_irqsave(&self->lock, flags);
+ nsc_ircc_change_speed(self, 9600);
+ spin_unlock_irqrestore(&self->lock, flags);
+ }
self->io.suspended = 0;
-}
+ rtnl_unlock();
-static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data;
- if (self) {
- switch (rqst) {
- case PM_SUSPEND:
- nsc_ircc_suspend(self);
- break;
- case PM_RESUME:
- nsc_ircc_wakeup(self);
- break;
- }
- }
- return 0;
+ return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");