1 /*
2 * Copyright (c) 2020-2023 IoT.bzh
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT renesas_rcar_gpio
8
9 #include <errno.h>
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/init.h>
14 #include <zephyr/drivers/gpio.h>
15 #include <zephyr/drivers/clock_control.h>
16 #include <zephyr/drivers/clock_control/renesas_cpg_mssr.h>
17 #include <zephyr/irq.h>
18
19 #include <zephyr/drivers/gpio/gpio_utils.h>
20
21 typedef void (*init_func_t)(const struct device *dev);
22
23 /* Required by DEVICE_MMIO_NAMED_* macros */
24 #define DEV_CFG(_dev) \
25 ((const struct gpio_rcar_cfg *)(_dev)->config)
26 #define DEV_DATA(_dev) ((struct gpio_rcar_data *)(_dev)->data)
27
28 struct gpio_rcar_cfg {
29 struct gpio_driver_config common;
30 DEVICE_MMIO_NAMED_ROM(reg_base);
31 init_func_t init_func;
32 const struct device *clock_dev;
33 struct rcar_cpg_clk mod_clk;
34 };
35
36 struct gpio_rcar_data {
37 struct gpio_driver_data common;
38 DEVICE_MMIO_NAMED_RAM(reg_base);
39 sys_slist_t cb;
40 };
41
42 #define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
43 #define INOUTSEL 0x04 /* General Input/Output Switching Register */
44 #define OUTDT 0x08 /* General Output Register */
45 #define INDT 0x0c /* General Input Register */
46 #define INTDT 0x10 /* Interrupt Display Register */
47 #define INTCLR 0x14 /* Interrupt Clear Register */
48 #define INTMSK 0x18 /* Interrupt Mask Register */
49 #define MSKCLR 0x1c /* Interrupt Mask Clear Register */
50 #define POSNEG 0x20 /* Positive/Negative Logic Select Register */
51 #define EDGLEVEL 0x24 /* Edge/level Select Register */
52 #define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
53 #define OUTDTSEL 0x40 /* Output Data Select Register */
54 #define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
55 #define INEN 0x50 /* General Input Enable Register */
56
gpio_rcar_read(const struct device * dev,uint32_t offs)57 static inline uint32_t gpio_rcar_read(const struct device *dev, uint32_t offs)
58 {
59 return sys_read32(DEVICE_MMIO_NAMED_GET(dev, reg_base) + offs);
60 }
61
gpio_rcar_write(const struct device * dev,uint32_t offs,uint32_t value)62 static inline void gpio_rcar_write(const struct device *dev, uint32_t offs, uint32_t value)
63 {
64 sys_write32(value, DEVICE_MMIO_NAMED_GET(dev, reg_base) + offs);
65 }
66
gpio_rcar_modify_bit(const struct device * dev,uint32_t offs,int bit,bool value)67 static void gpio_rcar_modify_bit(const struct device *dev,
68 uint32_t offs, int bit, bool value)
69 {
70 uint32_t tmp = gpio_rcar_read(dev, offs);
71
72 if (value) {
73 tmp |= BIT(bit);
74 } else {
75 tmp &= ~BIT(bit);
76 }
77
78 gpio_rcar_write(dev, offs, tmp);
79 }
80
gpio_rcar_port_isr(const struct device * dev)81 static void gpio_rcar_port_isr(const struct device *dev)
82 {
83 struct gpio_rcar_data *data = dev->data;
84 uint32_t pending, fsb, mask;
85
86 pending = gpio_rcar_read(dev, INTDT);
87 mask = gpio_rcar_read(dev, INTMSK);
88
89 while ((pending = gpio_rcar_read(dev, INTDT) &
90 gpio_rcar_read(dev, INTMSK))) {
91 fsb = find_lsb_set(pending) - 1;
92 gpio_fire_callbacks(&data->cb, dev, BIT(fsb));
93 gpio_rcar_write(dev, INTCLR, BIT(fsb));
94 }
95 }
96
gpio_rcar_config_general_input_output_mode(const struct device * dev,uint32_t gpio,bool output)97 static void gpio_rcar_config_general_input_output_mode(
98 const struct device *dev,
99 uint32_t gpio,
100 bool output)
101 {
102 /* follow steps in the GPIO documentation for
103 * "Setting General Output Mode" and
104 * "Setting General Input Mode"
105 */
106
107 /* Configure positive logic in POSNEG */
108 gpio_rcar_modify_bit(dev, POSNEG, gpio, false);
109
110 /* Select "Input Enable/Disable" in INEN for Gen4 SoCs */
111 #ifdef CONFIG_SOC_SERIES_RCAR_GEN4
112 gpio_rcar_modify_bit(dev, INEN, gpio, !output);
113 #endif
114
115 /* Select "General Input/Output Mode" in IOINTSEL */
116 gpio_rcar_modify_bit(dev, IOINTSEL, gpio, false);
117
118 /* Select Input Mode or Output Mode in INOUTSEL */
119 gpio_rcar_modify_bit(dev, INOUTSEL, gpio, output);
120
121 /* Select General Output Register to output data in OUTDTSEL */
122 if (output) {
123 gpio_rcar_modify_bit(dev, OUTDTSEL, gpio, false);
124 }
125 }
126
gpio_rcar_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)127 static int gpio_rcar_configure(const struct device *dev,
128 gpio_pin_t pin, gpio_flags_t flags)
129 {
130 if ((flags & GPIO_OUTPUT) && (flags & GPIO_INPUT)) {
131 /* Pin cannot be configured as input and output */
132 return -ENOTSUP;
133 } else if (!(flags & (GPIO_INPUT | GPIO_OUTPUT))) {
134 /* Pin has to be configured as input or output */
135 return -ENOTSUP;
136 }
137
138 if (flags & GPIO_OUTPUT) {
139 if (flags & GPIO_OUTPUT_INIT_HIGH) {
140 gpio_rcar_modify_bit(dev, OUTDT, pin, true);
141 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
142 gpio_rcar_modify_bit(dev, OUTDT, pin, false);
143 }
144 gpio_rcar_config_general_input_output_mode(dev, pin, true);
145 } else {
146 gpio_rcar_config_general_input_output_mode(dev, pin, false);
147 }
148
149 return 0;
150 }
151
gpio_rcar_port_get_raw(const struct device * dev,gpio_port_value_t * value)152 static int gpio_rcar_port_get_raw(const struct device *dev,
153 gpio_port_value_t *value)
154 {
155 *value = gpio_rcar_read(dev, INDT);
156 return 0;
157 }
158
gpio_rcar_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)159 static int gpio_rcar_port_set_masked_raw(const struct device *dev,
160 gpio_port_pins_t mask,
161 gpio_port_value_t value)
162 {
163 uint32_t port_val;
164
165 port_val = gpio_rcar_read(dev, OUTDT);
166 port_val = (port_val & ~mask) | (value & mask);
167 gpio_rcar_write(dev, OUTDT, port_val);
168
169 return 0;
170 }
171
gpio_rcar_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)172 static int gpio_rcar_port_set_bits_raw(const struct device *dev,
173 gpio_port_pins_t pins)
174 {
175 uint32_t port_val;
176
177 port_val = gpio_rcar_read(dev, OUTDT);
178 port_val |= pins;
179 gpio_rcar_write(dev, OUTDT, port_val);
180
181 return 0;
182 }
183
gpio_rcar_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)184 static int gpio_rcar_port_clear_bits_raw(const struct device *dev,
185 gpio_port_pins_t pins)
186 {
187 uint32_t port_val;
188
189 port_val = gpio_rcar_read(dev, OUTDT);
190 port_val &= ~pins;
191 gpio_rcar_write(dev, OUTDT, port_val);
192
193 return 0;
194 }
195
gpio_rcar_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)196 static int gpio_rcar_port_toggle_bits(const struct device *dev,
197 gpio_port_pins_t pins)
198 {
199 uint32_t port_val;
200
201 port_val = gpio_rcar_read(dev, OUTDT);
202 port_val ^= pins;
203 gpio_rcar_write(dev, OUTDT, port_val);
204
205 return 0;
206 }
207
gpio_rcar_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)208 static int gpio_rcar_pin_interrupt_configure(const struct device *dev,
209 gpio_pin_t pin,
210 enum gpio_int_mode mode,
211 enum gpio_int_trig trig)
212 {
213 if (mode == GPIO_INT_MODE_DISABLED) {
214 return -ENOTSUP;
215 }
216
217 /* Configure positive or negative logic in POSNEG */
218 gpio_rcar_modify_bit(dev, POSNEG, pin,
219 (trig == GPIO_INT_TRIG_LOW));
220
221 /* Configure edge or level trigger in EDGLEVEL */
222 if (mode == GPIO_INT_MODE_EDGE) {
223 gpio_rcar_modify_bit(dev, EDGLEVEL, pin, true);
224 } else {
225 gpio_rcar_modify_bit(dev, EDGLEVEL, pin, false);
226 }
227
228 if (trig == GPIO_INT_TRIG_BOTH) {
229 gpio_rcar_modify_bit(dev, BOTHEDGE, pin, true);
230 }
231
232 /* Select "Input Enable" in INEN for Gen4 SoCs */
233 #ifdef CONFIG_SOC_SERIES_RCAR_GEN4
234 gpio_rcar_modify_bit(dev, INEN, pin, true);
235 #endif
236
237 gpio_rcar_modify_bit(dev, IOINTSEL, pin, true);
238
239 if (mode == GPIO_INT_MODE_EDGE) {
240 /* Write INTCLR in case of edge trigger */
241 gpio_rcar_write(dev, INTCLR, BIT(pin));
242 }
243
244 gpio_rcar_write(dev, MSKCLR, BIT(pin));
245
246 return 0;
247 }
248
gpio_rcar_init(const struct device * dev)249 static int gpio_rcar_init(const struct device *dev)
250 {
251 const struct gpio_rcar_cfg *config = dev->config;
252 int ret;
253
254 if (!device_is_ready(config->clock_dev)) {
255 return -ENODEV;
256 }
257
258 ret = clock_control_on(config->clock_dev,
259 (clock_control_subsys_t) &config->mod_clk);
260
261 if (ret < 0) {
262 return ret;
263 }
264
265 DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE);
266 config->init_func(dev);
267 return 0;
268 }
269
gpio_rcar_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)270 static int gpio_rcar_manage_callback(const struct device *dev,
271 struct gpio_callback *callback,
272 bool set)
273 {
274 struct gpio_rcar_data *data = dev->data;
275
276 return gpio_manage_callback(&data->cb, callback, set);
277 }
278
279 static const struct gpio_driver_api gpio_rcar_driver_api = {
280 .pin_configure = gpio_rcar_configure,
281 .port_get_raw = gpio_rcar_port_get_raw,
282 .port_set_masked_raw = gpio_rcar_port_set_masked_raw,
283 .port_set_bits_raw = gpio_rcar_port_set_bits_raw,
284 .port_clear_bits_raw = gpio_rcar_port_clear_bits_raw,
285 .port_toggle_bits = gpio_rcar_port_toggle_bits,
286 .pin_interrupt_configure = gpio_rcar_pin_interrupt_configure,
287 .manage_callback = gpio_rcar_manage_callback,
288 };
289
290 /* Device Instantiation */
291 #define GPIO_RCAR_INIT(n) \
292 static void gpio_rcar_##n##_init(const struct device *dev); \
293 static const struct gpio_rcar_cfg gpio_rcar_cfg_##n = { \
294 DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \
295 .common = { \
296 .port_pin_mask = \
297 GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
298 }, \
299 .init_func = gpio_rcar_##n##_init, \
300 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
301 .mod_clk.module = \
302 DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \
303 .mod_clk.domain = \
304 DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \
305 }; \
306 static struct gpio_rcar_data gpio_rcar_data_##n; \
307 \
308 DEVICE_DT_INST_DEFINE(n, \
309 gpio_rcar_init, \
310 NULL, \
311 &gpio_rcar_data_##n, \
312 &gpio_rcar_cfg_##n, \
313 PRE_KERNEL_1, \
314 CONFIG_GPIO_INIT_PRIORITY, \
315 &gpio_rcar_driver_api \
316 ); \
317 static void gpio_rcar_##n##_init(const struct device *dev) \
318 { \
319 IRQ_CONNECT(DT_INST_IRQN(n), \
320 0, \
321 gpio_rcar_port_isr, \
322 DEVICE_DT_INST_GET(n), 0); \
323 \
324 irq_enable(DT_INST_IRQN(n)); \
325 }
326
327 DT_INST_FOREACH_STATUS_OKAY(GPIO_RCAR_INIT)
328