1bed5cd6fSEmil Renner Berthing // SPDX-License-Identifier: GPL-2.0 2bed5cd6fSEmil Renner Berthing /* 3bed5cd6fSEmil Renner Berthing * Pinctrl driver for the T-Head TH1520 SoC 4bed5cd6fSEmil Renner Berthing * 5bed5cd6fSEmil Renner Berthing * Copyright (C) 2023 Emil Renner Berthing <emil.renner.berthing@canonical.com> 6bed5cd6fSEmil Renner Berthing */ 7bed5cd6fSEmil Renner Berthing 8bed5cd6fSEmil Renner Berthing #include <linux/array_size.h> 9bed5cd6fSEmil Renner Berthing #include <linux/bits.h> 10bed5cd6fSEmil Renner Berthing #include <linux/cleanup.h> 11bed5cd6fSEmil Renner Berthing #include <linux/clk.h> 12bed5cd6fSEmil Renner Berthing #include <linux/device.h> 13bed5cd6fSEmil Renner Berthing #include <linux/io.h> 14bed5cd6fSEmil Renner Berthing #include <linux/mod_devicetable.h> 15bed5cd6fSEmil Renner Berthing #include <linux/module.h> 16bed5cd6fSEmil Renner Berthing #include <linux/mutex.h> 17bed5cd6fSEmil Renner Berthing #include <linux/of.h> 18bed5cd6fSEmil Renner Berthing #include <linux/platform_device.h> 19bed5cd6fSEmil Renner Berthing #include <linux/seq_file.h> 20bed5cd6fSEmil Renner Berthing #include <linux/spinlock.h> 21bed5cd6fSEmil Renner Berthing 22bed5cd6fSEmil Renner Berthing #include <linux/of_address.h> 23bed5cd6fSEmil Renner Berthing #include <linux/of_device.h> 24bed5cd6fSEmil Renner Berthing 25bed5cd6fSEmil Renner Berthing #include <linux/pinctrl/pinconf.h> 26bed5cd6fSEmil Renner Berthing #include <linux/pinctrl/pinconf-generic.h> 27bed5cd6fSEmil Renner Berthing #include <linux/pinctrl/pinctrl.h> 28bed5cd6fSEmil Renner Berthing #include <linux/pinctrl/pinmux.h> 29bed5cd6fSEmil Renner Berthing 30bed5cd6fSEmil Renner Berthing #include "core.h" 31bed5cd6fSEmil Renner Berthing #include "pinmux.h" 32bed5cd6fSEmil Renner Berthing #include "pinconf.h" 33bed5cd6fSEmil Renner Berthing 34bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_IE BIT(9) 35bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_SL BIT(8) 36bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_ST BIT(7) 37bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_SPU BIT(6) 38bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_PS BIT(5) 39bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_PE BIT(4) 40bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_BIAS (TH1520_PADCFG_SPU | TH1520_PADCFG_PS | TH1520_PADCFG_PE) 41bed5cd6fSEmil Renner Berthing #define TH1520_PADCFG_DS GENMASK(3, 0) 42bed5cd6fSEmil Renner Berthing 43bed5cd6fSEmil Renner Berthing #define TH1520_PULL_DOWN_OHM 44000 /* typ. 44kOhm */ 44bed5cd6fSEmil Renner Berthing #define TH1520_PULL_UP_OHM 48000 /* typ. 48kOhm */ 45bed5cd6fSEmil Renner Berthing #define TH1520_PULL_STRONG_OHM 2100 /* typ. 2.1kOhm */ 46bed5cd6fSEmil Renner Berthing 47bed5cd6fSEmil Renner Berthing #define TH1520_PAD_NO_PADCFG BIT(30) 48bed5cd6fSEmil Renner Berthing #define TH1520_PAD_MUXDATA GENMASK(29, 0) 49bed5cd6fSEmil Renner Berthing 50bed5cd6fSEmil Renner Berthing struct th1520_pad_group { 51bed5cd6fSEmil Renner Berthing const char *name; 52bed5cd6fSEmil Renner Berthing const struct pinctrl_pin_desc *pins; 53bed5cd6fSEmil Renner Berthing unsigned int npins; 54bed5cd6fSEmil Renner Berthing }; 55bed5cd6fSEmil Renner Berthing 56bed5cd6fSEmil Renner Berthing struct th1520_pinctrl { 57bed5cd6fSEmil Renner Berthing struct pinctrl_desc desc; 58bed5cd6fSEmil Renner Berthing struct mutex mutex; /* serialize adding functions */ 59bed5cd6fSEmil Renner Berthing raw_spinlock_t lock; /* serialize register access */ 60bed5cd6fSEmil Renner Berthing void __iomem *base; 61bed5cd6fSEmil Renner Berthing struct pinctrl_dev *pctl; 62bed5cd6fSEmil Renner Berthing }; 63bed5cd6fSEmil Renner Berthing 64bed5cd6fSEmil Renner Berthing static void __iomem *th1520_padcfg(struct th1520_pinctrl *thp, 65bed5cd6fSEmil Renner Berthing unsigned int pin) 66bed5cd6fSEmil Renner Berthing { 67bed5cd6fSEmil Renner Berthing return thp->base + 4 * (pin / 2); 68bed5cd6fSEmil Renner Berthing } 69bed5cd6fSEmil Renner Berthing 70bed5cd6fSEmil Renner Berthing static unsigned int th1520_padcfg_shift(unsigned int pin) 71bed5cd6fSEmil Renner Berthing { 72bed5cd6fSEmil Renner Berthing return 16 * (pin & BIT(0)); 73bed5cd6fSEmil Renner Berthing } 74bed5cd6fSEmil Renner Berthing 75bed5cd6fSEmil Renner Berthing static void __iomem *th1520_muxcfg(struct th1520_pinctrl *thp, 76bed5cd6fSEmil Renner Berthing unsigned int pin) 77bed5cd6fSEmil Renner Berthing { 78bed5cd6fSEmil Renner Berthing return thp->base + 0x400 + 4 * (pin / 8); 79bed5cd6fSEmil Renner Berthing } 80bed5cd6fSEmil Renner Berthing 81bed5cd6fSEmil Renner Berthing static unsigned int th1520_muxcfg_shift(unsigned int pin) 82bed5cd6fSEmil Renner Berthing { 83bed5cd6fSEmil Renner Berthing return 4 * (pin & GENMASK(2, 0)); 84bed5cd6fSEmil Renner Berthing } 85bed5cd6fSEmil Renner Berthing 86bed5cd6fSEmil Renner Berthing enum th1520_muxtype { 87bed5cd6fSEmil Renner Berthing TH1520_MUX_____, 88bed5cd6fSEmil Renner Berthing TH1520_MUX_GPIO, 89bed5cd6fSEmil Renner Berthing TH1520_MUX_PWM, 90bed5cd6fSEmil Renner Berthing TH1520_MUX_UART, 91bed5cd6fSEmil Renner Berthing TH1520_MUX_IR, 92bed5cd6fSEmil Renner Berthing TH1520_MUX_I2C, 93bed5cd6fSEmil Renner Berthing TH1520_MUX_SPI, 94bed5cd6fSEmil Renner Berthing TH1520_MUX_QSPI, 95bed5cd6fSEmil Renner Berthing TH1520_MUX_SDIO, 96bed5cd6fSEmil Renner Berthing TH1520_MUX_AUD, 97bed5cd6fSEmil Renner Berthing TH1520_MUX_I2S, 98bed5cd6fSEmil Renner Berthing TH1520_MUX_MAC0, 99bed5cd6fSEmil Renner Berthing TH1520_MUX_MAC1, 100bed5cd6fSEmil Renner Berthing TH1520_MUX_DPU0, 101bed5cd6fSEmil Renner Berthing TH1520_MUX_DPU1, 102bed5cd6fSEmil Renner Berthing TH1520_MUX_ISP, 103bed5cd6fSEmil Renner Berthing TH1520_MUX_HDMI, 104bed5cd6fSEmil Renner Berthing TH1520_MUX_BSEL, 105bed5cd6fSEmil Renner Berthing TH1520_MUX_DBG, 106bed5cd6fSEmil Renner Berthing TH1520_MUX_CLK, 107bed5cd6fSEmil Renner Berthing TH1520_MUX_JTAG, 108bed5cd6fSEmil Renner Berthing TH1520_MUX_ISO, 109bed5cd6fSEmil Renner Berthing TH1520_MUX_FUSE, 110bed5cd6fSEmil Renner Berthing TH1520_MUX_RST, 111bed5cd6fSEmil Renner Berthing }; 112bed5cd6fSEmil Renner Berthing 113bed5cd6fSEmil Renner Berthing static const char *const th1520_muxtype_string[] = { 114bed5cd6fSEmil Renner Berthing [TH1520_MUX_GPIO] = "gpio", 115bed5cd6fSEmil Renner Berthing [TH1520_MUX_PWM] = "pwm", 116bed5cd6fSEmil Renner Berthing [TH1520_MUX_UART] = "uart", 117bed5cd6fSEmil Renner Berthing [TH1520_MUX_IR] = "ir", 118bed5cd6fSEmil Renner Berthing [TH1520_MUX_I2C] = "i2c", 119bed5cd6fSEmil Renner Berthing [TH1520_MUX_SPI] = "spi", 120bed5cd6fSEmil Renner Berthing [TH1520_MUX_QSPI] = "qspi", 121bed5cd6fSEmil Renner Berthing [TH1520_MUX_SDIO] = "sdio", 122bed5cd6fSEmil Renner Berthing [TH1520_MUX_AUD] = "audio", 123bed5cd6fSEmil Renner Berthing [TH1520_MUX_I2S] = "i2s", 124bed5cd6fSEmil Renner Berthing [TH1520_MUX_MAC0] = "gmac0", 125bed5cd6fSEmil Renner Berthing [TH1520_MUX_MAC1] = "gmac1", 126bed5cd6fSEmil Renner Berthing [TH1520_MUX_DPU0] = "dpu0", 127bed5cd6fSEmil Renner Berthing [TH1520_MUX_DPU1] = "dpu1", 128bed5cd6fSEmil Renner Berthing [TH1520_MUX_ISP] = "isp", 129bed5cd6fSEmil Renner Berthing [TH1520_MUX_HDMI] = "hdmi", 130bed5cd6fSEmil Renner Berthing [TH1520_MUX_BSEL] = "bootsel", 131bed5cd6fSEmil Renner Berthing [TH1520_MUX_DBG] = "debug", 132bed5cd6fSEmil Renner Berthing [TH1520_MUX_CLK] = "clock", 133bed5cd6fSEmil Renner Berthing [TH1520_MUX_JTAG] = "jtag", 134bed5cd6fSEmil Renner Berthing [TH1520_MUX_ISO] = "iso7816", 135bed5cd6fSEmil Renner Berthing [TH1520_MUX_FUSE] = "efuse", 136bed5cd6fSEmil Renner Berthing [TH1520_MUX_RST] = "reset", 137bed5cd6fSEmil Renner Berthing }; 138bed5cd6fSEmil Renner Berthing 139bed5cd6fSEmil Renner Berthing static enum th1520_muxtype th1520_muxtype_get(const char *str) 140bed5cd6fSEmil Renner Berthing { 141bed5cd6fSEmil Renner Berthing enum th1520_muxtype mt; 142bed5cd6fSEmil Renner Berthing 143bed5cd6fSEmil Renner Berthing for (mt = TH1520_MUX_GPIO; mt < ARRAY_SIZE(th1520_muxtype_string); mt++) { 144bed5cd6fSEmil Renner Berthing if (!strcmp(str, th1520_muxtype_string[mt])) 145bed5cd6fSEmil Renner Berthing return mt; 146bed5cd6fSEmil Renner Berthing } 147bed5cd6fSEmil Renner Berthing return TH1520_MUX_____; 148bed5cd6fSEmil Renner Berthing } 149bed5cd6fSEmil Renner Berthing 150bed5cd6fSEmil Renner Berthing #define TH1520_PAD(_nr, _name, m0, m1, m2, m3, m4, m5, _flags) \ 151bed5cd6fSEmil Renner Berthing { .number = _nr, .name = #_name, .drv_data = (void *)((_flags) | \ 152bed5cd6fSEmil Renner Berthing (TH1520_MUX_##m0 << 0) | (TH1520_MUX_##m1 << 5) | (TH1520_MUX_##m2 << 10) | \ 153bed5cd6fSEmil Renner Berthing (TH1520_MUX_##m3 << 15) | (TH1520_MUX_##m4 << 20) | (TH1520_MUX_##m5 << 25)) } 154bed5cd6fSEmil Renner Berthing 1551fc30cd9SEmil Renner Berthing static unsigned long th1520_pad_muxdata(void *drv_data) 1561fc30cd9SEmil Renner Berthing { 1571fc30cd9SEmil Renner Berthing return (uintptr_t)drv_data & TH1520_PAD_MUXDATA; 1581fc30cd9SEmil Renner Berthing } 1591fc30cd9SEmil Renner Berthing 1601fc30cd9SEmil Renner Berthing static bool th1520_pad_no_padcfg(void *drv_data) 1611fc30cd9SEmil Renner Berthing { 1621fc30cd9SEmil Renner Berthing return (uintptr_t)drv_data & TH1520_PAD_NO_PADCFG; 1631fc30cd9SEmil Renner Berthing } 1641fc30cd9SEmil Renner Berthing 165bed5cd6fSEmil Renner Berthing static const struct pinctrl_pin_desc th1520_group1_pins[] = { 166bed5cd6fSEmil Renner Berthing TH1520_PAD(0, OSC_CLK_IN, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG), 167bed5cd6fSEmil Renner Berthing TH1520_PAD(1, OSC_CLK_OUT, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG), 168bed5cd6fSEmil Renner Berthing TH1520_PAD(2, SYS_RST_N, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG), 169bed5cd6fSEmil Renner Berthing TH1520_PAD(3, RTC_CLK_IN, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG), 170bed5cd6fSEmil Renner Berthing TH1520_PAD(4, RTC_CLK_OUT, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG), 171bed5cd6fSEmil Renner Berthing /* skip number 5 so we can calculate register offsets and shifts from the pin number */ 172bed5cd6fSEmil Renner Berthing TH1520_PAD(6, TEST_MODE, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG), 173bed5cd6fSEmil Renner Berthing TH1520_PAD(7, DEBUG_MODE, DBG, ____, ____, GPIO, ____, ____, TH1520_PAD_NO_PADCFG), 174bed5cd6fSEmil Renner Berthing TH1520_PAD(8, POR_SEL, ____, ____, ____, ____, ____, ____, TH1520_PAD_NO_PADCFG), 175bed5cd6fSEmil Renner Berthing TH1520_PAD(9, I2C_AON_SCL, I2C, ____, ____, GPIO, ____, ____, 0), 176bed5cd6fSEmil Renner Berthing TH1520_PAD(10, I2C_AON_SDA, I2C, ____, ____, GPIO, ____, ____, 0), 177bed5cd6fSEmil Renner Berthing TH1520_PAD(11, CPU_JTG_TCLK, JTAG, ____, ____, GPIO, ____, ____, 0), 178bed5cd6fSEmil Renner Berthing TH1520_PAD(12, CPU_JTG_TMS, JTAG, ____, ____, GPIO, ____, ____, 0), 179bed5cd6fSEmil Renner Berthing TH1520_PAD(13, CPU_JTG_TDI, JTAG, ____, ____, GPIO, ____, ____, 0), 180bed5cd6fSEmil Renner Berthing TH1520_PAD(14, CPU_JTG_TDO, JTAG, ____, ____, GPIO, ____, ____, 0), 181bed5cd6fSEmil Renner Berthing TH1520_PAD(15, CPU_JTG_TRST, JTAG, ____, ____, GPIO, ____, ____, 0), 182bed5cd6fSEmil Renner Berthing TH1520_PAD(16, AOGPIO_7, CLK, AUD, ____, GPIO, ____, ____, 0), 183bed5cd6fSEmil Renner Berthing TH1520_PAD(17, AOGPIO_8, UART, AUD, IR, GPIO, ____, ____, 0), 184bed5cd6fSEmil Renner Berthing TH1520_PAD(18, AOGPIO_9, UART, AUD, IR, GPIO, ____, ____, 0), 185bed5cd6fSEmil Renner Berthing TH1520_PAD(19, AOGPIO_10, CLK, AUD, ____, GPIO, ____, ____, 0), 186bed5cd6fSEmil Renner Berthing TH1520_PAD(20, AOGPIO_11, GPIO, AUD, ____, ____, ____, ____, 0), 187bed5cd6fSEmil Renner Berthing TH1520_PAD(21, AOGPIO_12, GPIO, AUD, ____, ____, ____, ____, 0), 188bed5cd6fSEmil Renner Berthing TH1520_PAD(22, AOGPIO_13, GPIO, AUD, ____, ____, ____, ____, 0), 189bed5cd6fSEmil Renner Berthing TH1520_PAD(23, AOGPIO_14, GPIO, AUD, ____, ____, ____, ____, 0), 190bed5cd6fSEmil Renner Berthing TH1520_PAD(24, AOGPIO_15, GPIO, AUD, ____, ____, ____, ____, 0), 191bed5cd6fSEmil Renner Berthing TH1520_PAD(25, AUDIO_PA0, AUD, ____, ____, GPIO, ____, ____, 0), 192bed5cd6fSEmil Renner Berthing TH1520_PAD(26, AUDIO_PA1, AUD, ____, ____, GPIO, ____, ____, 0), 193bed5cd6fSEmil Renner Berthing TH1520_PAD(27, AUDIO_PA2, AUD, ____, ____, GPIO, ____, ____, 0), 194bed5cd6fSEmil Renner Berthing TH1520_PAD(28, AUDIO_PA3, AUD, ____, ____, GPIO, ____, ____, 0), 195bed5cd6fSEmil Renner Berthing TH1520_PAD(29, AUDIO_PA4, AUD, ____, ____, GPIO, ____, ____, 0), 196bed5cd6fSEmil Renner Berthing TH1520_PAD(30, AUDIO_PA5, AUD, ____, ____, GPIO, ____, ____, 0), 197bed5cd6fSEmil Renner Berthing TH1520_PAD(31, AUDIO_PA6, AUD, ____, ____, GPIO, ____, ____, 0), 198bed5cd6fSEmil Renner Berthing TH1520_PAD(32, AUDIO_PA7, AUD, ____, ____, GPIO, ____, ____, 0), 199bed5cd6fSEmil Renner Berthing TH1520_PAD(33, AUDIO_PA8, AUD, ____, ____, GPIO, ____, ____, 0), 200bed5cd6fSEmil Renner Berthing TH1520_PAD(34, AUDIO_PA9, AUD, ____, ____, GPIO, ____, ____, 0), 201bed5cd6fSEmil Renner Berthing TH1520_PAD(35, AUDIO_PA10, AUD, ____, ____, GPIO, ____, ____, 0), 202bed5cd6fSEmil Renner Berthing TH1520_PAD(36, AUDIO_PA11, AUD, ____, ____, GPIO, ____, ____, 0), 203bed5cd6fSEmil Renner Berthing TH1520_PAD(37, AUDIO_PA12, AUD, ____, ____, GPIO, ____, ____, 0), 204bed5cd6fSEmil Renner Berthing TH1520_PAD(38, AUDIO_PA13, AUD, ____, ____, GPIO, ____, ____, 0), 205bed5cd6fSEmil Renner Berthing TH1520_PAD(39, AUDIO_PA14, AUD, ____, ____, GPIO, ____, ____, 0), 206bed5cd6fSEmil Renner Berthing TH1520_PAD(40, AUDIO_PA15, AUD, ____, ____, GPIO, ____, ____, 0), 207bed5cd6fSEmil Renner Berthing TH1520_PAD(41, AUDIO_PA16, AUD, ____, ____, GPIO, ____, ____, 0), 208bed5cd6fSEmil Renner Berthing TH1520_PAD(42, AUDIO_PA17, AUD, ____, ____, GPIO, ____, ____, 0), 209bed5cd6fSEmil Renner Berthing TH1520_PAD(43, AUDIO_PA27, AUD, ____, ____, GPIO, ____, ____, 0), 210bed5cd6fSEmil Renner Berthing TH1520_PAD(44, AUDIO_PA28, AUD, ____, ____, GPIO, ____, ____, 0), 211bed5cd6fSEmil Renner Berthing TH1520_PAD(45, AUDIO_PA29, AUD, ____, ____, GPIO, ____, ____, 0), 212bed5cd6fSEmil Renner Berthing TH1520_PAD(46, AUDIO_PA30, AUD, RST, ____, GPIO, ____, ____, 0), 213bed5cd6fSEmil Renner Berthing }; 214bed5cd6fSEmil Renner Berthing 215bed5cd6fSEmil Renner Berthing static const struct pinctrl_pin_desc th1520_group2_pins[] = { 216bed5cd6fSEmil Renner Berthing TH1520_PAD(0, QSPI1_SCLK, QSPI, ISO, ____, GPIO, FUSE, ____, 0), 217bed5cd6fSEmil Renner Berthing TH1520_PAD(1, QSPI1_CSN0, QSPI, ____, I2C, GPIO, FUSE, ____, 0), 218bed5cd6fSEmil Renner Berthing TH1520_PAD(2, QSPI1_D0_MOSI, QSPI, ISO, I2C, GPIO, FUSE, ____, 0), 219bed5cd6fSEmil Renner Berthing TH1520_PAD(3, QSPI1_D1_MISO, QSPI, ISO, ____, GPIO, FUSE, ____, 0), 220bed5cd6fSEmil Renner Berthing TH1520_PAD(4, QSPI1_D2_WP, QSPI, ISO, UART, GPIO, FUSE, ____, 0), 221bed5cd6fSEmil Renner Berthing TH1520_PAD(5, QSPI1_D3_HOLD, QSPI, ISO, UART, GPIO, ____, ____, 0), 222bed5cd6fSEmil Renner Berthing TH1520_PAD(6, I2C0_SCL, I2C, ____, ____, GPIO, ____, ____, 0), 223bed5cd6fSEmil Renner Berthing TH1520_PAD(7, I2C0_SDA, I2C, ____, ____, GPIO, ____, ____, 0), 224bed5cd6fSEmil Renner Berthing TH1520_PAD(8, I2C1_SCL, I2C, ____, ____, GPIO, ____, ____, 0), 225bed5cd6fSEmil Renner Berthing TH1520_PAD(9, I2C1_SDA, I2C, ____, ____, GPIO, ____, ____, 0), 226bed5cd6fSEmil Renner Berthing TH1520_PAD(10, UART1_TXD, UART, ____, ____, GPIO, ____, ____, 0), 227bed5cd6fSEmil Renner Berthing TH1520_PAD(11, UART1_RXD, UART, ____, ____, GPIO, ____, ____, 0), 228bed5cd6fSEmil Renner Berthing TH1520_PAD(12, UART4_TXD, UART, ____, ____, GPIO, ____, ____, 0), 229bed5cd6fSEmil Renner Berthing TH1520_PAD(13, UART4_RXD, UART, ____, ____, GPIO, ____, ____, 0), 230bed5cd6fSEmil Renner Berthing TH1520_PAD(14, UART4_CTSN, UART, ____, ____, GPIO, ____, ____, 0), 231bed5cd6fSEmil Renner Berthing TH1520_PAD(15, UART4_RTSN, UART, ____, ____, GPIO, ____, ____, 0), 232bed5cd6fSEmil Renner Berthing TH1520_PAD(16, UART3_TXD, DBG, UART, ____, GPIO, ____, ____, 0), 233bed5cd6fSEmil Renner Berthing TH1520_PAD(17, UART3_RXD, DBG, UART, ____, GPIO, ____, ____, 0), 234d1e16e21SEmil Renner Berthing TH1520_PAD(18, GPIO0_18, GPIO, I2C, ____, ____, DPU0, DPU1, 0), 235d1e16e21SEmil Renner Berthing TH1520_PAD(19, GPIO0_19, GPIO, I2C, ____, ____, DPU0, DPU1, 0), 236d1e16e21SEmil Renner Berthing TH1520_PAD(20, GPIO0_20, GPIO, UART, IR, ____, DPU0, DPU1, 0), 237bed5cd6fSEmil Renner Berthing TH1520_PAD(21, GPIO0_21, GPIO, UART, IR, ____, DPU0, DPU1, 0), 238bed5cd6fSEmil Renner Berthing TH1520_PAD(22, GPIO0_22, GPIO, JTAG, I2C, ____, DPU0, DPU1, 0), 239bed5cd6fSEmil Renner Berthing TH1520_PAD(23, GPIO0_23, GPIO, JTAG, I2C, ____, DPU0, DPU1, 0), 240bed5cd6fSEmil Renner Berthing TH1520_PAD(24, GPIO0_24, GPIO, JTAG, QSPI, ____, DPU0, DPU1, 0), 241bed5cd6fSEmil Renner Berthing TH1520_PAD(25, GPIO0_25, GPIO, JTAG, ____, ____, DPU0, DPU1, 0), 242bed5cd6fSEmil Renner Berthing TH1520_PAD(26, GPIO0_26, GPIO, JTAG, ____, ____, DPU0, DPU1, 0), 243bed5cd6fSEmil Renner Berthing TH1520_PAD(27, GPIO0_27, GPIO, ____, I2C, ____, DPU0, DPU1, 0), 244bed5cd6fSEmil Renner Berthing TH1520_PAD(28, GPIO0_28, GPIO, ____, I2C, ____, DPU0, DPU1, 0), 245bed5cd6fSEmil Renner Berthing TH1520_PAD(29, GPIO0_29, GPIO, ____, ____, ____, DPU0, DPU1, 0), 246bed5cd6fSEmil Renner Berthing TH1520_PAD(30, GPIO0_30, GPIO, ____, ____, ____, DPU0, DPU1, 0), 247bed5cd6fSEmil Renner Berthing TH1520_PAD(31, GPIO0_31, GPIO, ____, ____, ____, DPU0, DPU1, 0), 248bed5cd6fSEmil Renner Berthing TH1520_PAD(32, GPIO1_0, GPIO, JTAG, ____, ____, DPU0, DPU1, 0), 249bed5cd6fSEmil Renner Berthing TH1520_PAD(33, GPIO1_1, GPIO, JTAG, ____, ____, DPU0, DPU1, 0), 250bed5cd6fSEmil Renner Berthing TH1520_PAD(34, GPIO1_2, GPIO, JTAG, ____, ____, DPU0, DPU1, 0), 251bed5cd6fSEmil Renner Berthing TH1520_PAD(35, GPIO1_3, GPIO, JTAG, ____, ____, DPU0, DPU1, 0), 252bed5cd6fSEmil Renner Berthing TH1520_PAD(36, GPIO1_4, GPIO, JTAG, ____, ____, DPU0, DPU1, 0), 253bed5cd6fSEmil Renner Berthing TH1520_PAD(37, GPIO1_5, GPIO, ____, ____, ____, DPU0, DPU1, 0), 254d1e16e21SEmil Renner Berthing TH1520_PAD(38, GPIO1_6, GPIO, QSPI, ____, ____, DPU0, DPU1, 0), 255bed5cd6fSEmil Renner Berthing TH1520_PAD(39, GPIO1_7, GPIO, QSPI, ____, ____, DPU0, DPU1, 0), 256bed5cd6fSEmil Renner Berthing TH1520_PAD(40, GPIO1_8, GPIO, QSPI, ____, ____, DPU0, DPU1, 0), 257bed5cd6fSEmil Renner Berthing TH1520_PAD(41, GPIO1_9, GPIO, QSPI, ____, ____, DPU0, DPU1, 0), 258bed5cd6fSEmil Renner Berthing TH1520_PAD(42, GPIO1_10, GPIO, QSPI, ____, ____, DPU0, DPU1, 0), 259bed5cd6fSEmil Renner Berthing TH1520_PAD(43, GPIO1_11, GPIO, QSPI, ____, ____, DPU0, DPU1, 0), 260bed5cd6fSEmil Renner Berthing TH1520_PAD(44, GPIO1_12, GPIO, QSPI, ____, ____, DPU0, DPU1, 0), 261bed5cd6fSEmil Renner Berthing TH1520_PAD(45, GPIO1_13, GPIO, UART, ____, ____, DPU0, DPU1, 0), 262bed5cd6fSEmil Renner Berthing TH1520_PAD(46, GPIO1_14, GPIO, UART, ____, ____, DPU0, DPU1, 0), 263bed5cd6fSEmil Renner Berthing TH1520_PAD(47, GPIO1_15, GPIO, UART, ____, ____, DPU0, DPU1, 0), 264bed5cd6fSEmil Renner Berthing TH1520_PAD(48, GPIO1_16, GPIO, UART, ____, ____, DPU0, DPU1, 0), 265bed5cd6fSEmil Renner Berthing TH1520_PAD(49, CLK_OUT_0, BSEL, CLK, ____, GPIO, ____, ____, 0), 266bed5cd6fSEmil Renner Berthing TH1520_PAD(50, CLK_OUT_1, BSEL, CLK, ____, GPIO, ____, ____, 0), 267bed5cd6fSEmil Renner Berthing TH1520_PAD(51, CLK_OUT_2, BSEL, CLK, ____, GPIO, ____, ____, 0), 268bed5cd6fSEmil Renner Berthing TH1520_PAD(52, CLK_OUT_3, BSEL, CLK, ____, GPIO, ____, ____, 0), 269d1e16e21SEmil Renner Berthing TH1520_PAD(53, GPIO1_21, JTAG, ____, ISP, GPIO, ____, ____, 0), 270d1e16e21SEmil Renner Berthing TH1520_PAD(54, GPIO1_22, JTAG, ____, ISP, GPIO, ____, ____, 0), 271d1e16e21SEmil Renner Berthing TH1520_PAD(55, GPIO1_23, JTAG, ____, ISP, GPIO, ____, ____, 0), 272d1e16e21SEmil Renner Berthing TH1520_PAD(56, GPIO1_24, JTAG, ____, ISP, GPIO, ____, ____, 0), 273d1e16e21SEmil Renner Berthing TH1520_PAD(57, GPIO1_25, JTAG, ____, ISP, GPIO, ____, ____, 0), 274bed5cd6fSEmil Renner Berthing TH1520_PAD(58, GPIO1_26, GPIO, ____, ISP, ____, ____, ____, 0), 275bed5cd6fSEmil Renner Berthing TH1520_PAD(59, GPIO1_27, GPIO, ____, ISP, ____, ____, ____, 0), 276bed5cd6fSEmil Renner Berthing TH1520_PAD(60, GPIO1_28, GPIO, ____, ISP, ____, ____, ____, 0), 277bed5cd6fSEmil Renner Berthing TH1520_PAD(61, GPIO1_29, GPIO, ____, ISP, ____, ____, ____, 0), 278bed5cd6fSEmil Renner Berthing TH1520_PAD(62, GPIO1_30, GPIO, ____, ISP, ____, ____, ____, 0), 279bed5cd6fSEmil Renner Berthing }; 280bed5cd6fSEmil Renner Berthing 281bed5cd6fSEmil Renner Berthing static const struct pinctrl_pin_desc th1520_group3_pins[] = { 282bed5cd6fSEmil Renner Berthing TH1520_PAD(0, UART0_TXD, UART, ____, ____, GPIO, ____, ____, 0), 283bed5cd6fSEmil Renner Berthing TH1520_PAD(1, UART0_RXD, UART, ____, ____, GPIO, ____, ____, 0), 284bed5cd6fSEmil Renner Berthing TH1520_PAD(2, QSPI0_SCLK, QSPI, PWM, I2S, GPIO, ____, ____, 0), 285bed5cd6fSEmil Renner Berthing TH1520_PAD(3, QSPI0_CSN0, QSPI, PWM, I2S, GPIO, ____, ____, 0), 286bed5cd6fSEmil Renner Berthing TH1520_PAD(4, QSPI0_CSN1, QSPI, PWM, I2S, GPIO, ____, ____, 0), 287bed5cd6fSEmil Renner Berthing TH1520_PAD(5, QSPI0_D0_MOSI, QSPI, PWM, I2S, GPIO, ____, ____, 0), 288bed5cd6fSEmil Renner Berthing TH1520_PAD(6, QSPI0_D1_MISO, QSPI, PWM, I2S, GPIO, ____, ____, 0), 289bed5cd6fSEmil Renner Berthing TH1520_PAD(7, QSPI0_D2_WP, QSPI, PWM, I2S, GPIO, ____, ____, 0), 290bed5cd6fSEmil Renner Berthing TH1520_PAD(8, QSPI1_D3_HOLD, QSPI, ____, I2S, GPIO, ____, ____, 0), 291bed5cd6fSEmil Renner Berthing TH1520_PAD(9, I2C2_SCL, I2C, UART, ____, GPIO, ____, ____, 0), 292bed5cd6fSEmil Renner Berthing TH1520_PAD(10, I2C2_SDA, I2C, UART, ____, GPIO, ____, ____, 0), 293bed5cd6fSEmil Renner Berthing TH1520_PAD(11, I2C3_SCL, I2C, ____, ____, GPIO, ____, ____, 0), 294bed5cd6fSEmil Renner Berthing TH1520_PAD(12, I2C3_SDA, I2C, ____, ____, GPIO, ____, ____, 0), 295bed5cd6fSEmil Renner Berthing TH1520_PAD(13, GPIO2_13, GPIO, SPI, ____, ____, ____, ____, 0), 296bed5cd6fSEmil Renner Berthing TH1520_PAD(14, SPI_SCLK, SPI, UART, IR, GPIO, ____, ____, 0), 297bed5cd6fSEmil Renner Berthing TH1520_PAD(15, SPI_CSN, SPI, UART, IR, GPIO, ____, ____, 0), 298bed5cd6fSEmil Renner Berthing TH1520_PAD(16, SPI_MOSI, SPI, ____, ____, GPIO, ____, ____, 0), 299bed5cd6fSEmil Renner Berthing TH1520_PAD(17, SPI_MISO, SPI, ____, ____, GPIO, ____, ____, 0), 300bed5cd6fSEmil Renner Berthing TH1520_PAD(18, GPIO2_18, GPIO, MAC1, ____, ____, ____, ____, 0), 301bed5cd6fSEmil Renner Berthing TH1520_PAD(19, GPIO2_19, GPIO, MAC1, ____, ____, ____, ____, 0), 302bed5cd6fSEmil Renner Berthing TH1520_PAD(20, GPIO2_20, GPIO, MAC1, ____, ____, ____, ____, 0), 303bed5cd6fSEmil Renner Berthing TH1520_PAD(21, GPIO2_21, GPIO, MAC1, ____, ____, ____, ____, 0), 304bed5cd6fSEmil Renner Berthing TH1520_PAD(22, GPIO2_22, GPIO, MAC1, ____, ____, ____, ____, 0), 305bed5cd6fSEmil Renner Berthing TH1520_PAD(23, GPIO2_23, GPIO, MAC1, ____, ____, ____, ____, 0), 306bed5cd6fSEmil Renner Berthing TH1520_PAD(24, GPIO2_24, GPIO, MAC1, ____, ____, ____, ____, 0), 307bed5cd6fSEmil Renner Berthing TH1520_PAD(25, GPIO2_25, GPIO, MAC1, ____, ____, ____, ____, 0), 308bed5cd6fSEmil Renner Berthing TH1520_PAD(26, SDIO0_WPRTN, SDIO, ____, ____, GPIO, ____, ____, 0), 309bed5cd6fSEmil Renner Berthing TH1520_PAD(27, SDIO0_DETN, SDIO, ____, ____, GPIO, ____, ____, 0), 310bed5cd6fSEmil Renner Berthing TH1520_PAD(28, SDIO1_WPRTN, SDIO, ____, ____, GPIO, ____, ____, 0), 311bed5cd6fSEmil Renner Berthing TH1520_PAD(29, SDIO1_DETN, SDIO, ____, ____, GPIO, ____, ____, 0), 312bed5cd6fSEmil Renner Berthing TH1520_PAD(30, GPIO2_30, GPIO, MAC1, ____, ____, ____, ____, 0), 313bed5cd6fSEmil Renner Berthing TH1520_PAD(31, GPIO2_31, GPIO, MAC1, ____, ____, ____, ____, 0), 314bed5cd6fSEmil Renner Berthing TH1520_PAD(32, GPIO3_0, GPIO, MAC1, ____, ____, ____, ____, 0), 315bed5cd6fSEmil Renner Berthing TH1520_PAD(33, GPIO3_1, GPIO, MAC1, ____, ____, ____, ____, 0), 316bed5cd6fSEmil Renner Berthing TH1520_PAD(34, GPIO3_2, GPIO, PWM, ____, ____, ____, ____, 0), 317bed5cd6fSEmil Renner Berthing TH1520_PAD(35, GPIO3_3, GPIO, PWM, ____, ____, ____, ____, 0), 318bed5cd6fSEmil Renner Berthing TH1520_PAD(36, HDMI_SCL, HDMI, PWM, ____, GPIO, ____, ____, 0), 319bed5cd6fSEmil Renner Berthing TH1520_PAD(37, HDMI_SDA, HDMI, PWM, ____, GPIO, ____, ____, 0), 320bed5cd6fSEmil Renner Berthing TH1520_PAD(38, HDMI_CEC, HDMI, ____, ____, GPIO, ____, ____, 0), 321bed5cd6fSEmil Renner Berthing TH1520_PAD(39, GMAC0_TX_CLK, MAC0, ____, ____, GPIO, ____, ____, 0), 322bed5cd6fSEmil Renner Berthing TH1520_PAD(40, GMAC0_RX_CLK, MAC0, ____, ____, GPIO, ____, ____, 0), 323bed5cd6fSEmil Renner Berthing TH1520_PAD(41, GMAC0_TXEN, MAC0, UART, ____, GPIO, ____, ____, 0), 324bed5cd6fSEmil Renner Berthing TH1520_PAD(42, GMAC0_TXD0, MAC0, UART, ____, GPIO, ____, ____, 0), 325bed5cd6fSEmil Renner Berthing TH1520_PAD(43, GMAC0_TXD1, MAC0, UART, ____, GPIO, ____, ____, 0), 326bed5cd6fSEmil Renner Berthing TH1520_PAD(44, GMAC0_TXD2, MAC0, UART, ____, GPIO, ____, ____, 0), 327bed5cd6fSEmil Renner Berthing TH1520_PAD(45, GMAC0_TXD3, MAC0, I2C, ____, GPIO, ____, ____, 0), 328bed5cd6fSEmil Renner Berthing TH1520_PAD(46, GMAC0_RXDV, MAC0, I2C, ____, GPIO, ____, ____, 0), 329bed5cd6fSEmil Renner Berthing TH1520_PAD(47, GMAC0_RXD0, MAC0, I2C, ____, GPIO, ____, ____, 0), 330bed5cd6fSEmil Renner Berthing TH1520_PAD(48, GMAC0_RXD1, MAC0, I2C, ____, GPIO, ____, ____, 0), 331bed5cd6fSEmil Renner Berthing TH1520_PAD(49, GMAC0_RXD2, MAC0, SPI, ____, GPIO, ____, ____, 0), 332bed5cd6fSEmil Renner Berthing TH1520_PAD(50, GMAC0_RXD3, MAC0, SPI, ____, GPIO, ____, ____, 0), 333bed5cd6fSEmil Renner Berthing TH1520_PAD(51, GMAC0_MDC, MAC0, SPI, MAC1, GPIO, ____, ____, 0), 334bed5cd6fSEmil Renner Berthing TH1520_PAD(52, GMAC0_MDIO, MAC0, SPI, MAC1, GPIO, ____, ____, 0), 335bed5cd6fSEmil Renner Berthing TH1520_PAD(53, GMAC0_COL, MAC0, PWM, ____, GPIO, ____, ____, 0), 336bed5cd6fSEmil Renner Berthing TH1520_PAD(54, GMAC0_CRS, MAC0, PWM, ____, GPIO, ____, ____, 0), 337bed5cd6fSEmil Renner Berthing }; 338bed5cd6fSEmil Renner Berthing 339bed5cd6fSEmil Renner Berthing static const struct th1520_pad_group th1520_group1 = { 340bed5cd6fSEmil Renner Berthing .name = "th1520-group1", 341bed5cd6fSEmil Renner Berthing .pins = th1520_group1_pins, 342bed5cd6fSEmil Renner Berthing .npins = ARRAY_SIZE(th1520_group1_pins), 343bed5cd6fSEmil Renner Berthing }; 344bed5cd6fSEmil Renner Berthing 345bed5cd6fSEmil Renner Berthing static const struct th1520_pad_group th1520_group2 = { 346bed5cd6fSEmil Renner Berthing .name = "th1520-group2", 347bed5cd6fSEmil Renner Berthing .pins = th1520_group2_pins, 348bed5cd6fSEmil Renner Berthing .npins = ARRAY_SIZE(th1520_group2_pins), 349bed5cd6fSEmil Renner Berthing }; 350bed5cd6fSEmil Renner Berthing 351bed5cd6fSEmil Renner Berthing static const struct th1520_pad_group th1520_group3 = { 352bed5cd6fSEmil Renner Berthing .name = "th1520-group3", 353bed5cd6fSEmil Renner Berthing .pins = th1520_group3_pins, 354bed5cd6fSEmil Renner Berthing .npins = ARRAY_SIZE(th1520_group3_pins), 355bed5cd6fSEmil Renner Berthing }; 356bed5cd6fSEmil Renner Berthing 357bed5cd6fSEmil Renner Berthing static int th1520_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) 358bed5cd6fSEmil Renner Berthing { 359bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 360bed5cd6fSEmil Renner Berthing 361bed5cd6fSEmil Renner Berthing return thp->desc.npins; 362bed5cd6fSEmil Renner Berthing } 363bed5cd6fSEmil Renner Berthing 364bed5cd6fSEmil Renner Berthing static const char *th1520_pinctrl_get_group_name(struct pinctrl_dev *pctldev, 365bed5cd6fSEmil Renner Berthing unsigned int gsel) 366bed5cd6fSEmil Renner Berthing { 367bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 368bed5cd6fSEmil Renner Berthing 369bed5cd6fSEmil Renner Berthing return thp->desc.pins[gsel].name; 370bed5cd6fSEmil Renner Berthing } 371bed5cd6fSEmil Renner Berthing 372bed5cd6fSEmil Renner Berthing static int th1520_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, 373bed5cd6fSEmil Renner Berthing unsigned int gsel, 374bed5cd6fSEmil Renner Berthing const unsigned int **pins, 375bed5cd6fSEmil Renner Berthing unsigned int *npins) 376bed5cd6fSEmil Renner Berthing { 377bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 378bed5cd6fSEmil Renner Berthing 379bed5cd6fSEmil Renner Berthing *pins = &thp->desc.pins[gsel].number; 380bed5cd6fSEmil Renner Berthing *npins = 1; 381bed5cd6fSEmil Renner Berthing return 0; 382bed5cd6fSEmil Renner Berthing } 383bed5cd6fSEmil Renner Berthing 384bed5cd6fSEmil Renner Berthing #ifdef CONFIG_DEBUG_FS 385bed5cd6fSEmil Renner Berthing static void th1520_pin_dbg_show(struct pinctrl_dev *pctldev, 386bed5cd6fSEmil Renner Berthing struct seq_file *s, unsigned int pin) 387bed5cd6fSEmil Renner Berthing { 388bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 389bed5cd6fSEmil Renner Berthing void __iomem *padcfg = th1520_padcfg(thp, pin); 390bed5cd6fSEmil Renner Berthing void __iomem *muxcfg = th1520_muxcfg(thp, pin); 391bed5cd6fSEmil Renner Berthing u32 pad; 392bed5cd6fSEmil Renner Berthing u32 mux; 393bed5cd6fSEmil Renner Berthing 394bed5cd6fSEmil Renner Berthing scoped_guard(raw_spinlock_irqsave, &thp->lock) { 395bed5cd6fSEmil Renner Berthing pad = readl_relaxed(padcfg); 396bed5cd6fSEmil Renner Berthing mux = readl_relaxed(muxcfg); 397bed5cd6fSEmil Renner Berthing } 398bed5cd6fSEmil Renner Berthing 399bed5cd6fSEmil Renner Berthing seq_printf(s, "[PADCFG_%03u:0x%x=0x%07x MUXCFG_%03u:0x%x=0x%08x]", 400bed5cd6fSEmil Renner Berthing 1 + pin / 2, 0x000 + 4 * (pin / 2), pad, 401bed5cd6fSEmil Renner Berthing 1 + pin / 8, 0x400 + 4 * (pin / 8), mux); 402bed5cd6fSEmil Renner Berthing } 403bed5cd6fSEmil Renner Berthing #else 404bed5cd6fSEmil Renner Berthing #define th1520_pin_dbg_show NULL 405bed5cd6fSEmil Renner Berthing #endif 406bed5cd6fSEmil Renner Berthing 407bed5cd6fSEmil Renner Berthing static void th1520_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, 408bed5cd6fSEmil Renner Berthing struct pinctrl_map *map, unsigned int nmaps) 409bed5cd6fSEmil Renner Berthing { 410bed5cd6fSEmil Renner Berthing unsigned long *seen = NULL; 411bed5cd6fSEmil Renner Berthing unsigned int i; 412bed5cd6fSEmil Renner Berthing 413bed5cd6fSEmil Renner Berthing for (i = 0; i < nmaps; i++) { 414bed5cd6fSEmil Renner Berthing if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN && 415bed5cd6fSEmil Renner Berthing map[i].data.configs.configs != seen) { 416bed5cd6fSEmil Renner Berthing seen = map[i].data.configs.configs; 417bed5cd6fSEmil Renner Berthing kfree(seen); 418bed5cd6fSEmil Renner Berthing } 419bed5cd6fSEmil Renner Berthing } 420bed5cd6fSEmil Renner Berthing 421bed5cd6fSEmil Renner Berthing kfree(map); 422bed5cd6fSEmil Renner Berthing } 423bed5cd6fSEmil Renner Berthing 424bed5cd6fSEmil Renner Berthing static int th1520_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, 425bed5cd6fSEmil Renner Berthing struct device_node *np, 426bed5cd6fSEmil Renner Berthing struct pinctrl_map **maps, 427bed5cd6fSEmil Renner Berthing unsigned int *num_maps) 428bed5cd6fSEmil Renner Berthing { 429bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 430bed5cd6fSEmil Renner Berthing struct pinctrl_map *map; 431bed5cd6fSEmil Renner Berthing unsigned long *configs; 432bed5cd6fSEmil Renner Berthing unsigned int nconfigs; 433bed5cd6fSEmil Renner Berthing unsigned int nmaps; 434bed5cd6fSEmil Renner Berthing int ret; 435bed5cd6fSEmil Renner Berthing 436bed5cd6fSEmil Renner Berthing nmaps = 0; 437573cba28SDrew Fustini for_each_available_child_of_node_scoped(np, child) { 438bed5cd6fSEmil Renner Berthing int npins = of_property_count_strings(child, "pins"); 439bed5cd6fSEmil Renner Berthing 440bed5cd6fSEmil Renner Berthing if (npins <= 0) { 441bed5cd6fSEmil Renner Berthing dev_err(thp->pctl->dev, "no pins selected for %pOFn.%pOFn\n", 442bed5cd6fSEmil Renner Berthing np, child); 443bed5cd6fSEmil Renner Berthing return -EINVAL; 444bed5cd6fSEmil Renner Berthing } 445bed5cd6fSEmil Renner Berthing nmaps += npins; 446bed5cd6fSEmil Renner Berthing if (of_property_present(child, "function")) 447bed5cd6fSEmil Renner Berthing nmaps += npins; 448bed5cd6fSEmil Renner Berthing } 449bed5cd6fSEmil Renner Berthing 450bed5cd6fSEmil Renner Berthing map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL); 451bed5cd6fSEmil Renner Berthing if (!map) 452bed5cd6fSEmil Renner Berthing return -ENOMEM; 453bed5cd6fSEmil Renner Berthing 454bed5cd6fSEmil Renner Berthing nmaps = 0; 455f3a3d006SDrew Fustini guard(mutex)(&thp->mutex); 456573cba28SDrew Fustini for_each_available_child_of_node_scoped(np, child) { 457bed5cd6fSEmil Renner Berthing unsigned int rollback = nmaps; 458bed5cd6fSEmil Renner Berthing enum th1520_muxtype muxtype; 459bed5cd6fSEmil Renner Berthing struct property *prop; 460bed5cd6fSEmil Renner Berthing const char *funcname; 461bed5cd6fSEmil Renner Berthing const char **pgnames; 462bed5cd6fSEmil Renner Berthing const char *pinname; 463bed5cd6fSEmil Renner Berthing int npins; 464bed5cd6fSEmil Renner Berthing 465bed5cd6fSEmil Renner Berthing ret = pinconf_generic_parse_dt_config(child, pctldev, &configs, &nconfigs); 466bed5cd6fSEmil Renner Berthing if (ret) { 467bed5cd6fSEmil Renner Berthing dev_err(thp->pctl->dev, "%pOFn.%pOFn: error parsing pin config\n", 468bed5cd6fSEmil Renner Berthing np, child); 469573cba28SDrew Fustini goto free_map; 470bed5cd6fSEmil Renner Berthing } 471bed5cd6fSEmil Renner Berthing 472bed5cd6fSEmil Renner Berthing if (!of_property_read_string(child, "function", &funcname)) { 473bed5cd6fSEmil Renner Berthing muxtype = th1520_muxtype_get(funcname); 474bed5cd6fSEmil Renner Berthing if (!muxtype) { 475bed5cd6fSEmil Renner Berthing dev_err(thp->pctl->dev, "%pOFn.%pOFn: unknown function '%s'\n", 476bed5cd6fSEmil Renner Berthing np, child, funcname); 477bed5cd6fSEmil Renner Berthing ret = -EINVAL; 478bed5cd6fSEmil Renner Berthing goto free_configs; 479bed5cd6fSEmil Renner Berthing } 480bed5cd6fSEmil Renner Berthing 481bed5cd6fSEmil Renner Berthing funcname = devm_kasprintf(thp->pctl->dev, GFP_KERNEL, "%pOFn.%pOFn", 482bed5cd6fSEmil Renner Berthing np, child); 483bed5cd6fSEmil Renner Berthing if (!funcname) { 484bed5cd6fSEmil Renner Berthing ret = -ENOMEM; 485bed5cd6fSEmil Renner Berthing goto free_configs; 486bed5cd6fSEmil Renner Berthing } 487bed5cd6fSEmil Renner Berthing 488bed5cd6fSEmil Renner Berthing npins = of_property_count_strings(child, "pins"); 489bed5cd6fSEmil Renner Berthing pgnames = devm_kcalloc(thp->pctl->dev, npins, sizeof(*pgnames), GFP_KERNEL); 490bed5cd6fSEmil Renner Berthing if (!pgnames) { 491bed5cd6fSEmil Renner Berthing ret = -ENOMEM; 492bed5cd6fSEmil Renner Berthing goto free_configs; 493bed5cd6fSEmil Renner Berthing } 494bed5cd6fSEmil Renner Berthing } else { 495bed5cd6fSEmil Renner Berthing funcname = NULL; 496bed5cd6fSEmil Renner Berthing } 497bed5cd6fSEmil Renner Berthing 498bed5cd6fSEmil Renner Berthing npins = 0; 499bed5cd6fSEmil Renner Berthing of_property_for_each_string(child, "pins", prop, pinname) { 500bed5cd6fSEmil Renner Berthing unsigned int i; 501bed5cd6fSEmil Renner Berthing 502bed5cd6fSEmil Renner Berthing for (i = 0; i < thp->desc.npins; i++) { 503bed5cd6fSEmil Renner Berthing if (!strcmp(pinname, thp->desc.pins[i].name)) 504bed5cd6fSEmil Renner Berthing break; 505bed5cd6fSEmil Renner Berthing } 506bed5cd6fSEmil Renner Berthing if (i == thp->desc.npins) { 507bed5cd6fSEmil Renner Berthing nmaps = rollback; 508bed5cd6fSEmil Renner Berthing dev_err(thp->pctl->dev, "%pOFn.%pOFn: unknown pin '%s'\n", 509bed5cd6fSEmil Renner Berthing np, child, pinname); 5107027e36fSDrew Fustini ret = -EINVAL; 511bed5cd6fSEmil Renner Berthing goto free_configs; 512bed5cd6fSEmil Renner Berthing } 513bed5cd6fSEmil Renner Berthing 514bed5cd6fSEmil Renner Berthing if (nconfigs) { 515bed5cd6fSEmil Renner Berthing map[nmaps].type = PIN_MAP_TYPE_CONFIGS_PIN; 516bed5cd6fSEmil Renner Berthing map[nmaps].data.configs.group_or_pin = thp->desc.pins[i].name; 517bed5cd6fSEmil Renner Berthing map[nmaps].data.configs.configs = configs; 518bed5cd6fSEmil Renner Berthing map[nmaps].data.configs.num_configs = nconfigs; 519bed5cd6fSEmil Renner Berthing nmaps += 1; 520bed5cd6fSEmil Renner Berthing } 521bed5cd6fSEmil Renner Berthing if (funcname) { 522bed5cd6fSEmil Renner Berthing pgnames[npins++] = thp->desc.pins[i].name; 523bed5cd6fSEmil Renner Berthing map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP; 524bed5cd6fSEmil Renner Berthing map[nmaps].data.mux.function = funcname; 525bed5cd6fSEmil Renner Berthing map[nmaps].data.mux.group = thp->desc.pins[i].name; 526bed5cd6fSEmil Renner Berthing nmaps += 1; 527bed5cd6fSEmil Renner Berthing } 528bed5cd6fSEmil Renner Berthing } 529bed5cd6fSEmil Renner Berthing 530bed5cd6fSEmil Renner Berthing if (funcname) { 531bed5cd6fSEmil Renner Berthing ret = pinmux_generic_add_function(pctldev, funcname, pgnames, 532bed5cd6fSEmil Renner Berthing npins, (void *)muxtype); 533bed5cd6fSEmil Renner Berthing if (ret < 0) { 534bed5cd6fSEmil Renner Berthing dev_err(thp->pctl->dev, "error adding function %s\n", funcname); 535573cba28SDrew Fustini goto free_map; 536bed5cd6fSEmil Renner Berthing } 537bed5cd6fSEmil Renner Berthing } 538bed5cd6fSEmil Renner Berthing } 539bed5cd6fSEmil Renner Berthing 540bed5cd6fSEmil Renner Berthing *maps = map; 541bed5cd6fSEmil Renner Berthing *num_maps = nmaps; 542bed5cd6fSEmil Renner Berthing return 0; 543bed5cd6fSEmil Renner Berthing 544bed5cd6fSEmil Renner Berthing free_configs: 545bed5cd6fSEmil Renner Berthing kfree(configs); 546573cba28SDrew Fustini free_map: 547bed5cd6fSEmil Renner Berthing th1520_pinctrl_dt_free_map(pctldev, map, nmaps); 548bed5cd6fSEmil Renner Berthing return ret; 549bed5cd6fSEmil Renner Berthing } 550bed5cd6fSEmil Renner Berthing 551bed5cd6fSEmil Renner Berthing static const struct pinctrl_ops th1520_pinctrl_ops = { 552bed5cd6fSEmil Renner Berthing .get_groups_count = th1520_pinctrl_get_groups_count, 553bed5cd6fSEmil Renner Berthing .get_group_name = th1520_pinctrl_get_group_name, 554bed5cd6fSEmil Renner Berthing .get_group_pins = th1520_pinctrl_get_group_pins, 555bed5cd6fSEmil Renner Berthing .pin_dbg_show = th1520_pin_dbg_show, 556bed5cd6fSEmil Renner Berthing .dt_node_to_map = th1520_pinctrl_dt_node_to_map, 557bed5cd6fSEmil Renner Berthing .dt_free_map = th1520_pinctrl_dt_free_map, 558bed5cd6fSEmil Renner Berthing }; 559bed5cd6fSEmil Renner Berthing 560bed5cd6fSEmil Renner Berthing static const u8 th1520_drive_strength_in_ma[16] = { 561bed5cd6fSEmil Renner Berthing 1, 2, 3, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25, 562bed5cd6fSEmil Renner Berthing }; 563bed5cd6fSEmil Renner Berthing 564bed5cd6fSEmil Renner Berthing static u16 th1520_drive_strength_from_ma(u32 arg) 565bed5cd6fSEmil Renner Berthing { 566bed5cd6fSEmil Renner Berthing u16 ds; 567bed5cd6fSEmil Renner Berthing 568bed5cd6fSEmil Renner Berthing for (ds = 0; ds < TH1520_PADCFG_DS; ds++) { 569bed5cd6fSEmil Renner Berthing if (arg <= th1520_drive_strength_in_ma[ds]) 570bed5cd6fSEmil Renner Berthing return ds; 571bed5cd6fSEmil Renner Berthing } 572bed5cd6fSEmil Renner Berthing return TH1520_PADCFG_DS; 573bed5cd6fSEmil Renner Berthing } 574bed5cd6fSEmil Renner Berthing 575bed5cd6fSEmil Renner Berthing static int th1520_padcfg_rmw(struct th1520_pinctrl *thp, unsigned int pin, 576bed5cd6fSEmil Renner Berthing u32 mask, u32 value) 577bed5cd6fSEmil Renner Berthing { 578bed5cd6fSEmil Renner Berthing void __iomem *padcfg = th1520_padcfg(thp, pin); 579bed5cd6fSEmil Renner Berthing unsigned int shift = th1520_padcfg_shift(pin); 580bed5cd6fSEmil Renner Berthing u32 tmp; 581bed5cd6fSEmil Renner Berthing 582bed5cd6fSEmil Renner Berthing mask <<= shift; 583bed5cd6fSEmil Renner Berthing value <<= shift; 584bed5cd6fSEmil Renner Berthing 585bed5cd6fSEmil Renner Berthing scoped_guard(raw_spinlock_irqsave, &thp->lock) { 586bed5cd6fSEmil Renner Berthing tmp = readl_relaxed(padcfg); 587bed5cd6fSEmil Renner Berthing tmp = (tmp & ~mask) | value; 588bed5cd6fSEmil Renner Berthing writel_relaxed(tmp, padcfg); 589bed5cd6fSEmil Renner Berthing } 590bed5cd6fSEmil Renner Berthing return 0; 591bed5cd6fSEmil Renner Berthing } 592bed5cd6fSEmil Renner Berthing 593bed5cd6fSEmil Renner Berthing static int th1520_pinconf_get(struct pinctrl_dev *pctldev, 594bed5cd6fSEmil Renner Berthing unsigned int pin, unsigned long *config) 595bed5cd6fSEmil Renner Berthing { 596bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 597bed5cd6fSEmil Renner Berthing const struct pin_desc *desc = pin_desc_get(pctldev, pin); 598bed5cd6fSEmil Renner Berthing bool enabled; 599bed5cd6fSEmil Renner Berthing int param; 600bed5cd6fSEmil Renner Berthing u32 value; 601bed5cd6fSEmil Renner Berthing u32 arg; 602bed5cd6fSEmil Renner Berthing 6031fc30cd9SEmil Renner Berthing if (th1520_pad_no_padcfg(desc->drv_data)) 604ca35d5d2SEmil Renner Berthing return -ENOTSUPP; 605bed5cd6fSEmil Renner Berthing 606bed5cd6fSEmil Renner Berthing value = readl_relaxed(th1520_padcfg(thp, pin)); 607bed5cd6fSEmil Renner Berthing value = (value >> th1520_padcfg_shift(pin)) & GENMASK(9, 0); 608bed5cd6fSEmil Renner Berthing 609bed5cd6fSEmil Renner Berthing param = pinconf_to_config_param(*config); 610bed5cd6fSEmil Renner Berthing switch (param) { 611bed5cd6fSEmil Renner Berthing case PIN_CONFIG_BIAS_DISABLE: 612bed5cd6fSEmil Renner Berthing enabled = !(value & (TH1520_PADCFG_SPU | TH1520_PADCFG_PE)); 613bed5cd6fSEmil Renner Berthing arg = 0; 614bed5cd6fSEmil Renner Berthing break; 615bed5cd6fSEmil Renner Berthing case PIN_CONFIG_BIAS_PULL_DOWN: 616bed5cd6fSEmil Renner Berthing enabled = (value & TH1520_PADCFG_BIAS) == TH1520_PADCFG_PE; 617bed5cd6fSEmil Renner Berthing arg = enabled ? TH1520_PULL_DOWN_OHM : 0; 618bed5cd6fSEmil Renner Berthing break; 619bed5cd6fSEmil Renner Berthing case PIN_CONFIG_BIAS_PULL_UP: 620bed5cd6fSEmil Renner Berthing if (value & TH1520_PADCFG_SPU) { 621bed5cd6fSEmil Renner Berthing enabled = true; 622bed5cd6fSEmil Renner Berthing arg = TH1520_PULL_STRONG_OHM; 623bed5cd6fSEmil Renner Berthing } else if ((value & (TH1520_PADCFG_PE | TH1520_PADCFG_PS)) == 624bed5cd6fSEmil Renner Berthing (TH1520_PADCFG_PE | TH1520_PADCFG_PS)) { 625bed5cd6fSEmil Renner Berthing enabled = true; 626bed5cd6fSEmil Renner Berthing arg = TH1520_PULL_UP_OHM; 627bed5cd6fSEmil Renner Berthing } else { 628bed5cd6fSEmil Renner Berthing enabled = false; 629bed5cd6fSEmil Renner Berthing arg = 0; 630bed5cd6fSEmil Renner Berthing } 631bed5cd6fSEmil Renner Berthing break; 632bed5cd6fSEmil Renner Berthing case PIN_CONFIG_DRIVE_STRENGTH: 633bed5cd6fSEmil Renner Berthing enabled = true; 634bed5cd6fSEmil Renner Berthing arg = th1520_drive_strength_in_ma[value & TH1520_PADCFG_DS]; 635bed5cd6fSEmil Renner Berthing break; 636bed5cd6fSEmil Renner Berthing case PIN_CONFIG_INPUT_ENABLE: 637bed5cd6fSEmil Renner Berthing enabled = value & TH1520_PADCFG_IE; 638bed5cd6fSEmil Renner Berthing arg = enabled ? 1 : 0; 639bed5cd6fSEmil Renner Berthing break; 640bed5cd6fSEmil Renner Berthing case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 641bed5cd6fSEmil Renner Berthing enabled = value & TH1520_PADCFG_ST; 642bed5cd6fSEmil Renner Berthing arg = enabled ? 1 : 0; 643bed5cd6fSEmil Renner Berthing break; 644bed5cd6fSEmil Renner Berthing case PIN_CONFIG_SLEW_RATE: 645bed5cd6fSEmil Renner Berthing enabled = value & TH1520_PADCFG_SL; 646bed5cd6fSEmil Renner Berthing arg = enabled ? 1 : 0; 647bed5cd6fSEmil Renner Berthing break; 648bed5cd6fSEmil Renner Berthing default: 649ca35d5d2SEmil Renner Berthing return -ENOTSUPP; 650bed5cd6fSEmil Renner Berthing } 651bed5cd6fSEmil Renner Berthing 652bed5cd6fSEmil Renner Berthing *config = pinconf_to_config_packed(param, arg); 653bed5cd6fSEmil Renner Berthing return enabled ? 0 : -EINVAL; 654bed5cd6fSEmil Renner Berthing } 655bed5cd6fSEmil Renner Berthing 656bed5cd6fSEmil Renner Berthing static int th1520_pinconf_group_get(struct pinctrl_dev *pctldev, 657bed5cd6fSEmil Renner Berthing unsigned int gsel, unsigned long *config) 658bed5cd6fSEmil Renner Berthing { 659bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 660bed5cd6fSEmil Renner Berthing unsigned int pin = thp->desc.pins[gsel].number; 661bed5cd6fSEmil Renner Berthing 662bed5cd6fSEmil Renner Berthing return th1520_pinconf_get(pctldev, pin, config); 663bed5cd6fSEmil Renner Berthing } 664bed5cd6fSEmil Renner Berthing 665bed5cd6fSEmil Renner Berthing static int th1520_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 666bed5cd6fSEmil Renner Berthing unsigned long *configs, unsigned int num_configs) 667bed5cd6fSEmil Renner Berthing { 668bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 669bed5cd6fSEmil Renner Berthing const struct pin_desc *desc = pin_desc_get(pctldev, pin); 670bed5cd6fSEmil Renner Berthing unsigned int i; 671bed5cd6fSEmil Renner Berthing u16 mask, value; 672bed5cd6fSEmil Renner Berthing 6731fc30cd9SEmil Renner Berthing if (th1520_pad_no_padcfg(desc->drv_data)) 674ca35d5d2SEmil Renner Berthing return -ENOTSUPP; 675bed5cd6fSEmil Renner Berthing 676bed5cd6fSEmil Renner Berthing mask = 0; 677bed5cd6fSEmil Renner Berthing value = 0; 678bed5cd6fSEmil Renner Berthing for (i = 0; i < num_configs; i++) { 679bed5cd6fSEmil Renner Berthing int param = pinconf_to_config_param(configs[i]); 680bed5cd6fSEmil Renner Berthing u32 arg = pinconf_to_config_argument(configs[i]); 681bed5cd6fSEmil Renner Berthing 682bed5cd6fSEmil Renner Berthing switch (param) { 683bed5cd6fSEmil Renner Berthing case PIN_CONFIG_BIAS_DISABLE: 684bed5cd6fSEmil Renner Berthing mask |= TH1520_PADCFG_BIAS; 685bed5cd6fSEmil Renner Berthing value &= ~TH1520_PADCFG_BIAS; 686bed5cd6fSEmil Renner Berthing break; 687bed5cd6fSEmil Renner Berthing case PIN_CONFIG_BIAS_PULL_DOWN: 688bed5cd6fSEmil Renner Berthing if (arg == 0) 689ca35d5d2SEmil Renner Berthing return -ENOTSUPP; 690bed5cd6fSEmil Renner Berthing mask |= TH1520_PADCFG_BIAS; 691bed5cd6fSEmil Renner Berthing value &= ~TH1520_PADCFG_BIAS; 692bed5cd6fSEmil Renner Berthing value |= TH1520_PADCFG_PE; 693bed5cd6fSEmil Renner Berthing break; 694bed5cd6fSEmil Renner Berthing case PIN_CONFIG_BIAS_PULL_UP: 695bed5cd6fSEmil Renner Berthing if (arg == 0) 696ca35d5d2SEmil Renner Berthing return -ENOTSUPP; 697bed5cd6fSEmil Renner Berthing mask |= TH1520_PADCFG_BIAS; 698bed5cd6fSEmil Renner Berthing value &= ~TH1520_PADCFG_BIAS; 699bed5cd6fSEmil Renner Berthing if (arg == TH1520_PULL_STRONG_OHM) 700bed5cd6fSEmil Renner Berthing value |= TH1520_PADCFG_SPU; 701bed5cd6fSEmil Renner Berthing else 702bed5cd6fSEmil Renner Berthing value |= TH1520_PADCFG_PE | TH1520_PADCFG_PS; 703bed5cd6fSEmil Renner Berthing break; 704bed5cd6fSEmil Renner Berthing case PIN_CONFIG_DRIVE_STRENGTH: 705bed5cd6fSEmil Renner Berthing mask |= TH1520_PADCFG_DS; 706bed5cd6fSEmil Renner Berthing value &= ~TH1520_PADCFG_DS; 707bed5cd6fSEmil Renner Berthing value |= th1520_drive_strength_from_ma(arg); 708bed5cd6fSEmil Renner Berthing break; 709bed5cd6fSEmil Renner Berthing case PIN_CONFIG_INPUT_ENABLE: 710bed5cd6fSEmil Renner Berthing mask |= TH1520_PADCFG_IE; 711bed5cd6fSEmil Renner Berthing if (arg) 712bed5cd6fSEmil Renner Berthing value |= TH1520_PADCFG_IE; 713bed5cd6fSEmil Renner Berthing else 714bed5cd6fSEmil Renner Berthing value &= ~TH1520_PADCFG_IE; 715bed5cd6fSEmil Renner Berthing break; 716bed5cd6fSEmil Renner Berthing case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 717bed5cd6fSEmil Renner Berthing mask |= TH1520_PADCFG_ST; 718bed5cd6fSEmil Renner Berthing if (arg) 719bed5cd6fSEmil Renner Berthing value |= TH1520_PADCFG_ST; 720bed5cd6fSEmil Renner Berthing else 721bed5cd6fSEmil Renner Berthing value &= ~TH1520_PADCFG_ST; 722bed5cd6fSEmil Renner Berthing break; 723bed5cd6fSEmil Renner Berthing case PIN_CONFIG_SLEW_RATE: 724bed5cd6fSEmil Renner Berthing mask |= TH1520_PADCFG_SL; 725bed5cd6fSEmil Renner Berthing if (arg) 726bed5cd6fSEmil Renner Berthing value |= TH1520_PADCFG_SL; 727bed5cd6fSEmil Renner Berthing else 728bed5cd6fSEmil Renner Berthing value &= ~TH1520_PADCFG_SL; 729bed5cd6fSEmil Renner Berthing break; 730bed5cd6fSEmil Renner Berthing default: 731ca35d5d2SEmil Renner Berthing return -ENOTSUPP; 732bed5cd6fSEmil Renner Berthing } 733bed5cd6fSEmil Renner Berthing } 734bed5cd6fSEmil Renner Berthing 735bed5cd6fSEmil Renner Berthing return th1520_padcfg_rmw(thp, pin, mask, value); 736bed5cd6fSEmil Renner Berthing } 737bed5cd6fSEmil Renner Berthing 738bed5cd6fSEmil Renner Berthing static int th1520_pinconf_group_set(struct pinctrl_dev *pctldev, 739bed5cd6fSEmil Renner Berthing unsigned int gsel, 740bed5cd6fSEmil Renner Berthing unsigned long *configs, 741bed5cd6fSEmil Renner Berthing unsigned int num_configs) 742bed5cd6fSEmil Renner Berthing { 743bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 744bed5cd6fSEmil Renner Berthing unsigned int pin = thp->desc.pins[gsel].number; 745bed5cd6fSEmil Renner Berthing 746bed5cd6fSEmil Renner Berthing return th1520_pinconf_set(pctldev, pin, configs, num_configs); 747bed5cd6fSEmil Renner Berthing } 748bed5cd6fSEmil Renner Berthing 749bed5cd6fSEmil Renner Berthing #ifdef CONFIG_DEBUG_FS 750bed5cd6fSEmil Renner Berthing static void th1520_pinconf_dbg_show(struct pinctrl_dev *pctldev, 751bed5cd6fSEmil Renner Berthing struct seq_file *s, unsigned int pin) 752bed5cd6fSEmil Renner Berthing { 753bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 754bed5cd6fSEmil Renner Berthing u32 value = readl_relaxed(th1520_padcfg(thp, pin)); 755bed5cd6fSEmil Renner Berthing 756bed5cd6fSEmil Renner Berthing value = (value >> th1520_padcfg_shift(pin)) & GENMASK(9, 0); 757bed5cd6fSEmil Renner Berthing 758bed5cd6fSEmil Renner Berthing seq_printf(s, " [0x%03x]", value); 759bed5cd6fSEmil Renner Berthing } 760bed5cd6fSEmil Renner Berthing #else 761bed5cd6fSEmil Renner Berthing #define th1520_pinconf_dbg_show NULL 762bed5cd6fSEmil Renner Berthing #endif 763bed5cd6fSEmil Renner Berthing 764bed5cd6fSEmil Renner Berthing static const struct pinconf_ops th1520_pinconf_ops = { 765bed5cd6fSEmil Renner Berthing .pin_config_get = th1520_pinconf_get, 766bed5cd6fSEmil Renner Berthing .pin_config_group_get = th1520_pinconf_group_get, 767bed5cd6fSEmil Renner Berthing .pin_config_set = th1520_pinconf_set, 768bed5cd6fSEmil Renner Berthing .pin_config_group_set = th1520_pinconf_group_set, 769bed5cd6fSEmil Renner Berthing .pin_config_dbg_show = th1520_pinconf_dbg_show, 770bed5cd6fSEmil Renner Berthing .is_generic = true, 771bed5cd6fSEmil Renner Berthing }; 772bed5cd6fSEmil Renner Berthing 773bed5cd6fSEmil Renner Berthing static int th1520_pinmux_set(struct th1520_pinctrl *thp, unsigned int pin, 774bed5cd6fSEmil Renner Berthing unsigned long muxdata, enum th1520_muxtype muxtype) 775bed5cd6fSEmil Renner Berthing { 776bed5cd6fSEmil Renner Berthing void __iomem *muxcfg = th1520_muxcfg(thp, pin); 777bed5cd6fSEmil Renner Berthing unsigned int shift = th1520_muxcfg_shift(pin); 778bed5cd6fSEmil Renner Berthing u32 mask, value, tmp; 779bed5cd6fSEmil Renner Berthing 780bed5cd6fSEmil Renner Berthing for (value = 0; muxdata; muxdata >>= 5, value++) { 781bed5cd6fSEmil Renner Berthing if ((muxdata & GENMASK(4, 0)) == muxtype) 782bed5cd6fSEmil Renner Berthing break; 783bed5cd6fSEmil Renner Berthing } 784bed5cd6fSEmil Renner Berthing if (!muxdata) { 785bed5cd6fSEmil Renner Berthing dev_err(thp->pctl->dev, "invalid mux %s for pin %s\n", 786bed5cd6fSEmil Renner Berthing th1520_muxtype_string[muxtype], pin_get_name(thp->pctl, pin)); 787bed5cd6fSEmil Renner Berthing return -EINVAL; 788bed5cd6fSEmil Renner Berthing } 789bed5cd6fSEmil Renner Berthing 790bed5cd6fSEmil Renner Berthing mask = GENMASK(3, 0) << shift; 791bed5cd6fSEmil Renner Berthing value = value << shift; 792bed5cd6fSEmil Renner Berthing 793bed5cd6fSEmil Renner Berthing scoped_guard(raw_spinlock_irqsave, &thp->lock) { 794bed5cd6fSEmil Renner Berthing tmp = readl_relaxed(muxcfg); 795bed5cd6fSEmil Renner Berthing tmp = (tmp & ~mask) | value; 796bed5cd6fSEmil Renner Berthing writel_relaxed(tmp, muxcfg); 797bed5cd6fSEmil Renner Berthing } 798bed5cd6fSEmil Renner Berthing return 0; 799bed5cd6fSEmil Renner Berthing } 800bed5cd6fSEmil Renner Berthing 801bed5cd6fSEmil Renner Berthing static int th1520_pinmux_set_mux(struct pinctrl_dev *pctldev, 802bed5cd6fSEmil Renner Berthing unsigned int fsel, unsigned int gsel) 803bed5cd6fSEmil Renner Berthing { 804bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 805bed5cd6fSEmil Renner Berthing const struct function_desc *func = pinmux_generic_get_function(pctldev, fsel); 806*05214b06SColin Ian King enum th1520_muxtype muxtype; 807bed5cd6fSEmil Renner Berthing 808d01240b2Sclingfei if (!func) 809d01240b2Sclingfei return -EINVAL; 8101fc30cd9SEmil Renner Berthing 811*05214b06SColin Ian King muxtype = (uintptr_t)func->data; 812bed5cd6fSEmil Renner Berthing return th1520_pinmux_set(thp, thp->desc.pins[gsel].number, 8131fc30cd9SEmil Renner Berthing th1520_pad_muxdata(thp->desc.pins[gsel].drv_data), 8141fc30cd9SEmil Renner Berthing muxtype); 815bed5cd6fSEmil Renner Berthing } 816bed5cd6fSEmil Renner Berthing 817bed5cd6fSEmil Renner Berthing static int th1520_gpio_request_enable(struct pinctrl_dev *pctldev, 818bed5cd6fSEmil Renner Berthing struct pinctrl_gpio_range *range, 819bed5cd6fSEmil Renner Berthing unsigned int offset) 820bed5cd6fSEmil Renner Berthing { 821bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 822bed5cd6fSEmil Renner Berthing const struct pin_desc *desc = pin_desc_get(pctldev, offset); 823bed5cd6fSEmil Renner Berthing 824bed5cd6fSEmil Renner Berthing return th1520_pinmux_set(thp, offset, 8251fc30cd9SEmil Renner Berthing th1520_pad_muxdata(desc->drv_data), 826bed5cd6fSEmil Renner Berthing TH1520_MUX_GPIO); 827bed5cd6fSEmil Renner Berthing } 828bed5cd6fSEmil Renner Berthing 829bed5cd6fSEmil Renner Berthing static int th1520_gpio_set_direction(struct pinctrl_dev *pctldev, 830bed5cd6fSEmil Renner Berthing struct pinctrl_gpio_range *range, 831bed5cd6fSEmil Renner Berthing unsigned int offset, bool input) 832bed5cd6fSEmil Renner Berthing { 833bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp = pinctrl_dev_get_drvdata(pctldev); 834bed5cd6fSEmil Renner Berthing 835bed5cd6fSEmil Renner Berthing return th1520_padcfg_rmw(thp, offset, TH1520_PADCFG_IE, 836bed5cd6fSEmil Renner Berthing input ? TH1520_PADCFG_IE : 0); 837bed5cd6fSEmil Renner Berthing } 838bed5cd6fSEmil Renner Berthing 839bed5cd6fSEmil Renner Berthing static const struct pinmux_ops th1520_pinmux_ops = { 840bed5cd6fSEmil Renner Berthing .get_functions_count = pinmux_generic_get_function_count, 841bed5cd6fSEmil Renner Berthing .get_function_name = pinmux_generic_get_function_name, 842bed5cd6fSEmil Renner Berthing .get_function_groups = pinmux_generic_get_function_groups, 843bed5cd6fSEmil Renner Berthing .set_mux = th1520_pinmux_set_mux, 844bed5cd6fSEmil Renner Berthing .gpio_request_enable = th1520_gpio_request_enable, 845bed5cd6fSEmil Renner Berthing .gpio_set_direction = th1520_gpio_set_direction, 846bed5cd6fSEmil Renner Berthing .strict = true, 847bed5cd6fSEmil Renner Berthing }; 848bed5cd6fSEmil Renner Berthing 849bed5cd6fSEmil Renner Berthing static int th1520_pinctrl_probe(struct platform_device *pdev) 850bed5cd6fSEmil Renner Berthing { 851bed5cd6fSEmil Renner Berthing struct device *dev = &pdev->dev; 852bed5cd6fSEmil Renner Berthing const struct th1520_pad_group *group; 853bed5cd6fSEmil Renner Berthing struct device_node *np = dev->of_node; 854bed5cd6fSEmil Renner Berthing struct th1520_pinctrl *thp; 855bed5cd6fSEmil Renner Berthing struct clk *clk; 856bed5cd6fSEmil Renner Berthing u32 pin_group; 857bed5cd6fSEmil Renner Berthing int ret; 858bed5cd6fSEmil Renner Berthing 859bed5cd6fSEmil Renner Berthing thp = devm_kzalloc(dev, sizeof(*thp), GFP_KERNEL); 860bed5cd6fSEmil Renner Berthing if (!thp) 861bed5cd6fSEmil Renner Berthing return -ENOMEM; 862bed5cd6fSEmil Renner Berthing 863bed5cd6fSEmil Renner Berthing thp->base = devm_platform_ioremap_resource(pdev, 0); 864bed5cd6fSEmil Renner Berthing if (IS_ERR(thp->base)) 865bed5cd6fSEmil Renner Berthing return PTR_ERR(thp->base); 866bed5cd6fSEmil Renner Berthing 867bed5cd6fSEmil Renner Berthing clk = devm_clk_get_enabled(dev, NULL); 868bed5cd6fSEmil Renner Berthing if (IS_ERR(clk)) 869bed5cd6fSEmil Renner Berthing return dev_err_probe(dev, PTR_ERR(clk), "error getting clock\n"); 870bed5cd6fSEmil Renner Berthing 871bed5cd6fSEmil Renner Berthing ret = of_property_read_u32(np, "thead,pad-group", &pin_group); 872bed5cd6fSEmil Renner Berthing if (ret) 873bed5cd6fSEmil Renner Berthing return dev_err_probe(dev, ret, "failed to read the thead,pad-group property\n"); 874bed5cd6fSEmil Renner Berthing 875bed5cd6fSEmil Renner Berthing if (pin_group == 1) 876bed5cd6fSEmil Renner Berthing group = &th1520_group1; 877bed5cd6fSEmil Renner Berthing else if (pin_group == 2) 878bed5cd6fSEmil Renner Berthing group = &th1520_group2; 879bed5cd6fSEmil Renner Berthing else if (pin_group == 3) 880bed5cd6fSEmil Renner Berthing group = &th1520_group3; 881bed5cd6fSEmil Renner Berthing else 882bed5cd6fSEmil Renner Berthing return dev_err_probe(dev, -EINVAL, "unit address did not match any pad group\n"); 883bed5cd6fSEmil Renner Berthing 884bed5cd6fSEmil Renner Berthing thp->desc.name = group->name; 885bed5cd6fSEmil Renner Berthing thp->desc.pins = group->pins; 886bed5cd6fSEmil Renner Berthing thp->desc.npins = group->npins; 887bed5cd6fSEmil Renner Berthing thp->desc.pctlops = &th1520_pinctrl_ops; 888bed5cd6fSEmil Renner Berthing thp->desc.pmxops = &th1520_pinmux_ops; 889bed5cd6fSEmil Renner Berthing thp->desc.confops = &th1520_pinconf_ops; 890bed5cd6fSEmil Renner Berthing thp->desc.owner = THIS_MODULE; 891bed5cd6fSEmil Renner Berthing mutex_init(&thp->mutex); 892bed5cd6fSEmil Renner Berthing raw_spin_lock_init(&thp->lock); 893bed5cd6fSEmil Renner Berthing 894bed5cd6fSEmil Renner Berthing ret = devm_pinctrl_register_and_init(dev, &thp->desc, thp, &thp->pctl); 895bed5cd6fSEmil Renner Berthing if (ret) 896bed5cd6fSEmil Renner Berthing return dev_err_probe(dev, ret, "could not register pinctrl driver\n"); 897bed5cd6fSEmil Renner Berthing 898bed5cd6fSEmil Renner Berthing return pinctrl_enable(thp->pctl); 899bed5cd6fSEmil Renner Berthing } 900bed5cd6fSEmil Renner Berthing 901bed5cd6fSEmil Renner Berthing static const struct of_device_id th1520_pinctrl_of_match[] = { 902bed5cd6fSEmil Renner Berthing { .compatible = "thead,th1520-pinctrl"}, 903bed5cd6fSEmil Renner Berthing { /* sentinel */ } 904bed5cd6fSEmil Renner Berthing }; 905bed5cd6fSEmil Renner Berthing MODULE_DEVICE_TABLE(of, th1520_pinctrl_of_match); 906bed5cd6fSEmil Renner Berthing 907bed5cd6fSEmil Renner Berthing static struct platform_driver th1520_pinctrl_driver = { 908bed5cd6fSEmil Renner Berthing .probe = th1520_pinctrl_probe, 909bed5cd6fSEmil Renner Berthing .driver = { 910bed5cd6fSEmil Renner Berthing .name = "pinctrl-th1520", 911bed5cd6fSEmil Renner Berthing .of_match_table = th1520_pinctrl_of_match, 912bed5cd6fSEmil Renner Berthing }, 913bed5cd6fSEmil Renner Berthing }; 914bed5cd6fSEmil Renner Berthing module_platform_driver(th1520_pinctrl_driver); 915bed5cd6fSEmil Renner Berthing 916bed5cd6fSEmil Renner Berthing MODULE_DESCRIPTION("Pinctrl driver for the T-Head TH1520 SoC"); 917bed5cd6fSEmil Renner Berthing MODULE_AUTHOR("Emil Renner Berthing <emil.renner.berthing@canonical.com>"); 918bed5cd6fSEmil Renner Berthing MODULE_LICENSE("GPL"); 919