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 <glauber.ferreira@espressif.com>
This commit is contained in:
parent
8b13046cb6
commit
17f3792abf
@ -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
|
||||
|
||||
@ -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 <soc/gpio_reg.h>
|
||||
#include <soc/io_mux_reg.h>
|
||||
#include <soc/soc.h>
|
||||
#include <hal/gpio_types.h>
|
||||
#include <hal/gpio_ll.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/util.h>
|
||||
#include <drivers/pinmux.h>
|
||||
|
||||
/* 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<<MCU_SEL_S | 2<<FUN_DRV_S);
|
||||
gpio_ll_iomux_func_sel(GPIO_PIN_MUX_REG[pin], func);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pinmux_get(const struct device *dev, uint32_t pin, uint32_t *func)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
volatile uint32_t *reg = reg_for_pin(pin);
|
||||
|
||||
if (!reg) {
|
||||
if (pin >= 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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user