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
th1520_padcfg(struct th1520_pinctrl * thp,unsigned int pin)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
th1520_padcfg_shift(unsigned int pin)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
th1520_muxcfg(struct th1520_pinctrl * thp,unsigned int pin)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
th1520_muxcfg_shift(unsigned int pin)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
th1520_muxtype_get(const char * str)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
th1520_pad_muxdata(void * drv_data)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
th1520_pad_no_padcfg(void * drv_data)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
th1520_pinctrl_get_groups_count(struct pinctrl_dev * pctldev)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
th1520_pinctrl_get_group_name(struct pinctrl_dev * pctldev,unsigned int gsel)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
th1520_pinctrl_get_group_pins(struct pinctrl_dev * pctldev,unsigned int gsel,const unsigned int ** pins,unsigned int * npins)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
th1520_pin_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned int pin)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
th1520_pinctrl_dt_free_map(struct pinctrl_dev * pctldev,struct pinctrl_map * map,unsigned int nmaps)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
th1520_pinctrl_dt_node_to_map(struct pinctrl_dev * pctldev,struct device_node * np,struct pinctrl_map ** maps,unsigned int * num_maps)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
th1520_drive_strength_from_ma(u32 arg)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
th1520_padcfg_rmw(struct th1520_pinctrl * thp,unsigned int pin,u32 mask,u32 value)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
th1520_pinconf_get(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * config)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
th1520_pinconf_group_get(struct pinctrl_dev * pctldev,unsigned int gsel,unsigned long * config)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
th1520_pinconf_set(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * configs,unsigned int num_configs)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
th1520_pinconf_group_set(struct pinctrl_dev * pctldev,unsigned int gsel,unsigned long * configs,unsigned int num_configs)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
th1520_pinconf_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned int pin)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
th1520_pinmux_set(struct th1520_pinctrl * thp,unsigned int pin,unsigned long muxdata,enum th1520_muxtype muxtype)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
th1520_pinmux_set_mux(struct pinctrl_dev * pctldev,unsigned int fsel,unsigned int gsel)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
th1520_gpio_request_enable(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned int offset)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
th1520_gpio_set_direction(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned int offset,bool input)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
th1520_pinctrl_probe(struct platform_device * pdev)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