linux/drivers/gpio/gpio-viperboard.c
<<
>>
Prefs
   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 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 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 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 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 offset,
 255        unsigned 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 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 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 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 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        ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio);
 408        if (ret < 0) {
 409                dev_err(vb_gpio->gpioa.parent, "could not add gpio a");
 410                return ret;
 411        }
 412
 413        /* registering gpio b */
 414        vb_gpio->gpiob.label = "viperboard gpio b";
 415        vb_gpio->gpiob.parent = &pdev->dev;
 416        vb_gpio->gpiob.owner = THIS_MODULE;
 417        vb_gpio->gpiob.base = -1;
 418        vb_gpio->gpiob.ngpio = 16;
 419        vb_gpio->gpiob.can_sleep = true;
 420        vb_gpio->gpiob.set = vprbrd_gpiob_set;
 421        vb_gpio->gpiob.get = vprbrd_gpiob_get;
 422        vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input;
 423        vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
 424        ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
 425        if (ret < 0) {
 426                dev_err(vb_gpio->gpiob.parent, "could not add gpio b");
 427                return ret;
 428        }
 429
 430        platform_set_drvdata(pdev, vb_gpio);
 431
 432        return ret;
 433}
 434
 435static struct platform_driver vprbrd_gpio_driver = {
 436        .driver.name    = "viperboard-gpio",
 437        .probe          = vprbrd_gpio_probe,
 438};
 439
 440static int __init vprbrd_gpio_init(void)
 441{
 442        switch (gpioa_freq) {
 443        case 1000000:
 444                gpioa_clk = VPRBRD_GPIOA_CLK_1MHZ;
 445                break;
 446        case 100000:
 447                gpioa_clk = VPRBRD_GPIOA_CLK_100KHZ;
 448                break;
 449        case 10000:
 450                gpioa_clk = VPRBRD_GPIOA_CLK_10KHZ;
 451                break;
 452        case 1000:
 453                gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
 454                break;
 455        case 100:
 456                gpioa_clk = VPRBRD_GPIOA_CLK_100HZ;
 457                break;
 458        case 10:
 459                gpioa_clk = VPRBRD_GPIOA_CLK_10HZ;
 460                break;
 461        default:
 462                pr_warn("invalid gpioa_freq (%d)\n", gpioa_freq);
 463                gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
 464        }
 465
 466        return platform_driver_register(&vprbrd_gpio_driver);
 467}
 468subsys_initcall(vprbrd_gpio_init);
 469
 470static void __exit vprbrd_gpio_exit(void)
 471{
 472        platform_driver_unregister(&vprbrd_gpio_driver);
 473}
 474module_exit(vprbrd_gpio_exit);
 475
 476MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
 477MODULE_DESCRIPTION("GPIO driver for Nano River Techs Viperboard");
 478MODULE_LICENSE("GPL");
 479MODULE_ALIAS("platform:viperboard-gpio");
 480