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