Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
0004  */
0005 
0006 #include <linux/input/matrix_keypad.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/interrupt.h>
0009 #include <linux/io.h>
0010 #include <linux/delay.h>
0011 #include <linux/input.h>
0012 #include <linux/slab.h>
0013 #include <linux/clk.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 
0017 #define KEYPAD_SCAN_MODE    0x00
0018 #define KEYPAD_CNTL     0x04
0019 #define KEYPAD_INT      0x08
0020 #define KEYPAD_INTMSK       0x0C
0021 
0022 #define KEYPAD_DATA     0x10
0023 #define KEYPAD_GPIO     0x30
0024 
0025 #define KEYPAD_UNKNOWN_INT  0x40
0026 #define KEYPAD_UNKNOWN_INT_STS  0x44
0027 
0028 #define KEYPAD_BITMASK_COLS 11
0029 #define KEYPAD_BITMASK_ROWS 8
0030 
0031 struct nspire_keypad {
0032     void __iomem *reg_base;
0033     u32 int_mask;
0034 
0035     struct input_dev *input;
0036     struct clk *clk;
0037 
0038     struct matrix_keymap_data *keymap;
0039     int row_shift;
0040 
0041     /* Maximum delay estimated assuming 33MHz APB */
0042     u32 scan_interval;  /* In microseconds (~2000us max) */
0043     u32 row_delay;      /* In microseconds (~500us max) */
0044 
0045     u16 state[KEYPAD_BITMASK_ROWS];
0046 
0047     bool active_low;
0048 };
0049 
0050 static irqreturn_t nspire_keypad_irq(int irq, void *dev_id)
0051 {
0052     struct nspire_keypad *keypad = dev_id;
0053     struct input_dev *input = keypad->input;
0054     unsigned short *keymap = input->keycode;
0055     unsigned int code;
0056     int row, col;
0057     u32 int_sts;
0058     u16 state[8];
0059     u16 bits, changed;
0060 
0061     int_sts = readl(keypad->reg_base + KEYPAD_INT) & keypad->int_mask;
0062     if (!int_sts)
0063         return IRQ_NONE;
0064 
0065     memcpy_fromio(state, keypad->reg_base + KEYPAD_DATA, sizeof(state));
0066 
0067     for (row = 0; row < KEYPAD_BITMASK_ROWS; row++) {
0068         bits = state[row];
0069         if (keypad->active_low)
0070             bits = ~bits;
0071 
0072         changed = bits ^ keypad->state[row];
0073         if (!changed)
0074             continue;
0075 
0076         keypad->state[row] = bits;
0077 
0078         for (col = 0; col < KEYPAD_BITMASK_COLS; col++) {
0079             if (!(changed & (1U << col)))
0080                 continue;
0081 
0082             code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
0083             input_event(input, EV_MSC, MSC_SCAN, code);
0084             input_report_key(input, keymap[code],
0085                      bits & (1U << col));
0086         }
0087     }
0088 
0089     input_sync(input);
0090 
0091     writel(0x3, keypad->reg_base + KEYPAD_INT);
0092 
0093     return IRQ_HANDLED;
0094 }
0095 
0096 static int nspire_keypad_open(struct input_dev *input)
0097 {
0098     struct nspire_keypad *keypad = input_get_drvdata(input);
0099     unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles;
0100     int error;
0101 
0102     error = clk_prepare_enable(keypad->clk);
0103     if (error)
0104         return error;
0105 
0106     cycles_per_us = (clk_get_rate(keypad->clk) / 1000000);
0107     if (cycles_per_us == 0)
0108         cycles_per_us = 1;
0109 
0110     delay_cycles = cycles_per_us * keypad->scan_interval;
0111     WARN_ON(delay_cycles >= (1 << 16)); /* Overflow */
0112     delay_cycles &= 0xffff;
0113 
0114     row_delay_cycles = cycles_per_us * keypad->row_delay;
0115     WARN_ON(row_delay_cycles >= (1 << 14)); /* Overflow */
0116     row_delay_cycles &= 0x3fff;
0117 
0118     val |= 3 << 0; /* Set scan mode to 3 (continuous scan) */
0119     val |= row_delay_cycles << 2; /* Delay between scanning each row */
0120     val |= delay_cycles << 16; /* Delay between scans */
0121     writel(val, keypad->reg_base + KEYPAD_SCAN_MODE);
0122 
0123     val = (KEYPAD_BITMASK_ROWS & 0xff) | (KEYPAD_BITMASK_COLS & 0xff)<<8;
0124     writel(val, keypad->reg_base + KEYPAD_CNTL);
0125 
0126     /* Enable interrupts */
0127     keypad->int_mask = 1 << 1;
0128     writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK);
0129 
0130     return 0;
0131 }
0132 
0133 static void nspire_keypad_close(struct input_dev *input)
0134 {
0135     struct nspire_keypad *keypad = input_get_drvdata(input);
0136 
0137     /* Disable interrupts */
0138     writel(0, keypad->reg_base + KEYPAD_INTMSK);
0139     /* Acknowledge existing interrupts */
0140     writel(~0, keypad->reg_base + KEYPAD_INT);
0141 
0142     clk_disable_unprepare(keypad->clk);
0143 }
0144 
0145 static int nspire_keypad_probe(struct platform_device *pdev)
0146 {
0147     const struct device_node *of_node = pdev->dev.of_node;
0148     struct nspire_keypad *keypad;
0149     struct input_dev *input;
0150     struct resource *res;
0151     int irq;
0152     int error;
0153 
0154     irq = platform_get_irq(pdev, 0);
0155     if (irq < 0)
0156         return -EINVAL;
0157 
0158     keypad = devm_kzalloc(&pdev->dev, sizeof(struct nspire_keypad),
0159                   GFP_KERNEL);
0160     if (!keypad) {
0161         dev_err(&pdev->dev, "failed to allocate keypad memory\n");
0162         return -ENOMEM;
0163     }
0164 
0165     keypad->row_shift = get_count_order(KEYPAD_BITMASK_COLS);
0166 
0167     error = of_property_read_u32(of_node, "scan-interval",
0168                      &keypad->scan_interval);
0169     if (error) {
0170         dev_err(&pdev->dev, "failed to get scan-interval\n");
0171         return error;
0172     }
0173 
0174     error = of_property_read_u32(of_node, "row-delay",
0175                      &keypad->row_delay);
0176     if (error) {
0177         dev_err(&pdev->dev, "failed to get row-delay\n");
0178         return error;
0179     }
0180 
0181     keypad->active_low = of_property_read_bool(of_node, "active-low");
0182 
0183     keypad->clk = devm_clk_get(&pdev->dev, NULL);
0184     if (IS_ERR(keypad->clk)) {
0185         dev_err(&pdev->dev, "unable to get clock\n");
0186         return PTR_ERR(keypad->clk);
0187     }
0188 
0189     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0190     keypad->reg_base = devm_ioremap_resource(&pdev->dev, res);
0191     if (IS_ERR(keypad->reg_base))
0192         return PTR_ERR(keypad->reg_base);
0193 
0194     keypad->input = input = devm_input_allocate_device(&pdev->dev);
0195     if (!input) {
0196         dev_err(&pdev->dev, "failed to allocate input device\n");
0197         return -ENOMEM;
0198     }
0199 
0200     error = clk_prepare_enable(keypad->clk);
0201     if (error) {
0202         dev_err(&pdev->dev, "failed to enable clock\n");
0203         return error;
0204     }
0205 
0206     /* Disable interrupts */
0207     writel(0, keypad->reg_base + KEYPAD_INTMSK);
0208     /* Acknowledge existing interrupts */
0209     writel(~0, keypad->reg_base + KEYPAD_INT);
0210 
0211     /* Disable GPIO interrupts to prevent hanging on touchpad */
0212     /* Possibly used to detect touchpad events */
0213     writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT);
0214     /* Acknowledge existing GPIO interrupts */
0215     writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS);
0216 
0217     clk_disable_unprepare(keypad->clk);
0218 
0219     input_set_drvdata(input, keypad);
0220 
0221     input->id.bustype = BUS_HOST;
0222     input->name = "nspire-keypad";
0223     input->open = nspire_keypad_open;
0224     input->close = nspire_keypad_close;
0225 
0226     __set_bit(EV_KEY, input->evbit);
0227     __set_bit(EV_REP, input->evbit);
0228     input_set_capability(input, EV_MSC, MSC_SCAN);
0229 
0230     error = matrix_keypad_build_keymap(NULL, NULL,
0231                        KEYPAD_BITMASK_ROWS,
0232                        KEYPAD_BITMASK_COLS,
0233                        NULL, input);
0234     if (error) {
0235         dev_err(&pdev->dev, "building keymap failed\n");
0236         return error;
0237     }
0238 
0239     error = devm_request_irq(&pdev->dev, irq, nspire_keypad_irq, 0,
0240                  "nspire_keypad", keypad);
0241     if (error) {
0242         dev_err(&pdev->dev, "allocate irq %d failed\n", irq);
0243         return error;
0244     }
0245 
0246     error = input_register_device(input);
0247     if (error) {
0248         dev_err(&pdev->dev,
0249             "unable to register input device: %d\n", error);
0250         return error;
0251     }
0252 
0253     dev_dbg(&pdev->dev,
0254         "TI-NSPIRE keypad at %pR (scan_interval=%uus, row_delay=%uus%s)\n",
0255         res, keypad->row_delay, keypad->scan_interval,
0256         keypad->active_low ? ", active_low" : "");
0257 
0258     return 0;
0259 }
0260 
0261 static const struct of_device_id nspire_keypad_dt_match[] = {
0262     { .compatible = "ti,nspire-keypad" },
0263     { },
0264 };
0265 MODULE_DEVICE_TABLE(of, nspire_keypad_dt_match);
0266 
0267 static struct platform_driver nspire_keypad_driver = {
0268     .driver = {
0269         .name = "nspire-keypad",
0270         .of_match_table = nspire_keypad_dt_match,
0271     },
0272     .probe = nspire_keypad_probe,
0273 };
0274 
0275 module_platform_driver(nspire_keypad_driver);
0276 
0277 MODULE_LICENSE("GPL");
0278 MODULE_DESCRIPTION("TI-NSPIRE Keypad Driver");