xref: /openbmc/linux/drivers/pinctrl/mvebu/pinctrl-orion.c (revision 34d6f206a88c2651d216bd3487ac956a40b2ba8e)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   * Marvell Orion pinctrl driver based on mvebu pinctrl core
4   *
5   * Author: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
6   *
7   * The first 16 MPP pins on Orion are easy to handle: they are
8   * configured through 2 consecutive registers, located at the base
9   * address of the MPP device.
10   *
11   * However the last 4 MPP pins are handled by a register at offset
12   * 0x50 from the base address, so it is not consecutive with the first
13   * two registers.
14   */
15  
16  #include <linux/err.h>
17  #include <linux/init.h>
18  #include <linux/io.h>
19  #include <linux/platform_device.h>
20  #include <linux/clk.h>
21  #include <linux/of.h>
22  #include <linux/pinctrl/pinctrl.h>
23  #include <linux/property.h>
24  
25  #include "pinctrl-mvebu.h"
26  
27  static void __iomem *mpp_base;
28  static void __iomem *high_mpp_base;
29  
orion_mpp_ctrl_get(struct mvebu_mpp_ctrl_data * data,unsigned pid,unsigned long * config)30  static int orion_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data,
31  			      unsigned pid, unsigned long *config)
32  {
33  	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
34  
35  	if (pid < 16) {
36  		unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
37  		*config = (readl(mpp_base + off) >> shift) & MVEBU_MPP_MASK;
38  	}
39  	else {
40  		*config = (readl(high_mpp_base) >> shift) & MVEBU_MPP_MASK;
41  	}
42  
43  	return 0;
44  }
45  
orion_mpp_ctrl_set(struct mvebu_mpp_ctrl_data * data,unsigned pid,unsigned long config)46  static int orion_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data,
47  			      unsigned pid, unsigned long config)
48  {
49  	unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
50  
51  	if (pid < 16) {
52  		unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
53  		u32 reg = readl(mpp_base + off) & ~(MVEBU_MPP_MASK << shift);
54  		writel(reg | (config << shift), mpp_base + off);
55  	}
56  	else {
57  		u32 reg = readl(high_mpp_base) & ~(MVEBU_MPP_MASK << shift);
58  		writel(reg | (config << shift), high_mpp_base);
59  	}
60  
61  	return 0;
62  }
63  
64  #define V(f5181, f5182, f5281) \
65  	((f5181 << 0) | (f5182 << 1) | (f5281 << 2))
66  
67  enum orion_variant {
68  	V_5181  = V(1, 0, 0),
69  	V_5182  = V(0, 1, 0),
70  	V_5281  = V(0, 0, 1),
71  	V_ALL   = V(1, 1, 1),
72  };
73  
74  static struct mvebu_mpp_mode orion_mpp_modes[] = {
75  	MPP_MODE(0,
76  		 MPP_VAR_FUNCTION(0x0, "pcie", "rstout",    V_ALL),
77  		 MPP_VAR_FUNCTION(0x2, "pci", "req2",       V_ALL),
78  		 MPP_VAR_FUNCTION(0x3, "gpio", NULL,        V_ALL)),
79  	MPP_MODE(1,
80  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
81  		 MPP_VAR_FUNCTION(0x2, "pci", "gnt2",       V_ALL)),
82  	MPP_MODE(2,
83  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
84  		 MPP_VAR_FUNCTION(0x2, "pci", "req3",       V_ALL),
85  		 MPP_VAR_FUNCTION(0x3, "pci-1", "pme",      V_ALL)),
86  	MPP_MODE(3,
87  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
88  		 MPP_VAR_FUNCTION(0x2, "pci", "gnt3",       V_ALL)),
89  	MPP_MODE(4,
90  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
91  		 MPP_VAR_FUNCTION(0x2, "pci", "req4",       V_ALL),
92  		 MPP_VAR_FUNCTION(0x4, "bootnand", "re",    V_5182 | V_5281),
93  		 MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",    V_5182)),
94  	MPP_MODE(5,
95  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
96  		 MPP_VAR_FUNCTION(0x2, "pci", "gnt4",       V_ALL),
97  		 MPP_VAR_FUNCTION(0x4, "bootnand", "we",    V_5182 | V_5281),
98  		 MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",    V_5182)),
99  	MPP_MODE(6,
100  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
101  		 MPP_VAR_FUNCTION(0x2, "pci", "req5",       V_ALL),
102  		 MPP_VAR_FUNCTION(0x4, "nand", "re0",       V_5182 | V_5281),
103  		 MPP_VAR_FUNCTION(0x5, "pci-1", "clk",      V_5181),
104  		 MPP_VAR_FUNCTION(0x5, "sata0", "act",      V_5182)),
105  	MPP_MODE(7,
106  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
107  		 MPP_VAR_FUNCTION(0x2, "pci", "gnt5",       V_ALL),
108  		 MPP_VAR_FUNCTION(0x4, "nand", "we0",       V_5182 | V_5281),
109  		 MPP_VAR_FUNCTION(0x5, "pci-1", "clk",      V_5181),
110  		 MPP_VAR_FUNCTION(0x5, "sata1", "act",      V_5182)),
111  	MPP_MODE(8,
112  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
113  		 MPP_VAR_FUNCTION(0x1, "ge", "col",         V_ALL)),
114  	MPP_MODE(9,
115  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
116  		 MPP_VAR_FUNCTION(0x1, "ge", "rxerr",       V_ALL)),
117  	MPP_MODE(10,
118  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
119  		 MPP_VAR_FUNCTION(0x1, "ge", "crs",         V_ALL)),
120  	MPP_MODE(11,
121  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
122  		 MPP_VAR_FUNCTION(0x1, "ge", "txerr",       V_ALL)),
123  	MPP_MODE(12,
124  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
125  		 MPP_VAR_FUNCTION(0x1, "ge", "txd4",        V_ALL),
126  		 MPP_VAR_FUNCTION(0x4, "nand", "re1",       V_5182 | V_5281),
127  		 MPP_VAR_FUNCTION(0x5, "sata0", "ledprsnt", V_5182)),
128  	MPP_MODE(13,
129  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
130  		 MPP_VAR_FUNCTION(0x1, "ge", "txd5",        V_ALL),
131  		 MPP_VAR_FUNCTION(0x4, "nand", "we1",       V_5182 | V_5281),
132  		 MPP_VAR_FUNCTION(0x5, "sata1", "ledprsnt", V_5182)),
133  	MPP_MODE(14,
134  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
135  		 MPP_VAR_FUNCTION(0x1, "ge", "txd6",        V_ALL),
136  		 MPP_VAR_FUNCTION(0x4, "nand", "re2",       V_5182 | V_5281),
137  		 MPP_VAR_FUNCTION(0x5, "sata0", "ledact",   V_5182)),
138  	MPP_MODE(15,
139  		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_ALL),
140  		 MPP_VAR_FUNCTION(0x1, "ge", "txd7",        V_ALL),
141  		 MPP_VAR_FUNCTION(0x4, "nand", "we2",       V_5182 | V_5281),
142  		 MPP_VAR_FUNCTION(0x5, "sata1", "ledact",   V_5182)),
143  	MPP_MODE(16,
144  		 MPP_VAR_FUNCTION(0x0, "uart1", "rxd",      V_5182 | V_5281),
145  		 MPP_VAR_FUNCTION(0x1, "ge", "rxd4",        V_ALL),
146  		 MPP_VAR_FUNCTION(0x5, "gpio", NULL,        V_5182)),
147  	MPP_MODE(17,
148  		 MPP_VAR_FUNCTION(0x0, "uart1", "txd",      V_5182 | V_5281),
149  		 MPP_VAR_FUNCTION(0x1, "ge", "rxd5",        V_ALL),
150  		 MPP_VAR_FUNCTION(0x5, "gpio", NULL,        V_5182)),
151  	MPP_MODE(18,
152  		 MPP_VAR_FUNCTION(0x0, "uart1", "cts",      V_5182 | V_5281),
153  		 MPP_VAR_FUNCTION(0x1, "ge", "rxd6",        V_ALL),
154  		 MPP_VAR_FUNCTION(0x5, "gpio", NULL,        V_5182)),
155  	MPP_MODE(19,
156  		 MPP_VAR_FUNCTION(0x0, "uart1", "rts",      V_5182 | V_5281),
157  		 MPP_VAR_FUNCTION(0x1, "ge", "rxd7",        V_ALL),
158  		 MPP_VAR_FUNCTION(0x5, "gpio", NULL,        V_5182)),
159  };
160  
161  static const struct mvebu_mpp_ctrl orion_mpp_controls[] = {
162  	MPP_FUNC_CTRL(0, 19, NULL, orion_mpp_ctrl),
163  };
164  
165  static struct pinctrl_gpio_range mv88f5181_gpio_ranges[] = {
166  	MPP_GPIO_RANGE(0, 0, 0, 16),
167  };
168  
169  static struct pinctrl_gpio_range mv88f5182_gpio_ranges[] = {
170  	MPP_GPIO_RANGE(0, 0, 0, 19),
171  };
172  
173  static struct pinctrl_gpio_range mv88f5281_gpio_ranges[] = {
174  	MPP_GPIO_RANGE(0, 0, 0, 16),
175  };
176  
177  static struct mvebu_pinctrl_soc_info mv88f5181_info = {
178  	.variant = V_5181,
179  	.controls = orion_mpp_controls,
180  	.ncontrols = ARRAY_SIZE(orion_mpp_controls),
181  	.modes = orion_mpp_modes,
182  	.nmodes = ARRAY_SIZE(orion_mpp_modes),
183  	.gpioranges = mv88f5181_gpio_ranges,
184  	.ngpioranges = ARRAY_SIZE(mv88f5181_gpio_ranges),
185  };
186  
187  static struct mvebu_pinctrl_soc_info mv88f5182_info = {
188  	.variant = V_5182,
189  	.controls = orion_mpp_controls,
190  	.ncontrols = ARRAY_SIZE(orion_mpp_controls),
191  	.modes = orion_mpp_modes,
192  	.nmodes = ARRAY_SIZE(orion_mpp_modes),
193  	.gpioranges = mv88f5182_gpio_ranges,
194  	.ngpioranges = ARRAY_SIZE(mv88f5182_gpio_ranges),
195  };
196  
197  static struct mvebu_pinctrl_soc_info mv88f5281_info = {
198  	.variant = V_5281,
199  	.controls = orion_mpp_controls,
200  	.ncontrols = ARRAY_SIZE(orion_mpp_controls),
201  	.modes = orion_mpp_modes,
202  	.nmodes = ARRAY_SIZE(orion_mpp_modes),
203  	.gpioranges = mv88f5281_gpio_ranges,
204  	.ngpioranges = ARRAY_SIZE(mv88f5281_gpio_ranges),
205  };
206  
207  /*
208   * There are multiple variants of the Orion SoCs, but in terms of pin
209   * muxing, they are identical.
210   */
211  static const struct of_device_id orion_pinctrl_of_match[] = {
212  	{ .compatible = "marvell,88f5181-pinctrl", .data = &mv88f5181_info },
213  	{ .compatible = "marvell,88f5181l-pinctrl", .data = &mv88f5181_info },
214  	{ .compatible = "marvell,88f5182-pinctrl", .data = &mv88f5182_info },
215  	{ .compatible = "marvell,88f5281-pinctrl", .data = &mv88f5281_info },
216  	{ }
217  };
218  
orion_pinctrl_probe(struct platform_device * pdev)219  static int orion_pinctrl_probe(struct platform_device *pdev)
220  {
221  	pdev->dev.platform_data = (void*)device_get_match_data(&pdev->dev);
222  
223  	mpp_base = devm_platform_ioremap_resource(pdev, 0);
224  	if (IS_ERR(mpp_base))
225  		return PTR_ERR(mpp_base);
226  
227  	high_mpp_base = devm_platform_ioremap_resource(pdev, 1);
228  	if (IS_ERR(high_mpp_base))
229  		return PTR_ERR(high_mpp_base);
230  
231  	return mvebu_pinctrl_probe(pdev);
232  }
233  
234  static struct platform_driver orion_pinctrl_driver = {
235  	.driver = {
236  		.name = "orion-pinctrl",
237  		.of_match_table = of_match_ptr(orion_pinctrl_of_match),
238  	},
239  	.probe = orion_pinctrl_probe,
240  };
241  builtin_platform_driver(orion_pinctrl_driver);
242