]>
Commit | Line | Data |
---|---|---|
e7ae4cf2 DW |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * (C) Copyright 2019 Rockchip Electronics Co., Ltd | |
4 | */ | |
5 | ||
6 | #include <common.h> | |
7 | #include <dm.h> | |
f7ae49fc | 8 | #include <log.h> |
e7ae4cf2 DW |
9 | #include <dm/pinctrl.h> |
10 | #include <regmap.h> | |
11 | #include <syscon.h> | |
cd93d625 | 12 | #include <linux/bitops.h> |
e7ae4cf2 DW |
13 | |
14 | #include "pinctrl-rockchip.h" | |
15 | ||
16 | static struct rockchip_mux_route_data rk3399_mux_route_data[] = { | |
17 | { | |
18 | /* uart2dbga_rx */ | |
19 | .bank_num = 4, | |
20 | .pin = 8, | |
21 | .func = 2, | |
22 | .route_offset = 0xe21c, | |
23 | .route_val = BIT(16 + 10) | BIT(16 + 11), | |
24 | }, { | |
25 | /* uart2dbgb_rx */ | |
26 | .bank_num = 4, | |
27 | .pin = 16, | |
28 | .func = 2, | |
29 | .route_offset = 0xe21c, | |
30 | .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(10), | |
31 | }, { | |
32 | /* uart2dbgc_rx */ | |
33 | .bank_num = 4, | |
34 | .pin = 19, | |
35 | .func = 1, | |
36 | .route_offset = 0xe21c, | |
37 | .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(11), | |
38 | }, { | |
39 | /* pcie_clkreqn */ | |
40 | .bank_num = 2, | |
41 | .pin = 26, | |
42 | .func = 2, | |
43 | .route_offset = 0xe21c, | |
44 | .route_val = BIT(16 + 14), | |
45 | }, { | |
46 | /* pcie_clkreqnb */ | |
47 | .bank_num = 4, | |
48 | .pin = 24, | |
49 | .func = 1, | |
50 | .route_offset = 0xe21c, | |
51 | .route_val = BIT(16 + 14) | BIT(14), | |
52 | }, | |
53 | }; | |
54 | ||
54e75702 DW |
55 | static int rk3399_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) |
56 | { | |
57 | struct rockchip_pinctrl_priv *priv = bank->priv; | |
58 | int iomux_num = (pin / 8); | |
59 | struct regmap *regmap; | |
60 | int reg, ret, mask, mux_type; | |
61 | u8 bit; | |
62 | u32 data, route_reg, route_val; | |
63 | ||
64 | regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) | |
65 | ? priv->regmap_pmu : priv->regmap_base; | |
66 | ||
67 | /* get basic quadrupel of mux registers and the correct reg inside */ | |
68 | mux_type = bank->iomux[iomux_num].type; | |
69 | reg = bank->iomux[iomux_num].offset; | |
70 | reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask); | |
71 | ||
72 | if (bank->route_mask & BIT(pin)) { | |
73 | if (rockchip_get_mux_route(bank, pin, mux, &route_reg, | |
74 | &route_val)) { | |
75 | ret = regmap_write(regmap, route_reg, route_val); | |
76 | if (ret) | |
77 | return ret; | |
78 | } | |
79 | } | |
80 | ||
81 | data = (mask << (bit + 16)); | |
82 | data |= (mux & mask) << bit; | |
83 | ret = regmap_write(regmap, reg, data); | |
84 | ||
85 | return ret; | |
86 | } | |
87 | ||
e7ae4cf2 DW |
88 | #define RK3399_PULL_GRF_OFFSET 0xe040 |
89 | #define RK3399_PULL_PMU_OFFSET 0x40 | |
90 | ||
91 | static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, | |
92 | int pin_num, struct regmap **regmap, | |
93 | int *reg, u8 *bit) | |
94 | { | |
95 | struct rockchip_pinctrl_priv *priv = bank->priv; | |
96 | ||
97 | /* The bank0:16 and bank1:32 pins are located in PMU */ | |
98 | if (bank->bank_num == 0 || bank->bank_num == 1) { | |
99 | *regmap = priv->regmap_pmu; | |
100 | *reg = RK3399_PULL_PMU_OFFSET; | |
101 | ||
102 | *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; | |
e7ae4cf2 DW |
103 | } else { |
104 | *regmap = priv->regmap_base; | |
105 | *reg = RK3399_PULL_GRF_OFFSET; | |
106 | ||
107 | /* correct the offset, as we're starting with the 3rd bank */ | |
108 | *reg -= 0x20; | |
109 | *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; | |
743a7737 DW |
110 | } |
111 | ||
112 | *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); | |
113 | ||
114 | *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); | |
115 | *bit *= ROCKCHIP_PULL_BITS_PER_PIN; | |
116 | } | |
117 | ||
118 | static int rk3399_set_pull(struct rockchip_pin_bank *bank, | |
119 | int pin_num, int pull) | |
120 | { | |
121 | struct regmap *regmap; | |
122 | int reg, ret; | |
123 | u8 bit, type; | |
124 | u32 data; | |
e7ae4cf2 | 125 | |
743a7737 DW |
126 | if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) |
127 | return -ENOTSUPP; | |
128 | ||
129 | rk3399_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); | |
130 | type = bank->pull_type[pin_num / 8]; | |
131 | ret = rockchip_translate_pull_value(type, pull); | |
132 | if (ret < 0) { | |
133 | debug("unsupported pull setting %d\n", pull); | |
134 | return ret; | |
e7ae4cf2 | 135 | } |
743a7737 DW |
136 | |
137 | /* enable the write to the equivalent lower bits */ | |
138 | data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); | |
139 | data |= (ret << bit); | |
140 | ret = regmap_write(regmap, reg, data); | |
141 | ||
142 | return ret; | |
e7ae4cf2 DW |
143 | } |
144 | ||
145 | static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, | |
146 | int pin_num, struct regmap **regmap, | |
147 | int *reg, u8 *bit) | |
148 | { | |
149 | struct rockchip_pinctrl_priv *priv = bank->priv; | |
150 | int drv_num = (pin_num / 8); | |
151 | ||
152 | /* The bank0:16 and bank1:32 pins are located in PMU */ | |
153 | if (bank->bank_num == 0 || bank->bank_num == 1) | |
154 | *regmap = priv->regmap_pmu; | |
155 | else | |
156 | *regmap = priv->regmap_base; | |
157 | ||
158 | *reg = bank->drv[drv_num].offset; | |
159 | if (bank->drv[drv_num].drv_type == DRV_TYPE_IO_1V8_3V0_AUTO || | |
160 | bank->drv[drv_num].drv_type == DRV_TYPE_IO_3V3_ONLY) | |
161 | *bit = (pin_num % 8) * 3; | |
162 | else | |
163 | *bit = (pin_num % 8) * 2; | |
164 | } | |
165 | ||
625ab11f DW |
166 | static int rk3399_set_drive(struct rockchip_pin_bank *bank, |
167 | int pin_num, int strength) | |
168 | { | |
169 | struct regmap *regmap; | |
170 | int reg, ret; | |
171 | u32 data, rmask_bits, temp; | |
172 | u8 bit; | |
173 | int drv_type = bank->drv[pin_num / 8].drv_type; | |
174 | ||
175 | rk3399_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); | |
176 | ret = rockchip_translate_drive_value(drv_type, strength); | |
177 | if (ret < 0) { | |
178 | debug("unsupported driver strength %d\n", strength); | |
179 | return ret; | |
180 | } | |
181 | ||
182 | switch (drv_type) { | |
183 | case DRV_TYPE_IO_1V8_3V0_AUTO: | |
184 | case DRV_TYPE_IO_3V3_ONLY: | |
185 | rmask_bits = ROCKCHIP_DRV_3BITS_PER_PIN; | |
186 | switch (bit) { | |
187 | case 0 ... 12: | |
188 | /* regular case, nothing to do */ | |
189 | break; | |
190 | case 15: | |
191 | /* | |
192 | * drive-strength offset is special, as it is spread | |
193 | * over 2 registers, the bit data[15] contains bit 0 | |
194 | * of the value while temp[1:0] contains bits 2 and 1 | |
195 | */ | |
196 | data = (ret & 0x1) << 15; | |
197 | temp = (ret >> 0x1) & 0x3; | |
198 | ||
199 | data |= BIT(31); | |
200 | ret = regmap_write(regmap, reg, data); | |
201 | if (ret) | |
202 | return ret; | |
203 | ||
204 | temp |= (0x3 << 16); | |
205 | reg += 0x4; | |
206 | ret = regmap_write(regmap, reg, temp); | |
207 | ||
208 | return ret; | |
209 | case 18 ... 21: | |
210 | /* setting fully enclosed in the second register */ | |
211 | reg += 4; | |
212 | bit -= 16; | |
213 | break; | |
214 | default: | |
215 | debug("unsupported bit: %d for pinctrl drive type: %d\n", | |
216 | bit, drv_type); | |
217 | return -EINVAL; | |
218 | } | |
219 | break; | |
220 | case DRV_TYPE_IO_DEFAULT: | |
221 | case DRV_TYPE_IO_1V8_OR_3V0: | |
222 | case DRV_TYPE_IO_1V8_ONLY: | |
223 | rmask_bits = ROCKCHIP_DRV_BITS_PER_PIN; | |
224 | break; | |
225 | default: | |
226 | debug("unsupported pinctrl drive type: %d\n", | |
227 | drv_type); | |
228 | return -EINVAL; | |
229 | } | |
230 | ||
231 | /* enable the write to the equivalent lower bits */ | |
232 | data = ((1 << rmask_bits) - 1) << (bit + 16); | |
233 | data |= (ret << bit); | |
234 | ret = regmap_write(regmap, reg, data); | |
235 | ||
236 | return ret; | |
237 | } | |
238 | ||
e7ae4cf2 DW |
239 | static struct rockchip_pin_bank rk3399_pin_banks[] = { |
240 | PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0", | |
241 | IOMUX_SOURCE_PMU, | |
242 | IOMUX_SOURCE_PMU, | |
243 | IOMUX_SOURCE_PMU, | |
244 | IOMUX_SOURCE_PMU, | |
245 | DRV_TYPE_IO_1V8_ONLY, | |
246 | DRV_TYPE_IO_1V8_ONLY, | |
247 | DRV_TYPE_IO_DEFAULT, | |
248 | DRV_TYPE_IO_DEFAULT, | |
249 | 0x80, | |
250 | 0x88, | |
251 | -1, | |
252 | -1, | |
253 | PULL_TYPE_IO_1V8_ONLY, | |
254 | PULL_TYPE_IO_1V8_ONLY, | |
255 | PULL_TYPE_IO_DEFAULT, | |
256 | PULL_TYPE_IO_DEFAULT | |
257 | ), | |
258 | PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU, | |
259 | IOMUX_SOURCE_PMU, | |
260 | IOMUX_SOURCE_PMU, | |
261 | IOMUX_SOURCE_PMU, | |
262 | DRV_TYPE_IO_1V8_OR_3V0, | |
263 | DRV_TYPE_IO_1V8_OR_3V0, | |
264 | DRV_TYPE_IO_1V8_OR_3V0, | |
265 | DRV_TYPE_IO_1V8_OR_3V0, | |
266 | 0xa0, | |
267 | 0xa8, | |
268 | 0xb0, | |
269 | 0xb8 | |
270 | ), | |
271 | PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0, | |
272 | DRV_TYPE_IO_1V8_OR_3V0, | |
273 | DRV_TYPE_IO_1V8_ONLY, | |
274 | DRV_TYPE_IO_1V8_ONLY, | |
275 | PULL_TYPE_IO_DEFAULT, | |
276 | PULL_TYPE_IO_DEFAULT, | |
277 | PULL_TYPE_IO_1V8_ONLY, | |
278 | PULL_TYPE_IO_1V8_ONLY | |
279 | ), | |
280 | PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY, | |
281 | DRV_TYPE_IO_3V3_ONLY, | |
282 | DRV_TYPE_IO_3V3_ONLY, | |
283 | DRV_TYPE_IO_1V8_OR_3V0 | |
284 | ), | |
285 | PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0, | |
286 | DRV_TYPE_IO_1V8_3V0_AUTO, | |
287 | DRV_TYPE_IO_1V8_OR_3V0, | |
288 | DRV_TYPE_IO_1V8_OR_3V0 | |
289 | ), | |
290 | }; | |
291 | ||
292 | static struct rockchip_pin_ctrl rk3399_pin_ctrl = { | |
8541beb8 DW |
293 | .pin_banks = rk3399_pin_banks, |
294 | .nr_banks = ARRAY_SIZE(rk3399_pin_banks), | |
8541beb8 DW |
295 | .grf_mux_offset = 0xe000, |
296 | .pmu_mux_offset = 0x0, | |
297 | .grf_drv_offset = 0xe100, | |
298 | .pmu_drv_offset = 0x80, | |
299 | .iomux_routes = rk3399_mux_route_data, | |
300 | .niomux_routes = ARRAY_SIZE(rk3399_mux_route_data), | |
54e75702 | 301 | .set_mux = rk3399_set_mux, |
743a7737 | 302 | .set_pull = rk3399_set_pull, |
625ab11f | 303 | .set_drive = rk3399_set_drive, |
e7ae4cf2 DW |
304 | }; |
305 | ||
306 | static const struct udevice_id rk3399_pinctrl_ids[] = { | |
307 | { | |
308 | .compatible = "rockchip,rk3399-pinctrl", | |
309 | .data = (ulong)&rk3399_pin_ctrl | |
310 | }, | |
311 | { } | |
312 | }; | |
313 | ||
314 | U_BOOT_DRIVER(pinctrl_rk3399) = { | |
315 | .name = "rockchip_rk3399_pinctrl", | |
316 | .id = UCLASS_PINCTRL, | |
317 | .of_match = rk3399_pinctrl_ids, | |
318 | .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), | |
319 | .ops = &rockchip_pinctrl_ops, | |
320 | #if !CONFIG_IS_ENABLED(OF_PLATDATA) | |
321 | .bind = dm_scan_fdt_dev, | |
322 | #endif | |
323 | .probe = rockchip_pinctrl_probe, | |
324 | }; |