xref: /rk3399_rockchip-uboot/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c (revision 8cc92b996ddecd4c364d0bbb474c3569ebec55c7)
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(struct udevice *dev, unsigned pin)
48 {
49 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
50 	int pins_count = priv->socdata->pins_count;
51 	const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
52 	int i;
53 
54 	for (i = 0; i < pins_count; i++) {
55 		if (pins[i].number == pin) {
56 			unsigned int iectrl;
57 			u32 tmp;
58 
59 			iectrl = uniphier_pin_get_iectrl(pins[i].data);
60 			tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
61 			tmp |= 1 << iectrl;
62 			writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
63 		}
64 	}
65 }
66 
67 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
68 				    unsigned muxval)
69 {
70 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
71 	unsigned mux_bits, reg_stride, reg, reg_end, shift, mask;
72 	bool load_pinctrl;
73 	u32 tmp;
74 
75 	/* some pins need input-enabling */
76 	uniphier_pinconf_input_enable(dev, pin);
77 
78 	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
79 		/*
80 		 *  Mode       offset        bit
81 		 *  Normal     4 * n     shift+3:shift
82 		 *  Debug      4 * n     shift+7:shift+4
83 		 */
84 		mux_bits = 4;
85 		reg_stride = 8;
86 		load_pinctrl = true;
87 	} else {
88 		/*
89 		 *  Mode       offset           bit
90 		 *  Normal     8 * n        shift+3:shift
91 		 *  Debug      8 * n + 4    shift+3:shift
92 		 */
93 		mux_bits = 8;
94 		reg_stride = 4;
95 		load_pinctrl = false;
96 	}
97 
98 	reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
99 	reg_end = reg + reg_stride;
100 	shift = pin * mux_bits % 32;
101 	mask = (1U << mux_bits) - 1;
102 
103 	/*
104 	 * If reg_stride is greater than 4, the MSB of each pinsel shall be
105 	 * stored in the offset+4.
106 	 */
107 	for (; reg < reg_end; reg += 4) {
108 		tmp = readl(priv->base + reg);
109 		tmp &= ~(mask << shift);
110 		tmp |= (mask & muxval) << shift;
111 		writel(tmp, priv->base + reg);
112 
113 		muxval >>= mux_bits;
114 	}
115 
116 	if (load_pinctrl)
117 		writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
118 }
119 
120 static int uniphier_pinmux_group_set(struct udevice *dev,
121 				     unsigned group_selector,
122 				     unsigned func_selector)
123 {
124 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
125 	const struct uniphier_pinctrl_group *grp =
126 					&priv->socdata->groups[group_selector];
127 	int i;
128 
129 	for (i = 0; i < grp->num_pins; i++)
130 		uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
131 
132 	return 0;
133 }
134 
135 const struct pinctrl_ops uniphier_pinctrl_ops = {
136 	.get_groups_count = uniphier_pinctrl_get_groups_count,
137 	.get_group_name = uniphier_pinctrl_get_group_name,
138 	.get_functions_count = uniphier_pinmux_get_functions_count,
139 	.get_function_name = uniphier_pinmux_get_function_name,
140 	.pinmux_group_set = uniphier_pinmux_group_set,
141 	.set_state = pinctrl_generic_set_state,
142 };
143 
144 int uniphier_pinctrl_probe(struct udevice *dev,
145 			   struct uniphier_pinctrl_socdata *socdata)
146 {
147 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
148 	fdt_addr_t addr;
149 
150 	addr = dev_get_addr(dev);
151 	if (addr == FDT_ADDR_T_NONE)
152 		return -EINVAL;
153 
154 	priv->base = map_sysmem(addr, SZ_4K);
155 	if (!priv->base)
156 		return -ENOMEM;
157 
158 	priv->socdata = socdata;
159 
160 	return 0;
161 }
162 
163 int uniphier_pinctrl_remove(struct udevice *dev)
164 {
165 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
166 
167 	unmap_sysmem(priv->base);
168 
169 	return 0;
170 }
171