/* * Copyright (c) 2020 Nuvoton Technology Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include "soc_gpio.h" #include LOG_MODULE_REGISTER(pimux_npcx, LOG_LEVEL_ERR); /* Driver config */ struct npcx_scfg_config { /* scfg device base address */ uintptr_t base_scfg; uintptr_t base_dbg; uintptr_t base_glue; }; /* * Get io list which default functionality are not IOs. Then switch them to * GPIO in pin-mux init function. * * def-io-conf-list { * pinmux = <&alt0_gpio_no_spip * &alt0_gpio_no_fpip * ...>; * }; */ #define NPCX_NO_GPIO_ALT_ITEM(node_id, prop, idx) { \ .group = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), alts, group), \ .bit = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), alts, bit), \ .inverted = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), alts, inv), \ }, static const struct npcx_alt def_alts[] = { DT_FOREACH_PROP_ELEM(DT_INST(0, nuvoton_npcx_pinctrl_def), pinmux, NPCX_NO_GPIO_ALT_ITEM) }; static const struct npcx_scfg_config npcx_scfg_cfg = { .base_scfg = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), scfg), .base_dbg = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), dbg), .base_glue = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), glue), }; /* Driver convenience defines */ #define HAL_SFCG_INST() (struct scfg_reg *)(npcx_scfg_cfg.base_scfg) #define HAL_GLUE_INST() (struct glue_reg *)(npcx_scfg_cfg.base_glue) /* Pin-control local functions */ static void npcx_pinctrl_alt_sel(const struct npcx_alt *alt, int alt_func) { const uint32_t scfg_base = npcx_scfg_cfg.base_scfg; uint8_t alt_mask = BIT(alt->bit); /* * alt_fun == 0 means select GPIO, otherwise Alternate Func. * inverted == 0: * Set devalt bit to select Alternate Func. * inverted == 1: * Clear devalt bit to select Alternate Func. */ if (!!alt_func != !!alt->inverted) { NPCX_DEVALT(scfg_base, alt->group) |= alt_mask; } else { NPCX_DEVALT(scfg_base, alt->group) &= ~alt_mask; } } /* Platform specific pin-control functions */ void npcx_lvol_set_detect_level(int lvol_ctrl, int lvol_bit, bool enable) { const uintptr_t scfg_base = npcx_scfg_cfg.base_scfg; if (enable) { NPCX_LV_GPIO_CTL(scfg_base, lvol_ctrl) |= BIT(lvol_bit); } else { NPCX_LV_GPIO_CTL(scfg_base, lvol_ctrl) &= ~BIT(lvol_bit); } } bool npcx_lvol_get_detect_level(int lvol_ctrl, int lvol_bit) { const uintptr_t scfg_base = npcx_scfg_cfg.base_scfg; return NPCX_LV_GPIO_CTL(scfg_base, lvol_ctrl) & BIT(lvol_bit); } void npcx_pinctrl_i2c_port_sel(int controller, int port) { struct glue_reg *const inst_glue = HAL_GLUE_INST(); if (port != 0) { inst_glue->SMB_SEL |= BIT(controller); } else { inst_glue->SMB_SEL &= ~BIT(controller); } } int npcx_pinctrl_flash_write_protect_set(void) { struct scfg_reg *inst_scfg = HAL_SFCG_INST(); inst_scfg->DEV_CTL4 |= BIT(NPCX_DEV_CTL4_WP_IF); if (!IS_BIT_SET(inst_scfg->DEV_CTL4, NPCX_DEV_CTL4_WP_IF)) { return -EIO; } return 0; } bool npcx_pinctrl_flash_write_protect_is_set(void) { struct scfg_reg *inst_scfg = HAL_SFCG_INST(); return IS_BIT_SET(inst_scfg->DEV_CTL4, NPCX_DEV_CTL4_WP_IF); } void npcx_host_interface_sel(enum npcx_hif_type hif_type) { struct scfg_reg *inst_scfg = HAL_SFCG_INST(); SET_FIELD(inst_scfg->DEVCNT, NPCX_DEVCNT_HIF_TYP_SEL_FIELD, hif_type); } void npcx_dbg_freeze_enable(bool enable) { const uintptr_t dbg_base = npcx_scfg_cfg.base_dbg; if (enable) { NPCX_DBGFRZEN3(dbg_base) &= ~BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS); } else { NPCX_DBGFRZEN3(dbg_base) |= BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS); } } /* Pin-control driver registration */ static int npcx_scfg_init(void) { /* Change all pads whose default functionality isn't IO to GPIO */ for (int i = 0; i < ARRAY_SIZE(def_alts); i++) { npcx_pinctrl_alt_sel(&def_alts[i], 0); } return 0; } SYS_INIT(npcx_scfg_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);