1 /*
2  * Copyright (c) 2019 Intel Corporation
3  * Copyright (c) 2022 Microchip Technology Inc.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT microchip_xec_ps2
9 
10 #include <cmsis_core.h>
11 #include <errno.h>
12 #include <zephyr/device.h>
13 #include <zephyr/kernel.h>
14 #ifdef CONFIG_SOC_SERIES_MEC172X
15 #include <zephyr/drivers/clock_control/mchp_xec_clock_control.h>
16 #include <zephyr/drivers/interrupt_controller/intc_mchp_xec_ecia.h>
17 #endif
18 #include <zephyr/drivers/pinctrl.h>
19 #include <zephyr/pm/device.h>
20 #include <zephyr/pm/policy.h>
21 #include <zephyr/drivers/ps2.h>
22 #include <soc.h>
23 #include <zephyr/logging/log.h>
24 #include <zephyr/irq.h>
25 #include <zephyr/drivers/gpio.h>
26 
27 #define LOG_LEVEL CONFIG_PS2_LOG_LEVEL
28 LOG_MODULE_REGISTER(ps2_mchp_xec);
29 
30 /* in 50us units */
31 #define PS2_TIMEOUT 10000
32 
33 struct ps2_xec_config {
34 	struct ps2_regs * const regs;
35 	int isr_nvic;
36 	uint8_t girq_id;
37 	uint8_t girq_bit;
38 	uint8_t girq_id_wk;
39 	uint8_t girq_bit_wk;
40 	uint8_t pcr_idx;
41 	uint8_t pcr_pos;
42 	void (*irq_config_func)(void);
43 	const struct pinctrl_dev_config *pcfg;
44 #ifdef CONFIG_PM_DEVICE
45 	struct gpio_dt_spec wakerx_gpio;
46 	bool wakeup_source;
47 #endif
48 };
49 
50 
51 struct ps2_xec_data {
52 	ps2_callback_t callback_isr;
53 	struct k_sem tx_lock;
54 };
55 
56 
57 #ifdef CONFIG_SOC_SERIES_MEC172X
ps2_xec_slp_en_clr(const struct device * dev)58 static inline void ps2_xec_slp_en_clr(const struct device *dev)
59 {
60 	const struct ps2_xec_config * const cfg = dev->config;
61 
62 	z_mchp_xec_pcr_periph_sleep(cfg->pcr_idx, cfg->pcr_pos, 0);
63 }
64 
ps2_xec_girq_clr(uint8_t girq_idx,uint8_t girq_posn)65 static inline void ps2_xec_girq_clr(uint8_t girq_idx, uint8_t girq_posn)
66 {
67 	mchp_soc_ecia_girq_src_clr(girq_idx, girq_posn);
68 }
69 
ps2_xec_girq_en(uint8_t girq_idx,uint8_t girq_posn)70 static inline void ps2_xec_girq_en(uint8_t girq_idx, uint8_t girq_posn)
71 {
72 	mchp_xec_ecia_girq_src_en(girq_idx, girq_posn);
73 }
74 
ps2_xec_girq_dis(uint8_t girq_idx,uint8_t girq_posn)75 static inline void ps2_xec_girq_dis(uint8_t girq_idx, uint8_t girq_posn)
76 {
77 	mchp_xec_ecia_girq_src_dis(girq_idx, girq_posn);
78 }
79 #else
ps2_xec_slp_en_clr(const struct device * dev)80 static inline void ps2_xec_slp_en_clr(const struct device *dev)
81 {
82 	const struct ps2_xec_config * const cfg = dev->config;
83 
84 	if (cfg->pcr_pos == MCHP_PCR3_PS2_0_POS) {
85 		mchp_pcr_periph_slp_ctrl(PCR_PS2_0, 0);
86 	} else {
87 		mchp_pcr_periph_slp_ctrl(PCR_PS2_1, 0);
88 	}
89 }
90 
ps2_xec_girq_clr(uint8_t girq_idx,uint8_t girq_posn)91 static inline void ps2_xec_girq_clr(uint8_t girq_idx, uint8_t girq_posn)
92 {
93 	MCHP_GIRQ_SRC(girq_idx) = BIT(girq_posn);
94 }
95 
ps2_xec_girq_en(uint8_t girq_idx,uint8_t girq_posn)96 static inline void ps2_xec_girq_en(uint8_t girq_idx, uint8_t girq_posn)
97 {
98 	MCHP_GIRQ_ENSET(girq_idx) = BIT(girq_posn);
99 }
100 
ps2_xec_girq_dis(uint8_t girq_idx,uint8_t girq_posn)101 static inline void ps2_xec_girq_dis(uint8_t girq_idx, uint8_t girq_posn)
102 {
103 	MCHP_GIRQ_ENCLR(girq_idx) = MCHP_KBC_IBF_GIRQ;
104 }
105 #endif /* CONFIG_SOC_SERIES_MEC172X */
106 
ps2_xec_configure(const struct device * dev,ps2_callback_t callback_isr)107 static int ps2_xec_configure(const struct device *dev,
108 			     ps2_callback_t callback_isr)
109 {
110 	const struct ps2_xec_config * const config = dev->config;
111 	struct ps2_xec_data * const data = dev->data;
112 	struct ps2_regs * const regs = config->regs;
113 
114 	uint8_t  __attribute__((unused)) temp;
115 
116 	if (!callback_isr) {
117 		return -EINVAL;
118 	}
119 
120 	data->callback_isr = callback_isr;
121 
122 	/* In case the self test for a PS2 device already finished and
123 	 * set the SOURCE bit to 1 we clear it before enabling the
124 	 * interrupts. Instances must be allocated before the BAT
125 	 * (Basic Assurance Test) or the host may time out.
126 	 */
127 	temp = regs->TRX_BUFF;
128 	regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK;
129 	/* clear next higher level */
130 	ps2_xec_girq_clr(config->girq_id, config->girq_bit);
131 
132 	/* Enable FSM and init instance in rx mode*/
133 	regs->CTRL = MCHP_PS2_CTRL_EN_POS;
134 
135 	/* We enable the interrupts in the EC aggregator so that the
136 	 * result  can be forwarded to the ARM NVIC
137 	 */
138 	ps2_xec_girq_en(config->girq_id, config->girq_bit);
139 
140 	k_sem_give(&data->tx_lock);
141 
142 	return 0;
143 }
144 
145 
ps2_xec_write(const struct device * dev,uint8_t value)146 static int ps2_xec_write(const struct device *dev, uint8_t value)
147 {
148 	const struct ps2_xec_config * const config = dev->config;
149 	struct ps2_xec_data * const data = dev->data;
150 	struct ps2_regs * const regs = config->regs;
151 	int i = 0;
152 
153 	uint8_t  __attribute__((unused)) temp;
154 
155 	if (k_sem_take(&data->tx_lock, K_NO_WAIT)) {
156 		return -EACCES;
157 	}
158 	/* Allow the PS2 controller to complete a RX transaction. This
159 	 * is because the channel may be actively receiving data.
160 	 * In addition, it is necessary to wait for a previous TX
161 	 * transaction to complete. The PS2 block has a single
162 	 * FSM.
163 	 */
164 	while (((regs->STATUS &
165 		(MCHP_PS2_STATUS_RX_BUSY | MCHP_PS2_STATUS_TX_IDLE))
166 		!= MCHP_PS2_STATUS_TX_IDLE) && (i < PS2_TIMEOUT)) {
167 		k_busy_wait(50);
168 		i++;
169 	}
170 
171 	if (unlikely(i == PS2_TIMEOUT)) {
172 		LOG_DBG("PS2 write timed out");
173 		return -ETIMEDOUT;
174 	}
175 
176 	pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
177 
178 	/* Inhibit ps2 controller and clear status register */
179 	regs->CTRL = 0x00;
180 
181 	/* Read to clear data ready bit in the status register*/
182 	temp = regs->TRX_BUFF;
183 	k_sleep(K_MSEC(1));
184 	regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK;
185 
186 	/* Switch the interface to TX mode and enable state machine */
187 	regs->CTRL = MCHP_PS2_CTRL_TR_TX | MCHP_PS2_CTRL_EN;
188 
189 	/* Write value to TX/RX register */
190 	regs->TRX_BUFF = value;
191 
192 	k_sem_give(&data->tx_lock);
193 
194 	return 0;
195 }
196 
ps2_xec_inhibit_interface(const struct device * dev)197 static int ps2_xec_inhibit_interface(const struct device *dev)
198 {
199 	const struct ps2_xec_config * const config = dev->config;
200 	struct ps2_xec_data * const data = dev->data;
201 	struct ps2_regs * const regs = config->regs;
202 
203 	if (k_sem_take(&data->tx_lock, K_MSEC(10)) != 0) {
204 		return -EACCES;
205 	}
206 
207 	regs->CTRL = 0x00;
208 	regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK;
209 	ps2_xec_girq_clr(config->girq_id, config->girq_bit);
210 	NVIC_ClearPendingIRQ(config->isr_nvic);
211 
212 	k_sem_give(&data->tx_lock);
213 
214 	return 0;
215 }
216 
ps2_xec_enable_interface(const struct device * dev)217 static int ps2_xec_enable_interface(const struct device *dev)
218 {
219 	const struct ps2_xec_config * const config = dev->config;
220 	struct ps2_xec_data * const data = dev->data;
221 	struct ps2_regs * const regs = config->regs;
222 
223 	ps2_xec_girq_clr(config->girq_id, config->girq_bit);
224 	regs->CTRL = MCHP_PS2_CTRL_EN;
225 
226 	k_sem_give(&data->tx_lock);
227 
228 	return 0;
229 }
230 
231 #ifdef CONFIG_PM_DEVICE
ps2_xec_pm_action(const struct device * dev,enum pm_device_action action)232 static int ps2_xec_pm_action(const struct device *dev, enum pm_device_action action)
233 {
234 	const struct ps2_xec_config *const devcfg = dev->config;
235 	struct ps2_regs * const regs = devcfg->regs;
236 	int ret = 0;
237 
238 	switch (action) {
239 	case PM_DEVICE_ACTION_RESUME:
240 		if (devcfg->wakeup_source) {
241 			/* Disable PS2 wake interrupt
242 			 * Disable interrupt on PS2DAT pin
243 			 */
244 			if (devcfg->wakerx_gpio.port != NULL) {
245 				ret = gpio_pin_interrupt_configure_dt(
246 						&devcfg->wakerx_gpio,
247 						GPIO_INT_DISABLE);
248 				if (ret < 0) {
249 					LOG_ERR("Fail to disable PS2 wake interrupt (ret %d)", ret);
250 					return ret;
251 				}
252 			}
253 			ps2_xec_girq_dis(devcfg->girq_id_wk, devcfg->girq_bit_wk);
254 			ps2_xec_girq_clr(devcfg->girq_id_wk, devcfg->girq_bit_wk);
255 		} else {
256 			ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_DEFAULT);
257 			regs->CTRL |= MCHP_PS2_CTRL_EN;
258 		}
259 	break;
260 	case PM_DEVICE_ACTION_SUSPEND:
261 		if (devcfg->wakeup_source) {
262 			/* Enable PS2 wake interrupt
263 			 * Configure Falling Edge Trigger interrupt on PS2DAT pin
264 			 */
265 			ps2_xec_girq_clr(devcfg->girq_id_wk, devcfg->girq_bit_wk);
266 			ps2_xec_girq_en(devcfg->girq_id_wk, devcfg->girq_bit_wk);
267 			if (devcfg->wakerx_gpio.port != NULL) {
268 				ret = gpio_pin_interrupt_configure_dt(
269 					&devcfg->wakerx_gpio,
270 					GPIO_INT_MODE_EDGE | GPIO_INT_TRIG_LOW);
271 				if (ret < 0) {
272 					LOG_ERR("Fail to enable PS2 wake interrupt(ret %d)", ret);
273 					return ret;
274 				}
275 			}
276 		} else {
277 			regs->CTRL &= ~MCHP_PS2_CTRL_EN;
278 			/* If application does not want to turn off PS2 pins it will
279 			 * not define pinctrl-1 for this node.
280 			 */
281 			ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_SLEEP);
282 			if (ret == -ENOENT) { /* pinctrl-1 does not exist.  */
283 				ret = 0;
284 			}
285 		}
286 	break;
287 	default:
288 		ret = -ENOTSUP;
289 	}
290 
291 	return ret;
292 }
293 #endif /* CONFIG_PM_DEVICE */
294 
ps2_xec_isr(const struct device * dev)295 static void ps2_xec_isr(const struct device *dev)
296 {
297 	const struct ps2_xec_config * const config = dev->config;
298 	struct ps2_xec_data * const data = dev->data;
299 	struct ps2_regs * const regs = config->regs;
300 	uint32_t status;
301 
302 	/* Read and clear status */
303 	status = regs->STATUS;
304 
305 	/* clear next higher level the GIRQ */
306 	ps2_xec_girq_clr(config->girq_id, config->girq_bit);
307 
308 	if (status & MCHP_PS2_STATUS_RXD_RDY) {
309 		pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
310 
311 		regs->CTRL = 0x00;
312 		if (data->callback_isr) {
313 			data->callback_isr(dev, regs->TRX_BUFF);
314 		}
315 
316 		pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
317 	} else if (status &
318 		    (MCHP_PS2_STATUS_TX_TMOUT | MCHP_PS2_STATUS_TX_ST_TMOUT)) {
319 		/* Clear sticky bits and go to read mode */
320 		regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK;
321 		LOG_ERR("TX time out: %0x", status);
322 
323 		pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
324 	} else if (status &
325 			(MCHP_PS2_STATUS_RX_TMOUT | MCHP_PS2_STATUS_PE | MCHP_PS2_STATUS_FE)) {
326 		/* catch and clear rx error if any */
327 		regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK;
328 	} else if (status & MCHP_PS2_STATUS_TX_IDLE) {
329 		/* Transfer completed, release the lock to enter low per mode */
330 
331 		pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
332 	}
333 
334 	/* The control register reverts to RX automatically after
335 	 * transmitting the data
336 	 */
337 	regs->CTRL = MCHP_PS2_CTRL_EN;
338 }
339 
340 static DEVICE_API(ps2, ps2_xec_driver_api) = {
341 	.config = ps2_xec_configure,
342 	.read = NULL,
343 	.write = ps2_xec_write,
344 	.disable_callback = ps2_xec_inhibit_interface,
345 	.enable_callback = ps2_xec_enable_interface,
346 };
347 
ps2_xec_init(const struct device * dev)348 static int ps2_xec_init(const struct device *dev)
349 {
350 	const struct ps2_xec_config * const cfg = dev->config;
351 	struct ps2_xec_data * const data = dev->data;
352 	int ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
353 	if (ret != 0) {
354 		LOG_ERR("XEC PS2 pinctrl init failed (%d)", ret);
355 		return ret;
356 	}
357 
358 	ps2_xec_slp_en_clr(dev);
359 
360 	k_sem_init(&data->tx_lock, 0, 1);
361 
362 	cfg->irq_config_func();
363 
364 	return 0;
365 }
366 
367 /* To enable wakeup on the PS2, the DTS needs to have two entries defined
368  * in the corresponding PS2 node in the DTS specifying it as a wake source
369  * and specifying the PS2DAT GPIO; example as below
370  *
371  *	wakerx-gpios = <MCHP_GPIO_DECODE_115 GPIO_ACTIVE_HIGH>
372  *	wakeup-source;
373  */
374 #ifdef CONFIG_PM_DEVICE
375 #define XEC_PS2_PM_WAKEUP(n)						\
376 		.wakeup_source = (uint8_t)DT_INST_PROP_OR(n, wakeup_source, 0),	\
377 		.wakerx_gpio = GPIO_DT_SPEC_INST_GET_OR(n, wakerx_gpios, {0}),
378 #else
379 #define XEC_PS2_PM_WAKEUP(index) /* Not used */
380 #endif
381 
382 #define XEC_PS2_PINCTRL_CFG(inst) PINCTRL_DT_INST_DEFINE(inst)
383 #define XEC_PS2_CONFIG(inst)							\
384 	static const struct ps2_xec_config ps2_xec_config_##inst = {		\
385 		.regs = (struct ps2_regs * const)(DT_INST_REG_ADDR(inst)),	\
386 		.isr_nvic = DT_INST_IRQN(inst),					\
387 		.girq_id = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 0)),	\
388 		.girq_bit = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 1)),	\
389 		.girq_id_wk = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 2)),	\
390 		.girq_bit_wk = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 3)),	\
391 		.pcr_idx = (uint8_t)(DT_INST_PROP_BY_IDX(inst, pcrs, 0)),	\
392 		.pcr_pos = (uint8_t)(DT_INST_PROP_BY_IDX(inst, pcrs, 1)),	\
393 		.irq_config_func = ps2_xec_irq_config_func_##inst,		\
394 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),			\
395 		XEC_PS2_PM_WAKEUP(inst)						\
396 	}
397 
398 #define PS2_XEC_DEVICE(i)						\
399 									\
400 	static void ps2_xec_irq_config_func_##i(void)			\
401 	{								\
402 		IRQ_CONNECT(DT_INST_IRQN(i),				\
403 			    DT_INST_IRQ(i, priority),			\
404 			    ps2_xec_isr,				\
405 			    DEVICE_DT_INST_GET(i), 0);			\
406 		irq_enable(DT_INST_IRQN(i));				\
407 	}								\
408 									\
409 	static struct ps2_xec_data ps2_xec_port_data_##i;		\
410 									\
411 	XEC_PS2_PINCTRL_CFG(i);						\
412 									\
413 	XEC_PS2_CONFIG(i);						\
414 									\
415 	PM_DEVICE_DT_INST_DEFINE(i, ps2_xec_pm_action);		\
416 									\
417 	DEVICE_DT_INST_DEFINE(i, &ps2_xec_init,				\
418 		PM_DEVICE_DT_INST_GET(i),				\
419 		&ps2_xec_port_data_##i, &ps2_xec_config_##i,		\
420 		POST_KERNEL, CONFIG_PS2_INIT_PRIORITY,			\
421 		&ps2_xec_driver_api);
422 
423 DT_INST_FOREACH_STATUS_OKAY(PS2_XEC_DEVICE)
424