^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * SPEAr Keyboard Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Based on omap-keypad driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 ST Microelectronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Rajeev Kumar <rajeevkumar.linux@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/pm_wakeup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/platform_data/keyboard-spear.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Keyboard Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MODE_CTL_REG 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define STATUS_REG 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DATA_REG 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define INTR_MASK 0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Register Values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define NUM_ROWS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define NUM_COLS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MODE_CTL_PCLK_FREQ_SHIFT 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MODE_CTL_PCLK_FREQ_MSK 0x7F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MODE_CTL_KEYBOARD (0x2 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MODE_CTL_SCAN_RATE_10 (0x0 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MODE_CTL_SCAN_RATE_20 (0x1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MODE_CTL_SCAN_RATE_40 (0x2 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MODE_CTL_SCAN_RATE_80 (0x3 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MODE_CTL_KEYNUM_SHIFT 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MODE_CTL_START_SCAN (0x1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define STATUS_DATA_AVAIL (0x1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DATA_ROW_MASK 0xF0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define DATA_COLUMN_MASK 0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define ROW_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct spear_kbd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct input_dev *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void __iomem *io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int suspended_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned short last_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned short keycodes[NUM_ROWS * NUM_COLS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) bool rep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bool irq_wake_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 mode_ctl_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct spear_kbd *kbd = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct input_dev *input = kbd->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned int key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u32 sts, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) sts = readl_relaxed(kbd->io_base + STATUS_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!(sts & STATUS_DATA_AVAIL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (kbd->last_key != KEY_RESERVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) input_report_key(input, kbd->last_key, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) kbd->last_key = KEY_RESERVED;
^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) /* following reads active (row, col) pair */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) val = readl_relaxed(kbd->io_base + DATA_REG) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) (DATA_ROW_MASK | DATA_COLUMN_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) key = kbd->keycodes[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) input_event(input, EV_MSC, MSC_SCAN, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) input_report_key(input, key, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) input_sync(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) kbd->last_key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* clear interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) writel_relaxed(0, kbd->io_base + STATUS_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int spear_kbd_open(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct spear_kbd *kbd = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kbd->last_key = KEY_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) error = clk_enable(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* keyboard rate to be programmed is input clock (in MHz) - 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) val = clk_get_rate(kbd->clk) / 1000000 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) val = (val & MODE_CTL_PCLK_FREQ_MSK) << MODE_CTL_PCLK_FREQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* program keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) val = MODE_CTL_SCAN_RATE_80 | MODE_CTL_KEYBOARD | val |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) (kbd->mode << MODE_CTL_KEYNUM_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) writel_relaxed(1, kbd->io_base + STATUS_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* start key scan */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) val = readl_relaxed(kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) val |= MODE_CTL_START_SCAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void spear_kbd_close(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct spear_kbd *kbd = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* stop key scan */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) val = readl_relaxed(kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) val &= ~MODE_CTL_START_SCAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) clk_disable(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) kbd->last_key = KEY_RESERVED;
^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) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int spear_kbd_parse_dt(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct spear_kbd *kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u32 val, suspended_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dev_err(&pdev->dev, "Missing DT data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (of_property_read_bool(np, "autorepeat"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) kbd->rep = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (of_property_read_u32(np, "suspended_rate", &suspended_rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) kbd->suspended_rate = suspended_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) error = of_property_read_u32(np, "st,mode", &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) dev_err(&pdev->dev, "DT: Invalid or missing mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) kbd->mode = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static inline int spear_kbd_parse_dt(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct spear_kbd *kbd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static int spear_kbd_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct spear_kbd *kbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) kbd = devm_kzalloc(&pdev->dev, sizeof(*kbd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!kbd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dev_err(&pdev->dev, "not enough memory for driver data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) input_dev = devm_input_allocate_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (!input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dev_err(&pdev->dev, "unable to allocate input device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) kbd->input = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) kbd->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) error = spear_kbd_parse_dt(pdev, kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) kbd->mode = pdata->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) kbd->rep = pdata->rep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) kbd->suspended_rate = pdata->suspended_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) kbd->io_base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (IS_ERR(kbd->io_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return PTR_ERR(kbd->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) kbd->clk = devm_clk_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (IS_ERR(kbd->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return PTR_ERR(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) input_dev->name = "Spear Keyboard";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) input_dev->phys = "keyboard/input0";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) input_dev->id.bustype = BUS_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) input_dev->id.vendor = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) input_dev->id.product = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) input_dev->id.version = 0x0100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) input_dev->open = spear_kbd_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) input_dev->close = spear_kbd_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) error = matrix_keypad_build_keymap(keymap, NULL, NUM_ROWS, NUM_COLS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) kbd->keycodes, input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dev_err(&pdev->dev, "Failed to build keymap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (kbd->rep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) __set_bit(EV_REP, input_dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) input_set_capability(input_dev, EV_MSC, MSC_SCAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) input_set_drvdata(input_dev, kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) error = devm_request_irq(&pdev->dev, irq, spear_kbd_interrupt, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) "keyboard", kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) dev_err(&pdev->dev, "request_irq failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) error = clk_prepare(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) error = input_register_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dev_err(&pdev->dev, "Unable to register keyboard device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) clk_unprepare(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) device_init_wakeup(&pdev->dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) platform_set_drvdata(pdev, kbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int spear_kbd_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct spear_kbd *kbd = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) input_unregister_device(kbd->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) clk_unprepare(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int __maybe_unused spear_kbd_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct spear_kbd *kbd = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct input_dev *input_dev = kbd->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) unsigned int rate = 0, mode_ctl_reg, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) mutex_lock(&input_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* explicitly enable clock as we may program device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) clk_enable(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) mode_ctl_reg = readl_relaxed(kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (device_may_wakeup(&pdev->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!enable_irq_wake(kbd->irq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) kbd->irq_wake_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * reprogram the keyboard operating frequency as on some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * platform it may change during system suspended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (kbd->suspended_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) rate = kbd->suspended_rate / 1000000 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) rate = clk_get_rate(kbd->clk) / 1000000 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) val = mode_ctl_reg &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ~(MODE_CTL_PCLK_FREQ_MSK << MODE_CTL_PCLK_FREQ_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) val |= (rate & MODE_CTL_PCLK_FREQ_MSK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) << MODE_CTL_PCLK_FREQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (input_dev->users) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) writel_relaxed(mode_ctl_reg & ~MODE_CTL_START_SCAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) clk_disable(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* store current configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (input_dev->users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) kbd->mode_ctl_reg = mode_ctl_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* restore previous clk state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) clk_disable(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mutex_unlock(&input_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int __maybe_unused spear_kbd_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct spear_kbd *kbd = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct input_dev *input_dev = kbd->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) mutex_lock(&input_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (device_may_wakeup(&pdev->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (kbd->irq_wake_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) kbd->irq_wake_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) disable_irq_wake(kbd->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (input_dev->users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) clk_enable(kbd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* restore current configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (input_dev->users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) writel_relaxed(kbd->mode_ctl_reg, kbd->io_base + MODE_CTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) mutex_unlock(&input_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static const struct of_device_id spear_kbd_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) { .compatible = "st,spear300-kbd" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) MODULE_DEVICE_TABLE(of, spear_kbd_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static struct platform_driver spear_kbd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .probe = spear_kbd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .remove = spear_kbd_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .name = "keyboard",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .pm = &spear_kbd_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .of_match_table = of_match_ptr(spear_kbd_id_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) module_platform_driver(spear_kbd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) MODULE_AUTHOR("Rajeev Kumar");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) MODULE_DESCRIPTION("SPEAr Keyboard Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) MODULE_LICENSE("GPL");