* Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
return ret;
}
+static int zilog_irq = -1;
+
static int __devinit zs_probe(struct of_device *dev, const struct of_device_id *match)
{
- static int zilog_irq = -1;
struct of_device *op = to_of_device(&dev->dev);
struct uart_sunzilog_port *up;
struct zilog_layout __iomem *rp;
if (zilog_irq == -1) {
zilog_irq = op->irqs[0];
- err = request_irq(zilog_irq, sunzilog_interrupt, SA_SHIRQ,
+ err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
"zs", sunzilog_irq_chain);
if (err) {
of_iounmap(rp, sizeof(struct zilog_layout));
}
}
+ dev_set_drvdata(&dev->dev, &up[0]);
+
return 0;
}
-static int __devexit zs_remove(struct of_device *dev)
+static void __devexit zs_remove_one(struct uart_sunzilog_port *up)
{
- struct uart_sunzilog_port *up = dev_get_drvdata(&dev->dev);
- struct zilog_channel __iomem *channel;
-
if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
#ifdef CONFIG_SERIO
serio_unregister_port(&up->serio);
#endif
} else
uart_remove_one_port(&sunzilog_reg, &up->port);
+}
- channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+static int __devexit zs_remove(struct of_device *dev)
+{
+ struct uart_sunzilog_port *up = dev_get_drvdata(&dev->dev);
+ struct zilog_layout __iomem *regs;
+
+ zs_remove_one(&up[0]);
+ zs_remove_one(&up[1]);
- of_iounmap(channel, sizeof(struct zilog_channel));
+ regs = sunzilog_chip_regs[up[0].port.line / 2];
+ of_iounmap(regs, sizeof(struct zilog_layout));
+
+ dev_set_drvdata(&dev->dev, NULL);
return 0;
}
{
of_unregister_driver(&zs_driver);
+ if (zilog_irq != -1) {
+ free_irq(zilog_irq, sunzilog_irq_chain);
+ zilog_irq = -1;
+ }
+
if (NUM_SUNZILOG) {
uart_unregister_driver(&sunzilog_reg);
sunzilog_free_tables();
MODULE_AUTHOR("David S. Miller");
MODULE_DESCRIPTION("Sun Zilog serial port driver");
+MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");