1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/
4 * Andrew Davis <afd@ti.com>
7 #include <linux/bitmap.h>
8 #include <linux/bitops.h>
9 #include <linux/delay.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/gpio/driver.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/spi/spi.h>
16 #define DEFAULT_NGPIO 8
19 * struct pisosr_gpio - GPIO driver data
20 * @chip: GPIO controller chip
21 * @spi: SPI device pointer
22 * @buffer: Buffer for device reads
23 * @buffer_size: Size of buffer
24 * @load_gpio: GPIO pin used to load input into device
25 * @lock: Protects read sequences
28 struct gpio_chip chip
;
29 struct spi_device
*spi
;
32 struct gpio_desc
*load_gpio
;
36 static int pisosr_gpio_refresh(struct pisosr_gpio
*gpio
)
40 mutex_lock(&gpio
->lock
);
42 if (gpio
->load_gpio
) {
43 gpiod_set_value_cansleep(gpio
->load_gpio
, 1);
44 udelay(1); /* registers load time (~10ns) */
45 gpiod_set_value_cansleep(gpio
->load_gpio
, 0);
46 udelay(1); /* registers recovery time (~5ns) */
49 ret
= spi_read(gpio
->spi
, gpio
->buffer
, gpio
->buffer_size
);
51 mutex_unlock(&gpio
->lock
);
56 static int pisosr_gpio_get_direction(struct gpio_chip
*chip
,
59 /* This device always input */
60 return GPIO_LINE_DIRECTION_IN
;
63 static int pisosr_gpio_direction_input(struct gpio_chip
*chip
,
66 /* This device always input */
70 static int pisosr_gpio_direction_output(struct gpio_chip
*chip
,
71 unsigned offset
, int value
)
73 /* This device is input only */
77 static int pisosr_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
79 struct pisosr_gpio
*gpio
= gpiochip_get_data(chip
);
81 /* Refresh may not always be needed */
82 pisosr_gpio_refresh(gpio
);
84 return (gpio
->buffer
[offset
/ 8] >> (offset
% 8)) & 0x1;
87 static int pisosr_gpio_get_multiple(struct gpio_chip
*chip
,
88 unsigned long *mask
, unsigned long *bits
)
90 struct pisosr_gpio
*gpio
= gpiochip_get_data(chip
);
92 unsigned long gpio_mask
;
93 unsigned long buffer_state
;
95 pisosr_gpio_refresh(gpio
);
97 bitmap_zero(bits
, chip
->ngpio
);
98 for_each_set_clump8(offset
, gpio_mask
, mask
, chip
->ngpio
) {
99 buffer_state
= gpio
->buffer
[offset
/ 8] & gpio_mask
;
100 bitmap_set_value8(bits
, buffer_state
, offset
);
106 static const struct gpio_chip template_chip
= {
107 .label
= "pisosr-gpio",
108 .owner
= THIS_MODULE
,
109 .get_direction
= pisosr_gpio_get_direction
,
110 .direction_input
= pisosr_gpio_direction_input
,
111 .direction_output
= pisosr_gpio_direction_output
,
112 .get
= pisosr_gpio_get
,
113 .get_multiple
= pisosr_gpio_get_multiple
,
115 .ngpio
= DEFAULT_NGPIO
,
119 static void pisosr_mutex_destroy(void *lock
)
124 static int pisosr_gpio_probe(struct spi_device
*spi
)
126 struct device
*dev
= &spi
->dev
;
127 struct pisosr_gpio
*gpio
;
130 gpio
= devm_kzalloc(dev
, sizeof(*gpio
), GFP_KERNEL
);
134 gpio
->chip
= template_chip
;
135 gpio
->chip
.parent
= dev
;
136 of_property_read_u16(dev
->of_node
, "ngpios", &gpio
->chip
.ngpio
);
140 gpio
->buffer_size
= DIV_ROUND_UP(gpio
->chip
.ngpio
, 8);
141 gpio
->buffer
= devm_kzalloc(dev
, gpio
->buffer_size
, GFP_KERNEL
);
145 gpio
->load_gpio
= devm_gpiod_get_optional(dev
, "load", GPIOD_OUT_LOW
);
146 if (IS_ERR(gpio
->load_gpio
))
147 return dev_err_probe(dev
, PTR_ERR(gpio
->load_gpio
),
148 "Unable to allocate load GPIO\n");
150 mutex_init(&gpio
->lock
);
151 ret
= devm_add_action_or_reset(dev
, pisosr_mutex_destroy
, &gpio
->lock
);
155 ret
= devm_gpiochip_add_data(dev
, &gpio
->chip
, gpio
);
157 dev_err(dev
, "Unable to register gpiochip\n");
164 static const struct spi_device_id pisosr_gpio_id_table
[] = {
168 MODULE_DEVICE_TABLE(spi
, pisosr_gpio_id_table
);
170 static const struct of_device_id pisosr_gpio_of_match_table
[] = {
171 { .compatible
= "pisosr-gpio", },
174 MODULE_DEVICE_TABLE(of
, pisosr_gpio_of_match_table
);
176 static struct spi_driver pisosr_gpio_driver
= {
178 .name
= "pisosr-gpio",
179 .of_match_table
= pisosr_gpio_of_match_table
,
181 .probe
= pisosr_gpio_probe
,
182 .id_table
= pisosr_gpio_id_table
,
184 module_spi_driver(pisosr_gpio_driver
);
186 MODULE_AUTHOR("Andrew Davis <afd@ti.com>");
187 MODULE_DESCRIPTION("SPI Compatible PISO Shift Register GPIO Driver");
188 MODULE_LICENSE("GPL v2");