|
| 1 | +/* |
| 2 | + * Copyright (c) ENE Technology Inc. |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#define DT_DRV_COMPAT ene_kb106x_pinctrl |
| 8 | + |
| 9 | +#include <zephyr/devicetree.h> |
| 10 | +#include <zephyr/drivers/pinctrl.h> |
| 11 | +#include <zephyr/sys/util_macro.h> |
| 12 | +#include <zephyr/dt-bindings/pinctrl/ene-kb106x-pinctrl.h> |
| 13 | +#include <zephyr/sys/util.h> |
| 14 | +#include <reg/gcfg.h> |
| 15 | +#include <reg/gpio.h> |
| 16 | + |
| 17 | +/* |
| 18 | + * PINMUX_FUNC_A : GPIO Function |
| 19 | + * PINMUX_FUNC_B : AltOutput 1 Function |
| 20 | + * PINMUX_FUNC_C : AltOutput 2 Function |
| 21 | + * PINMUX_FUNC_D : AltOutput 3 Function |
| 22 | + * PINMUX_FUNC_E : AltOutput 4 Function |
| 23 | + * |
| 24 | + * GPIO Alternate Output Function Selection |
| 25 | + * (PINMUX_FUNC_A) (PINMUX_FUNC_B) (PINMUX_FUNC_C) (PINMUX_FUNC_D) (PINMUX_FUNC_E) |
| 26 | + * GPIO0B ESBCLK SCL5 |
| 27 | + * GPIO0C ESBDAT SDA5 |
| 28 | + * GPIO0D RLC_TX2 SDA4 |
| 29 | + * GPIO16 SER_TXD UART_SOUT SBUD_CLK |
| 30 | + * GPIO17 SER_RXD UART_SIN SBUD_DAT |
| 31 | + * GPIO19 PWM3 PWMLED0 |
| 32 | + * GPIO30 SER_TXD NKROKSI0 |
| 33 | + * GPIO48 KSO16 UART_SOUT2 |
| 34 | + * GPIO4C PSCLK2 SCL3 |
| 35 | + * GPIO4D SDAT2 SDA3 |
| 36 | + * GPIO4E PSCLK3 KSO18 |
| 37 | + * GPIO4F PSDAT3 KSO19 |
| 38 | + * GPIO4A PSCLK1 SCL2 USBDM |
| 39 | + * GPIO4B PSDAT1 SDA2 USBDP |
| 40 | + * GPIO01 ESPI_ALERT |
| 41 | + * GPIO03 ESPI_CS |
| 42 | + * GPIO07 ESPI_RST |
| 43 | + */ |
| 44 | + |
| 45 | +/* |
| 46 | + * f is function number |
| 47 | + * b[7:5] = pin bank |
| 48 | + * b[4:0] = pin position in bank |
| 49 | + * b[11:8] = function |
| 50 | + */ |
| 51 | + |
| 52 | +#define ENE_KB106X_PINMUX_PIN(p) FIELD_GET(GENMASK(4, 0), p) |
| 53 | +#define ENE_KB106X_PINMUX_PORT(p) FIELD_GET(GENMASK(7, 5), p) |
| 54 | +#define ENE_KB106X_PINMUX_FUNC(p) FIELD_GET(GENMASK(11, 8), p) |
| 55 | +#define ENE_KB106X_PINMUX_PORT_PIN(p) FIELD_GET(GENMASK(7, 0), p) |
| 56 | + |
| 57 | +static const uint32_t gcfg_reg_addr = DT_REG_ADDR_BY_NAME(DT_NODELABEL(gcfg), gcfg); |
| 58 | +static const uint32_t gpio_reg_bases[] = { |
| 59 | + DT_REG_ADDR(DT_NODELABEL(gpio0x1x)), |
| 60 | + DT_REG_ADDR(DT_NODELABEL(gpio2x3x)), |
| 61 | + DT_REG_ADDR(DT_NODELABEL(gpio4x5x)), |
| 62 | + DT_REG_ADDR(DT_NODELABEL(gpio6x7x)), |
| 63 | + DT_REG_ADDR(DT_NODELABEL(egpio0x1x)), |
| 64 | +}; |
| 65 | + |
| 66 | +static int kb106x_config_pin(uint32_t gpio, uint32_t conf, uint32_t func) |
| 67 | +{ |
| 68 | + uint32_t port = ENE_KB106X_PINMUX_PORT(gpio); |
| 69 | + uint32_t pin = (uint32_t)ENE_KB106X_PINMUX_PIN(gpio); |
| 70 | + struct gpio_regs *gpio_regs = (struct gpio_regs *)gpio_reg_bases[port]; |
| 71 | + struct gcfg_regs *gcfg_regs = (struct gcfg_regs *)gcfg_reg_addr; |
| 72 | + |
| 73 | + if (port >= ARRAY_SIZE(gpio_reg_bases)) { |
| 74 | + return -EINVAL; |
| 75 | + } |
| 76 | + |
| 77 | + if (func == PINMUX_FUNC_GPIO) { |
| 78 | + /* only GPIO function */ |
| 79 | + WRITE_BIT(gpio_regs->GPIOFS, pin, 0); |
| 80 | + } else { |
| 81 | + func -= 1; |
| 82 | + /*for change to GPIOALT setting value*/ |
| 83 | + switch (gpio) { |
| 84 | + case GPIO0B_ESBCLK_SCL5: |
| 85 | + WRITE_BIT(gcfg_regs->GPIOALT, 0, func); |
| 86 | + break; |
| 87 | + case GPIO0C_ESBDAT_SDA5: |
| 88 | + WRITE_BIT(gcfg_regs->GPIOALT, 1, func); |
| 89 | + break; |
| 90 | + case GPIO0D_RLCTX2_SDA4: |
| 91 | + WRITE_BIT(gcfg_regs->GPIOALT, 2, func); |
| 92 | + break; |
| 93 | + case GPIO16_SERTXD_UARTSOUT_SBUDCLK: |
| 94 | + case GPIO17_SERRXD_UARTSIN_SBUDDAT: |
| 95 | + gcfg_regs->GPIOMUX = (gcfg_regs->GPIOMUX & ~(3 << 9)) | (func << 9); |
| 96 | + break; |
| 97 | + case GPIO19_PWM3_PWMLED0: |
| 98 | + WRITE_BIT(gcfg_regs->GPIOALT, 3, func); |
| 99 | + break; |
| 100 | + case GPIO30_SERTXD_NKROKSI0: |
| 101 | + WRITE_BIT(gcfg_regs->GPIOALT, 5, func); |
| 102 | + break; |
| 103 | + case GPIO48_KSO16_UART_SOUT2: |
| 104 | + WRITE_BIT(gcfg_regs->GPIOALT, 6, func); |
| 105 | + break; |
| 106 | + case GPIO4C_PSCLK2_SCL3: |
| 107 | + WRITE_BIT(gcfg_regs->GPIOALT, 7, func); |
| 108 | + break; |
| 109 | + case GPIO4D_SDAT2_SDA3: |
| 110 | + WRITE_BIT(gcfg_regs->GPIOALT, 8, func); |
| 111 | + break; |
| 112 | + case GPIO4E_PSCLK3_KSO18: |
| 113 | + WRITE_BIT(gcfg_regs->GPIOALT, 9, func); |
| 114 | + break; |
| 115 | + case GPIO4F_PSDAT3_KSO19: |
| 116 | + WRITE_BIT(gcfg_regs->GPIOALT, 10, func); |
| 117 | + break; |
| 118 | + case GPIO4A_PSCLK1_SCL2_USBDM: |
| 119 | + gcfg_regs->GPIOALT = (gcfg_regs->GPIOALT & ~(3 << 24)) | (func << 24); |
| 120 | + break; |
| 121 | + case GPIO4B_PSDAT1_SDA2_USBDP: |
| 122 | + gcfg_regs->GPIOALT = (gcfg_regs->GPIOALT & ~(3 << 26)) | (func << 26); |
| 123 | + break; |
| 124 | + case GPIO60_SHICS: |
| 125 | + case GPIO61_SHICLK: |
| 126 | + case GPIO62_SHIDO: |
| 127 | + case GPIO78_SHIDI: |
| 128 | + gcfg_regs->GPIOMUX = (gcfg_regs->GPIOMUX & ~(3 << 0)) | (3 << 0); |
| 129 | + break; |
| 130 | + case GPIO5A_SHR_SPICS: |
| 131 | + case GPIO58_SHR_SPICLK: |
| 132 | + case GPIO5C_SHR_MOSI: |
| 133 | + case GPIO5B_SHR_MISO: |
| 134 | + gcfg_regs->GPIOMUX = (gcfg_regs->GPIOMUX & ~(3 << 0)) | (2 << 0); |
| 135 | + break; |
| 136 | + case GPIO01_ESPI_ALERT: |
| 137 | + case GPIO03_ESPI_CS: |
| 138 | + case GPIO07_ESPI_RST: |
| 139 | + WRITE_BIT(gcfg_regs->GPIOALT, 3, func); |
| 140 | + break; |
| 141 | + default: |
| 142 | + break; |
| 143 | + } |
| 144 | + WRITE_BIT(gpio_regs->GPIOFS, pin, 1); |
| 145 | +#ifdef CONFIG_PINCTRL_ENE_KB106X_ALT_OUTPUT_LOOKBACK |
| 146 | + /* default Input always enable for loopback */ |
| 147 | + WRITE_BIT(gpio_regs->GPIOIE, pin, 1); |
| 148 | +#endif /* CONFIG_PINCTRL_ENE_KB106X_ALT_OUTPUT_LOOKBACK */ |
| 149 | + } |
| 150 | + |
| 151 | + /* pull-up/pull-down function */ |
| 152 | + if (conf & BIT(ENE_KB106X_NO_PUD_POS)) { |
| 153 | + WRITE_BIT(gpio_regs->GPIOPU, pin, 0); |
| 154 | + } |
| 155 | + if (conf & BIT(ENE_KB106X_PU_POS)) { |
| 156 | + WRITE_BIT(gpio_regs->GPIOPU, pin, 1); |
| 157 | + } |
| 158 | + if (conf & BIT(ENE_KB106X_PD_POS)) { |
| 159 | + /* KB106x not support */ |
| 160 | + } |
| 161 | + /* output high/low, output type function */ |
| 162 | + if (conf & BIT(ENE_KB106X_OUT_LO_POS)) { |
| 163 | + WRITE_BIT(gpio_regs->GPIOD, pin, 0); |
| 164 | + } |
| 165 | + if (conf & BIT(ENE_KB106X_OUT_HI_POS)) { |
| 166 | + WRITE_BIT(gpio_regs->GPIOD, pin, 1); |
| 167 | + } |
| 168 | + if (conf & BIT(ENE_KB106X_PUSH_PULL_POS)) { |
| 169 | + WRITE_BIT(gpio_regs->GPIOOD, pin, 0); |
| 170 | + } |
| 171 | + if (conf & BIT(ENE_KB106X_OUT_DIS_POS)) { |
| 172 | + WRITE_BIT(gpio_regs->GPIOOE, pin, 0); |
| 173 | + WRITE_BIT(gpio_regs->GPIOOD, pin, 0); |
| 174 | + } |
| 175 | + if (conf & BIT(ENE_KB106X_OUT_EN_POS)) { |
| 176 | + if (conf & BIT(ENE_KB106X_OPEN_DRAIN_POS)) { |
| 177 | + WRITE_BIT(gpio_regs->GPIOOD, pin, 1); |
| 178 | + } |
| 179 | + WRITE_BIT(gpio_regs->GPIOOE, pin, 1); |
| 180 | + } |
| 181 | + /* low voltage mode(support 1.8v Vih/Vil) */ |
| 182 | + if (conf & BIT(ENE_KB106X_PIN_LOW_POWER_POS)) { |
| 183 | + WRITE_BIT(gpio_regs->GPIOLV, pin, 1); |
| 184 | + } |
| 185 | + /* input function */ |
| 186 | + if (conf & BIT(ENE_KB106X_IN_DIS_POS)) { |
| 187 | + WRITE_BIT(gpio_regs->GPIOIE, pin, 0); |
| 188 | + } |
| 189 | + if (conf & BIT(ENE_KB106X_IN_EN_POS)) { |
| 190 | + WRITE_BIT(gpio_regs->GPIOIE, pin, 1); |
| 191 | + } |
| 192 | + /* drive strength function(4mA/16mA) */ |
| 193 | + if (conf & BIT(ENE_KB106X_DRIVING_POS)) { |
| 194 | + WRITE_BIT(gpio_regs->GPIODC, pin, 1); |
| 195 | + } else { |
| 196 | + WRITE_BIT(gpio_regs->GPIODC, pin, 0); |
| 197 | + } |
| 198 | + return 0; |
| 199 | +} |
| 200 | + |
| 201 | +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) |
| 202 | +{ |
| 203 | + uint32_t portpin, pinmux, func; |
| 204 | + int ret; |
| 205 | + |
| 206 | + ARG_UNUSED(reg); |
| 207 | + |
| 208 | + for (uint8_t i = 0U; i < pin_cnt; i++) { |
| 209 | + pinmux = pins[i]; |
| 210 | + func = ENE_KB106X_PINMUX_FUNC(pinmux); |
| 211 | + if (func >= PINMUX_FUNC_MAX) { |
| 212 | + return -EINVAL; |
| 213 | + } |
| 214 | + |
| 215 | + portpin = ENE_KB106X_PINMUX_PORT_PIN(pinmux); |
| 216 | + ret = kb106x_config_pin(portpin, pinmux, func); |
| 217 | + if (ret < 0) { |
| 218 | + return ret; |
| 219 | + } |
| 220 | + } |
| 221 | + |
| 222 | + return 0; |
| 223 | +} |
0 commit comments