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