drivers/input/serio/ioc3kbd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/input/serio/ioc3kbd.c
Extension
.c
Size
4767 bytes
Lines
222
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 ioc3kbd_data {
	struct ioc3_serioregs __iomem *regs;
	struct serio *kbd, *aux;
	bool kbd_exists, aux_exists;
	int irq;
};

static int ioc3kbd_wait(struct ioc3_serioregs __iomem *regs, u32 mask)
{
	unsigned long timeout = 0;

	while ((readl(&regs->km_csr) & mask) && (timeout < 250)) {
		udelay(50);
		timeout++;
	}
	return (timeout >= 250) ? -ETIMEDOUT : 0;
}

static int ioc3kbd_write(struct serio *dev, u8 val)
{
	struct ioc3kbd_data *d = dev->port_data;
	int ret;

	ret = ioc3kbd_wait(d->regs, KM_CSR_K_WRT_PEND);
	if (ret)
		return ret;

	writel(val, &d->regs->k_wd);

	return 0;
}

static int ioc3kbd_start(struct serio *dev)
{
	struct ioc3kbd_data *d = dev->port_data;

	d->kbd_exists = true;
	return 0;
}

static void ioc3kbd_stop(struct serio *dev)
{
	struct ioc3kbd_data *d = dev->port_data;

	d->kbd_exists = false;
}

static int ioc3aux_write(struct serio *dev, u8 val)
{
	struct ioc3kbd_data *d = dev->port_data;
	int ret;

	ret = ioc3kbd_wait(d->regs, KM_CSR_M_WRT_PEND);
	if (ret)
		return ret;

	writel(val, &d->regs->m_wd);

	return 0;
}

static int ioc3aux_start(struct serio *dev)
{
	struct ioc3kbd_data *d = dev->port_data;

	d->aux_exists = true;
	return 0;
}

static void ioc3aux_stop(struct serio *dev)
{
	struct ioc3kbd_data *d = dev->port_data;

	d->aux_exists = false;
}

static void ioc3kbd_process_data(struct serio *dev, u32 data)
{
	if (data & KM_RD_VALID_0)
		serio_interrupt(dev, (data >> KM_RD_DATA_0_SHIFT) & 0xff, 0);
	if (data & KM_RD_VALID_1)
		serio_interrupt(dev, (data >> KM_RD_DATA_1_SHIFT) & 0xff, 0);
	if (data & KM_RD_VALID_2)
		serio_interrupt(dev, (data >> KM_RD_DATA_2_SHIFT) & 0xff, 0);
}

static irqreturn_t ioc3kbd_intr(int itq, void *dev_id)
{
	struct ioc3kbd_data *d = dev_id;
	u32 data_k, data_m;

Annotation

Implementation Notes