154 lines
4.0 KiB
C
154 lines
4.0 KiB
C
/*
|
|
* Copyright (c) 2020 Nuvoton Technology Corporation.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/drivers/gpio.h>
|
|
#include <zephyr/dt-bindings/pinctrl/npcx-pinctrl.h>
|
|
#include <zephyr/kernel.h>
|
|
#include <soc.h>
|
|
|
|
#include "soc_gpio.h"
|
|
|
|
#include <zephyr/logging/log.h>
|
|
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_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_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);
|
|
}
|
|
|
|
/* Pin-control driver registration */
|
|
static int npcx_scfg_init(const struct device *dev)
|
|
{
|
|
struct scfg_reg *inst_scfg = HAL_SFCG_INST();
|
|
|
|
/*
|
|
* Set bit 7 of DEVCNT again for npcx7 series. Please see Errata
|
|
* for more information. It will be fixed in next chip.
|
|
*/
|
|
if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX7)) {
|
|
inst_scfg->DEVCNT |= BIT(7);
|
|
}
|
|
|
|
/* 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);
|