xref: /linux/drivers/input/joystick/n64joy.c (revision f9bff0e31881d03badf191d3b0005839391f5f2b)
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);
346