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_i2c_target_start_wk_enable(int controller,bool enable)108 void npcx_i2c_target_start_wk_enable(int controller, bool enable)
109 {
110 struct glue_reg *const inst_glue = HAL_GLUE_INST();
111
112 if (enable) {
113 /* Clear Start condition detection status */
114 inst_glue->SMB_SBD |= BIT(controller);
115 /* Enable wake up event assertion */
116 inst_glue->SMB_EEN |= BIT(controller);
117 } else {
118 /* Disable wake up event assertion */
119 inst_glue->SMB_EEN &= ~BIT(controller);
120 }
121 }
122
npcx_i2c_target_clear_detection_event(void)123 void npcx_i2c_target_clear_detection_event(void)
124 {
125 struct glue_reg *const inst_glue = HAL_GLUE_INST();
126 uint8_t een = inst_glue->SMB_EEN;
127 uint8_t sbd = inst_glue->SMB_SBD;
128
129 /* Clear Start condition detection status */
130 for (uint8_t i = 0; i < 8; i++) {
131 if ((een & BIT(i)) != 0 && (sbd & BIT(i)) != 0) {
132 inst_glue->SMB_SBD |= BIT(i);
133 }
134 }
135 }
136
npcx_pinctrl_flash_write_protect_set(void)137 int npcx_pinctrl_flash_write_protect_set(void)
138 {
139 struct scfg_reg *inst_scfg = HAL_SFCG_INST();
140
141 inst_scfg->DEV_CTL4 |= BIT(NPCX_DEV_CTL4_WP_IF);
142 if (!IS_BIT_SET(inst_scfg->DEV_CTL4, NPCX_DEV_CTL4_WP_IF)) {
143 return -EIO;
144 }
145
146 return 0;
147 }
148
npcx_pinctrl_flash_write_protect_is_set(void)149 bool npcx_pinctrl_flash_write_protect_is_set(void)
150 {
151 struct scfg_reg *inst_scfg = HAL_SFCG_INST();
152
153 return IS_BIT_SET(inst_scfg->DEV_CTL4, NPCX_DEV_CTL4_WP_IF);
154 }
155
npcx_host_interface_sel(enum npcx_hif_type hif_type)156 void npcx_host_interface_sel(enum npcx_hif_type hif_type)
157 {
158 struct scfg_reg *inst_scfg = HAL_SFCG_INST();
159
160 SET_FIELD(inst_scfg->DEVCNT, NPCX_DEVCNT_HIF_TYP_SEL_FIELD, hif_type);
161 }
162
npcx_i3c_target_sel(uint8_t module_id,bool enable)163 void npcx_i3c_target_sel(uint8_t module_id, bool enable)
164 {
165 #if defined(CONFIG_SOC_SERIES_NPCX4)
166 struct scfg_reg *inst_scfg = HAL_SFCG_INST();
167
168 if (enable == true) {
169 inst_scfg->DEV_CTL3 |= NPCX_DEV_CTL3_I3C_MODE_BIT(module_id);
170 } else {
171 inst_scfg->DEV_CTL3 &= ~NPCX_DEV_CTL3_I3C_MODE_BIT(module_id);
172 }
173 #else
174 LOG_ERR("%s: i3c target select not supported yet", __func__);
175 #endif
176 }
177
npcx_dbg_freeze_enable(bool enable)178 void npcx_dbg_freeze_enable(bool enable)
179 {
180 const uintptr_t dbg_base = npcx_scfg_cfg.base_dbg;
181
182 if (enable) {
183 NPCX_DBGFRZEN3(dbg_base) &= ~BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS);
184 } else {
185 NPCX_DBGFRZEN3(dbg_base) |= BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS);
186 }
187 }
188
189 /* Pin-control driver registration */
scfg_init(void)190 void scfg_init(void)
191 {
192 /* If booter doesn't set the host interface type */
193 if (!NPCX_BOOTER_IS_HIF_TYPE_SET()) {
194 npcx_host_interface_sel(NPCX_HIF_TYPE_ESPI_SHI);
195 }
196
197 /* Change all pads whose default functionality isn't IO to GPIO */
198 for (int i = 0; i < ARRAY_SIZE(def_alts); i++) {
199 npcx_pinctrl_alt_sel(&def_alts[i], 0);
200 }
201 }
202