blob: ad7112a05e6fcb0c6fe9fa2c1ce25e921650317b [file] [log] [blame]
Svyatoslav Ryhelc53f4c02023-11-26 17:54:03 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2023
4 * Svyatoslav Ryhel <clamor95@gmail.com>
5 */
6
7#include <dm.h>
8#include <dm/device_compat.h>
9#include <dm/pinctrl.h>
10#include <stdlib.h>
11
12#include <asm/arch/pinmux.h>
13
14static void tegra_pinctrl_set_drive(struct udevice *config, int drvcnt)
15{
16 struct pmux_drvgrp_config *drive_group;
17 int i, ret, pad_id;
18 const char **pads;
19
20 drive_group = kmalloc_array(drvcnt, sizeof(*drive_group), GFP_KERNEL);
21 if (!drive_group) {
22 log_debug("%s: cannot allocate drive group array\n", __func__);
23 return;
24 }
25
26 drive_group[0].slwf = dev_read_u32_default(config, "nvidia,slew-rate-falling", 0);
27 drive_group[0].slwr = dev_read_u32_default(config, "nvidia,slew-rate-rising", 0);
28 drive_group[0].drvup = dev_read_u32_default(config, "nvidia,pull-up-strength", 0);
29 drive_group[0].drvdn = dev_read_u32_default(config, "nvidia,pull-down-strength", 0);
30#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
31 drive_group[0].lpmd = dev_read_u32_default(config, "nvidia,low-power-mode", 0);
32#endif
33#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
34 drive_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0);
35#endif
36#ifdef TEGRA_PMX_GRPS_HAVE_HSM
37 drive_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0);
38#endif
39
40 for (i = 1; i < drvcnt; i++)
41 memcpy(&drive_group[i], &drive_group[0], sizeof(drive_group[0]));
42
43 ret = dev_read_string_list(config, "nvidia,pins", &pads);
44 if (ret < 0) {
45 log_debug("%s: could not parse property nvidia,pins\n", __func__);
46 goto exit;
47 }
48
49 for (i = 0; i < drvcnt; i++) {
50 for (pad_id = 0; pad_id < PMUX_DRVGRP_COUNT; pad_id++)
51 if (tegra_pinctrl_to_drvgrp[pad_id])
52 if (!strcmp(pads[i], tegra_pinctrl_to_drvgrp[pad_id])) {
53 drive_group[i].drvgrp = pad_id;
54 break;
55 }
56
57 debug("%s drvmap: %d, %d, %d, %d, %d\n", pads[i],
58 drive_group[i].drvgrp, drive_group[i].slwf,
59 drive_group[i].slwr, drive_group[i].drvup,
60 drive_group[i].drvdn);
61 }
62
63 pinmux_config_drvgrp_table(drive_group, drvcnt);
64
65 free(pads);
66exit:
67 kfree(drive_group);
68}
69
70static void tegra_pinctrl_set_pin(struct udevice *config, int pincnt)
71{
72 struct pmux_pingrp_config *pinmux_group;
73 int i, ret, pin_id;
74 const char *function;
75 const char **pins;
76
77 pinmux_group = kmalloc_array(pincnt, sizeof(*pinmux_group), GFP_KERNEL);
78 if (!pinmux_group) {
79 log_debug("%s: cannot allocate pinmux group array\n", __func__);
80 return;
81 }
82
83 /* decode function id and fill the first copy of pmux_pingrp_config */
84 function = dev_read_string(config, "nvidia,function");
85 if (function)
86 for (i = 0; i < PMUX_FUNC_COUNT; i++)
87 if (tegra_pinctrl_to_func[i])
88 if (!strcmp(function, tegra_pinctrl_to_func[i]))
89 break;
90
91 pinmux_group[0].func = i;
92
93 pinmux_group[0].pull = dev_read_u32_default(config, "nvidia,pull", 0);
94 pinmux_group[0].tristate = dev_read_u32_default(config, "nvidia,tristate", 0);
95#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
96 pinmux_group[0].io = dev_read_u32_default(config, "nvidia,enable-input", 0);
97#endif
98#ifdef TEGRA_PMX_PINS_HAVE_LOCK
99 pinmux_group[0].lock = dev_read_u32_default(config, "nvidia,lock", 0);
100#endif
101#ifdef TEGRA_PMX_PINS_HAVE_OD
102 pinmux_group[0].od = dev_read_u32_default(config, "nvidia,open-drain", 0);
103#endif
104#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
105 pinmux_group[0].ioreset = dev_read_u32_default(config, "nvidia,io-reset", 0);
106#endif
107#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
108 pinmux_group[0].rcv_sel = dev_read_u32_default(config, "nvidia,rcv-sel", 0);
109#endif
110#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
111 pinmux_group[0].e_io_hv = dev_read_u32_default(config, "nvidia,io-hv", 0);
112#endif
113#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
114 pinmux_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0);
115#endif
116#ifdef TEGRA_PMX_PINS_HAVE_HSM
117 pinmux_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0);
118#endif
119
120 for (i = 1; i < pincnt; i++)
121 memcpy(&pinmux_group[i], &pinmux_group[0], sizeof(pinmux_group[0]));
122
123 ret = dev_read_string_list(config, "nvidia,pins", &pins);
124 if (ret < 0) {
125 log_debug("%s: could not parse property nvidia,pins\n", __func__);
126 goto exit;
127 }
128
129 for (i = 0; i < pincnt; i++) {
130 for (pin_id = 0; pin_id < PMUX_PINGRP_COUNT; pin_id++)
131 if (tegra_pinctrl_to_pingrp[pin_id])
132 if (!strcmp(pins[i], tegra_pinctrl_to_pingrp[pin_id])) {
133 pinmux_group[i].pingrp = pin_id;
134 break;
135 }
136
137 debug("%s pinmap: %d, %d, %d, %d\n", pins[i],
138 pinmux_group[i].pingrp, pinmux_group[i].func,
139 pinmux_group[i].pull, pinmux_group[i].tristate);
140 }
141
142 pinmux_config_pingrp_table(pinmux_group, pincnt);
143
144 free(pins);
145exit:
146 kfree(pinmux_group);
147}
148
149static int tegra_pinctrl_set_state(struct udevice *dev, struct udevice *config)
150{
151 struct udevice *child;
152 int ret;
153 const char *name;
154
155 device_foreach_child(child, config) {
156 /* Pinmux node can contain pins and drives */
157 ret = dev_read_string_index(child, "nvidia,pins", 0,
158 &name);
159 if (ret < 0) {
160 log_debug("%s: could not parse property nvidia,pins\n", __func__);
161 return ret;
162 }
163
164 ret = dev_read_string_count(child, "nvidia,pins");
165 if (ret < 0) {
166 log_debug("%s: could not count nvidia,pins\n", __func__);
167 return ret;
168 }
169
170 if (!strncmp(name, "drive_", 6))
171 /* Drive node is detected */
172 tegra_pinctrl_set_drive(child, ret);
173 else
174 /* Pin node is detected */
175 tegra_pinctrl_set_pin(child, ret);
176 }
177
178 return 0;
179}
180
181static int tegra_pinctrl_get_pins_count(struct udevice *dev)
182{
183 return PMUX_PINGRP_COUNT;
184}
185
186static const char *tegra_pinctrl_get_pin_name(struct udevice *dev,
187 unsigned int selector)
188{
189 return tegra_pinctrl_to_pingrp[selector];
190}
191
192static int tegra_pinctrl_get_groups_count(struct udevice *dev)
193{
194 return PMUX_DRVGRP_COUNT;
195}
196
197static const char *tegra_pinctrl_get_group_name(struct udevice *dev,
198 unsigned int selector)
199{
200 return tegra_pinctrl_to_drvgrp[selector];
201}
202
203static int tegra_pinctrl_get_functions_count(struct udevice *dev)
204{
205 return PMUX_FUNC_COUNT;
206}
207
208static const char *tegra_pinctrl_get_function_name(struct udevice *dev,
209 unsigned int selector)
210{
211 return tegra_pinctrl_to_func[selector];
212}
213
214const struct pinctrl_ops tegra_pinctrl_ops = {
215 .get_pins_count = tegra_pinctrl_get_pins_count,
216 .get_pin_name = tegra_pinctrl_get_pin_name,
217 .get_groups_count = tegra_pinctrl_get_groups_count,
218 .get_group_name = tegra_pinctrl_get_group_name,
219 .get_functions_count = tegra_pinctrl_get_functions_count,
220 .get_function_name = tegra_pinctrl_get_function_name,
221 .set_state = tegra_pinctrl_set_state,
222};
223
224static int tegra_pinctrl_bind(struct udevice *dev)
225{
226 /*
227 * Make sure that the pinctrl driver gets probed after binding
228 * to provide initial configuration and assure that further
229 * probed devices are working correctly.
230 */
231 dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
232
233 return 0;
234}
235
236static const struct udevice_id tegra_pinctrl_ids[] = {
237 { .compatible = "nvidia,tegra30-pinmux" },
238 { .compatible = "nvidia,tegra114-pinmux" },
239 { },
240};
241
242U_BOOT_DRIVER(tegra_pinctrl) = {
243 .name = "tegra_pinctrl",
244 .id = UCLASS_PINCTRL,
245 .of_match = tegra_pinctrl_ids,
246 .bind = tegra_pinctrl_bind,
247 .ops = &tegra_pinctrl_ops,
248};