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