1 /* 2 * Copyright (c) 2000-2001 Vojtech Pavlik 3 * Copyright (c) 2002 Russell King 4 */ 5 6 /* 7 * Acorn RiscPC PS/2 keyboard controller driver for Linux/ARM 8 */ 9 10 /* 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 #include <linux/module.h> 27 #include <linux/interrupt.h> 28 #include <linux/serio.h> 29 #include <linux/err.h> 30 #include <linux/platform_device.h> 31 #include <linux/io.h> 32 #include <linux/slab.h> 33 34 #include <mach/hardware.h> 35 #include <asm/hardware/iomd.h> 36 37 MODULE_AUTHOR("Vojtech Pavlik, Russell King"); 38 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver"); 39 MODULE_LICENSE("GPL"); 40 MODULE_ALIAS("platform:kart"); 41 42 struct rpckbd_data { 43 int tx_irq; 44 int rx_irq; 45 }; 46 47 static int rpckbd_write(struct serio *port, unsigned char val) 48 { 49 while (!(iomd_readb(IOMD_KCTRL) & (1 << 7))) 50 cpu_relax(); 51 52 iomd_writeb(val, IOMD_KARTTX); 53 54 return 0; 55 } 56 57 static irqreturn_t rpckbd_rx(int irq, void *dev_id) 58 { 59 struct serio *port = dev_id; 60 unsigned int byte; 61 int handled = IRQ_NONE; 62 63 while (iomd_readb(IOMD_KCTRL) & (1 << 5)) { 64 byte = iomd_readb(IOMD_KARTRX); 65 66 serio_interrupt(port, byte, 0); 67 handled = IRQ_HANDLED; 68 } 69 return handled; 70 } 71 72 static irqreturn_t rpckbd_tx(int irq, void *dev_id) 73 { 74 return IRQ_HANDLED; 75 } 76 77 static int rpckbd_open(struct serio *port) 78 { 79 struct rpckbd_data *rpckbd = port->port_data; 80 81 /* Reset the keyboard state machine. */ 82 iomd_writeb(0, IOMD_KCTRL); 83 iomd_writeb(8, IOMD_KCTRL); 84 iomd_readb(IOMD_KARTRX); 85 86 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"); 88 return -EBUSY; 89 } 90 91 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"); 93 free_irq(rpckbd->rx_irq, port); 94 return -EBUSY; 95 } 96 97 return 0; 98 } 99 100 static void rpckbd_close(struct serio *port) 101 { 102 struct rpckbd_data *rpckbd = port->port_data; 103 104 free_irq(rpckbd->rx_irq, port); 105 free_irq(rpckbd->tx_irq, port); 106 } 107 108 /* 109 * Allocate and initialize serio structure for subsequent registration 110 * with serio core. 111 */ 112 static int rpckbd_probe(struct platform_device *dev) 113 { 114 struct rpckbd_data *rpckbd; 115 struct serio *serio; 116 int tx_irq, rx_irq; 117 118 rx_irq = platform_get_irq(dev, 0); 119 if (rx_irq <= 0) 120 return rx_irq < 0 ? rx_irq : -ENXIO; 121 122 tx_irq = platform_get_irq(dev, 1); 123 if (tx_irq <= 0) 124 return tx_irq < 0 ? tx_irq : -ENXIO; 125 126 serio = kzalloc(sizeof(struct serio), GFP_KERNEL); 127 rpckbd = kzalloc(sizeof(*rpckbd), GFP_KERNEL); 128 if (!serio || !rpckbd) { 129 kfree(rpckbd); 130 kfree(serio); 131 return -ENOMEM; 132 } 133 134 rpckbd->rx_irq = rx_irq; 135 rpckbd->tx_irq = tx_irq; 136 137 serio->id.type = SERIO_8042; 138 serio->write = rpckbd_write; 139 serio->open = rpckbd_open; 140 serio->close = rpckbd_close; 141 serio->dev.parent = &dev->dev; 142 serio->port_data = rpckbd; 143 strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name)); 144 strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys)); 145 146 platform_set_drvdata(dev, serio); 147 serio_register_port(serio); 148 return 0; 149 } 150 151 static int rpckbd_remove(struct platform_device *dev) 152 { 153 struct serio *serio = platform_get_drvdata(dev); 154 struct rpckbd_data *rpckbd = serio->port_data; 155 156 serio_unregister_port(serio); 157 kfree(rpckbd); 158 159 return 0; 160 } 161 162 static struct platform_driver rpckbd_driver = { 163 .probe = rpckbd_probe, 164 .remove = rpckbd_remove, 165 .driver = { 166 .name = "kart", 167 }, 168 }; 169 module_platform_driver(rpckbd_driver); 170