^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2000-2001 Vojtech Pavlik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2002 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Acorn RiscPC PS/2 keyboard controller driver for Linux/ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/hardware/iomd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MODULE_AUTHOR("Vojtech Pavlik, Russell King");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) MODULE_ALIAS("platform:kart");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct rpckbd_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int tx_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int rx_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int rpckbd_write(struct serio *port, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) iomd_writeb(val, IOMD_KARTTX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static irqreturn_t rpckbd_rx(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct serio *port = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned int byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int handled = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) while (iomd_readb(IOMD_KCTRL) & (1 << 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) byte = iomd_readb(IOMD_KARTRX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) serio_interrupt(port, byte, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) handled = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return handled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static irqreturn_t rpckbd_tx(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int rpckbd_open(struct serio *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct rpckbd_data *rpckbd = port->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Reset the keyboard state machine. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) iomd_writeb(0, IOMD_KCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) iomd_writeb(8, IOMD_KCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) iomd_readb(IOMD_KARTRX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (request_irq(rpckbd->rx_irq, rpckbd_rx, 0, "rpckbd", port) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) printk(KERN_ERR "rpckbd.c: Could not allocate keyboard receive IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (request_irq(rpckbd->tx_irq, rpckbd_tx, 0, "rpckbd", port) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) free_irq(rpckbd->rx_irq, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void rpckbd_close(struct serio *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct rpckbd_data *rpckbd = port->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) free_irq(rpckbd->rx_irq, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) free_irq(rpckbd->tx_irq, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Allocate and initialize serio structure for subsequent registration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * with serio core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int rpckbd_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct rpckbd_data *rpckbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int tx_irq, rx_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) rx_irq = platform_get_irq(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (rx_irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return rx_irq < 0 ? rx_irq : -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) tx_irq = platform_get_irq(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (tx_irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return tx_irq < 0 ? tx_irq : -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) rpckbd = kzalloc(sizeof(*rpckbd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!serio || !rpckbd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) kfree(rpckbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) kfree(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) rpckbd->rx_irq = rx_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) rpckbd->tx_irq = tx_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) serio->id.type = SERIO_8042;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) serio->write = rpckbd_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) serio->open = rpckbd_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) serio->close = rpckbd_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) serio->dev.parent = &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) serio->port_data = rpckbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) platform_set_drvdata(dev, serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) serio_register_port(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int rpckbd_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct serio *serio = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct rpckbd_data *rpckbd = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) serio_unregister_port(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) kfree(rpckbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static struct platform_driver rpckbd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .probe = rpckbd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .remove = rpckbd_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .name = "kart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) module_platform_driver(rpckbd_driver);