blob: 2ef24dce6c99e8b7b7a5d58ebc47856f31a81df8 [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
6#ifndef __DRIVERS_PINCTRL_ROCKCHIP_H
7#define __DRIVERS_PINCTRL_ROCKCHIP_H
8
9#include <linux/types.h>
10
11enum rockchip_pinctrl_type {
12 RV1108,
13 RK3036,
14 RK3128,
15 RK3188,
16 RK3288,
17 RK3368,
18 RK3399,
19};
20
21/**
22 * Encode variants of iomux registers into a type variable
23 */
24#define IOMUX_GPIO_ONLY BIT(0)
25#define IOMUX_WIDTH_4BIT BIT(1)
26#define IOMUX_SOURCE_PMU BIT(2)
27#define IOMUX_UNROUTED BIT(3)
28#define IOMUX_WIDTH_3BIT BIT(4)
29
30/**
31 * Defined some common pins constants
32 */
33#define ROCKCHIP_PULL_BITS_PER_PIN 2
34#define ROCKCHIP_PULL_PINS_PER_REG 8
35#define ROCKCHIP_PULL_BANK_STRIDE 16
36#define ROCKCHIP_DRV_BITS_PER_PIN 2
37#define ROCKCHIP_DRV_PINS_PER_REG 8
38#define ROCKCHIP_DRV_BANK_STRIDE 16
39#define ROCKCHIP_DRV_3BITS_PER_PIN 3
40
41/**
42 * @type: iomux variant using IOMUX_* constants
43 * @offset: if initialized to -1 it will be autocalculated, by specifying
44 * an initial offset value the relevant source offset can be reset
45 * to a new value for autocalculating the following iomux registers.
46 */
47struct rockchip_iomux {
48 int type;
49 int offset;
50};
51
52/**
53 * enum type index corresponding to rockchip_perpin_drv_list arrays index.
54 */
55enum rockchip_pin_drv_type {
56 DRV_TYPE_IO_DEFAULT = 0,
57 DRV_TYPE_IO_1V8_OR_3V0,
58 DRV_TYPE_IO_1V8_ONLY,
59 DRV_TYPE_IO_1V8_3V0_AUTO,
60 DRV_TYPE_IO_3V3_ONLY,
61 DRV_TYPE_MAX
62};
63
64/**
65 * enum type index corresponding to rockchip_pull_list arrays index.
66 */
67enum rockchip_pin_pull_type {
68 PULL_TYPE_IO_DEFAULT = 0,
69 PULL_TYPE_IO_1V8_ONLY,
70 PULL_TYPE_MAX
71};
72
73/**
74 * @drv_type: drive strength variant using rockchip_perpin_drv_type
75 * @offset: if initialized to -1 it will be autocalculated, by specifying
76 * an initial offset value the relevant source offset can be reset
77 * to a new value for autocalculating the following drive strength
78 * registers. if used chips own cal_drv func instead to calculate
79 * registers offset, the variant could be ignored.
80 */
81struct rockchip_drv {
82 enum rockchip_pin_drv_type drv_type;
83 int offset;
84};
85
86/**
87 * @priv: common pinctrl private basedata
88 * @pin_base: first pin number
89 * @nr_pins: number of pins in this bank
90 * @name: name of the bank
91 * @bank_num: number of the bank, to account for holes
92 * @iomux: array describing the 4 iomux sources of the bank
93 * @drv: array describing the 4 drive strength sources of the bank
94 * @pull_type: array describing the 4 pull type sources of the bank
95 * @recalced_mask: bits describing the mux recalced pins of per bank
96 * @route_mask: bits describing the routing pins of per bank
97 */
98struct rockchip_pin_bank {
99 struct rockchip_pinctrl_priv *priv;
100 u32 pin_base;
101 u8 nr_pins;
102 char *name;
103 u8 bank_num;
104 struct rockchip_iomux iomux[4];
105 struct rockchip_drv drv[4];
106 enum rockchip_pin_pull_type pull_type[4];
107 u32 recalced_mask;
108 u32 route_mask;
109};
110
111#define PIN_BANK(id, pins, label) \
112 { \
113 .bank_num = id, \
114 .nr_pins = pins, \
115 .name = label, \
116 .iomux = { \
117 { .offset = -1 }, \
118 { .offset = -1 }, \
119 { .offset = -1 }, \
120 { .offset = -1 }, \
121 }, \
122 }
123
124#define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3) \
125 { \
126 .bank_num = id, \
127 .nr_pins = pins, \
128 .name = label, \
129 .iomux = { \
130 { .type = iom0, .offset = -1 }, \
131 { .type = iom1, .offset = -1 }, \
132 { .type = iom2, .offset = -1 }, \
133 { .type = iom3, .offset = -1 }, \
134 }, \
135 }
136
137#define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
138 { \
139 .bank_num = id, \
140 .nr_pins = pins, \
141 .name = label, \
142 .iomux = { \
143 { .offset = -1 }, \
144 { .offset = -1 }, \
145 { .offset = -1 }, \
146 { .offset = -1 }, \
147 }, \
148 .drv = { \
149 { .drv_type = type0, .offset = -1 }, \
150 { .drv_type = type1, .offset = -1 }, \
151 { .drv_type = type2, .offset = -1 }, \
152 { .drv_type = type3, .offset = -1 }, \
153 }, \
154 }
155
156#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1, \
157 drv2, drv3, pull0, pull1, \
158 pull2, pull3) \
159 { \
160 .bank_num = id, \
161 .nr_pins = pins, \
162 .name = label, \
163 .iomux = { \
164 { .offset = -1 }, \
165 { .offset = -1 }, \
166 { .offset = -1 }, \
167 { .offset = -1 }, \
168 }, \
169 .drv = { \
170 { .drv_type = drv0, .offset = -1 }, \
171 { .drv_type = drv1, .offset = -1 }, \
172 { .drv_type = drv2, .offset = -1 }, \
173 { .drv_type = drv3, .offset = -1 }, \
174 }, \
175 .pull_type[0] = pull0, \
176 .pull_type[1] = pull1, \
177 .pull_type[2] = pull2, \
178 .pull_type[3] = pull3, \
179 }
180
181#define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1, \
182 iom2, iom3, drv0, drv1, drv2, \
183 drv3, offset0, offset1, \
184 offset2, offset3) \
185 { \
186 .bank_num = id, \
187 .nr_pins = pins, \
188 .name = label, \
189 .iomux = { \
190 { .type = iom0, .offset = -1 }, \
191 { .type = iom1, .offset = -1 }, \
192 { .type = iom2, .offset = -1 }, \
193 { .type = iom3, .offset = -1 }, \
194 }, \
195 .drv = { \
196 { .drv_type = drv0, .offset = offset0 }, \
197 { .drv_type = drv1, .offset = offset1 }, \
198 { .drv_type = drv2, .offset = offset2 }, \
199 { .drv_type = drv3, .offset = offset3 }, \
200 }, \
David Wu5f596ae2019-01-02 21:00:55 +0800201 }
202
203#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins, \
204 label, iom0, iom1, iom2, \
205 iom3, drv0, drv1, drv2, \
206 drv3, offset0, offset1, \
207 offset2, offset3, pull0, \
208 pull1, pull2, pull3) \
209 { \
210 .bank_num = id, \
211 .nr_pins = pins, \
212 .name = label, \
213 .iomux = { \
214 { .type = iom0, .offset = -1 }, \
215 { .type = iom1, .offset = -1 }, \
216 { .type = iom2, .offset = -1 }, \
217 { .type = iom3, .offset = -1 }, \
218 }, \
219 .drv = { \
220 { .drv_type = drv0, .offset = offset0 }, \
221 { .drv_type = drv1, .offset = offset1 }, \
222 { .drv_type = drv2, .offset = offset2 }, \
223 { .drv_type = drv3, .offset = offset3 }, \
224 }, \
225 .pull_type[0] = pull0, \
226 .pull_type[1] = pull1, \
227 .pull_type[2] = pull2, \
228 .pull_type[3] = pull3, \
229 }
230
231/**
232 * struct rockchip_mux_recalced_data: recalculate a pin iomux data.
233 * @num: bank number.
234 * @pin: pin number.
235 * @reg: register offset.
236 * @bit: index at register.
237 * @mask: mask bit
238 */
239struct rockchip_mux_recalced_data {
240 u8 num;
241 u8 pin;
242 u32 reg;
243 u8 bit;
244 u8 mask;
245};
246
247/**
248 * struct rockchip_mux_route_data: route a pin iomux data.
249 * @bank_num: bank number.
250 * @pin: index at register or used to calc index.
251 * @func: the min pin.
252 * @route_offset: the max pin.
253 * @route_val: the register offset.
254 */
255struct rockchip_mux_route_data {
256 u8 bank_num;
257 u8 pin;
258 u8 func;
259 u32 route_offset;
260 u32 route_val;
261};
262
263/**
264 */
265struct rockchip_pin_ctrl {
266 struct rockchip_pin_bank *pin_banks;
267 u32 nr_banks;
268 u32 nr_pins;
269 char *label;
270 enum rockchip_pinctrl_type type;
271 int grf_mux_offset;
272 int pmu_mux_offset;
273 int grf_drv_offset;
274 int pmu_drv_offset;
275 struct rockchip_mux_recalced_data *iomux_recalced;
276 u32 niomux_recalced;
277 struct rockchip_mux_route_data *iomux_routes;
278 u32 niomux_routes;
279
David Wu3dd7d6c2019-04-16 21:50:55 +0800280 int (*set_mux)(struct rockchip_pin_bank *bank,
281 int pin, int mux);
282
David Wu5f596ae2019-01-02 21:00:55 +0800283 void (*pull_calc_reg)(struct rockchip_pin_bank *bank,
284 int pin_num, struct regmap **regmap,
285 int *reg, u8 *bit);
David Wu40a55482019-04-16 21:55:26 +0800286 int (*set_drive)(struct rockchip_pin_bank *bank,
287 int pin_num, int strength);
David Wu5f596ae2019-01-02 21:00:55 +0800288 int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank,
289 int pin_num, struct regmap **regmap,
290 int *reg, u8 *bit);
291};
292
293/**
294 */
295struct rockchip_pinctrl_priv {
296 struct rockchip_pin_ctrl *ctrl;
297 struct regmap *regmap_base;
298 struct regmap *regmap_pmu;
299};
300
301extern const struct pinctrl_ops rockchip_pinctrl_ops;
302int rockchip_pinctrl_probe(struct udevice *dev);
David Wu3dd7d6c2019-04-16 21:50:55 +0800303void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
304 int *reg, u8 *bit, int *mask);
305bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
306 int mux, u32 *reg, u32 *value);
307int rockchip_get_mux_data(int mux_type, int pin, u8 *bit, int *mask);
David Wu40a55482019-04-16 21:55:26 +0800308int rockchip_translate_drive_value(int type, int strength);
David Wu5f596ae2019-01-02 21:00:55 +0800309
310#endif /* __DRIVERS_PINCTRL_ROCKCHIP_H */