root/drivers/gpio/gpio-74x164.c

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

DEFINITIONS

This source file includes following definitions.
  1. __gen_74x164_write_config
  2. gen_74x164_get_value
  3. gen_74x164_set_value
  4. gen_74x164_set_multiple
  5. gen_74x164_direction_output
  6. gen_74x164_probe
  7. gen_74x164_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
   4  *
   5  *  Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
   6  *  Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.com>
   7  */
   8 
   9 #include <linux/gpio/consumer.h>
  10 #include <linux/gpio/driver.h>
  11 #include <linux/module.h>
  12 #include <linux/mutex.h>
  13 #include <linux/property.h>
  14 #include <linux/slab.h>
  15 #include <linux/spi/spi.h>
  16 
  17 #define GEN_74X164_NUMBER_GPIOS 8
  18 
  19 struct gen_74x164_chip {
  20         struct gpio_chip        gpio_chip;
  21         struct mutex            lock;
  22         struct gpio_desc        *gpiod_oe;
  23         u32                     registers;
  24         /*
  25          * Since the registers are chained, every byte sent will make
  26          * the previous byte shift to the next register in the
  27          * chain. Thus, the first byte sent will end up in the last
  28          * register at the end of the transfer. So, to have a logical
  29          * numbering, store the bytes in reverse order.
  30          */
  31         u8                      buffer[];
  32 };
  33 
  34 static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
  35 {
  36         return spi_write(to_spi_device(chip->gpio_chip.parent), chip->buffer,
  37                          chip->registers);
  38 }
  39 
  40 static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
  41 {
  42         struct gen_74x164_chip *chip = gpiochip_get_data(gc);
  43         u8 bank = chip->registers - 1 - offset / 8;
  44         u8 pin = offset % 8;
  45         int ret;
  46 
  47         mutex_lock(&chip->lock);
  48         ret = (chip->buffer[bank] >> pin) & 0x1;
  49         mutex_unlock(&chip->lock);
  50 
  51         return ret;
  52 }
  53 
  54 static void gen_74x164_set_value(struct gpio_chip *gc,
  55                 unsigned offset, int val)
  56 {
  57         struct gen_74x164_chip *chip = gpiochip_get_data(gc);
  58         u8 bank = chip->registers - 1 - offset / 8;
  59         u8 pin = offset % 8;
  60 
  61         mutex_lock(&chip->lock);
  62         if (val)
  63                 chip->buffer[bank] |= (1 << pin);
  64         else
  65                 chip->buffer[bank] &= ~(1 << pin);
  66 
  67         __gen_74x164_write_config(chip);
  68         mutex_unlock(&chip->lock);
  69 }
  70 
  71 static void gen_74x164_set_multiple(struct gpio_chip *gc, unsigned long *mask,
  72                                     unsigned long *bits)
  73 {
  74         struct gen_74x164_chip *chip = gpiochip_get_data(gc);
  75         unsigned int i, idx, shift;
  76         u8 bank, bankmask;
  77 
  78         mutex_lock(&chip->lock);
  79         for (i = 0, bank = chip->registers - 1; i < chip->registers;
  80              i++, bank--) {
  81                 idx = i / sizeof(*mask);
  82                 shift = i % sizeof(*mask) * BITS_PER_BYTE;
  83                 bankmask = mask[idx] >> shift;
  84                 if (!bankmask)
  85                         continue;
  86 
  87                 chip->buffer[bank] &= ~bankmask;
  88                 chip->buffer[bank] |= bankmask & (bits[idx] >> shift);
  89         }
  90         __gen_74x164_write_config(chip);
  91         mutex_unlock(&chip->lock);
  92 }
  93 
  94 static int gen_74x164_direction_output(struct gpio_chip *gc,
  95                 unsigned offset, int val)
  96 {
  97         gen_74x164_set_value(gc, offset, val);
  98         return 0;
  99 }
 100 
 101 static int gen_74x164_probe(struct spi_device *spi)
 102 {
 103         struct gen_74x164_chip *chip;
 104         u32 nregs;
 105         int ret;
 106 
 107         /*
 108          * bits_per_word cannot be configured in platform data
 109          */
 110         spi->bits_per_word = 8;
 111 
 112         ret = spi_setup(spi);
 113         if (ret < 0)
 114                 return ret;
 115 
 116         ret = device_property_read_u32(&spi->dev, "registers-number", &nregs);
 117         if (ret) {
 118                 dev_err(&spi->dev, "Missing 'registers-number' property.\n");
 119                 return -EINVAL;
 120         }
 121 
 122         chip = devm_kzalloc(&spi->dev, sizeof(*chip) + nregs, GFP_KERNEL);
 123         if (!chip)
 124                 return -ENOMEM;
 125 
 126         chip->gpiod_oe = devm_gpiod_get_optional(&spi->dev, "enable",
 127                                                  GPIOD_OUT_LOW);
 128         if (IS_ERR(chip->gpiod_oe))
 129                 return PTR_ERR(chip->gpiod_oe);
 130 
 131         gpiod_set_value_cansleep(chip->gpiod_oe, 1);
 132 
 133         spi_set_drvdata(spi, chip);
 134 
 135         chip->gpio_chip.label = spi->modalias;
 136         chip->gpio_chip.direction_output = gen_74x164_direction_output;
 137         chip->gpio_chip.get = gen_74x164_get_value;
 138         chip->gpio_chip.set = gen_74x164_set_value;
 139         chip->gpio_chip.set_multiple = gen_74x164_set_multiple;
 140         chip->gpio_chip.base = -1;
 141 
 142         chip->registers = nregs;
 143         chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
 144 
 145         chip->gpio_chip.can_sleep = true;
 146         chip->gpio_chip.parent = &spi->dev;
 147         chip->gpio_chip.owner = THIS_MODULE;
 148 
 149         mutex_init(&chip->lock);
 150 
 151         ret = __gen_74x164_write_config(chip);
 152         if (ret) {
 153                 dev_err(&spi->dev, "Failed writing: %d\n", ret);
 154                 goto exit_destroy;
 155         }
 156 
 157         ret = gpiochip_add_data(&chip->gpio_chip, chip);
 158         if (!ret)
 159                 return 0;
 160 
 161 exit_destroy:
 162         mutex_destroy(&chip->lock);
 163 
 164         return ret;
 165 }
 166 
 167 static int gen_74x164_remove(struct spi_device *spi)
 168 {
 169         struct gen_74x164_chip *chip = spi_get_drvdata(spi);
 170 
 171         gpiod_set_value_cansleep(chip->gpiod_oe, 0);
 172         gpiochip_remove(&chip->gpio_chip);
 173         mutex_destroy(&chip->lock);
 174 
 175         return 0;
 176 }
 177 
 178 static const struct of_device_id gen_74x164_dt_ids[] = {
 179         { .compatible = "fairchild,74hc595" },
 180         { .compatible = "nxp,74lvc594" },
 181         {},
 182 };
 183 MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);
 184 
 185 static struct spi_driver gen_74x164_driver = {
 186         .driver = {
 187                 .name           = "74x164",
 188                 .of_match_table = gen_74x164_dt_ids,
 189         },
 190         .probe          = gen_74x164_probe,
 191         .remove         = gen_74x164_remove,
 192 };
 193 module_spi_driver(gen_74x164_driver);
 194 
 195 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
 196 MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
 197 MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register");
 198 MODULE_LICENSE("GPL v2");

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