From 17f3792abfdc7c7e207f5cbdbcd90ae30259f47d Mon Sep 17 00:00:00 2001 From: Glauber Maroto Ferreira Date: Wed, 11 Aug 2021 13:56:53 -0300 Subject: [PATCH] esp32: drivers: pinmux: code refactoring to make use of Espressif's hal in order to ease both driver maintenance and code reuse between socs. Signed-off-by: Glauber Maroto Ferreira --- CODEOWNERS | 1 + drivers/pinmux/pinmux_esp32.c | 140 ++++++---------------------------- 2 files changed, 25 insertions(+), 116 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index b032ff60b19..51929a4a777 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -280,6 +280,7 @@ /drivers/pinmux/*b91* @yurvyn /drivers/pinmux/*hsdk* @iriszzw /drivers/pinmux/*it8xxx2* @ite +/drivers/pinmux/*esp32* @glaubermaroto /drivers/pm_cpu_ops/ @carlocaione /drivers/ps2/ @franciscomunoz @scottwcpg /drivers/ps2/*xec* @franciscomunoz @scottwcpg diff --git a/drivers/pinmux/pinmux_esp32.c b/drivers/pinmux/pinmux_esp32.c index 08eccf2b053..d2c5bbe29c2 100644 --- a/drivers/pinmux/pinmux_esp32.c +++ b/drivers/pinmux/pinmux_esp32.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,100 +8,35 @@ #define DT_DRV_COMPAT espressif_esp32_pinmux /* Include esp-idf headers first to avoid redefining BIT() macro */ -#include -#include #include +#include +#include #include -#include #include -/* DR_REG_IO_MUX_BASE is a 32-bit constant. Define a pin mux table - * using only offsets, in order to reduce ROM footprint. - * This table has been compiled from information present in "ESP32 - * Technical Reference Manual", "IO_MUX Pad List". The items in - * this array covers only the first function of each I/O pin. - * Items with offset `0` are not present in the documentation, and - * trying to configure them will result in -EINVAL being returned. - * - * Note: DR_REG_IO_MUX_BASE here is used to extract GPIO_X register offset. - * Don't replace it by device tree value, because PERIPHS_IO_MUX_ - * is "internally" depends on it. - */ -#define PIN(id) ((PERIPHS_IO_MUX_ ## id ## _U) - (DR_REG_IO_MUX_BASE)) -static const uint8_t pin_mux_off[] = { - PIN(GPIO0), PIN(U0TXD), PIN(GPIO2), PIN(U0RXD), - PIN(GPIO4), PIN(GPIO5), PIN(SD_CLK), PIN(SD_DATA0), - PIN(SD_DATA1), PIN(SD_DATA2), PIN(SD_DATA3), PIN(SD_CMD), - PIN(MTDI), PIN(MTCK), PIN(MTMS), PIN(MTDO), - PIN(GPIO16), PIN(GPIO17), PIN(GPIO18), PIN(GPIO19), - 0, PIN(GPIO21), PIN(GPIO22), PIN(GPIO23), - 0, PIN(GPIO25), PIN(GPIO26), PIN(GPIO27), - 0, 0, 0, 0, - PIN(GPIO32), PIN(GPIO33), PIN(GPIO34), PIN(GPIO35), - PIN(GPIO36), PIN(GPIO37), PIN(GPIO38), PIN(GPIO39) -}; -#undef PIN - -static uint32_t *reg_for_pin(uint32_t pin) -{ - uint8_t off; - - if (pin >= ARRAY_SIZE(pin_mux_off)) { - return NULL; - } - - off = pin_mux_off[pin]; - if (!off) { - return NULL; - } - - return (uint32_t *)(DT_INST_REG_ADDR(0) + off); -} - -static int set_reg(uint32_t pin, uint32_t clr_mask, uint32_t set_mask) -{ - volatile uint32_t *reg = reg_for_pin(pin); - uint32_t v; - - if (!reg) { - return -EINVAL; - } - - v = *reg; - v &= ~clr_mask; - v |= set_mask; - *reg = v; - - return 0; -} - static int pinmux_set(const struct device *dev, uint32_t pin, uint32_t func) { ARG_UNUSED(dev); - /* FIXME: Drive strength (FUN_DRV) is also set here to its maximum - * value due to a deficiency in the pinmux API. This setting is - * part of the GPIO API. - */ - - if (func > 6) { + if ((func > PINMUX_FUNC_G) || (pin >= GPIO_NUM_MAX)) { return -EINVAL; } - return set_reg(pin, MCU_SEL_M, func<= GPIO_NUM_MAX) { return -EINVAL; } - *func = (*reg & MCU_SEL_M) >> MCU_SEL_S; + *func = REG_GET_FIELD(GPIO_PIN_MUX_REG[pin], MCU_SEL); return 0; } @@ -111,54 +47,35 @@ static int pinmux_pullup(const struct device *dev, uint32_t pin, uint8_t func) switch (func) { case PINMUX_PULLUP_DISABLE: - return set_reg(pin, FUN_PU, FUN_PD); + gpio_ll_pullup_dis(&GPIO, pin); + break; case PINMUX_PULLUP_ENABLE: - return set_reg(pin, FUN_PD, FUN_PU); + gpio_ll_pullup_en(&GPIO, pin); + break; + default: + return -EINVAL; } - return -EINVAL; + return 0; } -#define CFG(id) ((GPIO_ ## id ## _REG) & 0xff) static int pinmux_input(const struct device *dev, uint32_t pin, uint8_t func) { ARG_UNUSED(dev); - static const uint8_t offs[2][3] = { - { CFG(ENABLE1_W1TC), CFG(ENABLE1_W1TS), 32 }, - { CFG(ENABLE_W1TC), CFG(ENABLE_W1TS), 0 }, - }; - const uint8_t *line = offs[pin < 32]; - volatile uint32_t *reg; - int r; - - /* Since PINMUX_INPUT_ENABLED == 1 and PINMUX_OUTPUT_ENABLED == 0, - * we can not set a gpio port as input and output at the same time, - * So we always set the gpio as input. Thus, the gpio can be used on - * I2C drivers for example. - */ - r = set_reg(pin, 0, FUN_IE); - if (func == PINMUX_INPUT_ENABLED) { - reg = (uint32_t *)(DR_REG_GPIO_BASE + line[0]); - } else if (func == PINMUX_OUTPUT_ENABLED) { - if (pin >= 34U && pin <= 39U) { - /* These pins are input only */ - return -EINVAL; - } - reg = (uint32_t *)(DR_REG_GPIO_BASE + line[1]); - } else { + switch (func) { + case PINMUX_INPUT_ENABLED: + gpio_ll_input_enable(&GPIO, pin); + break; + case PINMUX_OUTPUT_ENABLED: + gpio_ll_output_enable(&GPIO, pin); + break; + default: return -EINVAL; } - if (r < 0) { - return r; - } - - *reg = BIT(pin - line[2]); - return 0; } -#undef CFG static struct pinmux_driver_api api_funcs = { .set = pinmux_set, @@ -171,15 +88,6 @@ static int pinmux_initialize(const struct device *dev) { ARG_UNUSED(dev); -#if !CONFIG_BOOTLOADER_ESP_IDF - uint32_t pin; - - for (pin = 0U; pin < ARRAY_SIZE(pin_mux_off); pin++) { - pinmux_set(NULL, pin, 0); - } - -#endif - return 0; }