Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Nano River Technologies viperboard GPIO lib driver
0004  *
0005  *  (C) 2012 by Lemonage GmbH
0006  *  Author: Lars Poeschel <poeschel@lemonage.de>
0007  *  All rights reserved.
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/errno.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/types.h>
0015 #include <linux/mutex.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/usb.h>
0018 #include <linux/gpio/driver.h>
0019 
0020 #include <linux/mfd/viperboard.h>
0021 
0022 #define VPRBRD_GPIOA_CLK_1MHZ       0
0023 #define VPRBRD_GPIOA_CLK_100KHZ     1
0024 #define VPRBRD_GPIOA_CLK_10KHZ      2
0025 #define VPRBRD_GPIOA_CLK_1KHZ       3
0026 #define VPRBRD_GPIOA_CLK_100HZ      4
0027 #define VPRBRD_GPIOA_CLK_10HZ       5
0028 
0029 #define VPRBRD_GPIOA_FREQ_DEFAULT   1000
0030 
0031 #define VPRBRD_GPIOA_CMD_CONT       0x00
0032 #define VPRBRD_GPIOA_CMD_PULSE      0x01
0033 #define VPRBRD_GPIOA_CMD_PWM        0x02
0034 #define VPRBRD_GPIOA_CMD_SETOUT     0x03
0035 #define VPRBRD_GPIOA_CMD_SETIN      0x04
0036 #define VPRBRD_GPIOA_CMD_SETINT     0x05
0037 #define VPRBRD_GPIOA_CMD_GETIN      0x06
0038 
0039 #define VPRBRD_GPIOB_CMD_SETDIR     0x00
0040 #define VPRBRD_GPIOB_CMD_SETVAL     0x01
0041 
0042 struct vprbrd_gpioa_msg {
0043     u8 cmd;
0044     u8 clk;
0045     u8 offset;
0046     u8 t1;
0047     u8 t2;
0048     u8 invert;
0049     u8 pwmlevel;
0050     u8 outval;
0051     u8 risefall;
0052     u8 answer;
0053     u8 __fill;
0054 } __packed;
0055 
0056 struct vprbrd_gpiob_msg {
0057     u8 cmd;
0058     u16 val;
0059     u16 mask;
0060 } __packed;
0061 
0062 struct vprbrd_gpio {
0063     struct gpio_chip gpioa; /* gpio a related things */
0064     u32 gpioa_out;
0065     u32 gpioa_val;
0066     struct gpio_chip gpiob; /* gpio b related things */
0067     u32 gpiob_out;
0068     u32 gpiob_val;
0069     struct vprbrd *vb;
0070 };
0071 
0072 /* gpioa sampling clock module parameter */
0073 static unsigned char gpioa_clk;
0074 static unsigned int gpioa_freq = VPRBRD_GPIOA_FREQ_DEFAULT;
0075 module_param(gpioa_freq, uint, 0);
0076 MODULE_PARM_DESC(gpioa_freq,
0077     "gpio-a sampling freq in Hz (default is 1000Hz) valid values: 10, 100, 1000, 10000, 100000, 1000000");
0078 
0079 /* ----- begin of gipo a chip -------------------------------------------- */
0080 
0081 static int vprbrd_gpioa_get(struct gpio_chip *chip,
0082         unsigned int offset)
0083 {
0084     int ret, answer, error = 0;
0085     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0086     struct vprbrd *vb = gpio->vb;
0087     struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
0088 
0089     /* if io is set to output, just return the saved value */
0090     if (gpio->gpioa_out & (1 << offset))
0091         return !!(gpio->gpioa_val & (1 << offset));
0092 
0093     mutex_lock(&vb->lock);
0094 
0095     gamsg->cmd = VPRBRD_GPIOA_CMD_GETIN;
0096     gamsg->clk = 0x00;
0097     gamsg->offset = offset;
0098     gamsg->t1 = 0x00;
0099     gamsg->t2 = 0x00;
0100     gamsg->invert = 0x00;
0101     gamsg->pwmlevel = 0x00;
0102     gamsg->outval = 0x00;
0103     gamsg->risefall = 0x00;
0104     gamsg->answer = 0x00;
0105     gamsg->__fill = 0x00;
0106 
0107     ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
0108         VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
0109         0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
0110         VPRBRD_USB_TIMEOUT_MS);
0111     if (ret != sizeof(struct vprbrd_gpioa_msg))
0112         error = -EREMOTEIO;
0113 
0114     ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0),
0115         VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_IN, 0x0000,
0116         0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
0117         VPRBRD_USB_TIMEOUT_MS);
0118     answer = gamsg->answer & 0x01;
0119 
0120     mutex_unlock(&vb->lock);
0121 
0122     if (ret != sizeof(struct vprbrd_gpioa_msg))
0123         error = -EREMOTEIO;
0124 
0125     if (error)
0126         return error;
0127 
0128     return answer;
0129 }
0130 
0131 static void vprbrd_gpioa_set(struct gpio_chip *chip,
0132         unsigned int offset, int value)
0133 {
0134     int ret;
0135     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0136     struct vprbrd *vb = gpio->vb;
0137     struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
0138 
0139     if (gpio->gpioa_out & (1 << offset)) {
0140         if (value)
0141             gpio->gpioa_val |= (1 << offset);
0142         else
0143             gpio->gpioa_val &= ~(1 << offset);
0144 
0145         mutex_lock(&vb->lock);
0146 
0147         gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT;
0148         gamsg->clk = 0x00;
0149         gamsg->offset = offset;
0150         gamsg->t1 = 0x00;
0151         gamsg->t2 = 0x00;
0152         gamsg->invert = 0x00;
0153         gamsg->pwmlevel = 0x00;
0154         gamsg->outval = value;
0155         gamsg->risefall = 0x00;
0156         gamsg->answer = 0x00;
0157         gamsg->__fill = 0x00;
0158 
0159         ret = usb_control_msg(vb->usb_dev,
0160             usb_sndctrlpipe(vb->usb_dev, 0),
0161             VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT,
0162             0x0000, 0x0000, gamsg,
0163             sizeof(struct vprbrd_gpioa_msg), VPRBRD_USB_TIMEOUT_MS);
0164 
0165         mutex_unlock(&vb->lock);
0166 
0167         if (ret != sizeof(struct vprbrd_gpioa_msg))
0168             dev_err(chip->parent, "usb error setting pin value\n");
0169     }
0170 }
0171 
0172 static int vprbrd_gpioa_direction_input(struct gpio_chip *chip,
0173             unsigned int offset)
0174 {
0175     int ret;
0176     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0177     struct vprbrd *vb = gpio->vb;
0178     struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
0179 
0180     gpio->gpioa_out &= ~(1 << offset);
0181 
0182     mutex_lock(&vb->lock);
0183 
0184     gamsg->cmd = VPRBRD_GPIOA_CMD_SETIN;
0185     gamsg->clk = gpioa_clk;
0186     gamsg->offset = offset;
0187     gamsg->t1 = 0x00;
0188     gamsg->t2 = 0x00;
0189     gamsg->invert = 0x00;
0190     gamsg->pwmlevel = 0x00;
0191     gamsg->outval = 0x00;
0192     gamsg->risefall = 0x00;
0193     gamsg->answer = 0x00;
0194     gamsg->__fill = 0x00;
0195 
0196     ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
0197         VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
0198         0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
0199         VPRBRD_USB_TIMEOUT_MS);
0200 
0201     mutex_unlock(&vb->lock);
0202 
0203     if (ret != sizeof(struct vprbrd_gpioa_msg))
0204         return -EREMOTEIO;
0205 
0206     return 0;
0207 }
0208 
0209 static int vprbrd_gpioa_direction_output(struct gpio_chip *chip,
0210             unsigned int offset, int value)
0211 {
0212     int ret;
0213     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0214     struct vprbrd *vb = gpio->vb;
0215     struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf;
0216 
0217     gpio->gpioa_out |= (1 << offset);
0218     if (value)
0219         gpio->gpioa_val |= (1 << offset);
0220     else
0221         gpio->gpioa_val &= ~(1 << offset);
0222 
0223     mutex_lock(&vb->lock);
0224 
0225     gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT;
0226     gamsg->clk = 0x00;
0227     gamsg->offset = offset;
0228     gamsg->t1 = 0x00;
0229     gamsg->t2 = 0x00;
0230     gamsg->invert = 0x00;
0231     gamsg->pwmlevel = 0x00;
0232     gamsg->outval = value;
0233     gamsg->risefall = 0x00;
0234     gamsg->answer = 0x00;
0235     gamsg->__fill = 0x00;
0236 
0237     ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
0238         VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, 0x0000,
0239         0x0000, gamsg, sizeof(struct vprbrd_gpioa_msg),
0240         VPRBRD_USB_TIMEOUT_MS);
0241 
0242     mutex_unlock(&vb->lock);
0243 
0244     if (ret != sizeof(struct vprbrd_gpioa_msg))
0245         return -EREMOTEIO;
0246 
0247     return 0;
0248 }
0249 
0250 /* ----- end of gpio a chip ---------------------------------------------- */
0251 
0252 /* ----- begin of gipo b chip -------------------------------------------- */
0253 
0254 static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned int offset,
0255     unsigned int dir)
0256 {
0257     struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
0258     int ret;
0259 
0260     gbmsg->cmd = VPRBRD_GPIOB_CMD_SETDIR;
0261     gbmsg->val = cpu_to_be16(dir << offset);
0262     gbmsg->mask = cpu_to_be16(0x0001 << offset);
0263 
0264     ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0),
0265         VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT, 0x0000,
0266         0x0000, gbmsg, sizeof(struct vprbrd_gpiob_msg),
0267         VPRBRD_USB_TIMEOUT_MS);
0268 
0269     if (ret != sizeof(struct vprbrd_gpiob_msg))
0270         return -EREMOTEIO;
0271 
0272     return 0;
0273 }
0274 
0275 static int vprbrd_gpiob_get(struct gpio_chip *chip,
0276         unsigned int offset)
0277 {
0278     int ret;
0279     u16 val;
0280     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0281     struct vprbrd *vb = gpio->vb;
0282     struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
0283 
0284     /* if io is set to output, just return the saved value */
0285     if (gpio->gpiob_out & (1 << offset))
0286         return gpio->gpiob_val & (1 << offset);
0287 
0288     mutex_lock(&vb->lock);
0289 
0290     ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0),
0291         VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_IN, 0x0000,
0292         0x0000, gbmsg,  sizeof(struct vprbrd_gpiob_msg),
0293         VPRBRD_USB_TIMEOUT_MS);
0294     val = gbmsg->val;
0295 
0296     mutex_unlock(&vb->lock);
0297 
0298     if (ret != sizeof(struct vprbrd_gpiob_msg))
0299         return ret;
0300 
0301     /* cache the read values */
0302     gpio->gpiob_val = be16_to_cpu(val);
0303 
0304     return (gpio->gpiob_val >> offset) & 0x1;
0305 }
0306 
0307 static void vprbrd_gpiob_set(struct gpio_chip *chip,
0308         unsigned int offset, int value)
0309 {
0310     int ret;
0311     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0312     struct vprbrd *vb = gpio->vb;
0313     struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
0314 
0315     if (gpio->gpiob_out & (1 << offset)) {
0316         if (value)
0317             gpio->gpiob_val |= (1 << offset);
0318         else
0319             gpio->gpiob_val &= ~(1 << offset);
0320 
0321         mutex_lock(&vb->lock);
0322 
0323         gbmsg->cmd = VPRBRD_GPIOB_CMD_SETVAL;
0324         gbmsg->val = cpu_to_be16(value << offset);
0325         gbmsg->mask = cpu_to_be16(0x0001 << offset);
0326 
0327         ret = usb_control_msg(vb->usb_dev,
0328             usb_sndctrlpipe(vb->usb_dev, 0),
0329             VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT,
0330             0x0000, 0x0000, gbmsg,
0331             sizeof(struct vprbrd_gpiob_msg), VPRBRD_USB_TIMEOUT_MS);
0332 
0333         mutex_unlock(&vb->lock);
0334 
0335         if (ret != sizeof(struct vprbrd_gpiob_msg))
0336             dev_err(chip->parent, "usb error setting pin value\n");
0337     }
0338 }
0339 
0340 static int vprbrd_gpiob_direction_input(struct gpio_chip *chip,
0341             unsigned int offset)
0342 {
0343     int ret;
0344     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0345     struct vprbrd *vb = gpio->vb;
0346 
0347     gpio->gpiob_out &= ~(1 << offset);
0348 
0349     mutex_lock(&vb->lock);
0350 
0351     ret = vprbrd_gpiob_setdir(vb, offset, 0);
0352 
0353     mutex_unlock(&vb->lock);
0354 
0355     if (ret)
0356         dev_err(chip->parent, "usb error setting pin to input\n");
0357 
0358     return ret;
0359 }
0360 
0361 static int vprbrd_gpiob_direction_output(struct gpio_chip *chip,
0362             unsigned int offset, int value)
0363 {
0364     int ret;
0365     struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
0366     struct vprbrd *vb = gpio->vb;
0367 
0368     gpio->gpiob_out |= (1 << offset);
0369 
0370     mutex_lock(&vb->lock);
0371 
0372     ret = vprbrd_gpiob_setdir(vb, offset, 1);
0373     if (ret)
0374         dev_err(chip->parent, "usb error setting pin to output\n");
0375 
0376     mutex_unlock(&vb->lock);
0377 
0378     vprbrd_gpiob_set(chip, offset, value);
0379 
0380     return ret;
0381 }
0382 
0383 /* ----- end of gpio b chip ---------------------------------------------- */
0384 
0385 static int vprbrd_gpio_probe(struct platform_device *pdev)
0386 {
0387     struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
0388     struct vprbrd_gpio *vb_gpio;
0389     int ret;
0390 
0391     vb_gpio = devm_kzalloc(&pdev->dev, sizeof(*vb_gpio), GFP_KERNEL);
0392     if (vb_gpio == NULL)
0393         return -ENOMEM;
0394 
0395     vb_gpio->vb = vb;
0396     /* registering gpio a */
0397     vb_gpio->gpioa.label = "viperboard gpio a";
0398     vb_gpio->gpioa.parent = &pdev->dev;
0399     vb_gpio->gpioa.owner = THIS_MODULE;
0400     vb_gpio->gpioa.base = -1;
0401     vb_gpio->gpioa.ngpio = 16;
0402     vb_gpio->gpioa.can_sleep = true;
0403     vb_gpio->gpioa.set = vprbrd_gpioa_set;
0404     vb_gpio->gpioa.get = vprbrd_gpioa_get;
0405     vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input;
0406     vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output;
0407 
0408     ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio);
0409     if (ret < 0)
0410         return ret;
0411 
0412     /* registering gpio b */
0413     vb_gpio->gpiob.label = "viperboard gpio b";
0414     vb_gpio->gpiob.parent = &pdev->dev;
0415     vb_gpio->gpiob.owner = THIS_MODULE;
0416     vb_gpio->gpiob.base = -1;
0417     vb_gpio->gpiob.ngpio = 16;
0418     vb_gpio->gpiob.can_sleep = true;
0419     vb_gpio->gpiob.set = vprbrd_gpiob_set;
0420     vb_gpio->gpiob.get = vprbrd_gpiob_get;
0421     vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input;
0422     vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
0423 
0424     return devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
0425 }
0426 
0427 static struct platform_driver vprbrd_gpio_driver = {
0428     .driver.name    = "viperboard-gpio",
0429     .probe      = vprbrd_gpio_probe,
0430 };
0431 
0432 static int __init vprbrd_gpio_init(void)
0433 {
0434     switch (gpioa_freq) {
0435     case 1000000:
0436         gpioa_clk = VPRBRD_GPIOA_CLK_1MHZ;
0437         break;
0438     case 100000:
0439         gpioa_clk = VPRBRD_GPIOA_CLK_100KHZ;
0440         break;
0441     case 10000:
0442         gpioa_clk = VPRBRD_GPIOA_CLK_10KHZ;
0443         break;
0444     case 1000:
0445         gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
0446         break;
0447     case 100:
0448         gpioa_clk = VPRBRD_GPIOA_CLK_100HZ;
0449         break;
0450     case 10:
0451         gpioa_clk = VPRBRD_GPIOA_CLK_10HZ;
0452         break;
0453     default:
0454         pr_warn("invalid gpioa_freq (%d)\n", gpioa_freq);
0455         gpioa_clk = VPRBRD_GPIOA_CLK_1KHZ;
0456     }
0457 
0458     return platform_driver_register(&vprbrd_gpio_driver);
0459 }
0460 subsys_initcall(vprbrd_gpio_init);
0461 
0462 static void __exit vprbrd_gpio_exit(void)
0463 {
0464     platform_driver_unregister(&vprbrd_gpio_driver);
0465 }
0466 module_exit(vprbrd_gpio_exit);
0467 
0468 MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
0469 MODULE_DESCRIPTION("GPIO driver for Nano River Techs Viperboard");
0470 MODULE_LICENSE("GPL");
0471 MODULE_ALIAS("platform:viperboard-gpio");