1 /*
2  * Copyright (c) 2024 Renesas Electronics Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #define DT_DRV_COMPAT renesas_rz_scif_uart
7 
8 #include <zephyr/drivers/pinctrl.h>
9 #include <zephyr/drivers/uart.h>
10 #include <zephyr/logging/log.h>
11 #include "r_scif_uart.h"
12 
13 LOG_MODULE_REGISTER(rz_scif_uart);
14 
15 struct uart_rz_scif_config {
16 	const struct pinctrl_dev_config *pin_config;
17 	const uart_api_t *fsp_api;
18 };
19 
20 struct uart_rz_scif_data {
21 	struct uart_config uart_config;
22 	uart_cfg_t *fsp_cfg;
23 	scif_uart_instance_ctrl_t *fsp_ctrl;
24 };
25 
uart_rz_scif_poll_in(const struct device * dev,unsigned char * c)26 static int uart_rz_scif_poll_in(const struct device *dev, unsigned char *c)
27 {
28 	struct uart_rz_scif_data *data = dev->data;
29 	R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
30 
31 	if (reg->FDR_b.R == 0U) {
32 		/* There are no characters available to read. */
33 		return -1;
34 	}
35 	*c = reg->FRDR;
36 
37 	return 0;
38 }
39 
uart_rz_scif_poll_out(const struct device * dev,unsigned char c)40 static void uart_rz_scif_poll_out(const struct device *dev, unsigned char c)
41 {
42 	struct uart_rz_scif_data *data = dev->data;
43 	R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
44 
45 	while (!reg->FSR_b.TDFE) {
46 	}
47 
48 	reg->FTDR = c;
49 
50 	while (!reg->FSR_b.TEND) {
51 	}
52 }
53 
uart_rz_scif_err_check(const struct device * dev)54 static int uart_rz_scif_err_check(const struct device *dev)
55 {
56 	struct uart_rz_scif_data *data = dev->data;
57 	R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
58 
59 	const uint32_t fsr = reg->FSR;
60 	const uint32_t lsr = reg->LSR;
61 	int errors = 0;
62 
63 	if ((lsr & R_SCIFA0_LSR_ORER_Msk) != 0) {
64 		errors |= UART_ERROR_OVERRUN;
65 	}
66 	if ((fsr & R_SCIFA0_FSR_PER_Msk) != 0) {
67 		errors |= UART_ERROR_PARITY;
68 	}
69 	if ((fsr & R_SCIFA0_FSR_FER_Pos) != 0) {
70 		errors |= UART_ERROR_FRAMING;
71 	}
72 
73 	return errors;
74 }
75 
uart_rz_scif_apply_config(const struct device * dev)76 static int uart_rz_scif_apply_config(const struct device *dev)
77 {
78 	struct uart_rz_scif_data *data = dev->data;
79 
80 	struct uart_config *uart_config = &data->uart_config;
81 	uart_cfg_t *fsp_cfg = data->fsp_cfg;
82 
83 	scif_baud_setting_t baud_setting;
84 	scif_uart_extended_cfg_t config_extend;
85 	const scif_uart_extended_cfg_t *fsp_config_extend = fsp_cfg->p_extend;
86 
87 	fsp_err_t fsp_err;
88 
89 	fsp_err = R_SCIF_UART_BaudCalculate(data->fsp_ctrl, uart_config->baudrate, false, 5000,
90 					    &baud_setting);
91 	if (fsp_err) {
92 		return -EIO;
93 	}
94 
95 	memcpy(fsp_config_extend->p_baud_setting, &baud_setting, sizeof(scif_baud_setting_t));
96 
97 	switch (uart_config->data_bits) {
98 	case UART_CFG_DATA_BITS_7:
99 		fsp_cfg->data_bits = UART_DATA_BITS_7;
100 		break;
101 	case UART_CFG_DATA_BITS_8:
102 		fsp_cfg->data_bits = UART_DATA_BITS_8;
103 		break;
104 	default:
105 		return -ENOTSUP;
106 	}
107 
108 	switch (uart_config->parity) {
109 	case UART_CFG_PARITY_NONE:
110 		fsp_cfg->parity = UART_PARITY_OFF;
111 		break;
112 	case UART_CFG_PARITY_ODD:
113 		fsp_cfg->parity = UART_PARITY_ODD;
114 		break;
115 	case UART_CFG_PARITY_EVEN:
116 		fsp_cfg->parity = UART_PARITY_EVEN;
117 		break;
118 	default:
119 		return -ENOTSUP;
120 	}
121 
122 	switch (uart_config->stop_bits) {
123 	case UART_CFG_STOP_BITS_1:
124 		fsp_cfg->stop_bits = UART_STOP_BITS_1;
125 		break;
126 	case UART_CFG_STOP_BITS_2:
127 		fsp_cfg->stop_bits = UART_STOP_BITS_2;
128 		break;
129 	default:
130 		return -ENOTSUP;
131 	}
132 
133 	memcpy(&config_extend, fsp_config_extend->p_baud_setting, sizeof(scif_baud_setting_t));
134 
135 	switch (uart_config->flow_ctrl) {
136 	case UART_CFG_FLOW_CTRL_NONE:
137 		config_extend.flow_control = SCIF_UART_FLOW_CONTROL_NONE;
138 		config_extend.uart_mode = SCIF_UART_MODE_RS232;
139 		config_extend.rs485_setting.enable = SCI_UART_RS485_DISABLE;
140 		break;
141 	case UART_CFG_FLOW_CTRL_RTS_CTS:
142 		config_extend.flow_control = SCIF_UART_FLOW_CONTROL_AUTO;
143 		config_extend.uart_mode = SCIF_UART_MODE_RS232;
144 		config_extend.rs485_setting.enable = SCI_UART_RS485_DISABLE;
145 		break;
146 	default:
147 		return -ENOTSUP;
148 	}
149 
150 	memcpy(fsp_config_extend->p_baud_setting, &config_extend, sizeof(scif_baud_setting_t));
151 
152 	return 0;
153 }
154 
155 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
156 
uart_rz_scif_configure(const struct device * dev,const struct uart_config * cfg)157 static int uart_rz_scif_configure(const struct device *dev, const struct uart_config *cfg)
158 {
159 	int err;
160 	fsp_err_t fsp_err;
161 	const struct uart_rz_scif_config *config = dev->config;
162 	struct uart_rz_scif_data *data = dev->data;
163 
164 	memcpy(&data->uart_config, cfg, sizeof(struct uart_config));
165 
166 	err = uart_rz_scif_apply_config(dev);
167 
168 	if (err) {
169 		return err;
170 	}
171 
172 	fsp_err = config->fsp_api->close(data->fsp_ctrl);
173 	if (fsp_err) {
174 		return -EIO;
175 	}
176 
177 	fsp_err = config->fsp_api->open(data->fsp_ctrl, data->fsp_cfg);
178 	if (fsp_err) {
179 		return -EIO;
180 	}
181 
182 	R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
183 	/* Temporarily disable the DRI interrupt caused by receive data ready */
184 	/* TODO: support interrupt-driven api */
185 	reg->SCR_b.RIE = 0;
186 
187 	return err;
188 }
189 
uart_rz_scif_config_get(const struct device * dev,struct uart_config * cfg)190 static int uart_rz_scif_config_get(const struct device *dev, struct uart_config *cfg)
191 {
192 	struct uart_rz_scif_data *data = dev->data;
193 
194 	memcpy(cfg, &data->uart_config, sizeof(struct uart_config));
195 	return 0;
196 }
197 
198 #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
199 
200 static DEVICE_API(uart, uart_rz_scif_driver_api) = {
201 	.poll_in = uart_rz_scif_poll_in,
202 	.poll_out = uart_rz_scif_poll_out,
203 	.err_check = uart_rz_scif_err_check,
204 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
205 	.configure = uart_rz_scif_configure,
206 	.config_get = uart_rz_scif_config_get,
207 #endif
208 };
209 
uart_rz_scif_init(const struct device * dev)210 static int uart_rz_scif_init(const struct device *dev)
211 {
212 	const struct uart_rz_scif_config *config = dev->config;
213 	struct uart_rz_scif_data *data = dev->data;
214 	int ret;
215 
216 	/* Configure dt provided device signals when available */
217 	ret = pinctrl_apply_state(config->pin_config, PINCTRL_STATE_DEFAULT);
218 	if (ret < 0) {
219 		return ret;
220 	}
221 
222 	/* uart_rz_scif_apply_config must be called first before open api */
223 	ret = uart_rz_scif_apply_config(dev);
224 	if (ret < 0) {
225 		return ret;
226 	}
227 
228 	config->fsp_api->open(data->fsp_ctrl, data->fsp_cfg);
229 
230 	R_SCIFA0_Type *reg = data->fsp_ctrl->p_reg;
231 	/* Temporarily disable the DRI interrupt caused by receive data ready */
232 	/* TODO: support interrupt-driven api */
233 	reg->SCR_b.RIE = 0;
234 
235 	return 0;
236 }
237 
238 #define UART_RZG_INIT(n)                                                                           \
239 	static scif_uart_instance_ctrl_t g_uart##n##_ctrl;                                         \
240 	static scif_baud_setting_t g_uart##n##_baud_setting;                                       \
241 	static scif_uart_extended_cfg_t g_uart##n##_cfg_extend = {                                 \
242 		.bri_ipl = DT_INST_IRQ_BY_NAME(n, bri, priority),                                  \
243 		.bri_irq = DT_INST_IRQ_BY_NAME(n, bri, irq),                                       \
244 		.clock = SCIF_UART_CLOCK_INT,                                                      \
245 		.noise_cancel = SCIF_UART_NOISE_CANCELLATION_ENABLE,                               \
246 		.p_baud_setting = &g_uart##n##_baud_setting,                                       \
247 		.rx_fifo_trigger = SCIF_UART_RECEIVE_TRIGGER_MAX,                                  \
248 		.rts_fifo_trigger = SCIF_UART_RTS_TRIGGER_14,                                      \
249 		.uart_mode = SCIF_UART_MODE_RS232,                                                 \
250 		.flow_control = SCIF_UART_FLOW_CONTROL_NONE,                                       \
251 		.rs485_setting =                                                                   \
252 			{                                                                          \
253 				.enable = (sci_uart_rs485_enable_t)NULL,                           \
254 				.polarity = SCI_UART_RS485_DE_POLARITY_HIGH,                       \
255 				.de_control_pin =                                                  \
256 					(bsp_io_port_pin_t)SCIF_UART_INVALID_16BIT_PARAM,          \
257 			},                                                                         \
258 	};                                                                                         \
259 	static uart_cfg_t g_uart##n##_cfg = {                                                      \
260 		.channel = DT_INST_PROP(n, channel),                                               \
261 		.p_callback = NULL,                                                                \
262 		.p_context = NULL,                                                                 \
263 		.p_extend = &g_uart##n##_cfg_extend,                                               \
264 		.p_transfer_tx = NULL,                                                             \
265 		.p_transfer_rx = NULL,                                                             \
266 		.rxi_ipl = DT_INST_IRQ_BY_NAME(n, rxi, priority),                                  \
267 		.txi_ipl = DT_INST_IRQ_BY_NAME(n, txi, priority),                                  \
268 		.tei_ipl = DT_INST_IRQ_BY_NAME(n, tei, priority),                                  \
269 		.eri_ipl = DT_INST_IRQ_BY_NAME(n, eri, priority),                                  \
270 		.rxi_irq = DT_INST_IRQ_BY_NAME(n, rxi, irq),                                       \
271 		.txi_irq = DT_INST_IRQ_BY_NAME(n, txi, irq),                                       \
272 		.tei_irq = DT_INST_IRQ_BY_NAME(n, tei, irq),                                       \
273 		.eri_irq = DT_INST_IRQ_BY_NAME(n, eri, irq),                                       \
274 	};                                                                                         \
275 	PINCTRL_DT_INST_DEFINE(n);                                                                 \
276 	static const struct uart_rz_scif_config uart_rz_scif_config_##n = {                        \
277 		.pin_config = PINCTRL_DT_INST_DEV_CONFIG_GET(n), .fsp_api = &g_uart_on_scif};      \
278 	static struct uart_rz_scif_data uart_rz_scif_data_##n = {                                  \
279 		.uart_config =                                                                     \
280 			{                                                                          \
281 				.baudrate = DT_INST_PROP_OR(n, current_speed, 115200),             \
282 				.parity = DT_INST_ENUM_IDX_OR(n, parity, UART_CFG_PARITY_NONE),    \
283 				.stop_bits =                                                       \
284 					DT_INST_ENUM_IDX_OR(n, stop_bits, UART_CFG_STOP_BITS_1),   \
285 				.data_bits =                                                       \
286 					DT_INST_ENUM_IDX_OR(n, data_bits, UART_CFG_DATA_BITS_8),   \
287 				.flow_ctrl = DT_INST_PROP_OR(n, hw_flow_control,                   \
288 							     UART_CFG_FLOW_CTRL_NONE),             \
289 			},                                                                         \
290 		.fsp_cfg = &g_uart##n##_cfg,                                                       \
291 		.fsp_ctrl = &g_uart##n##_ctrl,                                                     \
292 	};                                                                                         \
293 	static int uart_rz_scif_init_##n(const struct device *dev)                                 \
294 	{                                                                                          \
295 		return uart_rz_scif_init(dev);                                                     \
296 	}                                                                                          \
297 	DEVICE_DT_INST_DEFINE(n, &uart_rz_scif_init_##n, NULL, &uart_rz_scif_data_##n,             \
298 			      &uart_rz_scif_config_##n, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
299 			      &uart_rz_scif_driver_api);
300 
301 DT_INST_FOREACH_STATUS_OKAY(UART_RZG_INIT)
302