]> git.sur5r.net Git - u-boot/blob - drivers/gpio/tegra186_gpio.c
Remove unnecessary instances of DECLARE_GLOBAL_DATA_PTR
[u-boot] / drivers / gpio / tegra186_gpio.c
1 /*
2  * Copyright (c) 2010-2016, NVIDIA CORPORATION.
3  * (based on tegra_gpio.c)
4  *
5  * SPDX-License-Identifier: GPL-2.0
6  */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <malloc.h>
11 #include <errno.h>
12 #include <fdtdec.h>
13 #include <asm/io.h>
14 #include <asm/bitops.h>
15 #include <asm/gpio.h>
16 #include <dm/device-internal.h>
17 #include <dt-bindings/gpio/gpio.h>
18 #include "tegra186_gpio_priv.h"
19
20 struct tegra186_gpio_port_data {
21         const char *name;
22         uint32_t offset;
23 };
24
25 struct tegra186_gpio_ctlr_data {
26         const struct tegra186_gpio_port_data *ports;
27         uint32_t port_count;
28 };
29
30 struct tegra186_gpio_platdata {
31         const char *name;
32         uint32_t *regs;
33 };
34
35 static uint32_t *tegra186_gpio_reg(struct udevice *dev, uint32_t reg,
36                                    uint32_t gpio)
37 {
38         struct tegra186_gpio_platdata *plat = dev->platdata;
39         uint32_t index = (reg + (gpio * TEGRA186_GPIO_PER_GPIO_STRIDE)) / 4;
40
41         return &(plat->regs[index]);
42 }
43
44 static int tegra186_gpio_set_out(struct udevice *dev, unsigned offset,
45                                  bool output)
46 {
47         uint32_t *reg;
48         uint32_t rval;
49
50         reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_CONTROL, offset);
51         rval = readl(reg);
52         if (output)
53                 rval &= ~TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
54         else
55                 rval |= TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
56         writel(rval, reg);
57
58         reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
59         rval = readl(reg);
60         if (output)
61                 rval |= TEGRA186_GPIO_ENABLE_CONFIG_OUT;
62         else
63                 rval &= ~TEGRA186_GPIO_ENABLE_CONFIG_OUT;
64         rval |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;
65         writel(rval, reg);
66
67         return 0;
68 }
69
70 static int tegra186_gpio_set_val(struct udevice *dev, unsigned offset, bool val)
71 {
72         uint32_t *reg;
73         uint32_t rval;
74
75         reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE, offset);
76         rval = readl(reg);
77         if (val)
78                 rval |= TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
79         else
80                 rval &= ~TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
81         writel(rval, reg);
82
83         return 0;
84 }
85
86 static int tegra186_gpio_direction_input(struct udevice *dev, unsigned offset)
87 {
88         return tegra186_gpio_set_out(dev, offset, false);
89 }
90
91 static int tegra186_gpio_direction_output(struct udevice *dev, unsigned offset,
92                                        int value)
93 {
94         int ret;
95
96         ret = tegra186_gpio_set_val(dev, offset, value != 0);
97         if (ret)
98                 return ret;
99         return tegra186_gpio_set_out(dev, offset, true);
100 }
101
102 static int tegra186_gpio_get_value(struct udevice *dev, unsigned offset)
103 {
104         uint32_t *reg;
105         uint32_t rval;
106
107         reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
108         rval = readl(reg);
109
110         if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
111                 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE,
112                                         offset);
113         else
114                 reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_INPUT, offset);
115
116         rval = readl(reg);
117         return !!rval;
118 }
119
120 static int tegra186_gpio_set_value(struct udevice *dev, unsigned offset,
121                                    int value)
122 {
123         return tegra186_gpio_set_val(dev, offset, value != 0);
124 }
125
126 static int tegra186_gpio_get_function(struct udevice *dev, unsigned offset)
127 {
128         uint32_t *reg;
129         uint32_t rval;
130
131         reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
132         rval = readl(reg);
133         if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
134                 return GPIOF_OUTPUT;
135         else
136                 return GPIOF_INPUT;
137 }
138
139 static int tegra186_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
140                                struct ofnode_phandle_args *args)
141 {
142         int gpio, port, ret;
143
144         gpio = args->args[0];
145         port = gpio / TEGRA186_GPIO_PER_GPIO_COUNT;
146         ret = device_get_child(dev, port, &desc->dev);
147         if (ret)
148                 return ret;
149         desc->offset = gpio % TEGRA186_GPIO_PER_GPIO_COUNT;
150         desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
151
152         return 0;
153 }
154
155 static const struct dm_gpio_ops tegra186_gpio_ops = {
156         .direction_input        = tegra186_gpio_direction_input,
157         .direction_output       = tegra186_gpio_direction_output,
158         .get_value              = tegra186_gpio_get_value,
159         .set_value              = tegra186_gpio_set_value,
160         .get_function           = tegra186_gpio_get_function,
161         .xlate                  = tegra186_gpio_xlate,
162 };
163
164 /**
165  * We have a top-level GPIO device with no actual GPIOs. It has a child device
166  * for each port within the controller.
167  */
168 static int tegra186_gpio_bind(struct udevice *parent)
169 {
170         struct tegra186_gpio_platdata *parent_plat = parent->platdata;
171         struct tegra186_gpio_ctlr_data *ctlr_data =
172                 (struct tegra186_gpio_ctlr_data *)dev_get_driver_data(parent);
173         uint32_t *regs;
174         int port, ret;
175
176         /* If this is a child device, there is nothing to do here */
177         if (parent_plat)
178                 return 0;
179
180         regs = (uint32_t *)devfdt_get_addr_name(parent, "gpio");
181         if (regs == (uint32_t *)FDT_ADDR_T_NONE)
182                 return -EINVAL;
183
184         for (port = 0; port < ctlr_data->port_count; port++) {
185                 struct tegra186_gpio_platdata *plat;
186                 struct udevice *dev;
187
188                 plat = calloc(1, sizeof(*plat));
189                 if (!plat)
190                         return -ENOMEM;
191                 plat->name = ctlr_data->ports[port].name;
192                 plat->regs = &(regs[ctlr_data->ports[port].offset / 4]);
193
194                 ret = device_bind(parent, parent->driver, plat->name, plat,
195                                   -1, &dev);
196                 if (ret)
197                         return ret;
198                 dev_set_of_offset(dev, dev_of_offset(parent));
199         }
200
201         return 0;
202 }
203
204 static int tegra186_gpio_probe(struct udevice *dev)
205 {
206         struct tegra186_gpio_platdata *plat = dev->platdata;
207         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
208
209         /* Only child devices have ports */
210         if (!plat)
211                 return 0;
212
213         uc_priv->gpio_count = TEGRA186_GPIO_PER_GPIO_COUNT;
214         uc_priv->bank_name = plat->name;
215
216         return 0;
217 }
218
219 static const struct tegra186_gpio_port_data tegra186_gpio_main_ports[] = {
220         {"A",  0x2000},
221         {"B",  0x3000},
222         {"C",  0x3200},
223         {"D",  0x3400},
224         {"E",  0x2200},
225         {"F",  0x2400},
226         {"G",  0x4200},
227         {"H",  0x1000},
228         {"I",  0x0800},
229         {"J",  0x5000},
230         {"K",  0x5200},
231         {"L",  0x1200},
232         {"M",  0x5600},
233         {"N",  0x0000},
234         {"O",  0x0200},
235         {"P",  0x4000},
236         {"Q",  0x0400},
237         {"R",  0x0a00},
238         {"T",  0x0600},
239         {"X",  0x1400},
240         {"Y",  0x1600},
241         {"BB", 0x2600},
242         {"CC", 0x5400},
243 };
244
245 static const struct tegra186_gpio_ctlr_data tegra186_gpio_main_data = {
246         .ports = tegra186_gpio_main_ports,
247         .port_count = ARRAY_SIZE(tegra186_gpio_main_ports),
248 };
249
250 static const struct tegra186_gpio_port_data tegra186_gpio_aon_ports[] = {
251         {"S",  0x0200},
252         {"U",  0x0400},
253         {"V",  0x0800},
254         {"W",  0x0a00},
255         {"Z",  0x0e00},
256         {"AA", 0x0c00},
257         {"EE", 0x0600},
258         {"FF", 0x0000},
259 };
260
261 static const struct tegra186_gpio_ctlr_data tegra186_gpio_aon_data = {
262         .ports = tegra186_gpio_aon_ports,
263         .port_count = ARRAY_SIZE(tegra186_gpio_aon_ports),
264 };
265
266 static const struct udevice_id tegra186_gpio_ids[] = {
267         {
268                 .compatible = "nvidia,tegra186-gpio",
269                 .data = (ulong)&tegra186_gpio_main_data,
270         },
271         {
272                 .compatible = "nvidia,tegra186-gpio-aon",
273                 .data = (ulong)&tegra186_gpio_aon_data,
274         },
275         { }
276 };
277
278 U_BOOT_DRIVER(tegra186_gpio) = {
279         .name = "tegra186_gpio",
280         .id = UCLASS_GPIO,
281         .of_match = tegra186_gpio_ids,
282         .bind = tegra186_gpio_bind,
283         .probe = tegra186_gpio_probe,
284         .ops = &tegra186_gpio_ops,
285         .flags = DM_FLAG_PRE_RELOC,
286 };