aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesper Nilsson <jesper.nilsson@axis.com>2017-04-03 08:47:04 -0400
committerLinus Walleij <linus.walleij@linaro.org>2017-04-07 05:48:33 -0400
commit00df0582eab1294d10ca615a8ef645e0bb57a6e3 (patch)
tree95377862fb395181c05918e30d7c49c20e150d1d
parent9c6c149be390e02a5ac6ace4efb9f03716431bbe (diff)
pinctrl: Add pincontrol driver for ARTPEC-6 SoC
Add pinctrl driver support for the Axis ARTPEC-6 SoC. There are only some pins that actually have different functions available, but all can control bias (pull-up/-down) and drive strength. Code originally written by Chris Paterson. Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/pinctrl/Kconfig11
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/pinctrl-artpec6.c992
4 files changed, 1005 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index ed5731a8f5b8..1d5bc9757dc1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1088,6 +1088,7 @@ L: linux-arm-kernel@axis.com
1088F: arch/arm/mach-artpec 1088F: arch/arm/mach-artpec
1089F: arch/arm/boot/dts/artpec6* 1089F: arch/arm/boot/dts/artpec6*
1090F: drivers/clk/axis 1090F: drivers/clk/axis
1091F: drivers/pinctrl/pinctrl-artpec*
1091F: Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt 1092F: Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt
1092 1093
1093ARM/ASPEED MACHINE SUPPORT 1094ARM/ASPEED MACHINE SUPPORT
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8f8c2af45781..37af5e3029d5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -41,6 +41,17 @@ config PINCTRL_ADI2
41 future processors. This option is selected automatically when specific 41 future processors. This option is selected automatically when specific
42 machine and arch are selected to build. 42 machine and arch are selected to build.
43 43
44config PINCTRL_ARTPEC6
45 bool "Axis ARTPEC-6 pin controller driver"
46 depends on MACH_ARTPEC6
47 select PINMUX
48 select GENERIC_PINCONF
49 help
50 This is the driver for the Axis ARTPEC-6 pin controller. This driver
51 supports pin function multiplexing as well as pin bias and drive
52 strength configuration. Device tree integration instructions can be
53 found in Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt
54
44config PINCTRL_AS3722 55config PINCTRL_AS3722
45 tristate "Pinctrl and GPIO driver for ams AS3722 PMIC" 56 tristate "Pinctrl and GPIO driver for ams AS3722 PMIC"
46 depends on MFD_AS3722 && GPIOLIB 57 depends on MFD_AS3722 && GPIOLIB
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index a251f439626f..5fc3c1ddd86f 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCONF) += pinconf.o
8obj-$(CONFIG_OF) += devicetree.o 8obj-$(CONFIG_OF) += devicetree.o
9obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o 9obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
10obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o 10obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o
11obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o
11obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o 12obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
12obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o 13obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
13obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o 14obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
diff --git a/drivers/pinctrl/pinctrl-artpec6.c b/drivers/pinctrl/pinctrl-artpec6.c
new file mode 100644
index 000000000000..b5a2eff7ae3d
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-artpec6.c
@@ -0,0 +1,992 @@
1/*
2 * Driver for the Axis ARTPEC-6 pin controller
3 *
4 * Author: Chris Paterson <chris.paterson@linux.pieboy.co.uk>
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#include <linux/device.h>
12#include <linux/err.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/platform_device.h>
18#include <linux/pinctrl/pinctrl.h>
19#include <linux/pinctrl/pinconf-generic.h>
20#include <linux/pinctrl/pinconf.h>
21#include <linux/pinctrl/pinmux.h>
22#include <linux/slab.h>
23#include "core.h"
24#include "pinconf.h"
25#include "pinctrl-utils.h"
26
27#define ARTPEC6_LAST_PIN 97 /* 97 pins in pinmux */
28#define ARTPEC6_MAX_MUXABLE 35 /* Last pin with muxable function */
29
30/* Pinmux control register bit definitions */
31#define ARTPEC6_PINMUX_UDC0_MASK 0x00000001
32#define ARTPEC6_PINMUX_UDC0_SHIFT 0
33#define ARTPEC6_PINMUX_UDC1_MASK 0x00000002
34#define ARTPEC6_PINMUX_UDC1_SHIFT 1
35#define ARTPEC6_PINMUX_DRV_MASK 0x00000060
36#define ARTPEC6_PINMUX_DRV_SHIFT 5
37#define ARTPEC6_PINMUX_SEL_MASK 0x00003000
38#define ARTPEC6_PINMUX_SEL_SHIFT 12
39
40/* Pinmux configurations */
41#define ARTPEC6_CONFIG_0 0
42#define ARTPEC6_CONFIG_1 1
43#define ARTPEC6_CONFIG_2 2
44#define ARTPEC6_CONFIG_3 3
45
46/* Pin drive strength options */
47#define ARTPEC6_DRIVE_4mA 4
48#define ARTPEC6_DRIVE_4mA_SET 0
49#define ARTPEC6_DRIVE_6mA 6
50#define ARTPEC6_DRIVE_6mA_SET 1
51#define ARTPEC6_DRIVE_8mA 8
52#define ARTPEC6_DRIVE_8mA_SET 2
53#define ARTPEC6_DRIVE_9mA 9
54#define ARTPEC6_DRIVE_9mA_SET 3
55
56struct artpec6_pmx {
57 struct device *dev;
58 struct pinctrl_dev *pctl;
59 void __iomem *base;
60 struct pinctrl_pin_desc *pins;
61 unsigned int num_pins;
62 const struct artpec6_pin_group *pin_groups;
63 unsigned int num_pin_groups;
64 const struct artpec6_pmx_func *functions;
65 unsigned int num_functions;
66};
67
68struct artpec6_pin_group {
69 const char *name;
70 const unsigned int *pins;
71 const unsigned int num_pins;
72 unsigned char config;
73};
74
75struct artpec6_pmx_func {
76 const char *name;
77 const char * const *groups;
78 const unsigned int num_groups;
79};
80
81/* pins */
82static struct pinctrl_pin_desc artpec6_pins[] = {
83 PINCTRL_PIN(0, "GPIO0"),
84 PINCTRL_PIN(1, "GPIO1"),
85 PINCTRL_PIN(2, "GPIO2"),
86 PINCTRL_PIN(3, "GPIO3"),
87 PINCTRL_PIN(4, "GPIO4"),
88 PINCTRL_PIN(5, "GPIO5"),
89 PINCTRL_PIN(6, "GPIO6"),
90 PINCTRL_PIN(7, "GPIO7"),
91 PINCTRL_PIN(8, "GPIO8"),
92 PINCTRL_PIN(9, "GPIO9"),
93 PINCTRL_PIN(10, "GPIO10"),
94 PINCTRL_PIN(11, "GPIO11"),
95 PINCTRL_PIN(12, "GPIO12"),
96 PINCTRL_PIN(13, "GPIO13"),
97 PINCTRL_PIN(14, "GPIO14"),
98 PINCTRL_PIN(15, "GPIO15"),
99 PINCTRL_PIN(16, "GPIO16"),
100 PINCTRL_PIN(17, "GPIO17"),
101 PINCTRL_PIN(18, "GPIO18"),
102 PINCTRL_PIN(19, "GPIO19"),
103 PINCTRL_PIN(20, "GPIO20"),
104 PINCTRL_PIN(21, "GPIO21"),
105 PINCTRL_PIN(22, "GPIO22"),
106 PINCTRL_PIN(23, "GPIO23"),
107 PINCTRL_PIN(24, "GPIO24"),
108 PINCTRL_PIN(25, "GPIO25"),
109 PINCTRL_PIN(26, "GPIO26"),
110 PINCTRL_PIN(27, "GPIO27"),
111 PINCTRL_PIN(28, "GPIO28"),
112 PINCTRL_PIN(29, "GPIO29"),
113 PINCTRL_PIN(30, "GPIO30"),
114 PINCTRL_PIN(31, "GPIO31"),
115 PINCTRL_PIN(32, "UART3_TXD"),
116 PINCTRL_PIN(33, "UART3_RXD"),
117 PINCTRL_PIN(34, "UART3_RTS"),
118 PINCTRL_PIN(35, "UART3_CTS"),
119 PINCTRL_PIN(36, "NF_ALE"),
120 PINCTRL_PIN(37, "NF_CE0_N"),
121 PINCTRL_PIN(38, "NF_CE1_N"),
122 PINCTRL_PIN(39, "NF_CLE"),
123 PINCTRL_PIN(40, "NF_RE_N"),
124 PINCTRL_PIN(41, "NF_WE_N"),
125 PINCTRL_PIN(42, "NF_WP0_N"),
126 PINCTRL_PIN(43, "NF_WP1_N"),
127 PINCTRL_PIN(44, "NF_IO0"),
128 PINCTRL_PIN(45, "NF_IO1"),
129 PINCTRL_PIN(46, "NF_IO2"),
130 PINCTRL_PIN(47, "NF_IO3"),
131 PINCTRL_PIN(48, "NF_IO4"),
132 PINCTRL_PIN(49, "NF_IO5"),
133 PINCTRL_PIN(50, "NF_IO6"),
134 PINCTRL_PIN(51, "NF_IO7"),
135 PINCTRL_PIN(52, "NF_RB0_N"),
136 PINCTRL_PIN(53, "SDIO0_CLK"),
137 PINCTRL_PIN(54, "SDIO0_CMD"),
138 PINCTRL_PIN(55, "SDIO0_DAT0"),
139 PINCTRL_PIN(56, "SDIO0_DAT1"),
140 PINCTRL_PIN(57, "SDIO0_DAT2"),
141 PINCTRL_PIN(58, "SDIO0_DAT3"),
142 PINCTRL_PIN(59, "SDI0_CD"),
143 PINCTRL_PIN(60, "SDI0_WP"),
144 PINCTRL_PIN(61, "SDIO1_CLK"),
145 PINCTRL_PIN(62, "SDIO1_CMD"),
146 PINCTRL_PIN(63, "SDIO1_DAT0"),
147 PINCTRL_PIN(64, "SDIO1_DAT1"),
148 PINCTRL_PIN(65, "SDIO1_DAT2"),
149 PINCTRL_PIN(66, "SDIO1_DAT3"),
150 PINCTRL_PIN(67, "SDIO1_CD"),
151 PINCTRL_PIN(68, "SDIO1_WP"),
152 PINCTRL_PIN(69, "GBE_REFCLk"),
153 PINCTRL_PIN(70, "GBE_GTX_CLK"),
154 PINCTRL_PIN(71, "GBE_TX_CLK"),
155 PINCTRL_PIN(72, "GBE_TX_EN"),
156 PINCTRL_PIN(73, "GBE_TX_ER"),
157 PINCTRL_PIN(74, "GBE_TXD0"),
158 PINCTRL_PIN(75, "GBE_TXD1"),
159 PINCTRL_PIN(76, "GBE_TXD2"),
160 PINCTRL_PIN(77, "GBE_TXD3"),
161 PINCTRL_PIN(78, "GBE_TXD4"),
162 PINCTRL_PIN(79, "GBE_TXD5"),
163 PINCTRL_PIN(80, "GBE_TXD6"),
164 PINCTRL_PIN(81, "GBE_TXD7"),
165 PINCTRL_PIN(82, "GBE_RX_CLK"),
166 PINCTRL_PIN(83, "GBE_RX_DV"),
167 PINCTRL_PIN(84, "GBE_RX_ER"),
168 PINCTRL_PIN(85, "GBE_RXD0"),
169 PINCTRL_PIN(86, "GBE_RXD1"),
170 PINCTRL_PIN(87, "GBE_RXD2"),
171 PINCTRL_PIN(88, "GBE_RXD3"),
172 PINCTRL_PIN(89, "GBE_RXD4"),
173 PINCTRL_PIN(90, "GBE_RXD5"),
174 PINCTRL_PIN(91, "GBE_RXD6"),
175 PINCTRL_PIN(92, "GBE_RXD7"),
176 PINCTRL_PIN(93, "GBE_CRS"),
177 PINCTRL_PIN(94, "GBE_COL"),
178 PINCTRL_PIN(95, "GBE_MDC"),
179 PINCTRL_PIN(96, "GBE_MDIO"),
180};
181
182static const unsigned int cpuclkout_pins0[] = { 0 };
183static const unsigned int udlclkout_pins0[] = { 1 };
184static const unsigned int i2c1_pins0[] = { 2, 3 };
185static const unsigned int i2c2_pins0[] = { 4, 5 };
186static const unsigned int i2c3_pins0[] = { 6, 7 };
187static const unsigned int i2s0_pins0[] = { 8, 9, 10, 11 };
188static const unsigned int i2s1_pins0[] = { 12, 13, 14, 15 };
189static const unsigned int i2srefclk_pins0[] = { 19 };
190static const unsigned int spi0_pins0[] = { 12, 13, 14, 15 };
191static const unsigned int spi1_pins0[] = { 16, 17, 18, 19 };
192static const unsigned int pciedebug_pins0[] = { 12, 13, 14, 15 };
193static const unsigned int uart0_pins0[] = { 16, 17, 18, 19, 20,
194 21, 22, 23, 24, 25 };
195static const unsigned int uart0_pins1[] = { 20, 21, 22, 23 };
196static const unsigned int uart1_pins0[] = { 24, 25, 26, 27 };
197static const unsigned int uart2_pins0[] = { 26, 27, 28, 29, 30,
198 31, 32, 33, 34, 35 };
199static const unsigned int uart2_pins1[] = { 28, 29, 30, 31 };
200static const unsigned int uart3_pins0[] = { 32, 33, 34, 35 };
201static const unsigned int uart4_pins0[] = { 20, 21, 22, 23 };
202static const unsigned int uart5_pins0[] = { 28, 29, 30, 31 };
203static const unsigned int nand_pins0[] = { 36, 37, 38, 39, 40, 41,
204 42, 43, 44, 45, 46, 47,
205 48, 49, 50, 51, 52 };
206static const unsigned int sdio0_pins0[] = { 53, 54, 55, 56, 57, 58, 59, 60 };
207static const unsigned int sdio1_pins0[] = { 61, 62, 63, 64, 65, 66, 67, 68 };
208static const unsigned int ethernet_pins0[] = { 69, 70, 71, 72, 73, 74, 75,
209 76, 77, 78, 79, 80, 81, 82,
210 83, 84, 85, 86, 87, 88, 89,
211 90, 91, 92, 93, 94, 95, 96 };
212
213static const struct artpec6_pin_group artpec6_pin_groups[] = {
214 {
215 .name = "cpuclkoutgrp0",
216 .pins = cpuclkout_pins0,
217 .num_pins = ARRAY_SIZE(cpuclkout_pins0),
218 .config = ARTPEC6_CONFIG_1,
219 },
220 {
221 .name = "udlclkoutgrp0",
222 .pins = udlclkout_pins0,
223 .num_pins = ARRAY_SIZE(udlclkout_pins0),
224 .config = ARTPEC6_CONFIG_1,
225 },
226 {
227 .name = "i2c1grp0",
228 .pins = i2c1_pins0,
229 .num_pins = ARRAY_SIZE(i2c1_pins0),
230 .config = ARTPEC6_CONFIG_1,
231 },
232 {
233 .name = "i2c2grp0",
234 .pins = i2c2_pins0,
235 .num_pins = ARRAY_SIZE(i2c2_pins0),
236 .config = ARTPEC6_CONFIG_1,
237 },
238 {
239 .name = "i2c3grp0",
240 .pins = i2c3_pins0,
241 .num_pins = ARRAY_SIZE(i2c3_pins0),
242 .config = ARTPEC6_CONFIG_1,
243 },
244 {
245 .name = "i2s0grp0",
246 .pins = i2s0_pins0,
247 .num_pins = ARRAY_SIZE(i2s0_pins0),
248 .config = ARTPEC6_CONFIG_1,
249 },
250 {
251 .name = "i2s1grp0",
252 .pins = i2s1_pins0,
253 .num_pins = ARRAY_SIZE(i2s1_pins0),
254 .config = ARTPEC6_CONFIG_1,
255 },
256 {
257 .name = "i2srefclkgrp0",
258 .pins = i2srefclk_pins0,
259 .num_pins = ARRAY_SIZE(i2srefclk_pins0),
260 .config = ARTPEC6_CONFIG_3,
261 },
262 {
263 .name = "spi0grp0",
264 .pins = spi0_pins0,
265 .num_pins = ARRAY_SIZE(spi0_pins0),
266 .config = ARTPEC6_CONFIG_2,
267 },
268 {
269 .name = "spi1grp0",
270 .pins = spi1_pins0,
271 .num_pins = ARRAY_SIZE(spi1_pins0),
272 .config = ARTPEC6_CONFIG_2,
273 },
274 {
275 .name = "pciedebuggrp0",
276 .pins = pciedebug_pins0,
277 .num_pins = ARRAY_SIZE(pciedebug_pins0),
278 .config = ARTPEC6_CONFIG_3,
279 },
280 {
281 .name = "uart0grp0",
282 .pins = uart0_pins0,
283 .num_pins = ARRAY_SIZE(uart0_pins0),
284 .config = ARTPEC6_CONFIG_1,
285 },
286 {
287 .name = "uart0grp1",
288 .pins = uart0_pins1,
289 .num_pins = ARRAY_SIZE(uart0_pins1),
290 .config = ARTPEC6_CONFIG_1,
291 },
292 {
293 .name = "uart1grp0",
294 .pins = uart1_pins0,
295 .num_pins = ARRAY_SIZE(uart1_pins0),
296 .config = ARTPEC6_CONFIG_2,
297 },
298 {
299 .name = "uart2grp0",
300 .pins = uart2_pins0,
301 .num_pins = ARRAY_SIZE(uart2_pins0),
302 .config = ARTPEC6_CONFIG_1,
303 },
304 {
305 .name = "uart2grp1",
306 .pins = uart2_pins1,
307 .num_pins = ARRAY_SIZE(uart2_pins1),
308 .config = ARTPEC6_CONFIG_1,
309 },
310 {
311 .name = "uart3grp0",
312 .pins = uart3_pins0,
313 .num_pins = ARRAY_SIZE(uart3_pins0),
314 .config = ARTPEC6_CONFIG_0,
315 },
316 {
317 .name = "uart4grp0",
318 .pins = uart4_pins0,
319 .num_pins = ARRAY_SIZE(uart4_pins0),
320 .config = ARTPEC6_CONFIG_2,
321 },
322 {
323 .name = "uart5grp0",
324 .pins = uart5_pins0,
325 .num_pins = ARRAY_SIZE(uart5_pins0),
326 .config = ARTPEC6_CONFIG_2,
327 },
328 {
329 .name = "uart5nocts",
330 .pins = uart5_pins0,
331 .num_pins = ARRAY_SIZE(uart5_pins0) - 1,
332 .config = ARTPEC6_CONFIG_2,
333 },
334 {
335 .name = "nandgrp0",
336 .pins = nand_pins0,
337 .num_pins = ARRAY_SIZE(nand_pins0),
338 .config = ARTPEC6_CONFIG_0,
339 },
340 {
341 .name = "sdio0grp0",
342 .pins = sdio0_pins0,
343 .num_pins = ARRAY_SIZE(sdio0_pins0),
344 .config = ARTPEC6_CONFIG_0,
345 },
346 {
347 .name = "sdio1grp0",
348 .pins = sdio1_pins0,
349 .num_pins = ARRAY_SIZE(sdio1_pins0),
350 .config = ARTPEC6_CONFIG_0,
351 },
352 {
353 .name = "ethernetgrp0",
354 .pins = ethernet_pins0,
355 .num_pins = ARRAY_SIZE(ethernet_pins0),
356 .config = ARTPEC6_CONFIG_0,
357 },
358};
359
360struct pin_register {
361 unsigned int start;
362 unsigned int end;
363 unsigned int reg_base;
364};
365
366/*
367 * The register map has two holes where the pin number
368 * no longer fits directly with the register offset.
369 * This table allows us to map this easily.
370 */
371static const struct pin_register pin_register[] = {
372 { 0, 35, 0x0 }, /* 0x0 - 0x8c */
373 { 36, 52, 0x100 }, /* 0x100 - 0x140 */
374 { 53, 96, 0x180 }, /* 0x180 - 0x22c */
375};
376
377static unsigned int artpec6_pmx_reg_offset(unsigned int pin)
378{
379 int i;
380
381 for (i = 0; i < ARRAY_SIZE(pin_register); i++) {
382 if (pin <= pin_register[i].end) {
383 return (pin - pin_register[i].start) * 4 +
384 pin_register[i].reg_base;
385 }
386 }
387 /*
388 * Anything we return here is wrong, but we can only
389 * get here if pin is outside registered range.
390 */
391 pr_err("%s: Impossible pin %d\n", __func__, pin);
392 return 0;
393}
394
395static int artpec6_get_groups_count(struct pinctrl_dev *pctldev)
396{
397 return ARRAY_SIZE(artpec6_pin_groups);
398}
399
400static const char *artpec6_get_group_name(struct pinctrl_dev *pctldev,
401 unsigned int group)
402{
403 return artpec6_pin_groups[group].name;
404}
405
406static int artpec6_get_group_pins(struct pinctrl_dev *pctldev,
407 unsigned int group,
408 const unsigned int **pins,
409 unsigned int *num_pins)
410{
411 *pins = (unsigned int *)artpec6_pin_groups[group].pins;
412 *num_pins = artpec6_pin_groups[group].num_pins;
413 return 0;
414}
415
416static int artpec6_pconf_drive_mA_to_field(unsigned int mA)
417{
418 switch (mA) {
419 case ARTPEC6_DRIVE_4mA:
420 return ARTPEC6_DRIVE_4mA_SET;
421 case ARTPEC6_DRIVE_6mA:
422 return ARTPEC6_DRIVE_6mA_SET;
423 case ARTPEC6_DRIVE_8mA:
424 return ARTPEC6_DRIVE_8mA_SET;
425 case ARTPEC6_DRIVE_9mA:
426 return ARTPEC6_DRIVE_9mA_SET;
427 default:
428 return -EINVAL;
429 }
430}
431
432static unsigned int artpec6_pconf_drive_field_to_mA(int field)
433{
434 switch (field) {
435 case ARTPEC6_DRIVE_4mA_SET:
436 return ARTPEC6_DRIVE_4mA;
437 case ARTPEC6_DRIVE_6mA_SET:
438 return ARTPEC6_DRIVE_6mA;
439 case ARTPEC6_DRIVE_8mA_SET:
440 return ARTPEC6_DRIVE_8mA;
441 case ARTPEC6_DRIVE_9mA_SET:
442 return ARTPEC6_DRIVE_9mA;
443 default:
444 /* Shouldn't happen */
445 return 0;
446 }
447}
448
449static struct pinctrl_ops artpec6_pctrl_ops = {
450 .get_group_pins = artpec6_get_group_pins,
451 .get_groups_count = artpec6_get_groups_count,
452 .get_group_name = artpec6_get_group_name,
453 .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
454 .dt_free_map = pinctrl_utils_free_map,
455};
456
457static const char * const gpiogrps[] = {
458 "cpuclkoutgrp0", "udlclkoutgrp0", "i2c1grp0", "i2c2grp0",
459 "i2c3grp0", "i2s0grp0", "i2s1grp0", "i2srefclkgrp0",
460 "spi0grp0", "spi1grp0", "pciedebuggrp0", "uart0grp0",
461 "uart0grp1", "uart1grp0", "uart2grp0", "uart2grp1",
462 "uart4grp0", "uart5grp0",
463};
464static const char * const cpuclkoutgrps[] = { "cpuclkoutgrp0" };
465static const char * const udlclkoutgrps[] = { "udlclkoutgrp0" };
466static const char * const i2c1grps[] = { "i2c1grp0" };
467static const char * const i2c2grps[] = { "i2c2grp0" };
468static const char * const i2c3grps[] = { "i2c3grp0" };
469static const char * const i2s0grps[] = { "i2s0grp0" };
470static const char * const i2s1grps[] = { "i2s1grp0" };
471static const char * const i2srefclkgrps[] = { "i2srefclkgrp0" };
472static const char * const spi0grps[] = { "spi0grp0" };
473static const char * const spi1grps[] = { "spi1grp0" };
474static const char * const pciedebuggrps[] = { "pciedebuggrp0" };
475static const char * const uart0grps[] = { "uart0grp0", "uart0grp1" };
476static const char * const uart1grps[] = { "uart1grp0" };
477static const char * const uart2grps[] = { "uart2grp0", "uart2grp1" };
478static const char * const uart3grps[] = { "uart3grp0" };
479static const char * const uart4grps[] = { "uart4grp0" };
480static const char * const uart5grps[] = { "uart5grp0", "uart5nocts" };
481static const char * const nandgrps[] = { "nandgrp0" };
482static const char * const sdio0grps[] = { "sdio0grp0" };
483static const char * const sdio1grps[] = { "sdio1grp0" };
484static const char * const ethernetgrps[] = { "ethernetgrp0" };
485
486static const struct artpec6_pmx_func artpec6_pmx_functions[] = {
487 {
488 .name = "gpio",
489 .groups = gpiogrps,
490 .num_groups = ARRAY_SIZE(gpiogrps),
491 },
492 {
493 .name = "cpuclkout",
494 .groups = cpuclkoutgrps,
495 .num_groups = ARRAY_SIZE(cpuclkoutgrps),
496 },
497 {
498 .name = "udlclkout",
499 .groups = udlclkoutgrps,
500 .num_groups = ARRAY_SIZE(udlclkoutgrps),
501 },
502 {
503 .name = "i2c1",
504 .groups = i2c1grps,
505 .num_groups = ARRAY_SIZE(i2c1grps),
506 },
507 {
508 .name = "i2c2",
509 .groups = i2c2grps,
510 .num_groups = ARRAY_SIZE(i2c2grps),
511 },
512 {
513 .name = "i2c3",
514 .groups = i2c3grps,
515 .num_groups = ARRAY_SIZE(i2c3grps),
516 },
517 {
518 .name = "i2s0",
519 .groups = i2s0grps,
520 .num_groups = ARRAY_SIZE(i2s0grps),
521 },
522 {
523 .name = "i2s1",
524 .groups = i2s1grps,
525 .num_groups = ARRAY_SIZE(i2s1grps),
526 },
527 {
528 .name = "i2srefclk",
529 .groups = i2srefclkgrps,
530 .num_groups = ARRAY_SIZE(i2srefclkgrps),
531 },
532 {
533 .name = "spi0",
534 .groups = spi0grps,
535 .num_groups = ARRAY_SIZE(spi0grps),
536 },
537 {
538 .name = "spi1",
539 .groups = spi1grps,
540 .num_groups = ARRAY_SIZE(spi1grps),
541 },
542 {
543 .name = "pciedebug",
544 .groups = pciedebuggrps,
545 .num_groups = ARRAY_SIZE(pciedebuggrps),
546 },
547 {
548 .name = "uart0",
549 .groups = uart0grps,
550 .num_groups = ARRAY_SIZE(uart0grps),
551 },
552 {
553 .name = "uart1",
554 .groups = uart1grps,
555 .num_groups = ARRAY_SIZE(uart1grps),
556 },
557 {
558 .name = "uart2",
559 .groups = uart2grps,
560 .num_groups = ARRAY_SIZE(uart2grps),
561 },
562 {
563 .name = "uart3",
564 .groups = uart3grps,
565 .num_groups = ARRAY_SIZE(uart3grps),
566 },
567 {
568 .name = "uart4",
569 .groups = uart4grps,
570 .num_groups = ARRAY_SIZE(uart4grps),
571 },
572 {
573 .name = "uart5",
574 .groups = uart5grps,
575 .num_groups = ARRAY_SIZE(uart5grps),
576 },
577 {
578 .name = "nand",
579 .groups = nandgrps,
580 .num_groups = ARRAY_SIZE(nandgrps),
581 },
582 {
583 .name = "sdio0",
584 .groups = sdio0grps,
585 .num_groups = ARRAY_SIZE(sdio0grps),
586 },
587 {
588 .name = "sdio1",
589 .groups = sdio1grps,
590 .num_groups = ARRAY_SIZE(sdio1grps),
591 },
592 {
593 .name = "ethernet",
594 .groups = ethernetgrps,
595 .num_groups = ARRAY_SIZE(ethernetgrps),
596 },
597};
598
599static int artpec6_pmx_get_functions_count(struct pinctrl_dev *pctldev)
600{
601 return ARRAY_SIZE(artpec6_pmx_functions);
602}
603
604static const char *artpec6_pmx_get_fname(struct pinctrl_dev *pctldev,
605 unsigned int function)
606{
607 return artpec6_pmx_functions[function].name;
608}
609
610static int artpec6_pmx_get_fgroups(struct pinctrl_dev *pctldev,
611 unsigned int function,
612 const char * const **groups,
613 unsigned int * const num_groups)
614{
615 *groups = artpec6_pmx_functions[function].groups;
616 *num_groups = artpec6_pmx_functions[function].num_groups;
617 return 0;
618}
619
620static void artpec6_pmx_select_func(struct pinctrl_dev *pctldev,
621 unsigned int function, unsigned int group,
622 bool enable)
623{
624 unsigned int regval, val;
625 unsigned int reg;
626 int i;
627 struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
628
629 for (i = 0; i < artpec6_pin_groups[group].num_pins; i++) {
630 /*
631 * Registers for pins above a ARTPEC6_MAX_MUXABLE
632 * do not have a SEL field and are always selected.
633 */
634 if (artpec6_pin_groups[group].pins[i] > ARTPEC6_MAX_MUXABLE)
635 continue;
636
637 if (!strcmp(artpec6_pmx_get_fname(pctldev, function), "gpio")) {
638 /* GPIO is always config 0 */
639 val = ARTPEC6_CONFIG_0 << ARTPEC6_PINMUX_SEL_SHIFT;
640 } else {
641 if (enable)
642 val = artpec6_pin_groups[group].config
643 << ARTPEC6_PINMUX_SEL_SHIFT;
644 else
645 val = ARTPEC6_CONFIG_0
646 << ARTPEC6_PINMUX_SEL_SHIFT;
647 }
648
649 reg = artpec6_pmx_reg_offset(artpec6_pin_groups[group].pins[i]);
650
651 regval = readl(pmx->base + reg);
652 regval &= ~ARTPEC6_PINMUX_SEL_MASK;
653 regval |= val;
654 writel(regval, pmx->base + reg);
655 }
656}
657
658int artpec6_pmx_enable(struct pinctrl_dev *pctldev, unsigned int function,
659 unsigned int group)
660{
661 struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
662
663 dev_dbg(pmx->dev, "enabling %s function for pin group %s\n",
664 artpec6_pmx_get_fname(pctldev, function),
665 artpec6_get_group_name(pctldev, group));
666
667 artpec6_pmx_select_func(pctldev, function, group, true);
668
669 return 0;
670}
671
672void artpec6_pmx_disable(struct pinctrl_dev *pctldev, unsigned int function,
673 unsigned int group)
674{
675 struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
676
677 dev_dbg(pmx->dev, "disabling %s function for pin group %s\n",
678 artpec6_pmx_get_fname(pctldev, function),
679 artpec6_get_group_name(pctldev, group));
680
681 artpec6_pmx_select_func(pctldev, function, group, false);
682}
683
684static int artpec6_pmx_request_gpio(struct pinctrl_dev *pctldev,
685 struct pinctrl_gpio_range *range,
686 unsigned int pin)
687{
688 struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
689 unsigned int reg = artpec6_pmx_reg_offset(pin);
690 u32 val;
691
692 if (pin >= 32)
693 return -EINVAL;
694
695 val = readl_relaxed(pmx->base + reg);
696 val &= ~ARTPEC6_PINMUX_SEL_MASK;
697 val |= ARTPEC6_CONFIG_0 << ARTPEC6_PINMUX_SEL_SHIFT;
698 writel_relaxed(val, pmx->base + reg);
699
700 return 0;
701}
702
703static const struct pinmux_ops artpec6_pmx_ops = {
704 .get_functions_count = artpec6_pmx_get_functions_count,
705 .get_function_name = artpec6_pmx_get_fname,
706 .get_function_groups = artpec6_pmx_get_fgroups,
707 .set_mux = artpec6_pmx_enable,
708 .gpio_request_enable = artpec6_pmx_request_gpio,
709};
710
711static int artpec6_pconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
712 unsigned long *config)
713{
714 struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
715 enum pin_config_param param = pinconf_to_config_param(*config);
716 unsigned int regval;
717
718 /* Check for valid pin */
719 if (pin >= pmx->num_pins) {
720 dev_dbg(pmx->dev, "pinconf is not supported for pin %s\n",
721 pmx->pins[pin].name);
722 return -ENOTSUPP;
723 }
724
725 dev_dbg(pmx->dev, "getting configuration for pin %s\n",
726 pmx->pins[pin].name);
727
728 /* Read pin register values */
729 regval = readl(pmx->base + artpec6_pmx_reg_offset(pin));
730
731 /* If valid, get configuration for parameter */
732 switch (param) {
733 case PIN_CONFIG_BIAS_DISABLE:
734 if (!(regval & ARTPEC6_PINMUX_UDC1_MASK))
735 return -EINVAL;
736 break;
737
738 case PIN_CONFIG_BIAS_PULL_UP:
739 case PIN_CONFIG_BIAS_PULL_DOWN:
740 if (regval & ARTPEC6_PINMUX_UDC1_MASK)
741 return -EINVAL;
742
743 regval = regval & ARTPEC6_PINMUX_UDC0_MASK;
744 if ((param == PIN_CONFIG_BIAS_PULL_UP && !regval) ||
745 (param == PIN_CONFIG_BIAS_PULL_DOWN && regval))
746 return -EINVAL;
747 break;
748 case PIN_CONFIG_DRIVE_STRENGTH:
749 regval = (regval & ARTPEC6_PINMUX_DRV_MASK)
750 >> ARTPEC6_PINMUX_DRV_SHIFT;
751 regval = artpec6_pconf_drive_field_to_mA(regval);
752 *config = pinconf_to_config_packed(param, regval);
753 break;
754 default:
755 return -ENOTSUPP;
756 }
757
758 return 0;
759}
760
761/*
762 * Valid combinations of param and arg:
763 *
764 * param arg
765 * PIN_CONFIG_BIAS_DISABLE: x (disable bias)
766 * PIN_CONFIG_BIAS_PULL_UP: 1 (pull up bias + enable)
767 * PIN_CONFIG_BIAS_PULL_DOWN: 1 (pull down bias + enable)
768 * PIN_CONFIG_DRIVE_STRENGTH: x (4mA, 6mA, 8mA, 9mA)
769 *
770 * All other args are invalid. All other params are not supported.
771 */
772static int artpec6_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
773 unsigned long *configs, unsigned int num_configs)
774{
775 struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
776 enum pin_config_param param;
777 unsigned int arg;
778 unsigned int regval;
779 unsigned int *reg;
780 int i;
781
782 /* Check for valid pin */
783 if (pin >= pmx->num_pins) {
784 dev_dbg(pmx->dev, "pinconf is not supported for pin %s\n",
785 pmx->pins[pin].name);
786 return -ENOTSUPP;
787 }
788
789 dev_dbg(pmx->dev, "setting configuration for pin %s\n",
790 pmx->pins[pin].name);
791
792 reg = pmx->base + artpec6_pmx_reg_offset(pin);
793
794 /* For each config */
795 for (i = 0; i < num_configs; i++) {
796 int drive;
797
798 param = pinconf_to_config_param(configs[i]);
799 arg = pinconf_to_config_argument(configs[i]);
800
801 switch (param) {
802 case PIN_CONFIG_BIAS_DISABLE:
803 regval = readl(reg);
804 regval |= (1 << ARTPEC6_PINMUX_UDC1_SHIFT);
805 writel(regval, reg);
806 break;
807
808 case PIN_CONFIG_BIAS_PULL_UP:
809 if (arg != 1) {
810 dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
811 __func__, arg);
812 return -EINVAL;
813 }
814
815 regval = readl(reg);
816 regval |= (arg << ARTPEC6_PINMUX_UDC0_SHIFT);
817 regval &= ~ARTPEC6_PINMUX_UDC1_MASK; /* Enable */
818 writel(regval, reg);
819 break;
820
821 case PIN_CONFIG_BIAS_PULL_DOWN:
822 if (arg != 1) {
823 dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
824 __func__, arg);
825 return -EINVAL;
826 }
827
828 regval = readl(reg);
829 regval &= ~(arg << ARTPEC6_PINMUX_UDC0_SHIFT);
830 regval &= ~ARTPEC6_PINMUX_UDC1_MASK; /* Enable */
831 writel(regval, reg);
832 break;
833
834 case PIN_CONFIG_DRIVE_STRENGTH:
835 drive = artpec6_pconf_drive_mA_to_field(arg);
836 if (drive < 0) {
837 dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
838 __func__, arg);
839 return -EINVAL;
840 }
841
842 regval = readl(reg);
843 regval &= ~ARTPEC6_PINMUX_DRV_MASK;
844 regval |= (drive << ARTPEC6_PINMUX_DRV_SHIFT);
845 writel(regval, reg);
846 break;
847
848 default:
849 dev_dbg(pmx->dev, "parameter not supported\n");
850 return -ENOTSUPP;
851 }
852 }
853
854 return 0;
855}
856
857static int artpec6_pconf_group_set(struct pinctrl_dev *pctldev,
858 unsigned int group, unsigned long *configs,
859 unsigned int num_configs)
860{
861 unsigned int num_pins, current_pin;
862 int ret;
863
864 dev_dbg(pctldev->dev, "setting group %s configuration\n",
865 artpec6_get_group_name(pctldev, group));
866
867 num_pins = artpec6_pin_groups[group].num_pins;
868
869 for (current_pin = 0; current_pin < num_pins; current_pin++) {
870 ret = artpec6_pconf_set(pctldev,
871 artpec6_pin_groups[group].pins[current_pin],
872 configs, num_configs);
873
874 if (ret < 0)
875 return ret;
876 }
877
878 return 0;
879}
880
881static const struct pinconf_ops artpec6_pconf_ops = {
882 .is_generic = true,
883 .pin_config_get = artpec6_pconf_get,
884 .pin_config_set = artpec6_pconf_set,
885 .pin_config_group_set = artpec6_pconf_group_set,
886};
887
888static struct pinctrl_desc artpec6_desc = {
889 .name = "artpec6-pinctrl",
890 .owner = THIS_MODULE,
891 .pins = artpec6_pins,
892 .npins = ARRAY_SIZE(artpec6_pins),
893 .pctlops = &artpec6_pctrl_ops,
894 .pmxops = &artpec6_pmx_ops,
895 .confops = &artpec6_pconf_ops,
896};
897
898/* The reset values say 4mA, but we want 8mA as default. */
899static void artpec6_pmx_reset(struct artpec6_pmx *pmx)
900{
901 void __iomem *base = pmx->base;
902 int i;
903
904 for (i = 0; i < ARTPEC6_LAST_PIN; i++) {
905 u32 val;
906
907 val = readl_relaxed(base + artpec6_pmx_reg_offset(i));
908 val &= ~ARTPEC6_PINMUX_DRV_MASK;
909 val |= ARTPEC6_DRIVE_8mA_SET << ARTPEC6_PINMUX_DRV_SHIFT;
910 writel_relaxed(val, base + artpec6_pmx_reg_offset(i));
911 }
912}
913
914static int artpec6_pmx_probe(struct platform_device *pdev)
915{
916 struct artpec6_pmx *pmx;
917 struct resource *res;
918
919 pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
920 if (!pmx)
921 return -ENOMEM;
922
923 pmx->dev = &pdev->dev;
924
925 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
926 pmx->base = devm_ioremap_resource(&pdev->dev, res);
927
928 if (IS_ERR(pmx->base))
929 return PTR_ERR(pmx->base);
930
931 artpec6_pmx_reset(pmx);
932
933 pmx->pins = artpec6_pins;
934 pmx->num_pins = ARRAY_SIZE(artpec6_pins);
935 pmx->functions = artpec6_pmx_functions;
936 pmx->num_functions = ARRAY_SIZE(artpec6_pmx_functions);
937 pmx->pin_groups = artpec6_pin_groups;
938 pmx->num_pin_groups = ARRAY_SIZE(artpec6_pin_groups);
939 pmx->pctl = pinctrl_register(&artpec6_desc, &pdev->dev, pmx);
940
941 if (!pmx->pctl) {
942 dev_err(&pdev->dev, "could not register pinctrl driver\n");
943 return -EINVAL;
944 }
945
946 platform_set_drvdata(pdev, pmx);
947
948 dev_info(&pdev->dev, "initialised Axis ARTPEC-6 pinctrl driver\n");
949
950 return 0;
951}
952
953static int artpec6_pmx_remove(struct platform_device *pdev)
954{
955 struct artpec6_pmx *pmx = platform_get_drvdata(pdev);
956
957 pinctrl_unregister(pmx->pctl);
958
959 return 0;
960}
961
962static const struct of_device_id artpec6_pinctrl_match[] = {
963 { .compatible = "axis,artpec6-pinctrl" },
964 {},
965};
966
967static struct platform_driver artpec6_pmx_driver = {
968 .driver = {
969 .name = "artpec6-pinctrl",
970 .owner = THIS_MODULE,
971 .of_match_table = artpec6_pinctrl_match,
972 },
973 .probe = artpec6_pmx_probe,
974 .remove = artpec6_pmx_remove,
975};
976
977static int __init artpec6_pmx_init(void)
978{
979 return platform_driver_register(&artpec6_pmx_driver);
980}
981arch_initcall(artpec6_pmx_init);
982
983static void __exit artpec6_pmx_exit(void)
984{
985 platform_driver_unregister(&artpec6_pmx_driver);
986}
987module_exit(artpec6_pmx_exit);
988
989MODULE_AUTHOR("Chris Paterson <chris.paterson@linux.pieboy.co.uk>");
990MODULE_DESCRIPTION("Axis ARTPEC-6 pin control driver");
991MODULE_LICENSE("GPL v2");
992MODULE_DEVICE_TABLE(of, artpec6_pinctrl_match);