Skip to content

Commit 5e8b072

Browse files
Andrei-Edward Popanashif
authored andcommitted
drivers: serial: added UART interrupts for Raspberry Pi Pico board
added UART interrupts driver for Raspberry Pi Pico board moved baudrate from config to data structure Signed-off-by: Andrei-Edward Popa <[email protected]>
1 parent 2fc2928 commit 5e8b072

File tree

2 files changed

+242
-15
lines changed

2 files changed

+242
-15
lines changed

drivers/serial/Kconfig.rpi_pico

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ config UART_RPI_PICO
99
default $(dt_compat_enabled,$(DT_COMPAT_RPI_PICO_UART))
1010
select SERIAL_HAS_DRIVER
1111
select PICOSDK_USE_UART
12+
select SERIAL_SUPPORT_INTERRUPT

drivers/serial/uart_rpi_pico.c

Lines changed: 241 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2021, Yonatan Schachter
3+
* Copyright (c) 2022, Andrei-Edward Popa
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -14,8 +15,19 @@
1415

1516
struct uart_rpi_config {
1617
uart_inst_t *const uart_dev;
17-
uint32_t baudrate;
18+
uart_hw_t *const uart_regs;
1819
const struct pinctrl_dev_config *pcfg;
20+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
21+
uart_irq_config_func_t irq_config_func;
22+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
23+
};
24+
25+
struct uart_rpi_data {
26+
uint32_t baudrate;
27+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
28+
uart_irq_callback_user_data_t irq_cb;
29+
void *irq_cb_data;
30+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
1931
};
2032

2133
static int uart_rpi_poll_in(const struct device *dev, unsigned char *c)
@@ -56,27 +68,241 @@ static int uart_rpi_init(const struct device *dev)
5668
return -EINVAL;
5769
}
5870

71+
hw_clear_bits(&uart_hw->lcr_h, UART_UARTLCR_H_FEN_BITS);
72+
uart_hw->dr = 0U;
73+
74+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
75+
config->irq_config_func(dev);
76+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
77+
5978
return 0;
6079
}
6180

81+
static int uart_rpi_err_check(const struct device *dev)
82+
{
83+
const struct uart_rpi_config * const config = dev->config;
84+
uart_hw_t * const uart_hw = config->uart_regs;
85+
uint32_t data_reg = uart_hw->dr;
86+
int errors = 0;
87+
88+
if (data_reg & UART_UARTDR_OE_BITS) {
89+
errors |= UART_ERROR_OVERRUN;
90+
}
91+
92+
if (data_reg & UART_UARTDR_BE_BITS) {
93+
errors |= UART_BREAK;
94+
}
95+
96+
if (data_reg & UART_UARTDR_PE_BITS) {
97+
errors |= UART_ERROR_PARITY;
98+
}
99+
100+
if (data_reg & UART_UARTDR_FE_BITS) {
101+
errors |= UART_ERROR_FRAMING;
102+
}
103+
104+
return errors;
105+
}
106+
107+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
108+
109+
static int uart_rpi_fifo_fill(const struct device *dev,
110+
const uint8_t *tx_data, int len)
111+
{
112+
const struct uart_rpi_config * const config = dev->config;
113+
uart_hw_t * const uart_hw = config->uart_regs;
114+
int tx_len = 0;
115+
116+
while (!(uart_hw->fr & UART_UARTFR_TXFF_BITS) && (len - tx_len) > 0) {
117+
uart_hw->dr = tx_data[tx_len++];
118+
}
119+
120+
return tx_len;
121+
}
122+
123+
static int uart_rpi_fifo_read(const struct device *dev,
124+
uint8_t *rx_data, const int len)
125+
{
126+
const struct uart_rpi_config * const config = dev->config;
127+
uart_hw_t * const uart_hw = config->uart_regs;
128+
int rx_len = 0;
129+
130+
while (!(uart_hw->fr & UART_UARTFR_RXFE_BITS) && (len - rx_len) > 0) {
131+
rx_data[rx_len++] = (uint8_t)uart_hw->dr;
132+
}
133+
134+
return rx_len;
135+
}
136+
137+
static void uart_rpi_irq_tx_enable(const struct device *dev)
138+
{
139+
const struct uart_rpi_config * const config = dev->config;
140+
uart_hw_t * const uart_hw = config->uart_regs;
141+
142+
uart_hw->imsc |= UART_UARTIMSC_TXIM_BITS;
143+
uart_hw->ifls &= ~UART_UARTIFLS_TXIFLSEL_BITS;
144+
}
145+
146+
static void uart_rpi_irq_tx_disable(const struct device *dev)
147+
{
148+
const struct uart_rpi_config * const config = dev->config;
149+
uart_hw_t * const uart_hw = config->uart_regs;
150+
151+
uart_hw->imsc &= ~UART_UARTIMSC_TXIM_BITS;
152+
}
153+
154+
static int uart_rpi_irq_tx_ready(const struct device *dev)
155+
{
156+
const struct uart_rpi_config * const config = dev->config;
157+
uart_hw_t * const uart_hw = config->uart_regs;
158+
159+
return (uart_hw->mis & UART_UARTMIS_TXMIS_BITS) == UART_UARTMIS_TXMIS_BITS;
160+
}
161+
162+
static void uart_rpi_irq_rx_enable(const struct device *dev)
163+
{
164+
const struct uart_rpi_config * const config = dev->config;
165+
uart_hw_t * const uart_hw = config->uart_regs;
166+
167+
uart_hw->imsc |= UART_UARTIMSC_RXIM_BITS;
168+
uart_hw->ifls &= ~UART_UARTIFLS_RXIFLSEL_BITS;
169+
}
170+
171+
static void uart_rpi_irq_rx_disable(const struct device *dev)
172+
{
173+
const struct uart_rpi_config * const config = dev->config;
174+
uart_hw_t * const uart_hw = config->uart_regs;
175+
176+
uart_hw->imsc &= ~UART_UARTIMSC_RXIM_BITS;
177+
}
178+
179+
static int uart_rpi_irq_tx_complete(const struct device *dev)
180+
{
181+
const struct uart_rpi_config * const config = dev->config;
182+
uart_hw_t * const uart_hw = config->uart_regs;
183+
184+
return !!(uart_hw->fr & UART_UARTFR_TXFE_BITS);
185+
}
186+
187+
static int uart_rpi_irq_rx_ready(const struct device *dev)
188+
{
189+
const struct uart_rpi_config * const config = dev->config;
190+
uart_hw_t * const uart_hw = config->uart_regs;
191+
192+
return (uart_hw->mis & UART_UARTMIS_RXMIS_BITS) == UART_UARTMIS_RXMIS_BITS;
193+
}
194+
195+
static void uart_rpi_irq_err_enable(const struct device *dev)
196+
{
197+
const struct uart_rpi_config * const config = dev->config;
198+
uart_hw_t * const uart_hw = config->uart_regs;
199+
200+
uart_hw->imsc |= (UART_UARTIMSC_OEIM_BITS |
201+
UART_UARTIMSC_BEIM_BITS |
202+
UART_UARTIMSC_PEIM_BITS |
203+
UART_UARTIMSC_FEIM_BITS |
204+
UART_UARTIMSC_RTIM_BITS);
205+
}
206+
207+
static void uart_rpi_irq_err_disable(const struct device *dev)
208+
{
209+
const struct uart_rpi_config * const config = dev->config;
210+
uart_hw_t * const uart_hw = config->uart_regs;
211+
212+
uart_hw->imsc &= ~(UART_UARTIMSC_OEIM_BITS |
213+
UART_UARTIMSC_BEIM_BITS |
214+
UART_UARTIMSC_PEIM_BITS |
215+
UART_UARTIMSC_FEIM_BITS |
216+
UART_UARTIMSC_RTIM_BITS);
217+
}
218+
219+
static int uart_rpi_irq_is_pending(const struct device *dev)
220+
{
221+
return !!(uart_rpi_irq_rx_ready(dev) || uart_rpi_irq_tx_ready(dev));
222+
}
223+
224+
static int uart_rpi_irq_update(const struct device *dev)
225+
{
226+
return 1;
227+
}
228+
229+
static void uart_rpi_irq_callback_set(const struct device *dev,
230+
uart_irq_callback_user_data_t cb,
231+
void *cb_data)
232+
{
233+
struct uart_rpi_data * const data = dev->data;
234+
235+
data->irq_cb = cb;
236+
data->irq_cb_data = cb_data;
237+
}
238+
239+
static void uart_rpi_isr(const struct device *dev)
240+
{
241+
struct uart_rpi_data * const data = dev->data;
242+
243+
if (data->irq_cb) {
244+
data->irq_cb(dev, data->irq_cb_data);
245+
}
246+
}
247+
248+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
249+
62250
static const struct uart_driver_api uart_rpi_driver_api = {
63251
.poll_in = uart_rpi_poll_in,
64252
.poll_out = uart_rpi_poll_out,
253+
.err_check = uart_rpi_err_check,
254+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
255+
.fifo_fill = uart_rpi_fifo_fill,
256+
.fifo_read = uart_rpi_fifo_read,
257+
.irq_tx_enable = uart_rpi_irq_tx_enable,
258+
.irq_tx_disable = uart_rpi_irq_tx_disable,
259+
.irq_tx_ready = uart_rpi_irq_tx_ready,
260+
.irq_rx_enable = uart_rpi_irq_rx_enable,
261+
.irq_rx_disable = uart_rpi_irq_rx_disable,
262+
.irq_tx_complete = uart_rpi_irq_tx_complete,
263+
.irq_rx_ready = uart_rpi_irq_rx_ready,
264+
.irq_err_enable = uart_rpi_irq_err_enable,
265+
.irq_err_disable = uart_rpi_irq_err_disable,
266+
.irq_is_pending = uart_rpi_irq_is_pending,
267+
.irq_update = uart_rpi_irq_update,
268+
.irq_callback_set = uart_rpi_irq_callback_set,
269+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
65270
};
66271

67-
#define RPI_UART_INIT(idx) \
68-
PINCTRL_DT_INST_DEFINE(idx); \
69-
static const struct uart_rpi_config uart_rpi_cfg_##idx = { \
70-
.uart_dev = (uart_inst_t *)DT_INST_REG_ADDR(idx), \
71-
.baudrate = DT_INST_PROP(idx, current_speed), \
72-
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
73-
}; \
74-
\
75-
DEVICE_DT_INST_DEFINE(idx, &uart_rpi_init, \
76-
NULL, \
77-
NULL, \
78-
&uart_rpi_cfg_##idx, PRE_KERNEL_1, \
79-
CONFIG_SERIAL_INIT_PRIORITY, \
80-
&uart_rpi_driver_api);
272+
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
273+
#define RPI_UART_IRQ_CONFIG_INIT(idx) \
274+
.irq_config_func = uart##idx##_rpi_irq_config_func
275+
#else
276+
#define RPI_UART_IRQ_CONFIG_INIT(idx)
277+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN*/
278+
279+
#define RPI_UART_INIT(idx) \
280+
PINCTRL_DT_INST_DEFINE(idx); \
281+
\
282+
static void uart##idx##_rpi_irq_config_func(const struct device *port) \
283+
{ \
284+
IRQ_CONNECT(DT_INST_IRQN(idx), \
285+
DT_INST_IRQ(idx, priority), \
286+
uart_rpi_isr, \
287+
DEVICE_DT_INST_GET(idx), 0); \
288+
irq_enable(DT_INST_IRQN(idx)); \
289+
} \
290+
\
291+
static const struct uart_rpi_config uart##idx##_rpi_config = { \
292+
.uart_dev = uart##idx, \
293+
.uart_regs = (uart_hw_t *)uart##idx, \
294+
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
295+
RPI_UART_IRQ_CONFIG_INIT(idx), \
296+
}; \
297+
\
298+
static struct uart_rpi_data uart##idx##_rpi_data = { \
299+
.baudrate = DT_INST_PROP(idx, current_speed), \
300+
}; \
301+
\
302+
DEVICE_DT_INST_DEFINE(idx, &uart_rpi_init, \
303+
NULL, &uart##idx##_rpi_data, \
304+
&uart##idx##_rpi_config, PRE_KERNEL_1, \
305+
CONFIG_SERIAL_INIT_PRIORITY, \
306+
&uart_rpi_driver_api); \
81307

82308
DT_INST_FOREACH_STATUS_OKAY(RPI_UART_INIT)

0 commit comments

Comments
 (0)