Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for the enhanced rotary controller on pxa930 and pxa935
0004  */
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/module.h>
0008 #include <linux/interrupt.h>
0009 #include <linux/input.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/io.h>
0012 #include <linux/slab.h>
0013 
0014 #include <linux/platform_data/keyboard-pxa930_rotary.h>
0015 
0016 #define SBCR    (0x04)
0017 #define ERCR    (0x0c)
0018 
0019 #define SBCR_ERSB   (1 << 5)
0020 
0021 struct pxa930_rotary {
0022     struct input_dev    *input_dev;
0023     void __iomem        *mmio_base;
0024     int         last_ercr;
0025 
0026     struct pxa930_rotary_platform_data *pdata;
0027 };
0028 
0029 static void clear_sbcr(struct pxa930_rotary *r)
0030 {
0031     uint32_t sbcr = __raw_readl(r->mmio_base + SBCR);
0032 
0033     __raw_writel(sbcr | SBCR_ERSB, r->mmio_base + SBCR);
0034     __raw_writel(sbcr & ~SBCR_ERSB, r->mmio_base + SBCR);
0035 }
0036 
0037 static irqreturn_t rotary_irq(int irq, void *dev_id)
0038 {
0039     struct pxa930_rotary *r = dev_id;
0040     struct pxa930_rotary_platform_data *pdata = r->pdata;
0041     int ercr, delta, key;
0042 
0043     ercr = __raw_readl(r->mmio_base + ERCR) & 0xf;
0044     clear_sbcr(r);
0045 
0046     delta = ercr - r->last_ercr;
0047     if (delta == 0)
0048         return IRQ_HANDLED;
0049 
0050     r->last_ercr = ercr;
0051 
0052     if (pdata->up_key && pdata->down_key) {
0053         key = (delta > 0) ? pdata->up_key : pdata->down_key;
0054         input_report_key(r->input_dev, key, 1);
0055         input_sync(r->input_dev);
0056         input_report_key(r->input_dev, key, 0);
0057     } else
0058         input_report_rel(r->input_dev, pdata->rel_code, delta);
0059 
0060     input_sync(r->input_dev);
0061 
0062     return IRQ_HANDLED;
0063 }
0064 
0065 static int pxa930_rotary_open(struct input_dev *dev)
0066 {
0067     struct pxa930_rotary *r = input_get_drvdata(dev);
0068 
0069     clear_sbcr(r);
0070 
0071     return 0;
0072 }
0073 
0074 static void pxa930_rotary_close(struct input_dev *dev)
0075 {
0076     struct pxa930_rotary *r = input_get_drvdata(dev);
0077 
0078     clear_sbcr(r);
0079 }
0080 
0081 static int pxa930_rotary_probe(struct platform_device *pdev)
0082 {
0083     struct pxa930_rotary_platform_data *pdata =
0084             dev_get_platdata(&pdev->dev);
0085     struct pxa930_rotary *r;
0086     struct input_dev *input_dev;
0087     struct resource *res;
0088     int irq;
0089     int err;
0090 
0091     irq = platform_get_irq(pdev, 0);
0092     if (irq < 0)
0093         return -ENXIO;
0094 
0095     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0096     if (!res) {
0097         dev_err(&pdev->dev, "no I/O memory defined\n");
0098         return -ENXIO;
0099     }
0100 
0101     if (!pdata) {
0102         dev_err(&pdev->dev, "no platform data defined\n");
0103         return -EINVAL;
0104     }
0105 
0106     r = kzalloc(sizeof(struct pxa930_rotary), GFP_KERNEL);
0107     if (!r)
0108         return -ENOMEM;
0109 
0110     r->mmio_base = ioremap(res->start, resource_size(res));
0111     if (r->mmio_base == NULL) {
0112         dev_err(&pdev->dev, "failed to remap IO memory\n");
0113         err = -ENXIO;
0114         goto failed_free;
0115     }
0116 
0117     r->pdata = pdata;
0118     platform_set_drvdata(pdev, r);
0119 
0120     /* allocate and register the input device */
0121     input_dev = input_allocate_device();
0122     if (!input_dev) {
0123         dev_err(&pdev->dev, "failed to allocate input device\n");
0124         err = -ENOMEM;
0125         goto failed_free_io;
0126     }
0127 
0128     input_dev->name = pdev->name;
0129     input_dev->id.bustype = BUS_HOST;
0130     input_dev->open = pxa930_rotary_open;
0131     input_dev->close = pxa930_rotary_close;
0132     input_dev->dev.parent = &pdev->dev;
0133 
0134     if (pdata->up_key && pdata->down_key) {
0135         __set_bit(pdata->up_key, input_dev->keybit);
0136         __set_bit(pdata->down_key, input_dev->keybit);
0137         __set_bit(EV_KEY, input_dev->evbit);
0138     } else {
0139         __set_bit(pdata->rel_code, input_dev->relbit);
0140         __set_bit(EV_REL, input_dev->evbit);
0141     }
0142 
0143     r->input_dev = input_dev;
0144     input_set_drvdata(input_dev, r);
0145 
0146     err = request_irq(irq, rotary_irq, 0,
0147             "enhanced rotary", r);
0148     if (err) {
0149         dev_err(&pdev->dev, "failed to request IRQ\n");
0150         goto failed_free_input;
0151     }
0152 
0153     err = input_register_device(input_dev);
0154     if (err) {
0155         dev_err(&pdev->dev, "failed to register input device\n");
0156         goto failed_free_irq;
0157     }
0158 
0159     return 0;
0160 
0161 failed_free_irq:
0162     free_irq(irq, r);
0163 failed_free_input:
0164     input_free_device(input_dev);
0165 failed_free_io:
0166     iounmap(r->mmio_base);
0167 failed_free:
0168     kfree(r);
0169     return err;
0170 }
0171 
0172 static int pxa930_rotary_remove(struct platform_device *pdev)
0173 {
0174     struct pxa930_rotary *r = platform_get_drvdata(pdev);
0175 
0176     free_irq(platform_get_irq(pdev, 0), r);
0177     input_unregister_device(r->input_dev);
0178     iounmap(r->mmio_base);
0179     kfree(r);
0180 
0181     return 0;
0182 }
0183 
0184 static struct platform_driver pxa930_rotary_driver = {
0185     .driver     = {
0186         .name   = "pxa930-rotary",
0187     },
0188     .probe      = pxa930_rotary_probe,
0189     .remove     = pxa930_rotary_remove,
0190 };
0191 module_platform_driver(pxa930_rotary_driver);
0192 
0193 MODULE_LICENSE("GPL");
0194 MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
0195 MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>");