root/drivers/gpio/gpio-moxtet.c

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

DEFINITIONS

This source file includes following definitions.
  1. moxtet_gpio_get_value
  2. moxtet_gpio_set_value
  3. moxtet_gpio_get_direction
  4. moxtet_gpio_direction_input
  5. moxtet_gpio_direction_output
  6. moxtet_gpio_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  Turris Mox Moxtet GPIO expander
   4  *
   5  *  Copyright (C) 2018 Marek Behun <marek.behun@nic.cz>
   6  */
   7 
   8 #include <linux/bitops.h>
   9 #include <linux/gpio/driver.h>
  10 #include <linux/moxtet.h>
  11 #include <linux/module.h>
  12 
  13 #define MOXTET_GPIO_NGPIOS      12
  14 #define MOXTET_GPIO_INPUTS      4
  15 
  16 struct moxtet_gpio_desc {
  17         u16 in_mask;
  18         u16 out_mask;
  19 };
  20 
  21 static const struct moxtet_gpio_desc descs[] = {
  22         [TURRIS_MOX_MODULE_SFP] = {
  23                 .in_mask = GENMASK(2, 0),
  24                 .out_mask = GENMASK(5, 4),
  25         },
  26 };
  27 
  28 struct moxtet_gpio_chip {
  29         struct device                   *dev;
  30         struct gpio_chip                gpio_chip;
  31         const struct moxtet_gpio_desc   *desc;
  32 };
  33 
  34 static int moxtet_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
  35 {
  36         struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
  37         int ret;
  38 
  39         if (chip->desc->in_mask & BIT(offset)) {
  40                 ret = moxtet_device_read(chip->dev);
  41         } else if (chip->desc->out_mask & BIT(offset)) {
  42                 ret = moxtet_device_written(chip->dev);
  43                 if (ret >= 0)
  44                         ret <<= MOXTET_GPIO_INPUTS;
  45         } else {
  46                 return -EINVAL;
  47         }
  48 
  49         if (ret < 0)
  50                 return ret;
  51 
  52         return !!(ret & BIT(offset));
  53 }
  54 
  55 static void moxtet_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
  56                                   int val)
  57 {
  58         struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
  59         int state;
  60 
  61         state = moxtet_device_written(chip->dev);
  62         if (state < 0)
  63                 return;
  64 
  65         offset -= MOXTET_GPIO_INPUTS;
  66 
  67         if (val)
  68                 state |= BIT(offset);
  69         else
  70                 state &= ~BIT(offset);
  71 
  72         moxtet_device_write(chip->dev, state);
  73 }
  74 
  75 static int moxtet_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
  76 {
  77         struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
  78 
  79         /* All lines are hard wired to be either input or output, not both. */
  80         if (chip->desc->in_mask & BIT(offset))
  81                 return 1;
  82         else if (chip->desc->out_mask & BIT(offset))
  83                 return 0;
  84         else
  85                 return -EINVAL;
  86 }
  87 
  88 static int moxtet_gpio_direction_input(struct gpio_chip *gc,
  89                                        unsigned int offset)
  90 {
  91         struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
  92 
  93         if (chip->desc->in_mask & BIT(offset))
  94                 return 0;
  95         else if (chip->desc->out_mask & BIT(offset))
  96                 return -ENOTSUPP;
  97         else
  98                 return -EINVAL;
  99 }
 100 
 101 static int moxtet_gpio_direction_output(struct gpio_chip *gc,
 102                                         unsigned int offset, int val)
 103 {
 104         struct moxtet_gpio_chip *chip = gpiochip_get_data(gc);
 105 
 106         if (chip->desc->out_mask & BIT(offset))
 107                 moxtet_gpio_set_value(gc, offset, val);
 108         else if (chip->desc->in_mask & BIT(offset))
 109                 return -ENOTSUPP;
 110         else
 111                 return -EINVAL;
 112 
 113         return 0;
 114 }
 115 
 116 static int moxtet_gpio_probe(struct device *dev)
 117 {
 118         struct moxtet_gpio_chip *chip;
 119         struct device_node *nc = dev->of_node;
 120         int id;
 121 
 122         id = to_moxtet_device(dev)->id;
 123 
 124         if (id >= ARRAY_SIZE(descs)) {
 125                 dev_err(dev, "%pOF Moxtet device id 0x%x is not supported by gpio-moxtet driver\n",
 126                         nc, id);
 127                 return -ENOTSUPP;
 128         }
 129 
 130         chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 131         if (!chip)
 132                 return -ENOMEM;
 133 
 134         chip->dev = dev;
 135         chip->gpio_chip.parent = dev;
 136         chip->desc = &descs[id];
 137 
 138         dev_set_drvdata(dev, chip);
 139 
 140         chip->gpio_chip.label = dev_name(dev);
 141         chip->gpio_chip.get_direction = moxtet_gpio_get_direction;
 142         chip->gpio_chip.direction_input = moxtet_gpio_direction_input;
 143         chip->gpio_chip.direction_output = moxtet_gpio_direction_output;
 144         chip->gpio_chip.get = moxtet_gpio_get_value;
 145         chip->gpio_chip.set = moxtet_gpio_set_value;
 146         chip->gpio_chip.base = -1;
 147 
 148         chip->gpio_chip.ngpio = MOXTET_GPIO_NGPIOS;
 149 
 150         chip->gpio_chip.can_sleep = true;
 151         chip->gpio_chip.owner = THIS_MODULE;
 152 
 153         return devm_gpiochip_add_data(dev, &chip->gpio_chip, chip);
 154 }
 155 
 156 static const struct of_device_id moxtet_gpio_dt_ids[] = {
 157         { .compatible = "cznic,moxtet-gpio", },
 158         {},
 159 };
 160 MODULE_DEVICE_TABLE(of, moxtet_gpio_dt_ids);
 161 
 162 static const enum turris_mox_module_id moxtet_gpio_module_table[] = {
 163         TURRIS_MOX_MODULE_SFP,
 164         0,
 165 };
 166 
 167 static struct moxtet_driver moxtet_gpio_driver = {
 168         .driver = {
 169                 .name           = "moxtet-gpio",
 170                 .of_match_table = moxtet_gpio_dt_ids,
 171                 .probe          = moxtet_gpio_probe,
 172         },
 173         .id_table = moxtet_gpio_module_table,
 174 };
 175 module_moxtet_driver(moxtet_gpio_driver);
 176 
 177 MODULE_AUTHOR("Marek Behun <marek.behun@nic.cz>");
 178 MODULE_DESCRIPTION("Turris Mox Moxtet GPIO expander");
 179 MODULE_LICENSE("GPL v2");

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