1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <device/mmio.h>
4 #include <gpio.h>
5 #include <soc/addressmap.h>
6 #include <stddef.h>
7 #include <stdint.h>
8
9 #include "pinmux.h"
10
__gpio_input(gpio_t gpio,u32 pull)11 static void __gpio_input(gpio_t gpio, u32 pull)
12 {
13 u32 pinmux_config = PINMUX_INPUT_ENABLE | pull;
14
15 gpio_set_int_enable(gpio, 0);
16 gpio_set_out_enable(gpio, 0);
17 gpio_set_mode(gpio, GPIO_MODE_GPIO);
18 pinmux_set_config(gpio >> GPIO_PINMUX_SHIFT, pinmux_config);
19 }
20
__gpio_output(gpio_t gpio,int value,u32 od)21 static void __gpio_output(gpio_t gpio, int value, u32 od)
22 {
23 gpio_set_int_enable(gpio, 0);
24 gpio_set(gpio, value);
25 gpio_set_out_enable(gpio, 1);
26 gpio_set_mode(gpio, GPIO_MODE_GPIO);
27 pinmux_set_config(gpio >> GPIO_PINMUX_SHIFT, PINMUX_PULL_NONE | od);
28 }
29
30 static const struct gpio_bank *gpio_banks = (void *)TEGRA_GPIO_BASE;
31
gpio_read_port(int index,size_t offset)32 static u32 gpio_read_port(int index, size_t offset)
33 {
34 int bank = index / GPIO_GPIOS_PER_BANK;
35 int port = (index - bank * GPIO_GPIOS_PER_BANK) / GPIO_GPIOS_PER_PORT;
36
37 return read32((u8 *)&gpio_banks[bank] + offset +
38 port * sizeof(u32));
39 }
40
gpio_write_port(int index,size_t offset,u32 mask,u32 value)41 static void gpio_write_port(int index, size_t offset, u32 mask, u32 value)
42 {
43 int bank = index / GPIO_GPIOS_PER_BANK;
44 int port = (index - bank * GPIO_GPIOS_PER_BANK) / GPIO_GPIOS_PER_PORT;
45
46 u32 reg = read32((u8 *)&gpio_banks[bank] + offset +
47 port * sizeof(u32));
48 u32 new_reg = (reg & ~mask) | (value & mask);
49
50 if (new_reg != reg) {
51 write32((u8 *)&gpio_banks[bank] + offset + port * sizeof(u32),
52 new_reg);
53 }
54 }
55
gpio_set_mode(gpio_t gpio,enum gpio_mode mode)56 void gpio_set_mode(gpio_t gpio, enum gpio_mode mode)
57 {
58 int bit = gpio % GPIO_GPIOS_PER_PORT;
59 gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
60 offsetof(struct gpio_bank, config),
61 1 << bit, mode ? (1 << bit) : 0);
62 }
63
gpio_get_mode(gpio_t gpio)64 int gpio_get_mode(gpio_t gpio)
65 {
66 int bit = gpio % GPIO_GPIOS_PER_PORT;
67 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
68 offsetof(struct gpio_bank, config));
69 return (port & (1 << bit)) != 0;
70 }
71
gpio_set_lock(gpio_t gpio)72 void gpio_set_lock(gpio_t gpio)
73 {
74 int bit = gpio % GPIO_GPIOS_PER_PORT + GPIO_GPIOS_PER_PORT;
75 gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
76 offsetof(struct gpio_bank, config),
77 1 << bit, 1 << bit);
78 }
79
gpio_get_lock(gpio_t gpio)80 int gpio_get_lock(gpio_t gpio)
81 {
82 int bit = gpio % GPIO_GPIOS_PER_PORT + GPIO_GPIOS_PER_PORT;
83 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
84 offsetof(struct gpio_bank, config));
85 return (port & (1 << bit)) != 0;
86 }
87
gpio_set_out_enable(gpio_t gpio,int enable)88 void gpio_set_out_enable(gpio_t gpio, int enable)
89 {
90 int bit = gpio % GPIO_GPIOS_PER_PORT;
91 gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
92 offsetof(struct gpio_bank, out_enable),
93 1 << bit, enable ? (1 << bit) : 0);
94 }
95
gpio_get_out_enable(gpio_t gpio)96 int gpio_get_out_enable(gpio_t gpio)
97 {
98 int bit = gpio % GPIO_GPIOS_PER_PORT;
99 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
100 offsetof(struct gpio_bank, out_enable));
101 return (port & (1 << bit)) != 0;
102 }
103
gpio_set(gpio_t gpio,int value)104 void gpio_set(gpio_t gpio, int value)
105 {
106 int bit = gpio % GPIO_GPIOS_PER_PORT;
107 gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
108 offsetof(struct gpio_bank, out_value),
109 1 << bit, value ? (1 << bit) : 0);
110 }
111
gpio_get_out_value(gpio_t gpio)112 int gpio_get_out_value(gpio_t gpio)
113 {
114 int bit = gpio % GPIO_GPIOS_PER_PORT;
115 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
116 offsetof(struct gpio_bank, out_value));
117 return (port & (1 << bit)) != 0;
118 }
119
gpio_get(gpio_t gpio)120 int gpio_get(gpio_t gpio)
121 {
122 int bit = gpio % GPIO_GPIOS_PER_PORT;
123 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
124 offsetof(struct gpio_bank, in_value));
125 return (port & (1 << bit)) != 0;
126 }
127
gpio_get_int_status(gpio_t gpio)128 int gpio_get_int_status(gpio_t gpio)
129 {
130 int bit = gpio % GPIO_GPIOS_PER_PORT;
131 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
132 offsetof(struct gpio_bank, int_status));
133 return (port & (1 << bit)) != 0;
134 }
135
gpio_set_int_enable(gpio_t gpio,int enable)136 void gpio_set_int_enable(gpio_t gpio, int enable)
137 {
138 int bit = gpio % GPIO_GPIOS_PER_PORT;
139 gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
140 offsetof(struct gpio_bank, int_enable),
141 1 << bit, enable ? (1 << bit) : 0);
142 }
143
gpio_get_int_enable(gpio_t gpio)144 int gpio_get_int_enable(gpio_t gpio)
145 {
146 int bit = gpio % GPIO_GPIOS_PER_PORT;
147 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
148 offsetof(struct gpio_bank, int_enable));
149 return (port & (1 << bit)) != 0;
150 }
151
gpio_set_int_level(gpio_t gpio,int high_rise,int edge,int delta)152 void gpio_set_int_level(gpio_t gpio, int high_rise, int edge, int delta)
153 {
154 int bit = gpio % GPIO_GPIOS_PER_PORT;
155 u32 value = (high_rise ? (0x000001 << bit) : 0) |
156 (edge ? (0x000100 << bit) : 0) |
157 (delta ? (0x010000 << bit) : 0);
158 gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
159 offsetof(struct gpio_bank, config),
160 0x010101 << bit, value);
161 }
162
gpio_get_int_level(gpio_t gpio,int * high_rise,int * edge,int * delta)163 void gpio_get_int_level(gpio_t gpio, int *high_rise, int *edge, int *delta)
164 {
165 int bit = gpio % GPIO_GPIOS_PER_PORT;
166 u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
167 offsetof(struct gpio_bank, int_level));
168 *high_rise = ((port & (0x000001 << bit)) != 0);
169 *edge = ((port & (0x000100 << bit)) != 0);
170 *delta = ((port & (0x010000 << bit)) != 0);
171 }
172
gpio_set_int_clear(gpio_t gpio)173 void gpio_set_int_clear(gpio_t gpio)
174 {
175 int bit = gpio % GPIO_GPIOS_PER_PORT;
176 gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1),
177 offsetof(struct gpio_bank, int_clear),
178 1 << bit, 1 << bit);
179 }
180
gpio_input_pulldown(gpio_t gpio)181 void gpio_input_pulldown(gpio_t gpio)
182 {
183 __gpio_input(gpio, PINMUX_PULL_DOWN);
184 }
185
gpio_input_pullup(gpio_t gpio)186 void gpio_input_pullup(gpio_t gpio)
187 {
188 __gpio_input(gpio, PINMUX_PULL_UP);
189 }
190
gpio_input(gpio_t gpio)191 void gpio_input(gpio_t gpio)
192 {
193 __gpio_input(gpio, PINMUX_PULL_NONE);
194 }
195
gpio_output(gpio_t gpio,int value)196 void gpio_output(gpio_t gpio, int value)
197 {
198 __gpio_output(gpio, value, 0);
199 }
200
gpio_output_open_drain(gpio_t gpio,int value)201 void gpio_output_open_drain(gpio_t gpio, int value)
202 {
203 __gpio_output(gpio, value, PINMUX_OPEN_DRAIN);
204 }
205