1*41795aa1SThéo Lebrun // SPDX-License-Identifier: GPL-2.0-only 2*41795aa1SThéo Lebrun /* 3*41795aa1SThéo Lebrun * Pinctrl driver for the Mobileye EyeQ5 platform. 4*41795aa1SThéo Lebrun * 5*41795aa1SThéo Lebrun * The registers are located in a syscon region called OLB. There are two pin 6*41795aa1SThéo Lebrun * banks, each being controlled by 5 registers (see enum eq5p_regs) for 7*41795aa1SThéo Lebrun * pull-down, pull-up, drive strength and muxing. 8*41795aa1SThéo Lebrun * 9*41795aa1SThéo Lebrun * For each pin, muxing is between two functions: (0) GPIO or (1) another one 10*41795aa1SThéo Lebrun * that is pin-dependent. Functions are declared statically in this driver. 11*41795aa1SThéo Lebrun * 12*41795aa1SThéo Lebrun * We create pinctrl groups that are 1:1 equivalent to pins: each group has a 13*41795aa1SThéo Lebrun * single pin, and its index/selector is the pin number. 14*41795aa1SThéo Lebrun * 15*41795aa1SThéo Lebrun * We use eq5p_ as prefix, as-in "EyeQ5 Pinctrl", but way shorter. 16*41795aa1SThéo Lebrun * 17*41795aa1SThéo Lebrun * Copyright (C) 2024 Mobileye Vision Technologies Ltd. 18*41795aa1SThéo Lebrun */ 19*41795aa1SThéo Lebrun 20*41795aa1SThéo Lebrun #include <linux/array_size.h> 21*41795aa1SThéo Lebrun #include <linux/auxiliary_bus.h> 22*41795aa1SThéo Lebrun #include <linux/bits.h> 23*41795aa1SThéo Lebrun #include <linux/bug.h> 24*41795aa1SThéo Lebrun #include <linux/device.h> 25*41795aa1SThéo Lebrun #include <linux/err.h> 26*41795aa1SThéo Lebrun #include <linux/errno.h> 27*41795aa1SThéo Lebrun #include <linux/io.h> 28*41795aa1SThéo Lebrun #include <linux/mod_devicetable.h> 29*41795aa1SThéo Lebrun #include <linux/seq_file.h> 30*41795aa1SThéo Lebrun #include <linux/slab.h> 31*41795aa1SThéo Lebrun #include <linux/types.h> 32*41795aa1SThéo Lebrun 33*41795aa1SThéo Lebrun #include <linux/pinctrl/pinconf-generic.h> 34*41795aa1SThéo Lebrun #include <linux/pinctrl/pinconf.h> 35*41795aa1SThéo Lebrun #include <linux/pinctrl/pinctrl.h> 36*41795aa1SThéo Lebrun #include <linux/pinctrl/pinmux.h> 37*41795aa1SThéo Lebrun 38*41795aa1SThéo Lebrun #include "core.h" 39*41795aa1SThéo Lebrun #include "pinctrl-utils.h" 40*41795aa1SThéo Lebrun 41*41795aa1SThéo Lebrun struct eq5p_pinctrl { 42*41795aa1SThéo Lebrun struct pinctrl_desc desc; 43*41795aa1SThéo Lebrun void __iomem *base; 44*41795aa1SThéo Lebrun }; 45*41795aa1SThéo Lebrun 46*41795aa1SThéo Lebrun enum eq5p_bank { 47*41795aa1SThéo Lebrun EQ5P_BANK_A, 48*41795aa1SThéo Lebrun EQ5P_BANK_B, 49*41795aa1SThéo Lebrun 50*41795aa1SThéo Lebrun EQ5P_BANK_COUNT, 51*41795aa1SThéo Lebrun }; 52*41795aa1SThéo Lebrun 53*41795aa1SThéo Lebrun enum eq5p_regs { 54*41795aa1SThéo Lebrun EQ5P_PD, 55*41795aa1SThéo Lebrun EQ5P_PU, 56*41795aa1SThéo Lebrun EQ5P_DS_LOW, 57*41795aa1SThéo Lebrun EQ5P_DS_HIGH, 58*41795aa1SThéo Lebrun EQ5P_IOCR, 59*41795aa1SThéo Lebrun 60*41795aa1SThéo Lebrun EQ5P_REG_COUNT, 61*41795aa1SThéo Lebrun }; 62*41795aa1SThéo Lebrun 63*41795aa1SThéo Lebrun static const unsigned int eq5p_regs[EQ5P_BANK_COUNT][EQ5P_REG_COUNT] = { 64*41795aa1SThéo Lebrun [EQ5P_BANK_A] = {0x0C0, 0x0C4, 0x0D0, 0x0D4, 0x0B0}, 65*41795aa1SThéo Lebrun [EQ5P_BANK_B] = {0x0C8, 0x0CC, 0x0D8, 0x0DC, 0x0B4}, 66*41795aa1SThéo Lebrun }; 67*41795aa1SThéo Lebrun 68*41795aa1SThéo Lebrun /* 69*41795aa1SThéo Lebrun * Drive strength; two bits per pin. 70*41795aa1SThéo Lebrun */ 71*41795aa1SThéo Lebrun #define EQ5P_DS_MASK GENMASK(1, 0) 72*41795aa1SThéo Lebrun 73*41795aa1SThéo Lebrun /* 74*41795aa1SThéo Lebrun * Comments to the right of each pin are the "signal name" in the datasheet. 75*41795aa1SThéo Lebrun */ 76*41795aa1SThéo Lebrun static const struct pinctrl_pin_desc eq5p_pins[] = { 77*41795aa1SThéo Lebrun /* Bank A */ 78*41795aa1SThéo Lebrun PINCTRL_PIN(0, "PA0"), /* A0_TIMER0_CK */ 79*41795aa1SThéo Lebrun PINCTRL_PIN(1, "PA1"), /* A1_TIMER0_EOC */ 80*41795aa1SThéo Lebrun PINCTRL_PIN(2, "PA2"), /* A2_TIMER1_CK */ 81*41795aa1SThéo Lebrun PINCTRL_PIN(3, "PA3"), /* A3_TIMER1_EOC */ 82*41795aa1SThéo Lebrun PINCTRL_PIN(4, "PA4"), /* A4_TIMER2_CK */ 83*41795aa1SThéo Lebrun PINCTRL_PIN(5, "PA5"), /* A5_TIMER2_EOC */ 84*41795aa1SThéo Lebrun PINCTRL_PIN(6, "PA6"), /* A6_TIMER5_EXT_INCAP1 */ 85*41795aa1SThéo Lebrun PINCTRL_PIN(7, "PA7"), /* A7_TIMER5_EXT_INCAP2 */ 86*41795aa1SThéo Lebrun PINCTRL_PIN(8, "PA8"), /* A8_TIMER5_EXT_OUTCMP1 */ 87*41795aa1SThéo Lebrun PINCTRL_PIN(9, "PA9"), /* A9_TIMER5_EXT_OUTCMP2 */ 88*41795aa1SThéo Lebrun PINCTRL_PIN(10, "PA10"), /* A10_UART_0_TX */ 89*41795aa1SThéo Lebrun PINCTRL_PIN(11, "PA11"), /* A11_UART_0_RX */ 90*41795aa1SThéo Lebrun PINCTRL_PIN(12, "PA12"), /* A12_UART_1_TX */ 91*41795aa1SThéo Lebrun PINCTRL_PIN(13, "PA13"), /* A13_UART_1_RX */ 92*41795aa1SThéo Lebrun PINCTRL_PIN(14, "PA14"), /* A14_CAN_0_TX */ 93*41795aa1SThéo Lebrun PINCTRL_PIN(15, "PA15"), /* A15_CAN_0_RX */ 94*41795aa1SThéo Lebrun PINCTRL_PIN(16, "PA16"), /* A16_CAN_1_TX */ 95*41795aa1SThéo Lebrun PINCTRL_PIN(17, "PA17"), /* A17_CAN_1_RX */ 96*41795aa1SThéo Lebrun PINCTRL_PIN(18, "PA18"), /* A18_SPI_0_DO */ 97*41795aa1SThéo Lebrun PINCTRL_PIN(19, "PA19"), /* A19_SPI_0_DI */ 98*41795aa1SThéo Lebrun PINCTRL_PIN(20, "PA20"), /* A20_SPI_0_CK */ 99*41795aa1SThéo Lebrun PINCTRL_PIN(21, "PA21"), /* A21_SPI_0_CS0 */ 100*41795aa1SThéo Lebrun PINCTRL_PIN(22, "PA22"), /* A22_SPI_0_CS1 */ 101*41795aa1SThéo Lebrun PINCTRL_PIN(23, "PA23"), /* A23_SPI_1_DO */ 102*41795aa1SThéo Lebrun PINCTRL_PIN(24, "PA24"), /* A24_SPI_1_DI */ 103*41795aa1SThéo Lebrun PINCTRL_PIN(25, "PA25"), /* A25_SPI_1_CK */ 104*41795aa1SThéo Lebrun PINCTRL_PIN(26, "PA26"), /* A26_SPI_1_CS0 */ 105*41795aa1SThéo Lebrun PINCTRL_PIN(27, "PA27"), /* A27_SPI_1_CS1 */ 106*41795aa1SThéo Lebrun PINCTRL_PIN(28, "PA28"), /* A28_REF_CLK0 */ 107*41795aa1SThéo Lebrun 108*41795aa1SThéo Lebrun #define EQ5P_PIN_OFFSET_BANK_B 29 109*41795aa1SThéo Lebrun 110*41795aa1SThéo Lebrun /* Bank B */ 111*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 0, "PB0"), /* B0_TIMER3_CK */ 112*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 1, "PB1"), /* B1_TIMER3_EOC */ 113*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 2, "PB2"), /* B2_TIMER4_CK */ 114*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 3, "PB3"), /* B3_TIMER4_EOC */ 115*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 4, "PB4"), /* B4_TIMER6_EXT_INCAP1 */ 116*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 5, "PB5"), /* B5_TIMER6_EXT_INCAP2 */ 117*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 6, "PB6"), /* B6_TIMER6_EXT_OUTCMP1 */ 118*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 7, "PB7"), /* B7_TIMER6_EXT_OUTCMP2 */ 119*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 8, "PB8"), /* B8_UART_2_TX */ 120*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 9, "PB9"), /* B9_UART_2_RX */ 121*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 10, "PB10"), /* B10_CAN_2_TX */ 122*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 11, "PB11"), /* B11_CAN_2_RX */ 123*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 12, "PB12"), /* B12_SPI_2_DO */ 124*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 13, "PB13"), /* B13_SPI_2_DI */ 125*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 14, "PB14"), /* B14_SPI_2_CK */ 126*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 15, "PB15"), /* B15_SPI_2_CS0 */ 127*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 16, "PB16"), /* B16_SPI_2_CS1 */ 128*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 17, "PB17"), /* B17_SPI_3_DO */ 129*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 18, "PB18"), /* B18_SPI_3_DI */ 130*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 19, "PB19"), /* B19_SPI_3_CK */ 131*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 20, "PB20"), /* B20_SPI_3_CS0 */ 132*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 21, "PB21"), /* B21_SPI_3_CS1 */ 133*41795aa1SThéo Lebrun PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 22, "PB22"), /* B22_MCLK0 */ 134*41795aa1SThéo Lebrun }; 135*41795aa1SThéo Lebrun 136*41795aa1SThéo Lebrun static const char * const gpio_groups[] = { 137*41795aa1SThéo Lebrun /* Bank A */ 138*41795aa1SThéo Lebrun "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", 139*41795aa1SThéo Lebrun "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", 140*41795aa1SThéo Lebrun "PA16", "PA17", "PA18", "PA19", "PA20", "PA21", "PA22", "PA23", 141*41795aa1SThéo Lebrun "PA24", "PA25", "PA26", "PA27", "PA28", 142*41795aa1SThéo Lebrun 143*41795aa1SThéo Lebrun /* Bank B */ 144*41795aa1SThéo Lebrun "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", 145*41795aa1SThéo Lebrun "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", 146*41795aa1SThéo Lebrun "PB16", "PB17", "PB18", "PB19", "PB20", "PB21", "PB22", 147*41795aa1SThéo Lebrun }; 148*41795aa1SThéo Lebrun 149*41795aa1SThéo Lebrun /* Groups of functions on bank A */ 150*41795aa1SThéo Lebrun static const char * const timer0_groups[] = { "PA0", "PA1" }; 151*41795aa1SThéo Lebrun static const char * const timer1_groups[] = { "PA2", "PA3" }; 152*41795aa1SThéo Lebrun static const char * const timer2_groups[] = { "PA4", "PA5" }; 153*41795aa1SThéo Lebrun static const char * const timer5_groups[] = { "PA6", "PA7", "PA8", "PA9" }; 154*41795aa1SThéo Lebrun static const char * const uart0_groups[] = { "PA10", "PA11" }; 155*41795aa1SThéo Lebrun static const char * const uart1_groups[] = { "PA12", "PA13" }; 156*41795aa1SThéo Lebrun static const char * const can0_groups[] = { "PA14", "PA15" }; 157*41795aa1SThéo Lebrun static const char * const can1_groups[] = { "PA16", "PA17" }; 158*41795aa1SThéo Lebrun static const char * const spi0_groups[] = { "PA18", "PA19", "PA20", "PA21", "PA22" }; 159*41795aa1SThéo Lebrun static const char * const spi1_groups[] = { "PA23", "PA24", "PA25", "PA26", "PA27" }; 160*41795aa1SThéo Lebrun static const char * const refclk0_groups[] = { "PA28" }; 161*41795aa1SThéo Lebrun 162*41795aa1SThéo Lebrun /* Groups of functions on bank B */ 163*41795aa1SThéo Lebrun static const char * const timer3_groups[] = { "PB0", "PB1" }; 164*41795aa1SThéo Lebrun static const char * const timer4_groups[] = { "PB2", "PB3" }; 165*41795aa1SThéo Lebrun static const char * const timer6_groups[] = { "PB4", "PB5", "PB6", "PB7" }; 166*41795aa1SThéo Lebrun static const char * const uart2_groups[] = { "PB8", "PB9" }; 167*41795aa1SThéo Lebrun static const char * const can2_groups[] = { "PB10", "PB11" }; 168*41795aa1SThéo Lebrun static const char * const spi2_groups[] = { "PB12", "PB13", "PB14", "PB15", "PB16" }; 169*41795aa1SThéo Lebrun static const char * const spi3_groups[] = { "PB17", "PB18", "PB19", "PB20", "PB21" }; 170*41795aa1SThéo Lebrun static const char * const mclk0_groups[] = { "PB22" }; 171*41795aa1SThéo Lebrun 172*41795aa1SThéo Lebrun static const struct pinfunction eq5p_functions[] = { 173*41795aa1SThéo Lebrun /* GPIO having a fixed index is depended upon, see GPIO_FUNC_SELECTOR. */ 174*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("gpio", gpio_groups, ARRAY_SIZE(gpio_groups)), 175*41795aa1SThéo Lebrun #define GPIO_FUNC_SELECTOR 0 176*41795aa1SThéo Lebrun 177*41795aa1SThéo Lebrun /* Bank A functions */ 178*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("timer0", timer0_groups, ARRAY_SIZE(timer0_groups)), 179*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("timer1", timer1_groups, ARRAY_SIZE(timer1_groups)), 180*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("timer2", timer2_groups, ARRAY_SIZE(timer2_groups)), 181*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("timer5", timer5_groups, ARRAY_SIZE(timer5_groups)), 182*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("uart0", uart0_groups, ARRAY_SIZE(uart0_groups)), 183*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("uart1", uart1_groups, ARRAY_SIZE(uart1_groups)), 184*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("can0", can0_groups, ARRAY_SIZE(can0_groups)), 185*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("can1", can1_groups, ARRAY_SIZE(can1_groups)), 186*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("spi0", spi0_groups, ARRAY_SIZE(spi0_groups)), 187*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("spi1", spi1_groups, ARRAY_SIZE(spi1_groups)), 188*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("refclk0", refclk0_groups, ARRAY_SIZE(refclk0_groups)), 189*41795aa1SThéo Lebrun 190*41795aa1SThéo Lebrun /* Bank B functions */ 191*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("timer3", timer3_groups, ARRAY_SIZE(timer3_groups)), 192*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("timer4", timer4_groups, ARRAY_SIZE(timer4_groups)), 193*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("timer6", timer6_groups, ARRAY_SIZE(timer6_groups)), 194*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("uart2", uart2_groups, ARRAY_SIZE(uart2_groups)), 195*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("can2", can2_groups, ARRAY_SIZE(can2_groups)), 196*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("spi2", spi2_groups, ARRAY_SIZE(spi2_groups)), 197*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("spi3", spi3_groups, ARRAY_SIZE(spi3_groups)), 198*41795aa1SThéo Lebrun PINCTRL_PINFUNCTION("mclk0", mclk0_groups, ARRAY_SIZE(mclk0_groups)), 199*41795aa1SThéo Lebrun }; 200*41795aa1SThéo Lebrun 201*41795aa1SThéo Lebrun static void eq5p_update_bits(const struct eq5p_pinctrl *pctrl, 202*41795aa1SThéo Lebrun enum eq5p_bank bank, enum eq5p_regs reg, 203*41795aa1SThéo Lebrun u32 mask, u32 val) 204*41795aa1SThéo Lebrun { 205*41795aa1SThéo Lebrun void __iomem *ptr = pctrl->base + eq5p_regs[bank][reg]; 206*41795aa1SThéo Lebrun 207*41795aa1SThéo Lebrun writel((readl(ptr) & ~mask) | (val & mask), ptr); 208*41795aa1SThéo Lebrun } 209*41795aa1SThéo Lebrun 210*41795aa1SThéo Lebrun static bool eq5p_test_bit(const struct eq5p_pinctrl *pctrl, 211*41795aa1SThéo Lebrun enum eq5p_bank bank, enum eq5p_regs reg, int offset) 212*41795aa1SThéo Lebrun { 213*41795aa1SThéo Lebrun u32 val = readl(pctrl->base + eq5p_regs[bank][reg]); 214*41795aa1SThéo Lebrun 215*41795aa1SThéo Lebrun if (WARN_ON(offset > 31)) 216*41795aa1SThéo Lebrun return false; 217*41795aa1SThéo Lebrun 218*41795aa1SThéo Lebrun return (val & BIT(offset)) != 0; 219*41795aa1SThéo Lebrun } 220*41795aa1SThéo Lebrun 221*41795aa1SThéo Lebrun static enum eq5p_bank eq5p_pin_to_bank(unsigned int pin) 222*41795aa1SThéo Lebrun { 223*41795aa1SThéo Lebrun if (pin < EQ5P_PIN_OFFSET_BANK_B) 224*41795aa1SThéo Lebrun return EQ5P_BANK_A; 225*41795aa1SThéo Lebrun else 226*41795aa1SThéo Lebrun return EQ5P_BANK_B; 227*41795aa1SThéo Lebrun } 228*41795aa1SThéo Lebrun 229*41795aa1SThéo Lebrun static unsigned int eq5p_pin_to_offset(unsigned int pin) 230*41795aa1SThéo Lebrun { 231*41795aa1SThéo Lebrun if (pin < EQ5P_PIN_OFFSET_BANK_B) 232*41795aa1SThéo Lebrun return pin; 233*41795aa1SThéo Lebrun else 234*41795aa1SThéo Lebrun return pin - EQ5P_PIN_OFFSET_BANK_B; 235*41795aa1SThéo Lebrun } 236*41795aa1SThéo Lebrun 237*41795aa1SThéo Lebrun static int eq5p_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) 238*41795aa1SThéo Lebrun { 239*41795aa1SThéo Lebrun return ARRAY_SIZE(eq5p_pins); 240*41795aa1SThéo Lebrun } 241*41795aa1SThéo Lebrun 242*41795aa1SThéo Lebrun static const char *eq5p_pinctrl_get_group_name(struct pinctrl_dev *pctldev, 243*41795aa1SThéo Lebrun unsigned int selector) 244*41795aa1SThéo Lebrun { 245*41795aa1SThéo Lebrun return pctldev->desc->pins[selector].name; 246*41795aa1SThéo Lebrun } 247*41795aa1SThéo Lebrun 248*41795aa1SThéo Lebrun static int eq5p_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, 249*41795aa1SThéo Lebrun unsigned int selector, 250*41795aa1SThéo Lebrun const unsigned int **pins, 251*41795aa1SThéo Lebrun unsigned int *num_pins) 252*41795aa1SThéo Lebrun { 253*41795aa1SThéo Lebrun *pins = &pctldev->desc->pins[selector].number; 254*41795aa1SThéo Lebrun *num_pins = 1; 255*41795aa1SThéo Lebrun return 0; 256*41795aa1SThéo Lebrun } 257*41795aa1SThéo Lebrun 258*41795aa1SThéo Lebrun static int eq5p_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, 259*41795aa1SThéo Lebrun unsigned long *config) 260*41795aa1SThéo Lebrun { 261*41795aa1SThéo Lebrun enum pin_config_param param = pinconf_to_config_param(*config); 262*41795aa1SThéo Lebrun struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 263*41795aa1SThéo Lebrun unsigned int offset = eq5p_pin_to_offset(pin); 264*41795aa1SThéo Lebrun enum eq5p_bank bank = eq5p_pin_to_bank(pin); 265*41795aa1SThéo Lebrun u32 val_ds, arg; 266*41795aa1SThéo Lebrun bool pd, pu; 267*41795aa1SThéo Lebrun 268*41795aa1SThéo Lebrun pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset); 269*41795aa1SThéo Lebrun pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset); 270*41795aa1SThéo Lebrun 271*41795aa1SThéo Lebrun switch (param) { 272*41795aa1SThéo Lebrun case PIN_CONFIG_BIAS_DISABLE: 273*41795aa1SThéo Lebrun arg = !(pd || pu); 274*41795aa1SThéo Lebrun break; 275*41795aa1SThéo Lebrun case PIN_CONFIG_BIAS_PULL_DOWN: 276*41795aa1SThéo Lebrun arg = pd; 277*41795aa1SThéo Lebrun break; 278*41795aa1SThéo Lebrun case PIN_CONFIG_BIAS_PULL_UP: 279*41795aa1SThéo Lebrun arg = pu; 280*41795aa1SThéo Lebrun break; 281*41795aa1SThéo Lebrun case PIN_CONFIG_DRIVE_STRENGTH: 282*41795aa1SThéo Lebrun offset *= 2; /* two bits per pin */ 283*41795aa1SThéo Lebrun if (offset >= 32) { 284*41795aa1SThéo Lebrun val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_HIGH]); 285*41795aa1SThéo Lebrun offset -= 32; 286*41795aa1SThéo Lebrun } else { 287*41795aa1SThéo Lebrun val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_LOW]); 288*41795aa1SThéo Lebrun } 289*41795aa1SThéo Lebrun arg = (val_ds >> offset) & EQ5P_DS_MASK; 290*41795aa1SThéo Lebrun break; 291*41795aa1SThéo Lebrun default: 292*41795aa1SThéo Lebrun return -ENOTSUPP; 293*41795aa1SThéo Lebrun } 294*41795aa1SThéo Lebrun 295*41795aa1SThéo Lebrun *config = pinconf_to_config_packed(param, arg); 296*41795aa1SThéo Lebrun return 0; 297*41795aa1SThéo Lebrun } 298*41795aa1SThéo Lebrun 299*41795aa1SThéo Lebrun static void eq5p_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, 300*41795aa1SThéo Lebrun struct seq_file *s, 301*41795aa1SThéo Lebrun unsigned int pin) 302*41795aa1SThéo Lebrun { 303*41795aa1SThéo Lebrun struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 304*41795aa1SThéo Lebrun const char *pin_name = pctrl->desc.pins[pin].name; 305*41795aa1SThéo Lebrun unsigned int offset = eq5p_pin_to_offset(pin); 306*41795aa1SThéo Lebrun enum eq5p_bank bank = eq5p_pin_to_bank(pin); 307*41795aa1SThéo Lebrun const char *func_name, *bias; 308*41795aa1SThéo Lebrun unsigned long ds_config; 309*41795aa1SThéo Lebrun u32 drive_strength; 310*41795aa1SThéo Lebrun bool pd, pu; 311*41795aa1SThéo Lebrun int i, j; 312*41795aa1SThéo Lebrun 313*41795aa1SThéo Lebrun /* 314*41795aa1SThéo Lebrun * First, let's get the function name. All pins have only two functions: 315*41795aa1SThéo Lebrun * GPIO (IOCR == 0) and something else (IOCR == 1). 316*41795aa1SThéo Lebrun */ 317*41795aa1SThéo Lebrun if (eq5p_test_bit(pctrl, bank, EQ5P_IOCR, offset)) { 318*41795aa1SThéo Lebrun func_name = NULL; 319*41795aa1SThéo Lebrun for (i = 0; i < ARRAY_SIZE(eq5p_functions); i++) { 320*41795aa1SThéo Lebrun if (i == GPIO_FUNC_SELECTOR) 321*41795aa1SThéo Lebrun continue; 322*41795aa1SThéo Lebrun 323*41795aa1SThéo Lebrun for (j = 0; j < eq5p_functions[i].ngroups; j++) { 324*41795aa1SThéo Lebrun /* Groups and pins are the same thing for us. */ 325*41795aa1SThéo Lebrun const char *x = eq5p_functions[i].groups[j]; 326*41795aa1SThéo Lebrun 327*41795aa1SThéo Lebrun if (strcmp(x, pin_name) == 0) { 328*41795aa1SThéo Lebrun func_name = eq5p_functions[i].name; 329*41795aa1SThéo Lebrun break; 330*41795aa1SThéo Lebrun } 331*41795aa1SThéo Lebrun } 332*41795aa1SThéo Lebrun 333*41795aa1SThéo Lebrun if (func_name) 334*41795aa1SThéo Lebrun break; 335*41795aa1SThéo Lebrun } 336*41795aa1SThéo Lebrun 337*41795aa1SThéo Lebrun /* 338*41795aa1SThéo Lebrun * We have not found the function attached to this pin, this 339*41795aa1SThéo Lebrun * should never occur as all pins have exactly two functions. 340*41795aa1SThéo Lebrun */ 341*41795aa1SThéo Lebrun if (!func_name) 342*41795aa1SThéo Lebrun func_name = "unknown"; 343*41795aa1SThéo Lebrun } else { 344*41795aa1SThéo Lebrun func_name = eq5p_functions[GPIO_FUNC_SELECTOR].name; 345*41795aa1SThéo Lebrun } 346*41795aa1SThéo Lebrun 347*41795aa1SThéo Lebrun /* Second, we retrieve the bias. */ 348*41795aa1SThéo Lebrun pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset); 349*41795aa1SThéo Lebrun pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset); 350*41795aa1SThéo Lebrun if (pd && pu) 351*41795aa1SThéo Lebrun bias = "both"; 352*41795aa1SThéo Lebrun else if (pd && !pu) 353*41795aa1SThéo Lebrun bias = "pulldown"; 354*41795aa1SThéo Lebrun else if (!pd && pu) 355*41795aa1SThéo Lebrun bias = "pullup"; 356*41795aa1SThéo Lebrun else 357*41795aa1SThéo Lebrun bias = "none"; 358*41795aa1SThéo Lebrun 359*41795aa1SThéo Lebrun /* Third, we get the drive strength. */ 360*41795aa1SThéo Lebrun ds_config = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, 0); 361*41795aa1SThéo Lebrun eq5p_pinconf_get(pctldev, pin, &ds_config); 362*41795aa1SThéo Lebrun drive_strength = pinconf_to_config_argument(ds_config); 363*41795aa1SThéo Lebrun 364*41795aa1SThéo Lebrun seq_printf(s, "function=%s bias=%s drive_strength=%d", 365*41795aa1SThéo Lebrun func_name, bias, drive_strength); 366*41795aa1SThéo Lebrun } 367*41795aa1SThéo Lebrun 368*41795aa1SThéo Lebrun static const struct pinctrl_ops eq5p_pinctrl_ops = { 369*41795aa1SThéo Lebrun .get_groups_count = eq5p_pinctrl_get_groups_count, 370*41795aa1SThéo Lebrun .get_group_name = eq5p_pinctrl_get_group_name, 371*41795aa1SThéo Lebrun .get_group_pins = eq5p_pinctrl_get_group_pins, 372*41795aa1SThéo Lebrun .pin_dbg_show = eq5p_pinctrl_pin_dbg_show, 373*41795aa1SThéo Lebrun .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 374*41795aa1SThéo Lebrun .dt_free_map = pinctrl_utils_free_map, 375*41795aa1SThéo Lebrun }; 376*41795aa1SThéo Lebrun 377*41795aa1SThéo Lebrun static int eq5p_pinmux_get_functions_count(struct pinctrl_dev *pctldev) 378*41795aa1SThéo Lebrun { 379*41795aa1SThéo Lebrun return ARRAY_SIZE(eq5p_functions); 380*41795aa1SThéo Lebrun } 381*41795aa1SThéo Lebrun 382*41795aa1SThéo Lebrun static const char *eq5p_pinmux_get_function_name(struct pinctrl_dev *pctldev, 383*41795aa1SThéo Lebrun unsigned int selector) 384*41795aa1SThéo Lebrun { 385*41795aa1SThéo Lebrun return eq5p_functions[selector].name; 386*41795aa1SThéo Lebrun } 387*41795aa1SThéo Lebrun 388*41795aa1SThéo Lebrun static int eq5p_pinmux_get_function_groups(struct pinctrl_dev *pctldev, 389*41795aa1SThéo Lebrun unsigned int selector, 390*41795aa1SThéo Lebrun const char * const **groups, 391*41795aa1SThéo Lebrun unsigned int *num_groups) 392*41795aa1SThéo Lebrun { 393*41795aa1SThéo Lebrun *groups = eq5p_functions[selector].groups; 394*41795aa1SThéo Lebrun *num_groups = eq5p_functions[selector].ngroups; 395*41795aa1SThéo Lebrun return 0; 396*41795aa1SThéo Lebrun } 397*41795aa1SThéo Lebrun 398*41795aa1SThéo Lebrun static int eq5p_pinmux_set_mux(struct pinctrl_dev *pctldev, 399*41795aa1SThéo Lebrun unsigned int func_selector, unsigned int pin) 400*41795aa1SThéo Lebrun { 401*41795aa1SThéo Lebrun struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 402*41795aa1SThéo Lebrun const char *func_name = eq5p_functions[func_selector].name; 403*41795aa1SThéo Lebrun const char *group_name = pctldev->desc->pins[pin].name; 404*41795aa1SThéo Lebrun bool is_gpio = func_selector == GPIO_FUNC_SELECTOR; 405*41795aa1SThéo Lebrun unsigned int offset = eq5p_pin_to_offset(pin); 406*41795aa1SThéo Lebrun enum eq5p_bank bank = eq5p_pin_to_bank(pin); 407*41795aa1SThéo Lebrun u32 mask, val; 408*41795aa1SThéo Lebrun 409*41795aa1SThéo Lebrun dev_dbg(pctldev->dev, "func=%s group=%s\n", func_name, group_name); 410*41795aa1SThéo Lebrun 411*41795aa1SThéo Lebrun mask = BIT(offset); 412*41795aa1SThéo Lebrun val = is_gpio ? 0 : mask; 413*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, EQ5P_IOCR, mask, val); 414*41795aa1SThéo Lebrun return 0; 415*41795aa1SThéo Lebrun } 416*41795aa1SThéo Lebrun 417*41795aa1SThéo Lebrun static int eq5p_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, 418*41795aa1SThéo Lebrun struct pinctrl_gpio_range *range, 419*41795aa1SThéo Lebrun unsigned int pin) 420*41795aa1SThéo Lebrun { 421*41795aa1SThéo Lebrun /* Pin numbers and group selectors are the same thing in our case. */ 422*41795aa1SThéo Lebrun return eq5p_pinmux_set_mux(pctldev, GPIO_FUNC_SELECTOR, pin); 423*41795aa1SThéo Lebrun } 424*41795aa1SThéo Lebrun 425*41795aa1SThéo Lebrun static const struct pinmux_ops eq5p_pinmux_ops = { 426*41795aa1SThéo Lebrun .get_functions_count = eq5p_pinmux_get_functions_count, 427*41795aa1SThéo Lebrun .get_function_name = eq5p_pinmux_get_function_name, 428*41795aa1SThéo Lebrun .get_function_groups = eq5p_pinmux_get_function_groups, 429*41795aa1SThéo Lebrun .set_mux = eq5p_pinmux_set_mux, 430*41795aa1SThéo Lebrun .gpio_request_enable = eq5p_pinmux_gpio_request_enable, 431*41795aa1SThéo Lebrun .strict = true, 432*41795aa1SThéo Lebrun }; 433*41795aa1SThéo Lebrun 434*41795aa1SThéo Lebrun static int eq5p_pinconf_set_drive_strength(struct pinctrl_dev *pctldev, 435*41795aa1SThéo Lebrun unsigned int pin, u32 arg) 436*41795aa1SThéo Lebrun { 437*41795aa1SThéo Lebrun struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 438*41795aa1SThéo Lebrun unsigned int offset = eq5p_pin_to_offset(pin); 439*41795aa1SThéo Lebrun enum eq5p_bank bank = eq5p_pin_to_bank(pin); 440*41795aa1SThéo Lebrun unsigned int reg; 441*41795aa1SThéo Lebrun u32 mask, val; 442*41795aa1SThéo Lebrun 443*41795aa1SThéo Lebrun if (arg & ~EQ5P_DS_MASK) { 444*41795aa1SThéo Lebrun dev_err(pctldev->dev, "Unsupported drive strength: %u\n", arg); 445*41795aa1SThéo Lebrun return -EINVAL; 446*41795aa1SThéo Lebrun } 447*41795aa1SThéo Lebrun 448*41795aa1SThéo Lebrun offset *= 2; /* two bits per pin */ 449*41795aa1SThéo Lebrun 450*41795aa1SThéo Lebrun if (offset >= 32) { 451*41795aa1SThéo Lebrun reg = EQ5P_DS_HIGH; 452*41795aa1SThéo Lebrun offset -= 32; 453*41795aa1SThéo Lebrun } else { 454*41795aa1SThéo Lebrun reg = EQ5P_DS_LOW; 455*41795aa1SThéo Lebrun } 456*41795aa1SThéo Lebrun 457*41795aa1SThéo Lebrun mask = EQ5P_DS_MASK << offset; 458*41795aa1SThéo Lebrun val = arg << offset; 459*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, reg, mask, val); 460*41795aa1SThéo Lebrun return 0; 461*41795aa1SThéo Lebrun } 462*41795aa1SThéo Lebrun 463*41795aa1SThéo Lebrun static int eq5p_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 464*41795aa1SThéo Lebrun unsigned long *configs, unsigned int num_configs) 465*41795aa1SThéo Lebrun { 466*41795aa1SThéo Lebrun struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 467*41795aa1SThéo Lebrun const char *pin_name = pctldev->desc->pins[pin].name; 468*41795aa1SThéo Lebrun unsigned int offset = eq5p_pin_to_offset(pin); 469*41795aa1SThéo Lebrun enum eq5p_bank bank = eq5p_pin_to_bank(pin); 470*41795aa1SThéo Lebrun struct device *dev = pctldev->dev; 471*41795aa1SThéo Lebrun u32 val = BIT(offset); 472*41795aa1SThéo Lebrun unsigned int i; 473*41795aa1SThéo Lebrun 474*41795aa1SThéo Lebrun for (i = 0; i < num_configs; i++) { 475*41795aa1SThéo Lebrun enum pin_config_param param = pinconf_to_config_param(configs[i]); 476*41795aa1SThéo Lebrun u32 arg = pinconf_to_config_argument(configs[i]); 477*41795aa1SThéo Lebrun 478*41795aa1SThéo Lebrun switch (param) { 479*41795aa1SThéo Lebrun case PIN_CONFIG_BIAS_DISABLE: 480*41795aa1SThéo Lebrun dev_dbg(dev, "pin=%s bias_disable\n", pin_name); 481*41795aa1SThéo Lebrun 482*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0); 483*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0); 484*41795aa1SThéo Lebrun break; 485*41795aa1SThéo Lebrun 486*41795aa1SThéo Lebrun case PIN_CONFIG_BIAS_PULL_DOWN: 487*41795aa1SThéo Lebrun dev_dbg(dev, "pin=%s bias_pull_down arg=%u\n", 488*41795aa1SThéo Lebrun pin_name, arg); 489*41795aa1SThéo Lebrun 490*41795aa1SThéo Lebrun if (arg == 0) /* cannot connect to GND */ 491*41795aa1SThéo Lebrun return -ENOTSUPP; 492*41795aa1SThéo Lebrun 493*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, EQ5P_PD, val, val); 494*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0); 495*41795aa1SThéo Lebrun break; 496*41795aa1SThéo Lebrun 497*41795aa1SThéo Lebrun case PIN_CONFIG_BIAS_PULL_UP: 498*41795aa1SThéo Lebrun dev_dbg(dev, "pin=%s bias_pull_up arg=%u\n", 499*41795aa1SThéo Lebrun pin_name, arg); 500*41795aa1SThéo Lebrun 501*41795aa1SThéo Lebrun if (arg == 0) /* cannot connect to VDD */ 502*41795aa1SThéo Lebrun return -ENOTSUPP; 503*41795aa1SThéo Lebrun 504*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0); 505*41795aa1SThéo Lebrun eq5p_update_bits(pctrl, bank, EQ5P_PU, val, val); 506*41795aa1SThéo Lebrun break; 507*41795aa1SThéo Lebrun 508*41795aa1SThéo Lebrun case PIN_CONFIG_DRIVE_STRENGTH: 509*41795aa1SThéo Lebrun dev_dbg(dev, "pin=%s drive_strength arg=%u\n", 510*41795aa1SThéo Lebrun pin_name, arg); 511*41795aa1SThéo Lebrun 512*41795aa1SThéo Lebrun eq5p_pinconf_set_drive_strength(pctldev, pin, arg); 513*41795aa1SThéo Lebrun break; 514*41795aa1SThéo Lebrun 515*41795aa1SThéo Lebrun default: 516*41795aa1SThéo Lebrun dev_err(dev, "Unsupported pinconf %u\n", param); 517*41795aa1SThéo Lebrun return -ENOTSUPP; 518*41795aa1SThéo Lebrun } 519*41795aa1SThéo Lebrun } 520*41795aa1SThéo Lebrun 521*41795aa1SThéo Lebrun return 0; 522*41795aa1SThéo Lebrun } 523*41795aa1SThéo Lebrun 524*41795aa1SThéo Lebrun static const struct pinconf_ops eq5p_pinconf_ops = { 525*41795aa1SThéo Lebrun .is_generic = true, 526*41795aa1SThéo Lebrun .pin_config_get = eq5p_pinconf_get, 527*41795aa1SThéo Lebrun .pin_config_set = eq5p_pinconf_set, 528*41795aa1SThéo Lebrun /* Pins and groups are equivalent in this driver. */ 529*41795aa1SThéo Lebrun .pin_config_group_get = eq5p_pinconf_get, 530*41795aa1SThéo Lebrun .pin_config_group_set = eq5p_pinconf_set, 531*41795aa1SThéo Lebrun }; 532*41795aa1SThéo Lebrun 533*41795aa1SThéo Lebrun static int eq5p_probe(struct auxiliary_device *adev, 534*41795aa1SThéo Lebrun const struct auxiliary_device_id *id) 535*41795aa1SThéo Lebrun { 536*41795aa1SThéo Lebrun struct device *dev = &adev->dev; 537*41795aa1SThéo Lebrun struct pinctrl_dev *pctldev; 538*41795aa1SThéo Lebrun struct eq5p_pinctrl *pctrl; 539*41795aa1SThéo Lebrun int ret; 540*41795aa1SThéo Lebrun 541*41795aa1SThéo Lebrun pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); 542*41795aa1SThéo Lebrun if (!pctrl) 543*41795aa1SThéo Lebrun return -ENOMEM; 544*41795aa1SThéo Lebrun 545*41795aa1SThéo Lebrun pctrl->base = (void __iomem *)dev_get_platdata(dev); 546*41795aa1SThéo Lebrun pctrl->desc.name = dev_name(dev); 547*41795aa1SThéo Lebrun pctrl->desc.pins = eq5p_pins; 548*41795aa1SThéo Lebrun pctrl->desc.npins = ARRAY_SIZE(eq5p_pins); 549*41795aa1SThéo Lebrun pctrl->desc.pctlops = &eq5p_pinctrl_ops; 550*41795aa1SThéo Lebrun pctrl->desc.pmxops = &eq5p_pinmux_ops; 551*41795aa1SThéo Lebrun pctrl->desc.confops = &eq5p_pinconf_ops; 552*41795aa1SThéo Lebrun pctrl->desc.owner = THIS_MODULE; 553*41795aa1SThéo Lebrun 554*41795aa1SThéo Lebrun ret = devm_pinctrl_register_and_init(dev, &pctrl->desc, pctrl, &pctldev); 555*41795aa1SThéo Lebrun if (ret) 556*41795aa1SThéo Lebrun return dev_err_probe(dev, ret, "failed registering pinctrl device\n"); 557*41795aa1SThéo Lebrun 558*41795aa1SThéo Lebrun ret = pinctrl_enable(pctldev); 559*41795aa1SThéo Lebrun if (ret) 560*41795aa1SThéo Lebrun return dev_err_probe(dev, ret, "failed enabling pinctrl device\n"); 561*41795aa1SThéo Lebrun 562*41795aa1SThéo Lebrun return 0; 563*41795aa1SThéo Lebrun } 564*41795aa1SThéo Lebrun 565*41795aa1SThéo Lebrun static const struct auxiliary_device_id eq5p_id_table[] = { 566*41795aa1SThéo Lebrun { .name = "clk_eyeq.pinctrl" }, 567*41795aa1SThéo Lebrun {} 568*41795aa1SThéo Lebrun }; 569*41795aa1SThéo Lebrun MODULE_DEVICE_TABLE(auxiliary, eq5p_id_table); 570*41795aa1SThéo Lebrun 571*41795aa1SThéo Lebrun static struct auxiliary_driver eq5p_driver = { 572*41795aa1SThéo Lebrun .probe = eq5p_probe, 573*41795aa1SThéo Lebrun .id_table = eq5p_id_table, 574*41795aa1SThéo Lebrun }; 575*41795aa1SThéo Lebrun module_auxiliary_driver(eq5p_driver); 576