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