Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-microblaze.git] / drivers / input / joystick / n64joy.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for the four N64 controllers.
4  *
5  * Copyright (c) 2021 Lauri Kasanen
6  */
7
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
10 #include <linux/errno.h>
11 #include <linux/init.h>
12 #include <linux/input.h>
13 #include <linux/limits.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/mutex.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 #include <linux/timer.h>
20
21 MODULE_AUTHOR("Lauri Kasanen <cand@gmx.com>");
22 MODULE_DESCRIPTION("Driver for N64 controllers");
23 MODULE_LICENSE("GPL");
24
25 #define PIF_RAM 0x1fc007c0
26
27 #define SI_DRAM_REG 0
28 #define SI_READ_REG 1
29 #define SI_WRITE_REG 4
30 #define SI_STATUS_REG 6
31
32 #define SI_STATUS_DMA_BUSY  BIT(0)
33 #define SI_STATUS_IO_BUSY   BIT(1)
34
35 #define N64_CONTROLLER_ID 0x0500
36
37 #define MAX_CONTROLLERS 4
38
39 static const char *n64joy_phys[MAX_CONTROLLERS] = {
40         "n64joy/port0",
41         "n64joy/port1",
42         "n64joy/port2",
43         "n64joy/port3",
44 };
45
46 struct n64joy_priv {
47         u64 si_buf[8] ____cacheline_aligned;
48         struct timer_list timer;
49         struct mutex n64joy_mutex;
50         struct input_dev *n64joy_dev[MAX_CONTROLLERS];
51         u32 __iomem *reg_base;
52         u8 n64joy_opened;
53 };
54
55 struct joydata {
56         unsigned int: 16; /* unused */
57         unsigned int err: 2;
58         unsigned int: 14; /* unused */
59
60         union {
61                 u32 data;
62
63                 struct {
64                         unsigned int a: 1;
65                         unsigned int b: 1;
66                         unsigned int z: 1;
67                         unsigned int start: 1;
68                         unsigned int up: 1;
69                         unsigned int down: 1;
70                         unsigned int left: 1;
71                         unsigned int right: 1;
72                         unsigned int: 2; /* unused */
73                         unsigned int l: 1;
74                         unsigned int r: 1;
75                         unsigned int c_up: 1;
76                         unsigned int c_down: 1;
77                         unsigned int c_left: 1;
78                         unsigned int c_right: 1;
79                         signed int x: 8;
80                         signed int y: 8;
81                 };
82         };
83 };
84
85 static void n64joy_write_reg(u32 __iomem *reg_base, const u8 reg, const u32 value)
86 {
87         writel(value, reg_base + reg);
88 }
89
90 static u32 n64joy_read_reg(u32 __iomem *reg_base, const u8 reg)
91 {
92         return readl(reg_base + reg);
93 }
94
95 static void n64joy_wait_si_dma(u32 __iomem *reg_base)
96 {
97         while (n64joy_read_reg(reg_base, SI_STATUS_REG) &
98                (SI_STATUS_DMA_BUSY | SI_STATUS_IO_BUSY))
99                 cpu_relax();
100 }
101
102 static void n64joy_exec_pif(struct n64joy_priv *priv, const u64 in[8])
103 {
104         unsigned long flags;
105
106         dma_cache_wback_inv((unsigned long) in, 8 * 8);
107         dma_cache_inv((unsigned long) priv->si_buf, 8 * 8);
108
109         local_irq_save(flags);
110
111         n64joy_wait_si_dma(priv->reg_base);
112
113         barrier();
114         n64joy_write_reg(priv->reg_base, SI_DRAM_REG, virt_to_phys(in));
115         barrier();
116         n64joy_write_reg(priv->reg_base, SI_WRITE_REG, PIF_RAM);
117         barrier();
118
119         n64joy_wait_si_dma(priv->reg_base);
120
121         barrier();
122         n64joy_write_reg(priv->reg_base, SI_DRAM_REG, virt_to_phys(priv->si_buf));
123         barrier();
124         n64joy_write_reg(priv->reg_base, SI_READ_REG, PIF_RAM);
125         barrier();
126
127         n64joy_wait_si_dma(priv->reg_base);
128
129         local_irq_restore(flags);
130 }
131
132 static const u64 polldata[] ____cacheline_aligned = {
133         0xff010401ffffffff,
134         0xff010401ffffffff,
135         0xff010401ffffffff,
136         0xff010401ffffffff,
137         0xfe00000000000000,
138         0,
139         0,
140         1
141 };
142
143 static void n64joy_poll(struct timer_list *t)
144 {
145         const struct joydata *data;
146         struct n64joy_priv *priv = container_of(t, struct n64joy_priv, timer);
147         struct input_dev *dev;
148         u32 i;
149
150         n64joy_exec_pif(priv, polldata);
151
152         data = (struct joydata *) priv->si_buf;
153
154         for (i = 0; i < MAX_CONTROLLERS; i++) {
155                 if (!priv->n64joy_dev[i])
156                         continue;
157
158                 dev = priv->n64joy_dev[i];
159
160                 /* d-pad */
161                 input_report_key(dev, BTN_DPAD_UP, data[i].up);
162                 input_report_key(dev, BTN_DPAD_DOWN, data[i].down);
163                 input_report_key(dev, BTN_DPAD_LEFT, data[i].left);
164                 input_report_key(dev, BTN_DPAD_RIGHT, data[i].right);
165
166                 /* c buttons */
167                 input_report_key(dev, BTN_FORWARD, data[i].c_up);
168                 input_report_key(dev, BTN_BACK, data[i].c_down);
169                 input_report_key(dev, BTN_LEFT, data[i].c_left);
170                 input_report_key(dev, BTN_RIGHT, data[i].c_right);
171
172                 /* matching buttons */
173                 input_report_key(dev, BTN_START, data[i].start);
174                 input_report_key(dev, BTN_Z, data[i].z);
175
176                 /* remaining ones: a, b, l, r */
177                 input_report_key(dev, BTN_0, data[i].a);
178                 input_report_key(dev, BTN_1, data[i].b);
179                 input_report_key(dev, BTN_2, data[i].l);
180                 input_report_key(dev, BTN_3, data[i].r);
181
182                 input_report_abs(dev, ABS_X, data[i].x);
183                 input_report_abs(dev, ABS_Y, data[i].y);
184
185                 input_sync(dev);
186         }
187
188         mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16));
189 }
190
191 static int n64joy_open(struct input_dev *dev)
192 {
193         struct n64joy_priv *priv = input_get_drvdata(dev);
194         int err;
195
196         err = mutex_lock_interruptible(&priv->n64joy_mutex);
197         if (err)
198                 return err;
199
200         if (!priv->n64joy_opened) {
201                 /*
202                  * We could use the vblank irq, but it's not important if
203                  * the poll point slightly changes.
204                  */
205                 timer_setup(&priv->timer, n64joy_poll, 0);
206                 mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16));
207         }
208
209         priv->n64joy_opened++;
210
211         mutex_unlock(&priv->n64joy_mutex);
212         return err;
213 }
214
215 static void n64joy_close(struct input_dev *dev)
216 {
217         struct n64joy_priv *priv = input_get_drvdata(dev);
218
219         mutex_lock(&priv->n64joy_mutex);
220         if (!--priv->n64joy_opened)
221                 del_timer_sync(&priv->timer);
222         mutex_unlock(&priv->n64joy_mutex);
223 }
224
225 static const u64 __initconst scandata[] ____cacheline_aligned = {
226         0xff010300ffffffff,
227         0xff010300ffffffff,
228         0xff010300ffffffff,
229         0xff010300ffffffff,
230         0xfe00000000000000,
231         0,
232         0,
233         1
234 };
235
236 /*
237  * The target device is embedded and RAM-constrained. We save RAM
238  * by initializing in __init code that gets dropped late in boot.
239  * For the same reason there is no module or unloading support.
240  */
241 static int __init n64joy_probe(struct platform_device *pdev)
242 {
243         const struct joydata *data;
244         struct n64joy_priv *priv;
245         struct input_dev *dev;
246         int err = 0;
247         u32 i, j, found = 0;
248
249         priv = kzalloc(sizeof(struct n64joy_priv), GFP_KERNEL);
250         if (!priv)
251                 return -ENOMEM;
252         mutex_init(&priv->n64joy_mutex);
253
254         priv->reg_base = devm_platform_ioremap_resource(pdev, 0);
255         if (IS_ERR(priv->reg_base)) {
256                 err = PTR_ERR(priv->reg_base);
257                 goto fail;
258         }
259
260         /* The controllers are not hotpluggable, so we can scan in init */
261         n64joy_exec_pif(priv, scandata);
262
263         data = (struct joydata *) priv->si_buf;
264
265         for (i = 0; i < MAX_CONTROLLERS; i++) {
266                 if (!data[i].err && data[i].data >> 16 == N64_CONTROLLER_ID) {
267                         found++;
268
269                         dev = priv->n64joy_dev[i] = input_allocate_device();
270                         if (!priv->n64joy_dev[i]) {
271                                 err = -ENOMEM;
272                                 goto fail;
273                         }
274
275                         input_set_drvdata(dev, priv);
276
277                         dev->name = "N64 controller";
278                         dev->phys = n64joy_phys[i];
279                         dev->id.bustype = BUS_HOST;
280                         dev->id.vendor = 0;
281                         dev->id.product = data[i].data >> 16;
282                         dev->id.version = 0;
283                         dev->dev.parent = &pdev->dev;
284
285                         dev->open = n64joy_open;
286                         dev->close = n64joy_close;
287
288                         /* d-pad */
289                         input_set_capability(dev, EV_KEY, BTN_DPAD_UP);
290                         input_set_capability(dev, EV_KEY, BTN_DPAD_DOWN);
291                         input_set_capability(dev, EV_KEY, BTN_DPAD_LEFT);
292                         input_set_capability(dev, EV_KEY, BTN_DPAD_RIGHT);
293                         /* c buttons */
294                         input_set_capability(dev, EV_KEY, BTN_LEFT);
295                         input_set_capability(dev, EV_KEY, BTN_RIGHT);
296                         input_set_capability(dev, EV_KEY, BTN_FORWARD);
297                         input_set_capability(dev, EV_KEY, BTN_BACK);
298                         /* matching buttons */
299                         input_set_capability(dev, EV_KEY, BTN_START);
300                         input_set_capability(dev, EV_KEY, BTN_Z);
301                         /* remaining ones: a, b, l, r */
302                         input_set_capability(dev, EV_KEY, BTN_0);
303                         input_set_capability(dev, EV_KEY, BTN_1);
304                         input_set_capability(dev, EV_KEY, BTN_2);
305                         input_set_capability(dev, EV_KEY, BTN_3);
306
307                         for (j = 0; j < 2; j++)
308                                 input_set_abs_params(dev, ABS_X + j,
309                                                      S8_MIN, S8_MAX, 0, 0);
310
311                         err = input_register_device(dev);
312                         if (err) {
313                                 input_free_device(dev);
314                                 goto fail;
315                         }
316                 }
317         }
318
319         pr_info("%u controller(s) connected\n", found);
320
321         if (!found)
322                 return -ENODEV;
323
324         return 0;
325 fail:
326         for (i = 0; i < MAX_CONTROLLERS; i++) {
327                 if (!priv->n64joy_dev[i])
328                         continue;
329                 input_unregister_device(priv->n64joy_dev[i]);
330         }
331         return err;
332 }
333
334 static struct platform_driver n64joy_driver = {
335         .driver = {
336                 .name = "n64joy",
337         },
338 };
339
340 static int __init n64joy_init(void)
341 {
342         return platform_driver_probe(&n64joy_driver, n64joy_probe);
343 }
344
345 module_init(n64joy_init);