1 /*
2 * Copyright (c) 2023 Antmicro <www.antmicro.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT renesas_rzt2m_gpio
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/gpio/gpio_utils.h>
12 #include <zephyr/sys/util.h>
13 #include <zephyr/sys/errno_private.h>
14 #include <zephyr/dt-bindings/gpio/renesas-rzt2m-gpio.h>
15 #include <soc.h>
16
17 #define PMm_OFFSET 0x200
18 #define PINm_OFFSET 0x800
19 #define DRCTLm_OFFSET 0xa00
20
21 #define DRIVE_SHIFT 0
22 #define SCHMITT_TRIGGER_SHIFT 4
23 #define SLEW_RATE_SHIFT 5
24
25 #define PULL_SHIFT 2
26 #define PULL_NONE (0 << PULL_SHIFT)
27 #define PULL_UP (1 << PULL_SHIFT)
28 #define PULL_DOWN (2 << PULL_SHIFT)
29
30 struct rzt2m_gpio_config {
31 struct gpio_driver_config common;
32 uint8_t *port_nsr;
33 uint8_t *ptadr;
34 uint8_t port;
35 };
36
37 struct rzt2m_gpio_data {
38 struct gpio_driver_data common;
39 };
40
rzt2m_gpio_unlock(void)41 static void rzt2m_gpio_unlock(void)
42 {
43 rzt2m_unlock_prcrn(PRCRN_PRC1);
44 rzt2m_unlock_prcrs(PRCRS_GPIO);
45 }
46
rzt2m_gpio_lock(void)47 static void rzt2m_gpio_lock(void)
48 {
49 rzt2m_lock_prcrn(PRCRN_PRC1);
50 rzt2m_lock_prcrs(PRCRS_GPIO);
51 }
52
53 /* Port m output data store */
rzt2m_gpio_get_p_reg(const struct device * dev)54 static volatile uint8_t *rzt2m_gpio_get_p_reg(const struct device *dev)
55 {
56 const struct rzt2m_gpio_config *config = dev->config;
57
58 return (volatile uint8_t *)(config->port_nsr + config->port);
59 }
60
61 /* Port m input data store */
rzt2m_gpio_get_pin_reg(const struct device * dev)62 static volatile uint8_t *rzt2m_gpio_get_pin_reg(const struct device *dev)
63 {
64 const struct rzt2m_gpio_config *config = dev->config;
65
66 return (volatile uint8_t *)(config->port_nsr + PINm_OFFSET + config->port);
67 }
68
69 /* Port m mode register */
rzt2m_gpio_get_pm_reg(const struct device * dev)70 static volatile uint16_t *rzt2m_gpio_get_pm_reg(const struct device *dev)
71 {
72 const struct rzt2m_gpio_config *config = dev->config;
73
74 return (volatile uint16_t *)(config->port_nsr + PMm_OFFSET + 0x2 * config->port);
75 }
76
77 /* IO Buffer m function switching register */
rzt2m_gpio_get_drctl_reg(const struct device * dev)78 static volatile uint64_t *rzt2m_gpio_get_drctl_reg(const struct device *dev)
79 {
80 const struct rzt2m_gpio_config *config = dev->config;
81
82 return (volatile uint64_t *)(config->port_nsr + DRCTLm_OFFSET + 0x8 * config->port);
83 }
84
85 /* Port m region select register */
rzt2m_gpio_get_rselp_reg(const struct device * dev)86 static volatile uint8_t *rzt2m_gpio_get_rselp_reg(const struct device *dev)
87 {
88 const struct rzt2m_gpio_config *config = dev->config;
89
90 return (volatile uint8_t *)(config->ptadr + config->port);
91 }
92
rzt2m_gpio_init(const struct device * dev)93 static int rzt2m_gpio_init(const struct device *dev)
94 {
95 rzt2m_gpio_unlock();
96
97 volatile uint8_t *rselp_reg = rzt2m_gpio_get_rselp_reg(dev);
98 *rselp_reg = 0xFF;
99
100 rzt2m_gpio_lock();
101
102 return 0;
103 }
104
rzt2m_gpio_get_raw(const struct device * dev,gpio_port_value_t * value)105 static int rzt2m_gpio_get_raw(const struct device *dev, gpio_port_value_t *value)
106 {
107 rzt2m_gpio_unlock();
108
109 volatile uint8_t *pin_reg = rzt2m_gpio_get_pin_reg(dev);
110 *value = *pin_reg;
111
112 rzt2m_gpio_lock();
113
114 return 0;
115 }
116
rzt2m_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)117 static int rzt2m_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
118 gpio_port_value_t value)
119 {
120 rzt2m_gpio_unlock();
121
122 volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev);
123 *p_reg = (*p_reg & ~mask) | (value & mask);
124
125 rzt2m_gpio_lock();
126
127 return 0;
128 }
129
rzt2m_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)130 static int rzt2m_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
131 {
132 rzt2m_gpio_unlock();
133
134 volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev);
135 *p_reg |= pins;
136
137 rzt2m_gpio_lock();
138
139 return 0;
140 }
141
rzt2m_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)142 static int rzt2m_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
143 {
144 rzt2m_gpio_unlock();
145
146 volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev);
147 *p_reg &= ~pins;
148
149 rzt2m_gpio_lock();
150
151 return 0;
152 }
153
rzt2m_gpio_toggle(const struct device * dev,gpio_port_pins_t pins)154 static int rzt2m_gpio_toggle(const struct device *dev, gpio_port_pins_t pins)
155 {
156 rzt2m_gpio_unlock();
157
158 volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev);
159 *p_reg ^= pins;
160
161 rzt2m_gpio_lock();
162
163 return 0;
164 }
165
rzt2m_gpio_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)166 static int rzt2m_gpio_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
167 {
168 volatile uint16_t *pm_reg = rzt2m_gpio_get_pm_reg(dev);
169 volatile uint64_t *drctl_reg = rzt2m_gpio_get_drctl_reg(dev);
170
171 rzt2m_gpio_unlock();
172
173 WRITE_BIT(*pm_reg, pin * 2, flags & GPIO_INPUT);
174 WRITE_BIT(*pm_reg, pin * 2 + 1, flags & GPIO_OUTPUT);
175
176 if (flags & GPIO_OUTPUT) {
177 if (flags & GPIO_OUTPUT_INIT_LOW) {
178 rzt2m_port_clear_bits_raw(dev, 1 << pin);
179 } else if (flags & GPIO_OUTPUT_INIT_HIGH) {
180 rzt2m_port_set_bits_raw(dev, 1 << pin);
181 }
182 }
183
184 if (flags & GPIO_PULL_UP && flags & GPIO_PULL_DOWN) {
185 rzt2m_gpio_lock();
186 return -EINVAL;
187 }
188
189 uint8_t drctl_pin_config = 0;
190
191 if (flags & GPIO_PULL_UP) {
192 drctl_pin_config |= PULL_UP;
193 } else if (flags & GPIO_PULL_DOWN) {
194 drctl_pin_config |= PULL_DOWN;
195 } else {
196 drctl_pin_config |= PULL_NONE;
197 }
198
199 drctl_pin_config |=
200 (flags & RZT2M_GPIO_DRIVE_MASK) >> (RZT2M_GPIO_DRIVE_OFFSET - DRIVE_SHIFT);
201 drctl_pin_config |= (flags & RZT2M_GPIO_SCHMITT_TRIGGER_MASK) >>
202 (RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET - SCHMITT_TRIGGER_SHIFT);
203 drctl_pin_config |= (flags & RZT2M_GPIO_SLEW_RATE_MASK) >>
204 (RZT2M_GPIO_SLEW_RATE_OFFSET - SLEW_RATE_SHIFT);
205
206 uint64_t drctl_pin_value = *drctl_reg & ~(0xFFULL << (pin * 8));
207 *drctl_reg = drctl_pin_value | ((uint64_t)drctl_pin_config << (pin * 8));
208
209 rzt2m_gpio_lock();
210
211 return 0;
212 }
213
214 static const struct gpio_driver_api rzt2m_gpio_driver_api = {
215 .pin_configure = rzt2m_gpio_configure,
216 .port_get_raw = rzt2m_gpio_get_raw,
217 .port_set_masked_raw = rzt2m_port_set_masked_raw,
218 .port_set_bits_raw = rzt2m_port_set_bits_raw,
219 .port_clear_bits_raw = rzt2m_port_clear_bits_raw,
220 .port_toggle_bits = rzt2m_gpio_toggle};
221
222 #define RZT2M_GPIO_DEFINE(inst) \
223 static struct rzt2m_gpio_data rzt2m_gpio_data##inst; \
224 static struct rzt2m_gpio_config rzt2m_gpio_config##inst = { \
225 .port_nsr = (uint8_t *)DT_REG_ADDR_BY_NAME(DT_INST_PARENT(inst), port_nsr), \
226 .ptadr = (uint8_t *)DT_REG_ADDR_BY_NAME(DT_INST_PARENT(inst), ptadr), \
227 .port = DT_INST_REG_ADDR(inst), \
228 .common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst)}}; \
229 DEVICE_DT_INST_DEFINE(inst, rzt2m_gpio_init, NULL, &rzt2m_gpio_data##inst, \
230 &rzt2m_gpio_config##inst, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \
231 &rzt2m_gpio_driver_api);
232
233 DT_INST_FOREACH_STATUS_OKAY(RZT2M_GPIO_DEFINE)
234