/* * Copyright (c) 2022 ITE Corporation. All Rights Reserved. * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT ite_it8xxx2_pinctrl_func #include #include LOG_MODULE_REGISTER(pinctrl_ite_it8xxx2, LOG_LEVEL_ERR); #define GPIO_IT8XXX2_REG_BASE \ ((struct gpio_it8xxx2_regs *)DT_REG_ADDR(DT_NODELABEL(gpiogcr))) #define GPIO_GROUP_MEMBERS 8 struct pinctrl_it8xxx2_config { /* gpio port control register (byte mapping to pin) */ uint8_t *reg_gpcr; /* function 3 general control register */ uintptr_t func3_gcr[GPIO_GROUP_MEMBERS]; /* function 3 enable mask */ uint8_t func3_en_mask[GPIO_GROUP_MEMBERS]; /* function 4 general control register */ uintptr_t func4_gcr[GPIO_GROUP_MEMBERS]; /* function 4 enable mask */ uint8_t func4_en_mask[GPIO_GROUP_MEMBERS]; /* Input voltage selection */ uintptr_t volt_sel[GPIO_GROUP_MEMBERS]; /* Input voltage selection mask */ uint8_t volt_sel_mask[GPIO_GROUP_MEMBERS]; }; static int pinctrl_it8xxx2_set(const pinctrl_soc_pin_t *pins) { const struct pinctrl_it8xxx2_config *pinctrl_config = pins->pinctrls->config; uint32_t pincfg = pins->pincfg; uint8_t pin = pins->pin; volatile uint8_t *reg_gpcr = (uint8_t *)pinctrl_config->reg_gpcr + pin; volatile uint8_t *reg_volt_sel = (uint8_t *)(pinctrl_config->volt_sel[pin]); /* Setting pull-up or pull-down. */ switch (IT8XXX2_DT_PINCFG_PUPDR(pincfg)) { case IT8XXX2_PULL_PIN_DEFAULT: /* No pull-up or pull-down */ *reg_gpcr &= ~(GPCR_PORT_PIN_MODE_PULLUP | GPCR_PORT_PIN_MODE_PULLDOWN); break; case IT8XXX2_PULL_UP: *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_PULLUP) & ~GPCR_PORT_PIN_MODE_PULLDOWN; break; case IT8XXX2_PULL_DOWN: *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_PULLDOWN) & ~GPCR_PORT_PIN_MODE_PULLUP; break; default: LOG_ERR("This pull level is not supported."); return -EINVAL; } /* Setting voltage 3.3V or 1.8V. */ switch (IT8XXX2_DT_PINCFG_VOLTAGE(pincfg)) { case IT8XXX2_VOLTAGE_3V3: /* Input voltage selection 3.3V. */ *reg_volt_sel &= ~pinctrl_config->volt_sel_mask[pin]; break; case IT8XXX2_VOLTAGE_1V8: __ASSERT(!(IT8XXX2_DT_PINCFG_PUPDR(pincfg) == IT8XXX2_PULL_UP), "Don't enable internal pullup if 1.8V voltage is used"); /* Input voltage selection 1.8V. */ *reg_volt_sel |= pinctrl_config->volt_sel_mask[pin]; break; default: LOG_ERR("The voltage selection is not supported"); return -EINVAL; } /* Setting tri-state mode. */ if (IT8XXX2_DT_PINCFG_IMPEDANCE(pincfg)) { *reg_gpcr |= (GPCR_PORT_PIN_MODE_PULLUP | GPCR_PORT_PIN_MODE_PULLDOWN); } return 0; } int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) { ARG_UNUSED(reg); const struct pinctrl_it8xxx2_config *pinctrl_config; volatile uint8_t *reg_gpcr; volatile uint8_t *reg_func3_gcr; volatile uint8_t *reg_func4_gcr; uint8_t pin; for (uint8_t i = 0U; i < pin_cnt; i++) { pinctrl_config = pins[i].pinctrls->config; pin = pins[i].pin; reg_gpcr = (uint8_t *)pinctrl_config->reg_gpcr + pin; reg_func3_gcr = (uint8_t *)(pinctrl_config->func3_gcr[pin]); reg_func4_gcr = (uint8_t *)(pinctrl_config->func4_gcr[pin]); /* Handle PIN configuration. */ if (pinctrl_it8xxx2_set(&pins[i])) { LOG_ERR("Pin configuration is invalid."); return -EINVAL; } /* * If pincfg is input, we don't need to handle * alternate function. */ if (IT8XXX2_DT_PINCFG_INPUT(pins[i].pincfg)) { *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_INPUT) & ~GPCR_PORT_PIN_MODE_OUTPUT; continue; } /* * Handle alternate function. */ /* Common settings for alternate function. */ *reg_gpcr &= ~(GPCR_PORT_PIN_MODE_INPUT | GPCR_PORT_PIN_MODE_OUTPUT); switch (pins[i].alt_func) { case IT8XXX2_ALT_FUNC_1: /* Func1: Alternate function has been set above. */ break; case IT8XXX2_ALT_FUNC_2: /* Func2: WUI function: turn the pin into an input */ *reg_gpcr |= GPCR_PORT_PIN_MODE_INPUT; break; case IT8XXX2_ALT_FUNC_3: /* * Func3: In addition to the alternate setting above, * Func3 also need to set the general control. */ *reg_func3_gcr |= pinctrl_config->func3_en_mask[pin]; break; case IT8XXX2_ALT_FUNC_4: /* * Func4: In addition to the alternate setting above, * Func4 also need to set the general control. */ *reg_func4_gcr |= pinctrl_config->func4_en_mask[pin]; break; case IT8XXX2_ALT_DEFAULT: *reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_INPUT) & ~GPCR_PORT_PIN_MODE_OUTPUT; *reg_func3_gcr &= ~pinctrl_config->func3_en_mask[pin]; *reg_func4_gcr &= ~pinctrl_config->func4_en_mask[pin]; break; default: LOG_ERR("This function is not supported."); return -EINVAL; } } return 0; } static int pinctrl_it8xxx2_init(const struct device *dev) { struct gpio_it8xxx2_regs *const gpio_base = GPIO_IT8XXX2_REG_BASE; /* * The default value of LPCRSTEN is bit2:1 = 10b(GPD2) in GCR. * If LPC reset is enabled on GPB7, we have to clear bit2:1 * to 00b. */ gpio_base->GPIO_GCR &= ~IT8XXX2_GPIO_LPCRSTEN; /* * TODO: If UART2 swaps from bit2:1 to bit6:5 in H group, we * have to set UART1PSEL = 1 in UART1PMR register. */ return 0; } #define PINCTRL_ITE_INIT(inst) \ static const struct pinctrl_it8xxx2_config pinctrl_it8xxx2_cfg_##inst = { \ .reg_gpcr = (uint8_t *)DT_INST_REG_ADDR(inst), \ .func3_gcr = DT_INST_PROP(inst, func3_gcr), \ .func3_en_mask = DT_INST_PROP(inst, func3_en_mask), \ .func4_gcr = DT_INST_PROP(inst, func4_gcr), \ .func4_en_mask = DT_INST_PROP(inst, func4_en_mask), \ .volt_sel = DT_INST_PROP(inst, volt_sel), \ .volt_sel_mask = DT_INST_PROP(inst, volt_sel_mask), \ }; \ \ DEVICE_DT_INST_DEFINE(inst, &pinctrl_it8xxx2_init, \ NULL, \ NULL, \ &pinctrl_it8xxx2_cfg_##inst, \ PRE_KERNEL_1, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ NULL); DT_INST_FOREACH_STATUS_OKAY(PINCTRL_ITE_INIT)