gpio-viperboard.c (11989B)
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 42struct 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 56struct vprbrd_gpiob_msg { 57 u8 cmd; 58 u16 val; 59 u16 mask; 60} __packed; 61 62struct 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 */ 73static unsigned char gpioa_clk; 74static unsigned int gpioa_freq = VPRBRD_GPIOA_FREQ_DEFAULT; 75module_param(gpioa_freq, uint, 0); 76MODULE_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 81static 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 131static 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 172static 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 209static 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 254static 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 275static 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 307static 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 340static 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 361static 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 385static 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 427static struct platform_driver vprbrd_gpio_driver = { 428 .driver.name = "viperboard-gpio", 429 .probe = vprbrd_gpio_probe, 430}; 431 432static 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} 460subsys_initcall(vprbrd_gpio_init); 461 462static void __exit vprbrd_gpio_exit(void) 463{ 464 platform_driver_unregister(&vprbrd_gpio_driver); 465} 466module_exit(vprbrd_gpio_exit); 467 468MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>"); 469MODULE_DESCRIPTION("GPIO driver for Nano River Techs Viperboard"); 470MODULE_LICENSE("GPL"); 471MODULE_ALIAS("platform:viperboard-gpio");