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