1// SPDX-License-Identifier: GPL-2.0-or-later
2// (C) 2022 Pali Roh��r <pali@kernel.org>
3
4#include <common.h>
5#include <config.h>
6#include <dm.h>
7#include <dm/devres.h>
8#include <dm/lists.h>
9#include <dm/pinctrl.h>
10#include <dm/root.h>
11#include <errno.h>
12#include <asm/io.h>
13
14struct mvebu_mpp_ctrl_setting {
15	const char *name;
16	const char *subname;
17	u8 val;
18	u8 variant;
19};
20
21struct mvebu_mpp_mode {
22	const char *name;
23	size_t nsettings;
24	struct mvebu_mpp_ctrl_setting *settings;
25};
26
27#define MPP_MODE(_name, ...)					\
28	{							\
29		.name = _name,					\
30		.nsettings = ARRAY_SIZE((			\
31			(struct mvebu_mpp_ctrl_setting[])	\
32			 { __VA_ARGS__ })),			\
33		.settings = (struct mvebu_mpp_ctrl_setting[]){	\
34			__VA_ARGS__ },				\
35	}
36
37#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)		\
38	{							\
39		.val = _val,					\
40		.name = _name,					\
41		.subname = _subname,				\
42		.variant = _mask,				\
43	}
44
45#define MVEBU_MPPS_PER_REG	8
46#define MVEBU_MPP_BITS		4
47#define MVEBU_MPP_MASK		0xf
48
49enum {
50	V_88F6810 = BIT(0),
51	V_88F6820 = BIT(1),
52	V_88F6828 = BIT(2),
53	V_88F6810_PLUS = (V_88F6810 | V_88F6820 | V_88F6828),
54	V_88F6820_PLUS = (V_88F6820 | V_88F6828),
55};
56
57static struct mvebu_mpp_mode armada_38x_mpp_modes[] = {
58	MPP_MODE("mpp0",
59		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
60		 MPP_VAR_FUNCTION(1, "ua0",   "rxd",        V_88F6810_PLUS)),
61	MPP_MODE("mpp1",
62		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
63		 MPP_VAR_FUNCTION(1, "ua0",   "txd",        V_88F6810_PLUS)),
64	MPP_MODE("mpp2",
65		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
66		 MPP_VAR_FUNCTION(1, "i2c0",  "sck",        V_88F6810_PLUS)),
67	MPP_MODE("mpp3",
68		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
69		 MPP_VAR_FUNCTION(1, "i2c0",  "sda",        V_88F6810_PLUS)),
70	MPP_MODE("mpp4",
71		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
72		 MPP_VAR_FUNCTION(1, "ge",    "mdc",        V_88F6810_PLUS),
73		 MPP_VAR_FUNCTION(2, "ua1",   "txd",        V_88F6810_PLUS),
74		 MPP_VAR_FUNCTION(3, "ua0",   "rts",        V_88F6810_PLUS)),
75	MPP_MODE("mpp5",
76		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
77		 MPP_VAR_FUNCTION(1, "ge",    "mdio",       V_88F6810_PLUS),
78		 MPP_VAR_FUNCTION(2, "ua1",   "rxd",        V_88F6810_PLUS),
79		 MPP_VAR_FUNCTION(3, "ua0",   "cts",        V_88F6810_PLUS)),
80	MPP_MODE("mpp6",
81		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
82		 MPP_VAR_FUNCTION(1, "ge0",   "txclkout",   V_88F6810_PLUS),
83		 MPP_VAR_FUNCTION(2, "ge0",   "crs",        V_88F6810_PLUS),
84		 MPP_VAR_FUNCTION(5, "dev",   "cs3",        V_88F6810_PLUS)),
85	MPP_MODE("mpp7",
86		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
87		 MPP_VAR_FUNCTION(1, "ge0",   "txd0",       V_88F6810_PLUS),
88		 MPP_VAR_FUNCTION(5, "dev",   "ad9",        V_88F6810_PLUS)),
89	MPP_MODE("mpp8",
90		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
91		 MPP_VAR_FUNCTION(1, "ge0",   "txd1",       V_88F6810_PLUS),
92		 MPP_VAR_FUNCTION(5, "dev",   "ad10",       V_88F6810_PLUS)),
93	MPP_MODE("mpp9",
94		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
95		 MPP_VAR_FUNCTION(1, "ge0",   "txd2",       V_88F6810_PLUS),
96		 MPP_VAR_FUNCTION(5, "dev",   "ad11",       V_88F6810_PLUS)),
97	MPP_MODE("mpp10",
98		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
99		 MPP_VAR_FUNCTION(1, "ge0",   "txd3",       V_88F6810_PLUS),
100		 MPP_VAR_FUNCTION(5, "dev",   "ad12",       V_88F6810_PLUS)),
101	MPP_MODE("mpp11",
102		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
103		 MPP_VAR_FUNCTION(1, "ge0",   "txctl",      V_88F6810_PLUS),
104		 MPP_VAR_FUNCTION(5, "dev",   "ad13",       V_88F6810_PLUS)),
105	MPP_MODE("mpp12",
106		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
107		 MPP_VAR_FUNCTION(1, "ge0",   "rxd0",       V_88F6810_PLUS),
108		 MPP_VAR_FUNCTION(2, "pcie0", "rstout",     V_88F6810_PLUS),
109		 MPP_VAR_FUNCTION(4, "spi0",  "cs1",        V_88F6810_PLUS),
110		 MPP_VAR_FUNCTION(5, "dev",   "ad14",       V_88F6810_PLUS),
111		 MPP_VAR_FUNCTION(6, "pcie3", "clkreq",     V_88F6810_PLUS)),
112	MPP_MODE("mpp13",
113		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
114		 MPP_VAR_FUNCTION(1, "ge0",   "rxd1",       V_88F6810_PLUS),
115		 MPP_VAR_FUNCTION(2, "pcie0", "clkreq",     V_88F6810_PLUS),
116		 MPP_VAR_FUNCTION(3, "pcie1", "clkreq",     V_88F6820_PLUS),
117		 MPP_VAR_FUNCTION(4, "spi0",  "cs2",        V_88F6810_PLUS),
118		 MPP_VAR_FUNCTION(5, "dev",   "ad15",       V_88F6810_PLUS),
119		 MPP_VAR_FUNCTION(6, "pcie2", "clkreq",     V_88F6810_PLUS)),
120	MPP_MODE("mpp14",
121		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
122		 MPP_VAR_FUNCTION(1, "ge0",   "rxd2",       V_88F6810_PLUS),
123		 MPP_VAR_FUNCTION(2, "ptp",   "clk",        V_88F6810_PLUS),
124		 MPP_VAR_FUNCTION(3, "dram",  "vttctrl",    V_88F6810_PLUS),
125		 MPP_VAR_FUNCTION(4, "spi0",  "cs3",        V_88F6810_PLUS),
126		 MPP_VAR_FUNCTION(5, "dev",   "we1",        V_88F6810_PLUS),
127		 MPP_VAR_FUNCTION(6, "pcie3", "clkreq",     V_88F6810_PLUS)),
128	MPP_MODE("mpp15",
129		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
130		 MPP_VAR_FUNCTION(1, "ge0",   "rxd3",       V_88F6810_PLUS),
131		 MPP_VAR_FUNCTION(2, "ge",    "mdc slave",  V_88F6810_PLUS),
132		 MPP_VAR_FUNCTION(3, "pcie0", "rstout",     V_88F6810_PLUS),
133		 MPP_VAR_FUNCTION(4, "spi0",  "mosi",       V_88F6810_PLUS)),
134	MPP_MODE("mpp16",
135		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
136		 MPP_VAR_FUNCTION(1, "ge0",   "rxctl",      V_88F6810_PLUS),
137		 MPP_VAR_FUNCTION(2, "ge",    "mdio slave", V_88F6810_PLUS),
138		 MPP_VAR_FUNCTION(3, "dram",  "deccerr",    V_88F6810_PLUS),
139		 MPP_VAR_FUNCTION(4, "spi0",  "miso",       V_88F6810_PLUS),
140		 MPP_VAR_FUNCTION(5, "pcie0", "clkreq",     V_88F6810_PLUS),
141		 MPP_VAR_FUNCTION(6, "pcie1", "clkreq",     V_88F6820_PLUS)),
142	MPP_MODE("mpp17",
143		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
144		 MPP_VAR_FUNCTION(1, "ge0",   "rxclk",      V_88F6810_PLUS),
145		 MPP_VAR_FUNCTION(2, "ptp",   "clk",        V_88F6810_PLUS),
146		 MPP_VAR_FUNCTION(3, "ua1",   "rxd",        V_88F6810_PLUS),
147		 MPP_VAR_FUNCTION(4, "spi0",  "sck",        V_88F6810_PLUS),
148		 MPP_VAR_FUNCTION(5, "sata1", "prsnt",      V_88F6810_PLUS),
149		 MPP_VAR_FUNCTION(6, "sata0", "prsnt",      V_88F6810_PLUS)),
150	MPP_MODE("mpp18",
151		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
152		 MPP_VAR_FUNCTION(1, "ge0",   "rxerr",      V_88F6810_PLUS),
153		 MPP_VAR_FUNCTION(2, "ptp",   "trig",       V_88F6810_PLUS),
154		 MPP_VAR_FUNCTION(3, "ua1",   "txd",        V_88F6810_PLUS),
155		 MPP_VAR_FUNCTION(4, "spi0",  "cs0",        V_88F6810_PLUS)),
156	MPP_MODE("mpp19",
157		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
158		 MPP_VAR_FUNCTION(1, "ge0",   "col",        V_88F6810_PLUS),
159		 MPP_VAR_FUNCTION(2, "ptp",   "evreq",      V_88F6810_PLUS),
160		 MPP_VAR_FUNCTION(3, "ge0",   "txerr",      V_88F6810_PLUS),
161		 MPP_VAR_FUNCTION(4, "sata1", "prsnt",      V_88F6810_PLUS),
162		 MPP_VAR_FUNCTION(5, "ua0",   "cts",        V_88F6810_PLUS),
163		 MPP_VAR_FUNCTION(6, "ua1",   "rxd",        V_88F6810_PLUS)),
164	MPP_MODE("mpp20",
165		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
166		 MPP_VAR_FUNCTION(1, "ge0",   "txclk",      V_88F6810_PLUS),
167		 MPP_VAR_FUNCTION(2, "ptp",   "clk",        V_88F6810_PLUS),
168		 MPP_VAR_FUNCTION(4, "sata0", "prsnt",      V_88F6810_PLUS),
169		 MPP_VAR_FUNCTION(5, "ua0",   "rts",        V_88F6810_PLUS),
170		 MPP_VAR_FUNCTION(6, "ua1",   "txd",        V_88F6810_PLUS)),
171	MPP_MODE("mpp21",
172		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
173		 MPP_VAR_FUNCTION(1, "spi0",  "cs1",        V_88F6810_PLUS),
174		 MPP_VAR_FUNCTION(2, "ge1",   "rxd0",       V_88F6810_PLUS),
175		 MPP_VAR_FUNCTION(3, "sata0", "prsnt",      V_88F6810_PLUS),
176		 MPP_VAR_FUNCTION(4, "sd0",   "cmd",        V_88F6810_PLUS),
177		 MPP_VAR_FUNCTION(5, "dev",   "bootcs",     V_88F6810_PLUS),
178		 MPP_VAR_FUNCTION(6, "sata1", "prsnt",      V_88F6810_PLUS)),
179	MPP_MODE("mpp22",
180		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
181		 MPP_VAR_FUNCTION(1, "spi0",  "mosi",       V_88F6810_PLUS),
182		 MPP_VAR_FUNCTION(5, "dev",   "ad0",        V_88F6810_PLUS)),
183	MPP_MODE("mpp23",
184		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
185		 MPP_VAR_FUNCTION(1, "spi0",  "sck",        V_88F6810_PLUS),
186		 MPP_VAR_FUNCTION(5, "dev",   "ad2",        V_88F6810_PLUS)),
187	MPP_MODE("mpp24",
188		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
189		 MPP_VAR_FUNCTION(1, "spi0",  "miso",       V_88F6810_PLUS),
190		 MPP_VAR_FUNCTION(2, "ua0",   "cts",        V_88F6810_PLUS),
191		 MPP_VAR_FUNCTION(3, "ua1",   "rxd",        V_88F6810_PLUS),
192		 MPP_VAR_FUNCTION(4, "sd0",   "d4",         V_88F6810_PLUS),
193		 MPP_VAR_FUNCTION(5, "dev",   "ready",      V_88F6810_PLUS)),
194	MPP_MODE("mpp25",
195		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
196		 MPP_VAR_FUNCTION(1, "spi0",  "cs0",        V_88F6810_PLUS),
197		 MPP_VAR_FUNCTION(2, "ua0",   "rts",        V_88F6810_PLUS),
198		 MPP_VAR_FUNCTION(3, "ua1",   "txd",        V_88F6810_PLUS),
199		 MPP_VAR_FUNCTION(4, "sd0",   "d5",         V_88F6810_PLUS),
200		 MPP_VAR_FUNCTION(5, "dev",   "cs0",        V_88F6810_PLUS)),
201	MPP_MODE("mpp26",
202		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
203		 MPP_VAR_FUNCTION(1, "spi0",  "cs2",        V_88F6810_PLUS),
204		 MPP_VAR_FUNCTION(3, "i2c1",  "sck",        V_88F6810_PLUS),
205		 MPP_VAR_FUNCTION(4, "sd0",   "d6",         V_88F6810_PLUS),
206		 MPP_VAR_FUNCTION(5, "dev",   "cs1",        V_88F6810_PLUS)),
207	MPP_MODE("mpp27",
208		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
209		 MPP_VAR_FUNCTION(1, "spi0",  "cs3",        V_88F6810_PLUS),
210		 MPP_VAR_FUNCTION(2, "ge1",   "txclkout",   V_88F6810_PLUS),
211		 MPP_VAR_FUNCTION(3, "i2c1",  "sda",        V_88F6810_PLUS),
212		 MPP_VAR_FUNCTION(4, "sd0",   "d7",         V_88F6810_PLUS),
213		 MPP_VAR_FUNCTION(5, "dev",   "cs2",        V_88F6810_PLUS)),
214	MPP_MODE("mpp28",
215		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
216		 MPP_VAR_FUNCTION(2, "ge1",   "txd0",       V_88F6810_PLUS),
217		 MPP_VAR_FUNCTION(4, "sd0",   "clk",        V_88F6810_PLUS),
218		 MPP_VAR_FUNCTION(5, "dev",   "ad5",        V_88F6810_PLUS)),
219	MPP_MODE("mpp29",
220		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
221		 MPP_VAR_FUNCTION(2, "ge1",   "txd1",       V_88F6810_PLUS),
222		 MPP_VAR_FUNCTION(5, "dev",   "ale0",       V_88F6810_PLUS)),
223	MPP_MODE("mpp30",
224		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
225		 MPP_VAR_FUNCTION(2, "ge1",   "txd2",       V_88F6810_PLUS),
226		 MPP_VAR_FUNCTION(5, "dev",   "oe",         V_88F6810_PLUS)),
227	MPP_MODE("mpp31",
228		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
229		 MPP_VAR_FUNCTION(2, "ge1",   "txd3",       V_88F6810_PLUS),
230		 MPP_VAR_FUNCTION(5, "dev",   "ale1",       V_88F6810_PLUS)),
231	MPP_MODE("mpp32",
232		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
233		 MPP_VAR_FUNCTION(2, "ge1",   "txctl",      V_88F6810_PLUS),
234		 MPP_VAR_FUNCTION(5, "dev",   "we0",        V_88F6810_PLUS)),
235	MPP_MODE("mpp33",
236		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
237		 MPP_VAR_FUNCTION(1, "dram",  "deccerr",    V_88F6810_PLUS),
238		 MPP_VAR_FUNCTION(5, "dev",   "ad3",        V_88F6810_PLUS)),
239	MPP_MODE("mpp34",
240		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
241		 MPP_VAR_FUNCTION(5, "dev",   "ad1",        V_88F6810_PLUS)),
242	MPP_MODE("mpp35",
243		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
244		 MPP_VAR_FUNCTION(1, "ref",   "clk_out1",   V_88F6810_PLUS),
245		 MPP_VAR_FUNCTION(5, "dev",   "a1",         V_88F6810_PLUS)),
246	MPP_MODE("mpp36",
247		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
248		 MPP_VAR_FUNCTION(1, "ptp",   "trig",       V_88F6810_PLUS),
249		 MPP_VAR_FUNCTION(5, "dev",   "a0",         V_88F6810_PLUS)),
250	MPP_MODE("mpp37",
251		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
252		 MPP_VAR_FUNCTION(1, "ptp",   "clk",        V_88F6810_PLUS),
253		 MPP_VAR_FUNCTION(2, "ge1",   "rxclk",      V_88F6810_PLUS),
254		 MPP_VAR_FUNCTION(4, "sd0",   "d3",         V_88F6810_PLUS),
255		 MPP_VAR_FUNCTION(5, "dev",   "ad8",        V_88F6810_PLUS)),
256	MPP_MODE("mpp38",
257		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
258		 MPP_VAR_FUNCTION(1, "ptp",   "evreq",      V_88F6810_PLUS),
259		 MPP_VAR_FUNCTION(2, "ge1",   "rxd1",       V_88F6810_PLUS),
260		 MPP_VAR_FUNCTION(3, "ref",   "clk_out0",   V_88F6810_PLUS),
261		 MPP_VAR_FUNCTION(4, "sd0",   "d0",         V_88F6810_PLUS),
262		 MPP_VAR_FUNCTION(5, "dev",   "ad4",        V_88F6810_PLUS)),
263	MPP_MODE("mpp39",
264		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
265		 MPP_VAR_FUNCTION(1, "i2c1",  "sck",        V_88F6810_PLUS),
266		 MPP_VAR_FUNCTION(2, "ge1",   "rxd2",       V_88F6810_PLUS),
267		 MPP_VAR_FUNCTION(3, "ua0",   "cts",        V_88F6810_PLUS),
268		 MPP_VAR_FUNCTION(4, "sd0",   "d1",         V_88F6810_PLUS),
269		 MPP_VAR_FUNCTION(5, "dev",   "a2",         V_88F6810_PLUS)),
270	MPP_MODE("mpp40",
271		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
272		 MPP_VAR_FUNCTION(1, "i2c1",  "sda",        V_88F6810_PLUS),
273		 MPP_VAR_FUNCTION(2, "ge1",   "rxd3",       V_88F6810_PLUS),
274		 MPP_VAR_FUNCTION(3, "ua0",   "rts",        V_88F6810_PLUS),
275		 MPP_VAR_FUNCTION(4, "sd0",   "d2",         V_88F6810_PLUS),
276		 MPP_VAR_FUNCTION(5, "dev",   "ad6",        V_88F6810_PLUS)),
277	MPP_MODE("mpp41",
278		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
279		 MPP_VAR_FUNCTION(1, "ua1",   "rxd",        V_88F6810_PLUS),
280		 MPP_VAR_FUNCTION(2, "ge1",   "rxctl",      V_88F6810_PLUS),
281		 MPP_VAR_FUNCTION(3, "ua0",   "cts",        V_88F6810_PLUS),
282		 MPP_VAR_FUNCTION(4, "spi1",  "cs3",        V_88F6810_PLUS),
283		 MPP_VAR_FUNCTION(5, "dev",   "burst/last", V_88F6810_PLUS),
284		 MPP_VAR_FUNCTION(6, "nand",  "rb0",        V_88F6810_PLUS)),
285	MPP_MODE("mpp42",
286		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
287		 MPP_VAR_FUNCTION(1, "ua1",   "txd",        V_88F6810_PLUS),
288		 MPP_VAR_FUNCTION(3, "ua0",   "rts",        V_88F6810_PLUS),
289		 MPP_VAR_FUNCTION(5, "dev",   "ad7",        V_88F6810_PLUS)),
290	MPP_MODE("mpp43",
291		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
292		 MPP_VAR_FUNCTION(1, "pcie0", "clkreq",     V_88F6810_PLUS),
293		 MPP_VAR_FUNCTION(2, "dram",  "vttctrl",    V_88F6810_PLUS),
294		 MPP_VAR_FUNCTION(3, "dram",  "deccerr",    V_88F6810_PLUS),
295		 MPP_VAR_FUNCTION(4, "spi1",  "cs2",        V_88F6810_PLUS),
296		 MPP_VAR_FUNCTION(5, "dev",   "clkout",     V_88F6810_PLUS),
297		 MPP_VAR_FUNCTION(6, "nand",  "rb1",        V_88F6810_PLUS)),
298	MPP_MODE("mpp44",
299		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
300		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
301		 MPP_VAR_FUNCTION(2, "sata1", "prsnt",      V_88F6810_PLUS),
302		 MPP_VAR_FUNCTION(3, "sata2", "prsnt",      V_88F6828),
303		 MPP_VAR_FUNCTION(4, "sata3", "prsnt",      V_88F6828)),
304	MPP_MODE("mpp45",
305		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
306		 MPP_VAR_FUNCTION(1, "ref",   "clk_out0",   V_88F6810_PLUS),
307		 MPP_VAR_FUNCTION(2, "pcie0", "rstout",     V_88F6810_PLUS),
308		 MPP_VAR_FUNCTION(6, "ua1",   "rxd",        V_88F6810_PLUS)),
309	MPP_MODE("mpp46",
310		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
311		 MPP_VAR_FUNCTION(1, "ref",   "clk_out1",   V_88F6810_PLUS),
312		 MPP_VAR_FUNCTION(2, "pcie0", "rstout",     V_88F6810_PLUS),
313		 MPP_VAR_FUNCTION(6, "ua1",   "txd",        V_88F6810_PLUS)),
314	MPP_MODE("mpp47",
315		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
316		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
317		 MPP_VAR_FUNCTION(2, "sata1", "prsnt",      V_88F6810_PLUS),
318		 MPP_VAR_FUNCTION(3, "sata2", "prsnt",      V_88F6828),
319		 MPP_VAR_FUNCTION(5, "sata3", "prsnt",      V_88F6828)),
320	MPP_MODE("mpp48",
321		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
322		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
323		 MPP_VAR_FUNCTION(2, "dram",  "vttctrl",    V_88F6810_PLUS),
324		 MPP_VAR_FUNCTION(3, "tdm",   "pclk",       V_88F6810_PLUS),
325		 MPP_VAR_FUNCTION(4, "audio", "mclk",       V_88F6810_PLUS),
326		 MPP_VAR_FUNCTION(5, "sd0",   "d4",         V_88F6810_PLUS),
327		 MPP_VAR_FUNCTION(6, "pcie0", "clkreq",     V_88F6810_PLUS)),
328	MPP_MODE("mpp49",
329		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
330		 MPP_VAR_FUNCTION(1, "sata2", "prsnt",      V_88F6828),
331		 MPP_VAR_FUNCTION(2, "sata3", "prsnt",      V_88F6828),
332		 MPP_VAR_FUNCTION(3, "tdm",   "fsync",      V_88F6810_PLUS),
333		 MPP_VAR_FUNCTION(4, "audio", "lrclk",      V_88F6810_PLUS),
334		 MPP_VAR_FUNCTION(5, "sd0",   "d5",         V_88F6810_PLUS),
335		 MPP_VAR_FUNCTION(6, "pcie1", "clkreq",     V_88F6820_PLUS)),
336	MPP_MODE("mpp50",
337		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
338		 MPP_VAR_FUNCTION(1, "pcie0", "rstout",     V_88F6810_PLUS),
339		 MPP_VAR_FUNCTION(3, "tdm",   "drx",        V_88F6810_PLUS),
340		 MPP_VAR_FUNCTION(4, "audio", "extclk",     V_88F6810_PLUS),
341		 MPP_VAR_FUNCTION(5, "sd0",   "cmd",        V_88F6810_PLUS)),
342	MPP_MODE("mpp51",
343		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
344		 MPP_VAR_FUNCTION(3, "tdm",   "dtx",        V_88F6810_PLUS),
345		 MPP_VAR_FUNCTION(4, "audio", "sdo",        V_88F6810_PLUS),
346		 MPP_VAR_FUNCTION(5, "dram",  "deccerr",    V_88F6810_PLUS),
347		 MPP_VAR_FUNCTION(6, "ptp",   "trig",       V_88F6810_PLUS)),
348	MPP_MODE("mpp52",
349		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
350		 MPP_VAR_FUNCTION(1, "pcie0", "rstout",     V_88F6810_PLUS),
351		 MPP_VAR_FUNCTION(3, "tdm",   "int",        V_88F6810_PLUS),
352		 MPP_VAR_FUNCTION(4, "audio", "sdi",        V_88F6810_PLUS),
353		 MPP_VAR_FUNCTION(5, "sd0",   "d6",         V_88F6810_PLUS),
354		 MPP_VAR_FUNCTION(6, "ptp",   "clk",        V_88F6810_PLUS)),
355	MPP_MODE("mpp53",
356		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
357		 MPP_VAR_FUNCTION(1, "sata1", "prsnt",      V_88F6810_PLUS),
358		 MPP_VAR_FUNCTION(2, "sata0", "prsnt",      V_88F6810_PLUS),
359		 MPP_VAR_FUNCTION(3, "tdm",   "rst",        V_88F6810_PLUS),
360		 MPP_VAR_FUNCTION(4, "audio", "bclk",       V_88F6810_PLUS),
361		 MPP_VAR_FUNCTION(5, "sd0",   "d7",         V_88F6810_PLUS),
362		 MPP_VAR_FUNCTION(6, "ptp",   "evreq",      V_88F6810_PLUS)),
363	MPP_MODE("mpp54",
364		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
365		 MPP_VAR_FUNCTION(1, "sata0", "prsnt",      V_88F6810_PLUS),
366		 MPP_VAR_FUNCTION(2, "sata1", "prsnt",      V_88F6810_PLUS),
367		 MPP_VAR_FUNCTION(3, "pcie0", "rstout",     V_88F6810_PLUS),
368		 MPP_VAR_FUNCTION(4, "ge0",   "txerr",      V_88F6810_PLUS),
369		 MPP_VAR_FUNCTION(5, "sd0",   "d3",         V_88F6810_PLUS)),
370	MPP_MODE("mpp55",
371		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
372		 MPP_VAR_FUNCTION(1, "ua1",   "cts",        V_88F6810_PLUS),
373		 MPP_VAR_FUNCTION(2, "ge",    "mdio",       V_88F6810_PLUS),
374		 MPP_VAR_FUNCTION(3, "pcie1", "clkreq",     V_88F6820_PLUS),
375		 MPP_VAR_FUNCTION(4, "spi1",  "cs1",        V_88F6810_PLUS),
376		 MPP_VAR_FUNCTION(5, "sd0",   "d0",         V_88F6810_PLUS),
377		 MPP_VAR_FUNCTION(6, "ua1",   "rxd",        V_88F6810_PLUS)),
378	MPP_MODE("mpp56",
379		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
380		 MPP_VAR_FUNCTION(1, "ua1",   "rts",        V_88F6810_PLUS),
381		 MPP_VAR_FUNCTION(2, "ge",    "mdc",        V_88F6810_PLUS),
382		 MPP_VAR_FUNCTION(3, "dram",  "deccerr",    V_88F6810_PLUS),
383		 MPP_VAR_FUNCTION(4, "spi1",  "mosi",       V_88F6810_PLUS),
384		 MPP_VAR_FUNCTION(6, "ua1",   "txd",        V_88F6810_PLUS)),
385	MPP_MODE("mpp57",
386		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
387		 MPP_VAR_FUNCTION(4, "spi1",  "sck",        V_88F6810_PLUS),
388		 MPP_VAR_FUNCTION(5, "sd0",   "clk",        V_88F6810_PLUS),
389		 MPP_VAR_FUNCTION(6, "ua1",   "txd",        V_88F6810_PLUS)),
390	MPP_MODE("mpp58",
391		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
392		 MPP_VAR_FUNCTION(1, "pcie1", "clkreq",     V_88F6820_PLUS),
393		 MPP_VAR_FUNCTION(2, "i2c1",  "sck",        V_88F6810_PLUS),
394		 MPP_VAR_FUNCTION(3, "pcie2", "clkreq",     V_88F6810_PLUS),
395		 MPP_VAR_FUNCTION(4, "spi1",  "miso",       V_88F6810_PLUS),
396		 MPP_VAR_FUNCTION(5, "sd0",   "d1",         V_88F6810_PLUS),
397		 MPP_VAR_FUNCTION(6, "ua1",   "rxd",        V_88F6810_PLUS)),
398	MPP_MODE("mpp59",
399		 MPP_VAR_FUNCTION(0, "gpio",  NULL,         V_88F6810_PLUS),
400		 MPP_VAR_FUNCTION(1, "pcie0", "rstout",     V_88F6810_PLUS),
401		 MPP_VAR_FUNCTION(2, "i2c1",  "sda",        V_88F6810_PLUS),
402		 MPP_VAR_FUNCTION(4, "spi1",  "cs0",        V_88F6810_PLUS),
403		 MPP_VAR_FUNCTION(5, "sd0",   "d2",         V_88F6810_PLUS)),
404};
405
406static const char * const armada_38x_mpp_function_names[] = {
407	"gpio", /* make gpio always as function 0 */
408
409	"audio",
410	"dev",
411	"dram",
412	"ge",
413	"ge0",
414	"ge1",
415	"i2c0",
416	"i2c1",
417	"nand",
418	"pcie0",
419	"pcie1",
420	"pcie2",
421	"pcie3",
422	"ptp",
423	"ref",
424	"sata0",
425	"sata1",
426	"sata2",
427	"sata3",
428	"sd0",
429	"spi0",
430	"spi1",
431	"tdm",
432	"ua0",
433	"ua1",
434};
435
436struct armada_38x_pinctrl {
437	void __iomem *base;
438	u8 variant;
439};
440
441static int armada_38x_pinctrl_get_pins_count(struct udevice *dev)
442{
443	return ARRAY_SIZE(armada_38x_mpp_modes);
444}
445
446static const char *armada_38x_pinctrl_get_pin_name(struct udevice *dev, unsigned int selector)
447{
448	return armada_38x_mpp_modes[selector].name;
449}
450
451static int armada_38x_pinctrl_get_functions_count(struct udevice *dev)
452{
453	return ARRAY_SIZE(armada_38x_mpp_function_names);
454}
455
456static const char *armada_38x_pinctrl_get_function_name(struct udevice *dev, unsigned int selector)
457{
458	return armada_38x_mpp_function_names[selector];
459}
460
461static int armada_38x_pinctrl_get_pin_muxing(struct udevice *dev, unsigned int selector,
462					     char *buf, int size)
463{
464	struct armada_38x_pinctrl *info = dev_get_priv(dev);
465	unsigned int off = (selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
466	unsigned int shift = (selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
467	const char *func_name = NULL;
468	const char *sub_name = NULL;
469	unsigned long config;
470	int i;
471
472	config = (readl(info->base + off) >> shift) & MVEBU_MPP_MASK;
473
474	for (i = 0; i < armada_38x_mpp_modes[selector].nsettings; i++) {
475		if (armada_38x_mpp_modes[selector].settings[i].val == config)
476			break;
477	}
478
479	if (i < armada_38x_mpp_modes[selector].nsettings) {
480		func_name = armada_38x_mpp_modes[selector].settings[i].name;
481		sub_name = armada_38x_mpp_modes[selector].settings[i].subname;
482	}
483
484	snprintf(buf, size, "%s%s%s",
485		 func_name ? func_name : "unknown",
486		 sub_name ? "_" : "",
487		 sub_name ? sub_name : "");
488	return 0;
489}
490
491static int armada_38x_pinctrl_pinmux_set(struct udevice *dev, unsigned int pin_selector,
492					 unsigned int func_selector)
493{
494	struct armada_38x_pinctrl *info = dev_get_priv(dev);
495	unsigned int off = (pin_selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
496	unsigned int shift = (pin_selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
497	const char *func_name = armada_38x_mpp_function_names[func_selector];
498	unsigned long config, reg;
499	int i;
500
501	for (i = 0; i < armada_38x_mpp_modes[pin_selector].nsettings; i++) {
502		if (strcmp(armada_38x_mpp_modes[pin_selector].settings[i].name, func_name) == 0)
503			break;
504	}
505
506	if (i >= armada_38x_mpp_modes[pin_selector].nsettings)
507		return -EINVAL;
508
509	if (!(info->variant & armada_38x_mpp_modes[pin_selector].settings[i].variant))
510		return -EINVAL;
511
512	reg = readl(info->base + off) & ~(MVEBU_MPP_MASK << shift);
513	config = armada_38x_mpp_modes[pin_selector].settings[i].val;
514	writel(reg | (config << shift), info->base + off);
515
516	return 0;
517}
518
519static int armada_38x_pinctrl_gpio_request_enable(struct udevice *dev, unsigned int selector)
520{
521	char buf[20];
522
523	armada_38x_pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf));
524	if (strcmp(buf, "gpio") != 0)
525		printf("Warning: Changing mpp%u function from %s to gpio...\n", selector, buf);
526
527	return armada_38x_pinctrl_pinmux_set(dev, selector, 0); /* gpio is always function 0 */
528}
529
530static int armada_38x_pinctrl_gpio_disable_free(struct udevice *dev, unsigned int selector)
531{
532	/* nothing to do */
533	return 0;
534}
535
536static int armada_38x_pinctrl_set_state(struct udevice *dev, struct udevice *config)
537{
538	return pinctrl_generic_set_state_prefix(dev, config, "marvell,");
539}
540
541static int armada_38x_pinctrl_probe(struct udevice *dev)
542{
543	struct armada_38x_pinctrl *info = dev_get_priv(dev);
544
545	info->variant = (u8)dev_get_driver_data(dev);
546	info->base = dev_read_addr_ptr(dev);
547
548	if (!info->base)
549		return -EINVAL;
550
551	return 0;
552}
553
554struct pinctrl_ops armada_37xx_pinctrl_ops = {
555	.get_pins_count = armada_38x_pinctrl_get_pins_count,
556	.get_pin_name = armada_38x_pinctrl_get_pin_name,
557	.get_functions_count = armada_38x_pinctrl_get_functions_count,
558	.get_function_name = armada_38x_pinctrl_get_function_name,
559	.get_pin_muxing = armada_38x_pinctrl_get_pin_muxing,
560	.pinmux_set = armada_38x_pinctrl_pinmux_set,
561	.gpio_request_enable = armada_38x_pinctrl_gpio_request_enable,
562	.gpio_disable_free = armada_38x_pinctrl_gpio_disable_free,
563	.set_state = armada_38x_pinctrl_set_state,
564};
565
566static const struct udevice_id armada_38x_pinctrl_of_match[] = {
567	{
568		.compatible = "marvell,mv88f6810-pinctrl",
569		.data       = V_88F6810,
570	},
571	{
572		.compatible = "marvell,mv88f6820-pinctrl",
573		.data       = V_88F6820,
574	},
575	{
576		.compatible = "marvell,mv88f6828-pinctrl",
577		.data       = V_88F6828,
578	},
579	{ },
580};
581
582U_BOOT_DRIVER(armada_38x_pinctrl) = {
583	.name = "armada-38x-pinctrl",
584	.id = UCLASS_PINCTRL,
585	.of_match = of_match_ptr(armada_38x_pinctrl_of_match),
586	.probe = armada_38x_pinctrl_probe,
587	.priv_auto = sizeof(struct armada_38x_pinctrl),
588	.ops = &armada_37xx_pinctrl_ops,
589};
590