blob: e6b957f553780932c1804c625be1014a85e6ad22 [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
Svyatoslav Ryhel1fc2d612024-11-21 14:43:00 +020070#ifdef TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS
71static void tegra_pinctrl_set_mipipad(struct udevice *config, int padcnt)
72{
73 struct pmux_mipipadctrlgrp_config *mipipad_group;
74 int i, ret, pad_id;
75 const char *function;
76 const char **pads;
77
78 mipipad_group = kmalloc_array(padcnt, sizeof(*mipipad_group), GFP_KERNEL);
79 if (!mipipad_group) {
80 log_debug("%s: cannot allocate mipi pad group array\n", __func__);
81 return;
82 }
83
84 /* decode function id and fill the first copy of pmux_mipipadctrlgrp_config */
85 function = dev_read_string(config, "nvidia,function");
86 if (function)
87 for (i = 0; i < PMUX_FUNC_COUNT; i++)
88 if (tegra_pinctrl_to_func[i])
89 if (!strcmp(function, tegra_pinctrl_to_func[i]))
90 break;
91
92 mipipad_group[0].func = i;
93
94 for (i = 1; i < padcnt; i++)
95 memcpy(&mipipad_group[i], &mipipad_group[0], sizeof(mipipad_group[0]));
96
97 ret = dev_read_string_list(config, "nvidia,pins", &pads);
98 if (ret < 0) {
99 log_debug("%s: could not parse property nvidia,pins\n", __func__);
100 goto exit;
101 }
102
103 for (i = 0; i < padcnt; i++) {
104 for (pad_id = 0; pad_id < PMUX_MIPIPADCTRLGRP_COUNT; pad_id++)
105 if (tegra_pinctrl_to_mipipadgrp[pad_id])
106 if (!strcmp(pads[i], tegra_pinctrl_to_mipipadgrp[pad_id])) {
107 mipipad_group[i].grp = pad_id;
108 break;
109 }
110 }
111
112 pinmux_config_mipipadctrlgrp_table(mipipad_group, padcnt);
113
114 free(pads);
115exit:
116 kfree(mipipad_group);
117}
118#else
119static void tegra_pinctrl_set_mipipad(struct udevice *config, int padcnt) { }
120#endif
121
Svyatoslav Ryhelc53f4c02023-11-26 17:54:03 +0200122static void tegra_pinctrl_set_pin(struct udevice *config, int pincnt)
123{
124 struct pmux_pingrp_config *pinmux_group;
125 int i, ret, pin_id;
126 const char *function;
127 const char **pins;
128
129 pinmux_group = kmalloc_array(pincnt, sizeof(*pinmux_group), GFP_KERNEL);
130 if (!pinmux_group) {
131 log_debug("%s: cannot allocate pinmux group array\n", __func__);
132 return;
133 }
134
135 /* decode function id and fill the first copy of pmux_pingrp_config */
136 function = dev_read_string(config, "nvidia,function");
137 if (function)
138 for (i = 0; i < PMUX_FUNC_COUNT; i++)
139 if (tegra_pinctrl_to_func[i])
140 if (!strcmp(function, tegra_pinctrl_to_func[i]))
141 break;
142
143 pinmux_group[0].func = i;
144
145 pinmux_group[0].pull = dev_read_u32_default(config, "nvidia,pull", 0);
146 pinmux_group[0].tristate = dev_read_u32_default(config, "nvidia,tristate", 0);
147#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
148 pinmux_group[0].io = dev_read_u32_default(config, "nvidia,enable-input", 0);
149#endif
150#ifdef TEGRA_PMX_PINS_HAVE_LOCK
151 pinmux_group[0].lock = dev_read_u32_default(config, "nvidia,lock", 0);
152#endif
153#ifdef TEGRA_PMX_PINS_HAVE_OD
154 pinmux_group[0].od = dev_read_u32_default(config, "nvidia,open-drain", 0);
155#endif
156#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
157 pinmux_group[0].ioreset = dev_read_u32_default(config, "nvidia,io-reset", 0);
158#endif
159#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
160 pinmux_group[0].rcv_sel = dev_read_u32_default(config, "nvidia,rcv-sel", 0);
161#endif
162#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
163 pinmux_group[0].e_io_hv = dev_read_u32_default(config, "nvidia,io-hv", 0);
164#endif
165#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
166 pinmux_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0);
167#endif
168#ifdef TEGRA_PMX_PINS_HAVE_HSM
169 pinmux_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0);
170#endif
171
172 for (i = 1; i < pincnt; i++)
173 memcpy(&pinmux_group[i], &pinmux_group[0], sizeof(pinmux_group[0]));
174
175 ret = dev_read_string_list(config, "nvidia,pins", &pins);
176 if (ret < 0) {
177 log_debug("%s: could not parse property nvidia,pins\n", __func__);
178 goto exit;
179 }
180
181 for (i = 0; i < pincnt; i++) {
182 for (pin_id = 0; pin_id < PMUX_PINGRP_COUNT; pin_id++)
183 if (tegra_pinctrl_to_pingrp[pin_id])
184 if (!strcmp(pins[i], tegra_pinctrl_to_pingrp[pin_id])) {
185 pinmux_group[i].pingrp = pin_id;
186 break;
187 }
188
189 debug("%s pinmap: %d, %d, %d, %d\n", pins[i],
190 pinmux_group[i].pingrp, pinmux_group[i].func,
191 pinmux_group[i].pull, pinmux_group[i].tristate);
192 }
193
194 pinmux_config_pingrp_table(pinmux_group, pincnt);
195
196 free(pins);
197exit:
198 kfree(pinmux_group);
199}
200
201static int tegra_pinctrl_set_state(struct udevice *dev, struct udevice *config)
202{
203 struct udevice *child;
204 int ret;
205 const char *name;
206
207 device_foreach_child(child, config) {
208 /* Pinmux node can contain pins and drives */
209 ret = dev_read_string_index(child, "nvidia,pins", 0,
210 &name);
211 if (ret < 0) {
212 log_debug("%s: could not parse property nvidia,pins\n", __func__);
213 return ret;
214 }
215
216 ret = dev_read_string_count(child, "nvidia,pins");
217 if (ret < 0) {
218 log_debug("%s: could not count nvidia,pins\n", __func__);
219 return ret;
220 }
221
222 if (!strncmp(name, "drive_", 6))
223 /* Drive node is detected */
224 tegra_pinctrl_set_drive(child, ret);
Svyatoslav Ryhel1fc2d612024-11-21 14:43:00 +0200225 else if (!strncmp(name, "mipi_pad_ctrl_", 14))
226 /* Handle T124 specific pinconfig */
227 tegra_pinctrl_set_mipipad(child, ret);
Svyatoslav Ryhelc53f4c02023-11-26 17:54:03 +0200228 else
229 /* Pin node is detected */
230 tegra_pinctrl_set_pin(child, ret);
231 }
232
233 return 0;
234}
235
236static int tegra_pinctrl_get_pins_count(struct udevice *dev)
237{
238 return PMUX_PINGRP_COUNT;
239}
240
241static const char *tegra_pinctrl_get_pin_name(struct udevice *dev,
242 unsigned int selector)
243{
244 return tegra_pinctrl_to_pingrp[selector];
245}
246
247static int tegra_pinctrl_get_groups_count(struct udevice *dev)
248{
249 return PMUX_DRVGRP_COUNT;
250}
251
252static const char *tegra_pinctrl_get_group_name(struct udevice *dev,
253 unsigned int selector)
254{
255 return tegra_pinctrl_to_drvgrp[selector];
256}
257
258static int tegra_pinctrl_get_functions_count(struct udevice *dev)
259{
260 return PMUX_FUNC_COUNT;
261}
262
263static const char *tegra_pinctrl_get_function_name(struct udevice *dev,
264 unsigned int selector)
265{
266 return tegra_pinctrl_to_func[selector];
267}
268
269const struct pinctrl_ops tegra_pinctrl_ops = {
270 .get_pins_count = tegra_pinctrl_get_pins_count,
271 .get_pin_name = tegra_pinctrl_get_pin_name,
272 .get_groups_count = tegra_pinctrl_get_groups_count,
273 .get_group_name = tegra_pinctrl_get_group_name,
274 .get_functions_count = tegra_pinctrl_get_functions_count,
275 .get_function_name = tegra_pinctrl_get_function_name,
276 .set_state = tegra_pinctrl_set_state,
277};
278
279static int tegra_pinctrl_bind(struct udevice *dev)
280{
281 /*
282 * Make sure that the pinctrl driver gets probed after binding
283 * to provide initial configuration and assure that further
284 * probed devices are working correctly.
285 */
286 dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
287
288 return 0;
289}
290
291static const struct udevice_id tegra_pinctrl_ids[] = {
292 { .compatible = "nvidia,tegra30-pinmux" },
293 { .compatible = "nvidia,tegra114-pinmux" },
Svyatoslav Ryhel1fc2d612024-11-21 14:43:00 +0200294 { .compatible = "nvidia,tegra124-pinmux" },
Svyatoslav Ryhelc53f4c02023-11-26 17:54:03 +0200295 { },
296};
297
298U_BOOT_DRIVER(tegra_pinctrl) = {
299 .name = "tegra_pinctrl",
300 .id = UCLASS_PINCTRL,
301 .of_match = tegra_pinctrl_ids,
302 .bind = tegra_pinctrl_bind,
303 .ops = &tegra_pinctrl_ops,
304};