^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for the enhanced rotary controller on pxa930 and pxa935
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/platform_data/keyboard-pxa930_rotary.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define SBCR (0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define ERCR (0x0c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define SBCR_ERSB (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct pxa930_rotary {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void __iomem *mmio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int last_ercr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct pxa930_rotary_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static void clear_sbcr(struct pxa930_rotary *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) uint32_t sbcr = __raw_readl(r->mmio_base + SBCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) __raw_writel(sbcr | SBCR_ERSB, r->mmio_base + SBCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) __raw_writel(sbcr & ~SBCR_ERSB, r->mmio_base + SBCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static irqreturn_t rotary_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct pxa930_rotary *r = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct pxa930_rotary_platform_data *pdata = r->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int ercr, delta, key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ercr = __raw_readl(r->mmio_base + ERCR) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) clear_sbcr(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) delta = ercr - r->last_ercr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (delta == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) r->last_ercr = ercr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (pdata->up_key && pdata->down_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) key = (delta > 0) ? pdata->up_key : pdata->down_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) input_report_key(r->input_dev, key, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) input_sync(r->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) input_report_key(r->input_dev, key, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) input_report_rel(r->input_dev, pdata->rel_code, delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) input_sync(r->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int pxa930_rotary_open(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct pxa930_rotary *r = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) clear_sbcr(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void pxa930_rotary_close(struct input_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct pxa930_rotary *r = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) clear_sbcr(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int pxa930_rotary_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct pxa930_rotary_platform_data *pdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct pxa930_rotary *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) dev_err(&pdev->dev, "no I/O memory defined\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev_err(&pdev->dev, "no platform data defined\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) r = kzalloc(sizeof(struct pxa930_rotary), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) r->mmio_base = ioremap(res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (r->mmio_base == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dev_err(&pdev->dev, "failed to remap IO memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) goto failed_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) r->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) platform_set_drvdata(pdev, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* allocate and register the input device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dev_err(&pdev->dev, "failed to allocate input device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto failed_free_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) input_dev->name = pdev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) input_dev->id.bustype = BUS_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) input_dev->open = pxa930_rotary_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) input_dev->close = pxa930_rotary_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) input_dev->dev.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (pdata->up_key && pdata->down_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) __set_bit(pdata->up_key, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) __set_bit(pdata->down_key, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) __set_bit(EV_KEY, input_dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) __set_bit(pdata->rel_code, input_dev->relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) __set_bit(EV_REL, input_dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) r->input_dev = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) input_set_drvdata(input_dev, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) err = request_irq(irq, rotary_irq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "enhanced rotary", r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dev_err(&pdev->dev, "failed to request IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) goto failed_free_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) err = input_register_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dev_err(&pdev->dev, "failed to register input device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) goto failed_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) failed_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) free_irq(irq, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) failed_free_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) input_free_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) failed_free_io:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) iounmap(r->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) failed_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) kfree(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return err;
^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) static int pxa930_rotary_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct pxa930_rotary *r = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) free_irq(platform_get_irq(pdev, 0), r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) input_unregister_device(r->input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) iounmap(r->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) kfree(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static struct platform_driver pxa930_rotary_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .name = "pxa930-rotary",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .probe = pxa930_rotary_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .remove = pxa930_rotary_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) module_platform_driver(pxa930_rotary_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>");