1 /*
2  * Copyright (c) 2020 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nuvoton_npcx_host_sub
8 
9 /**
10  * @file
11  * @brief Nuvoton NPCX host sub modules driver
12  *
13  * This file contains the drivers of NPCX Host Sub-Modules that serve as an
14  * interface between the Host and Core domains. Please refer the block diagram.
15  *
16  *                                        +------------+
17  *                                        |   Serial   |---> TXD
18  *                                  +<--->|    Port    |<--- RXD
19  *                                  |     |            |<--> ...
20  *                                  |     +------------+
21  *                                  |     +------------+     |
22  *                +------------+    |<--->|  KBC & PM  |<--->|
23  *   eSPI_CLK --->|  eSPI Bus  |    |     |  Channels  |     |
24  *   eSPI_RST --->| Controller |    |     +------------+     |
25  * eSPI_IO3-0 <-->|            |<-->|     +------------+     |
26  *    eSPI_CS --->| (eSPI mode)|    |     |   Shared   |     |
27  * eSPI_ALERT <-->|            |    |<--->|   Memory   |<--->|
28  *                +------------+    |     +------------+     |
29  *                                  |     +------------+     |
30  *                                  |<--->|    MSWC    |<--->|
31  *                                  |     +------------+     |
32  *                                  |     +------------+     |
33  *                                  |     |    Core    |     |
34  *                                  |<--->|   to Host  |<--->|
35  *                                  |     |   Access   |     |
36  *                                  |     +------------+     |
37  *                                HMIB                       | Core Bus
38  *                     (Host Modules Internal Bus)           +------------
39  *
40  *
41  * For most of them, the Host can configure these modules via eSPI(Peripheral
42  * Channel)/LPC by accessing 'Configuration and Control register Set' which IO
43  * base address is 0x4E as default. (The table below illustrates structure of
44  * 'Configuration and Control Register Set') And the interrupts in core domain
45  * help handling any events from host side.
46  *
47  *   Index |     Configuration and Control Register Set
48  * --------|--------------------------------------------------+   Bank Select
49  *    07h  |      Logical Device Number Register (LDN)        |---------+
50  * --------|---------------------------------------------------         |
51  *  20-2Fh |        SuperI/O Configuration Registers          |         |
52  * ------------------------------------------------------------         |
53  * --------|---------------------------------------------------_        |
54  *    30h  |      Logical Device Control Register             | |_      |
55  * --------|--------------------------------------------------- | |_    |
56  *  60-63h |   I/O Space Configuration Registers              | | | |   |
57  * --------|--------------------------------------------------- | | |   |
58  *  70-71h |     Interrupt Configuration Registers            | | | |   |
59  * --------|--------------------------------------------------- | | |   |
60  *  73-74h | DMA Configuration Registers (No support in NPCX) | | | |   |
61  * --------|--------------------------------------------------- | | |<--+
62  *  F0-FFh | Special Logical Device Configuration Registers   | | | |
63  * --------|--------------------------------------------------- | | |
64  *           |--------------------------------------------------- | |
65  *             |--------------------------------------------------- |
66  *               |---------------------------------------------------
67  *
68  *
69  * This driver introduces six host sub-modules. It includes:
70  *
71  * 1. Keyboard and Mouse Controller (KBC) interface.
72  *   ● Intel 8051SL-compatible Host interface
73  *     — 8042 KBD standard interface (ports 60h, 64h)
74  *     — Legacy IRQ: IRQ1 (KBD) and IRQ12 (mouse) support
75  *   ● Configured by two logical devices: Keyboard and Mouse (LDN 0x06/0x05)
76  *
77  * 2. Power Management (PM) channels.
78  *   ● PM channel registers
79  *     — Command/Status register
80  *     — Data register
81  *       channel 1: legacy 62h, 66h; channel 2: legacy 68h, 6Ch;
82  *       channel 3: legacy 6Ah, 6Eh; channel 4: legacy 6Bh, 6Fh;
83  *   ● PM interrupt using:
84  *     — Serial IRQ
85  *     — SMI
86  *     — EC_SCI
87  *   ● Configured by four logical devices: PM1/2/3/4 (LDN 0x11/0x12/0x17/0x1E)
88  *
89  * 3. Shared Memory mechanism (SHM).
90  *   This module allows sharing of the on-chip RAM by both Core and the Host.
91  *   It also supports the following features:
92  *   ● Four Core/Host communication windows for direct RAM access
93  *   ● Eight Protection regions for each access window
94  *   ● Host IRQ and SMI generation
95  *   ● Port 80 debug support
96  *   ● Configured by one logical device: SHM (LDN 0x0F)
97  *
98  * 4. Core Access to Host Modules (C2H).
99  *   ● A interface to access module registers in host domain.
100  *     It enables the Core to access the registers in host domain (i.e., Host
101  *     Configuration, Serial Port, SHM, and MSWC), through HMIB.
102  *
103  * 5. Mobile System Wake-Up functions (MSWC).
104  *   It detects and handles wake-up events from various sources in the Host
105  *   modules and alerts the Core for better power consumption.
106  *
107  * 6. Serial Port (Legacy UART)
108  *   It provides UART functionality by supporting serial data communication
109  *   with a remote peripheral device or a modem.
110  *
111  * INCLUDE FILES: soc_host.h
112  *
113  */
114 
115 #include <assert.h>
116 #include <zephyr/drivers/espi.h>
117 #include <zephyr/drivers/gpio.h>
118 #include <zephyr/drivers/clock_control.h>
119 #include <zephyr/drivers/pinctrl.h>
120 #include <zephyr/kernel.h>
121 #include <zephyr/sys/ring_buffer.h>
122 #include <soc.h>
123 #include "espi_utils.h"
124 #include "soc_host.h"
125 #include "soc_espi.h"
126 #include "soc_miwu.h"
127 
128 #include <zephyr/logging/log.h>
129 #include <zephyr/irq.h>
130 LOG_MODULE_REGISTER(host_sub_npcx, LOG_LEVEL_ERR);
131 
132 struct host_sub_npcx_config {
133 	/* host module instances */
134 	struct mswc_reg *const inst_mswc;
135 	struct shm_reg *const inst_shm;
136 	struct c2h_reg *const inst_c2h;
137 	struct kbc_reg *const inst_kbc;
138 	struct pmch_reg *const inst_pm_acpi;
139 	struct pmch_reg *const inst_pm_hcmd;
140 	/* clock configuration */
141 	const uint8_t clks_size;
142 	const struct npcx_clk_cfg *clks_list;
143 	/* mapping table between host access signals and wake-up input */
144 	struct npcx_wui host_acc_wui;
145 };
146 
147 struct host_sub_npcx_data {
148 	sys_slist_t *callbacks; /* pointer on the espi callback list */
149 	uint8_t plt_rst_asserted; /* current PLT_RST# status */
150 	uint8_t espi_rst_level; /* current ESPI_RST# status */
151 	const struct device *host_bus_dev; /* device for eSPI/LPC bus */
152 #ifdef CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE
153 	struct ring_buf port80_ring_buf;
154 	uint8_t port80_data[CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_RING_BUF_SIZE];
155 	struct k_work work;
156 #endif
157 };
158 
159 struct npcx_dp80_buf {
160 	union {
161 		uint16_t offset_code_16;
162 		uint8_t offset_code[2];
163 	};
164 };
165 
166 static const struct npcx_clk_cfg host_dev_clk_cfg[] =
167 					NPCX_DT_CLK_CFG_ITEMS_LIST(0);
168 
169 struct host_sub_npcx_config host_sub_cfg = {
170 	.inst_mswc = (struct mswc_reg *)DT_INST_REG_ADDR_BY_NAME(0, mswc),
171 	.inst_shm = (struct shm_reg *)DT_INST_REG_ADDR_BY_NAME(0, shm),
172 	.inst_c2h = (struct c2h_reg *)DT_INST_REG_ADDR_BY_NAME(0, c2h),
173 	.inst_kbc = (struct kbc_reg *)DT_INST_REG_ADDR_BY_NAME(0, kbc),
174 	.inst_pm_acpi = (struct pmch_reg *)DT_INST_REG_ADDR_BY_NAME(0, pm_acpi),
175 	.inst_pm_hcmd = (struct pmch_reg *)DT_INST_REG_ADDR_BY_NAME(0, pm_hcmd),
176 	.host_acc_wui = NPCX_DT_WUI_ITEM_BY_NAME(0, host_acc_wui),
177 	.clks_size = ARRAY_SIZE(host_dev_clk_cfg),
178 	.clks_list = host_dev_clk_cfg,
179 };
180 
181 struct host_sub_npcx_data host_sub_data;
182 
183 /* Application shouldn't touch these flags in KBC status register directly */
184 #define NPCX_KBC_STS_MASK (BIT(NPCX_HIKMST_IBF) | BIT(NPCX_HIKMST_OBF) \
185 						| BIT(NPCX_HIKMST_A2))
186 
187 /* IO base address of EC Logical Device Configuration */
188 #define NPCX_EC_CFG_IO_ADDR 0x4E
189 
190 /* Timeout to wait for Core-to-Host transaction to be completed. */
191 #define NPCX_C2H_TRANSACTION_TIMEOUT_US 200
192 
193 /* Logical Device Number Assignments */
194 #define EC_CFG_LDN_SP    0x03
195 #define EC_CFG_LDN_MOUSE 0x05
196 #define EC_CFG_LDN_KBC   0x06
197 #define EC_CFG_LDN_SHM   0x0F
198 #define EC_CFG_LDN_ACPI  0x11 /* PM Channel 1 */
199 #define EC_CFG_LDN_HCMD  0x12 /* PM Channel 2 */
200 
201 /* Index of EC (4E/4F) Configuration Register */
202 #define EC_CFG_IDX_LDN            0x07
203 #define EC_CFG_IDX_CTRL           0x30
204 #define EC_CFG_IDX_DATA_IO_ADDR_H 0x60
205 #define EC_CFG_IDX_DATA_IO_ADDR_L 0x61
206 #define EC_CFG_IDX_CMD_IO_ADDR_H  0x62
207 #define EC_CFG_IDX_CMD_IO_ADDR_L  0x63
208 
209 /* LDN Activation Enable */
210 #define EC_CFG_IDX_CTRL_LDN_ENABLE 0x01
211 
212 /* Index of SuperI/O Control and Configuration Registers */
213 #define EC_CFG_IDX_SUPERIO_SIOCF9      0x29
214 #define EC_CFG_IDX_SUPERIO_SIOCF9_CKEN 2
215 
216 /* Index of Special Logical Device Configuration (Shared Memory Module) */
217 #define EC_CFG_IDX_SHM_CFG             0xF1
218 #define EC_CFG_IDX_SHM_WND1_ADDR_0     0xF4
219 #define EC_CFG_IDX_SHM_WND1_ADDR_1     0xF5
220 #define EC_CFG_IDX_SHM_WND1_ADDR_2     0xF6
221 #define EC_CFG_IDX_SHM_WND1_ADDR_3     0xF7
222 #define EC_CFG_IDX_SHM_WND2_ADDR_0     0xF8
223 #define EC_CFG_IDX_SHM_WND2_ADDR_1     0xF9
224 #define EC_CFG_IDX_SHM_WND2_ADDR_2     0xFA
225 #define EC_CFG_IDX_SHM_WND2_ADDR_3     0xFB
226 #define EC_CFG_IDX_SHM_DP80_ADDR_RANGE 0xFD
227 
228 /* Index of Special Logical Device Configuration (Serial Port/Host UART) */
229 #define EC_CFG_IDX_SP_CFG              0xF0
230 /* Enable selection of bank 2 and 3 for the Serial Port */
231 #define EC_CFG_IDX_SP_CFG_BK_SL_ENABLE 7
232 
233 /* Host sub-device local inline functions */
host_shd_mem_wnd_size_sl(uint32_t size)234 static inline uint8_t host_shd_mem_wnd_size_sl(uint32_t size)
235 {
236 	/* The minimum supported shared memory region size is 8 bytes */
237 	if (size <= 8U) {
238 		size = 8U;
239 	}
240 
241 	/* The maximum supported shared memory region size is 4K bytes */
242 	if (size >= 4096U) {
243 		size = 4096U;
244 	}
245 
246 	/*
247 	 * If window size is not a power-of-two, it is rounded-up to the next
248 	 * power-of-two value, and return value corresponds to RWINx_SIZE field.
249 	 */
250 	return (32 - __builtin_clz(size - 1U)) & 0xff;
251 }
252 
253 /* Host KBC sub-device local functions */
254 #if defined(CONFIG_ESPI_PERIPHERAL_8042_KBC)
host_kbc_ibf_isr(const void * arg)255 static void host_kbc_ibf_isr(const void *arg)
256 {
257 	ARG_UNUSED(arg);
258 	struct kbc_reg *const inst_kbc = host_sub_cfg.inst_kbc;
259 	struct espi_event evt = { ESPI_BUS_PERIPHERAL_NOTIFICATION,
260 		ESPI_PERIPHERAL_8042_KBC, ESPI_PERIPHERAL_NODATA
261 	};
262 	struct espi_evt_data_kbc *kbc_evt =
263 				(struct espi_evt_data_kbc *)&evt.evt_data;
264 
265 	/* KBC Input Buffer Full event */
266 	kbc_evt->evt = HOST_KBC_EVT_IBF;
267 	/* The data in KBC Input Buffer */
268 	kbc_evt->data = inst_kbc->HIKMDI;
269 	/*
270 	 * Indicates if the host sent a command or data.
271 	 * 0 = data
272 	 * 1 = Command.
273 	 */
274 	kbc_evt->type = IS_BIT_SET(inst_kbc->HIKMST, NPCX_HIKMST_A2);
275 
276 	LOG_DBG("%s: kbc data 0x%02x", __func__, evt.evt_data);
277 	espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev,
278 							evt);
279 }
280 
host_kbc_obe_isr(const void * arg)281 static void host_kbc_obe_isr(const void *arg)
282 {
283 	ARG_UNUSED(arg);
284 	struct kbc_reg *const inst_kbc = host_sub_cfg.inst_kbc;
285 	struct espi_event evt = { ESPI_BUS_PERIPHERAL_NOTIFICATION,
286 		ESPI_PERIPHERAL_8042_KBC, ESPI_PERIPHERAL_NODATA
287 	};
288 	struct espi_evt_data_kbc *kbc_evt =
289 				(struct espi_evt_data_kbc *)&evt.evt_data;
290 
291 	/* Disable KBC OBE interrupt first */
292 	inst_kbc->HICTRL &= ~BIT(NPCX_HICTRL_OBECIE);
293 
294 	LOG_DBG("%s: kbc status 0x%02x", __func__, inst_kbc->HIKMST);
295 
296 	/*
297 	 * Notify application that host already read out data. The application
298 	 * might need to clear status register via espi_api_lpc_write_request()
299 	 * with E8042_CLEAR_FLAG opcode in callback.
300 	 */
301 	kbc_evt->evt = HOST_KBC_EVT_OBE;
302 	kbc_evt->data = 0;
303 	kbc_evt->type = 0;
304 
305 	espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev,
306 							evt);
307 }
308 
host_kbc_init(void)309 static void host_kbc_init(void)
310 {
311 	struct kbc_reg *const inst_kbc = host_sub_cfg.inst_kbc;
312 
313 	/* Make sure the previous OBF and IRQ has been sent out. */
314 	k_busy_wait(4);
315 	/* Set FW_OBF to clear OBF flag in both STATUS and HIKMST to 0 */
316 	inst_kbc->HICTRL |= BIT(NPCX_HICTRL_FW_OBF);
317 	/* Ensure there is no OBF set in this period. */
318 	k_busy_wait(4);
319 
320 	/*
321 	 * Init KBC with:
322 	 * 1. Enable Input Buffer Full (IBF) core interrupt for Keyboard/mouse.
323 	 * 2. Enable Output Buffer Full Mouse(OBFM) SIRQ 12.
324 	 * 3. Enable Output Buffer Full Keyboard (OBFK) SIRQ 1.
325 	 */
326 	inst_kbc->HICTRL = BIT(NPCX_HICTRL_IBFCIE) | BIT(NPCX_HICTRL_OBFMIE)
327 						| BIT(NPCX_HICTRL_OBFKIE);
328 
329 	/* Configure SIRQ 1/12 type (level + high) */
330 	inst_kbc->HIIRQC = 0x00;
331 }
332 #endif
333 
334 /* Host ACPI sub-device local functions */
335 #if defined(CONFIG_ESPI_PERIPHERAL_HOST_IO)
host_acpi_process_input_data(uint8_t data)336 static void host_acpi_process_input_data(uint8_t data)
337 {
338 	struct pmch_reg *const inst_acpi = host_sub_cfg.inst_pm_acpi;
339 	struct espi_event evt = {
340 		.evt_type = ESPI_BUS_PERIPHERAL_NOTIFICATION,
341 		.evt_details = ESPI_PERIPHERAL_HOST_IO,
342 		.evt_data = ESPI_PERIPHERAL_NODATA
343 	};
344 	struct espi_evt_data_acpi *acpi_evt =
345 				(struct espi_evt_data_acpi *)&evt.evt_data;
346 
347 	LOG_DBG("%s: acpi data 0x%02x", __func__, data);
348 
349 	/*
350 	 * Indicates if the host sent a command or data.
351 	 * 0 = data
352 	 * 1 = Command.
353 	 */
354 	acpi_evt->type = IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_CMD);
355 	acpi_evt->data = data;
356 
357 	espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev,
358 							evt);
359 }
360 
host_acpi_init(void)361 static void host_acpi_init(void)
362 {
363 	struct pmch_reg *const inst_acpi = host_sub_cfg.inst_pm_acpi;
364 
365 	/* Use SMI/SCI postive polarity by default */
366 	inst_acpi->HIPMCTL &= ~BIT(NPCX_HIPMCTL_SCIPOL);
367 	inst_acpi->HIPMIC &= ~BIT(NPCX_HIPMIC_SMIPOL);
368 
369 	/* Set SMIB/SCIB bits to make sure SMI#/SCI# are driven to high */
370 	inst_acpi->HIPMIC |= BIT(NPCX_HIPMIC_SMIB) | BIT(NPCX_HIPMIC_SCIB);
371 
372 	/*
373 	 * Allow SMI#/SCI# generated from PM module.
374 	 * On eSPI bus, we suggest set VW value of SCI#/SMI# directly.
375 	 */
376 	inst_acpi->HIPMIE |= BIT(NPCX_HIPMIE_SCIE);
377 	inst_acpi->HIPMIE |= BIT(NPCX_HIPMIE_SMIE);
378 
379 	/*
380 	 * Init ACPI PM channel (Host IO) with:
381 	 * 1. Enable Input-Buffer Full (IBF) core interrupt.
382 	 * 2. BIT 7 must be 1.
383 	 */
384 	inst_acpi->HIPMCTL |= BIT(7) | BIT(NPCX_HIPMCTL_IBFIE);
385 }
386 #endif
387 
388 #if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)
389 /* Host command argument and memory map buffers */
390 static uint8_t	shm_host_cmd[CONFIG_ESPI_NPCX_PERIPHERAL_HOST_CMD_PARAM_SIZE]
391 	__aligned(8);
392 /* Host command sub-device local functions */
host_hcmd_process_input_data(uint8_t data)393 static void host_hcmd_process_input_data(uint8_t data)
394 {
395 	struct espi_event evt = { ESPI_BUS_PERIPHERAL_NOTIFICATION,
396 		ESPI_PERIPHERAL_EC_HOST_CMD, ESPI_PERIPHERAL_NODATA
397 	};
398 
399 	evt.evt_data = data;
400 	LOG_DBG("%s: host cmd data 0x%02x", __func__, evt.evt_data);
401 	espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev,
402 							evt);
403 }
404 
host_hcmd_init(void)405 static void host_hcmd_init(void)
406 {
407 	struct pmch_reg *const inst_hcmd = host_sub_cfg.inst_pm_hcmd;
408 	struct shm_reg *const inst_shm = host_sub_cfg.inst_shm;
409 	uint32_t win_size = CONFIG_ESPI_NPCX_PERIPHERAL_HOST_CMD_PARAM_SIZE;
410 
411 	/* Don't stall SHM transactions */
412 	inst_shm->SHM_CTL &= ~0x40;
413 	/* Disable Window 1 protection */
414 	inst_shm->WIN1_WR_PROT = 0;
415 	inst_shm->WIN1_RD_PROT = 0;
416 
417 	/* Configure Win1 size for ec host command. */
418 	SET_FIELD(inst_shm->WIN_SIZE, NPCX_WIN_SIZE_RWIN1_SIZE_FIELD,
419 		host_shd_mem_wnd_size_sl(win_size));
420 	inst_shm->WIN_BASE1 = (uint32_t)shm_host_cmd;
421 
422 	/*
423 	 * Clear processing flag before enabling host's interrupts in case
424 	 * it's set by the other command during sysjump.
425 	 */
426 	inst_hcmd->HIPMST &= ~BIT(NPCX_HIPMST_F0);
427 
428 	/*
429 	 * Init Host Command PM channel (Host IO) with:
430 	 * 1. Enable Input-Buffer Full (IBF) core interrupt.
431 	 * 2. BIT 7 must be 1.
432 	 */
433 	inst_hcmd->HIPMCTL |= BIT(7) | BIT(NPCX_HIPMCTL_IBFIE);
434 }
435 #endif
436 
437 #if defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
438 /* Host command argument and memory map buffers */
439 static uint8_t shm_acpi_mmap[CONFIG_ESPI_NPCX_PERIPHERAL_ACPI_SHD_MEM_SIZE]
440 	__aligned(8);
host_shared_mem_region_init(void)441 static void host_shared_mem_region_init(void)
442 {
443 	struct shm_reg *const inst_shm = host_sub_cfg.inst_shm;
444 	uint32_t win_size = CONFIG_ESPI_NPCX_PERIPHERAL_ACPI_SHD_MEM_SIZE;
445 
446 	/* Don't stall SHM transactions */
447 	inst_shm->SHM_CTL &= ~0x40;
448 	/* Disable Window 2 protection */
449 	inst_shm->WIN2_WR_PROT = 0;
450 	inst_shm->WIN2_RD_PROT = 0;
451 
452 	/* Configure Win2 size for ACPI shared mem region. */
453 	SET_FIELD(inst_shm->WIN_SIZE, NPCX_WIN_SIZE_RWIN2_SIZE_FIELD,
454 		host_shd_mem_wnd_size_sl(win_size));
455 	inst_shm->WIN_BASE2 = (uint32_t)shm_acpi_mmap;
456 	/* Enable write protect of Share memory window 2 */
457 	inst_shm->WIN2_WR_PROT = 0xFF;
458 
459 	/*
460 	 * TODO: Initialize shm_acpi_mmap buffer for host command flags. We
461 	 * might use EACPI_GET_SHARED_MEMORY in espi_api_lpc_read_request()
462 	 * instead of setting host command flags here directly.
463 	 */
464 }
465 #endif
466 
467 #if defined(CONFIG_ESPI_PERIPHERAL_HOST_IO) || \
468 				defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)
469 /* Host pm (host io) sub-module isr function for all channels such as ACPI. */
host_pmch_ibf_isr(const void * arg)470 static void host_pmch_ibf_isr(const void *arg)
471 {
472 	ARG_UNUSED(arg);
473 	struct pmch_reg *const inst_acpi = host_sub_cfg.inst_pm_acpi;
474 	struct pmch_reg *const inst_hcmd = host_sub_cfg.inst_pm_hcmd;
475 	uint8_t in_data;
476 
477 	/* Host put data on input buffer of ACPI channel */
478 	if (IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_IBF)) {
479 		/* Set processing flag before reading command byte */
480 		inst_acpi->HIPMST |= BIT(NPCX_HIPMST_F0);
481 		/* Read out input data and clear IBF pending bit */
482 		in_data = inst_acpi->HIPMDI;
483 #if defined(CONFIG_ESPI_PERIPHERAL_HOST_IO)
484 		host_acpi_process_input_data(in_data);
485 #endif
486 	}
487 
488 	/* Host put data on input buffer of HOSTCMD channel */
489 	if (IS_BIT_SET(inst_hcmd->HIPMST, NPCX_HIPMST_IBF)) {
490 		/* Set processing flag before reading command byte */
491 		inst_hcmd->HIPMST |= BIT(NPCX_HIPMST_F0);
492 		/* Read out input data and clear IBF pending bit */
493 		in_data = inst_hcmd->HIPMDI;
494 #if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)
495 		host_hcmd_process_input_data(in_data);
496 #endif
497 	}
498 }
499 #endif
500 
501 /* Host port80 sub-device local functions */
502 #if defined(CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80)
503 #if defined(CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE)
host_port80_work_handler(struct k_work * item)504 static void host_port80_work_handler(struct k_work *item)
505 {
506 	uint32_t code = 0;
507 	struct host_sub_npcx_data *data = CONTAINER_OF(item, struct host_sub_npcx_data, work);
508 	struct ring_buf *rbuf = &data->port80_ring_buf;
509 	struct espi_event evt = {ESPI_BUS_PERIPHERAL_NOTIFICATION,
510 				 (ESPI_PERIPHERAL_INDEX_0 << 16) | ESPI_PERIPHERAL_DEBUG_PORT80,
511 				 ESPI_PERIPHERAL_NODATA};
512 
513 	while (!ring_buf_is_empty(rbuf)) {
514 		struct npcx_dp80_buf dp80_buf;
515 		uint8_t offset;
516 
517 		ring_buf_get(rbuf, &dp80_buf.offset_code[0], sizeof(dp80_buf.offset_code));
518 		offset = dp80_buf.offset_code[1];
519 		code |= dp80_buf.offset_code[0] << (8 * offset);
520 		if (ring_buf_is_empty(rbuf)) {
521 			evt.evt_data = code;
522 			espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev,
523 					    evt);
524 			break;
525 		}
526 		/* peek the offset of the next byte */
527 		ring_buf_peek(rbuf, &dp80_buf.offset_code[0], sizeof(dp80_buf.offset_code));
528 		offset = dp80_buf.offset_code[1];
529 		/*
530 		 * If the peeked next byte's offset is 0, it is the start of the new code.
531 		 * Pass the current code to the application layer to handle the Port80 code.
532 		 */
533 		if (offset == 0) {
534 			evt.evt_data = code;
535 			espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev,
536 					    evt);
537 			code = 0;
538 		}
539 	}
540 }
541 #endif
542 
host_port80_isr(const void * arg)543 static void host_port80_isr(const void *arg)
544 {
545 	ARG_UNUSED(arg);
546 	struct shm_reg *const inst_shm = host_sub_cfg.inst_shm;
547 	uint8_t status = inst_shm->DP80STS;
548 
549 #ifdef CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE
550 	struct ring_buf *rbuf = &host_sub_data.port80_ring_buf;
551 
552 	while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) {
553 		struct npcx_dp80_buf dp80_buf;
554 
555 		dp80_buf.offset_code_16 = inst_shm->DP80BUF;
556 		ring_buf_put(rbuf, &dp80_buf.offset_code[0], sizeof(dp80_buf.offset_code));
557 	}
558 	k_work_submit(&host_sub_data.work);
559 #else
560 	struct espi_event evt = {ESPI_BUS_PERIPHERAL_NOTIFICATION,
561 				 (ESPI_PERIPHERAL_INDEX_0 << 16) | ESPI_PERIPHERAL_DEBUG_PORT80,
562 				 ESPI_PERIPHERAL_NODATA};
563 
564 	/* Read out port80 data continuously if FIFO is not empty */
565 	while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) {
566 		LOG_DBG("p80: %04x", inst_shm->DP80BUF);
567 		evt.evt_data = inst_shm->DP80BUF;
568 		espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev, evt);
569 	}
570 #endif
571 	LOG_DBG("%s: p80 status 0x%02X", __func__, status);
572 
573 	/* If FIFO is overflow, show error msg */
574 	if (IS_BIT_SET(status, NPCX_DP80STS_FOR)) {
575 		inst_shm->DP80STS |= BIT(NPCX_DP80STS_FOR);
576 		LOG_DBG("Port80 FIFO Overflow!");
577 	}
578 
579 	/* If there are pending post codes remains in FIFO after processing and sending previous
580 	 * post codes, do not clear the FNE bit. This allows this handler to be called again
581 	 * immediately after it exists.
582 	 */
583 	if (!IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) {
584 		/* Clear all pending bit indicates that FIFO was written by host */
585 		inst_shm->DP80STS |= BIT(NPCX_DP80STS_FWR);
586 	}
587 }
588 
host_port80_init(void)589 static void host_port80_init(void)
590 {
591 	struct shm_reg *const inst_shm = host_sub_cfg.inst_shm;
592 
593 	/*
594 	 * Init PORT80 which includes:
595 	 * Enables a Core interrupt on every Host write to the FIFO,
596 	 * SYNC mode (It must be 1 in eSPI mode), Read Auto Advance mode, and
597 	 * Port80 module itself.
598 	 */
599 	inst_shm->DP80CTL = BIT(NPCX_DP80CTL_CIEN) | BIT(NPCX_DP80CTL_RAA)
600 			| BIT(NPCX_DP80CTL_DP80EN) | BIT(NPCX_DP80CTL_SYNCEN);
601 }
602 #endif
603 
604 #if defined(CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE)
host_cus_opcode_enable_interrupts(void)605 static void host_cus_opcode_enable_interrupts(void)
606 {
607 	/* Enable host KBC sub-device interrupt */
608 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_8042_KBC)) {
609 		irq_enable(DT_INST_IRQ_BY_NAME(0, kbc_ibf, irq));
610 		irq_enable(DT_INST_IRQ_BY_NAME(0, kbc_obe, irq));
611 	}
612 
613 	/* Enable host PM channel (Host IO) sub-device interrupt */
614 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_HOST_IO) ||
615 	    IS_ENABLED(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)) {
616 		irq_enable(DT_INST_IRQ_BY_NAME(0, pmch_ibf, irq));
617 	}
618 
619 	/* Enable host Port80 sub-device interrupt installation */
620 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80)) {
621 		irq_enable(DT_INST_IRQ_BY_NAME(0, p80_fifo, irq));
622 	}
623 
624 	/* Enable host interface interrupts if its interface is eSPI */
625 	if (IS_ENABLED(CONFIG_ESPI)) {
626 		npcx_espi_enable_interrupts(host_sub_data.host_bus_dev);
627 	}
628 }
629 
host_cus_opcode_disable_interrupts(void)630 static void host_cus_opcode_disable_interrupts(void)
631 {
632 	/* Disable host KBC sub-device interrupt */
633 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_8042_KBC)) {
634 		irq_disable(DT_INST_IRQ_BY_NAME(0, kbc_ibf, irq));
635 		irq_disable(DT_INST_IRQ_BY_NAME(0, kbc_obe, irq));
636 	}
637 
638 	/* Disable host PM channel (Host IO) sub-device interrupt */
639 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_HOST_IO) ||
640 		IS_ENABLED(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)) {
641 		irq_disable(DT_INST_IRQ_BY_NAME(0, pmch_ibf, irq));
642 	}
643 
644 	/* Disable host Port80 sub-device interrupt installation */
645 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80)) {
646 		irq_disable(DT_INST_IRQ_BY_NAME(0, p80_fifo, irq));
647 	}
648 
649 	/* Disable host interface interrupts if its interface is eSPI */
650 	if (IS_ENABLED(CONFIG_ESPI)) {
651 		npcx_espi_disable_interrupts(host_sub_data.host_bus_dev);
652 	}
653 }
654 #endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
655 
656 #if defined(CONFIG_ESPI_PERIPHERAL_UART)
657 /* host uart pinmux configuration */
658 PINCTRL_DT_DEFINE(DT_INST(0, nuvoton_npcx_host_uart));
659 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(nuvoton_npcx_host_uart) == 1,
660 	"only one 'nuvoton_npcx_host_uart' compatible node may be present");
661 const struct pinctrl_dev_config *huart_cfg =
662 			PINCTRL_DT_DEV_CONFIG_GET(DT_INST(0, nuvoton_npcx_host_uart));
663 /* Host UART sub-device local functions */
host_uart_init(void)664 void host_uart_init(void)
665 {
666 	struct c2h_reg *const inst_c2h = host_sub_cfg.inst_c2h;
667 
668 	/* Configure pin-mux for serial port device */
669 	pinctrl_apply_state(huart_cfg, PINCTRL_STATE_DEFAULT);
670 
671 	/* Make sure unlock host access of serial port */
672 	inst_c2h->LKSIOHA &= ~BIT(NPCX_LKSIOHA_LKSPHA);
673 	/* Clear 'Host lock violation occurred' bit of serial port initially */
674 	inst_c2h->SIOLV |= BIT(NPCX_SIOLV_SPLV);
675 }
676 #endif
677 
678 /* host core-to-host interface local functions */
host_c2h_wait_write_done(void)679 static void host_c2h_wait_write_done(void)
680 {
681 	struct c2h_reg *const inst_c2h = host_sub_cfg.inst_c2h;
682 	uint32_t elapsed_cycles;
683 	uint32_t start_cycles = k_cycle_get_32();
684 	uint32_t max_wait_cycles =
685 			k_us_to_cyc_ceil32(NPCX_C2H_TRANSACTION_TIMEOUT_US);
686 
687 	while (IS_BIT_SET(inst_c2h->SIBCTRL, NPCX_SIBCTRL_CSWR)) {
688 		elapsed_cycles = k_cycle_get_32() - start_cycles;
689 		if (elapsed_cycles > max_wait_cycles) {
690 			LOG_ERR("c2h write transaction expired!");
691 			break;
692 		}
693 	}
694 }
695 
host_c2h_wait_read_done(void)696 static void host_c2h_wait_read_done(void)
697 {
698 	struct c2h_reg *const inst_c2h = host_sub_cfg.inst_c2h;
699 	uint32_t elapsed_cycles;
700 	uint32_t start_cycles = k_cycle_get_32();
701 	uint32_t max_wait_cycles =
702 			k_us_to_cyc_ceil32(NPCX_C2H_TRANSACTION_TIMEOUT_US);
703 
704 	while (IS_BIT_SET(inst_c2h->SIBCTRL, NPCX_SIBCTRL_CSRD)) {
705 		elapsed_cycles = k_cycle_get_32() - start_cycles;
706 		if (elapsed_cycles > max_wait_cycles) {
707 			LOG_ERR("c2h read transaction expired!");
708 			break;
709 		}
710 	}
711 }
712 
host_c2h_write_io_cfg_reg(uint8_t reg_index,uint8_t reg_data)713 void host_c2h_write_io_cfg_reg(uint8_t reg_index, uint8_t reg_data)
714 {
715 	struct c2h_reg *const inst_c2h = host_sub_cfg.inst_c2h;
716 
717 	/* Disable interrupts */
718 	unsigned int key = irq_lock();
719 
720 	/* Lock host access EC configuration registers (0x4E/0x4F) */
721 	inst_c2h->LKSIOHA |= BIT(NPCX_LKSIOHA_LKCFG);
722 	/* Enable Core-to-Host access CFG module */
723 	inst_c2h->CRSMAE |= BIT(NPCX_CRSMAE_CFGAE);
724 
725 	/* Verify core-to-host modules is not in progress */
726 	host_c2h_wait_read_done();
727 	host_c2h_wait_write_done();
728 
729 	/*
730 	 * Specifying the in-direct IO address which A0 = 0 indicates the index
731 	 * register is accessed. Then write index address directly and it starts
732 	 * a write transaction to host sub-module on LPC/eSPI bus.
733 	 */
734 	inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR;
735 	inst_c2h->IHD = reg_index;
736 	host_c2h_wait_write_done();
737 
738 	/*
739 	 * Specifying the in-direct IO address which A0 = 1 indicates the data
740 	 * register is accessed. Then write data directly and it starts a write
741 	 * transaction to host sub-module on LPC/eSPI bus.
742 	 */
743 	inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR + 1;
744 	inst_c2h->IHD = reg_data;
745 	host_c2h_wait_write_done();
746 
747 	/* Disable Core-to-Host access CFG module */
748 	inst_c2h->CRSMAE &= ~BIT(NPCX_CRSMAE_CFGAE);
749 	/* Unlock host access EC configuration registers (0x4E/0x4F) */
750 	inst_c2h->LKSIOHA &= ~BIT(NPCX_LKSIOHA_LKCFG);
751 
752 	/* Enable interrupts */
753 	irq_unlock(key);
754 }
755 
host_c2h_read_io_cfg_reg(uint8_t reg_index)756 uint8_t host_c2h_read_io_cfg_reg(uint8_t reg_index)
757 {
758 	struct c2h_reg *const inst_c2h = host_sub_cfg.inst_c2h;
759 	uint8_t data_val;
760 
761 	/* Disable interrupts */
762 	unsigned int key = irq_lock();
763 
764 	/* Lock host access EC configuration registers (0x4E/0x4F) */
765 	inst_c2h->LKSIOHA |= BIT(NPCX_LKSIOHA_LKCFG);
766 	/* Enable Core-to-Host access CFG module */
767 	inst_c2h->CRSMAE |= BIT(NPCX_CRSMAE_CFGAE);
768 
769 	/* Verify core-to-host modules is not in progress */
770 	host_c2h_wait_read_done();
771 	host_c2h_wait_write_done();
772 
773 	/*
774 	 * Specifying the in-direct IO address which A0 = 0 indicates the index
775 	 * register is accessed. Then write index address directly and it starts
776 	 * a write transaction to host sub-module on LPC/eSPI bus.
777 	 */
778 	inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR;
779 	inst_c2h->IHD = reg_index;
780 	host_c2h_wait_write_done();
781 
782 	/*
783 	 * Specifying the in-direct IO address which A0 = 1 indicates the data
784 	 * register is accessed. Then write CSRD bit in SIBCTRL to issue a read
785 	 * transaction to host sub-module on LPC/eSPI bus. Once it was done,
786 	 * read data out from IHD.
787 	 */
788 	inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR + 1;
789 	inst_c2h->SIBCTRL |= BIT(NPCX_SIBCTRL_CSRD);
790 	host_c2h_wait_read_done();
791 	data_val = inst_c2h->IHD;
792 
793 	/* Disable Core-to-Host access CFG module */
794 	inst_c2h->CRSMAE &= ~BIT(NPCX_CRSMAE_CFGAE);
795 	/* Unlock host access EC configuration registers (0x4E/0x4F) */
796 	inst_c2h->LKSIOHA &= ~BIT(NPCX_LKSIOHA_LKCFG);
797 
798 	/* Enable interrupts */
799 	irq_unlock(key);
800 
801 	return data_val;
802 }
803 
804 /* Platform specific host sub modules functions */
npcx_host_periph_read_request(enum lpc_peripheral_opcode op,uint32_t * data)805 int npcx_host_periph_read_request(enum lpc_peripheral_opcode op,
806 								uint32_t *data)
807 {
808 	if (op >= E8042_START_OPCODE && op <= E8042_MAX_OPCODE) {
809 		struct kbc_reg *const inst_kbc = host_sub_cfg.inst_kbc;
810 
811 		/* Make sure kbc 8042 is on */
812 		if (!IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFKIE) ||
813 			!IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFMIE)) {
814 			return -ENOTSUP;
815 		}
816 
817 		switch (op) {
818 		case E8042_OBF_HAS_CHAR:
819 			/* EC has written data back to host. OBF is
820 			 * automatically cleared after host reads
821 			 * the data
822 			 */
823 			*data = IS_BIT_SET(inst_kbc->HIKMST, NPCX_HIKMST_OBF);
824 			break;
825 		case E8042_IBF_HAS_CHAR:
826 			*data = IS_BIT_SET(inst_kbc->HIKMST, NPCX_HIKMST_IBF);
827 			break;
828 		case E8042_READ_KB_STS:
829 			*data = inst_kbc->HIKMST;
830 			break;
831 		default:
832 			return -EINVAL;
833 		}
834 	} else if (op >= EACPI_START_OPCODE && op <= EACPI_MAX_OPCODE) {
835 		struct pmch_reg *const inst_acpi = host_sub_cfg.inst_pm_acpi;
836 
837 		/* Make sure pm channel for apci is on */
838 		if (!IS_BIT_SET(inst_acpi->HIPMCTL, NPCX_HIPMCTL_IBFIE)) {
839 			return -ENOTSUP;
840 		}
841 
842 		switch (op) {
843 		case EACPI_OBF_HAS_CHAR:
844 			/* EC has written data back to host. OBF is
845 			 * automatically cleared after host reads
846 			 * the data
847 			 */
848 			*data = IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_OBF);
849 			break;
850 		case EACPI_IBF_HAS_CHAR:
851 			*data = IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_IBF);
852 			break;
853 		case EACPI_READ_STS:
854 			*data = inst_acpi->HIPMST;
855 			break;
856 #if defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
857 		case EACPI_GET_SHARED_MEMORY:
858 			*data = (uint32_t)shm_acpi_mmap;
859 			break;
860 #endif /* CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION */
861 		default:
862 			return -EINVAL;
863 		}
864 	}
865 #if defined(CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE)
866 	else if (op >= ECUSTOM_START_OPCODE && op <= ECUSTOM_MAX_OPCODE) {
867 		/* Other customized op codes */
868 		switch (op) {
869 		case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY:
870 			*data = (uint32_t)shm_host_cmd;
871 			break;
872 		case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY_SIZE:
873 			*data = CONFIG_ESPI_NPCX_PERIPHERAL_HOST_CMD_PARAM_SIZE;
874 			break;
875 		default:
876 			return -EINVAL;
877 		}
878 	}
879 #endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
880 	else {
881 		return -ENOTSUP;
882 	}
883 
884 	return 0;
885 }
886 
npcx_host_periph_write_request(enum lpc_peripheral_opcode op,const uint32_t * data)887 int npcx_host_periph_write_request(enum lpc_peripheral_opcode op,
888 							const uint32_t *data)
889 {
890 	volatile uint32_t __attribute__((unused)) dummy;
891 	struct kbc_reg *const inst_kbc = host_sub_cfg.inst_kbc;
892 
893 	if (op >= E8042_START_OPCODE && op <= E8042_MAX_OPCODE) {
894 		/* Make sure kbc 8042 is on */
895 		if (!IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFKIE) ||
896 			!IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFMIE)) {
897 			return -ENOTSUP;
898 		}
899 		if (data) {
900 			LOG_INF("%s: op 0x%x data %x", __func__, op, *data);
901 		} else {
902 			LOG_INF("%s: op 0x%x only", __func__, op);
903 		}
904 
905 		switch (op) {
906 		case E8042_WRITE_KB_CHAR:
907 			inst_kbc->HIKDO = *data & 0xff;
908 			/*
909 			 * Enable KBC OBE interrupt after putting data in
910 			 * keyboard data register.
911 			 */
912 			inst_kbc->HICTRL |= BIT(NPCX_HICTRL_OBECIE);
913 			break;
914 		case E8042_WRITE_MB_CHAR:
915 			inst_kbc->HIMDO = *data & 0xff;
916 			/*
917 			 * Enable KBC OBE interrupt after putting data in
918 			 * mouse data register.
919 			 */
920 			inst_kbc->HICTRL |= BIT(NPCX_HICTRL_OBECIE);
921 			break;
922 		case E8042_RESUME_IRQ:
923 			/* Enable KBC IBF interrupt */
924 			inst_kbc->HICTRL |= BIT(NPCX_HICTRL_IBFCIE);
925 			break;
926 		case E8042_PAUSE_IRQ:
927 			/* Disable KBC IBF interrupt */
928 			inst_kbc->HICTRL &= ~BIT(NPCX_HICTRL_IBFCIE);
929 			break;
930 		case E8042_CLEAR_OBF:
931 			/* Clear OBF flag in both STATUS and HIKMST to 0 */
932 			inst_kbc->HICTRL |= BIT(NPCX_HICTRL_FW_OBF);
933 			break;
934 		case E8042_SET_FLAG:
935 			/* FW shouldn't modify these flags directly */
936 			inst_kbc->HIKMST |= *data & ~NPCX_KBC_STS_MASK;
937 			break;
938 		case E8042_CLEAR_FLAG:
939 			/* FW shouldn't modify these flags directly */
940 			inst_kbc->HIKMST &= ~(*data | NPCX_KBC_STS_MASK);
941 			break;
942 		default:
943 			return -EINVAL;
944 		}
945 	} else if (op >= EACPI_START_OPCODE && op <= EACPI_MAX_OPCODE) {
946 		struct pmch_reg *const inst_acpi = host_sub_cfg.inst_pm_acpi;
947 
948 		/* Make sure pm channel for apci is on */
949 		if (!IS_BIT_SET(inst_acpi->HIPMCTL, NPCX_HIPMCTL_IBFIE)) {
950 			return -ENOTSUP;
951 		}
952 
953 		switch (op) {
954 		case EACPI_WRITE_CHAR:
955 			inst_acpi->HIPMDO = (*data & 0xff);
956 			break;
957 		case EACPI_WRITE_STS:
958 			inst_acpi->HIPMST = (*data & 0xff);
959 			break;
960 		default:
961 			return -EINVAL;
962 		}
963 	}
964 #if defined(CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE)
965 	else if (op >= ECUSTOM_START_OPCODE && op <= ECUSTOM_MAX_OPCODE) {
966 		/* Other customized op codes */
967 		struct pmch_reg *const inst_hcmd = host_sub_cfg.inst_pm_hcmd;
968 
969 		switch (op) {
970 		case ECUSTOM_HOST_SUBS_INTERRUPT_EN:
971 			if (*data != 0) {
972 				host_cus_opcode_enable_interrupts();
973 			} else {
974 				host_cus_opcode_disable_interrupts();
975 			}
976 			break;
977 		case ECUSTOM_HOST_CMD_SEND_RESULT:
978 			/*
979 			 * Write result to the data byte.  This sets the TOH
980 			 * status bit.
981 			 */
982 			inst_hcmd->HIPMDO = (*data & 0xff);
983 			/* Clear processing flag */
984 			inst_hcmd->HIPMST &= ~BIT(NPCX_HIPMST_F0);
985 			break;
986 		default:
987 			return -EINVAL;
988 		}
989 	}
990 #endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
991 	else {
992 		return -ENOTSUP;
993 	}
994 
995 	return 0;
996 }
997 
npcx_host_init_subs_host_domain(void)998 void npcx_host_init_subs_host_domain(void)
999 {
1000 	struct c2h_reg *const inst_c2h = host_sub_cfg.inst_c2h;
1001 
1002 	/* Enable Core-to-Host access module */
1003 	inst_c2h->SIBCTRL |= BIT(NPCX_SIBCTRL_CSAE);
1004 
1005 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_8042_KBC)) {
1006 		/*
1007 		 * Select Keyboard/Mouse banks which LDN are 0x06/05 and enable
1008 		 * modules by setting bit 0 in its Control (index is 0x30) reg.
1009 		 */
1010 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_KBC);
1011 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE);
1012 
1013 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_MOUSE);
1014 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE);
1015 	}
1016 
1017 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_HOST_IO)) {
1018 		/*
1019 		 * Select ACPI bank which LDN are 0x11 (PM Channel 1) and enable
1020 		 * module by setting bit 0 in its Control (index is 0x30) reg.
1021 		 */
1022 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_ACPI);
1023 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE);
1024 	}
1025 
1026 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) ||
1027 	    IS_ENABLED(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)) {
1028 		/* Select 'Host Command' bank which LDN are 0x12 (PM chan 2) */
1029 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_HCMD);
1030 #if defined(CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM)
1031 		/* Configure IO address of CMD portt (default: 0x200) */
1032 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_DATA_IO_ADDR_H,
1033 		 (CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM >> 8) & 0xff);
1034 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_DATA_IO_ADDR_L,
1035 		 CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM & 0xff);
1036 		/* Configure IO address of Data portt (default: 0x204) */
1037 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_CMD_IO_ADDR_H,
1038 		 ((CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM + 4) >> 8)
1039 		 & 0xff);
1040 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_CMD_IO_ADDR_L,
1041 		 (CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM + 4) & 0xff);
1042 #endif
1043 		/* Enable 'Host Command' io port (PM Channel 2) */
1044 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE);
1045 
1046 		/* Select 'Shared Memory' bank which LDN are 0x0F */
1047 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_SHM);
1048 		/* WIN 1 & 2 mapping to IO space */
1049 		host_c2h_write_io_cfg_reg(0xF1,
1050 				host_c2h_read_io_cfg_reg(0xF1) | 0x30);
1051 		/* WIN1 as Host Command on the IO address (default: 0x0800) */
1052 #if defined(CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM)
1053 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_SHM_WND1_ADDR_1,
1054 		(CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM >> 8) & 0xff);
1055 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_SHM_WND1_ADDR_0,
1056 		CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM & 0xff);
1057 #endif
1058 		/* Set WIN2 as MEMMAP on the configured IO address */
1059 #if defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM)
1060 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_SHM_WND2_ADDR_1,
1061 		(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM >> 8) & 0xff);
1062 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_SHM_WND2_ADDR_0,
1063 		CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM & 0xff);
1064 #endif
1065 		if (IS_ENABLED(CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE)) {
1066 			host_c2h_write_io_cfg_reg(EC_CFG_IDX_SHM_DP80_ADDR_RANGE, 0x0f);
1067 		}
1068 	/* Enable SHM direct memory access */
1069 	host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE);
1070 	}
1071 
1072 	if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_UART)) {
1073 		/* Select Serial Port banks which LDN are 0x03. */
1074 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_SP);
1075 		/* Enable SIO_CLK */
1076 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_SUPERIO_SIOCF9,
1077 					  host_c2h_read_io_cfg_reg(EC_CFG_IDX_SUPERIO_SIOCF9) |
1078 						  BIT(EC_CFG_IDX_SUPERIO_SIOCF9_CKEN));
1079 		/* Enable Bank Select */
1080 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_SP_CFG,
1081 					  host_c2h_read_io_cfg_reg(EC_CFG_IDX_SP_CFG) |
1082 						  BIT(EC_CFG_IDX_SP_CFG_BK_SL_ENABLE));
1083 		host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE);
1084 	}
1085 
1086 	LOG_DBG("Hos sub-modules configurations are done!");
1087 }
1088 
npcx_host_enable_access_interrupt(void)1089 void npcx_host_enable_access_interrupt(void)
1090 {
1091 	npcx_miwu_irq_get_and_clear_pending(&host_sub_cfg.host_acc_wui);
1092 
1093 	npcx_miwu_irq_enable(&host_sub_cfg.host_acc_wui);
1094 }
1095 
npcx_host_disable_access_interrupt(void)1096 void npcx_host_disable_access_interrupt(void)
1097 {
1098 	npcx_miwu_irq_disable(&host_sub_cfg.host_acc_wui);
1099 }
1100 
npcx_host_init_subs_core_domain(const struct device * host_bus_dev,sys_slist_t * callbacks)1101 int npcx_host_init_subs_core_domain(const struct device *host_bus_dev,
1102 							sys_slist_t *callbacks)
1103 {
1104 	struct mswc_reg *const inst_mswc = host_sub_cfg.inst_mswc;
1105 	struct shm_reg *const inst_shm = host_sub_cfg.inst_shm;
1106 	const struct device *const clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE);
1107 	int i;
1108 	uint8_t shm_sts;
1109 
1110 	host_sub_data.callbacks = callbacks;
1111 	host_sub_data.host_bus_dev = host_bus_dev;
1112 
1113 	/* Turn on all host necessary sub-module clocks first */
1114 	for (i = 0; i < host_sub_cfg.clks_size; i++) {
1115 		int ret;
1116 
1117 		if (!device_is_ready(clk_dev)) {
1118 			return -ENODEV;
1119 		}
1120 
1121 		ret = clock_control_on(clk_dev, (clock_control_subsys_t)
1122 				&host_sub_cfg.clks_list[i]);
1123 		if (ret < 0) {
1124 			return ret;
1125 		}
1126 	}
1127 
1128 	/* Configure EC legacy configuration IO base address to 0x4E. */
1129 	if (!IS_BIT_SET(inst_mswc->MSWCTL1, NPCX_MSWCTL1_VHCFGA)) {
1130 		inst_mswc->HCBAL = NPCX_EC_CFG_IO_ADDR;
1131 		inst_mswc->HCBAH = 0x0;
1132 	}
1133 
1134 	/*
1135 	 * Set HOSTWAIT bit and avoid the other settings, then host can freely
1136 	 * communicate with slave (EC).
1137 	 */
1138 	inst_shm->SMC_CTL &= BIT(NPCX_SMC_CTL_HOSTWAIT);
1139 	/* Clear shared memory status */
1140 	shm_sts = inst_shm->SMC_STS;
1141 	inst_shm->SMC_STS = shm_sts;
1142 
1143 	/* host sub-module initialization in core domain */
1144 #if defined(CONFIG_ESPI_PERIPHERAL_8042_KBC)
1145 	host_kbc_init();
1146 #endif
1147 #if defined(CONFIG_ESPI_PERIPHERAL_HOST_IO)
1148 	host_acpi_init();
1149 #endif
1150 #if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)
1151 	host_hcmd_init();
1152 #endif
1153 #if defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
1154 	host_shared_mem_region_init();
1155 #endif
1156 #if defined(CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80)
1157 	host_port80_init();
1158 #if defined(CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE)
1159 	ring_buf_init(&host_sub_data.port80_ring_buf, sizeof(host_sub_data.port80_data),
1160 		      host_sub_data.port80_data);
1161 	k_work_init(&host_sub_data.work, host_port80_work_handler);
1162 #endif
1163 #endif
1164 #if defined(CONFIG_ESPI_PERIPHERAL_UART)
1165 	host_uart_init();
1166 #endif
1167 
1168 	/* Host KBC sub-device interrupt installation */
1169 #if defined(CONFIG_ESPI_PERIPHERAL_8042_KBC)
1170 	IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, kbc_ibf, irq),
1171 		    DT_INST_IRQ_BY_NAME(0, kbc_ibf, priority),
1172 		    host_kbc_ibf_isr,
1173 		    NULL, 0);
1174 
1175 	IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, kbc_obe, irq),
1176 		    DT_INST_IRQ_BY_NAME(0, kbc_obe, priority),
1177 		    host_kbc_obe_isr,
1178 		    NULL, 0);
1179 #endif
1180 
1181 	/* Host PM channel (Host IO) sub-device interrupt installation */
1182 #if defined(CONFIG_ESPI_PERIPHERAL_HOST_IO) || \
1183 				defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)
1184 	IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, pmch_ibf, irq),
1185 		    DT_INST_IRQ_BY_NAME(0, pmch_ibf, priority),
1186 		    host_pmch_ibf_isr,
1187 		    NULL, 0);
1188 #endif
1189 
1190 	/* Host Port80 sub-device interrupt installation */
1191 #if defined(CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80)
1192 	IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, p80_fifo, irq),
1193 		    DT_INST_IRQ_BY_NAME(0, p80_fifo, priority),
1194 		    host_port80_isr,
1195 		    NULL, 0);
1196 #endif
1197 
1198 	if (IS_ENABLED(CONFIG_PM)) {
1199 		/*
1200 		 * Configure the host access wake-up event triggered from a host
1201 		 * transaction on eSPI/LPC bus. Do not enable it here. Or plenty
1202 		 * of interrupts will jam the system in S0.
1203 		 */
1204 		npcx_miwu_interrupt_configure(&host_sub_cfg.host_acc_wui,
1205 				NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_HIGH);
1206 	}
1207 
1208 	return 0;
1209 }
1210