diff options
Diffstat (limited to 'drivers/input/serio/rpckbd.c')
-rw-r--r-- | drivers/input/serio/rpckbd.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 8b44ddc8041c..2af5df6a8fba 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c | |||
@@ -36,16 +36,19 @@ | |||
36 | #include <linux/io.h> | 36 | #include <linux/io.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | 38 | ||
39 | #include <asm/irq.h> | ||
40 | #include <mach/hardware.h> | 39 | #include <mach/hardware.h> |
41 | #include <asm/hardware/iomd.h> | 40 | #include <asm/hardware/iomd.h> |
42 | #include <asm/system.h> | ||
43 | 41 | ||
44 | MODULE_AUTHOR("Vojtech Pavlik, Russell King"); | 42 | MODULE_AUTHOR("Vojtech Pavlik, Russell King"); |
45 | MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver"); | 43 | MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver"); |
46 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
47 | MODULE_ALIAS("platform:kart"); | 45 | MODULE_ALIAS("platform:kart"); |
48 | 46 | ||
47 | struct rpckbd_data { | ||
48 | int tx_irq; | ||
49 | int rx_irq; | ||
50 | }; | ||
51 | |||
49 | static int rpckbd_write(struct serio *port, unsigned char val) | 52 | static int rpckbd_write(struct serio *port, unsigned char val) |
50 | { | 53 | { |
51 | while (!(iomd_readb(IOMD_KCTRL) & (1 << 7))) | 54 | while (!(iomd_readb(IOMD_KCTRL) & (1 << 7))) |
@@ -78,19 +81,21 @@ static irqreturn_t rpckbd_tx(int irq, void *dev_id) | |||
78 | 81 | ||
79 | static int rpckbd_open(struct serio *port) | 82 | static int rpckbd_open(struct serio *port) |
80 | { | 83 | { |
84 | struct rpckbd_data *rpckbd = port->port_data; | ||
85 | |||
81 | /* Reset the keyboard state machine. */ | 86 | /* Reset the keyboard state machine. */ |
82 | iomd_writeb(0, IOMD_KCTRL); | 87 | iomd_writeb(0, IOMD_KCTRL); |
83 | iomd_writeb(8, IOMD_KCTRL); | 88 | iomd_writeb(8, IOMD_KCTRL); |
84 | iomd_readb(IOMD_KARTRX); | 89 | iomd_readb(IOMD_KARTRX); |
85 | 90 | ||
86 | if (request_irq(IRQ_KEYBOARDRX, rpckbd_rx, 0, "rpckbd", port) != 0) { | 91 | if (request_irq(rpckbd->rx_irq, rpckbd_rx, 0, "rpckbd", port) != 0) { |
87 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard receive IRQ\n"); | 92 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard receive IRQ\n"); |
88 | return -EBUSY; | 93 | return -EBUSY; |
89 | } | 94 | } |
90 | 95 | ||
91 | if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) { | 96 | if (request_irq(rpckbd->tx_irq, rpckbd_tx, 0, "rpckbd", port) != 0) { |
92 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n"); | 97 | printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n"); |
93 | free_irq(IRQ_KEYBOARDRX, port); | 98 | free_irq(rpckbd->rx_irq, port); |
94 | return -EBUSY; | 99 | return -EBUSY; |
95 | } | 100 | } |
96 | 101 | ||
@@ -99,8 +104,10 @@ static int rpckbd_open(struct serio *port) | |||
99 | 104 | ||
100 | static void rpckbd_close(struct serio *port) | 105 | static void rpckbd_close(struct serio *port) |
101 | { | 106 | { |
102 | free_irq(IRQ_KEYBOARDRX, port); | 107 | struct rpckbd_data *rpckbd = port->port_data; |
103 | free_irq(IRQ_KEYBOARDTX, port); | 108 | |
109 | free_irq(rpckbd->rx_irq, port); | ||
110 | free_irq(rpckbd->tx_irq, port); | ||
104 | } | 111 | } |
105 | 112 | ||
106 | /* | 113 | /* |
@@ -109,17 +116,35 @@ static void rpckbd_close(struct serio *port) | |||
109 | */ | 116 | */ |
110 | static int __devinit rpckbd_probe(struct platform_device *dev) | 117 | static int __devinit rpckbd_probe(struct platform_device *dev) |
111 | { | 118 | { |
119 | struct rpckbd_data *rpckbd; | ||
112 | struct serio *serio; | 120 | struct serio *serio; |
121 | int tx_irq, rx_irq; | ||
122 | |||
123 | rx_irq = platform_get_irq(dev, 0); | ||
124 | if (rx_irq <= 0) | ||
125 | return rx_irq < 0 ? rx_irq : -ENXIO; | ||
126 | |||
127 | tx_irq = platform_get_irq(dev, 1); | ||
128 | if (tx_irq <= 0) | ||
129 | return tx_irq < 0 ? tx_irq : -ENXIO; | ||
113 | 130 | ||
114 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 131 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
115 | if (!serio) | 132 | rpckbd = kzalloc(sizeof(*rpckbd), GFP_KERNEL); |
133 | if (!serio || !rpckbd) { | ||
134 | kfree(rpckbd); | ||
135 | kfree(serio); | ||
116 | return -ENOMEM; | 136 | return -ENOMEM; |
137 | } | ||
138 | |||
139 | rpckbd->rx_irq = rx_irq; | ||
140 | rpckbd->tx_irq = tx_irq; | ||
117 | 141 | ||
118 | serio->id.type = SERIO_8042; | 142 | serio->id.type = SERIO_8042; |
119 | serio->write = rpckbd_write; | 143 | serio->write = rpckbd_write; |
120 | serio->open = rpckbd_open; | 144 | serio->open = rpckbd_open; |
121 | serio->close = rpckbd_close; | 145 | serio->close = rpckbd_close; |
122 | serio->dev.parent = &dev->dev; | 146 | serio->dev.parent = &dev->dev; |
147 | serio->port_data = rpckbd; | ||
123 | strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name)); | 148 | strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name)); |
124 | strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys)); | 149 | strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys)); |
125 | 150 | ||
@@ -131,7 +156,11 @@ static int __devinit rpckbd_probe(struct platform_device *dev) | |||
131 | static int __devexit rpckbd_remove(struct platform_device *dev) | 156 | static int __devexit rpckbd_remove(struct platform_device *dev) |
132 | { | 157 | { |
133 | struct serio *serio = platform_get_drvdata(dev); | 158 | struct serio *serio = platform_get_drvdata(dev); |
159 | struct rpckbd_data *rpckbd = serio->port_data; | ||
160 | |||
134 | serio_unregister_port(serio); | 161 | serio_unregister_port(serio); |
162 | kfree(rpckbd); | ||
163 | |||
135 | return 0; | 164 | return 0; |
136 | } | 165 | } |
137 | 166 | ||