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);
93 dev_err(&pdev
->dev
, "no irq for rotary controller\n");
97 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
99 dev_err(&pdev
->dev
, "no I/O memory defined\n");
104 dev_err(&pdev
->dev
, "no platform data defined\n");
108 r
= kzalloc(sizeof(struct pxa930_rotary
), GFP_KERNEL
);
112 r
->mmio_base
= ioremap_nocache(res
->start
, resource_size(res
));
113 if (r
->mmio_base
== NULL
) {
114 dev_err(&pdev
->dev
, "failed to remap IO memory\n");
120 platform_set_drvdata(pdev
, r
);
122 /* allocate and register the input device */
123 input_dev
= input_allocate_device();
125 dev_err(&pdev
->dev
, "failed to allocate input device\n");
130 input_dev
->name
= pdev
->name
;
131 input_dev
->id
.bustype
= BUS_HOST
;
132 input_dev
->open
= pxa930_rotary_open
;
133 input_dev
->close
= pxa930_rotary_close
;
134 input_dev
->dev
.parent
= &pdev
->dev
;
136 if (pdata
->up_key
&& pdata
->down_key
) {
137 __set_bit(pdata
->up_key
, input_dev
->keybit
);
138 __set_bit(pdata
->down_key
, input_dev
->keybit
);
139 __set_bit(EV_KEY
, input_dev
->evbit
);
141 __set_bit(pdata
->rel_code
, input_dev
->relbit
);
142 __set_bit(EV_REL
, input_dev
->evbit
);
145 r
->input_dev
= input_dev
;
146 input_set_drvdata(input_dev
, r
);
148 err
= request_irq(irq
, rotary_irq
, 0,
149 "enhanced rotary", r
);
151 dev_err(&pdev
->dev
, "failed to request IRQ\n");
152 goto failed_free_input
;
155 err
= input_register_device(input_dev
);
157 dev_err(&pdev
->dev
, "failed to register input device\n");
158 goto failed_free_irq
;
166 input_free_device(input_dev
);
168 iounmap(r
->mmio_base
);
174 static int pxa930_rotary_remove(struct platform_device
*pdev
)
176 struct pxa930_rotary
*r
= platform_get_drvdata(pdev
);
178 free_irq(platform_get_irq(pdev
, 0), r
);
179 input_unregister_device(r
->input_dev
);
180 iounmap(r
->mmio_base
);
186 static struct platform_driver pxa930_rotary_driver
= {
188 .name
= "pxa930-rotary",
190 .probe
= pxa930_rotary_probe
,
191 .remove
= pxa930_rotary_remove
,
193 module_platform_driver(pxa930_rotary_driver
);
195 MODULE_LICENSE("GPL");
196 MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
197 MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>");