Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * NXP LPC32xx SoC Key Scan Interface
0004  *
0005  * Authors:
0006  *    Kevin Wells <kevin.wells@nxp.com>
0007  *    Roland Stigge <stigge@antcom.de>
0008  *
0009  * Copyright (C) 2010 NXP Semiconductors
0010  * Copyright (C) 2012 Roland Stigge
0011  *
0012  * This controller supports square key matrices from 1x1 up to 8x8
0013  */
0014 
0015 #include <linux/module.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/slab.h>
0018 #include <linux/irq.h>
0019 #include <linux/pm.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/input.h>
0022 #include <linux/clk.h>
0023 #include <linux/io.h>
0024 #include <linux/of.h>
0025 #include <linux/input/matrix_keypad.h>
0026 
0027 #define DRV_NAME                "lpc32xx_keys"
0028 
0029 /*
0030  * Key scanner register offsets
0031  */
0032 #define LPC32XX_KS_DEB(x)           ((x) + 0x00)
0033 #define LPC32XX_KS_STATE_COND(x)        ((x) + 0x04)
0034 #define LPC32XX_KS_IRQ(x)           ((x) + 0x08)
0035 #define LPC32XX_KS_SCAN_CTL(x)          ((x) + 0x0C)
0036 #define LPC32XX_KS_FAST_TST(x)          ((x) + 0x10)
0037 #define LPC32XX_KS_MATRIX_DIM(x)        ((x) + 0x14) /* 1..8 */
0038 #define LPC32XX_KS_DATA(x, y)           ((x) + 0x40 + ((y) << 2))
0039 
0040 #define LPC32XX_KSCAN_DEB_NUM_DEB_PASS(n)   ((n) & 0xFF)
0041 
0042 #define LPC32XX_KSCAN_SCOND_IN_IDLE     0x0
0043 #define LPC32XX_KSCAN_SCOND_IN_SCANONCE     0x1
0044 #define LPC32XX_KSCAN_SCOND_IN_IRQGEN       0x2
0045 #define LPC32XX_KSCAN_SCOND_IN_SCAN_MATRIX  0x3
0046 
0047 #define LPC32XX_KSCAN_IRQ_PENDING_CLR       0x1
0048 
0049 #define LPC32XX_KSCAN_SCTRL_SCAN_DELAY(n)   ((n) & 0xFF)
0050 
0051 #define LPC32XX_KSCAN_FTST_FORCESCANONCE    0x1
0052 #define LPC32XX_KSCAN_FTST_USE32K_CLK       0x2
0053 
0054 #define LPC32XX_KSCAN_MSEL_SELECT(n)        ((n) & 0xF)
0055 
0056 struct lpc32xx_kscan_drv {
0057     struct input_dev *input;
0058     struct clk *clk;
0059     void __iomem *kscan_base;
0060     unsigned int irq;
0061 
0062     u32 matrix_sz;      /* Size of matrix in XxY, ie. 3 = 3x3 */
0063     u32 deb_clks;       /* Debounce clocks (based on 32KHz clock) */
0064     u32 scan_delay;     /* Scan delay (based on 32KHz clock) */
0065 
0066     unsigned short *keymap; /* Pointer to key map for the scan matrix */
0067     unsigned int row_shift;
0068 
0069     u8 lastkeystates[8];
0070 };
0071 
0072 static void lpc32xx_mod_states(struct lpc32xx_kscan_drv *kscandat, int col)
0073 {
0074     struct input_dev *input = kscandat->input;
0075     unsigned row, changed, scancode, keycode;
0076     u8 key;
0077 
0078     key = readl(LPC32XX_KS_DATA(kscandat->kscan_base, col));
0079     changed = key ^ kscandat->lastkeystates[col];
0080     kscandat->lastkeystates[col] = key;
0081 
0082     for (row = 0; changed; row++, changed >>= 1) {
0083         if (changed & 1) {
0084             /* Key state changed, signal an event */
0085             scancode = MATRIX_SCAN_CODE(row, col,
0086                             kscandat->row_shift);
0087             keycode = kscandat->keymap[scancode];
0088             input_event(input, EV_MSC, MSC_SCAN, scancode);
0089             input_report_key(input, keycode, key & (1 << row));
0090         }
0091     }
0092 }
0093 
0094 static irqreturn_t lpc32xx_kscan_irq(int irq, void *dev_id)
0095 {
0096     struct lpc32xx_kscan_drv *kscandat = dev_id;
0097     int i;
0098 
0099     for (i = 0; i < kscandat->matrix_sz; i++)
0100         lpc32xx_mod_states(kscandat, i);
0101 
0102     writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
0103 
0104     input_sync(kscandat->input);
0105 
0106     return IRQ_HANDLED;
0107 }
0108 
0109 static int lpc32xx_kscan_open(struct input_dev *dev)
0110 {
0111     struct lpc32xx_kscan_drv *kscandat = input_get_drvdata(dev);
0112     int error;
0113 
0114     error = clk_prepare_enable(kscandat->clk);
0115     if (error)
0116         return error;
0117 
0118     writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
0119 
0120     return 0;
0121 }
0122 
0123 static void lpc32xx_kscan_close(struct input_dev *dev)
0124 {
0125     struct lpc32xx_kscan_drv *kscandat = input_get_drvdata(dev);
0126 
0127     writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
0128     clk_disable_unprepare(kscandat->clk);
0129 }
0130 
0131 static int lpc32xx_parse_dt(struct device *dev,
0132                       struct lpc32xx_kscan_drv *kscandat)
0133 {
0134     struct device_node *np = dev->of_node;
0135     u32 rows = 0, columns = 0;
0136     int err;
0137 
0138     err = matrix_keypad_parse_properties(dev, &rows, &columns);
0139     if (err)
0140         return err;
0141     if (rows != columns) {
0142         dev_err(dev, "rows and columns must be equal!\n");
0143         return -EINVAL;
0144     }
0145 
0146     kscandat->matrix_sz = rows;
0147     kscandat->row_shift = get_count_order(columns);
0148 
0149     of_property_read_u32(np, "nxp,debounce-delay-ms", &kscandat->deb_clks);
0150     of_property_read_u32(np, "nxp,scan-delay-ms", &kscandat->scan_delay);
0151     if (!kscandat->deb_clks || !kscandat->scan_delay) {
0152         dev_err(dev, "debounce or scan delay not specified\n");
0153         return -EINVAL;
0154     }
0155 
0156     return 0;
0157 }
0158 
0159 static int lpc32xx_kscan_probe(struct platform_device *pdev)
0160 {
0161     struct lpc32xx_kscan_drv *kscandat;
0162     struct input_dev *input;
0163     struct resource *res;
0164     size_t keymap_size;
0165     int error;
0166     int irq;
0167 
0168     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0169     if (!res) {
0170         dev_err(&pdev->dev, "failed to get platform I/O memory\n");
0171         return -EINVAL;
0172     }
0173 
0174     irq = platform_get_irq(pdev, 0);
0175     if (irq < 0)
0176         return -EINVAL;
0177 
0178     kscandat = devm_kzalloc(&pdev->dev, sizeof(*kscandat),
0179                 GFP_KERNEL);
0180     if (!kscandat)
0181         return -ENOMEM;
0182 
0183     error = lpc32xx_parse_dt(&pdev->dev, kscandat);
0184     if (error) {
0185         dev_err(&pdev->dev, "failed to parse device tree\n");
0186         return error;
0187     }
0188 
0189     keymap_size = sizeof(kscandat->keymap[0]) *
0190                 (kscandat->matrix_sz << kscandat->row_shift);
0191     kscandat->keymap = devm_kzalloc(&pdev->dev, keymap_size, GFP_KERNEL);
0192     if (!kscandat->keymap)
0193         return -ENOMEM;
0194 
0195     kscandat->input = input = devm_input_allocate_device(&pdev->dev);
0196     if (!input) {
0197         dev_err(&pdev->dev, "failed to allocate input device\n");
0198         return -ENOMEM;
0199     }
0200 
0201     /* Setup key input */
0202     input->name     = pdev->name;
0203     input->phys     = "lpc32xx/input0";
0204     input->id.vendor    = 0x0001;
0205     input->id.product   = 0x0001;
0206     input->id.version   = 0x0100;
0207     input->open     = lpc32xx_kscan_open;
0208     input->close        = lpc32xx_kscan_close;
0209     input->dev.parent   = &pdev->dev;
0210 
0211     input_set_capability(input, EV_MSC, MSC_SCAN);
0212 
0213     error = matrix_keypad_build_keymap(NULL, NULL,
0214                        kscandat->matrix_sz,
0215                        kscandat->matrix_sz,
0216                        kscandat->keymap, kscandat->input);
0217     if (error) {
0218         dev_err(&pdev->dev, "failed to build keymap\n");
0219         return error;
0220     }
0221 
0222     input_set_drvdata(kscandat->input, kscandat);
0223 
0224     kscandat->kscan_base = devm_ioremap_resource(&pdev->dev, res);
0225     if (IS_ERR(kscandat->kscan_base))
0226         return PTR_ERR(kscandat->kscan_base);
0227 
0228     /* Get the key scanner clock */
0229     kscandat->clk = devm_clk_get(&pdev->dev, NULL);
0230     if (IS_ERR(kscandat->clk)) {
0231         dev_err(&pdev->dev, "failed to get clock\n");
0232         return PTR_ERR(kscandat->clk);
0233     }
0234 
0235     /* Configure the key scanner */
0236     error = clk_prepare_enable(kscandat->clk);
0237     if (error)
0238         return error;
0239 
0240     writel(kscandat->deb_clks, LPC32XX_KS_DEB(kscandat->kscan_base));
0241     writel(kscandat->scan_delay, LPC32XX_KS_SCAN_CTL(kscandat->kscan_base));
0242     writel(LPC32XX_KSCAN_FTST_USE32K_CLK,
0243            LPC32XX_KS_FAST_TST(kscandat->kscan_base));
0244     writel(kscandat->matrix_sz,
0245            LPC32XX_KS_MATRIX_DIM(kscandat->kscan_base));
0246     writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
0247     clk_disable_unprepare(kscandat->clk);
0248 
0249     error = devm_request_irq(&pdev->dev, irq, lpc32xx_kscan_irq, 0,
0250                  pdev->name, kscandat);
0251     if (error) {
0252         dev_err(&pdev->dev, "failed to request irq\n");
0253         return error;
0254     }
0255 
0256     error = input_register_device(kscandat->input);
0257     if (error) {
0258         dev_err(&pdev->dev, "failed to register input device\n");
0259         return error;
0260     }
0261 
0262     platform_set_drvdata(pdev, kscandat);
0263 
0264     return 0;
0265 }
0266 
0267 #ifdef CONFIG_PM_SLEEP
0268 static int lpc32xx_kscan_suspend(struct device *dev)
0269 {
0270     struct platform_device *pdev = to_platform_device(dev);
0271     struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
0272     struct input_dev *input = kscandat->input;
0273 
0274     mutex_lock(&input->mutex);
0275 
0276     if (input_device_enabled(input)) {
0277         /* Clear IRQ and disable clock */
0278         writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
0279         clk_disable_unprepare(kscandat->clk);
0280     }
0281 
0282     mutex_unlock(&input->mutex);
0283     return 0;
0284 }
0285 
0286 static int lpc32xx_kscan_resume(struct device *dev)
0287 {
0288     struct platform_device *pdev = to_platform_device(dev);
0289     struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
0290     struct input_dev *input = kscandat->input;
0291     int retval = 0;
0292 
0293     mutex_lock(&input->mutex);
0294 
0295     if (input_device_enabled(input)) {
0296         /* Enable clock and clear IRQ */
0297         retval = clk_prepare_enable(kscandat->clk);
0298         if (retval == 0)
0299             writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
0300     }
0301 
0302     mutex_unlock(&input->mutex);
0303     return retval;
0304 }
0305 #endif
0306 
0307 static SIMPLE_DEV_PM_OPS(lpc32xx_kscan_pm_ops, lpc32xx_kscan_suspend,
0308              lpc32xx_kscan_resume);
0309 
0310 static const struct of_device_id lpc32xx_kscan_match[] = {
0311     { .compatible = "nxp,lpc3220-key" },
0312     {},
0313 };
0314 MODULE_DEVICE_TABLE(of, lpc32xx_kscan_match);
0315 
0316 static struct platform_driver lpc32xx_kscan_driver = {
0317     .probe      = lpc32xx_kscan_probe,
0318     .driver     = {
0319         .name   = DRV_NAME,
0320         .pm = &lpc32xx_kscan_pm_ops,
0321         .of_match_table = lpc32xx_kscan_match,
0322     }
0323 };
0324 
0325 module_platform_driver(lpc32xx_kscan_driver);
0326 
0327 MODULE_LICENSE("GPL");
0328 MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
0329 MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
0330 MODULE_DESCRIPTION("Key scanner driver for LPC32XX devices");