1 /*
2 * Copyright (c) 2021 Nuvoton Technology Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nuvoton_npcx_ps2_ctrl
8
9 /**
10 * @file
11 * @brief Nuvoton NPCX PS/2 module (controller) driver
12 *
13 * This file contains the driver of PS/2 module (controller) which provides a
14 * hardware accelerator mechanism to handle both incoming and outgoing data.
15 * The hardware accelerator mechanism is shared by four PS/2 channels.
16 */
17
18 #include <zephyr/kernel.h>
19 #include <zephyr/drivers/clock_control.h>
20 #include <zephyr/drivers/ps2.h>
21 #include <zephyr/dt-bindings/clock/npcx_clock.h>
22
23 #include <zephyr/logging/log.h>
24 #include <zephyr/irq.h>
25 LOG_MODULE_REGISTER(ps2_npcx_ctrl, CONFIG_PS2_LOG_LEVEL);
26
27 #define NPCX_PS2_CH_COUNT 4
28
29 /*
30 * Set WDAT3-0 and clear CLK3-0 in the PSOSIG register to
31 * reset the shift mechanism.
32 */
33 #define NPCX_PS2_SHIFT_MECH_RESET (uint8_t)~NPCX_PSOSIG_CLK_MASK_ALL
34
35 /* in 50us units */
36 #define PS2_RETRY_COUNT 10000
37
38 /*
39 * The max duration of a PS/2 clock is about 100 micro-seconds.
40 * A PS/2 transaction needs 11 clock cycles. It will take about 1.1 ms for a
41 * complete transaction.
42 */
43 #define PS2_TRANSACTION_TIMEOUT K_MSEC(2)
44
45 /* Device config */
46 struct ps2_npcx_ctrl_config {
47 uintptr_t base;
48 struct npcx_clk_cfg clk_cfg;
49 };
50
51 /* Driver data */
52 struct ps2_npcx_ctrl_data {
53 /*
54 * Bit mask to record the enabled PS/2 channels.
55 * Only bit[7] and bit[5:3] are used
56 * (i.e. the bit position of CLK3-0 in the PS2_PSOSIG register)
57 */
58 uint8_t channel_enabled_mask;
59 /* The mutex of the PS/2 controller */
60 struct k_sem lock;
61 /* The semaphore to synchronize the Tx transaction */
62 struct k_sem tx_sync_sem;
63 /*
64 * The callback function to handle the data received from PS/2 device
65 */
66 ps2_callback_t callback_isr[NPCX_PS2_CH_COUNT];
67 };
68
69 /* Driver convenience defines */
70 #define HAL_PS2_INSTANCE(dev) \
71 ((struct ps2_reg *)((const struct ps2_npcx_ctrl_config *)(dev)->config)->base)
72
ps2_npcx_ctrl_get_ch_clk_mask(uint8_t channel_id)73 static uint8_t ps2_npcx_ctrl_get_ch_clk_mask(uint8_t channel_id)
74 {
75 return BIT(NPCX_PSOSIG_CLK(channel_id));
76 }
77
ps2_npcx_ctrl_configure(const struct device * dev,uint8_t channel_id,ps2_callback_t callback_isr)78 int ps2_npcx_ctrl_configure(const struct device *dev, uint8_t channel_id,
79 ps2_callback_t callback_isr)
80 {
81 struct ps2_npcx_ctrl_data *const data = dev->data;
82
83 if (channel_id >= NPCX_PS2_CH_COUNT) {
84 LOG_ERR("unexpected channel ID: %d", channel_id);
85 return -EINVAL;
86 }
87
88 if (callback_isr == NULL) {
89 return -EINVAL;
90 }
91
92 k_sem_take(&data->lock, K_FOREVER);
93 data->callback_isr[channel_id] = callback_isr;
94 k_sem_give(&data->lock);
95
96 return 0;
97 }
98
ps2_npcx_ctrl_enable_interface(const struct device * dev,uint8_t channel_id,bool enable)99 int ps2_npcx_ctrl_enable_interface(const struct device *dev, uint8_t channel_id,
100 bool enable)
101 {
102 struct ps2_npcx_ctrl_data *const data = dev->data;
103 struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
104 uint8_t ch_clk_mask;
105
106 k_sem_take(&data->lock, K_FOREVER);
107 /*
108 * Disable the interrupt during changing the enabled channel mask to
109 * prevent from preemption.
110 */
111 irq_disable(DT_INST_IRQN(0));
112
113 if (channel_id >= NPCX_PS2_CH_COUNT) {
114 LOG_ERR("unexpected channel ID: %d", channel_id);
115 irq_enable(DT_INST_IRQN(0));
116 k_sem_give(&data->lock);
117 return -EINVAL;
118 }
119
120 ch_clk_mask = ps2_npcx_ctrl_get_ch_clk_mask(channel_id);
121 if (enable) {
122 data->channel_enabled_mask |= ch_clk_mask;
123 /* Enable the relevant channel clock */
124 inst->PSOSIG |= ch_clk_mask;
125 } else {
126 data->channel_enabled_mask &= ~ch_clk_mask;
127 /* Disable the relevant channel clock */
128 inst->PSOSIG &= ~ch_clk_mask;
129 }
130
131 irq_enable(DT_INST_IRQN(0));
132 k_sem_give(&data->lock);
133
134 return 0;
135 }
136
ps2_npcx_ctrl_bus_busy(const struct device * dev)137 static int ps2_npcx_ctrl_bus_busy(const struct device *dev)
138 {
139 struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
140
141 /*
142 * The driver pulls the CLK for non-active channels to low when Start
143 * bit is detected and pull the CLK of the active channel low after
144 * Stop bit detected. The EOT bit is set when Stop bit is detected,
145 * but both SOT and EOT are cleared when all CLKs are pull low
146 * (due to Shift Mechanism is reset)
147 */
148 return (IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_SOT) ||
149 IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_EOT)) ?
150 -EBUSY :
151 0;
152 }
153
ps2_npcx_ctrl_write(const struct device * dev,uint8_t channel_id,uint8_t value)154 int ps2_npcx_ctrl_write(const struct device *dev, uint8_t channel_id,
155 uint8_t value)
156 {
157 struct ps2_npcx_ctrl_data *const data = dev->data;
158 struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
159 int i = 0;
160
161 if (channel_id >= NPCX_PS2_CH_COUNT) {
162 LOG_ERR("unexpected channel ID: %d", channel_id);
163 return -EINVAL;
164 }
165
166 if (!(ps2_npcx_ctrl_get_ch_clk_mask(channel_id) &
167 data->channel_enabled_mask)) {
168 LOG_ERR("channel %d is not enabled", channel_id);
169 return -EINVAL;
170 }
171
172 k_sem_take(&data->lock, K_FOREVER);
173
174 while (ps2_npcx_ctrl_bus_busy(dev) && (i < PS2_RETRY_COUNT)) {
175 k_busy_wait(50);
176 i++;
177 }
178
179 if (unlikely(i == PS2_RETRY_COUNT)) {
180 LOG_ERR("PS2 write attempt timed out");
181 goto timeout_invalid;
182 }
183
184 /* Set PS/2 in transmit mode */
185 inst->PSCON |= BIT(NPCX_PSCON_XMT);
186 /* Enable Start Of Transaction interrupt */
187 inst->PSIEN |= BIT(NPCX_PSIEN_SOTIE);
188
189 /* Reset the shift mechanism */
190 inst->PSOSIG = NPCX_PS2_SHIFT_MECH_RESET;
191 /* Inhibit communication should last at least 100 micro-seconds */
192 k_busy_wait(100);
193
194 /* Write the data to be transmitted */
195 inst->PSDAT = value;
196 /* Apply the Request-to-send */
197 inst->PSOSIG &= ~BIT(NPCX_PSOSIG_WDAT(channel_id));
198 inst->PSOSIG |= ps2_npcx_ctrl_get_ch_clk_mask(channel_id);
199 if (k_sem_take(&data->tx_sync_sem, PS2_TRANSACTION_TIMEOUT) != 0) {
200 irq_disable(DT_INST_IRQN(0));
201 LOG_ERR("PS/2 Tx timeout");
202 /* Reset the shift mechanism */
203 inst->PSOSIG = NPCX_PS2_SHIFT_MECH_RESET;
204 /* Change the PS/2 module to receive mode */
205 inst->PSCON &= ~BIT(NPCX_PSCON_XMT);
206 /*
207 * Restore the channel back to enable according to
208 * channel_enabled_mask.
209 */
210 inst->PSOSIG |= data->channel_enabled_mask;
211 irq_enable(DT_INST_IRQN(0));
212 goto timeout_invalid;
213 }
214
215 k_sem_give(&data->lock);
216 return 0;
217
218 timeout_invalid:
219 k_sem_give(&data->lock);
220 return -ETIMEDOUT;
221 }
222
ps2_npcx_ctrl_is_rx_error(const struct device * dev)223 static int ps2_npcx_ctrl_is_rx_error(const struct device *dev)
224 {
225 struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
226 uint8_t status;
227
228 status = inst->PSTAT & (BIT(NPCX_PSTAT_PERR) | BIT(NPCX_PSTAT_RFERR));
229 if (status) {
230 if (status & BIT(NPCX_PSTAT_PERR))
231 LOG_ERR("RX parity error");
232 if (status & BIT(NPCX_PSTAT_RFERR))
233 LOG_ERR("RX Frame error");
234 return -EIO;
235 }
236
237 return 0;
238 }
239
ps2_npcx_ctrl_isr(const struct device * dev)240 static void ps2_npcx_ctrl_isr(const struct device *dev)
241 {
242 uint8_t active_ch, mask;
243 struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
244 struct ps2_npcx_ctrl_data *const data = dev->data;
245
246 /*
247 * ACH = 1 : Channel 0
248 * ACH = 2 : Channel 1
249 * ACH = 4 : Channel 2
250 * ACH = 5 : Channel 3
251 */
252 active_ch = GET_FIELD(inst->PSTAT, NPCX_PSTAT_ACH);
253 active_ch = active_ch > 2 ? (active_ch - 2) : (active_ch - 1);
254 LOG_DBG("ACH: %d\n", active_ch);
255
256 /*
257 * Inhibit PS/2 transaction of the other non-active channels by
258 * pulling down the clock signal
259 */
260 mask = ~NPCX_PSOSIG_CLK_MASK_ALL | BIT(NPCX_PSOSIG_CLK(active_ch));
261 inst->PSOSIG &= mask;
262
263 /* PS/2 Start of Transaction */
264 if (IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_SOT) &&
265 IS_BIT_SET(inst->PSIEN, NPCX_PSIEN_SOTIE)) {
266 /*
267 * Once set, SOT is not cleared until the shift mechanism
268 * is reset. Therefore, SOTIE should be cleared on the
269 * first occurrence of an SOT interrupt.
270 */
271 inst->PSIEN &= ~BIT(NPCX_PSIEN_SOTIE);
272 LOG_DBG("SOT");
273 /* PS/2 End of Transaction */
274 } else if (IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_EOT)) {
275 inst->PSIEN &= ~BIT(NPCX_PSIEN_EOTIE);
276
277 /*
278 * Clear the CLK of active channel to reset
279 * the shift mechanism
280 */
281 inst->PSOSIG &= ~BIT(NPCX_PSOSIG_CLK(active_ch));
282
283 /* Tx is done */
284 if (IS_BIT_SET(inst->PSCON, NPCX_PSCON_XMT)) {
285 /* Change the PS/2 module to receive mode */
286 inst->PSCON &= ~BIT(NPCX_PSCON_XMT);
287 k_sem_give(&data->tx_sync_sem);
288 } else {
289 if (ps2_npcx_ctrl_is_rx_error(dev) == 0) {
290 ps2_callback_t callback;
291 uint8_t data_in = inst->PSDAT;
292
293 LOG_DBG("Recv:0x%02x", data_in);
294 callback = data->callback_isr[active_ch];
295 if (callback != NULL) {
296 callback(dev, data_in);
297 }
298 }
299 }
300
301 /* Restore the enabled channel */
302 inst->PSOSIG |= data->channel_enabled_mask;
303 /*
304 * Re-enable the Start Of Transaction interrupt when
305 * the shift mechanism is reset
306 */
307 inst->PSIEN |= BIT(NPCX_PSIEN_SOTIE);
308 inst->PSIEN |= BIT(NPCX_PSIEN_EOTIE);
309 LOG_DBG("EOT");
310 }
311 }
312
313 /* PS/2 driver registration */
314 static int ps2_npcx_ctrl_init(const struct device *dev);
315
316 static struct ps2_npcx_ctrl_data ps2_npcx_ctrl_data_0;
317
318 static const struct ps2_npcx_ctrl_config ps2_npcx_ctrl_config_0 = {
319 .base = DT_INST_REG_ADDR(0),
320 .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0),
321 };
322
323 DEVICE_DT_INST_DEFINE(0, &ps2_npcx_ctrl_init, NULL, &ps2_npcx_ctrl_data_0,
324 &ps2_npcx_ctrl_config_0, POST_KERNEL,
325 CONFIG_PS2_INIT_PRIORITY, NULL);
326
ps2_npcx_ctrl_init(const struct device * dev)327 static int ps2_npcx_ctrl_init(const struct device *dev)
328 {
329 const struct ps2_npcx_ctrl_config *const config = dev->config;
330 struct ps2_npcx_ctrl_data *const data = dev->data;
331 struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
332 const struct device *const clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE);
333 int ret;
334
335 if (!device_is_ready(clk_dev)) {
336 LOG_ERR("%s device not ready", clk_dev->name);
337 return -ENODEV;
338 }
339
340 /* Turn on PS/2 controller device clock */
341 ret = clock_control_on(clk_dev,
342 (clock_control_subsys_t)&config->clk_cfg);
343 if (ret < 0) {
344 LOG_ERR("Turn on PS/2 clock fail %d", ret);
345 return ret;
346 }
347
348 /* Disable shift mechanism and configure PS/2 to received mode. */
349 inst->PSCON = 0x0;
350 /* Set WDAT3-0 and clear CLK3-0 before enabling shift mechanism */
351 inst->PSOSIG = NPCX_PS2_SHIFT_MECH_RESET;
352 /*
353 * PS/2 interrupt enable register
354 * [0] - : SOTIE = 1: Start Of Transaction Interrupt Enable
355 * [1] - : EOTIE = 1: End Of Transaction Interrupt Enable
356 * [4] - : WUE = 1: Wake-Up Enable
357 * [7] - : CLK_SEL = 1: Select Free-Run clock as the basic clock
358 * 0: Select APB1 clock as the basic clock
359 */
360 inst->PSIEN = BIT(NPCX_PSIEN_SOTIE) | BIT(NPCX_PSIEN_EOTIE) |
361 BIT(NPCX_PSIEN_PS2_WUE);
362 if (config->clk_cfg.bus == NPCX_CLOCK_BUS_FREERUN)
363 inst->PSIEN |= BIT(NPCX_PSIEN_PS2_CLK_SEL);
364 /* Enable weak internal pull-up */
365 inst->PSCON |= BIT(NPCX_PSCON_WPUED);
366 /* Enable shift mechanism */
367 inst->PSCON |= BIT(NPCX_PSCON_EN);
368
369 k_sem_init(&data->lock, 1, 1);
370 k_sem_init(&data->tx_sync_sem, 0, 1);
371
372 IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
373 ps2_npcx_ctrl_isr, DEVICE_DT_INST_GET(0), 0);
374
375 irq_enable(DT_INST_IRQN(0));
376
377 return 0;
378 }
379