drivers/input/serio/arc_ps2.c

Source file repositories/reference/linux-study-clean/drivers/input/serio/arc_ps2.c

File Facts

System
Linux kernel
Corpus path
drivers/input/serio/arc_ps2.c
Extension
.c
Size
6237 bytes
Lines
270
Domain
Driver Families
Bucket
drivers/input
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct arc_ps2_port {
	void __iomem *data_addr;
	void __iomem *status_addr;
	struct serio *io;
};

struct arc_ps2_data {
	struct arc_ps2_port port[ARC_PS2_PORTS];
	void __iomem *addr;
	unsigned int frame_error;
	unsigned int buf_overflow;
	unsigned int total_int;
};

static void arc_ps2_check_rx(struct arc_ps2_data *arc_ps2,
			     struct arc_ps2_port *port)
{
	unsigned int timeout = 1000;
	unsigned int flag, status;
	unsigned char data;

	do {
		status = ioread32(port->status_addr);
		if (!(status & PS2_STAT_RX_VAL))
			return;

		data = ioread32(port->data_addr) & 0xff;

		flag = 0;
		arc_ps2->total_int++;
		if (status & PS2_STAT_RX_FRM_ERR) {
			arc_ps2->frame_error++;
			flag |= SERIO_PARITY;
		} else if (status & PS2_STAT_RX_BUF_OVER) {
			arc_ps2->buf_overflow++;
			flag |= SERIO_FRAME;
		}

		serio_interrupt(port->io, data, flag);
	} while (--timeout);

	dev_err(&port->io->dev, "PS/2 hardware stuck\n");
}

static irqreturn_t arc_ps2_interrupt(int irq, void *dev)
{
	struct arc_ps2_data *arc_ps2 = dev;
	int i;

	for (i = 0; i < ARC_PS2_PORTS; i++)
		arc_ps2_check_rx(arc_ps2, &arc_ps2->port[i]);

	return IRQ_HANDLED;
}

static int arc_ps2_write(struct serio *io, unsigned char val)
{
	unsigned status;
	struct arc_ps2_port *port = io->port_data;
	int timeout = STAT_TIMEOUT;

	do {
		status = ioread32(port->status_addr);
		cpu_relax();

		if (status & PS2_STAT_TX_ISNOT_FUL) {
			iowrite32(val & 0xff, port->data_addr);
			return 0;
		}

	} while (--timeout);

	dev_err(&io->dev, "write timeout\n");
	return -ETIMEDOUT;
}

static int arc_ps2_open(struct serio *io)
{
	struct arc_ps2_port *port = io->port_data;

	iowrite32(PS2_STAT_RX_INT_EN, port->status_addr);

	return 0;
}

static void arc_ps2_close(struct serio *io)
{
	struct arc_ps2_port *port = io->port_data;

	iowrite32(ioread32(port->status_addr) & ~PS2_STAT_RX_INT_EN,

Annotation

Implementation Notes