^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) * OLPC serio driver for multiplexed input from Marvell MMP security processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2011-2013 One Laptop Per Child
^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) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Instead, the OLPC firmware runs a bit-banging PS/2 implementation on an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * otherwise-unused slow processor which is included in the Marvell MMP2/MMP3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * SoC, known as the "Security Processor" (SP) or "Wireless Trusted Module"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * (WTM). This firmware then reports its results via the WTM registers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * which we read from the Application Processor (AP, i.e. main CPU) in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * On the hardware side we have a PS/2 mouse and an AT keyboard, the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * is multiplexed through this system. We create a serio port for each one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * and demultiplex the data accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* WTM register offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SECURE_PROCESSOR_COMMAND 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define COMMAND_RETURN_STATUS 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define COMMAND_FIFO_STATUS 0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define PJ_RST_INTERRUPT 0xc8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PJ_INTERRUPT_MASK 0xcc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * The upper byte of SECURE_PROCESSOR_COMMAND and COMMAND_RETURN_STATUS is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * used to identify which port (device) is being talked to. The lower byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * is the data being sent/received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define PORT_MASK 0xff00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define DATA_MASK 0x00ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define PORT_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define KEYBOARD_PORT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define TOUCHPAD_PORT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* COMMAND_FIFO_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define CMD_CNTR_MASK 0x7 /* Number of pending/unprocessed commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MAX_PENDING_CMDS 4 /* from device specs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* PJ_RST_INTERRUPT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SP_COMMAND_COMPLETE_RESET 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* PJ_INTERRUPT_MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define INT_0 (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* COMMAND_FIFO_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CMD_STS_MASK 0x100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct olpc_apsp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct serio *kbio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct serio *padio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int open_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int olpc_apsp_write(struct serio *port, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct olpc_apsp *priv = port->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 which = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (port == priv->padio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) which = TOUCHPAD_PORT << PORT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) which = KEYBOARD_PORT << PORT_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dev_dbg(priv->dev, "olpc_apsp_write which=%x val=%x\n", which, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) for (i = 0; i < 50; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u32 sts = readl(priv->base + COMMAND_FIFO_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if ((sts & CMD_CNTR_MASK) < MAX_PENDING_CMDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) writel(which | val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) priv->base + SECURE_PROCESSOR_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* SP busy. This has not been seen in practice. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) dev_dbg(priv->dev, "olpc_apsp_write timeout, status=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) readl(priv->base + COMMAND_FIFO_STATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static irqreturn_t olpc_apsp_rx(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct olpc_apsp *priv = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned int w, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * Write 1 to PJ_RST_INTERRUPT to acknowledge and clear the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Write 0xff00 to SECURE_PROCESSOR_COMMAND.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) tmp = readl(priv->base + PJ_RST_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!(tmp & SP_COMMAND_COMPLETE_RESET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dev_warn(priv->dev, "spurious interrupt?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) w = readl(priv->base + COMMAND_RETURN_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dev_dbg(priv->dev, "olpc_apsp_rx %x\n", w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (w >> PORT_SHIFT == KEYBOARD_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) serio = priv->kbio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) serio = priv->padio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) serio_interrupt(serio, w & DATA_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* Ack and clear interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) writel(tmp | SP_COMMAND_COMPLETE_RESET, priv->base + PJ_RST_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) writel(PORT_MASK, priv->base + SECURE_PROCESSOR_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pm_wakeup_event(priv->dev, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int olpc_apsp_open(struct serio *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct olpc_apsp *priv = port->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned long l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (priv->open_count++ == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) l = readl(priv->base + COMMAND_FIFO_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!(l & CMD_STS_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) dev_err(priv->dev, "SP cannot accept commands.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Enable interrupt 0 by clearing its bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) tmp = readl(priv->base + PJ_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) writel(tmp & ~INT_0, priv->base + PJ_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static void olpc_apsp_close(struct serio *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct olpc_apsp *priv = port->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (--priv->open_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Disable interrupt 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) tmp = readl(priv->base + PJ_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int olpc_apsp_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct serio *kb_serio, *pad_serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct olpc_apsp *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) priv = devm_kzalloc(&pdev->dev, sizeof(struct olpc_apsp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) priv->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) priv->base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (IS_ERR(priv->base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dev_err(&pdev->dev, "Failed to map WTM registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return PTR_ERR(priv->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) priv->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (priv->irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return priv->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* KEYBOARD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (!kb_serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) kb_serio->id.type = SERIO_8042_XL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) kb_serio->write = olpc_apsp_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) kb_serio->open = olpc_apsp_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) kb_serio->close = olpc_apsp_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) kb_serio->port_data = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) kb_serio->dev.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) strlcpy(kb_serio->name, "sp keyboard", sizeof(kb_serio->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) strlcpy(kb_serio->phys, "sp/serio0", sizeof(kb_serio->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) priv->kbio = kb_serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) serio_register_port(kb_serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* TOUCHPAD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pad_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!pad_serio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) goto err_pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) pad_serio->id.type = SERIO_8042;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) pad_serio->write = olpc_apsp_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) pad_serio->open = olpc_apsp_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) pad_serio->close = olpc_apsp_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) pad_serio->port_data = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) pad_serio->dev.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) strlcpy(pad_serio->name, "sp touchpad", sizeof(pad_serio->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) strlcpy(pad_serio->phys, "sp/serio1", sizeof(pad_serio->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) priv->padio = pad_serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) serio_register_port(pad_serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) error = request_irq(priv->irq, olpc_apsp_rx, 0, "olpc-apsp", priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) dev_err(&pdev->dev, "Failed to request IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) goto err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) device_init_wakeup(priv->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) dev_dbg(&pdev->dev, "probed successfully.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) serio_unregister_port(pad_serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) err_pad:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) serio_unregister_port(kb_serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int olpc_apsp_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct olpc_apsp *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) free_irq(priv->irq, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) serio_unregister_port(priv->kbio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) serio_unregister_port(priv->padio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static const struct of_device_id olpc_apsp_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { .compatible = "olpc,ap-sp", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) MODULE_DEVICE_TABLE(of, olpc_apsp_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static struct platform_driver olpc_apsp_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .probe = olpc_apsp_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .remove = olpc_apsp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .name = "olpc-apsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .of_match_table = olpc_apsp_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) MODULE_DESCRIPTION("OLPC AP-SP serio driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) module_platform_driver(olpc_apsp_driver);