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
19struct tegra186_gpio_port_data {
20	const char *name;
21	uint32_t offset;
22};
23
24struct tegra186_gpio_ctlr_data {
25	const struct tegra186_gpio_port_data *ports;
26	uint32_t port_count;
27};
28
29struct tegra186_gpio_plat {
30	const char *name;
31	uint32_t *regs;
32};
33
34static 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
43static 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
69static 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
85static int tegra186_gpio_direction_input(struct udevice *dev, unsigned offset)
86{
87	return tegra186_gpio_set_out(dev, offset, false);
88}
89
90static 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
101static 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
119static 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
125static 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
138static 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
154static 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 */
167static 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 = dev_read_addr_name_ptr(parent, "gpio");
180	if (!regs)
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
202static 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
217static 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
243static 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
248static 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
259static 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
264static 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
276U_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};
284