Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * linux/drivers/input/serio/pcips2.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 2003 Russell King, All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  I'm not sure if this is a generic PS/2 PCI interface or specific to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  the Mobility Electronics docking station.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/pci.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/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define PS2_CTRL		(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define PS2_STATUS		(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define PS2_DATA		(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define PS2_CTRL_CLK		(1<<0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define PS2_CTRL_DAT		(1<<1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define PS2_CTRL_TXIRQ		(1<<2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define PS2_CTRL_ENABLE		(1<<3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define PS2_CTRL_RXIRQ		(1<<4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define PS2_STAT_CLK		(1<<0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define PS2_STAT_DAT		(1<<1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define PS2_STAT_PARITY		(1<<2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define PS2_STAT_RXFULL		(1<<5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define PS2_STAT_TXBUSY		(1<<6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define PS2_STAT_TXEMPTY	(1<<7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) struct pcips2_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct serio	*io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	unsigned int	base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct pci_dev	*dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static int pcips2_write(struct serio *io, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	struct pcips2_data *ps2if = io->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	unsigned int stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		stat = inb(ps2if->base + PS2_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	} while (!(stat & PS2_STAT_TXEMPTY));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	outb(val, ps2if->base + PS2_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) static irqreturn_t pcips2_interrupt(int irq, void *devid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	struct pcips2_data *ps2if = devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	unsigned char status, scancode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		unsigned int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		status = inb(ps2if->base + PS2_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		if (!(status & PS2_STAT_RXFULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		scancode = inb(ps2if->base + PS2_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		if (status == 0xff && scancode == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		if (hweight8(scancode) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			flag ^= SERIO_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		serio_interrupt(ps2if->io, scancode, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	} while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	return IRQ_RETVAL(handled);
^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) static void pcips2_flush_input(struct pcips2_data *ps2if)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	unsigned char status, scancode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		status = inb(ps2if->base + PS2_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		if (!(status & PS2_STAT_RXFULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		scancode = inb(ps2if->base + PS2_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		if (status == 0xff && scancode == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	} while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static int pcips2_open(struct serio *io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	struct pcips2_data *ps2if = io->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	int ret, val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	outb(PS2_CTRL_ENABLE, ps2if->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	pcips2_flush_input(ps2if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	ret = request_irq(ps2if->dev->irq, pcips2_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			  "pcips2", ps2if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		val = PS2_CTRL_ENABLE | PS2_CTRL_RXIRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	outb(val, ps2if->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	return ret;
^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) static void pcips2_close(struct serio *io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	struct pcips2_data *ps2if = io->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	outb(0, ps2if->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	free_irq(ps2if->dev->irq, ps2if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	struct pcips2_data *ps2if;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	ret = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	ret = pci_request_regions(dev, "pcips2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		goto disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	ps2if = kzalloc(sizeof(struct pcips2_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if (!ps2if || !serio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		goto release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	}
^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) 	serio->id.type		= SERIO_8042;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	serio->write		= pcips2_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	serio->open		= pcips2_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	serio->close		= pcips2_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	serio->port_data	= ps2if;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	serio->dev.parent	= &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	ps2if->io		= serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	ps2if->dev		= dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	ps2if->base		= pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	pci_set_drvdata(dev, ps2if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	serio_register_port(ps2if->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	kfree(ps2if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	kfree(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void pcips2_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	struct pcips2_data *ps2if = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	serio_unregister_port(ps2if->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	kfree(ps2if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static const struct pci_device_id pcips2_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		.vendor		= 0x14f2,	/* MOBILITY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		.device		= 0x0123,	/* Keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		.subvendor	= PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		.subdevice	= PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		.class		= PCI_CLASS_INPUT_KEYBOARD << 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		.class_mask	= 0xffff00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		.vendor		= 0x14f2,	/* MOBILITY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		.device		= 0x0124,	/* Mouse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		.subvendor	= PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		.subdevice	= PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		.class		= PCI_CLASS_INPUT_MOUSE << 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		.class_mask	= 0xffff00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	{ 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) MODULE_DEVICE_TABLE(pci, pcips2_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static struct pci_driver pcips2_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	.name			= "pcips2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	.id_table		= pcips2_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	.probe			= pcips2_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	.remove			= pcips2_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) module_pci_driver(pcips2_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver");