Lines Matching +full:host +full:- +full:io

4  * SPDX-License-Identifier: Apache-2.0
11 * @brief Nuvoton NPCX host sub modules driver
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.
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 * | +------------+ |
34 * |<--->| to Host |<--->|
36 * | +------------+ |
38 * (Host Modules Internal Bus) +------------
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
45 * help handling any events from host side.
48 * --------|--------------------------------------------------+ Bank Select
49 * 07h | Logical Device Number Register (LDN) |---------+
50 * --------|--------------------------------------------------- |
51 * 20-2Fh | SuperI/O Configuration Registers | |
52 * ------------------------------------------------------------ |
53 * --------|---------------------------------------------------_ |
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 * |---------------------------------------------------
69 * This driver introduces six host sub-modules. It includes:
72 * ● Intel 8051SL-compatible Host interface
90 * This module allows sharing of the on-chip RAM by both Core and the Host.
92 * ● Four Core/Host communication windows for direct RAM access
94 * ● Host IRQ and SMI generation
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
103 * 5. Mobile System Wake-Up functions (MSWC).
104 * It detects and handles wake-up events from various sources in the Host
133 /* host module instances */
143 /* mapping table between host access signals and wake-up input */
187 /* IO base address of EC Logical Device Configuration */
190 /* Timeout to wait for Core-to-Host transaction to be completed. */
228 /* Index of Special Logical Device Configuration (Serial Port/Host UART) */
233 /* Host sub-device local inline functions */
247 * If window size is not a power-of-two, it is rounded-up to the next in host_shd_mem_wnd_size_sl()
248 * power-of-two value, and return value corresponds to RWINx_SIZE field. in host_shd_mem_wnd_size_sl()
250 return (32 - __builtin_clz(size - 1U)) & 0xff; in host_shd_mem_wnd_size_sl()
253 /* Host KBC sub-device local functions */
266 kbc_evt->evt = HOST_KBC_EVT_IBF; in host_kbc_ibf_isr()
268 kbc_evt->data = inst_kbc->HIKMDI; in host_kbc_ibf_isr()
270 * Indicates if the host sent a command or data. in host_kbc_ibf_isr()
274 kbc_evt->type = IS_BIT_SET(inst_kbc->HIKMST, NPCX_HIKMST_A2); in host_kbc_ibf_isr()
292 inst_kbc->HICTRL &= ~BIT(NPCX_HICTRL_OBECIE); in host_kbc_obe_isr()
294 LOG_DBG("%s: kbc status 0x%02x", __func__, inst_kbc->HIKMST); in host_kbc_obe_isr()
297 * Notify application that host already read out data. The application in host_kbc_obe_isr()
301 kbc_evt->evt = HOST_KBC_EVT_OBE; in host_kbc_obe_isr()
302 kbc_evt->data = 0; in host_kbc_obe_isr()
303 kbc_evt->type = 0; in host_kbc_obe_isr()
316 inst_kbc->HICTRL |= BIT(NPCX_HICTRL_FW_OBF); in host_kbc_init()
326 inst_kbc->HICTRL = BIT(NPCX_HICTRL_IBFCIE) | BIT(NPCX_HICTRL_OBFMIE) in host_kbc_init()
330 inst_kbc->HIIRQC = 0x00; in host_kbc_init()
334 /* Host ACPI sub-device local functions */
350 * Indicates if the host sent a command or data. in host_acpi_process_input_data()
354 acpi_evt->type = IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_CMD); in host_acpi_process_input_data()
355 acpi_evt->data = data; in host_acpi_process_input_data()
366 inst_acpi->HIPMCTL &= ~BIT(NPCX_HIPMCTL_SCIPOL); in host_acpi_init()
367 inst_acpi->HIPMIC &= ~BIT(NPCX_HIPMIC_SMIPOL); in host_acpi_init()
370 inst_acpi->HIPMIC |= BIT(NPCX_HIPMIC_SMIB) | BIT(NPCX_HIPMIC_SCIB); in host_acpi_init()
376 inst_acpi->HIPMIE |= BIT(NPCX_HIPMIE_SCIE); in host_acpi_init()
377 inst_acpi->HIPMIE |= BIT(NPCX_HIPMIE_SMIE); in host_acpi_init()
380 * Init ACPI PM channel (Host IO) with: in host_acpi_init()
381 * 1. Enable Input-Buffer Full (IBF) core interrupt. in host_acpi_init()
384 inst_acpi->HIPMCTL |= BIT(7) | BIT(NPCX_HIPMCTL_IBFIE); in host_acpi_init()
389 /* Host command argument and memory map buffers */
392 /* Host command sub-device local functions */
400 LOG_DBG("%s: host cmd data 0x%02x", __func__, evt.evt_data); in host_hcmd_process_input_data()
412 inst_shm->SHM_CTL &= ~0x40; in host_hcmd_init()
414 inst_shm->WIN1_WR_PROT = 0; in host_hcmd_init()
415 inst_shm->WIN1_RD_PROT = 0; in host_hcmd_init()
417 /* Configure Win1 size for ec host command. */ in host_hcmd_init()
418 SET_FIELD(inst_shm->WIN_SIZE, NPCX_WIN_SIZE_RWIN1_SIZE_FIELD, in host_hcmd_init()
420 inst_shm->WIN_BASE1 = (uint32_t)shm_host_cmd; in host_hcmd_init()
423 * Clear processing flag before enabling host's interrupts in case in host_hcmd_init()
426 inst_hcmd->HIPMST &= ~BIT(NPCX_HIPMST_F0); in host_hcmd_init()
429 * Init Host Command PM channel (Host IO) with: in host_hcmd_init()
430 * 1. Enable Input-Buffer Full (IBF) core interrupt. in host_hcmd_init()
433 inst_hcmd->HIPMCTL |= BIT(7) | BIT(NPCX_HIPMCTL_IBFIE); in host_hcmd_init()
438 /* Host command argument and memory map buffers */
447 inst_shm->SHM_CTL &= ~0x40; in host_shared_mem_region_init()
449 inst_shm->WIN2_WR_PROT = 0; in host_shared_mem_region_init()
450 inst_shm->WIN2_RD_PROT = 0; in host_shared_mem_region_init()
453 SET_FIELD(inst_shm->WIN_SIZE, NPCX_WIN_SIZE_RWIN2_SIZE_FIELD, in host_shared_mem_region_init()
455 inst_shm->WIN_BASE2 = (uint32_t)shm_acpi_mmap; in host_shared_mem_region_init()
457 inst_shm->WIN2_WR_PROT = 0xFF; in host_shared_mem_region_init()
460 * TODO: Initialize shm_acpi_mmap buffer for host command flags. We in host_shared_mem_region_init()
462 * instead of setting host command flags here directly. in host_shared_mem_region_init()
469 /* Host pm (host io) sub-module isr function for all channels such as ACPI. */
477 /* Host put data on input buffer of ACPI channel */ in host_pmch_ibf_isr()
478 if (IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_IBF)) { in host_pmch_ibf_isr()
480 inst_acpi->HIPMST |= BIT(NPCX_HIPMST_F0); in host_pmch_ibf_isr()
482 in_data = inst_acpi->HIPMDI; in host_pmch_ibf_isr()
488 /* Host put data on input buffer of HOSTCMD channel */ in host_pmch_ibf_isr()
489 if (IS_BIT_SET(inst_hcmd->HIPMST, NPCX_HIPMST_IBF)) { in host_pmch_ibf_isr()
491 inst_hcmd->HIPMST |= BIT(NPCX_HIPMST_F0); in host_pmch_ibf_isr()
493 in_data = inst_hcmd->HIPMDI; in host_pmch_ibf_isr()
501 /* Host port80 sub-device local functions */
508 struct ring_buf *rbuf = &data->port80_ring_buf; in host_port80_work_handler()
547 uint8_t status = inst_shm->DP80STS; in host_port80_isr()
552 while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) { in host_port80_isr()
555 dp80_buf.offset_code_16 = inst_shm->DP80BUF; in host_port80_isr()
565 while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) { in host_port80_isr()
566 LOG_DBG("p80: %04x", inst_shm->DP80BUF); in host_port80_isr()
567 evt.evt_data = inst_shm->DP80BUF; in host_port80_isr()
575 inst_shm->DP80STS |= BIT(NPCX_DP80STS_FOR); in host_port80_isr()
583 if (!IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) { in host_port80_isr()
584 /* Clear all pending bit indicates that FIFO was written by host */ in host_port80_isr()
585 inst_shm->DP80STS |= BIT(NPCX_DP80STS_FWR); in host_port80_isr()
595 * Enables a Core interrupt on every Host write to the FIFO, in host_port80_init()
599 inst_shm->DP80CTL = BIT(NPCX_DP80CTL_CIEN) | BIT(NPCX_DP80CTL_RAA) in host_port80_init()
607 /* Enable host KBC sub-device interrupt */ in host_cus_opcode_enable_interrupts()
613 /* Enable host PM channel (Host IO) sub-device interrupt */ in host_cus_opcode_enable_interrupts()
619 /* Enable host Port80 sub-device interrupt installation */ in host_cus_opcode_enable_interrupts()
624 /* Enable host interface interrupts if its interface is eSPI */ in host_cus_opcode_enable_interrupts()
632 /* Disable host KBC sub-device interrupt */ in host_cus_opcode_disable_interrupts()
638 /* Disable host PM channel (Host IO) sub-device interrupt */ in host_cus_opcode_disable_interrupts()
644 /* Disable host Port80 sub-device interrupt installation */ in host_cus_opcode_disable_interrupts()
649 /* Disable host interface interrupts if its interface is eSPI */ in host_cus_opcode_disable_interrupts()
657 /* host uart pinmux configuration */
663 /* Host UART sub-device local functions */
668 /* Configure pin-mux for serial port device */ in host_uart_init()
671 /* Make sure unlock host access of serial port */ in host_uart_init()
672 inst_c2h->LKSIOHA &= ~BIT(NPCX_LKSIOHA_LKSPHA); in host_uart_init()
673 /* Clear 'Host lock violation occurred' bit of serial port initially */ in host_uart_init()
674 inst_c2h->SIOLV |= BIT(NPCX_SIOLV_SPLV); in host_uart_init()
678 /* host core-to-host interface local functions */
687 while (IS_BIT_SET(inst_c2h->SIBCTRL, NPCX_SIBCTRL_CSWR)) { in host_c2h_wait_write_done()
688 elapsed_cycles = k_cycle_get_32() - start_cycles; in host_c2h_wait_write_done()
704 while (IS_BIT_SET(inst_c2h->SIBCTRL, NPCX_SIBCTRL_CSRD)) { in host_c2h_wait_read_done()
705 elapsed_cycles = k_cycle_get_32() - start_cycles; in host_c2h_wait_read_done()
720 /* Lock host access EC configuration registers (0x4E/0x4F) */ in host_c2h_write_io_cfg_reg()
721 inst_c2h->LKSIOHA |= BIT(NPCX_LKSIOHA_LKCFG); in host_c2h_write_io_cfg_reg()
722 /* Enable Core-to-Host access CFG module */ in host_c2h_write_io_cfg_reg()
723 inst_c2h->CRSMAE |= BIT(NPCX_CRSMAE_CFGAE); in host_c2h_write_io_cfg_reg()
725 /* Verify core-to-host modules is not in progress */ in host_c2h_write_io_cfg_reg()
730 * Specifying the in-direct IO address which A0 = 0 indicates the index in host_c2h_write_io_cfg_reg()
732 * a write transaction to host sub-module on LPC/eSPI bus. in host_c2h_write_io_cfg_reg()
734 inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR; in host_c2h_write_io_cfg_reg()
735 inst_c2h->IHD = reg_index; in host_c2h_write_io_cfg_reg()
739 * Specifying the in-direct IO address which A0 = 1 indicates the data in host_c2h_write_io_cfg_reg()
741 * transaction to host sub-module on LPC/eSPI bus. in host_c2h_write_io_cfg_reg()
743 inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR + 1; in host_c2h_write_io_cfg_reg()
744 inst_c2h->IHD = reg_data; in host_c2h_write_io_cfg_reg()
747 /* Disable Core-to-Host access CFG module */ in host_c2h_write_io_cfg_reg()
748 inst_c2h->CRSMAE &= ~BIT(NPCX_CRSMAE_CFGAE); in host_c2h_write_io_cfg_reg()
749 /* Unlock host access EC configuration registers (0x4E/0x4F) */ in host_c2h_write_io_cfg_reg()
750 inst_c2h->LKSIOHA &= ~BIT(NPCX_LKSIOHA_LKCFG); in host_c2h_write_io_cfg_reg()
764 /* Lock host access EC configuration registers (0x4E/0x4F) */ in host_c2h_read_io_cfg_reg()
765 inst_c2h->LKSIOHA |= BIT(NPCX_LKSIOHA_LKCFG); in host_c2h_read_io_cfg_reg()
766 /* Enable Core-to-Host access CFG module */ in host_c2h_read_io_cfg_reg()
767 inst_c2h->CRSMAE |= BIT(NPCX_CRSMAE_CFGAE); in host_c2h_read_io_cfg_reg()
769 /* Verify core-to-host modules is not in progress */ in host_c2h_read_io_cfg_reg()
774 * Specifying the in-direct IO address which A0 = 0 indicates the index in host_c2h_read_io_cfg_reg()
776 * a write transaction to host sub-module on LPC/eSPI bus. in host_c2h_read_io_cfg_reg()
778 inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR; in host_c2h_read_io_cfg_reg()
779 inst_c2h->IHD = reg_index; in host_c2h_read_io_cfg_reg()
783 * Specifying the in-direct IO address which A0 = 1 indicates the data in host_c2h_read_io_cfg_reg()
785 * transaction to host sub-module on LPC/eSPI bus. Once it was done, in host_c2h_read_io_cfg_reg()
788 inst_c2h->IHIOA = NPCX_EC_CFG_IO_ADDR + 1; in host_c2h_read_io_cfg_reg()
789 inst_c2h->SIBCTRL |= BIT(NPCX_SIBCTRL_CSRD); in host_c2h_read_io_cfg_reg()
791 data_val = inst_c2h->IHD; in host_c2h_read_io_cfg_reg()
793 /* Disable Core-to-Host access CFG module */ in host_c2h_read_io_cfg_reg()
794 inst_c2h->CRSMAE &= ~BIT(NPCX_CRSMAE_CFGAE); in host_c2h_read_io_cfg_reg()
795 /* Unlock host access EC configuration registers (0x4E/0x4F) */ in host_c2h_read_io_cfg_reg()
796 inst_c2h->LKSIOHA &= ~BIT(NPCX_LKSIOHA_LKCFG); in host_c2h_read_io_cfg_reg()
804 /* Platform specific host sub modules functions */
812 if (!IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFKIE) || in npcx_host_periph_read_request()
813 !IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFMIE)) { in npcx_host_periph_read_request()
814 return -ENOTSUP; in npcx_host_periph_read_request()
819 /* EC has written data back to host. OBF is in npcx_host_periph_read_request()
820 * automatically cleared after host reads in npcx_host_periph_read_request()
823 *data = IS_BIT_SET(inst_kbc->HIKMST, NPCX_HIKMST_OBF); in npcx_host_periph_read_request()
826 *data = IS_BIT_SET(inst_kbc->HIKMST, NPCX_HIKMST_IBF); in npcx_host_periph_read_request()
829 *data = inst_kbc->HIKMST; in npcx_host_periph_read_request()
832 return -EINVAL; in npcx_host_periph_read_request()
838 if (!IS_BIT_SET(inst_acpi->HIPMCTL, NPCX_HIPMCTL_IBFIE)) { in npcx_host_periph_read_request()
839 return -ENOTSUP; in npcx_host_periph_read_request()
844 /* EC has written data back to host. OBF is in npcx_host_periph_read_request()
845 * automatically cleared after host reads in npcx_host_periph_read_request()
848 *data = IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_OBF); in npcx_host_periph_read_request()
851 *data = IS_BIT_SET(inst_acpi->HIPMST, NPCX_HIPMST_IBF); in npcx_host_periph_read_request()
854 *data = inst_acpi->HIPMST; in npcx_host_periph_read_request()
862 return -EINVAL; in npcx_host_periph_read_request()
876 return -EINVAL; in npcx_host_periph_read_request()
881 return -ENOTSUP; in npcx_host_periph_read_request()
895 if (!IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFKIE) || in npcx_host_periph_write_request()
896 !IS_BIT_SET(inst_kbc->HICTRL, NPCX_HICTRL_OBFMIE)) { in npcx_host_periph_write_request()
897 return -ENOTSUP; in npcx_host_periph_write_request()
907 inst_kbc->HIKDO = *data & 0xff; in npcx_host_periph_write_request()
912 inst_kbc->HICTRL |= BIT(NPCX_HICTRL_OBECIE); in npcx_host_periph_write_request()
915 inst_kbc->HIMDO = *data & 0xff; in npcx_host_periph_write_request()
920 inst_kbc->HICTRL |= BIT(NPCX_HICTRL_OBECIE); in npcx_host_periph_write_request()
924 inst_kbc->HICTRL |= BIT(NPCX_HICTRL_IBFCIE); in npcx_host_periph_write_request()
928 inst_kbc->HICTRL &= ~BIT(NPCX_HICTRL_IBFCIE); in npcx_host_periph_write_request()
932 inst_kbc->HICTRL |= BIT(NPCX_HICTRL_FW_OBF); in npcx_host_periph_write_request()
936 inst_kbc->HIKMST |= *data & ~NPCX_KBC_STS_MASK; in npcx_host_periph_write_request()
940 inst_kbc->HIKMST &= ~(*data | NPCX_KBC_STS_MASK); in npcx_host_periph_write_request()
943 return -EINVAL; in npcx_host_periph_write_request()
949 if (!IS_BIT_SET(inst_acpi->HIPMCTL, NPCX_HIPMCTL_IBFIE)) { in npcx_host_periph_write_request()
950 return -ENOTSUP; in npcx_host_periph_write_request()
955 inst_acpi->HIPMDO = (*data & 0xff); in npcx_host_periph_write_request()
958 inst_acpi->HIPMST = (*data & 0xff); in npcx_host_periph_write_request()
961 return -EINVAL; in npcx_host_periph_write_request()
982 inst_hcmd->HIPMDO = (*data & 0xff); in npcx_host_periph_write_request()
984 inst_hcmd->HIPMST &= ~BIT(NPCX_HIPMST_F0); in npcx_host_periph_write_request()
987 return -EINVAL; in npcx_host_periph_write_request()
992 return -ENOTSUP; in npcx_host_periph_write_request()
1002 /* Enable Core-to-Host access module */ in npcx_host_init_subs_host_domain()
1003 inst_c2h->SIBCTRL |= BIT(NPCX_SIBCTRL_CSAE); in npcx_host_init_subs_host_domain()
1028 /* Select 'Host Command' bank which LDN are 0x12 (PM chan 2) */ in npcx_host_init_subs_host_domain()
1031 /* Configure IO address of CMD portt (default: 0x200) */ in npcx_host_init_subs_host_domain()
1036 /* Configure IO address of Data portt (default: 0x204) */ in npcx_host_init_subs_host_domain()
1043 /* Enable 'Host Command' io port (PM Channel 2) */ in npcx_host_init_subs_host_domain()
1048 /* WIN 1 & 2 mapping to IO space */ in npcx_host_init_subs_host_domain()
1051 /* WIN1 as Host Command on the IO address (default: 0x0800) */ in npcx_host_init_subs_host_domain()
1058 /* Set WIN2 as MEMMAP on the configured IO address */ in npcx_host_init_subs_host_domain()
1086 LOG_DBG("Hos sub-modules configurations are done!"); in npcx_host_init_subs_host_domain()
1113 /* Turn on all host necessary sub-module clocks first */ in npcx_host_init_subs_core_domain()
1118 return -ENODEV; in npcx_host_init_subs_core_domain()
1128 /* Configure EC legacy configuration IO base address to 0x4E. */ in npcx_host_init_subs_core_domain()
1129 if (!IS_BIT_SET(inst_mswc->MSWCTL1, NPCX_MSWCTL1_VHCFGA)) { in npcx_host_init_subs_core_domain()
1130 inst_mswc->HCBAL = NPCX_EC_CFG_IO_ADDR; in npcx_host_init_subs_core_domain()
1131 inst_mswc->HCBAH = 0x0; in npcx_host_init_subs_core_domain()
1135 * Set HOSTWAIT bit and avoid the other settings, then host can freely in npcx_host_init_subs_core_domain()
1138 inst_shm->SMC_CTL &= BIT(NPCX_SMC_CTL_HOSTWAIT); in npcx_host_init_subs_core_domain()
1140 shm_sts = inst_shm->SMC_STS; in npcx_host_init_subs_core_domain()
1141 inst_shm->SMC_STS = shm_sts; in npcx_host_init_subs_core_domain()
1143 /* host sub-module initialization in core domain */ in npcx_host_init_subs_core_domain()
1168 /* Host KBC sub-device interrupt installation */ in npcx_host_init_subs_core_domain()
1181 /* Host PM channel (Host IO) sub-device interrupt installation */ in npcx_host_init_subs_core_domain()
1190 /* Host Port80 sub-device interrupt installation */ in npcx_host_init_subs_core_domain()
1200 * Configure the host access wake-up event triggered from a host in npcx_host_init_subs_core_domain()