1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for the enhanced rotary controller on pxa930 and pxa935
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/interrupt.h>
9 #include <linux/input.h>
10 #include <linux/platform_device.h>
12 #include <linux/slab.h>
14 #include <linux/platform_data/keyboard-pxa930_rotary.h>
19 #define SBCR_ERSB (1 << 5)
21 struct pxa930_rotary
{
22 struct input_dev
*input_dev
;
23 void __iomem
*mmio_base
;
26 struct pxa930_rotary_platform_data
*pdata
;
29 static void clear_sbcr(struct pxa930_rotary
*r
)
31 uint32_t sbcr
= __raw_readl(r
->mmio_base
+ SBCR
);
33 __raw_writel(sbcr
| SBCR_ERSB
, r
->mmio_base
+ SBCR
);
34 __raw_writel(sbcr
& ~SBCR_ERSB
, r
->mmio_base
+ SBCR
);
37 static irqreturn_t
rotary_irq(int irq
, void *dev_id
)
39 struct pxa930_rotary
*r
= dev_id
;
40 struct pxa930_rotary_platform_data
*pdata
= r
->pdata
;
43 ercr
= __raw_readl(r
->mmio_base
+ ERCR
) & 0xf;
46 delta
= ercr
- r
->last_ercr
;
52 if (pdata
->up_key
&& pdata
->down_key
) {
53 key
= (delta
> 0) ? pdata
->up_key
: pdata
->down_key
;
54 input_report_key(r
->input_dev
, key
, 1);
55 input_sync(r
->input_dev
);
56 input_report_key(r
->input_dev
, key
, 0);
58 input_report_rel(r
->input_dev
, pdata
->rel_code
, delta
);
60 input_sync(r
->input_dev
);
65 static int pxa930_rotary_open(struct input_dev
*dev
)
67 struct pxa930_rotary
*r
= input_get_drvdata(dev
);
74 static void pxa930_rotary_close(struct input_dev
*dev
)
76 struct pxa930_rotary
*r
= input_get_drvdata(dev
);
81 static int pxa930_rotary_probe(struct platform_device
*pdev
)
83 struct pxa930_rotary_platform_data
*pdata
=
84 dev_get_platdata(&pdev
->dev
);
85 struct pxa930_rotary
*r
;
86 struct input_dev
*input_dev
;
91 irq
= platform_get_irq(pdev
, 0);
95 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
97 dev_err(&pdev
->dev
, "no I/O memory defined\n");
102 dev_err(&pdev
->dev
, "no platform data defined\n");
106 r
= kzalloc(sizeof(struct pxa930_rotary
), GFP_KERNEL
);
110 r
->mmio_base
= ioremap(res
->start
, resource_size(res
));
111 if (r
->mmio_base
== NULL
) {
112 dev_err(&pdev
->dev
, "failed to remap IO memory\n");
118 platform_set_drvdata(pdev
, r
);
120 /* allocate and register the input device */
121 input_dev
= input_allocate_device();
123 dev_err(&pdev
->dev
, "failed to allocate input device\n");
128 input_dev
->name
= pdev
->name
;
129 input_dev
->id
.bustype
= BUS_HOST
;
130 input_dev
->open
= pxa930_rotary_open
;
131 input_dev
->close
= pxa930_rotary_close
;
132 input_dev
->dev
.parent
= &pdev
->dev
;
134 if (pdata
->up_key
&& pdata
->down_key
) {
135 __set_bit(pdata
->up_key
, input_dev
->keybit
);
136 __set_bit(pdata
->down_key
, input_dev
->keybit
);
137 __set_bit(EV_KEY
, input_dev
->evbit
);
139 __set_bit(pdata
->rel_code
, input_dev
->relbit
);
140 __set_bit(EV_REL
, input_dev
->evbit
);
143 r
->input_dev
= input_dev
;
144 input_set_drvdata(input_dev
, r
);
146 err
= request_irq(irq
, rotary_irq
, 0,
147 "enhanced rotary", r
);
149 dev_err(&pdev
->dev
, "failed to request IRQ\n");
150 goto failed_free_input
;
153 err
= input_register_device(input_dev
);
155 dev_err(&pdev
->dev
, "failed to register input device\n");
156 goto failed_free_irq
;
164 input_free_device(input_dev
);
166 iounmap(r
->mmio_base
);
172 static int pxa930_rotary_remove(struct platform_device
*pdev
)
174 struct pxa930_rotary
*r
= platform_get_drvdata(pdev
);
176 free_irq(platform_get_irq(pdev
, 0), r
);
177 input_unregister_device(r
->input_dev
);
178 iounmap(r
->mmio_base
);
184 static struct platform_driver pxa930_rotary_driver
= {
186 .name
= "pxa930-rotary",
188 .probe
= pxa930_rotary_probe
,
189 .remove
= pxa930_rotary_remove
,
191 module_platform_driver(pxa930_rotary_driver
);
193 MODULE_LICENSE("GPL");
194 MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
195 MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>");