ITE: drviers/pinctrl: Add pinctrl driver for IT8XXX2
Add pinctrl driver for ITE IT8XXX2. Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
This commit is contained in:
parent
4c31f24de7
commit
efaeed6cb2
12 changed files with 884 additions and 1 deletions
|
@ -6,6 +6,7 @@ zephyr_library_sources(common.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_TELINK_B91 pinctrl_b91.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AFIO pinctrl_gd32_afio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_ITE_IT8XXX2 pinctrl_ite_it8xxx2.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_NRF pinctrl_nrf.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_RCAR_PFC pfc_rcar.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_RPI_PICO pinctrl_rpi_pico.c)
|
||||
|
|
|
@ -31,6 +31,7 @@ config PINCTRL_DYNAMIC
|
|||
|
||||
source "drivers/pinctrl/Kconfig.b91"
|
||||
source "drivers/pinctrl/Kconfig.gd32"
|
||||
source "drivers/pinctrl/Kconfig.it8xxx2"
|
||||
source "drivers/pinctrl/Kconfig.nrf"
|
||||
source "drivers/pinctrl/Kconfig.rcar"
|
||||
source "drivers/pinctrl/Kconfig.rpi_pico"
|
||||
|
|
11
drivers/pinctrl/Kconfig.it8xxx2
Normal file
11
drivers/pinctrl/Kconfig.it8xxx2
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Copyright (c) 2022 ITE Corporation. All Rights Reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
DT_COMPAT_ITE_IT8XXX2_PINCTRL := ite,it8xxx2-pinctrl
|
||||
|
||||
config PINCTRL_ITE_IT8XXX2
|
||||
bool "ITE IT8XXX2 pin controller driver"
|
||||
depends on SOC_FAMILY_RISCV_ITE
|
||||
default $(dt_compat_enabled,$(DT_COMPAT_ITE_IT8XXX2_PINCTRL))
|
||||
help
|
||||
Enable IT8XXX2 pin controller driver.
|
206
drivers/pinctrl/pinctrl_ite_it8xxx2.c
Normal file
206
drivers/pinctrl/pinctrl_ite_it8xxx2.c
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Copyright (c) 2022 ITE Corporation. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT ite_it8xxx2_pinctrl_func
|
||||
|
||||
#include <drivers/pinctrl.h>
|
||||
|
||||
#include <logging/log.h>
|
||||
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)
|
Loading…
Add table
Add a link
Reference in a new issue