aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/rockchip/pinctrl_rk3399.c')
-rw-r--r--drivers/pinctrl/rockchip/pinctrl_rk3399.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3399.c b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
index bc92dd7c06..5c5af3a0bd 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3399.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3399.c
@@ -1,6 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0+ 1// SPDX-License-Identifier: GPL-2.0+
2/* 2/*
3 * (C) Copyright 2016 Rockchip Electronics Co., Ltd 3 * (C) Copyright 2016 Rockchip Electronics Co., Ltd
4 * (C) 2018 Theobroma Systems Design und Consulting GmbH
4 */ 5 */
5 6
6#include <common.h> 7#include <common.h>
@@ -14,11 +15,241 @@
14#include <asm/arch/clock.h> 15#include <asm/arch/clock.h>
15#include <dm/pinctrl.h> 16#include <dm/pinctrl.h>
16 17
18#if CONFIG_IS_ENABLED(PINCTRL_ROCKCHIP_RK3399_FULL)
19static const u32 RK_GRF_P_PULLUP = 1;
20static const u32 RK_GRF_P_PULLDOWN = 2;
21#endif /* PINCTRL_ROCKCHIP_RK3399_FULL */
22
17struct rk3399_pinctrl_priv { 23struct rk3399_pinctrl_priv {
18 struct rk3399_grf_regs *grf; 24 struct rk3399_grf_regs *grf;
19 struct rk3399_pmugrf_regs *pmugrf; 25 struct rk3399_pmugrf_regs *pmugrf;
26 struct rockchip_pin_bank *banks;
27};
28
29#if CONFIG_IS_ENABLED(PINCTRL_ROCKCHIP_RK3399_FULL)
30/* Location of pinctrl/pinconf registers. */
31enum rk_grf_location {
32 RK_GRF,
33 RK_PMUGRF,
34};
35
36/**
37 * @nr_pins: number of pins in this bank
38 * @grf_location: location of pinctrl/pinconf registers
39 * @bank_num: number of the bank, to account for holes
40 * @iomux: array describing the 4 iomux sources of the bank
41 */
42struct rockchip_pin_bank {
43 u8 nr_pins;
44 enum rk_grf_location grf_location;
45 size_t iomux_offset;
46 size_t pupd_offset;
20}; 47};
21 48
49#define PIN_BANK(pins, grf, iomux, pupd) \
50 { \
51 .nr_pins = pins, \
52 .grf_location = grf, \
53 .iomux_offset = iomux, \
54 .pupd_offset = pupd, \
55 }
56
57static struct rockchip_pin_bank rk3399_pin_banks[] = {
58 PIN_BANK(16, RK_PMUGRF,
59 offsetof(struct rk3399_pmugrf_regs, gpio0a_iomux),
60 offsetof(struct rk3399_pmugrf_regs, gpio0_p)),
61 PIN_BANK(32, RK_PMUGRF,
62 offsetof(struct rk3399_pmugrf_regs, gpio1a_iomux),
63 offsetof(struct rk3399_pmugrf_regs, gpio1_p)),
64 PIN_BANK(32, RK_GRF,
65 offsetof(struct rk3399_grf_regs, gpio2a_iomux),
66 offsetof(struct rk3399_grf_regs, gpio2_p)),
67 PIN_BANK(32, RK_GRF,
68 offsetof(struct rk3399_grf_regs, gpio3a_iomux),
69 offsetof(struct rk3399_grf_regs, gpio3_p)),
70 PIN_BANK(32, RK_GRF,
71 offsetof(struct rk3399_grf_regs, gpio4a_iomux),
72 offsetof(struct rk3399_grf_regs, gpio4_p)),
73};
74
75static void rk_pinctrl_get_info(uintptr_t base, u32 index, uintptr_t *addr,
76 u32 *shift, u32 *mask)
77{
78 /*
79 * In general we four subsequent 32-bit configuration registers
80 * per bank (e.g. GPIO2A_P, GPIO2B_P, GPIO2C_P, GPIO2D_P).
81 * The configuration for each pin has two bits.
82 *
83 * @base...contains the address to the first register.
84 * @index...defines the pin within the bank (0..31).
85 * @addr...will be the address of the actual register to use
86 * @shift...will be the bit position in the configuration register
87 * @mask...will be the (unshifted) mask
88 */
89
90 const u32 pins_per_register = 8;
91 const u32 config_bits_per_pin = 2;
92
93 /* Get the address of the configuration register. */
94 *addr = base + (index / pins_per_register) * sizeof(u32);
95
96 /* Get the bit offset within the configuration register. */
97 *shift = (index & (pins_per_register - 1)) * config_bits_per_pin;
98
99 /* Get the (unshifted) mask for the configuration pins. */
100 *mask = ((1 << config_bits_per_pin) - 1);
101
102 pr_debug("%s: addr=0x%lx, mask=0x%x, shift=0x%x\n",
103 __func__, *addr, *mask, *shift);
104}
105
106static void rk3399_pinctrl_set_pin_iomux(uintptr_t grf_addr,
107 struct rockchip_pin_bank *bank,
108 u32 index, u32 muxval)
109{
110 uintptr_t iomux_base, addr;
111 u32 shift, mask;
112
113 iomux_base = grf_addr + bank->iomux_offset;
114 rk_pinctrl_get_info(iomux_base, index, &addr, &shift, &mask);
115
116 /* Set pinmux register */
117 rk_clrsetreg(addr, mask << shift, muxval << shift);
118}
119
120static void rk3399_pinctrl_set_pin_pupd(uintptr_t grf_addr,
121 struct rockchip_pin_bank *bank,
122 u32 index, int pinconfig)
123{
124 uintptr_t pupd_base, addr;
125 u32 shift, mask, pupdval;
126
127 /* Fast path in case there's nothing to do. */
128 if (!pinconfig)
129 return;
130
131 if (pinconfig & (1 << PIN_CONFIG_BIAS_PULL_UP))
132 pupdval = RK_GRF_P_PULLUP;
133 else if (pinconfig & (1 << PIN_CONFIG_BIAS_PULL_DOWN)) {
134 pupdval = RK_GRF_P_PULLDOWN;
135 } else {
136 /* Flag not supported. */
137 pr_warn("%s: Unsupported pinconfig flag: 0x%x\n", __func__,
138 pinconfig);
139 return;
140 }
141
142 pupd_base = grf_addr + (uintptr_t)bank->pupd_offset;
143 rk_pinctrl_get_info(pupd_base, index, &addr, &shift, &mask);
144
145 /* Set pull-up/pull-down regisrer */
146 rk_clrsetreg(addr, mask << shift, pupdval << shift);
147}
148
149static int rk3399_pinctrl_set_pin(struct udevice *dev, u32 banknum, u32 index,
150 u32 muxval, int pinconfig)
151{
152 struct rk3399_pinctrl_priv *priv = dev_get_priv(dev);
153 struct rockchip_pin_bank *bank = &priv->banks[banknum];
154 uintptr_t grf_addr;
155
156 pr_debug("%s: 0x%x 0x%x 0x%x 0x%x\n", __func__, banknum, index, muxval,
157 pinconfig);
158
159 if (bank->grf_location == RK_GRF)
160 grf_addr = (uintptr_t)priv->grf;
161 else if (bank->grf_location == RK_PMUGRF)
162 grf_addr = (uintptr_t)priv->pmugrf;
163 else
164 return -EINVAL;
165
166 rk3399_pinctrl_set_pin_iomux(grf_addr, bank, index, muxval);
167
168 rk3399_pinctrl_set_pin_pupd(grf_addr, bank, index, pinconfig);
169 return 0;
170}
171
172static int rk3399_pinctrl_set_state(struct udevice *dev, struct udevice *config)
173{
174 /*
175 * The order of the fields in this struct must match the order of
176 * the fields in the "rockchip,pins" property.
177 */
178 struct rk_pin {
179 u32 banknum;
180 u32 index;
181 u32 muxval;
182 u32 phandle;
183 } __packed;
184
185 u32 *fields = NULL;
186 const int fields_per_pin = 4;
187 int num_fields, num_pins;
188 int ret;
189 int size;
190 int i;
191 struct rk_pin *pin;
192
193 pr_debug("%s: %s\n", __func__, config->name);
194
195 size = dev_read_size(config, "rockchip,pins");
196 if (size < 0)
197 return -EINVAL;
198
199 num_fields = size / sizeof(u32);
200 num_pins = num_fields / fields_per_pin;
201
202 if (num_fields * sizeof(u32) != size ||
203 num_pins * fields_per_pin != num_fields) {
204 pr_warn("Invalid number of rockchip,pins fields.\n");
205 return -EINVAL;
206 }
207
208 fields = calloc(num_fields, sizeof(u32));
209 if (!fields)
210 return -ENOMEM;
211
212 ret = dev_read_u32_array(config, "rockchip,pins", fields, num_fields);
213 if (ret) {
214 pr_warn("%s: Failed to read rockchip,pins fields.\n",
215 config->name);
216 goto end;
217 }
218
219 pin = (struct rk_pin *)fields;
220 for (i = 0; i < num_pins; i++, pin++) {
221 struct udevice *dev_pinconfig;
222 int pinconfig;
223
224 ret = uclass_get_device_by_phandle_id(UCLASS_PINCONFIG,
225 pin->phandle,
226 &dev_pinconfig);
227 if (ret) {
228 pr_debug("Could not get pinconfig device\n");
229 goto end;
230 }
231
232 pinconfig = pinctrl_decode_pin_config_dm(dev_pinconfig);
233 if (pinconfig < 0) {
234 pr_warn("Could not parse pinconfig\n");
235 goto end;
236 }
237
238 ret = rk3399_pinctrl_set_pin(dev, pin->banknum, pin->index,
239 pin->muxval, pinconfig);
240 if (ret) {
241 pr_warn("Could not set pinctrl settings\n");
242 goto end;
243 }
244 }
245
246end:
247 free(fields);
248 return ret;
249}
250
251#endif /* PINCTRL_ROCKCHIP_RK3399_FULL */
252
22static void pinctrl_rk3399_pwm_config(struct rk3399_grf_regs *grf, 253static void pinctrl_rk3399_pwm_config(struct rk3399_grf_regs *grf,
23 struct rk3399_pmugrf_regs *pmugrf, int pwm_id) 254 struct rk3399_pmugrf_regs *pmugrf, int pwm_id)
24{ 255{
@@ -468,6 +699,9 @@ static int rk3399_pinctrl_set_state_simple(struct udevice *dev,
468} 699}
469 700
470static struct pinctrl_ops rk3399_pinctrl_ops = { 701static struct pinctrl_ops rk3399_pinctrl_ops = {
702#if CONFIG_IS_ENABLED(PINCTRL_ROCKCHIP_RK3399_FULL)
703 .set_state = rk3399_pinctrl_set_state,
704#endif
471 .set_state_simple = rk3399_pinctrl_set_state_simple, 705 .set_state_simple = rk3399_pinctrl_set_state_simple,
472 .request = rk3399_pinctrl_request, 706 .request = rk3399_pinctrl_request,
473 .get_periph_id = rk3399_pinctrl_get_periph_id, 707 .get_periph_id = rk3399_pinctrl_get_periph_id,
@@ -481,6 +715,9 @@ static int rk3399_pinctrl_probe(struct udevice *dev)
481 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 715 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
482 priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF); 716 priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
483 debug("%s: grf=%p, pmugrf=%p\n", __func__, priv->grf, priv->pmugrf); 717 debug("%s: grf=%p, pmugrf=%p\n", __func__, priv->grf, priv->pmugrf);
718#if CONFIG_IS_ENABLED(PINCTRL_ROCKCHIP_RK3399_FULL)
719 priv->banks = rk3399_pin_banks;
720#endif /* PINCTRL_ROCKCHIP_RK3399_FULL */
484 721
485 return ret; 722 return ret;
486} 723}