drivers/input/keyboard/spear-keyboard.c
Source file repositories/reference/linux-study-clean/drivers/input/keyboard/spear-keyboard.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/input/keyboard/spear-keyboard.c- Extension
.c- Size
- 8130 bytes
- Lines
- 328
- 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.
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/errno.hlinux/interrupt.hlinux/input.hlinux/input/matrix_keypad.hlinux/io.hlinux/irq.hlinux/kernel.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/slab.hlinux/types.h
Detected Declarations
struct spear_kbdfunction spear_kbd_interruptfunction spear_kbd_openfunction spear_kbd_closefunction spear_kbd_probefunction spear_kbd_suspendfunction spear_kbd_resume
Annotated Snippet
struct spear_kbd {
struct input_dev *input;
void __iomem *io_base;
struct clk *clk;
unsigned int irq;
u32 mode;
u32 suspended_rate;
u32 mode_ctl_reg;
unsigned short last_key;
unsigned short keycodes[NUM_ROWS * NUM_COLS];
bool irq_wake_enabled;
};
static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id)
{
struct spear_kbd *kbd = dev_id;
struct input_dev *input = kbd->input;
unsigned int key;
u32 sts, val;
sts = readl_relaxed(kbd->io_base + STATUS_REG);
if (!(sts & STATUS_DATA_AVAIL))
return IRQ_NONE;
if (kbd->last_key != KEY_RESERVED) {
input_report_key(input, kbd->last_key, 0);
kbd->last_key = KEY_RESERVED;
}
/* following reads active (row, col) pair */
val = readl_relaxed(kbd->io_base + DATA_REG) &
(DATA_ROW_MASK | DATA_COLUMN_MASK);
key = kbd->keycodes[val];
input_event(input, EV_MSC, MSC_SCAN, val);
input_report_key(input, key, 1);
input_sync(input);
kbd->last_key = key;
/* clear interrupt */
writel_relaxed(0, kbd->io_base + STATUS_REG);
return IRQ_HANDLED;
}
static int spear_kbd_open(struct input_dev *dev)
{
struct spear_kbd *kbd = input_get_drvdata(dev);
int error;
u32 val;
kbd->last_key = KEY_RESERVED;
error = clk_enable(kbd->clk);
if (error)
return error;
/* keyboard rate to be programmed is input clock (in MHz) - 1 */
val = clk_get_rate(kbd->clk) / 1000000 - 1;
val = (val & MODE_CTL_PCLK_FREQ_MSK) << MODE_CTL_PCLK_FREQ_SHIFT;
/* program keyboard */
val = MODE_CTL_SCAN_RATE_80 | MODE_CTL_KEYBOARD | val |
(kbd->mode << MODE_CTL_KEYNUM_SHIFT);
writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
writel_relaxed(1, kbd->io_base + STATUS_REG);
/* start key scan */
val = readl_relaxed(kbd->io_base + MODE_CTL_REG);
val |= MODE_CTL_START_SCAN;
writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
return 0;
}
static void spear_kbd_close(struct input_dev *dev)
{
struct spear_kbd *kbd = input_get_drvdata(dev);
u32 val;
/* stop key scan */
val = readl_relaxed(kbd->io_base + MODE_CTL_REG);
val &= ~MODE_CTL_START_SCAN;
writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
clk_disable(kbd->clk);
kbd->last_key = KEY_RESERVED;
}
Annotation
- Immediate include surface: `linux/clk.h`, `linux/errno.h`, `linux/interrupt.h`, `linux/input.h`, `linux/input/matrix_keypad.h`, `linux/io.h`, `linux/irq.h`, `linux/kernel.h`.
- Detected declarations: `struct spear_kbd`, `function spear_kbd_interrupt`, `function spear_kbd_open`, `function spear_kbd_close`, `function spear_kbd_probe`, `function spear_kbd_suspend`, `function spear_kbd_resume`.
- Atlas domain: Driver Families / drivers/input.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.