root/drivers/gpio/gpio-da9052.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. da9052_gpio_port_odd
  2. da9052_gpio_get
  3. da9052_gpio_set
  4. da9052_gpio_direction_input
  5. da9052_gpio_direction_output
  6. da9052_gpio_to_irq
  7. da9052_gpio_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * GPIO Driver for Dialog DA9052 PMICs.
   4  *
   5  * Copyright(c) 2011 Dialog Semiconductor Ltd.
   6  *
   7  * Author: David Dajun Chen <dchen@diasemi.com>
   8  */
   9 #include <linux/module.h>
  10 #include <linux/fs.h>
  11 #include <linux/uaccess.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/gpio/driver.h>
  14 #include <linux/syscalls.h>
  15 #include <linux/seq_file.h>
  16 
  17 #include <linux/mfd/da9052/da9052.h>
  18 #include <linux/mfd/da9052/reg.h>
  19 #include <linux/mfd/da9052/pdata.h>
  20 
  21 #define DA9052_INPUT                            1
  22 #define DA9052_OUTPUT_OPENDRAIN         2
  23 #define DA9052_OUTPUT_PUSHPULL                  3
  24 
  25 #define DA9052_SUPPLY_VDD_IO1                   0
  26 
  27 #define DA9052_DEBOUNCING_OFF                   0
  28 #define DA9052_DEBOUNCING_ON                    1
  29 
  30 #define DA9052_OUTPUT_LOWLEVEL                  0
  31 
  32 #define DA9052_ACTIVE_LOW                       0
  33 #define DA9052_ACTIVE_HIGH                      1
  34 
  35 #define DA9052_GPIO_MAX_PORTS_PER_REGISTER      8
  36 #define DA9052_GPIO_SHIFT_COUNT(no)             (no%8)
  37 #define DA9052_GPIO_MASK_UPPER_NIBBLE           0xF0
  38 #define DA9052_GPIO_MASK_LOWER_NIBBLE           0x0F
  39 #define DA9052_GPIO_NIBBLE_SHIFT                4
  40 #define DA9052_IRQ_GPI0                 16
  41 #define DA9052_GPIO_ODD_SHIFT                   7
  42 #define DA9052_GPIO_EVEN_SHIFT                  3
  43 
  44 struct da9052_gpio {
  45         struct da9052 *da9052;
  46         struct gpio_chip gp;
  47 };
  48 
  49 static unsigned char da9052_gpio_port_odd(unsigned offset)
  50 {
  51         return offset % 2;
  52 }
  53 
  54 static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
  55 {
  56         struct da9052_gpio *gpio = gpiochip_get_data(gc);
  57         int da9052_port_direction = 0;
  58         int ret;
  59 
  60         ret = da9052_reg_read(gpio->da9052,
  61                               DA9052_GPIO_0_1_REG + (offset >> 1));
  62         if (ret < 0)
  63                 return ret;
  64 
  65         if (da9052_gpio_port_odd(offset)) {
  66                 da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN;
  67                 da9052_port_direction >>= 4;
  68         } else {
  69                 da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN;
  70         }
  71 
  72         switch (da9052_port_direction) {
  73         case DA9052_INPUT:
  74                 if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
  75                         ret = da9052_reg_read(gpio->da9052,
  76                                               DA9052_STATUS_C_REG);
  77                 else
  78                         ret = da9052_reg_read(gpio->da9052,
  79                                               DA9052_STATUS_D_REG);
  80                 if (ret < 0)
  81                         return ret;
  82                 return !!(ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset)));
  83         case DA9052_OUTPUT_PUSHPULL:
  84                 if (da9052_gpio_port_odd(offset))
  85                         return !!(ret & DA9052_GPIO_ODD_PORT_MODE);
  86                 else
  87                         return !!(ret & DA9052_GPIO_EVEN_PORT_MODE);
  88         default:
  89                 return -EINVAL;
  90         }
  91 }
  92 
  93 static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
  94 {
  95         struct da9052_gpio *gpio = gpiochip_get_data(gc);
  96         int ret;
  97 
  98         if (da9052_gpio_port_odd(offset)) {
  99                         ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 100                                                 DA9052_GPIO_0_1_REG,
 101                                                 DA9052_GPIO_ODD_PORT_MODE,
 102                                                 value << DA9052_GPIO_ODD_SHIFT);
 103                         if (ret != 0)
 104                                 dev_err(gpio->da9052->dev,
 105                                         "Failed to updated gpio odd reg,%d",
 106                                         ret);
 107         } else {
 108                         ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 109                                                 DA9052_GPIO_0_1_REG,
 110                                                 DA9052_GPIO_EVEN_PORT_MODE,
 111                                                 value << DA9052_GPIO_EVEN_SHIFT);
 112                         if (ret != 0)
 113                                 dev_err(gpio->da9052->dev,
 114                                         "Failed to updated gpio even reg,%d",
 115                                         ret);
 116         }
 117 }
 118 
 119 static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
 120 {
 121         struct da9052_gpio *gpio = gpiochip_get_data(gc);
 122         unsigned char register_value;
 123         int ret;
 124 
 125         /* Format: function - 2 bits type - 1 bit mode - 1 bit */
 126         register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 |
 127                          DA9052_DEBOUNCING_ON << 3;
 128 
 129         if (da9052_gpio_port_odd(offset))
 130                 ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 131                                         DA9052_GPIO_0_1_REG,
 132                                         DA9052_GPIO_MASK_UPPER_NIBBLE,
 133                                         (register_value <<
 134                                         DA9052_GPIO_NIBBLE_SHIFT));
 135         else
 136                 ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 137                                         DA9052_GPIO_0_1_REG,
 138                                         DA9052_GPIO_MASK_LOWER_NIBBLE,
 139                                         register_value);
 140 
 141         return ret;
 142 }
 143 
 144 static int da9052_gpio_direction_output(struct gpio_chip *gc,
 145                                         unsigned offset, int value)
 146 {
 147         struct da9052_gpio *gpio = gpiochip_get_data(gc);
 148         unsigned char register_value;
 149         int ret;
 150 
 151         /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */
 152         register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 |
 153                          value << 3;
 154 
 155         if (da9052_gpio_port_odd(offset))
 156                 ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 157                                         DA9052_GPIO_0_1_REG,
 158                                         DA9052_GPIO_MASK_UPPER_NIBBLE,
 159                                         (register_value <<
 160                                         DA9052_GPIO_NIBBLE_SHIFT));
 161         else
 162                 ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
 163                                         DA9052_GPIO_0_1_REG,
 164                                         DA9052_GPIO_MASK_LOWER_NIBBLE,
 165                                         register_value);
 166 
 167         return ret;
 168 }
 169 
 170 static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
 171 {
 172         struct da9052_gpio *gpio = gpiochip_get_data(gc);
 173         struct da9052 *da9052 = gpio->da9052;
 174 
 175         int irq;
 176 
 177         irq = regmap_irq_get_virq(da9052->irq_data, DA9052_IRQ_GPI0 + offset);
 178 
 179         return irq;
 180 }
 181 
 182 static const struct gpio_chip reference_gp = {
 183         .label = "da9052-gpio",
 184         .owner = THIS_MODULE,
 185         .get = da9052_gpio_get,
 186         .set = da9052_gpio_set,
 187         .direction_input = da9052_gpio_direction_input,
 188         .direction_output = da9052_gpio_direction_output,
 189         .to_irq = da9052_gpio_to_irq,
 190         .can_sleep = true,
 191         .ngpio = 16,
 192         .base = -1,
 193 };
 194 
 195 static int da9052_gpio_probe(struct platform_device *pdev)
 196 {
 197         struct da9052_gpio *gpio;
 198         struct da9052_pdata *pdata;
 199         int ret;
 200 
 201         gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
 202         if (!gpio)
 203                 return -ENOMEM;
 204 
 205         gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
 206         pdata = dev_get_platdata(gpio->da9052->dev);
 207 
 208         gpio->gp = reference_gp;
 209         if (pdata && pdata->gpio_base)
 210                 gpio->gp.base = pdata->gpio_base;
 211 
 212         ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
 213         if (ret < 0) {
 214                 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
 215                 return ret;
 216         }
 217 
 218         platform_set_drvdata(pdev, gpio);
 219 
 220         return 0;
 221 }
 222 
 223 static struct platform_driver da9052_gpio_driver = {
 224         .probe = da9052_gpio_probe,
 225         .driver = {
 226                 .name   = "da9052-gpio",
 227         },
 228 };
 229 
 230 module_platform_driver(da9052_gpio_driver);
 231 
 232 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
 233 MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
 234 MODULE_LICENSE("GPL");
 235 MODULE_ALIAS("platform:da9052-gpio");

/* [<][>][^][v][top][bottom][index][help] */