13
13
#include <zephyr/drivers/gpio.h>
14
14
#include <zephyr/drivers/clock_control.h>
15
15
#include <zephyr/drivers/clock_control/clock_control_rts5912.h>
16
+ #include <zephyr/drivers/serial/uart_ns16550.h>
16
17
#include <zephyr/logging/log.h>
18
+ #include <zephyr/pm/pm.h>
19
+ #include <zephyr/pm/policy.h>
20
+ #include <zephyr/pm/device.h>
21
+ #include "zephyr/drivers/gpio/gpio_rts5912.h"
17
22
18
23
LOG_MODULE_REGISTER (uart_rts5912 , CONFIG_UART_LOG_LEVEL );
19
24
20
- BUILD_ASSERT (CONFIG_UART_RTS5912_INIT_PRIORITY < CONFIG_SERIAL_INIT_PRIORITY ,
21
- "The uart_realtek_rts5912 driver must be initialized before the uart_ns16550 driver" );
22
-
23
25
/* device config */
24
26
struct uart_rts5912_device_config {
25
27
const struct pinctrl_dev_config * pcfg ;
26
28
const struct device * clk_dev ;
27
29
struct rts5912_sccon_subsys sccon_cfg ;
30
+ struct gpio_dt_spec uart_rx_wakeup ;
31
+ const struct device * uart_dev ;
28
32
};
29
33
30
34
/** Device data structure */
31
35
struct uart_rts5912_dev_data {
36
+ #if defined(CONFIG_PM )
37
+ struct pm_notifier pm_handles ;
38
+ uint32_t * rts5912_rx_wake_reg ;
39
+ uint32_t rx_wakeup_pin_num ;
40
+ #endif
32
41
};
33
42
43
+ DT_INST_FOREACH_STATUS_OKAY (PINCTRL_DT_INST_DEFINE );
44
+ #if defined(CONFIG_PM )
45
+ #define REG_IIR 0x08 /* Interrupt ID reg. */
46
+ #define REG_LSR 0x14 /* Line status reg. */
47
+ #define REG_USR 0x7C /* UART status reg. (DW8250) */
48
+ #define IIR_NIP 0x01 /* no interrupt pending */
49
+ #define IIR_THRE 0x02 /* transmit holding register empty interrupt */
50
+ #define IIR_RBRF 0x04 /* receiver buffer register full interrupt */
51
+ #define IIR_LS 0x06 /* receiver line status interrupt */
52
+ #define IIR_MASK 0x07 /* interrupt id bits mask */
53
+ #define IIR_BUSY 0x07 /* iir busy mask */
54
+ #define USR_BUSY_CHECK BIT(0)
55
+ #define RTS5912_MAXIMUM_UART_POLLING_TIME_US (50 * USEC_PER_MSEC)
56
+ static struct k_work_delayable rx_refresh_timeout_work ;
57
+
58
+ static void uart_rts5912_rx_refresh_timeout (struct k_work * work )
59
+ {
60
+ ARG_UNUSED (work );
61
+
62
+ pm_policy_state_lock_put (PM_STATE_SUSPEND_TO_IDLE , PM_ALL_SUBSTATES );
63
+ }
64
+ /* Hook to count entry/exit */
65
+ static void uart_rts5912_pm_state_entry (const struct device * dev , enum pm_state state )
66
+ {
67
+ const struct uart_rts5912_dev_data * const dev_data = dev -> data ;
68
+
69
+ switch (state ) {
70
+ case PM_STATE_SUSPEND_TO_IDLE :
71
+ irq_enable (dev_data -> rx_wakeup_pin_num );
72
+ gpio_rts5912_set_wakeup_pin (dev_data -> rx_wakeup_pin_num );
73
+ break ;
74
+ default :
75
+ break ;
76
+ }
77
+ }
78
+ /* Hook to count entry/exit */
79
+ static void uart_rts5912_pm_state_exit (const struct device * dev , enum pm_state state )
80
+ {
81
+ const struct uart_rts5912_device_config * const dev_cfg = dev -> config ;
82
+ const struct uart_rts5912_dev_data * const dev_data = dev -> data ;
83
+
84
+ switch (state ) {
85
+ case PM_STATE_SUSPEND_TO_IDLE :
86
+ uint32_t interrupt_pin = gpio_rts5912_get_intr_pin (dev_data -> rts5912_rx_wake_reg );
87
+
88
+ pinctrl_apply_state (dev_cfg -> pcfg , PINCTRL_STATE_DEFAULT );
89
+ if (IS_ENABLED (CONFIG_UART_CONSOLE_INPUT_EXPIRED ) &&
90
+ interrupt_pin == dev_cfg -> uart_rx_wakeup .pin ) {
91
+ k_timeout_t delay = K_MSEC (CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT );
92
+
93
+ pm_policy_state_lock_get (PM_STATE_SUSPEND_TO_IDLE , PM_ALL_SUBSTATES );
94
+ k_work_reschedule (& rx_refresh_timeout_work , delay );
95
+ }
96
+ NVIC_ClearPendingIRQ (dev_data -> rx_wakeup_pin_num );
97
+ irq_disable (dev_data -> rx_wakeup_pin_num );
98
+ break ;
99
+ default :
100
+ break ;
101
+ }
102
+ }
103
+
104
+ static void uart_rx_wait (const struct device * dev , void * user_data )
105
+ {
106
+ ARG_UNUSED (user_data );
107
+ if (IS_ENABLED (CONFIG_UART_CONSOLE_INPUT_EXPIRED ) && uart_irq_rx_ready (dev )) {
108
+ k_timeout_t delay = K_MSEC (CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT );
109
+
110
+ pm_policy_state_lock_get (PM_STATE_SUSPEND_TO_IDLE , PM_ALL_SUBSTATES );
111
+ k_work_reschedule (& rx_refresh_timeout_work , delay );
112
+ }
113
+ }
114
+ #endif
115
+
34
116
static int rts5912_uart_init (const struct device * dev )
35
117
{
36
118
const struct uart_rts5912_device_config * const dev_cfg = dev -> config ;
119
+ struct uart_rts5912_dev_data * const dev_data = dev -> data ;
37
120
int rc ;
38
121
39
122
if (!device_is_ready (dev_cfg -> clk_dev )) {
@@ -50,11 +133,87 @@ static int rts5912_uart_init(const struct device *dev)
50
133
return rc ;
51
134
}
52
135
136
+ #if defined(CONFIG_PM )
137
+ const uint32_t uart_reg = uart_ns16550_get_port (dev_cfg -> uart_dev );
138
+ uint32_t wf_cycle_count = k_us_to_cyc_ceil32 (RTS5912_MAXIMUM_UART_POLLING_TIME_US );
139
+ uint32_t wf_start = k_cycle_get_32 ();
140
+ uint32_t wf_now = wf_start ;
141
+
142
+ /* For RTS5912 UART, if enable UART wake up function, it will
143
+ * change GPIO pin from uart funciton to gpio function before WFI.
144
+ * System need to ensure this register is cleared in every time doing init function.
145
+ */
146
+ while (wf_cycle_count > (wf_now - wf_start )) {
147
+ uint32_t iir = sys_read32 (uart_reg + REG_IIR ) & IIR_MASK ;
148
+
149
+ if (iir == IIR_NIP ) {
150
+ break ;
151
+ }
152
+ switch (iir ) {
153
+ case IIR_LS : /* Receiver line status */
154
+ sys_read32 (uart_reg + REG_LSR );
155
+ break ;
156
+ case IIR_RBRF : /* Received data available*/
157
+ sys_write32 (sys_read32 (uart_reg + REG_IIR ) | IIR_THRE ,
158
+ (uart_reg + REG_IIR ));
159
+ break ;
160
+ case IIR_BUSY :
161
+ while (wf_cycle_count > (wf_now - wf_start )) {
162
+ uint32_t usr = sys_read32 (uart_reg + REG_USR );
163
+
164
+ if ((usr & USR_BUSY_CHECK ) == 0 ) {
165
+ break ;
166
+ }
167
+ wf_now = k_cycle_get_32 ();
168
+ }
169
+ break ;
170
+ }
171
+ iir = sys_read32 (uart_reg + REG_IIR ) & IIR_MASK ;
172
+ if (iir == IIR_NIP ) {
173
+ break ;
174
+ }
175
+ k_busy_wait (10 );
176
+ wf_now = k_cycle_get_32 ();
177
+ }
178
+
179
+ if (wf_cycle_count <= (wf_now - wf_start )) {
180
+ LOG_ERR ("Uart reset iir reach timeout" );
181
+ return - EIO ;
182
+ }
183
+
184
+ k_work_init_delayable (& rx_refresh_timeout_work , uart_rts5912_rx_refresh_timeout );
185
+ pm_notifier_register (& dev_data -> pm_handles );
186
+ uart_irq_callback_set (DEVICE_DT_GET (DT_CHOSEN (zephyr_console )), uart_rx_wait );
187
+ dev_data -> rx_wakeup_pin_num = gpio_rts5912_get_pin_num (& dev_cfg -> uart_rx_wakeup );
188
+ dev_data -> rts5912_rx_wake_reg = gpio_rts5912_get_port_address (& dev_cfg -> uart_rx_wakeup );
189
+ #endif
190
+
53
191
return 0 ;
54
192
}
55
193
194
+ #if defined(CONFIG_PM )
195
+ #define UART_REALTEK_RTS5912_PM_HANDLES_DEFINE (n ) \
196
+ static void uart_rts5912_##n##_pm_entry(enum pm_state state) \
197
+ { \
198
+ uart_rts5912_pm_state_entry(DEVICE_DT_INST_GET(n), state); \
199
+ } \
200
+ \
201
+ static void uart_rts5912_##n##_pm_exit(enum pm_state state) \
202
+ { \
203
+ uart_rts5912_pm_state_exit(DEVICE_DT_INST_GET(n), state); \
204
+ }
205
+ #define UART_REALTEK_RTS5912_PM_HANDLES_BIND (n ) \
206
+ .pm_handles = { \
207
+ .state_entry = uart_rts5912_##n##_pm_entry, \
208
+ .state_exit = uart_rts5912_##n##_pm_exit, \
209
+ },
210
+ #else
211
+ #define UART_REALTEK_RTS5912_PM_HANDLES_DEFINE (n )
212
+ #define UART_REALTEK_RTS5912_PM_HANDLES_BIND (n )
213
+ #endif
214
+
56
215
#define UART_RTS5912_DEVICE_INIT (n ) \
57
- PINCTRL_DT_INST_DEFINE (n); \
216
+ UART_REALTEK_RTS5912_PM_HANDLES_DEFINE (n) \
58
217
\
59
218
static const struct uart_rts5912_device_config uart_rts5912_dev_cfg_##n = { \
60
219
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
@@ -64,9 +223,12 @@ static int rts5912_uart_init(const struct device *dev)
64
223
.clk_grp = DT_INST_CLOCKS_CELL_BY_NAME(n, uart##n, clk_grp), \
65
224
.clk_idx = DT_INST_CLOCKS_CELL_BY_NAME(n, uart##n, clk_idx), \
66
225
}, \
226
+ .uart_rx_wakeup = GPIO_DT_SPEC_INST_GET(n, rx_gpios), \
227
+ .uart_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, uart_dev)), \
67
228
}; \
68
229
\
69
- static struct uart_rts5912_dev_data uart_rts5912_dev_data_##n; \
230
+ static struct uart_rts5912_dev_data uart_rts5912_dev_data_##n = { \
231
+ UART_REALTEK_RTS5912_PM_HANDLES_BIND(n)}; \
70
232
\
71
233
DEVICE_DT_INST_DEFINE(n, &rts5912_uart_init, NULL, &uart_rts5912_dev_data_##n, \
72
234
&uart_rts5912_dev_cfg_##n, PRE_KERNEL_1, \
0 commit comments