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 <drivers/clock_control.h>
19 #include <drivers/ps2.h>
20 #include <dt-bindings/clock/npcx_clock.h>
21 
22 #include <logging/log.h>
23 LOG_MODULE_REGISTER(ps2_npcx_ctrl, CONFIG_PS2_LOG_LEVEL);
24 
25 #define NPCX_PS2_CH_COUNT 4
26 
27 /*
28  * Set WDAT3-0 and clear CLK3-0 in the PSOSIG register to
29  * reset the shift mechanism.
30  */
31 #define NPCX_PS2_SHIFT_MECH_RESET (uint8_t)~NPCX_PSOSIG_CLK_MASK_ALL
32 
33 /* in 50us units */
34 #define PS2_RETRY_COUNT 10000
35 
36 /*
37  * The max duration of a PS/2 clock is about 100 micro-seconds.
38  * A PS/2 transaction needs 11 clock cycles. It will take about 1.1 ms for a
39  * complete transaction.
40  */
41 #define PS2_TRANSACTION_TIMEOUT K_MSEC(2)
42 
43 /* Device config */
44 struct ps2_npcx_ctrl_config {
45 	uintptr_t base;
46 	struct npcx_clk_cfg clk_cfg;
47 };
48 
49 /* Driver data */
50 struct ps2_npcx_ctrl_data {
51 	/*
52 	 * Bit mask to record the enabled PS/2 channels.
53 	 * Only bit[7] and bit[5:3] are used
54 	 * (i.e. the bit position of CLK3-0 in the PS2_PSOSIG register)
55 	 */
56 	uint8_t channel_enabled_mask;
57 	/* The mutex of the PS/2 controller */
58 	struct k_sem lock;
59 	/* The semaphore to synchronize the Tx transaction */
60 	struct k_sem tx_sync_sem;
61 	/*
62 	 * The callback function to handle the data received from PS/2 device
63 	 */
64 	ps2_callback_t callback_isr[NPCX_PS2_CH_COUNT];
65 };
66 
67 /* Driver convenience defines */
68 #define DRV_CONFIG(dev) ((const struct ps2_npcx_ctrl_config *)(dev)->config)
69 
70 #define DRV_DATA(dev) ((struct ps2_npcx_ctrl_data *)(dev)->data)
71 
72 #define HAL_PS2_INSTANCE(dev) (struct ps2_reg *)(DRV_CONFIG(dev)->base)
73 
ps2_npcx_ctrl_get_ch_clk_mask(uint8_t channel_id)74 static uint8_t ps2_npcx_ctrl_get_ch_clk_mask(uint8_t channel_id)
75 {
76 	return BIT(NPCX_PSOSIG_CLK(channel_id));
77 }
78 
ps2_npcx_ctrl_configure(const struct device * dev,uint8_t channel_id,ps2_callback_t callback_isr)79 int ps2_npcx_ctrl_configure(const struct device *dev, uint8_t channel_id,
80 			    ps2_callback_t callback_isr)
81 {
82 	struct ps2_npcx_ctrl_data *const data = DRV_DATA(dev);
83 
84 	if (channel_id >= NPCX_PS2_CH_COUNT) {
85 		LOG_ERR("unexpected channel ID: %d", channel_id);
86 		return -EINVAL;
87 	}
88 
89 	if (callback_isr == NULL) {
90 		return -EINVAL;
91 	}
92 
93 	k_sem_take(&data->lock, K_FOREVER);
94 	data->callback_isr[channel_id] = callback_isr;
95 	k_sem_give(&data->lock);
96 
97 	return 0;
98 }
99 
ps2_npcx_ctrl_enable_interface(const struct device * dev,uint8_t channel_id,bool enable)100 int ps2_npcx_ctrl_enable_interface(const struct device *dev, uint8_t channel_id,
101 				   bool enable)
102 {
103 	struct ps2_npcx_ctrl_data *const data = DRV_DATA(dev);
104 	struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
105 	uint8_t ch_clk_mask;
106 
107 	k_sem_take(&data->lock, K_FOREVER);
108 	/*
109 	 * Disable the interrupt during changing the enabled channel mask to
110 	 * prevent from preemption.
111 	 */
112 	irq_disable(DT_INST_IRQN(0));
113 
114 	if (channel_id >= NPCX_PS2_CH_COUNT) {
115 		LOG_ERR("unexpected channel ID: %d", channel_id);
116 		irq_enable(DT_INST_IRQN(0));
117 		k_sem_give(&data->lock);
118 		return -EINVAL;
119 	}
120 
121 	ch_clk_mask = ps2_npcx_ctrl_get_ch_clk_mask(channel_id);
122 	if (enable) {
123 		data->channel_enabled_mask |= ch_clk_mask;
124 		/* Enable the relevant channel clock */
125 		inst->PSOSIG |= ch_clk_mask;
126 	} else {
127 		data->channel_enabled_mask &= ~ch_clk_mask;
128 		/* Disable the relevant channel clock */
129 		inst->PSOSIG &= ~ch_clk_mask;
130 	}
131 
132 	irq_enable(DT_INST_IRQN(0));
133 	k_sem_give(&data->lock);
134 
135 	return 0;
136 }
137 
ps2_npcx_ctrl_bus_busy(const struct device * dev)138 static int ps2_npcx_ctrl_bus_busy(const struct device *dev)
139 {
140 	struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
141 
142 	/*
143 	 * The driver pulls the CLK for non-active channels to low when Start
144 	 * bit is detected and pull the CLK of the active channel low after
145 	 * Stop bit detected. The EOT bit is set when Stop bit is detected,
146 	 * but both SOT and EOT are cleared when all CLKs are pull low
147 	 * (due to Shift Mechanism is reset)
148 	 */
149 	return (IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_SOT) ||
150 		IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_EOT)) ?
151 		       -EBUSY :
152 		       0;
153 }
154 
ps2_npcx_ctrl_write(const struct device * dev,uint8_t channel_id,uint8_t value)155 int ps2_npcx_ctrl_write(const struct device *dev, uint8_t channel_id,
156 			uint8_t value)
157 {
158 	struct ps2_npcx_ctrl_data *const data = DRV_DATA(dev);
159 	struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
160 	int i = 0;
161 
162 	if (channel_id >= NPCX_PS2_CH_COUNT) {
163 		LOG_ERR("unexpected channel ID: %d", channel_id);
164 		return -EINVAL;
165 	}
166 
167 	if (!(ps2_npcx_ctrl_get_ch_clk_mask(channel_id) &
168 	      data->channel_enabled_mask)) {
169 		LOG_ERR("channel %d is not enabled", channel_id);
170 		return -EINVAL;
171 	}
172 
173 	k_sem_take(&data->lock, K_FOREVER);
174 
175 	while (ps2_npcx_ctrl_bus_busy(dev) && (i < PS2_RETRY_COUNT)) {
176 		k_busy_wait(50);
177 		i++;
178 	}
179 
180 	if (unlikely(i == PS2_RETRY_COUNT)) {
181 		LOG_ERR("PS2 write attempt timed out");
182 		goto timeout_invalid;
183 	}
184 
185 	/* Set PS/2 in transmit mode */
186 	inst->PSCON |= BIT(NPCX_PSCON_XMT);
187 	/* Enable Start Of Transaction interrupt */
188 	inst->PSIEN |= BIT(NPCX_PSIEN_SOTIE);
189 
190 	/* Reset the shift mechanism */
191 	inst->PSOSIG = NPCX_PS2_SHIFT_MECH_RESET;
192 	/* Inhibit communication should last at least 100 micro-seconds */
193 	k_busy_wait(100);
194 
195 	/* Write the data to be transmitted */
196 	inst->PSDAT = value;
197 	/* Apply the Request-to-send */
198 	inst->PSOSIG &= ~BIT(NPCX_PSOSIG_WDAT(channel_id));
199 	inst->PSOSIG |= ps2_npcx_ctrl_get_ch_clk_mask(channel_id);
200 	if (k_sem_take(&data->tx_sync_sem, PS2_TRANSACTION_TIMEOUT) != 0) {
201 		irq_disable(DT_INST_IRQN(0));
202 		LOG_ERR("PS/2 Tx timeout");
203 		/* Reset the shift mechanism */
204 		inst->PSOSIG = NPCX_PS2_SHIFT_MECH_RESET;
205 		/* Change the PS/2 module to receive mode */
206 		inst->PSCON &= ~BIT(NPCX_PSCON_XMT);
207 		/*
208 		 * Restore the channel back to enable according to
209 		 * channel_enabled_mask.
210 		 */
211 		inst->PSOSIG |= data->channel_enabled_mask;
212 		irq_enable(DT_INST_IRQN(0));
213 		goto timeout_invalid;
214 	}
215 
216 	k_sem_give(&data->lock);
217 	return 0;
218 
219 timeout_invalid:
220 	k_sem_give(&data->lock);
221 	return -ETIMEDOUT;
222 }
223 
ps2_npcx_ctrl_is_rx_error(const struct device * dev)224 static int ps2_npcx_ctrl_is_rx_error(const struct device *dev)
225 {
226 	struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
227 	uint8_t status;
228 
229 	status = inst->PSTAT & (BIT(NPCX_PSTAT_PERR) | BIT(NPCX_PSTAT_RFERR));
230 	if (status) {
231 		if (status & BIT(NPCX_PSTAT_PERR))
232 			LOG_ERR("RX parity error");
233 		if (status & BIT(NPCX_PSTAT_RFERR))
234 			LOG_ERR("RX Frame error");
235 		return -EIO;
236 	}
237 
238 	return 0;
239 }
240 
ps2_npcx_ctrl_isr(const struct device * dev)241 static void ps2_npcx_ctrl_isr(const struct device *dev)
242 {
243 	uint8_t active_ch, mask;
244 	struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
245 	struct ps2_npcx_ctrl_data *const data = DRV_DATA(dev);
246 
247 	/*
248 	 * ACH = 1 : Channel 0
249 	 * ACH = 2 : Channel 1
250 	 * ACH = 4 : Channel 2
251 	 * ACH = 5 : Channel 3
252 	 */
253 	active_ch = GET_FIELD(inst->PSTAT, NPCX_PSTAT_ACH);
254 	active_ch = active_ch > 2 ? (active_ch - 2) : (active_ch - 1);
255 	LOG_DBG("ACH: %d\n", active_ch);
256 
257 	/*
258 	 * Inhibit PS/2 transaction of the other non-active channels by
259 	 * pulling down the clock signal
260 	 */
261 	mask = ~NPCX_PSOSIG_CLK_MASK_ALL | BIT(NPCX_PSOSIG_CLK(active_ch));
262 	inst->PSOSIG &= mask;
263 
264 	/* PS/2 Start of Transaction */
265 	if (IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_SOT) &&
266 	    IS_BIT_SET(inst->PSIEN, NPCX_PSIEN_SOTIE)) {
267 		/*
268 		 * Once set, SOT is not cleared until the shift mechanism
269 		 * is reset. Therefore, SOTIE should be cleared on the
270 		 * first occurrence of an SOT interrupt.
271 		 */
272 		inst->PSIEN &= ~BIT(NPCX_PSIEN_SOTIE);
273 		LOG_DBG("SOT");
274 		/* PS/2 End of Transaction */
275 	} else if (IS_BIT_SET(inst->PSTAT, NPCX_PSTAT_EOT)) {
276 		inst->PSIEN &= ~BIT(NPCX_PSIEN_EOTIE);
277 
278 		/*
279 		 * Clear the CLK of active channel to reset
280 		 * the shift mechanism
281 		 */
282 		inst->PSOSIG &= ~BIT(NPCX_PSOSIG_CLK(active_ch));
283 
284 		/* Tx is done */
285 		if (IS_BIT_SET(inst->PSCON, NPCX_PSCON_XMT)) {
286 			/* Change the PS/2 module to receive mode */
287 			inst->PSCON &= ~BIT(NPCX_PSCON_XMT);
288 			k_sem_give(&data->tx_sync_sem);
289 		} else {
290 			if (ps2_npcx_ctrl_is_rx_error(dev) == 0) {
291 				ps2_callback_t callback;
292 				uint8_t data_in = inst->PSDAT;
293 
294 				LOG_DBG("Recv:0x%02x", data_in);
295 				callback = data->callback_isr[active_ch];
296 				if (callback != NULL)
297 					callback(dev, data_in);
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 = DRV_CONFIG(dev);
330 	struct ps2_npcx_ctrl_data *const data = DRV_DATA(dev);
331 	struct ps2_reg *const inst = HAL_PS2_INSTANCE(dev);
332 	const struct device *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