blob: 3870c1b7a341f998cc0b3cfcaa3a0acbdd0daa39 [file] [log] [blame]
David Wu5f596ae2019-01-02 21:00:55 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2019 Rockchip Electronics Co., Ltd
4 */
5
David Wu5f596ae2019-01-02 21:00:55 +08006#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06007#include <log.h>
David Wu5f596ae2019-01-02 21:00:55 +08008#include <dm/pinctrl.h>
9#include <regmap.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060010#include <linux/bitops.h>
David Wu5f596ae2019-01-02 21:00:55 +080011
12#include "pinctrl-rockchip.h"
13
14static struct rockchip_mux_route_data rk3288_mux_route_data[] = {
15 {
16 /* edphdmi_cecinoutt1 */
17 .bank_num = 7,
18 .pin = 16,
19 .func = 2,
20 .route_offset = 0x264,
21 .route_val = BIT(16 + 12) | BIT(12),
22 }, {
23 /* edphdmi_cecinout */
24 .bank_num = 7,
25 .pin = 23,
26 .func = 4,
27 .route_offset = 0x264,
28 .route_val = BIT(16 + 12),
29 },
30};
31
David Wu3dd7d6c2019-04-16 21:50:55 +080032static int rk3288_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
33{
34 struct rockchip_pinctrl_priv *priv = bank->priv;
35 int iomux_num = (pin / 8);
36 struct regmap *regmap;
37 int reg, ret, mask, mux_type;
38 u8 bit;
Jagan Teki9e0e6812022-12-14 23:20:56 +053039 u32 data;
David Wu3dd7d6c2019-04-16 21:50:55 +080040
41 regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
42 ? priv->regmap_pmu : priv->regmap_base;
43
44 /* get basic quadrupel of mux registers and the correct reg inside */
45 mux_type = bank->iomux[iomux_num].type;
46 reg = bank->iomux[iomux_num].offset;
47 reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
48
David Wu84248ec2019-04-16 21:50:56 +080049 /* bank0 is special, there are no higher 16 bit writing bits. */
50 if (bank->bank_num == 0) {
51 regmap_read(regmap, reg, &data);
52 data &= ~(mask << bit);
53 } else {
54 /* enable the write to the equivalent lower bits */
55 data = (mask << (bit + 16));
56 }
57
David Wu3dd7d6c2019-04-16 21:50:55 +080058 data |= (mux & mask) << bit;
59 ret = regmap_write(regmap, reg, data);
60
61 return ret;
62}
63
David Wu5f596ae2019-01-02 21:00:55 +080064#define RK3288_PULL_OFFSET 0x140
65#define RK3288_PULL_PMU_OFFSET 0x64
66
67static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
68 int pin_num, struct regmap **regmap,
69 int *reg, u8 *bit)
70{
71 struct rockchip_pinctrl_priv *priv = bank->priv;
72
73 /* The first 24 pins of the first bank are located in PMU */
74 if (bank->bank_num == 0) {
75 *regmap = priv->regmap_pmu;
76 *reg = RK3288_PULL_PMU_OFFSET;
David Wu5f596ae2019-01-02 21:00:55 +080077 } else {
78 *regmap = priv->regmap_base;
79 *reg = RK3288_PULL_OFFSET;
80
81 /* correct the offset, as we're starting with the 2nd bank */
82 *reg -= 0x10;
83 *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE;
David Wu2972c452019-04-16 21:57:05 +080084 }
85
86 *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4);
87
88 *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG);
89 *bit *= ROCKCHIP_PULL_BITS_PER_PIN;
90}
91
92static int rk3288_set_pull(struct rockchip_pin_bank *bank,
93 int pin_num, int pull)
94{
95 struct regmap *regmap;
96 int reg, ret;
97 u8 bit, type;
98 u32 data;
99
100 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
101 return -ENOTSUPP;
David Wu5f596ae2019-01-02 21:00:55 +0800102
David Wu2972c452019-04-16 21:57:05 +0800103 rk3288_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
104 type = bank->pull_type[pin_num / 8];
105 ret = rockchip_translate_pull_value(type, pull);
106 if (ret < 0) {
107 debug("unsupported pull setting %d\n", pull);
108 return ret;
David Wu5f596ae2019-01-02 21:00:55 +0800109 }
David Wu2972c452019-04-16 21:57:05 +0800110
David Wu2e6959e2019-04-16 21:57:28 +0800111 /* bank0 is special, there are no higher 16 bit writing bits */
112 if (bank->bank_num == 0) {
113 regmap_read(regmap, reg, &data);
114 data &= ~(((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << bit);
115 } else {
116 /* enable the write to the equivalent lower bits */
117 data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
118 }
119
David Wu2972c452019-04-16 21:57:05 +0800120 data |= (ret << bit);
121 ret = regmap_write(regmap, reg, data);
122
123 return ret;
David Wu5f596ae2019-01-02 21:00:55 +0800124}
125
126#define RK3288_DRV_PMU_OFFSET 0x70
127#define RK3288_DRV_GRF_OFFSET 0x1c0
128
129static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
130 int pin_num, struct regmap **regmap,
131 int *reg, u8 *bit)
132{
133 struct rockchip_pinctrl_priv *priv = bank->priv;
134
135 /* The first 24 pins of the first bank are located in PMU */
136 if (bank->bank_num == 0) {
137 *regmap = priv->regmap_pmu;
138 *reg = RK3288_DRV_PMU_OFFSET;
David Wu5f596ae2019-01-02 21:00:55 +0800139 } else {
140 *regmap = priv->regmap_base;
141 *reg = RK3288_DRV_GRF_OFFSET;
142
143 /* correct the offset, as we're starting with the 2nd bank */
144 *reg -= 0x10;
145 *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE;
David Wu40a55482019-04-16 21:55:26 +0800146 }
147
148 *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4);
149 *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG);
150 *bit *= ROCKCHIP_DRV_BITS_PER_PIN;
151}
152
153static int rk3288_set_drive(struct rockchip_pin_bank *bank,
154 int pin_num, int strength)
155{
156 struct regmap *regmap;
157 int reg, ret;
158 u32 data;
159 u8 bit;
160 int type = bank->drv[pin_num / 8].drv_type;
David Wu5f596ae2019-01-02 21:00:55 +0800161
David Wu40a55482019-04-16 21:55:26 +0800162 rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
163 ret = rockchip_translate_drive_value(type, strength);
164 if (ret < 0) {
165 debug("unsupported driver strength %d\n", strength);
166 return ret;
David Wu5f596ae2019-01-02 21:00:55 +0800167 }
David Wu40a55482019-04-16 21:55:26 +0800168
David Wu15300472019-04-16 21:56:34 +0800169 /* bank0 is special, there are no higher 16 bit writing bits. */
170 if (bank->bank_num == 0) {
171 regmap_read(regmap, reg, &data);
172 data &= ~(((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << bit);
173 } else {
174 /* enable the write to the equivalent lower bits */
175 data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
176 }
177
David Wu40a55482019-04-16 21:55:26 +0800178 data |= (ret << bit);
179 ret = regmap_write(regmap, reg, data);
180 return ret;
David Wu5f596ae2019-01-02 21:00:55 +0800181}
182
183static struct rockchip_pin_bank rk3288_pin_banks[] = {
Kever Yang56573c42019-05-07 09:36:32 +0800184 PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
185 IOMUX_SOURCE_PMU,
186 IOMUX_SOURCE_PMU,
187 IOMUX_UNROUTED
David Wu5f596ae2019-01-02 21:00:55 +0800188 ),
189 PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED,
190 IOMUX_UNROUTED,
191 IOMUX_UNROUTED,
192 0
193 ),
194 PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED),
195 PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT),
196 PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
197 IOMUX_WIDTH_4BIT,
198 0,
199 0
200 ),
201 PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED,
202 0,
203 0,
204 IOMUX_UNROUTED
205 ),
206 PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED),
207 PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0,
208 0,
209 IOMUX_WIDTH_4BIT,
210 IOMUX_UNROUTED
211 ),
212 PIN_BANK(8, 16, "gpio8"),
213};
214
215static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
David Wu71aede02019-04-16 21:50:54 +0800216 .pin_banks = rk3288_pin_banks,
217 .nr_banks = ARRAY_SIZE(rk3288_pin_banks),
David Wu71aede02019-04-16 21:50:54 +0800218 .grf_mux_offset = 0x0,
219 .pmu_mux_offset = 0x84,
220 .iomux_routes = rk3288_mux_route_data,
221 .niomux_routes = ARRAY_SIZE(rk3288_mux_route_data),
David Wu3dd7d6c2019-04-16 21:50:55 +0800222 .set_mux = rk3288_set_mux,
David Wu2972c452019-04-16 21:57:05 +0800223 .set_pull = rk3288_set_pull,
David Wu40a55482019-04-16 21:55:26 +0800224 .set_drive = rk3288_set_drive,
David Wu5f596ae2019-01-02 21:00:55 +0800225};
226
227static const struct udevice_id rk3288_pinctrl_ids[] = {
228 {
229 .compatible = "rockchip,rk3288-pinctrl",
230 .data = (ulong)&rk3288_pin_ctrl
231 },
232 { }
233};
234
Walter Lozano2901ac62020-06-25 01:10:04 -0300235U_BOOT_DRIVER(rockchip_rk3288_pinctrl) = {
David Wu5f596ae2019-01-02 21:00:55 +0800236 .name = "rockchip_rk3288_pinctrl",
237 .id = UCLASS_PINCTRL,
238 .of_match = rk3288_pinctrl_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700239 .priv_auto = sizeof(struct rockchip_pinctrl_priv),
David Wu5f596ae2019-01-02 21:00:55 +0800240 .ops = &rockchip_pinctrl_ops,
Simon Glass92882652021-08-07 07:24:04 -0600241#if CONFIG_IS_ENABLED(OF_REAL)
David Wu5f596ae2019-01-02 21:00:55 +0800242 .bind = dm_scan_fdt_dev,
243#endif
244 .probe = rockchip_pinctrl_probe,
245};