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