1 /*
2  * Copyright (c) 2020 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/init.h>
8 #include <zephyr/drivers/gpio.h>
9 #include <zephyr/dt-bindings/pinctrl/npcx-pinctrl.h>
10 #include <zephyr/kernel.h>
11 #include <soc.h>
12 
13 #include "soc_gpio.h"
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(pimux_npcx, LOG_LEVEL_ERR);
17 
18 /* Driver config */
19 struct npcx_scfg_config {
20 	/* scfg device base address */
21 	uintptr_t base_scfg;
22 	uintptr_t base_dbg;
23 	uintptr_t base_glue;
24 };
25 
26 /*
27  * Get io list which default functionality are not IOs. Then switch them to
28  * GPIO in pin-mux init function.
29  *
30  * def-io-conf-list {
31  *               pinmux = <&alt0_gpio_no_spip
32  *                         &alt0_gpio_no_fpip
33  *                         ...>;
34  *               };
35  */
36 #define NPCX_NO_GPIO_ALT_ITEM(node_id, prop, idx) {				\
37 	  .group = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), alts, group),	\
38 	  .bit = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), alts, bit),		\
39 	  .inverted = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), alts, inv),	\
40 	},
41 
42 static const struct npcx_alt def_alts[] = {
43 	DT_FOREACH_PROP_ELEM(DT_INST(0, nuvoton_npcx_pinctrl_def), pinmux,
44 				NPCX_NO_GPIO_ALT_ITEM)
45 };
46 
47 static const struct npcx_scfg_config npcx_scfg_cfg = {
48 	.base_scfg = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), scfg),
49 	.base_dbg = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), dbg),
50 	.base_glue = DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), glue),
51 };
52 
53 /* Driver convenience defines */
54 #define HAL_SFCG_INST() (struct scfg_reg *)(npcx_scfg_cfg.base_scfg)
55 
56 #define HAL_GLUE_INST() (struct glue_reg *)(npcx_scfg_cfg.base_glue)
57 
58 /* Pin-control local functions */
npcx_pinctrl_alt_sel(const struct npcx_alt * alt,int alt_func)59 static void npcx_pinctrl_alt_sel(const struct npcx_alt *alt, int alt_func)
60 {
61 	const uint32_t scfg_base = npcx_scfg_cfg.base_scfg;
62 	uint8_t alt_mask = BIT(alt->bit);
63 
64 	/*
65 	 * alt_fun == 0 means select GPIO, otherwise Alternate Func.
66 	 * inverted == 0:
67 	 *    Set devalt bit to select Alternate Func.
68 	 * inverted == 1:
69 	 *    Clear devalt bit to select Alternate Func.
70 	 */
71 	if (!!alt_func != !!alt->inverted) {
72 		NPCX_DEVALT(scfg_base, alt->group) |=  alt_mask;
73 	} else {
74 		NPCX_DEVALT(scfg_base, alt->group) &= ~alt_mask;
75 	}
76 }
77 
78 /* Platform specific pin-control functions */
npcx_lvol_set_detect_level(int lvol_ctrl,int lvol_bit,bool enable)79 void npcx_lvol_set_detect_level(int lvol_ctrl, int lvol_bit, bool enable)
80 {
81 	const uintptr_t scfg_base = npcx_scfg_cfg.base_scfg;
82 
83 	if (enable) {
84 		NPCX_LV_GPIO_CTL(scfg_base, lvol_ctrl) |= BIT(lvol_bit);
85 	} else {
86 		NPCX_LV_GPIO_CTL(scfg_base, lvol_ctrl) &= ~BIT(lvol_bit);
87 	}
88 }
89 
npcx_lvol_get_detect_level(int lvol_ctrl,int lvol_bit)90 bool npcx_lvol_get_detect_level(int lvol_ctrl, int lvol_bit)
91 {
92 	const uintptr_t scfg_base = npcx_scfg_cfg.base_scfg;
93 
94 	return NPCX_LV_GPIO_CTL(scfg_base, lvol_ctrl) & BIT(lvol_bit);
95 }
96 
npcx_pinctrl_i2c_port_sel(int controller,int port)97 void npcx_pinctrl_i2c_port_sel(int controller, int port)
98 {
99 	struct glue_reg *const inst_glue = HAL_GLUE_INST();
100 
101 	if (port != 0) {
102 		inst_glue->SMB_SEL |= BIT(controller);
103 	} else {
104 		inst_glue->SMB_SEL &= ~BIT(controller);
105 	}
106 }
107 
npcx_pinctrl_flash_write_protect_set(void)108 int npcx_pinctrl_flash_write_protect_set(void)
109 {
110 	struct scfg_reg *inst_scfg = HAL_SFCG_INST();
111 
112 	inst_scfg->DEV_CTL4 |= BIT(NPCX_DEV_CTL4_WP_IF);
113 	if (!IS_BIT_SET(inst_scfg->DEV_CTL4, NPCX_DEV_CTL4_WP_IF)) {
114 		return -EIO;
115 	}
116 
117 	return 0;
118 }
119 
npcx_pinctrl_flash_write_protect_is_set(void)120 bool npcx_pinctrl_flash_write_protect_is_set(void)
121 {
122 	struct scfg_reg *inst_scfg = HAL_SFCG_INST();
123 
124 	return IS_BIT_SET(inst_scfg->DEV_CTL4, NPCX_DEV_CTL4_WP_IF);
125 }
126 
npcx_host_interface_sel(enum npcx_hif_type hif_type)127 void npcx_host_interface_sel(enum npcx_hif_type hif_type)
128 {
129 	struct scfg_reg *inst_scfg = HAL_SFCG_INST();
130 
131 	SET_FIELD(inst_scfg->DEVCNT, NPCX_DEVCNT_HIF_TYP_SEL_FIELD, hif_type);
132 }
133 
npcx_dbg_freeze_enable(bool enable)134 void npcx_dbg_freeze_enable(bool enable)
135 {
136 	const uintptr_t dbg_base = npcx_scfg_cfg.base_dbg;
137 
138 	if (enable) {
139 		NPCX_DBGFRZEN3(dbg_base) &= ~BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS);
140 	} else {
141 		NPCX_DBGFRZEN3(dbg_base) |= BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS);
142 	}
143 }
144 
145 /* Pin-control driver registration */
npcx_scfg_init(void)146 static int npcx_scfg_init(void)
147 {
148 	/* Change all pads whose default functionality isn't IO to GPIO */
149 	for (int i = 0; i < ARRAY_SIZE(def_alts); i++) {
150 		npcx_pinctrl_alt_sel(&def_alts[i], 0);
151 	}
152 
153 	return 0;
154 }
155 
156 SYS_INIT(npcx_scfg_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
157