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