blob: b8e26d90e276082f78223a4400720f3196327927 [file] [log] [blame]
Masahiro Yamada847e618b82015-09-11 20:17:32 +09001/*
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>
Masahiro Yamadafba3a662016-03-24 22:32:43 +090011#include <linux/sizes.h>
Masahiro Yamada847e618b82015-09-11 20:17:32 +090012#include <dm/device.h>
13#include <dm/pinctrl.h>
14
15#include "pinctrl-uniphier.h"
16
Masahiro Yamada847e618b82015-09-11 20:17:32 +090017static 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
24static 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
32static 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
39static 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
Masahiro Yamada73e67752016-03-24 22:32:45 +090047static 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
62static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
63 unsigned pin)
Masahiro Yamada847e618b82015-09-11 20:17:32 +090064{
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
Masahiro Yamada73e67752016-03-24 22:32:45 +090083static 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
Masahiro Yamada847e618b82015-09-11 20:17:32 +090093static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
94 unsigned muxval)
95{
96 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
Masahiro Yamada7a629ef2016-03-24 22:32:44 +090097 unsigned mux_bits, reg_stride, reg, reg_end, shift, mask;
98 bool load_pinctrl;
Masahiro Yamada847e618b82015-09-11 20:17:32 +090099 u32 tmp;
100
Masahiro Yamadaa64e11a2016-03-04 15:56:16 +0900101 /* some pins need input-enabling */
102 uniphier_pinconf_input_enable(dev, pin);
103
Masahiro Yamada7a629ef2016-03-24 22:32:44 +0900104 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
Masahiro Yamada847e618b82015-09-11 20:17:32 +0900124 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
Masahiro Yamada7a629ef2016-03-24 22:32:44 +0900142 if (load_pinctrl)
Masahiro Yamada847e618b82015-09-11 20:17:32 +0900143 writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
Masahiro Yamada847e618b82015-09-11 20:17:32 +0900144}
145
146static 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
161const 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
170int 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;
Masahiro Yamada847e618b82015-09-11 20:17:32 +0900175
Masahiro Yamadafba3a662016-03-24 22:32:43 +0900176 addr = dev_get_addr(dev);
Masahiro Yamada847e618b82015-09-11 20:17:32 +0900177 if (addr == FDT_ADDR_T_NONE)
178 return -EINVAL;
179
Masahiro Yamadafba3a662016-03-24 22:32:43 +0900180 priv->base = map_sysmem(addr, SZ_4K);
Masahiro Yamada847e618b82015-09-11 20:17:32 +0900181 if (!priv->base)
182 return -ENOMEM;
183
184 priv->socdata = socdata;
185
186 return 0;
187}
188
189int 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}