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