1 /*
2  * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <mapmem.h>
9 #include <linux/io.h>
10 #include <linux/err.h>
11 #include <linux/sizes.h>
12 #include <dm/device.h>
13 #include <dm/pinctrl.h>
14 
15 #include "pinctrl-uniphier.h"
16 
17 static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
18 {
19 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
20 
21 	return priv->socdata->groups_count;
22 }
23 
24 static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
25 						   unsigned selector)
26 {
27 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
28 
29 	return priv->socdata->groups[selector].name;
30 }
31 
32 static int uniphier_pinmux_get_functions_count(struct udevice *dev)
33 {
34 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
35 
36 	return priv->socdata->functions_count;
37 }
38 
39 static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
40 						     unsigned selector)
41 {
42 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
43 
44 	return priv->socdata->functions[selector];
45 }
46 
47 static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
48 						 unsigned pin)
49 {
50 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
51 	unsigned reg;
52 	u32 mask, tmp;
53 
54 	reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
55 	mask = BIT(pin % 32);
56 
57 	tmp = readl(priv->base + reg);
58 	tmp |= mask;
59 	writel(tmp, priv->base + reg);
60 }
61 
62 static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
63 						 unsigned pin)
64 {
65 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
66 	int pins_count = priv->socdata->pins_count;
67 	const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
68 	int i;
69 
70 	for (i = 0; i < pins_count; i++) {
71 		if (pins[i].number == pin) {
72 			unsigned int iectrl;
73 			u32 tmp;
74 
75 			iectrl = uniphier_pin_get_iectrl(pins[i].data);
76 			tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
77 			tmp |= 1 << iectrl;
78 			writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
79 		}
80 	}
81 }
82 
83 static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
84 {
85 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
86 
87 	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
88 		uniphier_pinconf_input_enable_perpin(dev, pin);
89 	else
90 		uniphier_pinconf_input_enable_legacy(dev, pin);
91 }
92 
93 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
94 				    unsigned muxval)
95 {
96 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
97 	unsigned mux_bits, reg_stride, reg, reg_end, shift, mask;
98 	bool load_pinctrl;
99 	u32 tmp;
100 
101 	/* some pins need input-enabling */
102 	uniphier_pinconf_input_enable(dev, pin);
103 
104 	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
105 		/*
106 		 *  Mode       offset        bit
107 		 *  Normal     4 * n     shift+3:shift
108 		 *  Debug      4 * n     shift+7:shift+4
109 		 */
110 		mux_bits = 4;
111 		reg_stride = 8;
112 		load_pinctrl = true;
113 	} else {
114 		/*
115 		 *  Mode       offset           bit
116 		 *  Normal     8 * n        shift+3:shift
117 		 *  Debug      8 * n + 4    shift+3:shift
118 		 */
119 		mux_bits = 8;
120 		reg_stride = 4;
121 		load_pinctrl = false;
122 	}
123 
124 	reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
125 	reg_end = reg + reg_stride;
126 	shift = pin * mux_bits % 32;
127 	mask = (1U << mux_bits) - 1;
128 
129 	/*
130 	 * If reg_stride is greater than 4, the MSB of each pinsel shall be
131 	 * stored in the offset+4.
132 	 */
133 	for (; reg < reg_end; reg += 4) {
134 		tmp = readl(priv->base + reg);
135 		tmp &= ~(mask << shift);
136 		tmp |= (mask & muxval) << shift;
137 		writel(tmp, priv->base + reg);
138 
139 		muxval >>= mux_bits;
140 	}
141 
142 	if (load_pinctrl)
143 		writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
144 }
145 
146 static int uniphier_pinmux_group_set(struct udevice *dev,
147 				     unsigned group_selector,
148 				     unsigned func_selector)
149 {
150 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
151 	const struct uniphier_pinctrl_group *grp =
152 					&priv->socdata->groups[group_selector];
153 	int i;
154 
155 	for (i = 0; i < grp->num_pins; i++)
156 		uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
157 
158 	return 0;
159 }
160 
161 const struct pinctrl_ops uniphier_pinctrl_ops = {
162 	.get_groups_count = uniphier_pinctrl_get_groups_count,
163 	.get_group_name = uniphier_pinctrl_get_group_name,
164 	.get_functions_count = uniphier_pinmux_get_functions_count,
165 	.get_function_name = uniphier_pinmux_get_function_name,
166 	.pinmux_group_set = uniphier_pinmux_group_set,
167 	.set_state = pinctrl_generic_set_state,
168 };
169 
170 int uniphier_pinctrl_probe(struct udevice *dev,
171 			   struct uniphier_pinctrl_socdata *socdata)
172 {
173 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
174 	fdt_addr_t addr;
175 
176 	addr = dev_get_addr(dev);
177 	if (addr == FDT_ADDR_T_NONE)
178 		return -EINVAL;
179 
180 	priv->base = map_sysmem(addr, SZ_4K);
181 	if (!priv->base)
182 		return -ENOMEM;
183 
184 	priv->socdata = socdata;
185 
186 	return 0;
187 }
188 
189 int uniphier_pinctrl_remove(struct udevice *dev)
190 {
191 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
192 
193 	unmap_sysmem(priv->base);
194 
195 	return 0;
196 }
197