blob: d5171b8be235ee99919ad8240dd2bcb0b9d43079 [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_pin(struct udevice *config)
15{
16 int i, count, pin_id, ret;
17 int pull, tristate;
18 const char **pins;
19
20 ret = dev_read_u32(config, "nvidia,pull", &pull);
21 if (ret)
22 pull = ret;
23
24 ret = dev_read_u32(config, "nvidia,tristate", &tristate);
25 if (ret)
26 tristate = ret;
27
28 count = dev_read_string_list(config, "nvidia,pins", &pins);
29 if (count < 0) {
30 log_debug("%s: could not parse property nvidia,pins\n", __func__);
31 return;
32 }
33
34 for (i = 0; i < count; i++) {
35 for (pin_id = 0; pin_id < PMUX_PINGRP_COUNT; pin_id++)
36 if (tegra_pinctrl_to_pingrp[pin_id])
37 if (!strcmp(pins[i], tegra_pinctrl_to_pingrp[pin_id]))
38 break;
39
40 if (pull >= 0)
41 pinmux_set_pullupdown(pin_id, pull);
42
43 if (tristate >= 0) {
44 if (!tristate)
45 pinmux_tristate_disable(pin_id);
46 else
47 pinmux_tristate_enable(pin_id);
48 }
49 }
50
51 free(pins);
52}
53
54static void tegra_pinctrl_set_func(struct udevice *config)
55{
56 int i, count, func_id, pin_id;
57 const char *function;
58 const char **pins;
59
60 function = dev_read_string(config, "nvidia,function");
61 if (function)
62 for (i = 0; i < PMUX_FUNC_COUNT; i++)
63 if (tegra_pinctrl_to_func[i])
64 if (!strcmp(function, tegra_pinctrl_to_func[i]))
65 break;
66
67 func_id = i;
68
69 count = dev_read_string_list(config, "nvidia,pins", &pins);
70 if (count < 0) {
71 log_debug("%s: could not parse property nvidia,pins\n", __func__);
72 return;
73 }
74
75 for (i = 0; i < count; i++) {
76 for (pin_id = 0; pin_id < PMUX_PINGRP_COUNT; pin_id++)
77 if (tegra_pinctrl_to_pingrp[pin_id])
78 if (!strcmp(pins[i], tegra_pinctrl_to_pingrp[pin_id]))
79 break;
80
81 debug("%s(%d) muxed to %s(%d)\n", pins[i], pin_id, function, func_id);
82
83 pinmux_set_func(pin_id, func_id);
84 }
85
86 free(pins);
87}
88
89static int tegra_pinctrl_set_state(struct udevice *dev, struct udevice *config)
90{
91 struct udevice *child;
92
93 device_foreach_child(child, config) {
94 /*
95 * Tegra20 pinmux is set differently then any other
96 * Tegra SOC. Nodes are arranged by function muxing,
97 * then actual pins setup (with node name prefix
98 * conf_*) and then drive setup.
99 */
100 if (!strncmp(child->name, "conf_", 5))
101 tegra_pinctrl_set_pin(child);
102 else if (!strncmp(child->name, "drive_", 6))
103 debug("%s: drive configuration is not supported\n", __func__);
104 else
105 tegra_pinctrl_set_func(child);
106 }
107
108 return 0;
109}
110
111static int tegra_pinctrl_get_pins_count(struct udevice *dev)
112{
113 return PMUX_PINGRP_COUNT;
114}
115
116static const char *tegra_pinctrl_get_pin_name(struct udevice *dev,
117 unsigned int selector)
118{
119 return tegra_pinctrl_to_pingrp[selector];
120}
121
122static int tegra_pinctrl_get_groups_count(struct udevice *dev)
123{
124 return PMUX_DRVGRP_COUNT;
125}
126
127static const char *tegra_pinctrl_get_group_name(struct udevice *dev,
128 unsigned int selector)
129{
130 return tegra_pinctrl_to_drvgrp[selector];
131}
132
133static int tegra_pinctrl_get_functions_count(struct udevice *dev)
134{
135 return PMUX_FUNC_COUNT;
136}
137
138static const char *tegra_pinctrl_get_function_name(struct udevice *dev,
139 unsigned int selector)
140{
141 return tegra_pinctrl_to_func[selector];
142}
143
144const struct pinctrl_ops tegra_pinctrl_ops = {
145 .get_pins_count = tegra_pinctrl_get_pins_count,
146 .get_pin_name = tegra_pinctrl_get_pin_name,
147 .get_groups_count = tegra_pinctrl_get_groups_count,
148 .get_group_name = tegra_pinctrl_get_group_name,
149 .get_functions_count = tegra_pinctrl_get_functions_count,
150 .get_function_name = tegra_pinctrl_get_function_name,
151 .set_state = tegra_pinctrl_set_state,
152};
153
154static int tegra_pinctrl_bind(struct udevice *dev)
155{
156 /*
157 * Make sure that the pinctrl driver gets probed after binding
158 * to provide initial configuration and assure that further
159 * probed devices are working correctly.
160 */
161 dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
162
163 return 0;
164}
165
166static const struct udevice_id tegra_pinctrl_ids[] = {
167 { .compatible = "nvidia,tegra20-pinmux" },
168 { },
169};
170
171U_BOOT_DRIVER(tegra_pinctrl) = {
172 .name = "tegra_pinctrl",
173 .id = UCLASS_PINCTRL,
174 .of_match = tegra_pinctrl_ids,
175 .bind = tegra_pinctrl_bind,
176 .ops = &tegra_pinctrl_ops,
177};