100df0582SJesper Nilsson /*
200df0582SJesper Nilsson * Driver for the Axis ARTPEC-6 pin controller
300df0582SJesper Nilsson *
400df0582SJesper Nilsson * Author: Chris Paterson <chris.paterson@linux.pieboy.co.uk>
500df0582SJesper Nilsson *
600df0582SJesper Nilsson * This file is licensed under the terms of the GNU General Public
700df0582SJesper Nilsson * License version 2. This program is licensed "as is" without any
800df0582SJesper Nilsson * warranty of any kind, whether express or implied.
900df0582SJesper Nilsson */
1000df0582SJesper Nilsson
1100df0582SJesper Nilsson #include <linux/device.h>
1200df0582SJesper Nilsson #include <linux/err.h>
1300df0582SJesper Nilsson #include <linux/init.h>
1400df0582SJesper Nilsson #include <linux/io.h>
1500df0582SJesper Nilsson #include <linux/of.h>
1600df0582SJesper Nilsson #include <linux/platform_device.h>
1700df0582SJesper Nilsson #include <linux/pinctrl/pinctrl.h>
1800df0582SJesper Nilsson #include <linux/pinctrl/pinconf-generic.h>
1900df0582SJesper Nilsson #include <linux/pinctrl/pinconf.h>
2000df0582SJesper Nilsson #include <linux/pinctrl/pinmux.h>
2100df0582SJesper Nilsson #include <linux/slab.h>
2200df0582SJesper Nilsson #include "core.h"
2300df0582SJesper Nilsson #include "pinconf.h"
2400df0582SJesper Nilsson #include "pinctrl-utils.h"
2500df0582SJesper Nilsson
2600df0582SJesper Nilsson #define ARTPEC6_LAST_PIN 97 /* 97 pins in pinmux */
2700df0582SJesper Nilsson #define ARTPEC6_MAX_MUXABLE 35 /* Last pin with muxable function */
2800df0582SJesper Nilsson
2900df0582SJesper Nilsson /* Pinmux control register bit definitions */
3000df0582SJesper Nilsson #define ARTPEC6_PINMUX_UDC0_MASK 0x00000001
3100df0582SJesper Nilsson #define ARTPEC6_PINMUX_UDC0_SHIFT 0
3200df0582SJesper Nilsson #define ARTPEC6_PINMUX_UDC1_MASK 0x00000002
3300df0582SJesper Nilsson #define ARTPEC6_PINMUX_UDC1_SHIFT 1
3400df0582SJesper Nilsson #define ARTPEC6_PINMUX_DRV_MASK 0x00000060
3500df0582SJesper Nilsson #define ARTPEC6_PINMUX_DRV_SHIFT 5
3600df0582SJesper Nilsson #define ARTPEC6_PINMUX_SEL_MASK 0x00003000
3700df0582SJesper Nilsson #define ARTPEC6_PINMUX_SEL_SHIFT 12
3800df0582SJesper Nilsson
3900df0582SJesper Nilsson /* Pinmux configurations */
4000df0582SJesper Nilsson #define ARTPEC6_CONFIG_0 0
4100df0582SJesper Nilsson #define ARTPEC6_CONFIG_1 1
4200df0582SJesper Nilsson #define ARTPEC6_CONFIG_2 2
4300df0582SJesper Nilsson #define ARTPEC6_CONFIG_3 3
4400df0582SJesper Nilsson
4500df0582SJesper Nilsson /* Pin drive strength options */
4600df0582SJesper Nilsson #define ARTPEC6_DRIVE_4mA 4
4700df0582SJesper Nilsson #define ARTPEC6_DRIVE_4mA_SET 0
4800df0582SJesper Nilsson #define ARTPEC6_DRIVE_6mA 6
4900df0582SJesper Nilsson #define ARTPEC6_DRIVE_6mA_SET 1
5000df0582SJesper Nilsson #define ARTPEC6_DRIVE_8mA 8
5100df0582SJesper Nilsson #define ARTPEC6_DRIVE_8mA_SET 2
5200df0582SJesper Nilsson #define ARTPEC6_DRIVE_9mA 9
5300df0582SJesper Nilsson #define ARTPEC6_DRIVE_9mA_SET 3
5400df0582SJesper Nilsson
5500df0582SJesper Nilsson struct artpec6_pmx {
5600df0582SJesper Nilsson struct device *dev;
5700df0582SJesper Nilsson struct pinctrl_dev *pctl;
5800df0582SJesper Nilsson void __iomem *base;
5900df0582SJesper Nilsson struct pinctrl_pin_desc *pins;
6000df0582SJesper Nilsson unsigned int num_pins;
6100df0582SJesper Nilsson const struct artpec6_pin_group *pin_groups;
6200df0582SJesper Nilsson unsigned int num_pin_groups;
6300df0582SJesper Nilsson const struct artpec6_pmx_func *functions;
6400df0582SJesper Nilsson unsigned int num_functions;
6500df0582SJesper Nilsson };
6600df0582SJesper Nilsson
6700df0582SJesper Nilsson struct artpec6_pin_group {
6800df0582SJesper Nilsson const char *name;
6900df0582SJesper Nilsson const unsigned int *pins;
7000df0582SJesper Nilsson const unsigned int num_pins;
7100df0582SJesper Nilsson unsigned char config;
7200df0582SJesper Nilsson };
7300df0582SJesper Nilsson
7400df0582SJesper Nilsson struct artpec6_pmx_func {
7500df0582SJesper Nilsson const char *name;
7600df0582SJesper Nilsson const char * const *groups;
7700df0582SJesper Nilsson const unsigned int num_groups;
7800df0582SJesper Nilsson };
7900df0582SJesper Nilsson
8000df0582SJesper Nilsson /* pins */
8100df0582SJesper Nilsson static struct pinctrl_pin_desc artpec6_pins[] = {
8200df0582SJesper Nilsson PINCTRL_PIN(0, "GPIO0"),
8300df0582SJesper Nilsson PINCTRL_PIN(1, "GPIO1"),
8400df0582SJesper Nilsson PINCTRL_PIN(2, "GPIO2"),
8500df0582SJesper Nilsson PINCTRL_PIN(3, "GPIO3"),
8600df0582SJesper Nilsson PINCTRL_PIN(4, "GPIO4"),
8700df0582SJesper Nilsson PINCTRL_PIN(5, "GPIO5"),
8800df0582SJesper Nilsson PINCTRL_PIN(6, "GPIO6"),
8900df0582SJesper Nilsson PINCTRL_PIN(7, "GPIO7"),
9000df0582SJesper Nilsson PINCTRL_PIN(8, "GPIO8"),
9100df0582SJesper Nilsson PINCTRL_PIN(9, "GPIO9"),
9200df0582SJesper Nilsson PINCTRL_PIN(10, "GPIO10"),
9300df0582SJesper Nilsson PINCTRL_PIN(11, "GPIO11"),
9400df0582SJesper Nilsson PINCTRL_PIN(12, "GPIO12"),
9500df0582SJesper Nilsson PINCTRL_PIN(13, "GPIO13"),
9600df0582SJesper Nilsson PINCTRL_PIN(14, "GPIO14"),
9700df0582SJesper Nilsson PINCTRL_PIN(15, "GPIO15"),
9800df0582SJesper Nilsson PINCTRL_PIN(16, "GPIO16"),
9900df0582SJesper Nilsson PINCTRL_PIN(17, "GPIO17"),
10000df0582SJesper Nilsson PINCTRL_PIN(18, "GPIO18"),
10100df0582SJesper Nilsson PINCTRL_PIN(19, "GPIO19"),
10200df0582SJesper Nilsson PINCTRL_PIN(20, "GPIO20"),
10300df0582SJesper Nilsson PINCTRL_PIN(21, "GPIO21"),
10400df0582SJesper Nilsson PINCTRL_PIN(22, "GPIO22"),
10500df0582SJesper Nilsson PINCTRL_PIN(23, "GPIO23"),
10600df0582SJesper Nilsson PINCTRL_PIN(24, "GPIO24"),
10700df0582SJesper Nilsson PINCTRL_PIN(25, "GPIO25"),
10800df0582SJesper Nilsson PINCTRL_PIN(26, "GPIO26"),
10900df0582SJesper Nilsson PINCTRL_PIN(27, "GPIO27"),
11000df0582SJesper Nilsson PINCTRL_PIN(28, "GPIO28"),
11100df0582SJesper Nilsson PINCTRL_PIN(29, "GPIO29"),
11200df0582SJesper Nilsson PINCTRL_PIN(30, "GPIO30"),
11300df0582SJesper Nilsson PINCTRL_PIN(31, "GPIO31"),
11400df0582SJesper Nilsson PINCTRL_PIN(32, "UART3_TXD"),
11500df0582SJesper Nilsson PINCTRL_PIN(33, "UART3_RXD"),
11600df0582SJesper Nilsson PINCTRL_PIN(34, "UART3_RTS"),
11700df0582SJesper Nilsson PINCTRL_PIN(35, "UART3_CTS"),
11800df0582SJesper Nilsson PINCTRL_PIN(36, "NF_ALE"),
11900df0582SJesper Nilsson PINCTRL_PIN(37, "NF_CE0_N"),
12000df0582SJesper Nilsson PINCTRL_PIN(38, "NF_CE1_N"),
12100df0582SJesper Nilsson PINCTRL_PIN(39, "NF_CLE"),
12200df0582SJesper Nilsson PINCTRL_PIN(40, "NF_RE_N"),
12300df0582SJesper Nilsson PINCTRL_PIN(41, "NF_WE_N"),
12400df0582SJesper Nilsson PINCTRL_PIN(42, "NF_WP0_N"),
12500df0582SJesper Nilsson PINCTRL_PIN(43, "NF_WP1_N"),
12600df0582SJesper Nilsson PINCTRL_PIN(44, "NF_IO0"),
12700df0582SJesper Nilsson PINCTRL_PIN(45, "NF_IO1"),
12800df0582SJesper Nilsson PINCTRL_PIN(46, "NF_IO2"),
12900df0582SJesper Nilsson PINCTRL_PIN(47, "NF_IO3"),
13000df0582SJesper Nilsson PINCTRL_PIN(48, "NF_IO4"),
13100df0582SJesper Nilsson PINCTRL_PIN(49, "NF_IO5"),
13200df0582SJesper Nilsson PINCTRL_PIN(50, "NF_IO6"),
13300df0582SJesper Nilsson PINCTRL_PIN(51, "NF_IO7"),
13400df0582SJesper Nilsson PINCTRL_PIN(52, "NF_RB0_N"),
13500df0582SJesper Nilsson PINCTRL_PIN(53, "SDIO0_CLK"),
13600df0582SJesper Nilsson PINCTRL_PIN(54, "SDIO0_CMD"),
13700df0582SJesper Nilsson PINCTRL_PIN(55, "SDIO0_DAT0"),
13800df0582SJesper Nilsson PINCTRL_PIN(56, "SDIO0_DAT1"),
13900df0582SJesper Nilsson PINCTRL_PIN(57, "SDIO0_DAT2"),
14000df0582SJesper Nilsson PINCTRL_PIN(58, "SDIO0_DAT3"),
14100df0582SJesper Nilsson PINCTRL_PIN(59, "SDI0_CD"),
14200df0582SJesper Nilsson PINCTRL_PIN(60, "SDI0_WP"),
14300df0582SJesper Nilsson PINCTRL_PIN(61, "SDIO1_CLK"),
14400df0582SJesper Nilsson PINCTRL_PIN(62, "SDIO1_CMD"),
14500df0582SJesper Nilsson PINCTRL_PIN(63, "SDIO1_DAT0"),
14600df0582SJesper Nilsson PINCTRL_PIN(64, "SDIO1_DAT1"),
14700df0582SJesper Nilsson PINCTRL_PIN(65, "SDIO1_DAT2"),
14800df0582SJesper Nilsson PINCTRL_PIN(66, "SDIO1_DAT3"),
14900df0582SJesper Nilsson PINCTRL_PIN(67, "SDIO1_CD"),
15000df0582SJesper Nilsson PINCTRL_PIN(68, "SDIO1_WP"),
15100df0582SJesper Nilsson PINCTRL_PIN(69, "GBE_REFCLk"),
15200df0582SJesper Nilsson PINCTRL_PIN(70, "GBE_GTX_CLK"),
15300df0582SJesper Nilsson PINCTRL_PIN(71, "GBE_TX_CLK"),
15400df0582SJesper Nilsson PINCTRL_PIN(72, "GBE_TX_EN"),
15500df0582SJesper Nilsson PINCTRL_PIN(73, "GBE_TX_ER"),
15600df0582SJesper Nilsson PINCTRL_PIN(74, "GBE_TXD0"),
15700df0582SJesper Nilsson PINCTRL_PIN(75, "GBE_TXD1"),
15800df0582SJesper Nilsson PINCTRL_PIN(76, "GBE_TXD2"),
15900df0582SJesper Nilsson PINCTRL_PIN(77, "GBE_TXD3"),
16000df0582SJesper Nilsson PINCTRL_PIN(78, "GBE_TXD4"),
16100df0582SJesper Nilsson PINCTRL_PIN(79, "GBE_TXD5"),
16200df0582SJesper Nilsson PINCTRL_PIN(80, "GBE_TXD6"),
16300df0582SJesper Nilsson PINCTRL_PIN(81, "GBE_TXD7"),
16400df0582SJesper Nilsson PINCTRL_PIN(82, "GBE_RX_CLK"),
16500df0582SJesper Nilsson PINCTRL_PIN(83, "GBE_RX_DV"),
16600df0582SJesper Nilsson PINCTRL_PIN(84, "GBE_RX_ER"),
16700df0582SJesper Nilsson PINCTRL_PIN(85, "GBE_RXD0"),
16800df0582SJesper Nilsson PINCTRL_PIN(86, "GBE_RXD1"),
16900df0582SJesper Nilsson PINCTRL_PIN(87, "GBE_RXD2"),
17000df0582SJesper Nilsson PINCTRL_PIN(88, "GBE_RXD3"),
17100df0582SJesper Nilsson PINCTRL_PIN(89, "GBE_RXD4"),
17200df0582SJesper Nilsson PINCTRL_PIN(90, "GBE_RXD5"),
17300df0582SJesper Nilsson PINCTRL_PIN(91, "GBE_RXD6"),
17400df0582SJesper Nilsson PINCTRL_PIN(92, "GBE_RXD7"),
17500df0582SJesper Nilsson PINCTRL_PIN(93, "GBE_CRS"),
17600df0582SJesper Nilsson PINCTRL_PIN(94, "GBE_COL"),
17700df0582SJesper Nilsson PINCTRL_PIN(95, "GBE_MDC"),
17800df0582SJesper Nilsson PINCTRL_PIN(96, "GBE_MDIO"),
17900df0582SJesper Nilsson };
18000df0582SJesper Nilsson
18100df0582SJesper Nilsson static const unsigned int cpuclkout_pins0[] = { 0 };
18200df0582SJesper Nilsson static const unsigned int udlclkout_pins0[] = { 1 };
18300df0582SJesper Nilsson static const unsigned int i2c1_pins0[] = { 2, 3 };
18400df0582SJesper Nilsson static const unsigned int i2c2_pins0[] = { 4, 5 };
18500df0582SJesper Nilsson static const unsigned int i2c3_pins0[] = { 6, 7 };
18600df0582SJesper Nilsson static const unsigned int i2s0_pins0[] = { 8, 9, 10, 11 };
18700df0582SJesper Nilsson static const unsigned int i2s1_pins0[] = { 12, 13, 14, 15 };
18800df0582SJesper Nilsson static const unsigned int i2srefclk_pins0[] = { 19 };
18900df0582SJesper Nilsson static const unsigned int spi0_pins0[] = { 12, 13, 14, 15 };
19000df0582SJesper Nilsson static const unsigned int spi1_pins0[] = { 16, 17, 18, 19 };
19100df0582SJesper Nilsson static const unsigned int pciedebug_pins0[] = { 12, 13, 14, 15 };
19200df0582SJesper Nilsson static const unsigned int uart0_pins0[] = { 16, 17, 18, 19, 20,
19300df0582SJesper Nilsson 21, 22, 23, 24, 25 };
19400df0582SJesper Nilsson static const unsigned int uart0_pins1[] = { 20, 21, 22, 23 };
19500df0582SJesper Nilsson static const unsigned int uart1_pins0[] = { 24, 25, 26, 27 };
19600df0582SJesper Nilsson static const unsigned int uart2_pins0[] = { 26, 27, 28, 29, 30,
19700df0582SJesper Nilsson 31, 32, 33, 34, 35 };
19800df0582SJesper Nilsson static const unsigned int uart2_pins1[] = { 28, 29, 30, 31 };
19900df0582SJesper Nilsson static const unsigned int uart3_pins0[] = { 32, 33, 34, 35 };
20000df0582SJesper Nilsson static const unsigned int uart4_pins0[] = { 20, 21, 22, 23 };
20100df0582SJesper Nilsson static const unsigned int uart5_pins0[] = { 28, 29, 30, 31 };
20200df0582SJesper Nilsson static const unsigned int nand_pins0[] = { 36, 37, 38, 39, 40, 41,
20300df0582SJesper Nilsson 42, 43, 44, 45, 46, 47,
20400df0582SJesper Nilsson 48, 49, 50, 51, 52 };
20500df0582SJesper Nilsson static const unsigned int sdio0_pins0[] = { 53, 54, 55, 56, 57, 58, 59, 60 };
20600df0582SJesper Nilsson static const unsigned int sdio1_pins0[] = { 61, 62, 63, 64, 65, 66, 67, 68 };
20700df0582SJesper Nilsson static const unsigned int ethernet_pins0[] = { 69, 70, 71, 72, 73, 74, 75,
20800df0582SJesper Nilsson 76, 77, 78, 79, 80, 81, 82,
20900df0582SJesper Nilsson 83, 84, 85, 86, 87, 88, 89,
21000df0582SJesper Nilsson 90, 91, 92, 93, 94, 95, 96 };
21100df0582SJesper Nilsson
21200df0582SJesper Nilsson static const struct artpec6_pin_group artpec6_pin_groups[] = {
21300df0582SJesper Nilsson {
21400df0582SJesper Nilsson .name = "cpuclkoutgrp0",
21500df0582SJesper Nilsson .pins = cpuclkout_pins0,
21600df0582SJesper Nilsson .num_pins = ARRAY_SIZE(cpuclkout_pins0),
21700df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
21800df0582SJesper Nilsson },
21900df0582SJesper Nilsson {
22000df0582SJesper Nilsson .name = "udlclkoutgrp0",
22100df0582SJesper Nilsson .pins = udlclkout_pins0,
22200df0582SJesper Nilsson .num_pins = ARRAY_SIZE(udlclkout_pins0),
22300df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
22400df0582SJesper Nilsson },
22500df0582SJesper Nilsson {
22600df0582SJesper Nilsson .name = "i2c1grp0",
22700df0582SJesper Nilsson .pins = i2c1_pins0,
22800df0582SJesper Nilsson .num_pins = ARRAY_SIZE(i2c1_pins0),
22900df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
23000df0582SJesper Nilsson },
23100df0582SJesper Nilsson {
23200df0582SJesper Nilsson .name = "i2c2grp0",
23300df0582SJesper Nilsson .pins = i2c2_pins0,
23400df0582SJesper Nilsson .num_pins = ARRAY_SIZE(i2c2_pins0),
23500df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
23600df0582SJesper Nilsson },
23700df0582SJesper Nilsson {
23800df0582SJesper Nilsson .name = "i2c3grp0",
23900df0582SJesper Nilsson .pins = i2c3_pins0,
24000df0582SJesper Nilsson .num_pins = ARRAY_SIZE(i2c3_pins0),
24100df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
24200df0582SJesper Nilsson },
24300df0582SJesper Nilsson {
24400df0582SJesper Nilsson .name = "i2s0grp0",
24500df0582SJesper Nilsson .pins = i2s0_pins0,
24600df0582SJesper Nilsson .num_pins = ARRAY_SIZE(i2s0_pins0),
24700df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
24800df0582SJesper Nilsson },
24900df0582SJesper Nilsson {
25000df0582SJesper Nilsson .name = "i2s1grp0",
25100df0582SJesper Nilsson .pins = i2s1_pins0,
25200df0582SJesper Nilsson .num_pins = ARRAY_SIZE(i2s1_pins0),
25300df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
25400df0582SJesper Nilsson },
25500df0582SJesper Nilsson {
25600df0582SJesper Nilsson .name = "i2srefclkgrp0",
25700df0582SJesper Nilsson .pins = i2srefclk_pins0,
25800df0582SJesper Nilsson .num_pins = ARRAY_SIZE(i2srefclk_pins0),
25900df0582SJesper Nilsson .config = ARTPEC6_CONFIG_3,
26000df0582SJesper Nilsson },
26100df0582SJesper Nilsson {
26200df0582SJesper Nilsson .name = "spi0grp0",
26300df0582SJesper Nilsson .pins = spi0_pins0,
26400df0582SJesper Nilsson .num_pins = ARRAY_SIZE(spi0_pins0),
26500df0582SJesper Nilsson .config = ARTPEC6_CONFIG_2,
26600df0582SJesper Nilsson },
26700df0582SJesper Nilsson {
26800df0582SJesper Nilsson .name = "spi1grp0",
26900df0582SJesper Nilsson .pins = spi1_pins0,
27000df0582SJesper Nilsson .num_pins = ARRAY_SIZE(spi1_pins0),
27100df0582SJesper Nilsson .config = ARTPEC6_CONFIG_2,
27200df0582SJesper Nilsson },
27300df0582SJesper Nilsson {
27400df0582SJesper Nilsson .name = "pciedebuggrp0",
27500df0582SJesper Nilsson .pins = pciedebug_pins0,
27600df0582SJesper Nilsson .num_pins = ARRAY_SIZE(pciedebug_pins0),
27700df0582SJesper Nilsson .config = ARTPEC6_CONFIG_3,
27800df0582SJesper Nilsson },
27900df0582SJesper Nilsson {
28041e009b2SJesper Nilsson .name = "uart0grp0", /* All pins. */
28100df0582SJesper Nilsson .pins = uart0_pins0,
28200df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart0_pins0),
28300df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
28400df0582SJesper Nilsson },
28500df0582SJesper Nilsson {
28641e009b2SJesper Nilsson .name = "uart0grp1", /* RX/TX and RTS/CTS */
28700df0582SJesper Nilsson .pins = uart0_pins1,
28800df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart0_pins1),
28900df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
29000df0582SJesper Nilsson },
29100df0582SJesper Nilsson {
29241e009b2SJesper Nilsson .name = "uart0grp2", /* Only RX/TX pins. */
29341e009b2SJesper Nilsson .pins = uart0_pins1,
29441e009b2SJesper Nilsson .num_pins = ARRAY_SIZE(uart0_pins1) - 2,
29541e009b2SJesper Nilsson .config = ARTPEC6_CONFIG_1,
29641e009b2SJesper Nilsson },
29741e009b2SJesper Nilsson {
29841e009b2SJesper Nilsson .name = "uart1grp0", /* RX/TX and RTS/CTS */
29900df0582SJesper Nilsson .pins = uart1_pins0,
30000df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart1_pins0),
30100df0582SJesper Nilsson .config = ARTPEC6_CONFIG_2,
30200df0582SJesper Nilsson },
30300df0582SJesper Nilsson {
30441e009b2SJesper Nilsson .name = "uart1grp1", /* Only RX/TX pins. */
30541e009b2SJesper Nilsson .pins = uart1_pins0,
30641e009b2SJesper Nilsson .num_pins = 2,
30741e009b2SJesper Nilsson .config = ARTPEC6_CONFIG_2,
30841e009b2SJesper Nilsson },
30941e009b2SJesper Nilsson {
31041e009b2SJesper Nilsson .name = "uart2grp0", /* Full pinout */
31100df0582SJesper Nilsson .pins = uart2_pins0,
31200df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart2_pins0),
31300df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
31400df0582SJesper Nilsson },
31500df0582SJesper Nilsson {
31641e009b2SJesper Nilsson .name = "uart2grp1", /* RX/TX and RTS/CTS */
31700df0582SJesper Nilsson .pins = uart2_pins1,
31800df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart2_pins1),
31900df0582SJesper Nilsson .config = ARTPEC6_CONFIG_1,
32000df0582SJesper Nilsson },
32100df0582SJesper Nilsson {
32241e009b2SJesper Nilsson .name = "uart2grp2", /* Only RX/TX */
32341e009b2SJesper Nilsson .pins = uart2_pins1,
32441e009b2SJesper Nilsson .num_pins = 2,
32541e009b2SJesper Nilsson .config = ARTPEC6_CONFIG_1,
32641e009b2SJesper Nilsson },
32741e009b2SJesper Nilsson {
32841e009b2SJesper Nilsson .name = "uart3grp0", /* RX/TX and CTS/RTS */
32941e009b2SJesper Nilsson .pins = uart3_pins0,
33041e009b2SJesper Nilsson .num_pins = ARRAY_SIZE(uart3_pins0),
33141e009b2SJesper Nilsson .config = ARTPEC6_CONFIG_0,
33241e009b2SJesper Nilsson },
33341e009b2SJesper Nilsson {
33441e009b2SJesper Nilsson .name = "uart3grp1", /* Only RX/TX */
33500df0582SJesper Nilsson .pins = uart3_pins0,
33600df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart3_pins0),
33700df0582SJesper Nilsson .config = ARTPEC6_CONFIG_0,
33800df0582SJesper Nilsson },
33900df0582SJesper Nilsson {
34000df0582SJesper Nilsson .name = "uart4grp0",
34100df0582SJesper Nilsson .pins = uart4_pins0,
34200df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart4_pins0),
34300df0582SJesper Nilsson .config = ARTPEC6_CONFIG_2,
34400df0582SJesper Nilsson },
34500df0582SJesper Nilsson {
34641e009b2SJesper Nilsson .name = "uart5grp0", /* TX/RX and RTS/CTS */
34700df0582SJesper Nilsson .pins = uart5_pins0,
34800df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart5_pins0),
34900df0582SJesper Nilsson .config = ARTPEC6_CONFIG_2,
35000df0582SJesper Nilsson },
35100df0582SJesper Nilsson {
35241e009b2SJesper Nilsson .name = "uart5grp1", /* Only TX/RX */
35341e009b2SJesper Nilsson .pins = uart5_pins0,
35441e009b2SJesper Nilsson .num_pins = 2,
35541e009b2SJesper Nilsson .config = ARTPEC6_CONFIG_2,
35641e009b2SJesper Nilsson },
35741e009b2SJesper Nilsson {
35841e009b2SJesper Nilsson .name = "uart5nocts", /* TX/RX/RTS */
35900df0582SJesper Nilsson .pins = uart5_pins0,
36000df0582SJesper Nilsson .num_pins = ARRAY_SIZE(uart5_pins0) - 1,
36100df0582SJesper Nilsson .config = ARTPEC6_CONFIG_2,
36200df0582SJesper Nilsson },
36300df0582SJesper Nilsson {
36400df0582SJesper Nilsson .name = "nandgrp0",
36500df0582SJesper Nilsson .pins = nand_pins0,
36600df0582SJesper Nilsson .num_pins = ARRAY_SIZE(nand_pins0),
36700df0582SJesper Nilsson .config = ARTPEC6_CONFIG_0,
36800df0582SJesper Nilsson },
36900df0582SJesper Nilsson {
37000df0582SJesper Nilsson .name = "sdio0grp0",
37100df0582SJesper Nilsson .pins = sdio0_pins0,
37200df0582SJesper Nilsson .num_pins = ARRAY_SIZE(sdio0_pins0),
37300df0582SJesper Nilsson .config = ARTPEC6_CONFIG_0,
37400df0582SJesper Nilsson },
37500df0582SJesper Nilsson {
37600df0582SJesper Nilsson .name = "sdio1grp0",
37700df0582SJesper Nilsson .pins = sdio1_pins0,
37800df0582SJesper Nilsson .num_pins = ARRAY_SIZE(sdio1_pins0),
37900df0582SJesper Nilsson .config = ARTPEC6_CONFIG_0,
38000df0582SJesper Nilsson },
38100df0582SJesper Nilsson {
38200df0582SJesper Nilsson .name = "ethernetgrp0",
38300df0582SJesper Nilsson .pins = ethernet_pins0,
38400df0582SJesper Nilsson .num_pins = ARRAY_SIZE(ethernet_pins0),
38500df0582SJesper Nilsson .config = ARTPEC6_CONFIG_0,
38600df0582SJesper Nilsson },
38700df0582SJesper Nilsson };
38800df0582SJesper Nilsson
38900df0582SJesper Nilsson struct pin_register {
39000df0582SJesper Nilsson unsigned int start;
39100df0582SJesper Nilsson unsigned int end;
39200df0582SJesper Nilsson unsigned int reg_base;
39300df0582SJesper Nilsson };
39400df0582SJesper Nilsson
39500df0582SJesper Nilsson /*
39600df0582SJesper Nilsson * The register map has two holes where the pin number
39700df0582SJesper Nilsson * no longer fits directly with the register offset.
39800df0582SJesper Nilsson * This table allows us to map this easily.
39900df0582SJesper Nilsson */
40000df0582SJesper Nilsson static const struct pin_register pin_register[] = {
40100df0582SJesper Nilsson { 0, 35, 0x0 }, /* 0x0 - 0x8c */
40200df0582SJesper Nilsson { 36, 52, 0x100 }, /* 0x100 - 0x140 */
40300df0582SJesper Nilsson { 53, 96, 0x180 }, /* 0x180 - 0x22c */
40400df0582SJesper Nilsson };
40500df0582SJesper Nilsson
artpec6_pmx_reg_offset(unsigned int pin)40600df0582SJesper Nilsson static unsigned int artpec6_pmx_reg_offset(unsigned int pin)
40700df0582SJesper Nilsson {
40800df0582SJesper Nilsson int i;
40900df0582SJesper Nilsson
41000df0582SJesper Nilsson for (i = 0; i < ARRAY_SIZE(pin_register); i++) {
41100df0582SJesper Nilsson if (pin <= pin_register[i].end) {
41200df0582SJesper Nilsson return (pin - pin_register[i].start) * 4 +
41300df0582SJesper Nilsson pin_register[i].reg_base;
41400df0582SJesper Nilsson }
41500df0582SJesper Nilsson }
41600df0582SJesper Nilsson /*
41700df0582SJesper Nilsson * Anything we return here is wrong, but we can only
41800df0582SJesper Nilsson * get here if pin is outside registered range.
41900df0582SJesper Nilsson */
42000df0582SJesper Nilsson pr_err("%s: Impossible pin %d\n", __func__, pin);
42100df0582SJesper Nilsson return 0;
42200df0582SJesper Nilsson }
42300df0582SJesper Nilsson
artpec6_get_groups_count(struct pinctrl_dev * pctldev)42400df0582SJesper Nilsson static int artpec6_get_groups_count(struct pinctrl_dev *pctldev)
42500df0582SJesper Nilsson {
42600df0582SJesper Nilsson return ARRAY_SIZE(artpec6_pin_groups);
42700df0582SJesper Nilsson }
42800df0582SJesper Nilsson
artpec6_get_group_name(struct pinctrl_dev * pctldev,unsigned int group)42900df0582SJesper Nilsson static const char *artpec6_get_group_name(struct pinctrl_dev *pctldev,
43000df0582SJesper Nilsson unsigned int group)
43100df0582SJesper Nilsson {
43200df0582SJesper Nilsson return artpec6_pin_groups[group].name;
43300df0582SJesper Nilsson }
43400df0582SJesper Nilsson
artpec6_get_group_pins(struct pinctrl_dev * pctldev,unsigned int group,const unsigned int ** pins,unsigned int * num_pins)43500df0582SJesper Nilsson static int artpec6_get_group_pins(struct pinctrl_dev *pctldev,
43600df0582SJesper Nilsson unsigned int group,
43700df0582SJesper Nilsson const unsigned int **pins,
43800df0582SJesper Nilsson unsigned int *num_pins)
43900df0582SJesper Nilsson {
44000df0582SJesper Nilsson *pins = (unsigned int *)artpec6_pin_groups[group].pins;
44100df0582SJesper Nilsson *num_pins = artpec6_pin_groups[group].num_pins;
44200df0582SJesper Nilsson return 0;
44300df0582SJesper Nilsson }
44400df0582SJesper Nilsson
artpec6_pconf_drive_mA_to_field(unsigned int mA)44500df0582SJesper Nilsson static int artpec6_pconf_drive_mA_to_field(unsigned int mA)
44600df0582SJesper Nilsson {
44700df0582SJesper Nilsson switch (mA) {
44800df0582SJesper Nilsson case ARTPEC6_DRIVE_4mA:
44900df0582SJesper Nilsson return ARTPEC6_DRIVE_4mA_SET;
45000df0582SJesper Nilsson case ARTPEC6_DRIVE_6mA:
45100df0582SJesper Nilsson return ARTPEC6_DRIVE_6mA_SET;
45200df0582SJesper Nilsson case ARTPEC6_DRIVE_8mA:
45300df0582SJesper Nilsson return ARTPEC6_DRIVE_8mA_SET;
45400df0582SJesper Nilsson case ARTPEC6_DRIVE_9mA:
45500df0582SJesper Nilsson return ARTPEC6_DRIVE_9mA_SET;
45600df0582SJesper Nilsson default:
45700df0582SJesper Nilsson return -EINVAL;
45800df0582SJesper Nilsson }
45900df0582SJesper Nilsson }
46000df0582SJesper Nilsson
artpec6_pconf_drive_field_to_mA(int field)46100df0582SJesper Nilsson static unsigned int artpec6_pconf_drive_field_to_mA(int field)
46200df0582SJesper Nilsson {
46300df0582SJesper Nilsson switch (field) {
46400df0582SJesper Nilsson case ARTPEC6_DRIVE_4mA_SET:
46500df0582SJesper Nilsson return ARTPEC6_DRIVE_4mA;
46600df0582SJesper Nilsson case ARTPEC6_DRIVE_6mA_SET:
46700df0582SJesper Nilsson return ARTPEC6_DRIVE_6mA;
46800df0582SJesper Nilsson case ARTPEC6_DRIVE_8mA_SET:
46900df0582SJesper Nilsson return ARTPEC6_DRIVE_8mA;
47000df0582SJesper Nilsson case ARTPEC6_DRIVE_9mA_SET:
47100df0582SJesper Nilsson return ARTPEC6_DRIVE_9mA;
47200df0582SJesper Nilsson default:
47300df0582SJesper Nilsson /* Shouldn't happen */
47400df0582SJesper Nilsson return 0;
47500df0582SJesper Nilsson }
47600df0582SJesper Nilsson }
47700df0582SJesper Nilsson
478d82a9700SJulia Lawall static const struct pinctrl_ops artpec6_pctrl_ops = {
47900df0582SJesper Nilsson .get_group_pins = artpec6_get_group_pins,
48000df0582SJesper Nilsson .get_groups_count = artpec6_get_groups_count,
48100df0582SJesper Nilsson .get_group_name = artpec6_get_group_name,
48200df0582SJesper Nilsson .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
48300df0582SJesper Nilsson .dt_free_map = pinctrl_utils_free_map,
48400df0582SJesper Nilsson };
48500df0582SJesper Nilsson
48600df0582SJesper Nilsson static const char * const gpiogrps[] = {
48700df0582SJesper Nilsson "cpuclkoutgrp0", "udlclkoutgrp0", "i2c1grp0", "i2c2grp0",
48800df0582SJesper Nilsson "i2c3grp0", "i2s0grp0", "i2s1grp0", "i2srefclkgrp0",
48900df0582SJesper Nilsson "spi0grp0", "spi1grp0", "pciedebuggrp0", "uart0grp0",
49041e009b2SJesper Nilsson "uart0grp1", "uart0grp2", "uart1grp0", "uart1grp1",
49141e009b2SJesper Nilsson "uart2grp0", "uart2grp1", "uart2grp2", "uart4grp0", "uart5grp0",
49241e009b2SJesper Nilsson "uart5grp1", "uart5nocts",
49300df0582SJesper Nilsson };
49400df0582SJesper Nilsson static const char * const cpuclkoutgrps[] = { "cpuclkoutgrp0" };
49500df0582SJesper Nilsson static const char * const udlclkoutgrps[] = { "udlclkoutgrp0" };
49600df0582SJesper Nilsson static const char * const i2c1grps[] = { "i2c1grp0" };
49700df0582SJesper Nilsson static const char * const i2c2grps[] = { "i2c2grp0" };
49800df0582SJesper Nilsson static const char * const i2c3grps[] = { "i2c3grp0" };
49900df0582SJesper Nilsson static const char * const i2s0grps[] = { "i2s0grp0" };
50000df0582SJesper Nilsson static const char * const i2s1grps[] = { "i2s1grp0" };
50100df0582SJesper Nilsson static const char * const i2srefclkgrps[] = { "i2srefclkgrp0" };
50200df0582SJesper Nilsson static const char * const spi0grps[] = { "spi0grp0" };
50300df0582SJesper Nilsson static const char * const spi1grps[] = { "spi1grp0" };
50400df0582SJesper Nilsson static const char * const pciedebuggrps[] = { "pciedebuggrp0" };
50541e009b2SJesper Nilsson static const char * const uart0grps[] = { "uart0grp0", "uart0grp1",
50641e009b2SJesper Nilsson "uart0grp2" };
50741e009b2SJesper Nilsson static const char * const uart1grps[] = { "uart1grp0", "uart1grp1" };
50841e009b2SJesper Nilsson static const char * const uart2grps[] = { "uart2grp0", "uart2grp1",
50941e009b2SJesper Nilsson "uart2grp2" };
51000df0582SJesper Nilsson static const char * const uart3grps[] = { "uart3grp0" };
51141e009b2SJesper Nilsson static const char * const uart4grps[] = { "uart4grp0", "uart4grp1" };
51241e009b2SJesper Nilsson static const char * const uart5grps[] = { "uart5grp0", "uart5grp1",
51341e009b2SJesper Nilsson "uart5nocts" };
51400df0582SJesper Nilsson static const char * const nandgrps[] = { "nandgrp0" };
51500df0582SJesper Nilsson static const char * const sdio0grps[] = { "sdio0grp0" };
51600df0582SJesper Nilsson static const char * const sdio1grps[] = { "sdio1grp0" };
51700df0582SJesper Nilsson static const char * const ethernetgrps[] = { "ethernetgrp0" };
51800df0582SJesper Nilsson
51900df0582SJesper Nilsson static const struct artpec6_pmx_func artpec6_pmx_functions[] = {
52000df0582SJesper Nilsson {
52100df0582SJesper Nilsson .name = "gpio",
52200df0582SJesper Nilsson .groups = gpiogrps,
52300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(gpiogrps),
52400df0582SJesper Nilsson },
52500df0582SJesper Nilsson {
52600df0582SJesper Nilsson .name = "cpuclkout",
52700df0582SJesper Nilsson .groups = cpuclkoutgrps,
52800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(cpuclkoutgrps),
52900df0582SJesper Nilsson },
53000df0582SJesper Nilsson {
53100df0582SJesper Nilsson .name = "udlclkout",
53200df0582SJesper Nilsson .groups = udlclkoutgrps,
53300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(udlclkoutgrps),
53400df0582SJesper Nilsson },
53500df0582SJesper Nilsson {
53600df0582SJesper Nilsson .name = "i2c1",
53700df0582SJesper Nilsson .groups = i2c1grps,
53800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(i2c1grps),
53900df0582SJesper Nilsson },
54000df0582SJesper Nilsson {
54100df0582SJesper Nilsson .name = "i2c2",
54200df0582SJesper Nilsson .groups = i2c2grps,
54300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(i2c2grps),
54400df0582SJesper Nilsson },
54500df0582SJesper Nilsson {
54600df0582SJesper Nilsson .name = "i2c3",
54700df0582SJesper Nilsson .groups = i2c3grps,
54800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(i2c3grps),
54900df0582SJesper Nilsson },
55000df0582SJesper Nilsson {
55100df0582SJesper Nilsson .name = "i2s0",
55200df0582SJesper Nilsson .groups = i2s0grps,
55300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(i2s0grps),
55400df0582SJesper Nilsson },
55500df0582SJesper Nilsson {
55600df0582SJesper Nilsson .name = "i2s1",
55700df0582SJesper Nilsson .groups = i2s1grps,
55800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(i2s1grps),
55900df0582SJesper Nilsson },
56000df0582SJesper Nilsson {
56100df0582SJesper Nilsson .name = "i2srefclk",
56200df0582SJesper Nilsson .groups = i2srefclkgrps,
56300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(i2srefclkgrps),
56400df0582SJesper Nilsson },
56500df0582SJesper Nilsson {
56600df0582SJesper Nilsson .name = "spi0",
56700df0582SJesper Nilsson .groups = spi0grps,
56800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(spi0grps),
56900df0582SJesper Nilsson },
57000df0582SJesper Nilsson {
57100df0582SJesper Nilsson .name = "spi1",
57200df0582SJesper Nilsson .groups = spi1grps,
57300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(spi1grps),
57400df0582SJesper Nilsson },
57500df0582SJesper Nilsson {
57600df0582SJesper Nilsson .name = "pciedebug",
57700df0582SJesper Nilsson .groups = pciedebuggrps,
57800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(pciedebuggrps),
57900df0582SJesper Nilsson },
58000df0582SJesper Nilsson {
58100df0582SJesper Nilsson .name = "uart0",
58200df0582SJesper Nilsson .groups = uart0grps,
58300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(uart0grps),
58400df0582SJesper Nilsson },
58500df0582SJesper Nilsson {
58600df0582SJesper Nilsson .name = "uart1",
58700df0582SJesper Nilsson .groups = uart1grps,
58800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(uart1grps),
58900df0582SJesper Nilsson },
59000df0582SJesper Nilsson {
59100df0582SJesper Nilsson .name = "uart2",
59200df0582SJesper Nilsson .groups = uart2grps,
59300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(uart2grps),
59400df0582SJesper Nilsson },
59500df0582SJesper Nilsson {
59600df0582SJesper Nilsson .name = "uart3",
59700df0582SJesper Nilsson .groups = uart3grps,
59800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(uart3grps),
59900df0582SJesper Nilsson },
60000df0582SJesper Nilsson {
60100df0582SJesper Nilsson .name = "uart4",
60200df0582SJesper Nilsson .groups = uart4grps,
60300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(uart4grps),
60400df0582SJesper Nilsson },
60500df0582SJesper Nilsson {
60600df0582SJesper Nilsson .name = "uart5",
60700df0582SJesper Nilsson .groups = uart5grps,
60800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(uart5grps),
60900df0582SJesper Nilsson },
61000df0582SJesper Nilsson {
61100df0582SJesper Nilsson .name = "nand",
61200df0582SJesper Nilsson .groups = nandgrps,
61300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(nandgrps),
61400df0582SJesper Nilsson },
61500df0582SJesper Nilsson {
61600df0582SJesper Nilsson .name = "sdio0",
61700df0582SJesper Nilsson .groups = sdio0grps,
61800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(sdio0grps),
61900df0582SJesper Nilsson },
62000df0582SJesper Nilsson {
62100df0582SJesper Nilsson .name = "sdio1",
62200df0582SJesper Nilsson .groups = sdio1grps,
62300df0582SJesper Nilsson .num_groups = ARRAY_SIZE(sdio1grps),
62400df0582SJesper Nilsson },
62500df0582SJesper Nilsson {
62600df0582SJesper Nilsson .name = "ethernet",
62700df0582SJesper Nilsson .groups = ethernetgrps,
62800df0582SJesper Nilsson .num_groups = ARRAY_SIZE(ethernetgrps),
62900df0582SJesper Nilsson },
63000df0582SJesper Nilsson };
63100df0582SJesper Nilsson
artpec6_pmx_get_functions_count(struct pinctrl_dev * pctldev)63200df0582SJesper Nilsson static int artpec6_pmx_get_functions_count(struct pinctrl_dev *pctldev)
63300df0582SJesper Nilsson {
63400df0582SJesper Nilsson return ARRAY_SIZE(artpec6_pmx_functions);
63500df0582SJesper Nilsson }
63600df0582SJesper Nilsson
artpec6_pmx_get_fname(struct pinctrl_dev * pctldev,unsigned int function)63700df0582SJesper Nilsson static const char *artpec6_pmx_get_fname(struct pinctrl_dev *pctldev,
63800df0582SJesper Nilsson unsigned int function)
63900df0582SJesper Nilsson {
64000df0582SJesper Nilsson return artpec6_pmx_functions[function].name;
64100df0582SJesper Nilsson }
64200df0582SJesper Nilsson
artpec6_pmx_get_fgroups(struct pinctrl_dev * pctldev,unsigned int function,const char * const ** groups,unsigned int * const num_groups)64300df0582SJesper Nilsson static int artpec6_pmx_get_fgroups(struct pinctrl_dev *pctldev,
64400df0582SJesper Nilsson unsigned int function,
64500df0582SJesper Nilsson const char * const **groups,
64600df0582SJesper Nilsson unsigned int * const num_groups)
64700df0582SJesper Nilsson {
64800df0582SJesper Nilsson *groups = artpec6_pmx_functions[function].groups;
64900df0582SJesper Nilsson *num_groups = artpec6_pmx_functions[function].num_groups;
65000df0582SJesper Nilsson return 0;
65100df0582SJesper Nilsson }
65200df0582SJesper Nilsson
artpec6_pmx_select_func(struct pinctrl_dev * pctldev,unsigned int function,unsigned int group,bool enable)65300df0582SJesper Nilsson static void artpec6_pmx_select_func(struct pinctrl_dev *pctldev,
65400df0582SJesper Nilsson unsigned int function, unsigned int group,
65500df0582SJesper Nilsson bool enable)
65600df0582SJesper Nilsson {
65700df0582SJesper Nilsson unsigned int regval, val;
65800df0582SJesper Nilsson unsigned int reg;
65900df0582SJesper Nilsson int i;
66000df0582SJesper Nilsson struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
66100df0582SJesper Nilsson
66200df0582SJesper Nilsson for (i = 0; i < artpec6_pin_groups[group].num_pins; i++) {
66300df0582SJesper Nilsson /*
66400df0582SJesper Nilsson * Registers for pins above a ARTPEC6_MAX_MUXABLE
66500df0582SJesper Nilsson * do not have a SEL field and are always selected.
66600df0582SJesper Nilsson */
66700df0582SJesper Nilsson if (artpec6_pin_groups[group].pins[i] > ARTPEC6_MAX_MUXABLE)
66800df0582SJesper Nilsson continue;
66900df0582SJesper Nilsson
67000df0582SJesper Nilsson if (!strcmp(artpec6_pmx_get_fname(pctldev, function), "gpio")) {
67100df0582SJesper Nilsson /* GPIO is always config 0 */
67200df0582SJesper Nilsson val = ARTPEC6_CONFIG_0 << ARTPEC6_PINMUX_SEL_SHIFT;
67300df0582SJesper Nilsson } else {
67400df0582SJesper Nilsson if (enable)
67500df0582SJesper Nilsson val = artpec6_pin_groups[group].config
67600df0582SJesper Nilsson << ARTPEC6_PINMUX_SEL_SHIFT;
67700df0582SJesper Nilsson else
67800df0582SJesper Nilsson val = ARTPEC6_CONFIG_0
67900df0582SJesper Nilsson << ARTPEC6_PINMUX_SEL_SHIFT;
68000df0582SJesper Nilsson }
68100df0582SJesper Nilsson
68200df0582SJesper Nilsson reg = artpec6_pmx_reg_offset(artpec6_pin_groups[group].pins[i]);
68300df0582SJesper Nilsson
68400df0582SJesper Nilsson regval = readl(pmx->base + reg);
68500df0582SJesper Nilsson regval &= ~ARTPEC6_PINMUX_SEL_MASK;
68600df0582SJesper Nilsson regval |= val;
68700df0582SJesper Nilsson writel(regval, pmx->base + reg);
68800df0582SJesper Nilsson }
68900df0582SJesper Nilsson }
69000df0582SJesper Nilsson
artpec6_pmx_set(struct pinctrl_dev * pctldev,unsigned int function,unsigned int group)69121989587SLinus Walleij static int artpec6_pmx_set(struct pinctrl_dev *pctldev,
6921889ae50SYueHaibing unsigned int function,
69300df0582SJesper Nilsson unsigned int group)
69400df0582SJesper Nilsson {
69500df0582SJesper Nilsson struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
69600df0582SJesper Nilsson
69700df0582SJesper Nilsson dev_dbg(pmx->dev, "enabling %s function for pin group %s\n",
69800df0582SJesper Nilsson artpec6_pmx_get_fname(pctldev, function),
69900df0582SJesper Nilsson artpec6_get_group_name(pctldev, group));
70000df0582SJesper Nilsson
70100df0582SJesper Nilsson artpec6_pmx_select_func(pctldev, function, group, true);
70200df0582SJesper Nilsson
70300df0582SJesper Nilsson return 0;
70400df0582SJesper Nilsson }
70500df0582SJesper Nilsson
artpec6_pmx_request_gpio(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned int pin)70600df0582SJesper Nilsson static int artpec6_pmx_request_gpio(struct pinctrl_dev *pctldev,
70700df0582SJesper Nilsson struct pinctrl_gpio_range *range,
70800df0582SJesper Nilsson unsigned int pin)
70900df0582SJesper Nilsson {
71000df0582SJesper Nilsson struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
71100df0582SJesper Nilsson unsigned int reg = artpec6_pmx_reg_offset(pin);
71200df0582SJesper Nilsson u32 val;
71300df0582SJesper Nilsson
71400df0582SJesper Nilsson if (pin >= 32)
71500df0582SJesper Nilsson return -EINVAL;
71600df0582SJesper Nilsson
71700df0582SJesper Nilsson val = readl_relaxed(pmx->base + reg);
71800df0582SJesper Nilsson val &= ~ARTPEC6_PINMUX_SEL_MASK;
71900df0582SJesper Nilsson val |= ARTPEC6_CONFIG_0 << ARTPEC6_PINMUX_SEL_SHIFT;
72000df0582SJesper Nilsson writel_relaxed(val, pmx->base + reg);
72100df0582SJesper Nilsson
72200df0582SJesper Nilsson return 0;
72300df0582SJesper Nilsson }
72400df0582SJesper Nilsson
72500df0582SJesper Nilsson static const struct pinmux_ops artpec6_pmx_ops = {
72600df0582SJesper Nilsson .get_functions_count = artpec6_pmx_get_functions_count,
72700df0582SJesper Nilsson .get_function_name = artpec6_pmx_get_fname,
72800df0582SJesper Nilsson .get_function_groups = artpec6_pmx_get_fgroups,
72921989587SLinus Walleij .set_mux = artpec6_pmx_set,
73000df0582SJesper Nilsson .gpio_request_enable = artpec6_pmx_request_gpio,
73100df0582SJesper Nilsson };
73200df0582SJesper Nilsson
artpec6_pconf_get(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * config)73300df0582SJesper Nilsson static int artpec6_pconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
73400df0582SJesper Nilsson unsigned long *config)
73500df0582SJesper Nilsson {
73600df0582SJesper Nilsson struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
73700df0582SJesper Nilsson enum pin_config_param param = pinconf_to_config_param(*config);
73800df0582SJesper Nilsson unsigned int regval;
73900df0582SJesper Nilsson
74000df0582SJesper Nilsson /* Check for valid pin */
74100df0582SJesper Nilsson if (pin >= pmx->num_pins) {
74200df0582SJesper Nilsson dev_dbg(pmx->dev, "pinconf is not supported for pin %s\n",
74300df0582SJesper Nilsson pmx->pins[pin].name);
74400df0582SJesper Nilsson return -ENOTSUPP;
74500df0582SJesper Nilsson }
74600df0582SJesper Nilsson
74700df0582SJesper Nilsson dev_dbg(pmx->dev, "getting configuration for pin %s\n",
74800df0582SJesper Nilsson pmx->pins[pin].name);
74900df0582SJesper Nilsson
75000df0582SJesper Nilsson /* Read pin register values */
75100df0582SJesper Nilsson regval = readl(pmx->base + artpec6_pmx_reg_offset(pin));
75200df0582SJesper Nilsson
75300df0582SJesper Nilsson /* If valid, get configuration for parameter */
75400df0582SJesper Nilsson switch (param) {
75500df0582SJesper Nilsson case PIN_CONFIG_BIAS_DISABLE:
75600df0582SJesper Nilsson if (!(regval & ARTPEC6_PINMUX_UDC1_MASK))
75700df0582SJesper Nilsson return -EINVAL;
75800df0582SJesper Nilsson break;
75900df0582SJesper Nilsson
76000df0582SJesper Nilsson case PIN_CONFIG_BIAS_PULL_UP:
76100df0582SJesper Nilsson case PIN_CONFIG_BIAS_PULL_DOWN:
76200df0582SJesper Nilsson if (regval & ARTPEC6_PINMUX_UDC1_MASK)
76300df0582SJesper Nilsson return -EINVAL;
76400df0582SJesper Nilsson
76500df0582SJesper Nilsson regval = regval & ARTPEC6_PINMUX_UDC0_MASK;
76600df0582SJesper Nilsson if ((param == PIN_CONFIG_BIAS_PULL_UP && !regval) ||
76700df0582SJesper Nilsson (param == PIN_CONFIG_BIAS_PULL_DOWN && regval))
76800df0582SJesper Nilsson return -EINVAL;
76900df0582SJesper Nilsson break;
77000df0582SJesper Nilsson case PIN_CONFIG_DRIVE_STRENGTH:
77100df0582SJesper Nilsson regval = (regval & ARTPEC6_PINMUX_DRV_MASK)
77200df0582SJesper Nilsson >> ARTPEC6_PINMUX_DRV_SHIFT;
77300df0582SJesper Nilsson regval = artpec6_pconf_drive_field_to_mA(regval);
77400df0582SJesper Nilsson *config = pinconf_to_config_packed(param, regval);
77500df0582SJesper Nilsson break;
77600df0582SJesper Nilsson default:
77700df0582SJesper Nilsson return -ENOTSUPP;
77800df0582SJesper Nilsson }
77900df0582SJesper Nilsson
78000df0582SJesper Nilsson return 0;
78100df0582SJesper Nilsson }
78200df0582SJesper Nilsson
78300df0582SJesper Nilsson /*
78400df0582SJesper Nilsson * Valid combinations of param and arg:
78500df0582SJesper Nilsson *
78600df0582SJesper Nilsson * param arg
78700df0582SJesper Nilsson * PIN_CONFIG_BIAS_DISABLE: x (disable bias)
78800df0582SJesper Nilsson * PIN_CONFIG_BIAS_PULL_UP: 1 (pull up bias + enable)
78900df0582SJesper Nilsson * PIN_CONFIG_BIAS_PULL_DOWN: 1 (pull down bias + enable)
79000df0582SJesper Nilsson * PIN_CONFIG_DRIVE_STRENGTH: x (4mA, 6mA, 8mA, 9mA)
79100df0582SJesper Nilsson *
79200df0582SJesper Nilsson * All other args are invalid. All other params are not supported.
79300df0582SJesper Nilsson */
artpec6_pconf_set(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * configs,unsigned int num_configs)79400df0582SJesper Nilsson static int artpec6_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
79500df0582SJesper Nilsson unsigned long *configs, unsigned int num_configs)
79600df0582SJesper Nilsson {
79700df0582SJesper Nilsson struct artpec6_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
79800df0582SJesper Nilsson enum pin_config_param param;
79900df0582SJesper Nilsson unsigned int arg;
80000df0582SJesper Nilsson unsigned int regval;
801*9a4c2274SBen Dooks (Codethink) void __iomem *reg;
80200df0582SJesper Nilsson int i;
80300df0582SJesper Nilsson
80400df0582SJesper Nilsson /* Check for valid pin */
80500df0582SJesper Nilsson if (pin >= pmx->num_pins) {
80600df0582SJesper Nilsson dev_dbg(pmx->dev, "pinconf is not supported for pin %s\n",
80700df0582SJesper Nilsson pmx->pins[pin].name);
80800df0582SJesper Nilsson return -ENOTSUPP;
80900df0582SJesper Nilsson }
81000df0582SJesper Nilsson
81100df0582SJesper Nilsson dev_dbg(pmx->dev, "setting configuration for pin %s\n",
81200df0582SJesper Nilsson pmx->pins[pin].name);
81300df0582SJesper Nilsson
81400df0582SJesper Nilsson reg = pmx->base + artpec6_pmx_reg_offset(pin);
81500df0582SJesper Nilsson
81600df0582SJesper Nilsson /* For each config */
81700df0582SJesper Nilsson for (i = 0; i < num_configs; i++) {
81800df0582SJesper Nilsson int drive;
81900df0582SJesper Nilsson
82000df0582SJesper Nilsson param = pinconf_to_config_param(configs[i]);
82100df0582SJesper Nilsson arg = pinconf_to_config_argument(configs[i]);
82200df0582SJesper Nilsson
82300df0582SJesper Nilsson switch (param) {
82400df0582SJesper Nilsson case PIN_CONFIG_BIAS_DISABLE:
82500df0582SJesper Nilsson regval = readl(reg);
82600df0582SJesper Nilsson regval |= (1 << ARTPEC6_PINMUX_UDC1_SHIFT);
82700df0582SJesper Nilsson writel(regval, reg);
82800df0582SJesper Nilsson break;
82900df0582SJesper Nilsson
83000df0582SJesper Nilsson case PIN_CONFIG_BIAS_PULL_UP:
83100df0582SJesper Nilsson if (arg != 1) {
83200df0582SJesper Nilsson dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
83300df0582SJesper Nilsson __func__, arg);
83400df0582SJesper Nilsson return -EINVAL;
83500df0582SJesper Nilsson }
83600df0582SJesper Nilsson
83700df0582SJesper Nilsson regval = readl(reg);
83800df0582SJesper Nilsson regval |= (arg << ARTPEC6_PINMUX_UDC0_SHIFT);
83900df0582SJesper Nilsson regval &= ~ARTPEC6_PINMUX_UDC1_MASK; /* Enable */
84000df0582SJesper Nilsson writel(regval, reg);
84100df0582SJesper Nilsson break;
84200df0582SJesper Nilsson
84300df0582SJesper Nilsson case PIN_CONFIG_BIAS_PULL_DOWN:
84400df0582SJesper Nilsson if (arg != 1) {
84500df0582SJesper Nilsson dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
84600df0582SJesper Nilsson __func__, arg);
84700df0582SJesper Nilsson return -EINVAL;
84800df0582SJesper Nilsson }
84900df0582SJesper Nilsson
85000df0582SJesper Nilsson regval = readl(reg);
85100df0582SJesper Nilsson regval &= ~(arg << ARTPEC6_PINMUX_UDC0_SHIFT);
85200df0582SJesper Nilsson regval &= ~ARTPEC6_PINMUX_UDC1_MASK; /* Enable */
85300df0582SJesper Nilsson writel(regval, reg);
85400df0582SJesper Nilsson break;
85500df0582SJesper Nilsson
85600df0582SJesper Nilsson case PIN_CONFIG_DRIVE_STRENGTH:
85700df0582SJesper Nilsson drive = artpec6_pconf_drive_mA_to_field(arg);
85800df0582SJesper Nilsson if (drive < 0) {
85900df0582SJesper Nilsson dev_dbg(pctldev->dev, "%s: arg %u out of range\n",
86000df0582SJesper Nilsson __func__, arg);
86100df0582SJesper Nilsson return -EINVAL;
86200df0582SJesper Nilsson }
86300df0582SJesper Nilsson
86400df0582SJesper Nilsson regval = readl(reg);
86500df0582SJesper Nilsson regval &= ~ARTPEC6_PINMUX_DRV_MASK;
86600df0582SJesper Nilsson regval |= (drive << ARTPEC6_PINMUX_DRV_SHIFT);
86700df0582SJesper Nilsson writel(regval, reg);
86800df0582SJesper Nilsson break;
86900df0582SJesper Nilsson
87000df0582SJesper Nilsson default:
87100df0582SJesper Nilsson dev_dbg(pmx->dev, "parameter not supported\n");
87200df0582SJesper Nilsson return -ENOTSUPP;
87300df0582SJesper Nilsson }
87400df0582SJesper Nilsson }
87500df0582SJesper Nilsson
87600df0582SJesper Nilsson return 0;
87700df0582SJesper Nilsson }
87800df0582SJesper Nilsson
artpec6_pconf_group_set(struct pinctrl_dev * pctldev,unsigned int group,unsigned long * configs,unsigned int num_configs)87900df0582SJesper Nilsson static int artpec6_pconf_group_set(struct pinctrl_dev *pctldev,
88000df0582SJesper Nilsson unsigned int group, unsigned long *configs,
88100df0582SJesper Nilsson unsigned int num_configs)
88200df0582SJesper Nilsson {
88300df0582SJesper Nilsson unsigned int num_pins, current_pin;
88400df0582SJesper Nilsson int ret;
88500df0582SJesper Nilsson
88600df0582SJesper Nilsson dev_dbg(pctldev->dev, "setting group %s configuration\n",
88700df0582SJesper Nilsson artpec6_get_group_name(pctldev, group));
88800df0582SJesper Nilsson
88900df0582SJesper Nilsson num_pins = artpec6_pin_groups[group].num_pins;
89000df0582SJesper Nilsson
89100df0582SJesper Nilsson for (current_pin = 0; current_pin < num_pins; current_pin++) {
89200df0582SJesper Nilsson ret = artpec6_pconf_set(pctldev,
89300df0582SJesper Nilsson artpec6_pin_groups[group].pins[current_pin],
89400df0582SJesper Nilsson configs, num_configs);
89500df0582SJesper Nilsson
89600df0582SJesper Nilsson if (ret < 0)
89700df0582SJesper Nilsson return ret;
89800df0582SJesper Nilsson }
89900df0582SJesper Nilsson
90000df0582SJesper Nilsson return 0;
90100df0582SJesper Nilsson }
90200df0582SJesper Nilsson
90300df0582SJesper Nilsson static const struct pinconf_ops artpec6_pconf_ops = {
90400df0582SJesper Nilsson .is_generic = true,
90500df0582SJesper Nilsson .pin_config_get = artpec6_pconf_get,
90600df0582SJesper Nilsson .pin_config_set = artpec6_pconf_set,
90700df0582SJesper Nilsson .pin_config_group_set = artpec6_pconf_group_set,
90800df0582SJesper Nilsson };
90900df0582SJesper Nilsson
91000df0582SJesper Nilsson static struct pinctrl_desc artpec6_desc = {
91100df0582SJesper Nilsson .name = "artpec6-pinctrl",
91200df0582SJesper Nilsson .owner = THIS_MODULE,
91300df0582SJesper Nilsson .pins = artpec6_pins,
91400df0582SJesper Nilsson .npins = ARRAY_SIZE(artpec6_pins),
91500df0582SJesper Nilsson .pctlops = &artpec6_pctrl_ops,
91600df0582SJesper Nilsson .pmxops = &artpec6_pmx_ops,
91700df0582SJesper Nilsson .confops = &artpec6_pconf_ops,
91800df0582SJesper Nilsson };
91900df0582SJesper Nilsson
92000df0582SJesper Nilsson /* The reset values say 4mA, but we want 8mA as default. */
artpec6_pmx_reset(struct artpec6_pmx * pmx)92100df0582SJesper Nilsson static void artpec6_pmx_reset(struct artpec6_pmx *pmx)
92200df0582SJesper Nilsson {
92300df0582SJesper Nilsson void __iomem *base = pmx->base;
92400df0582SJesper Nilsson int i;
92500df0582SJesper Nilsson
92600df0582SJesper Nilsson for (i = 0; i < ARTPEC6_LAST_PIN; i++) {
92700df0582SJesper Nilsson u32 val;
92800df0582SJesper Nilsson
92900df0582SJesper Nilsson val = readl_relaxed(base + artpec6_pmx_reg_offset(i));
93000df0582SJesper Nilsson val &= ~ARTPEC6_PINMUX_DRV_MASK;
93100df0582SJesper Nilsson val |= ARTPEC6_DRIVE_8mA_SET << ARTPEC6_PINMUX_DRV_SHIFT;
93200df0582SJesper Nilsson writel_relaxed(val, base + artpec6_pmx_reg_offset(i));
93300df0582SJesper Nilsson }
93400df0582SJesper Nilsson }
93500df0582SJesper Nilsson
artpec6_pmx_probe(struct platform_device * pdev)93600df0582SJesper Nilsson static int artpec6_pmx_probe(struct platform_device *pdev)
93700df0582SJesper Nilsson {
93800df0582SJesper Nilsson struct artpec6_pmx *pmx;
93900df0582SJesper Nilsson
94000df0582SJesper Nilsson pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
94100df0582SJesper Nilsson if (!pmx)
94200df0582SJesper Nilsson return -ENOMEM;
94300df0582SJesper Nilsson
94400df0582SJesper Nilsson pmx->dev = &pdev->dev;
94500df0582SJesper Nilsson
9464b024225SYueHaibing pmx->base = devm_platform_ioremap_resource(pdev, 0);
94700df0582SJesper Nilsson
94800df0582SJesper Nilsson if (IS_ERR(pmx->base))
94900df0582SJesper Nilsson return PTR_ERR(pmx->base);
95000df0582SJesper Nilsson
95100df0582SJesper Nilsson artpec6_pmx_reset(pmx);
95200df0582SJesper Nilsson
95300df0582SJesper Nilsson pmx->pins = artpec6_pins;
95400df0582SJesper Nilsson pmx->num_pins = ARRAY_SIZE(artpec6_pins);
95500df0582SJesper Nilsson pmx->functions = artpec6_pmx_functions;
95600df0582SJesper Nilsson pmx->num_functions = ARRAY_SIZE(artpec6_pmx_functions);
95700df0582SJesper Nilsson pmx->pin_groups = artpec6_pin_groups;
95800df0582SJesper Nilsson pmx->num_pin_groups = ARRAY_SIZE(artpec6_pin_groups);
95900df0582SJesper Nilsson pmx->pctl = pinctrl_register(&artpec6_desc, &pdev->dev, pmx);
96000df0582SJesper Nilsson
961c312c2c3SWei Yongjun if (IS_ERR(pmx->pctl)) {
96200df0582SJesper Nilsson dev_err(&pdev->dev, "could not register pinctrl driver\n");
963c312c2c3SWei Yongjun return PTR_ERR(pmx->pctl);
96400df0582SJesper Nilsson }
96500df0582SJesper Nilsson
96600df0582SJesper Nilsson platform_set_drvdata(pdev, pmx);
96700df0582SJesper Nilsson
96800df0582SJesper Nilsson dev_info(&pdev->dev, "initialised Axis ARTPEC-6 pinctrl driver\n");
96900df0582SJesper Nilsson
97000df0582SJesper Nilsson return 0;
97100df0582SJesper Nilsson }
97200df0582SJesper Nilsson
artpec6_pmx_remove(struct platform_device * pdev)97300df0582SJesper Nilsson static int artpec6_pmx_remove(struct platform_device *pdev)
97400df0582SJesper Nilsson {
97500df0582SJesper Nilsson struct artpec6_pmx *pmx = platform_get_drvdata(pdev);
97600df0582SJesper Nilsson
97700df0582SJesper Nilsson pinctrl_unregister(pmx->pctl);
97800df0582SJesper Nilsson
97900df0582SJesper Nilsson return 0;
98000df0582SJesper Nilsson }
98100df0582SJesper Nilsson
98200df0582SJesper Nilsson static const struct of_device_id artpec6_pinctrl_match[] = {
98300df0582SJesper Nilsson { .compatible = "axis,artpec6-pinctrl" },
98400df0582SJesper Nilsson {},
98500df0582SJesper Nilsson };
98600df0582SJesper Nilsson
98700df0582SJesper Nilsson static struct platform_driver artpec6_pmx_driver = {
98800df0582SJesper Nilsson .driver = {
98900df0582SJesper Nilsson .name = "artpec6-pinctrl",
99000df0582SJesper Nilsson .of_match_table = artpec6_pinctrl_match,
99100df0582SJesper Nilsson },
99200df0582SJesper Nilsson .probe = artpec6_pmx_probe,
99300df0582SJesper Nilsson .remove = artpec6_pmx_remove,
99400df0582SJesper Nilsson };
99500df0582SJesper Nilsson
artpec6_pmx_init(void)99600df0582SJesper Nilsson static int __init artpec6_pmx_init(void)
99700df0582SJesper Nilsson {
99800df0582SJesper Nilsson return platform_driver_register(&artpec6_pmx_driver);
99900df0582SJesper Nilsson }
100000df0582SJesper Nilsson arch_initcall(artpec6_pmx_init);
1001