1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * GPIO driver for EXAR XRA1403 16-bit GPIO expander |
4 | * |
5 | * Copyright (c) 2017, General Electric Company |
6 | */ |
7 | |
8 | #include <linux/bitops.h> |
9 | #include <linux/gpio/driver.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/mod_devicetable.h> |
12 | #include <linux/module.h> |
13 | #include <linux/mutex.h> |
14 | #include <linux/seq_file.h> |
15 | #include <linux/spi/spi.h> |
16 | #include <linux/regmap.h> |
17 | |
18 | /* XRA1403 registers */ |
19 | #define XRA_GSR 0x00 /* GPIO State */ |
20 | #define XRA_OCR 0x02 /* Output Control */ |
21 | #define XRA_PIR 0x04 /* Input Polarity Inversion */ |
22 | #define XRA_GCR 0x06 /* GPIO Configuration */ |
23 | #define XRA_PUR 0x08 /* Input Internal Pull-up Resistor Enable/Disable */ |
24 | #define XRA_IER 0x0A /* Input Interrupt Enable */ |
25 | #define XRA_TSCR 0x0C /* Output Three-State Control */ |
26 | #define XRA_ISR 0x0E /* Input Interrupt Status */ |
27 | #define XRA_REIR 0x10 /* Input Rising Edge Interrupt Enable */ |
28 | #define XRA_FEIR 0x12 /* Input Falling Edge Interrupt Enable */ |
29 | #define XRA_IFR 0x14 /* Input Filter Enable/Disable */ |
30 | #define XRA_LAST 0x15 /* Bounds */ |
31 | |
32 | struct xra1403 { |
33 | struct gpio_chip chip; |
34 | struct regmap *regmap; |
35 | }; |
36 | |
37 | static const struct regmap_config xra1403_regmap_cfg = { |
38 | .reg_bits = 7, |
39 | .pad_bits = 1, |
40 | .val_bits = 8, |
41 | |
42 | .max_register = XRA_LAST, |
43 | }; |
44 | |
45 | static unsigned int to_reg(unsigned int reg, unsigned int offset) |
46 | { |
47 | return reg + (offset > 7); |
48 | } |
49 | |
50 | static int xra1403_direction_input(struct gpio_chip *chip, unsigned int offset) |
51 | { |
52 | struct xra1403 *xra = gpiochip_get_data(gc: chip); |
53 | |
54 | return regmap_update_bits(map: xra->regmap, reg: to_reg(XRA_GCR, offset), |
55 | BIT(offset % 8), BIT(offset % 8)); |
56 | } |
57 | |
58 | static int xra1403_direction_output(struct gpio_chip *chip, unsigned int offset, |
59 | int value) |
60 | { |
61 | int ret; |
62 | struct xra1403 *xra = gpiochip_get_data(gc: chip); |
63 | |
64 | ret = regmap_update_bits(map: xra->regmap, reg: to_reg(XRA_GCR, offset), |
65 | BIT(offset % 8), val: 0); |
66 | if (ret) |
67 | return ret; |
68 | |
69 | ret = regmap_update_bits(map: xra->regmap, reg: to_reg(XRA_OCR, offset), |
70 | BIT(offset % 8), val: value ? BIT(offset % 8) : 0); |
71 | |
72 | return ret; |
73 | } |
74 | |
75 | static int xra1403_get_direction(struct gpio_chip *chip, unsigned int offset) |
76 | { |
77 | int ret; |
78 | unsigned int val; |
79 | struct xra1403 *xra = gpiochip_get_data(gc: chip); |
80 | |
81 | ret = regmap_read(map: xra->regmap, reg: to_reg(XRA_GCR, offset), val: &val); |
82 | if (ret) |
83 | return ret; |
84 | |
85 | if (val & BIT(offset % 8)) |
86 | return GPIO_LINE_DIRECTION_IN; |
87 | |
88 | return GPIO_LINE_DIRECTION_OUT; |
89 | } |
90 | |
91 | static int xra1403_get(struct gpio_chip *chip, unsigned int offset) |
92 | { |
93 | int ret; |
94 | unsigned int val; |
95 | struct xra1403 *xra = gpiochip_get_data(gc: chip); |
96 | |
97 | ret = regmap_read(map: xra->regmap, reg: to_reg(XRA_GSR, offset), val: &val); |
98 | if (ret) |
99 | return ret; |
100 | |
101 | return !!(val & BIT(offset % 8)); |
102 | } |
103 | |
104 | static void xra1403_set(struct gpio_chip *chip, unsigned int offset, int value) |
105 | { |
106 | int ret; |
107 | struct xra1403 *xra = gpiochip_get_data(gc: chip); |
108 | |
109 | ret = regmap_update_bits(map: xra->regmap, reg: to_reg(XRA_OCR, offset), |
110 | BIT(offset % 8), val: value ? BIT(offset % 8) : 0); |
111 | if (ret) |
112 | dev_err(chip->parent, "Failed to set pin: %d, ret: %d\n" , |
113 | offset, ret); |
114 | } |
115 | |
116 | #ifdef CONFIG_DEBUG_FS |
117 | static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip) |
118 | { |
119 | int reg; |
120 | struct xra1403 *xra = gpiochip_get_data(gc: chip); |
121 | int value[XRA_LAST]; |
122 | int i; |
123 | const char *label; |
124 | unsigned int gcr; |
125 | unsigned int gsr; |
126 | |
127 | seq_puts(m: s, s: "xra reg:" ); |
128 | for (reg = 0; reg <= XRA_LAST; reg++) |
129 | seq_printf(m: s, fmt: " %2.2x" , reg); |
130 | seq_puts(m: s, s: "\n value:" ); |
131 | for (reg = 0; reg < XRA_LAST; reg++) { |
132 | regmap_read(map: xra->regmap, reg, val: &value[reg]); |
133 | seq_printf(m: s, fmt: " %2.2x" , value[reg]); |
134 | } |
135 | seq_puts(m: s, s: "\n" ); |
136 | |
137 | gcr = value[XRA_GCR + 1] << 8 | value[XRA_GCR]; |
138 | gsr = value[XRA_GSR + 1] << 8 | value[XRA_GSR]; |
139 | for_each_requested_gpio(chip, i, label) { |
140 | seq_printf(m: s, fmt: " gpio-%-3d (%-12s) %s %s\n" , |
141 | chip->base + i, label, |
142 | (gcr & BIT(i)) ? "in" : "out" , |
143 | (gsr & BIT(i)) ? "hi" : "lo" ); |
144 | } |
145 | } |
146 | #else |
147 | #define xra1403_dbg_show NULL |
148 | #endif |
149 | |
150 | static int xra1403_probe(struct spi_device *spi) |
151 | { |
152 | struct xra1403 *xra; |
153 | struct gpio_desc *reset_gpio; |
154 | int ret; |
155 | |
156 | xra = devm_kzalloc(dev: &spi->dev, size: sizeof(*xra), GFP_KERNEL); |
157 | if (!xra) |
158 | return -ENOMEM; |
159 | |
160 | /* bring the chip out of reset if reset pin is provided*/ |
161 | reset_gpio = devm_gpiod_get_optional(dev: &spi->dev, con_id: "reset" , flags: GPIOD_OUT_LOW); |
162 | if (IS_ERR(ptr: reset_gpio)) |
163 | dev_warn(&spi->dev, "Could not get reset-gpios\n" ); |
164 | |
165 | xra->chip.direction_input = xra1403_direction_input; |
166 | xra->chip.direction_output = xra1403_direction_output; |
167 | xra->chip.get_direction = xra1403_get_direction; |
168 | xra->chip.get = xra1403_get; |
169 | xra->chip.set = xra1403_set; |
170 | |
171 | xra->chip.dbg_show = xra1403_dbg_show; |
172 | |
173 | xra->chip.ngpio = 16; |
174 | xra->chip.label = "xra1403" ; |
175 | |
176 | xra->chip.base = -1; |
177 | xra->chip.can_sleep = true; |
178 | xra->chip.parent = &spi->dev; |
179 | xra->chip.owner = THIS_MODULE; |
180 | |
181 | xra->regmap = devm_regmap_init_spi(spi, &xra1403_regmap_cfg); |
182 | if (IS_ERR(ptr: xra->regmap)) { |
183 | ret = PTR_ERR(ptr: xra->regmap); |
184 | dev_err(&spi->dev, "Failed to allocate regmap: %d\n" , ret); |
185 | return ret; |
186 | } |
187 | |
188 | return devm_gpiochip_add_data(&spi->dev, &xra->chip, xra); |
189 | } |
190 | |
191 | static const struct spi_device_id xra1403_ids[] = { |
192 | { "xra1403" }, |
193 | {}, |
194 | }; |
195 | MODULE_DEVICE_TABLE(spi, xra1403_ids); |
196 | |
197 | static const struct of_device_id xra1403_spi_of_match[] = { |
198 | { .compatible = "exar,xra1403" }, |
199 | {}, |
200 | }; |
201 | MODULE_DEVICE_TABLE(of, xra1403_spi_of_match); |
202 | |
203 | static struct spi_driver xra1403_driver = { |
204 | .probe = xra1403_probe, |
205 | .id_table = xra1403_ids, |
206 | .driver = { |
207 | .name = "xra1403" , |
208 | .of_match_table = xra1403_spi_of_match, |
209 | }, |
210 | }; |
211 | |
212 | module_spi_driver(xra1403_driver); |
213 | |
214 | MODULE_AUTHOR("Nandor Han <nandor.han@ge.com>" ); |
215 | MODULE_AUTHOR("Semi Malinen <semi.malinen@ge.com>" ); |
216 | MODULE_DESCRIPTION("GPIO expander driver for EXAR XRA1403" ); |
217 | MODULE_LICENSE("GPL v2" ); |
218 | |