1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  Nano River Technologies viperboard GPIO lib driver
4  *
5  *  (C) 2012 by Lemonage GmbH
6  *  Author: Lars Poeschel <poeschel@lemonage.de>
7  *  All rights reserved.
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/types.h>
15 #include <linux/mutex.h>
16 #include <linux/platform_device.h>
17 #include <linux/usb.h>
18 #include <linux/gpio/driver.h>
19 
20 #include <linux/mfd/viperboard.h>
21 
22 #define VPRBRD_GPIOA_CLK_1MHZ		0
23 #define VPRBRD_GPIOA_CLK_100KHZ		1
24 #define VPRBRD_GPIOA_CLK_10KHZ		2
25 #define VPRBRD_GPIOA_CLK_1KHZ		3
26 #define VPRBRD_GPIOA_CLK_100HZ		4
27 #define VPRBRD_GPIOA_CLK_10HZ		5
28 
29 #define VPRBRD_GPIOA_FREQ_DEFAULT	1000
30 
31 #define VPRBRD_GPIOA_CMD_CONT		0x00
32 #define VPRBRD_GPIOA_CMD_PULSE		0x01
33 #define VPRBRD_GPIOA_CMD_PWM		0x02
34 #define VPRBRD_GPIOA_CMD_SETOUT		0x03
35 #define VPRBRD_GPIOA_CMD_SETIN		0x04
36 #define VPRBRD_GPIOA_CMD_SETINT		0x05
37 #define VPRBRD_GPIOA_CMD_GETIN		0x06
38 
39 #define VPRBRD_GPIOB_CMD_SETDIR		0x00
40 #define VPRBRD_GPIOB_CMD_SETVAL		0x01
41 
42 struct vprbrd_gpioa_msg {
43 	u8 cmd;
44 	u8 clk;
45 	u8 offset;
46 	u8 t1;
47 	u8 t2;
48 	u8 invert;
49 	u8 pwmlevel;
50 	u8 outval;
51 	u8 risefall;
52 	u8 answer;
53 	u8 __fill;
54 } __packed;
55 
56 struct vprbrd_gpiob_msg {
57 	u8 cmd;
58 	u16 val;
59 	u16 mask;
60 } __packed;
61 
62 struct vprbrd_gpio {
63 	struct gpio_chip gpioa; /* gpio a related things */
64 	u32 gpioa_out;
65 	u32 gpioa_val;
66 	struct gpio_chip gpiob; /* gpio b related things */
67 	u32 gpiob_out;
68 	u32 gpiob_val;
69 	struct vprbrd *vb;
70 };
71 
72 /* gpioa sampling clock module parameter */
73 static unsigned char gpioa_clk;
74 static unsigned int gpioa_freq = VPRBRD_GPIOA_FREQ_DEFAULT;
75 module_param(gpioa_freq, uint, 0);
76 MODULE_PARM_DESC(gpioa_freq,
77 	"gpio-a sampling freq in Hz (default is 1000Hz) valid values: 10, 100, 1000, 10000, 100000, 1000000");
78 
79 /* ----- begin of gipo a chip -------------------------------------------- */
80 
vprbrd_gpioa_get(struct gpio_chip * chip,unsigned int offset)81 static int vprbrd_gpioa_get(struct gpio_chip *chip,
82 		unsigned int offset)
83 {
84 	int ret, answer, error = 0;
85 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
86 	struct vprbrd *vb = gpio->vb;
87 	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
88 
89 	/* if io is set to output, just return the saved value */
90 	if (gpio->gpioa_out & (1 << offset))
91 		return !!(gpio->gpioa_val & (1 << offset));
92 
93 	mutex_lock(&vb->lock);
94 
95 	gamsg->cmd = VPRBRD_GPIOA_CMD_GETIN;
96 	gamsg->clk = 0x00;
97 	gamsg->offset = offset;
98 	gamsg->t1 = 0x00;
99 	gamsg->t2 = 0x00;
100 	gamsg->invert = 0x00;
101 	gamsg->pwmlevel = 0x00;
102 	gamsg->outval = 0x00;
103 	gamsg->risefall = 0x00;
104 	gamsg->answer = 0x00;
105 	gamsg->__fill = 0x00;
106 
107 	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
108 		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
109 		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
110 		VPRBRD_USB_TIMEOUT_MS);
111 	if (ret != sizeof(struct vprbrd_gpioa_msg))
112 		error = -EREMOTEIO;
113 
114 	ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0),
115 		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_IN, 0x0000,
116 		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
117 		VPRBRD_USB_TIMEOUT_MS);
118 	answer = gamsg->answer & 0x01;
119 
120 	mutex_unlock(&vb->lock);
121 
122 	if (ret != sizeof(struct vprbrd_gpioa_msg))
123 		error = -EREMOTEIO;
124 
125 	if (error)
126 		return error;
127 
128 	return answer;
129 }
130 
vprbrd_gpioa_set(struct gpio_chip * chip,unsigned int offset,int value)131 static void vprbrd_gpioa_set(struct gpio_chip *chip,
132 		unsigned int offset, int value)
133 {
134 	int ret;
135 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
136 	struct vprbrd *vb = gpio->vb;
137 	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
138 
139 	if (gpio->gpioa_out & (1 << offset)) {
140 		if (value)
141 			gpio->gpioa_val |= (1 << offset);
142 		else
143 			gpio->gpioa_val &= ~(1 << offset);
144 
145 		mutex_lock(&vb->lock);
146 
147 		gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT;
148 		gamsg->clk = 0x00;
149 		gamsg->offset = offset;
150 		gamsg->t1 = 0x00;
151 		gamsg->t2 = 0x00;
152 		gamsg->invert = 0x00;
153 		gamsg->pwmlevel = 0x00;
154 		gamsg->outval = value;
155 		gamsg->risefall = 0x00;
156 		gamsg->answer = 0x00;
157 		gamsg->__fill = 0x00;
158 
159 		ret = usb_control_msg(vb->usb_dev,
160 			usb_sndctrlpipe(vb->usb_dev, 0),
161 			VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT,
162 			0x0000,	0x0000, gamsg,
163 			sizeof(struct vprbrd_gpioa_msg), VPRBRD_USB_TIMEOUT_MS);
164 
165 		mutex_unlock(&vb->lock);
166 
167 		if (ret != sizeof(struct vprbrd_gpioa_msg))
168 			dev_err(chip->parent, "usb error setting pin value\n");
169 	}
170 }
171 
vprbrd_gpioa_direction_input(struct gpio_chip * chip,unsigned int offset)172 static int vprbrd_gpioa_direction_input(struct gpio_chip *chip,
173 			unsigned int offset)
174 {
175 	int ret;
176 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
177 	struct vprbrd *vb = gpio->vb;
178 	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
179 
180 	gpio->gpioa_out &= ~(1 << offset);
181 
182 	mutex_lock(&vb->lock);
183 
184 	gamsg->cmd = VPRBRD_GPIOA_CMD_SETIN;
185 	gamsg->clk = gpioa_clk;
186 	gamsg->offset = offset;
187 	gamsg->t1 = 0x00;
188 	gamsg->t2 = 0x00;
189 	gamsg->invert = 0x00;
190 	gamsg->pwmlevel = 0x00;
191 	gamsg->outval = 0x00;
192 	gamsg->risefall = 0x00;
193 	gamsg->answer = 0x00;
194 	gamsg->__fill = 0x00;
195 
196 	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
197 		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
198 		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
199 		VPRBRD_USB_TIMEOUT_MS);
200 
201 	mutex_unlock(&vb->lock);
202 
203 	if (ret != sizeof(struct vprbrd_gpioa_msg))
204 		return -EREMOTEIO;
205 
206 	return 0;
207 }
208 
vprbrd_gpioa_direction_output(struct gpio_chip * chip,unsigned int offset,int value)209 static int vprbrd_gpioa_direction_output(struct gpio_chip *chip,
210 			unsigned int offset, int value)
211 {
212 	int ret;
213 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
214 	struct vprbrd *vb = gpio->vb;
215 	struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
216 
217 	gpio->gpioa_out |= (1 << offset);
218 	if (value)
219 		gpio->gpioa_val |= (1 << offset);
220 	else
221 		gpio->gpioa_val &= ~(1 << offset);
222 
223 	mutex_lock(&vb->lock);
224 
225 	gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT;
226 	gamsg->clk = 0x00;
227 	gamsg->offset = offset;
228 	gamsg->t1 = 0x00;
229 	gamsg->t2 = 0x00;
230 	gamsg->invert = 0x00;
231 	gamsg->pwmlevel = 0x00;
232 	gamsg->outval = value;
233 	gamsg->risefall = 0x00;
234 	gamsg->answer = 0x00;
235 	gamsg->__fill = 0x00;
236 
237 	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
238 		VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
239 		0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
240 		VPRBRD_USB_TIMEOUT_MS);
241 
242 	mutex_unlock(&vb->lock);
243 
244 	if (ret != sizeof(struct vprbrd_gpioa_msg))
245 		return -EREMOTEIO;
246 
247 	return 0;
248 }
249 
250 /* ----- end of gpio a chip ---------------------------------------------- */
251 
252 /* ----- begin of gipo b chip -------------------------------------------- */
253 
vprbrd_gpiob_setdir(struct vprbrd * vb,unsigned int offset,unsigned int dir)254 static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned int offset,
255 	unsigned int dir)
256 {
257 	struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
258 	int ret;
259 
260 	gbmsg->cmd = VPRBRD_GPIOB_CMD_SETDIR;
261 	gbmsg->val = cpu_to_be16(dir << offset);
262 	gbmsg->mask = cpu_to_be16(0x0001 << offset);
263 
264 	ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
265 		VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT, 0x0000,
266 		0x0000, gbmsg, sizeof(struct vprbrd_gpiob_msg),
267 		VPRBRD_USB_TIMEOUT_MS);
268 
269 	if (ret != sizeof(struct vprbrd_gpiob_msg))
270 		return -EREMOTEIO;
271 
272 	return 0;
273 }
274 
vprbrd_gpiob_get(struct gpio_chip * chip,unsigned int offset)275 static int vprbrd_gpiob_get(struct gpio_chip *chip,
276 		unsigned int offset)
277 {
278 	int ret;
279 	u16 val;
280 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
281 	struct vprbrd *vb = gpio->vb;
282 	struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
283 
284 	/* if io is set to output, just return the saved value */
285 	if (gpio->gpiob_out & (1 << offset))
286 		return gpio->gpiob_val & (1 << offset);
287 
288 	mutex_lock(&vb->lock);
289 
290 	ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0),
291 		VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_IN, 0x0000,
292 		0x0000, gbmsg,	sizeof(struct vprbrd_gpiob_msg),
293 		VPRBRD_USB_TIMEOUT_MS);
294 	val = gbmsg->val;
295 
296 	mutex_unlock(&vb->lock);
297 
298 	if (ret != sizeof(struct vprbrd_gpiob_msg))
299 		return ret;
300 
301 	/* cache the read values */
302 	gpio->gpiob_val = be16_to_cpu(val);
303 
304 	return (gpio->gpiob_val >> offset) & 0x1;
305 }
306 
vprbrd_gpiob_set(struct gpio_chip * chip,unsigned int offset,int value)307 static void vprbrd_gpiob_set(struct gpio_chip *chip,
308 		unsigned int offset, int value)
309 {
310 	int ret;
311 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
312 	struct vprbrd *vb = gpio->vb;
313 	struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
314 
315 	if (gpio->gpiob_out & (1 << offset)) {
316 		if (value)
317 			gpio->gpiob_val |= (1 << offset);
318 		else
319 			gpio->gpiob_val &= ~(1 << offset);
320 
321 		mutex_lock(&vb->lock);
322 
323 		gbmsg->cmd = VPRBRD_GPIOB_CMD_SETVAL;
324 		gbmsg->val = cpu_to_be16(value << offset);
325 		gbmsg->mask = cpu_to_be16(0x0001 << offset);
326 
327 		ret = usb_control_msg(vb->usb_dev,
328 			usb_sndctrlpipe(vb->usb_dev, 0),
329 			VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT,
330 			0x0000,	0x0000, gbmsg,
331 			sizeof(struct vprbrd_gpiob_msg), VPRBRD_USB_TIMEOUT_MS);
332 
333 		mutex_unlock(&vb->lock);
334 
335 		if (ret != sizeof(struct vprbrd_gpiob_msg))
336 			dev_err(chip->parent, "usb error setting pin value\n");
337 	}
338 }
339 
vprbrd_gpiob_direction_input(struct gpio_chip * chip,unsigned int offset)340 static int vprbrd_gpiob_direction_input(struct gpio_chip *chip,
341 			unsigned int offset)
342 {
343 	int ret;
344 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
345 	struct vprbrd *vb = gpio->vb;
346 
347 	gpio->gpiob_out &= ~(1 << offset);
348 
349 	mutex_lock(&vb->lock);
350 
351 	ret = vprbrd_gpiob_setdir(vb, offset, 0);
352 
353 	mutex_unlock(&vb->lock);
354 
355 	if (ret)
356 		dev_err(chip->parent, "usb error setting pin to input\n");
357 
358 	return ret;
359 }
360 
vprbrd_gpiob_direction_output(struct gpio_chip * chip,unsigned int offset,int value)361 static int vprbrd_gpiob_direction_output(struct gpio_chip *chip,
362 			unsigned int offset, int value)
363 {
364 	int ret;
365 	struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
366 	struct vprbrd *vb = gpio->vb;
367 
368 	gpio->gpiob_out |= (1 << offset);
369 
370 	mutex_lock(&vb->lock);
371 
372 	ret = vprbrd_gpiob_setdir(vb, offset, 1);
373 	if (ret)
374 		dev_err(chip->parent, "usb error setting pin to output\n");
375 
376 	mutex_unlock(&vb->lock);
377 
378 	vprbrd_gpiob_set(chip, offset, value);
379 
380 	return ret;
381 }
382 
383 /* ----- end of gpio b chip ---------------------------------------------- */
384 
vprbrd_gpio_probe(struct platform_device * pdev)385 static int vprbrd_gpio_probe(struct platform_device *pdev)
386 {
387 	struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
388 	struct vprbrd_gpio *vb_gpio;
389 	int ret;
390 
391 	vb_gpio = devm_kzalloc(&pdev->dev, sizeof(*vb_gpio), GFP_KERNEL);
392 	if (vb_gpio == NULL)
393 		return -ENOMEM;
394 
395 	vb_gpio->vb = vb;
396 	/* registering gpio a */
397 	vb_gpio->gpioa.label = "viperboard gpio a";
398 	vb_gpio->gpioa.parent = &pdev->dev;
399 	vb_gpio->gpioa.owner = THIS_MODULE;
400 	vb_gpio->gpioa.base = -1;
401 	vb_gpio->gpioa.ngpio = 16;
402 	vb_gpio->gpioa.can_sleep = true;
403 	vb_gpio->gpioa.set = vprbrd_gpioa_set;
404 	vb_gpio->gpioa.get = vprbrd_gpioa_get;
405 	vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input;
406 	vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output;
407 
408 	ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio);
409 	if (ret < 0)
410 		return ret;
411 
412 	/* registering gpio b */
413 	vb_gpio->gpiob.label = "viperboard gpio b";
414 	vb_gpio->gpiob.parent = &pdev->dev;
415 	vb_gpio->gpiob.owner = THIS_MODULE;
416 	vb_gpio->gpiob.base = -1;
417 	vb_gpio->gpiob.ngpio = 16;
418 	vb_gpio->gpiob.can_sleep = true;
419 	vb_gpio->gpiob.set = vprbrd_gpiob_set;
420 	vb_gpio->gpiob.get = vprbrd_gpiob_get;
421 	vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input;
422 	vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
423 
424 	return devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
425 }
426 
427 static struct platform_driver vprbrd_gpio_driver = {
428 	.driver.name	= "viperboard-gpio",
429 	.probe		= vprbrd_gpio_probe,
430 };
431 
vprbrd_gpio_init(void)432 static int __init vprbrd_gpio_init(void)
433 {
434 	switch (gpioa_freq) {
435 	case 1000000:
436 		gpioa_clk = VPRBRD_GPIOA_CLK_1MHZ;
437 		break;
438 	case 100000:
439 		gpioa_clk = VPRBRD_GPIOA_CLK_100KHZ;
440 		break;
441 	case 10000:
442 		gpioa_clk = VPRBRD_GPIOA_CLK_10KHZ;
443 		break;
444 	case 1000:
445 		gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
446 		break;
447 	case 100:
448 		gpioa_clk = VPRBRD_GPIOA_CLK_100HZ;
449 		break;
450 	case 10:
451 		gpioa_clk = VPRBRD_GPIOA_CLK_10HZ;
452 		break;
453 	default:
454 		pr_warn("invalid gpioa_freq (%d)\n", gpioa_freq);
455 		gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
456 	}
457 
458 	return platform_driver_register(&vprbrd_gpio_driver);
459 }
460 subsys_initcall(vprbrd_gpio_init);
461 
vprbrd_gpio_exit(void)462 static void __exit vprbrd_gpio_exit(void)
463 {
464 	platform_driver_unregister(&vprbrd_gpio_driver);
465 }
466 module_exit(vprbrd_gpio_exit);
467 
468 MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
469 MODULE_DESCRIPTION("GPIO driver for Nano River Techs Viperboard");
470 MODULE_LICENSE("GPL");
471 MODULE_ALIAS("platform:viperboard-gpio");
472