1d3e51161SHeiko Stübner /*
2d3e51161SHeiko Stübner  * Pinctrl driver for Rockchip SoCs
3d3e51161SHeiko Stübner  *
4d3e51161SHeiko Stübner  * Copyright (c) 2013 MundoReader S.L.
5d3e51161SHeiko Stübner  * Author: Heiko Stuebner <heiko@sntech.de>
6d3e51161SHeiko Stübner  *
7d3e51161SHeiko Stübner  * With some ideas taken from pinctrl-samsung:
8d3e51161SHeiko Stübner  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
9d3e51161SHeiko Stübner  *		http://www.samsung.com
10d3e51161SHeiko Stübner  * Copyright (c) 2012 Linaro Ltd
11d3e51161SHeiko Stübner  *		http://www.linaro.org
12d3e51161SHeiko Stübner  *
13d3e51161SHeiko Stübner  * and pinctrl-at91:
14d3e51161SHeiko Stübner  * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
15d3e51161SHeiko Stübner  *
16d3e51161SHeiko Stübner  * This program is free software; you can redistribute it and/or modify
17d3e51161SHeiko Stübner  * it under the terms of the GNU General Public License version 2 as published
18d3e51161SHeiko Stübner  * by the Free Software Foundation.
19d3e51161SHeiko Stübner  *
20d3e51161SHeiko Stübner  * This program is distributed in the hope that it will be useful,
21d3e51161SHeiko Stübner  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22d3e51161SHeiko Stübner  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23d3e51161SHeiko Stübner  * GNU General Public License for more details.
24d3e51161SHeiko Stübner  */
25d3e51161SHeiko Stübner 
262f436204SPaul Gortmaker #include <linux/init.h>
27d3e51161SHeiko Stübner #include <linux/platform_device.h>
28d3e51161SHeiko Stübner #include <linux/io.h>
29d3e51161SHeiko Stübner #include <linux/bitops.h>
30*1c5fb66aSLinus Walleij #include <linux/gpio/driver.h>
31d3e51161SHeiko Stübner #include <linux/of_address.h>
32d3e51161SHeiko Stübner #include <linux/of_irq.h>
33d3e51161SHeiko Stübner #include <linux/pinctrl/machine.h>
34d3e51161SHeiko Stübner #include <linux/pinctrl/pinconf.h>
35d3e51161SHeiko Stübner #include <linux/pinctrl/pinctrl.h>
36d3e51161SHeiko Stübner #include <linux/pinctrl/pinmux.h>
37d3e51161SHeiko Stübner #include <linux/pinctrl/pinconf-generic.h>
38d3e51161SHeiko Stübner #include <linux/irqchip/chained_irq.h>
397e865abbSHeiko Stübner #include <linux/clk.h>
40751a99abSHeiko Stübner #include <linux/regmap.h>
4114dee867SHeiko Stübner #include <linux/mfd/syscon.h>
42d3e51161SHeiko Stübner #include <dt-bindings/pinctrl/rockchip.h>
43d3e51161SHeiko Stübner 
44d3e51161SHeiko Stübner #include "core.h"
45d3e51161SHeiko Stübner #include "pinconf.h"
46d3e51161SHeiko Stübner 
47d3e51161SHeiko Stübner /* GPIO control registers */
48d3e51161SHeiko Stübner #define GPIO_SWPORT_DR		0x00
49d3e51161SHeiko Stübner #define GPIO_SWPORT_DDR		0x04
50d3e51161SHeiko Stübner #define GPIO_INTEN		0x30
51d3e51161SHeiko Stübner #define GPIO_INTMASK		0x34
52d3e51161SHeiko Stübner #define GPIO_INTTYPE_LEVEL	0x38
53d3e51161SHeiko Stübner #define GPIO_INT_POLARITY	0x3c
54d3e51161SHeiko Stübner #define GPIO_INT_STATUS		0x40
55d3e51161SHeiko Stübner #define GPIO_INT_RAWSTATUS	0x44
56d3e51161SHeiko Stübner #define GPIO_DEBOUNCE		0x48
57d3e51161SHeiko Stübner #define GPIO_PORTS_EOI		0x4c
58d3e51161SHeiko Stübner #define GPIO_EXT_PORT		0x50
59d3e51161SHeiko Stübner #define GPIO_LS_SYNC		0x60
60d3e51161SHeiko Stübner 
61a282926dSHeiko Stübner enum rockchip_pinctrl_type {
6287065ca9SDavid Wu 	PX30,
63b9c6dcabSAndy Yan 	RV1108,
64a282926dSHeiko Stübner 	RK2928,
65a282926dSHeiko Stübner 	RK3066B,
66d23c66dfSDavid Wu 	RK3128,
67a282926dSHeiko Stübner 	RK3188,
6866d750e1SHeiko Stübner 	RK3288,
69daecdc66SHeiko Stübner 	RK3368,
70b6c23275SDavid Wu 	RK3399,
71a282926dSHeiko Stübner };
72a282926dSHeiko Stübner 
73fc72c923SHeiko Stübner /**
74fc72c923SHeiko Stübner  * Encode variants of iomux registers into a type variable
75fc72c923SHeiko Stübner  */
76fc72c923SHeiko Stübner #define IOMUX_GPIO_ONLY		BIT(0)
7703716e1dSHeiko Stübner #define IOMUX_WIDTH_4BIT	BIT(1)
7895ec8ae4SHeiko Stübner #define IOMUX_SOURCE_PMU	BIT(2)
7962f49226SHeiko Stübner #define IOMUX_UNROUTED		BIT(3)
808b6c6f93Sdavid.wu #define IOMUX_WIDTH_3BIT	BIT(4)
81fc72c923SHeiko Stübner 
82fc72c923SHeiko Stübner /**
83fc72c923SHeiko Stübner  * @type: iomux variant using IOMUX_* constants
846bc0d121SHeiko Stübner  * @offset: if initialized to -1 it will be autocalculated, by specifying
856bc0d121SHeiko Stübner  *	    an initial offset value the relevant source offset can be reset
866bc0d121SHeiko Stübner  *	    to a new value for autocalculating the following iomux registers.
87fc72c923SHeiko Stübner  */
88fc72c923SHeiko Stübner struct rockchip_iomux {
89fc72c923SHeiko Stübner 	int				type;
906bc0d121SHeiko Stübner 	int				offset;
9165fca613SHeiko Stübner };
9265fca613SHeiko Stübner 
93d3e51161SHeiko Stübner /**
94b6c23275SDavid Wu  * enum type index corresponding to rockchip_perpin_drv_list arrays index.
95b6c23275SDavid Wu  */
96b6c23275SDavid Wu enum rockchip_pin_drv_type {
97b6c23275SDavid Wu 	DRV_TYPE_IO_DEFAULT = 0,
98b6c23275SDavid Wu 	DRV_TYPE_IO_1V8_OR_3V0,
99b6c23275SDavid Wu 	DRV_TYPE_IO_1V8_ONLY,
100b6c23275SDavid Wu 	DRV_TYPE_IO_1V8_3V0_AUTO,
101b6c23275SDavid Wu 	DRV_TYPE_IO_3V3_ONLY,
102b6c23275SDavid Wu 	DRV_TYPE_MAX
103b6c23275SDavid Wu };
104b6c23275SDavid Wu 
105b6c23275SDavid Wu /**
1063ba6767aSDavid Wu  * enum type index corresponding to rockchip_pull_list arrays index.
1073ba6767aSDavid Wu  */
1083ba6767aSDavid Wu enum rockchip_pin_pull_type {
1093ba6767aSDavid Wu 	PULL_TYPE_IO_DEFAULT = 0,
1103ba6767aSDavid Wu 	PULL_TYPE_IO_1V8_ONLY,
1113ba6767aSDavid Wu 	PULL_TYPE_MAX
1123ba6767aSDavid Wu };
1133ba6767aSDavid Wu 
1143ba6767aSDavid Wu /**
115b6c23275SDavid Wu  * @drv_type: drive strength variant using rockchip_perpin_drv_type
116b6c23275SDavid Wu  * @offset: if initialized to -1 it will be autocalculated, by specifying
117b6c23275SDavid Wu  *	    an initial offset value the relevant source offset can be reset
118b6c23275SDavid Wu  *	    to a new value for autocalculating the following drive strength
119b6c23275SDavid Wu  *	    registers. if used chips own cal_drv func instead to calculate
120b6c23275SDavid Wu  *	    registers offset, the variant could be ignored.
121b6c23275SDavid Wu  */
122b6c23275SDavid Wu struct rockchip_drv {
123b6c23275SDavid Wu 	enum rockchip_pin_drv_type	drv_type;
124b6c23275SDavid Wu 	int				offset;
125b6c23275SDavid Wu };
126b6c23275SDavid Wu 
127b6c23275SDavid Wu /**
128d3e51161SHeiko Stübner  * @reg_base: register base of the gpio bank
1296ca5274dSHeiko Stübner  * @reg_pull: optional separate register for additional pull settings
130d3e51161SHeiko Stübner  * @clk: clock of the gpio bank
131d3e51161SHeiko Stübner  * @irq: interrupt of the gpio bank
1325ae0c7adSDoug Anderson  * @saved_masks: Saved content of GPIO_INTEN at suspend time.
133d3e51161SHeiko Stübner  * @pin_base: first pin number
134d3e51161SHeiko Stübner  * @nr_pins: number of pins in this bank
135d3e51161SHeiko Stübner  * @name: name of the bank
136d3e51161SHeiko Stübner  * @bank_num: number of the bank, to account for holes
137fc72c923SHeiko Stübner  * @iomux: array describing the 4 iomux sources of the bank
138b6c23275SDavid Wu  * @drv: array describing the 4 drive strength sources of the bank
1393ba6767aSDavid Wu  * @pull_type: array describing the 4 pull type sources of the bank
14085dc397aSMarkus Elfring  * @valid: is all necessary information present
141d3e51161SHeiko Stübner  * @of_node: dt node of this bank
142d3e51161SHeiko Stübner  * @drvdata: common pinctrl basedata
143d3e51161SHeiko Stübner  * @domain: irqdomain of the gpio bank
144d3e51161SHeiko Stübner  * @gpio_chip: gpiolib chip
145d3e51161SHeiko Stübner  * @grange: gpio range
146d3e51161SHeiko Stübner  * @slock: spinlock for the gpio bank
147bd35b9bfSDavid Wu  * @route_mask: bits describing the routing pins of per bank
148d3e51161SHeiko Stübner  */
149d3e51161SHeiko Stübner struct rockchip_pin_bank {
150d3e51161SHeiko Stübner 	void __iomem			*reg_base;
151751a99abSHeiko Stübner 	struct regmap			*regmap_pull;
152d3e51161SHeiko Stübner 	struct clk			*clk;
153d3e51161SHeiko Stübner 	int				irq;
1545ae0c7adSDoug Anderson 	u32				saved_masks;
155d3e51161SHeiko Stübner 	u32				pin_base;
156d3e51161SHeiko Stübner 	u8				nr_pins;
157d3e51161SHeiko Stübner 	char				*name;
158d3e51161SHeiko Stübner 	u8				bank_num;
159fc72c923SHeiko Stübner 	struct rockchip_iomux		iomux[4];
160b6c23275SDavid Wu 	struct rockchip_drv		drv[4];
1613ba6767aSDavid Wu 	enum rockchip_pin_pull_type	pull_type[4];
162d3e51161SHeiko Stübner 	bool				valid;
163d3e51161SHeiko Stübner 	struct device_node		*of_node;
164d3e51161SHeiko Stübner 	struct rockchip_pinctrl		*drvdata;
165d3e51161SHeiko Stübner 	struct irq_domain		*domain;
166d3e51161SHeiko Stübner 	struct gpio_chip		gpio_chip;
167d3e51161SHeiko Stübner 	struct pinctrl_gpio_range	grange;
16870b7aa7aSJohn Keeping 	raw_spinlock_t			slock;
1695a927501SHeiko Stübner 	u32				toggle_edge_mode;
170c04c3fa6SDavid Wu 	u32				recalced_mask;
171bd35b9bfSDavid Wu 	u32				route_mask;
172d3e51161SHeiko Stübner };
173d3e51161SHeiko Stübner 
174d3e51161SHeiko Stübner #define PIN_BANK(id, pins, label)			\
175d3e51161SHeiko Stübner 	{						\
176d3e51161SHeiko Stübner 		.bank_num	= id,			\
177d3e51161SHeiko Stübner 		.nr_pins	= pins,			\
178d3e51161SHeiko Stübner 		.name		= label,		\
1796bc0d121SHeiko Stübner 		.iomux		= {			\
1806bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1816bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1826bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1836bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1846bc0d121SHeiko Stübner 		},					\
185d3e51161SHeiko Stübner 	}
186d3e51161SHeiko Stübner 
187fc72c923SHeiko Stübner #define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3)	\
188fc72c923SHeiko Stübner 	{								\
189fc72c923SHeiko Stübner 		.bank_num	= id,					\
190fc72c923SHeiko Stübner 		.nr_pins	= pins,					\
191fc72c923SHeiko Stübner 		.name		= label,				\
192fc72c923SHeiko Stübner 		.iomux		= {					\
1936bc0d121SHeiko Stübner 			{ .type = iom0, .offset = -1 },			\
1946bc0d121SHeiko Stübner 			{ .type = iom1, .offset = -1 },			\
1956bc0d121SHeiko Stübner 			{ .type = iom2, .offset = -1 },			\
1966bc0d121SHeiko Stübner 			{ .type = iom3, .offset = -1 },			\
197fc72c923SHeiko Stübner 		},							\
198fc72c923SHeiko Stübner 	}
199fc72c923SHeiko Stübner 
200b6c23275SDavid Wu #define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
201b6c23275SDavid Wu 	{								\
202b6c23275SDavid Wu 		.bank_num	= id,					\
203b6c23275SDavid Wu 		.nr_pins	= pins,					\
204b6c23275SDavid Wu 		.name		= label,				\
205b6c23275SDavid Wu 		.iomux		= {					\
206b6c23275SDavid Wu 			{ .offset = -1 },				\
207b6c23275SDavid Wu 			{ .offset = -1 },				\
208b6c23275SDavid Wu 			{ .offset = -1 },				\
209b6c23275SDavid Wu 			{ .offset = -1 },				\
210b6c23275SDavid Wu 		},							\
211b6c23275SDavid Wu 		.drv		= {					\
212b6c23275SDavid Wu 			{ .drv_type = type0, .offset = -1 },		\
213b6c23275SDavid Wu 			{ .drv_type = type1, .offset = -1 },		\
214b6c23275SDavid Wu 			{ .drv_type = type2, .offset = -1 },		\
215b6c23275SDavid Wu 			{ .drv_type = type3, .offset = -1 },		\
216b6c23275SDavid Wu 		},							\
217b6c23275SDavid Wu 	}
218b6c23275SDavid Wu 
2193ba6767aSDavid Wu #define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1,	\
2203ba6767aSDavid Wu 				      drv2, drv3, pull0, pull1,		\
2213ba6767aSDavid Wu 				      pull2, pull3)			\
2223ba6767aSDavid Wu 	{								\
2233ba6767aSDavid Wu 		.bank_num	= id,					\
2243ba6767aSDavid Wu 		.nr_pins	= pins,					\
2253ba6767aSDavid Wu 		.name		= label,				\
2263ba6767aSDavid Wu 		.iomux		= {					\
2273ba6767aSDavid Wu 			{ .offset = -1 },				\
2283ba6767aSDavid Wu 			{ .offset = -1 },				\
2293ba6767aSDavid Wu 			{ .offset = -1 },				\
2303ba6767aSDavid Wu 			{ .offset = -1 },				\
2313ba6767aSDavid Wu 		},							\
2323ba6767aSDavid Wu 		.drv		= {					\
2333ba6767aSDavid Wu 			{ .drv_type = drv0, .offset = -1 },		\
2343ba6767aSDavid Wu 			{ .drv_type = drv1, .offset = -1 },		\
2353ba6767aSDavid Wu 			{ .drv_type = drv2, .offset = -1 },		\
2363ba6767aSDavid Wu 			{ .drv_type = drv3, .offset = -1 },		\
2373ba6767aSDavid Wu 		},							\
2383ba6767aSDavid Wu 		.pull_type[0] = pull0,					\
2393ba6767aSDavid Wu 		.pull_type[1] = pull1,					\
2403ba6767aSDavid Wu 		.pull_type[2] = pull2,					\
2413ba6767aSDavid Wu 		.pull_type[3] = pull3,					\
2423ba6767aSDavid Wu 	}
2433ba6767aSDavid Wu 
244b6c23275SDavid Wu #define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,	\
245b6c23275SDavid Wu 					iom2, iom3, drv0, drv1, drv2,	\
246b6c23275SDavid Wu 					drv3, offset0, offset1,		\
247b6c23275SDavid Wu 					offset2, offset3)		\
248b6c23275SDavid Wu 	{								\
249b6c23275SDavid Wu 		.bank_num	= id,					\
250b6c23275SDavid Wu 		.nr_pins	= pins,					\
251b6c23275SDavid Wu 		.name		= label,				\
252b6c23275SDavid Wu 		.iomux		= {					\
253b6c23275SDavid Wu 			{ .type = iom0, .offset = -1 },			\
254b6c23275SDavid Wu 			{ .type = iom1, .offset = -1 },			\
255b6c23275SDavid Wu 			{ .type = iom2, .offset = -1 },			\
256b6c23275SDavid Wu 			{ .type = iom3, .offset = -1 },			\
257b6c23275SDavid Wu 		},							\
258b6c23275SDavid Wu 		.drv		= {					\
259b6c23275SDavid Wu 			{ .drv_type = drv0, .offset = offset0 },	\
260b6c23275SDavid Wu 			{ .drv_type = drv1, .offset = offset1 },	\
261b6c23275SDavid Wu 			{ .drv_type = drv2, .offset = offset2 },	\
262b6c23275SDavid Wu 			{ .drv_type = drv3, .offset = offset3 },	\
263b6c23275SDavid Wu 		},							\
264b6c23275SDavid Wu 	}
265b6c23275SDavid Wu 
2663ba6767aSDavid Wu #define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins,	\
2673ba6767aSDavid Wu 					      label, iom0, iom1, iom2,  \
2683ba6767aSDavid Wu 					      iom3, drv0, drv1, drv2,   \
2693ba6767aSDavid Wu 					      drv3, offset0, offset1,   \
2703ba6767aSDavid Wu 					      offset2, offset3, pull0,  \
2713ba6767aSDavid Wu 					      pull1, pull2, pull3)	\
2723ba6767aSDavid Wu 	{								\
2733ba6767aSDavid Wu 		.bank_num	= id,					\
2743ba6767aSDavid Wu 		.nr_pins	= pins,					\
2753ba6767aSDavid Wu 		.name		= label,				\
2763ba6767aSDavid Wu 		.iomux		= {					\
2773ba6767aSDavid Wu 			{ .type = iom0, .offset = -1 },			\
2783ba6767aSDavid Wu 			{ .type = iom1, .offset = -1 },			\
2793ba6767aSDavid Wu 			{ .type = iom2, .offset = -1 },			\
2803ba6767aSDavid Wu 			{ .type = iom3, .offset = -1 },			\
2813ba6767aSDavid Wu 		},							\
2823ba6767aSDavid Wu 		.drv		= {					\
2833ba6767aSDavid Wu 			{ .drv_type = drv0, .offset = offset0 },	\
2843ba6767aSDavid Wu 			{ .drv_type = drv1, .offset = offset1 },	\
2853ba6767aSDavid Wu 			{ .drv_type = drv2, .offset = offset2 },	\
2863ba6767aSDavid Wu 			{ .drv_type = drv3, .offset = offset3 },	\
2873ba6767aSDavid Wu 		},							\
2883ba6767aSDavid Wu 		.pull_type[0] = pull0,					\
2893ba6767aSDavid Wu 		.pull_type[1] = pull1,					\
2903ba6767aSDavid Wu 		.pull_type[2] = pull2,					\
2913ba6767aSDavid Wu 		.pull_type[3] = pull3,					\
2923ba6767aSDavid Wu 	}
2933ba6767aSDavid Wu 
294d3e51161SHeiko Stübner /**
295bd35b9bfSDavid Wu  * struct rockchip_mux_recalced_data: represent a pin iomux data.
296c04c3fa6SDavid Wu  * @num: bank number.
297c04c3fa6SDavid Wu  * @pin: pin number.
298c04c3fa6SDavid Wu  * @bit: index at register.
299c04c3fa6SDavid Wu  * @reg: register offset.
300c04c3fa6SDavid Wu  * @mask: mask bit
301c04c3fa6SDavid Wu  */
302c04c3fa6SDavid Wu struct rockchip_mux_recalced_data {
303c04c3fa6SDavid Wu 	u8 num;
304c04c3fa6SDavid Wu 	u8 pin;
30512b8f018SDavid Wu 	u32 reg;
306c04c3fa6SDavid Wu 	u8 bit;
307c04c3fa6SDavid Wu 	u8 mask;
308c04c3fa6SDavid Wu };
309c04c3fa6SDavid Wu 
310c04c3fa6SDavid Wu /**
311c04c3fa6SDavid Wu  * struct rockchip_mux_recalced_data: represent a pin iomux data.
312bd35b9bfSDavid Wu  * @bank_num: bank number.
313bd35b9bfSDavid Wu  * @pin: index at register or used to calc index.
314bd35b9bfSDavid Wu  * @func: the min pin.
315bd35b9bfSDavid Wu  * @route_offset: the max pin.
316bd35b9bfSDavid Wu  * @route_val: the register offset.
317bd35b9bfSDavid Wu  */
318bd35b9bfSDavid Wu struct rockchip_mux_route_data {
319bd35b9bfSDavid Wu 	u8 bank_num;
320bd35b9bfSDavid Wu 	u8 pin;
321bd35b9bfSDavid Wu 	u8 func;
322bd35b9bfSDavid Wu 	u32 route_offset;
323bd35b9bfSDavid Wu 	u32 route_val;
324bd35b9bfSDavid Wu };
325bd35b9bfSDavid Wu 
326bd35b9bfSDavid Wu /**
327d3e51161SHeiko Stübner  */
328d3e51161SHeiko Stübner struct rockchip_pin_ctrl {
329d3e51161SHeiko Stübner 	struct rockchip_pin_bank	*pin_banks;
330d3e51161SHeiko Stübner 	u32				nr_banks;
331d3e51161SHeiko Stübner 	u32				nr_pins;
332d3e51161SHeiko Stübner 	char				*label;
333a282926dSHeiko Stübner 	enum rockchip_pinctrl_type	type;
33495ec8ae4SHeiko Stübner 	int				grf_mux_offset;
33595ec8ae4SHeiko Stübner 	int				pmu_mux_offset;
336b6c23275SDavid Wu 	int				grf_drv_offset;
337b6c23275SDavid Wu 	int				pmu_drv_offset;
338c04c3fa6SDavid Wu 	struct rockchip_mux_recalced_data *iomux_recalced;
339c04c3fa6SDavid Wu 	u32				niomux_recalced;
340bd35b9bfSDavid Wu 	struct rockchip_mux_route_data *iomux_routes;
341bd35b9bfSDavid Wu 	u32				niomux_routes;
342b6c23275SDavid Wu 
343751a99abSHeiko Stübner 	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank,
344751a99abSHeiko Stübner 				    int pin_num, struct regmap **regmap,
345751a99abSHeiko Stübner 				    int *reg, u8 *bit);
346ef17f69fSHeiko Stübner 	void	(*drv_calc_reg)(struct rockchip_pin_bank *bank,
347ef17f69fSHeiko Stübner 				    int pin_num, struct regmap **regmap,
348ef17f69fSHeiko Stübner 				    int *reg, u8 *bit);
349e3b357d7Sdavid.wu 	int	(*schmitt_calc_reg)(struct rockchip_pin_bank *bank,
350e3b357d7Sdavid.wu 				    int pin_num, struct regmap **regmap,
351e3b357d7Sdavid.wu 				    int *reg, u8 *bit);
352d3e51161SHeiko Stübner };
353d3e51161SHeiko Stübner 
354d3e51161SHeiko Stübner struct rockchip_pin_config {
355d3e51161SHeiko Stübner 	unsigned int		func;
356d3e51161SHeiko Stübner 	unsigned long		*configs;
357d3e51161SHeiko Stübner 	unsigned int		nconfigs;
358d3e51161SHeiko Stübner };
359d3e51161SHeiko Stübner 
360d3e51161SHeiko Stübner /**
361d3e51161SHeiko Stübner  * struct rockchip_pin_group: represent group of pins of a pinmux function.
362d3e51161SHeiko Stübner  * @name: name of the pin group, used to lookup the group.
363d3e51161SHeiko Stübner  * @pins: the pins included in this group.
364d3e51161SHeiko Stübner  * @npins: number of pins included in this group.
365d3e51161SHeiko Stübner  * @func: the mux function number to be programmed when selected.
366d3e51161SHeiko Stübner  * @configs: the config values to be set for each pin
367d3e51161SHeiko Stübner  * @nconfigs: number of configs for each pin
368d3e51161SHeiko Stübner  */
369d3e51161SHeiko Stübner struct rockchip_pin_group {
370d3e51161SHeiko Stübner 	const char			*name;
371d3e51161SHeiko Stübner 	unsigned int			npins;
372d3e51161SHeiko Stübner 	unsigned int			*pins;
373d3e51161SHeiko Stübner 	struct rockchip_pin_config	*data;
374d3e51161SHeiko Stübner };
375d3e51161SHeiko Stübner 
376d3e51161SHeiko Stübner /**
377d3e51161SHeiko Stübner  * struct rockchip_pmx_func: represent a pin function.
378d3e51161SHeiko Stübner  * @name: name of the pin function, used to lookup the function.
379d3e51161SHeiko Stübner  * @groups: one or more names of pin groups that provide this function.
380d3e51161SHeiko Stübner  * @num_groups: number of groups included in @groups.
381d3e51161SHeiko Stübner  */
382d3e51161SHeiko Stübner struct rockchip_pmx_func {
383d3e51161SHeiko Stübner 	const char		*name;
384d3e51161SHeiko Stübner 	const char		**groups;
385d3e51161SHeiko Stübner 	u8			ngroups;
386d3e51161SHeiko Stübner };
387d3e51161SHeiko Stübner 
388d3e51161SHeiko Stübner struct rockchip_pinctrl {
389751a99abSHeiko Stübner 	struct regmap			*regmap_base;
390bfc7a42aSHeiko Stübner 	int				reg_size;
391751a99abSHeiko Stübner 	struct regmap			*regmap_pull;
39214dee867SHeiko Stübner 	struct regmap			*regmap_pmu;
393d3e51161SHeiko Stübner 	struct device			*dev;
394d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl	*ctrl;
395d3e51161SHeiko Stübner 	struct pinctrl_desc		pctl;
396d3e51161SHeiko Stübner 	struct pinctrl_dev		*pctl_dev;
397d3e51161SHeiko Stübner 	struct rockchip_pin_group	*groups;
398d3e51161SHeiko Stübner 	unsigned int			ngroups;
399d3e51161SHeiko Stübner 	struct rockchip_pmx_func	*functions;
400d3e51161SHeiko Stübner 	unsigned int			nfunctions;
401d3e51161SHeiko Stübner };
402d3e51161SHeiko Stübner 
403751a99abSHeiko Stübner static struct regmap_config rockchip_regmap_config = {
404751a99abSHeiko Stübner 	.reg_bits = 32,
405751a99abSHeiko Stübner 	.val_bits = 32,
406751a99abSHeiko Stübner 	.reg_stride = 4,
407751a99abSHeiko Stübner };
408751a99abSHeiko Stübner 
40956411f3cSArnd Bergmann static inline const struct rockchip_pin_group *pinctrl_name_to_group(
410d3e51161SHeiko Stübner 					const struct rockchip_pinctrl *info,
411d3e51161SHeiko Stübner 					const char *name)
412d3e51161SHeiko Stübner {
413d3e51161SHeiko Stübner 	int i;
414d3e51161SHeiko Stübner 
415d3e51161SHeiko Stübner 	for (i = 0; i < info->ngroups; i++) {
4161cb95395SAxel Lin 		if (!strcmp(info->groups[i].name, name))
4171cb95395SAxel Lin 			return &info->groups[i];
418d3e51161SHeiko Stübner 	}
419d3e51161SHeiko Stübner 
4201cb95395SAxel Lin 	return NULL;
421d3e51161SHeiko Stübner }
422d3e51161SHeiko Stübner 
423d3e51161SHeiko Stübner /*
424d3e51161SHeiko Stübner  * given a pin number that is local to a pin controller, find out the pin bank
425d3e51161SHeiko Stübner  * and the register base of the pin bank.
426d3e51161SHeiko Stübner  */
427d3e51161SHeiko Stübner static struct rockchip_pin_bank *pin_to_bank(struct rockchip_pinctrl *info,
428d3e51161SHeiko Stübner 								unsigned pin)
429d3e51161SHeiko Stübner {
430d3e51161SHeiko Stübner 	struct rockchip_pin_bank *b = info->ctrl->pin_banks;
431d3e51161SHeiko Stübner 
43251578b9bSAxel Lin 	while (pin >= (b->pin_base + b->nr_pins))
433d3e51161SHeiko Stübner 		b++;
434d3e51161SHeiko Stübner 
435d3e51161SHeiko Stübner 	return b;
436d3e51161SHeiko Stübner }
437d3e51161SHeiko Stübner 
438d3e51161SHeiko Stübner static struct rockchip_pin_bank *bank_num_to_bank(
439d3e51161SHeiko Stübner 					struct rockchip_pinctrl *info,
440d3e51161SHeiko Stübner 					unsigned num)
441d3e51161SHeiko Stübner {
442d3e51161SHeiko Stübner 	struct rockchip_pin_bank *b = info->ctrl->pin_banks;
443d3e51161SHeiko Stübner 	int i;
444d3e51161SHeiko Stübner 
4451cb95395SAxel Lin 	for (i = 0; i < info->ctrl->nr_banks; i++, b++) {
446d3e51161SHeiko Stübner 		if (b->bank_num == num)
4471cb95395SAxel Lin 			return b;
448d3e51161SHeiko Stübner 	}
449d3e51161SHeiko Stübner 
450d3e51161SHeiko Stübner 	return ERR_PTR(-EINVAL);
451d3e51161SHeiko Stübner }
452d3e51161SHeiko Stübner 
453d3e51161SHeiko Stübner /*
454d3e51161SHeiko Stübner  * Pinctrl_ops handling
455d3e51161SHeiko Stübner  */
456d3e51161SHeiko Stübner 
457d3e51161SHeiko Stübner static int rockchip_get_groups_count(struct pinctrl_dev *pctldev)
458d3e51161SHeiko Stübner {
459d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
460d3e51161SHeiko Stübner 
461d3e51161SHeiko Stübner 	return info->ngroups;
462d3e51161SHeiko Stübner }
463d3e51161SHeiko Stübner 
464d3e51161SHeiko Stübner static const char *rockchip_get_group_name(struct pinctrl_dev *pctldev,
465d3e51161SHeiko Stübner 							unsigned selector)
466d3e51161SHeiko Stübner {
467d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
468d3e51161SHeiko Stübner 
469d3e51161SHeiko Stübner 	return info->groups[selector].name;
470d3e51161SHeiko Stübner }
471d3e51161SHeiko Stübner 
472d3e51161SHeiko Stübner static int rockchip_get_group_pins(struct pinctrl_dev *pctldev,
473d3e51161SHeiko Stübner 				      unsigned selector, const unsigned **pins,
474d3e51161SHeiko Stübner 				      unsigned *npins)
475d3e51161SHeiko Stübner {
476d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
477d3e51161SHeiko Stübner 
478d3e51161SHeiko Stübner 	if (selector >= info->ngroups)
479d3e51161SHeiko Stübner 		return -EINVAL;
480d3e51161SHeiko Stübner 
481d3e51161SHeiko Stübner 	*pins = info->groups[selector].pins;
482d3e51161SHeiko Stübner 	*npins = info->groups[selector].npins;
483d3e51161SHeiko Stübner 
484d3e51161SHeiko Stübner 	return 0;
485d3e51161SHeiko Stübner }
486d3e51161SHeiko Stübner 
487d3e51161SHeiko Stübner static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev,
488d3e51161SHeiko Stübner 				 struct device_node *np,
489d3e51161SHeiko Stübner 				 struct pinctrl_map **map, unsigned *num_maps)
490d3e51161SHeiko Stübner {
491d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
492d3e51161SHeiko Stübner 	const struct rockchip_pin_group *grp;
493d3e51161SHeiko Stübner 	struct pinctrl_map *new_map;
494d3e51161SHeiko Stübner 	struct device_node *parent;
495d3e51161SHeiko Stübner 	int map_num = 1;
496d3e51161SHeiko Stübner 	int i;
497d3e51161SHeiko Stübner 
498d3e51161SHeiko Stübner 	/*
499d3e51161SHeiko Stübner 	 * first find the group of this node and check if we need to create
500d3e51161SHeiko Stübner 	 * config maps for pins
501d3e51161SHeiko Stübner 	 */
502d3e51161SHeiko Stübner 	grp = pinctrl_name_to_group(info, np->name);
503d3e51161SHeiko Stübner 	if (!grp) {
50494f4e54cSRob Herring 		dev_err(info->dev, "unable to find group for node %pOFn\n",
50594f4e54cSRob Herring 			np);
506d3e51161SHeiko Stübner 		return -EINVAL;
507d3e51161SHeiko Stübner 	}
508d3e51161SHeiko Stübner 
509d3e51161SHeiko Stübner 	map_num += grp->npins;
510a86854d0SKees Cook 	new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map),
511d3e51161SHeiko Stübner 								GFP_KERNEL);
512d3e51161SHeiko Stübner 	if (!new_map)
513d3e51161SHeiko Stübner 		return -ENOMEM;
514d3e51161SHeiko Stübner 
515d3e51161SHeiko Stübner 	*map = new_map;
516d3e51161SHeiko Stübner 	*num_maps = map_num;
517d3e51161SHeiko Stübner 
518d3e51161SHeiko Stübner 	/* create mux map */
519d3e51161SHeiko Stübner 	parent = of_get_parent(np);
520d3e51161SHeiko Stübner 	if (!parent) {
521d3e51161SHeiko Stübner 		devm_kfree(pctldev->dev, new_map);
522d3e51161SHeiko Stübner 		return -EINVAL;
523d3e51161SHeiko Stübner 	}
524d3e51161SHeiko Stübner 	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
525d3e51161SHeiko Stübner 	new_map[0].data.mux.function = parent->name;
526d3e51161SHeiko Stübner 	new_map[0].data.mux.group = np->name;
527d3e51161SHeiko Stübner 	of_node_put(parent);
528d3e51161SHeiko Stübner 
529d3e51161SHeiko Stübner 	/* create config map */
530d3e51161SHeiko Stübner 	new_map++;
531d3e51161SHeiko Stübner 	for (i = 0; i < grp->npins; i++) {
532d3e51161SHeiko Stübner 		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
533d3e51161SHeiko Stübner 		new_map[i].data.configs.group_or_pin =
534d3e51161SHeiko Stübner 				pin_get_name(pctldev, grp->pins[i]);
535d3e51161SHeiko Stübner 		new_map[i].data.configs.configs = grp->data[i].configs;
536d3e51161SHeiko Stübner 		new_map[i].data.configs.num_configs = grp->data[i].nconfigs;
537d3e51161SHeiko Stübner 	}
538d3e51161SHeiko Stübner 
539d3e51161SHeiko Stübner 	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
540d3e51161SHeiko Stübner 		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
541d3e51161SHeiko Stübner 
542d3e51161SHeiko Stübner 	return 0;
543d3e51161SHeiko Stübner }
544d3e51161SHeiko Stübner 
545d3e51161SHeiko Stübner static void rockchip_dt_free_map(struct pinctrl_dev *pctldev,
546d3e51161SHeiko Stübner 				    struct pinctrl_map *map, unsigned num_maps)
547d3e51161SHeiko Stübner {
548d3e51161SHeiko Stübner }
549d3e51161SHeiko Stübner 
550d3e51161SHeiko Stübner static const struct pinctrl_ops rockchip_pctrl_ops = {
551d3e51161SHeiko Stübner 	.get_groups_count	= rockchip_get_groups_count,
552d3e51161SHeiko Stübner 	.get_group_name		= rockchip_get_group_name,
553d3e51161SHeiko Stübner 	.get_group_pins		= rockchip_get_group_pins,
554d3e51161SHeiko Stübner 	.dt_node_to_map		= rockchip_dt_node_to_map,
555d3e51161SHeiko Stübner 	.dt_free_map		= rockchip_dt_free_map,
556d3e51161SHeiko Stübner };
557d3e51161SHeiko Stübner 
558d3e51161SHeiko Stübner /*
559d3e51161SHeiko Stübner  * Hardware access
560d3e51161SHeiko Stübner  */
561d3e51161SHeiko Stübner 
56212b8f018SDavid Wu static struct rockchip_mux_recalced_data rv1108_mux_recalced_data[] = {
56312b8f018SDavid Wu 	{
56412b8f018SDavid Wu 		.num = 1,
56512b8f018SDavid Wu 		.pin = 0,
56612b8f018SDavid Wu 		.reg = 0x418,
56712b8f018SDavid Wu 		.bit = 0,
56812b8f018SDavid Wu 		.mask = 0x3
56912b8f018SDavid Wu 	}, {
57012b8f018SDavid Wu 		.num = 1,
57112b8f018SDavid Wu 		.pin = 1,
57212b8f018SDavid Wu 		.reg = 0x418,
57312b8f018SDavid Wu 		.bit = 2,
57412b8f018SDavid Wu 		.mask = 0x3
57512b8f018SDavid Wu 	}, {
57612b8f018SDavid Wu 		.num = 1,
57712b8f018SDavid Wu 		.pin = 2,
57812b8f018SDavid Wu 		.reg = 0x418,
57912b8f018SDavid Wu 		.bit = 4,
58012b8f018SDavid Wu 		.mask = 0x3
58112b8f018SDavid Wu 	}, {
58212b8f018SDavid Wu 		.num = 1,
58312b8f018SDavid Wu 		.pin = 3,
58412b8f018SDavid Wu 		.reg = 0x418,
58512b8f018SDavid Wu 		.bit = 6,
58612b8f018SDavid Wu 		.mask = 0x3
58712b8f018SDavid Wu 	}, {
58812b8f018SDavid Wu 		.num = 1,
58912b8f018SDavid Wu 		.pin = 4,
59012b8f018SDavid Wu 		.reg = 0x418,
59112b8f018SDavid Wu 		.bit = 8,
59212b8f018SDavid Wu 		.mask = 0x3
59312b8f018SDavid Wu 	}, {
59412b8f018SDavid Wu 		.num = 1,
59512b8f018SDavid Wu 		.pin = 5,
59612b8f018SDavid Wu 		.reg = 0x418,
59712b8f018SDavid Wu 		.bit = 10,
59812b8f018SDavid Wu 		.mask = 0x3
59912b8f018SDavid Wu 	}, {
60012b8f018SDavid Wu 		.num = 1,
60112b8f018SDavid Wu 		.pin = 6,
60212b8f018SDavid Wu 		.reg = 0x418,
60312b8f018SDavid Wu 		.bit = 12,
60412b8f018SDavid Wu 		.mask = 0x3
60512b8f018SDavid Wu 	}, {
60612b8f018SDavid Wu 		.num = 1,
60712b8f018SDavid Wu 		.pin = 7,
60812b8f018SDavid Wu 		.reg = 0x418,
60912b8f018SDavid Wu 		.bit = 14,
61012b8f018SDavid Wu 		.mask = 0x3
61112b8f018SDavid Wu 	}, {
61212b8f018SDavid Wu 		.num = 1,
61312b8f018SDavid Wu 		.pin = 8,
61412b8f018SDavid Wu 		.reg = 0x41c,
61512b8f018SDavid Wu 		.bit = 0,
61612b8f018SDavid Wu 		.mask = 0x3
61712b8f018SDavid Wu 	}, {
61812b8f018SDavid Wu 		.num = 1,
61912b8f018SDavid Wu 		.pin = 9,
62012b8f018SDavid Wu 		.reg = 0x41c,
62112b8f018SDavid Wu 		.bit = 2,
62212b8f018SDavid Wu 		.mask = 0x3
62312b8f018SDavid Wu 	},
62412b8f018SDavid Wu };
62512b8f018SDavid Wu 
626d23c66dfSDavid Wu static  struct rockchip_mux_recalced_data rk3128_mux_recalced_data[] = {
627d23c66dfSDavid Wu 	{
628d23c66dfSDavid Wu 		.num = 2,
629d23c66dfSDavid Wu 		.pin = 20,
630d23c66dfSDavid Wu 		.reg = 0xe8,
631d23c66dfSDavid Wu 		.bit = 0,
632d23c66dfSDavid Wu 		.mask = 0x7
633d23c66dfSDavid Wu 	}, {
634d23c66dfSDavid Wu 		.num = 2,
635d23c66dfSDavid Wu 		.pin = 21,
636d23c66dfSDavid Wu 		.reg = 0xe8,
637d23c66dfSDavid Wu 		.bit = 4,
638d23c66dfSDavid Wu 		.mask = 0x7
639d23c66dfSDavid Wu 	}, {
640d23c66dfSDavid Wu 		.num = 2,
641d23c66dfSDavid Wu 		.pin = 22,
642d23c66dfSDavid Wu 		.reg = 0xe8,
643d23c66dfSDavid Wu 		.bit = 8,
644d23c66dfSDavid Wu 		.mask = 0x7
645d23c66dfSDavid Wu 	}, {
646d23c66dfSDavid Wu 		.num = 2,
647d23c66dfSDavid Wu 		.pin = 23,
648d23c66dfSDavid Wu 		.reg = 0xe8,
649d23c66dfSDavid Wu 		.bit = 12,
650d23c66dfSDavid Wu 		.mask = 0x7
651d23c66dfSDavid Wu 	}, {
652d23c66dfSDavid Wu 		.num = 2,
653d23c66dfSDavid Wu 		.pin = 24,
654d23c66dfSDavid Wu 		.reg = 0xd4,
655d23c66dfSDavid Wu 		.bit = 12,
656d23c66dfSDavid Wu 		.mask = 0x7
657d23c66dfSDavid Wu 	},
658d23c66dfSDavid Wu };
659d23c66dfSDavid Wu 
660c04c3fa6SDavid Wu static struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = {
6613818e4a7Sdavid.wu 	{
6623818e4a7Sdavid.wu 		.num = 2,
6633818e4a7Sdavid.wu 		.pin = 12,
6643818e4a7Sdavid.wu 		.reg = 0x24,
6653818e4a7Sdavid.wu 		.bit = 8,
6663818e4a7Sdavid.wu 		.mask = 0x3
6673818e4a7Sdavid.wu 	}, {
6683818e4a7Sdavid.wu 		.num = 2,
6693818e4a7Sdavid.wu 		.pin = 15,
6703818e4a7Sdavid.wu 		.reg = 0x28,
6713818e4a7Sdavid.wu 		.bit = 0,
6723818e4a7Sdavid.wu 		.mask = 0x7
6733818e4a7Sdavid.wu 	}, {
6743818e4a7Sdavid.wu 		.num = 2,
6753818e4a7Sdavid.wu 		.pin = 23,
6763818e4a7Sdavid.wu 		.reg = 0x30,
6773818e4a7Sdavid.wu 		.bit = 14,
6783818e4a7Sdavid.wu 		.mask = 0x3
6793818e4a7Sdavid.wu 	},
6803818e4a7Sdavid.wu };
6813818e4a7Sdavid.wu 
682c04c3fa6SDavid Wu static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
683c04c3fa6SDavid Wu 				      int *reg, u8 *bit, int *mask)
6843818e4a7Sdavid.wu {
685c04c3fa6SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
686c04c3fa6SDavid Wu 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
687c04c3fa6SDavid Wu 	struct rockchip_mux_recalced_data *data;
6883818e4a7Sdavid.wu 	int i;
6893818e4a7Sdavid.wu 
690c04c3fa6SDavid Wu 	for (i = 0; i < ctrl->niomux_recalced; i++) {
691c04c3fa6SDavid Wu 		data = &ctrl->iomux_recalced[i];
692c04c3fa6SDavid Wu 		if (data->num == bank->bank_num &&
693c04c3fa6SDavid Wu 		    data->pin == pin)
6943818e4a7Sdavid.wu 			break;
6953818e4a7Sdavid.wu 	}
6963818e4a7Sdavid.wu 
697c04c3fa6SDavid Wu 	if (i >= ctrl->niomux_recalced)
6983818e4a7Sdavid.wu 		return;
6993818e4a7Sdavid.wu 
7003818e4a7Sdavid.wu 	*reg = data->reg;
7013818e4a7Sdavid.wu 	*mask = data->mask;
7023818e4a7Sdavid.wu 	*bit = data->bit;
7033818e4a7Sdavid.wu }
7043818e4a7Sdavid.wu 
70587065ca9SDavid Wu static struct rockchip_mux_route_data px30_mux_route_data[] = {
70687065ca9SDavid Wu 	{
70787065ca9SDavid Wu 		/* cif-d2m0 */
70887065ca9SDavid Wu 		.bank_num = 2,
70987065ca9SDavid Wu 		.pin = 0,
71087065ca9SDavid Wu 		.func = 1,
71187065ca9SDavid Wu 		.route_offset = 0x184,
71287065ca9SDavid Wu 		.route_val = BIT(16 + 7),
71387065ca9SDavid Wu 	}, {
71487065ca9SDavid Wu 		/* cif-d2m1 */
71587065ca9SDavid Wu 		.bank_num = 3,
71687065ca9SDavid Wu 		.pin = 3,
71787065ca9SDavid Wu 		.func = 3,
71887065ca9SDavid Wu 		.route_offset = 0x184,
71987065ca9SDavid Wu 		.route_val = BIT(16 + 7) | BIT(7),
72087065ca9SDavid Wu 	}, {
72187065ca9SDavid Wu 		/* pdm-m0 */
72287065ca9SDavid Wu 		.bank_num = 3,
72387065ca9SDavid Wu 		.pin = 22,
72487065ca9SDavid Wu 		.func = 2,
72587065ca9SDavid Wu 		.route_offset = 0x184,
72687065ca9SDavid Wu 		.route_val = BIT(16 + 8),
72787065ca9SDavid Wu 	}, {
72887065ca9SDavid Wu 		/* pdm-m1 */
72987065ca9SDavid Wu 		.bank_num = 2,
73087065ca9SDavid Wu 		.pin = 22,
73187065ca9SDavid Wu 		.func = 1,
73287065ca9SDavid Wu 		.route_offset = 0x184,
73387065ca9SDavid Wu 		.route_val = BIT(16 + 8) | BIT(8),
73487065ca9SDavid Wu 	}, {
73587065ca9SDavid Wu 		/* uart2-rxm0 */
73687065ca9SDavid Wu 		.bank_num = 1,
73787065ca9SDavid Wu 		.pin = 27,
73887065ca9SDavid Wu 		.func = 2,
73987065ca9SDavid Wu 		.route_offset = 0x184,
74087065ca9SDavid Wu 		.route_val = BIT(16 + 10),
74187065ca9SDavid Wu 	}, {
74287065ca9SDavid Wu 		/* uart2-rxm1 */
74387065ca9SDavid Wu 		.bank_num = 2,
74487065ca9SDavid Wu 		.pin = 14,
74587065ca9SDavid Wu 		.func = 2,
74687065ca9SDavid Wu 		.route_offset = 0x184,
74787065ca9SDavid Wu 		.route_val = BIT(16 + 10) | BIT(10),
74887065ca9SDavid Wu 	}, {
74987065ca9SDavid Wu 		/* uart3-rxm0 */
75087065ca9SDavid Wu 		.bank_num = 0,
75187065ca9SDavid Wu 		.pin = 17,
75287065ca9SDavid Wu 		.func = 2,
75387065ca9SDavid Wu 		.route_offset = 0x184,
75487065ca9SDavid Wu 		.route_val = BIT(16 + 9),
75587065ca9SDavid Wu 	}, {
75687065ca9SDavid Wu 		/* uart3-rxm1 */
75787065ca9SDavid Wu 		.bank_num = 1,
75887065ca9SDavid Wu 		.pin = 15,
75987065ca9SDavid Wu 		.func = 2,
76087065ca9SDavid Wu 		.route_offset = 0x184,
76187065ca9SDavid Wu 		.route_val = BIT(16 + 9) | BIT(9),
76287065ca9SDavid Wu 	},
76387065ca9SDavid Wu };
76487065ca9SDavid Wu 
765d23c66dfSDavid Wu static struct rockchip_mux_route_data rk3128_mux_route_data[] = {
766d23c66dfSDavid Wu 	{
767d23c66dfSDavid Wu 		/* spi-0 */
768d23c66dfSDavid Wu 		.bank_num = 1,
769d23c66dfSDavid Wu 		.pin = 10,
770d23c66dfSDavid Wu 		.func = 1,
771d23c66dfSDavid Wu 		.route_offset = 0x144,
772d23c66dfSDavid Wu 		.route_val = BIT(16 + 3) | BIT(16 + 4),
773d23c66dfSDavid Wu 	}, {
774d23c66dfSDavid Wu 		/* spi-1 */
775d23c66dfSDavid Wu 		.bank_num = 1,
776d23c66dfSDavid Wu 		.pin = 27,
777d23c66dfSDavid Wu 		.func = 3,
778d23c66dfSDavid Wu 		.route_offset = 0x144,
779d23c66dfSDavid Wu 		.route_val = BIT(16 + 3) | BIT(16 + 4) | BIT(3),
780d23c66dfSDavid Wu 	}, {
781d23c66dfSDavid Wu 		/* spi-2 */
782d23c66dfSDavid Wu 		.bank_num = 0,
783d23c66dfSDavid Wu 		.pin = 13,
784d23c66dfSDavid Wu 		.func = 2,
785d23c66dfSDavid Wu 		.route_offset = 0x144,
786d23c66dfSDavid Wu 		.route_val = BIT(16 + 3) | BIT(16 + 4) | BIT(4),
787d23c66dfSDavid Wu 	}, {
788d23c66dfSDavid Wu 		/* i2s-0 */
789d23c66dfSDavid Wu 		.bank_num = 1,
790d23c66dfSDavid Wu 		.pin = 5,
791d23c66dfSDavid Wu 		.func = 1,
792d23c66dfSDavid Wu 		.route_offset = 0x144,
793d23c66dfSDavid Wu 		.route_val = BIT(16 + 5),
794d23c66dfSDavid Wu 	}, {
795d23c66dfSDavid Wu 		/* i2s-1 */
796d23c66dfSDavid Wu 		.bank_num = 0,
797d23c66dfSDavid Wu 		.pin = 14,
798d23c66dfSDavid Wu 		.func = 1,
799d23c66dfSDavid Wu 		.route_offset = 0x144,
800d23c66dfSDavid Wu 		.route_val = BIT(16 + 5) | BIT(5),
801d23c66dfSDavid Wu 	}, {
802d23c66dfSDavid Wu 		/* emmc-0 */
803d23c66dfSDavid Wu 		.bank_num = 1,
804d23c66dfSDavid Wu 		.pin = 22,
805d23c66dfSDavid Wu 		.func = 2,
806d23c66dfSDavid Wu 		.route_offset = 0x144,
807d23c66dfSDavid Wu 		.route_val = BIT(16 + 6),
808d23c66dfSDavid Wu 	}, {
809d23c66dfSDavid Wu 		/* emmc-1 */
810d23c66dfSDavid Wu 		.bank_num = 2,
811d23c66dfSDavid Wu 		.pin = 4,
812d23c66dfSDavid Wu 		.func = 2,
813d23c66dfSDavid Wu 		.route_offset = 0x144,
814d23c66dfSDavid Wu 		.route_val = BIT(16 + 6) | BIT(6),
815d23c66dfSDavid Wu 	},
816d23c66dfSDavid Wu };
817d23c66dfSDavid Wu 
818d4970ee0SDavid Wu static struct rockchip_mux_route_data rk3228_mux_route_data[] = {
819d4970ee0SDavid Wu 	{
820d4970ee0SDavid Wu 		/* pwm0-0 */
821d4970ee0SDavid Wu 		.bank_num = 0,
822d4970ee0SDavid Wu 		.pin = 26,
823d4970ee0SDavid Wu 		.func = 1,
824d4970ee0SDavid Wu 		.route_offset = 0x50,
825d4970ee0SDavid Wu 		.route_val = BIT(16),
826d4970ee0SDavid Wu 	}, {
827d4970ee0SDavid Wu 		/* pwm0-1 */
828d4970ee0SDavid Wu 		.bank_num = 3,
829d4970ee0SDavid Wu 		.pin = 21,
830d4970ee0SDavid Wu 		.func = 1,
831d4970ee0SDavid Wu 		.route_offset = 0x50,
832d4970ee0SDavid Wu 		.route_val = BIT(16) | BIT(0),
833d4970ee0SDavid Wu 	}, {
834d4970ee0SDavid Wu 		/* pwm1-0 */
835d4970ee0SDavid Wu 		.bank_num = 0,
836d4970ee0SDavid Wu 		.pin = 27,
837d4970ee0SDavid Wu 		.func = 1,
838d4970ee0SDavid Wu 		.route_offset = 0x50,
839d4970ee0SDavid Wu 		.route_val = BIT(16 + 1),
840d4970ee0SDavid Wu 	}, {
841d4970ee0SDavid Wu 		/* pwm1-1 */
842d4970ee0SDavid Wu 		.bank_num = 0,
843d4970ee0SDavid Wu 		.pin = 30,
844d4970ee0SDavid Wu 		.func = 2,
845d4970ee0SDavid Wu 		.route_offset = 0x50,
846d4970ee0SDavid Wu 		.route_val = BIT(16 + 1) | BIT(1),
847d4970ee0SDavid Wu 	}, {
848d4970ee0SDavid Wu 		/* pwm2-0 */
849d4970ee0SDavid Wu 		.bank_num = 0,
850d4970ee0SDavid Wu 		.pin = 28,
851d4970ee0SDavid Wu 		.func = 1,
852d4970ee0SDavid Wu 		.route_offset = 0x50,
853d4970ee0SDavid Wu 		.route_val = BIT(16 + 2),
854d4970ee0SDavid Wu 	}, {
855d4970ee0SDavid Wu 		/* pwm2-1 */
856d4970ee0SDavid Wu 		.bank_num = 1,
857d4970ee0SDavid Wu 		.pin = 12,
858d4970ee0SDavid Wu 		.func = 2,
859d4970ee0SDavid Wu 		.route_offset = 0x50,
860d4970ee0SDavid Wu 		.route_val = BIT(16 + 2) | BIT(2),
861d4970ee0SDavid Wu 	}, {
862d4970ee0SDavid Wu 		/* pwm3-0 */
863d4970ee0SDavid Wu 		.bank_num = 3,
864d4970ee0SDavid Wu 		.pin = 26,
865d4970ee0SDavid Wu 		.func = 1,
866d4970ee0SDavid Wu 		.route_offset = 0x50,
867d4970ee0SDavid Wu 		.route_val = BIT(16 + 3),
868d4970ee0SDavid Wu 	}, {
869d4970ee0SDavid Wu 		/* pwm3-1 */
870d4970ee0SDavid Wu 		.bank_num = 1,
871d4970ee0SDavid Wu 		.pin = 11,
872d4970ee0SDavid Wu 		.func = 2,
873d4970ee0SDavid Wu 		.route_offset = 0x50,
874d4970ee0SDavid Wu 		.route_val = BIT(16 + 3) | BIT(3),
875d4970ee0SDavid Wu 	}, {
876d4970ee0SDavid Wu 		/* sdio-0_d0 */
877d4970ee0SDavid Wu 		.bank_num = 1,
878d4970ee0SDavid Wu 		.pin = 1,
879d4970ee0SDavid Wu 		.func = 1,
880d4970ee0SDavid Wu 		.route_offset = 0x50,
881d4970ee0SDavid Wu 		.route_val = BIT(16 + 4),
882d4970ee0SDavid Wu 	}, {
883d4970ee0SDavid Wu 		/* sdio-1_d0 */
884d4970ee0SDavid Wu 		.bank_num = 3,
885d4970ee0SDavid Wu 		.pin = 2,
886d4970ee0SDavid Wu 		.func = 1,
887d4970ee0SDavid Wu 		.route_offset = 0x50,
888d4970ee0SDavid Wu 		.route_val = BIT(16 + 4) | BIT(4),
889d4970ee0SDavid Wu 	}, {
890d4970ee0SDavid Wu 		/* spi-0_rx */
891d4970ee0SDavid Wu 		.bank_num = 0,
892d4970ee0SDavid Wu 		.pin = 13,
893d4970ee0SDavid Wu 		.func = 2,
894d4970ee0SDavid Wu 		.route_offset = 0x50,
895d4970ee0SDavid Wu 		.route_val = BIT(16 + 5),
896d4970ee0SDavid Wu 	}, {
897d4970ee0SDavid Wu 		/* spi-1_rx */
898d4970ee0SDavid Wu 		.bank_num = 2,
899d4970ee0SDavid Wu 		.pin = 0,
900d4970ee0SDavid Wu 		.func = 2,
901d4970ee0SDavid Wu 		.route_offset = 0x50,
902d4970ee0SDavid Wu 		.route_val = BIT(16 + 5) | BIT(5),
903d4970ee0SDavid Wu 	}, {
904d4970ee0SDavid Wu 		/* emmc-0_cmd */
905d4970ee0SDavid Wu 		.bank_num = 1,
906d4970ee0SDavid Wu 		.pin = 22,
907d4970ee0SDavid Wu 		.func = 2,
908d4970ee0SDavid Wu 		.route_offset = 0x50,
909d4970ee0SDavid Wu 		.route_val = BIT(16 + 7),
910d4970ee0SDavid Wu 	}, {
911d4970ee0SDavid Wu 		/* emmc-1_cmd */
912d4970ee0SDavid Wu 		.bank_num = 2,
913d4970ee0SDavid Wu 		.pin = 4,
914d4970ee0SDavid Wu 		.func = 2,
915d4970ee0SDavid Wu 		.route_offset = 0x50,
916d4970ee0SDavid Wu 		.route_val = BIT(16 + 7) | BIT(7),
917d4970ee0SDavid Wu 	}, {
918d4970ee0SDavid Wu 		/* uart2-0_rx */
919d4970ee0SDavid Wu 		.bank_num = 1,
920d4970ee0SDavid Wu 		.pin = 19,
921d4970ee0SDavid Wu 		.func = 2,
922d4970ee0SDavid Wu 		.route_offset = 0x50,
923d4970ee0SDavid Wu 		.route_val = BIT(16 + 8),
924d4970ee0SDavid Wu 	}, {
925d4970ee0SDavid Wu 		/* uart2-1_rx */
926d4970ee0SDavid Wu 		.bank_num = 1,
927d4970ee0SDavid Wu 		.pin = 10,
928d4970ee0SDavid Wu 		.func = 2,
929d4970ee0SDavid Wu 		.route_offset = 0x50,
930d4970ee0SDavid Wu 		.route_val = BIT(16 + 8) | BIT(8),
931d4970ee0SDavid Wu 	}, {
932d4970ee0SDavid Wu 		/* uart1-0_rx */
933d4970ee0SDavid Wu 		.bank_num = 1,
934d4970ee0SDavid Wu 		.pin = 10,
935d4970ee0SDavid Wu 		.func = 1,
936d4970ee0SDavid Wu 		.route_offset = 0x50,
937d4970ee0SDavid Wu 		.route_val = BIT(16 + 11),
938d4970ee0SDavid Wu 	}, {
939d4970ee0SDavid Wu 		/* uart1-1_rx */
940d4970ee0SDavid Wu 		.bank_num = 3,
941d4970ee0SDavid Wu 		.pin = 13,
942d4970ee0SDavid Wu 		.func = 1,
943d4970ee0SDavid Wu 		.route_offset = 0x50,
944d4970ee0SDavid Wu 		.route_val = BIT(16 + 11) | BIT(11),
945d4970ee0SDavid Wu 	},
946d4970ee0SDavid Wu };
947d4970ee0SDavid Wu 
9484e96fd30SHeiko Stuebner static struct rockchip_mux_route_data rk3288_mux_route_data[] = {
9494e96fd30SHeiko Stuebner 	{
9504e96fd30SHeiko Stuebner 		/* edphdmi_cecinoutt1 */
9514e96fd30SHeiko Stuebner 		.bank_num = 7,
9524e96fd30SHeiko Stuebner 		.pin = 16,
9534e96fd30SHeiko Stuebner 		.func = 2,
9544e96fd30SHeiko Stuebner 		.route_offset = 0x264,
9554e96fd30SHeiko Stuebner 		.route_val = BIT(16 + 12) | BIT(12),
9564e96fd30SHeiko Stuebner 	}, {
9574e96fd30SHeiko Stuebner 		/* edphdmi_cecinout */
9584e96fd30SHeiko Stuebner 		.bank_num = 7,
9594e96fd30SHeiko Stuebner 		.pin = 23,
9604e96fd30SHeiko Stuebner 		.func = 4,
9614e96fd30SHeiko Stuebner 		.route_offset = 0x264,
9624e96fd30SHeiko Stuebner 		.route_val = BIT(16 + 12),
9634e96fd30SHeiko Stuebner 	},
9644e96fd30SHeiko Stuebner };
9654e96fd30SHeiko Stuebner 
966cedc964aSDavid Wu static struct rockchip_mux_route_data rk3328_mux_route_data[] = {
967cedc964aSDavid Wu 	{
968cedc964aSDavid Wu 		/* uart2dbg_rxm0 */
969cedc964aSDavid Wu 		.bank_num = 1,
970cedc964aSDavid Wu 		.pin = 1,
971cedc964aSDavid Wu 		.func = 2,
972cedc964aSDavid Wu 		.route_offset = 0x50,
973cedc964aSDavid Wu 		.route_val = BIT(16) | BIT(16 + 1),
974cedc964aSDavid Wu 	}, {
975cedc964aSDavid Wu 		/* uart2dbg_rxm1 */
976cedc964aSDavid Wu 		.bank_num = 2,
977cedc964aSDavid Wu 		.pin = 1,
978cedc964aSDavid Wu 		.func = 1,
979cedc964aSDavid Wu 		.route_offset = 0x50,
980cedc964aSDavid Wu 		.route_val = BIT(16) | BIT(16 + 1) | BIT(0),
981cedc964aSDavid Wu 	}, {
982a976d7b1SDavid Wu 		/* gmac-m1_rxd0 */
983cedc964aSDavid Wu 		.bank_num = 1,
984cedc964aSDavid Wu 		.pin = 11,
985cedc964aSDavid Wu 		.func = 2,
986cedc964aSDavid Wu 		.route_offset = 0x50,
987a976d7b1SDavid Wu 		.route_val = BIT(16 + 2) | BIT(2),
988a976d7b1SDavid Wu 	}, {
989a976d7b1SDavid Wu 		/* gmac-m1-optimized_rxd3 */
990a976d7b1SDavid Wu 		.bank_num = 1,
991a976d7b1SDavid Wu 		.pin = 14,
992a976d7b1SDavid Wu 		.func = 2,
993a976d7b1SDavid Wu 		.route_offset = 0x50,
994a976d7b1SDavid Wu 		.route_val = BIT(16 + 10) | BIT(10),
995cedc964aSDavid Wu 	}, {
996cedc964aSDavid Wu 		/* pdm_sdi0m0 */
997cedc964aSDavid Wu 		.bank_num = 2,
998cedc964aSDavid Wu 		.pin = 19,
999cedc964aSDavid Wu 		.func = 2,
1000cedc964aSDavid Wu 		.route_offset = 0x50,
1001cedc964aSDavid Wu 		.route_val = BIT(16 + 3),
1002cedc964aSDavid Wu 	}, {
1003cedc964aSDavid Wu 		/* pdm_sdi0m1 */
1004cedc964aSDavid Wu 		.bank_num = 1,
1005cedc964aSDavid Wu 		.pin = 23,
1006cedc964aSDavid Wu 		.func = 3,
1007cedc964aSDavid Wu 		.route_offset = 0x50,
1008cedc964aSDavid Wu 		.route_val =  BIT(16 + 3) | BIT(3),
1009cedc964aSDavid Wu 	}, {
1010cedc964aSDavid Wu 		/* spi_rxdm2 */
1011cedc964aSDavid Wu 		.bank_num = 3,
1012cedc964aSDavid Wu 		.pin = 2,
1013cedc964aSDavid Wu 		.func = 4,
1014cedc964aSDavid Wu 		.route_offset = 0x50,
1015cedc964aSDavid Wu 		.route_val =  BIT(16 + 4) | BIT(16 + 5) | BIT(5),
1016cedc964aSDavid Wu 	}, {
1017cedc964aSDavid Wu 		/* i2s2_sdim0 */
1018cedc964aSDavid Wu 		.bank_num = 1,
1019cedc964aSDavid Wu 		.pin = 24,
1020cedc964aSDavid Wu 		.func = 1,
1021cedc964aSDavid Wu 		.route_offset = 0x50,
1022cedc964aSDavid Wu 		.route_val = BIT(16 + 6),
1023cedc964aSDavid Wu 	}, {
1024cedc964aSDavid Wu 		/* i2s2_sdim1 */
1025cedc964aSDavid Wu 		.bank_num = 3,
1026cedc964aSDavid Wu 		.pin = 2,
1027cedc964aSDavid Wu 		.func = 6,
1028cedc964aSDavid Wu 		.route_offset = 0x50,
1029cedc964aSDavid Wu 		.route_val =  BIT(16 + 6) | BIT(6),
1030cedc964aSDavid Wu 	}, {
1031cedc964aSDavid Wu 		/* card_iom1 */
1032cedc964aSDavid Wu 		.bank_num = 2,
1033cedc964aSDavid Wu 		.pin = 22,
1034cedc964aSDavid Wu 		.func = 3,
1035cedc964aSDavid Wu 		.route_offset = 0x50,
1036cedc964aSDavid Wu 		.route_val =  BIT(16 + 7) | BIT(7),
1037cedc964aSDavid Wu 	}, {
1038cedc964aSDavid Wu 		/* tsp_d5m1 */
1039cedc964aSDavid Wu 		.bank_num = 2,
1040cedc964aSDavid Wu 		.pin = 16,
1041cedc964aSDavid Wu 		.func = 3,
1042cedc964aSDavid Wu 		.route_offset = 0x50,
1043cedc964aSDavid Wu 		.route_val =  BIT(16 + 8) | BIT(8),
1044cedc964aSDavid Wu 	}, {
1045cedc964aSDavid Wu 		/* cif_data5m1 */
1046cedc964aSDavid Wu 		.bank_num = 2,
1047cedc964aSDavid Wu 		.pin = 16,
1048cedc964aSDavid Wu 		.func = 4,
1049cedc964aSDavid Wu 		.route_offset = 0x50,
1050cedc964aSDavid Wu 		.route_val =  BIT(16 + 9) | BIT(9),
1051cedc964aSDavid Wu 	},
1052cedc964aSDavid Wu };
1053cedc964aSDavid Wu 
1054accc1ce7SDavid Wu static struct rockchip_mux_route_data rk3399_mux_route_data[] = {
1055accc1ce7SDavid Wu 	{
1056accc1ce7SDavid Wu 		/* uart2dbga_rx */
1057accc1ce7SDavid Wu 		.bank_num = 4,
1058accc1ce7SDavid Wu 		.pin = 8,
1059accc1ce7SDavid Wu 		.func = 2,
1060accc1ce7SDavid Wu 		.route_offset = 0xe21c,
1061accc1ce7SDavid Wu 		.route_val = BIT(16 + 10) | BIT(16 + 11),
1062accc1ce7SDavid Wu 	}, {
1063accc1ce7SDavid Wu 		/* uart2dbgb_rx */
1064accc1ce7SDavid Wu 		.bank_num = 4,
1065accc1ce7SDavid Wu 		.pin = 16,
1066accc1ce7SDavid Wu 		.func = 2,
1067accc1ce7SDavid Wu 		.route_offset = 0xe21c,
1068accc1ce7SDavid Wu 		.route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(10),
1069accc1ce7SDavid Wu 	}, {
1070accc1ce7SDavid Wu 		/* uart2dbgc_rx */
1071accc1ce7SDavid Wu 		.bank_num = 4,
1072accc1ce7SDavid Wu 		.pin = 19,
1073accc1ce7SDavid Wu 		.func = 1,
1074accc1ce7SDavid Wu 		.route_offset = 0xe21c,
1075accc1ce7SDavid Wu 		.route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(11),
1076accc1ce7SDavid Wu 	}, {
1077accc1ce7SDavid Wu 		/* pcie_clkreqn */
1078accc1ce7SDavid Wu 		.bank_num = 2,
1079accc1ce7SDavid Wu 		.pin = 26,
1080accc1ce7SDavid Wu 		.func = 2,
1081accc1ce7SDavid Wu 		.route_offset = 0xe21c,
1082accc1ce7SDavid Wu 		.route_val = BIT(16 + 14),
1083accc1ce7SDavid Wu 	}, {
1084accc1ce7SDavid Wu 		/* pcie_clkreqnb */
1085accc1ce7SDavid Wu 		.bank_num = 4,
1086accc1ce7SDavid Wu 		.pin = 24,
1087accc1ce7SDavid Wu 		.func = 1,
1088accc1ce7SDavid Wu 		.route_offset = 0xe21c,
1089accc1ce7SDavid Wu 		.route_val = BIT(16 + 14) | BIT(14),
1090accc1ce7SDavid Wu 	},
1091accc1ce7SDavid Wu };
1092accc1ce7SDavid Wu 
1093bd35b9bfSDavid Wu static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
1094bd35b9bfSDavid Wu 				   int mux, u32 *reg, u32 *value)
1095bd35b9bfSDavid Wu {
1096bd35b9bfSDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
1097bd35b9bfSDavid Wu 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1098bd35b9bfSDavid Wu 	struct rockchip_mux_route_data *data;
1099bd35b9bfSDavid Wu 	int i;
1100bd35b9bfSDavid Wu 
1101bd35b9bfSDavid Wu 	for (i = 0; i < ctrl->niomux_routes; i++) {
1102bd35b9bfSDavid Wu 		data = &ctrl->iomux_routes[i];
1103bd35b9bfSDavid Wu 		if ((data->bank_num == bank->bank_num) &&
1104bd35b9bfSDavid Wu 		    (data->pin == pin) && (data->func == mux))
1105bd35b9bfSDavid Wu 			break;
1106bd35b9bfSDavid Wu 	}
1107bd35b9bfSDavid Wu 
1108bd35b9bfSDavid Wu 	if (i >= ctrl->niomux_routes)
1109bd35b9bfSDavid Wu 		return false;
1110bd35b9bfSDavid Wu 
1111bd35b9bfSDavid Wu 	*reg = data->route_offset;
1112bd35b9bfSDavid Wu 	*value = data->route_val;
1113bd35b9bfSDavid Wu 
1114bd35b9bfSDavid Wu 	return true;
1115bd35b9bfSDavid Wu }
1116bd35b9bfSDavid Wu 
1117a076e2edSHeiko Stübner static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
1118a076e2edSHeiko Stübner {
1119a076e2edSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1120fc72c923SHeiko Stübner 	int iomux_num = (pin / 8);
112195ec8ae4SHeiko Stübner 	struct regmap *regmap;
1122751a99abSHeiko Stübner 	unsigned int val;
1123ea262ad6Sdavid.wu 	int reg, ret, mask, mux_type;
1124a076e2edSHeiko Stübner 	u8 bit;
1125a076e2edSHeiko Stübner 
1126fc72c923SHeiko Stübner 	if (iomux_num > 3)
1127fc72c923SHeiko Stübner 		return -EINVAL;
1128fc72c923SHeiko Stübner 
112962f49226SHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
113062f49226SHeiko Stübner 		dev_err(info->dev, "pin %d is unrouted\n", pin);
113162f49226SHeiko Stübner 		return -EINVAL;
113262f49226SHeiko Stübner 	}
113362f49226SHeiko Stübner 
1134fc72c923SHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
1135a076e2edSHeiko Stübner 		return RK_FUNC_GPIO;
1136a076e2edSHeiko Stübner 
113795ec8ae4SHeiko Stübner 	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
113895ec8ae4SHeiko Stübner 				? info->regmap_pmu : info->regmap_base;
113995ec8ae4SHeiko Stübner 
1140a076e2edSHeiko Stübner 	/* get basic quadrupel of mux registers and the correct reg inside */
1141ea262ad6Sdavid.wu 	mux_type = bank->iomux[iomux_num].type;
11426bc0d121SHeiko Stübner 	reg = bank->iomux[iomux_num].offset;
1143ea262ad6Sdavid.wu 	if (mux_type & IOMUX_WIDTH_4BIT) {
114403716e1dSHeiko Stübner 		if ((pin % 8) >= 4)
114503716e1dSHeiko Stübner 			reg += 0x4;
114603716e1dSHeiko Stübner 		bit = (pin % 4) * 4;
11478b6c6f93Sdavid.wu 		mask = 0xf;
1148ea262ad6Sdavid.wu 	} else if (mux_type & IOMUX_WIDTH_3BIT) {
11498b6c6f93Sdavid.wu 		if ((pin % 8) >= 5)
11508b6c6f93Sdavid.wu 			reg += 0x4;
11518b6c6f93Sdavid.wu 		bit = (pin % 8 % 5) * 3;
11528b6c6f93Sdavid.wu 		mask = 0x7;
115303716e1dSHeiko Stübner 	} else {
1154a076e2edSHeiko Stübner 		bit = (pin % 8) * 2;
11558b6c6f93Sdavid.wu 		mask = 0x3;
115603716e1dSHeiko Stübner 	}
1157a076e2edSHeiko Stübner 
1158c04c3fa6SDavid Wu 	if (bank->recalced_mask & BIT(pin))
1159c04c3fa6SDavid Wu 		rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
1160ea262ad6Sdavid.wu 
116195ec8ae4SHeiko Stübner 	ret = regmap_read(regmap, reg, &val);
1162751a99abSHeiko Stübner 	if (ret)
1163751a99abSHeiko Stübner 		return ret;
1164751a99abSHeiko Stübner 
116503716e1dSHeiko Stübner 	return ((val >> bit) & mask);
1166a076e2edSHeiko Stübner }
1167a076e2edSHeiko Stübner 
116805709c3eSJohn Keeping static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
116905709c3eSJohn Keeping 			       int pin, int mux)
117005709c3eSJohn Keeping {
117105709c3eSJohn Keeping 	struct rockchip_pinctrl *info = bank->drvdata;
117205709c3eSJohn Keeping 	int iomux_num = (pin / 8);
117305709c3eSJohn Keeping 
117405709c3eSJohn Keeping 	if (iomux_num > 3)
117505709c3eSJohn Keeping 		return -EINVAL;
117605709c3eSJohn Keeping 
117705709c3eSJohn Keeping 	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
117805709c3eSJohn Keeping 		dev_err(info->dev, "pin %d is unrouted\n", pin);
117905709c3eSJohn Keeping 		return -EINVAL;
118005709c3eSJohn Keeping 	}
118105709c3eSJohn Keeping 
118205709c3eSJohn Keeping 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
118305709c3eSJohn Keeping 		if (mux != RK_FUNC_GPIO) {
118405709c3eSJohn Keeping 			dev_err(info->dev,
118505709c3eSJohn Keeping 				"pin %d only supports a gpio mux\n", pin);
118605709c3eSJohn Keeping 			return -ENOTSUPP;
118705709c3eSJohn Keeping 		}
118805709c3eSJohn Keeping 	}
118905709c3eSJohn Keeping 
119005709c3eSJohn Keeping 	return 0;
119105709c3eSJohn Keeping }
119205709c3eSJohn Keeping 
1193d3e51161SHeiko Stübner /*
1194d3e51161SHeiko Stübner  * Set a new mux function for a pin.
1195d3e51161SHeiko Stübner  *
1196d3e51161SHeiko Stübner  * The register is divided into the upper and lower 16 bit. When changing
1197d3e51161SHeiko Stübner  * a value, the previous register value is not read and changed. Instead
1198d3e51161SHeiko Stübner  * it seems the changed bits are marked in the upper 16 bit, while the
1199d3e51161SHeiko Stübner  * changed value gets set in the same offset in the lower 16 bit.
1200d3e51161SHeiko Stübner  * All pin settings seem to be 2 bit wide in both the upper and lower
1201d3e51161SHeiko Stübner  * parts.
1202d3e51161SHeiko Stübner  * @bank: pin bank to change
1203d3e51161SHeiko Stübner  * @pin: pin to change
1204d3e51161SHeiko Stübner  * @mux: new mux function to set
1205d3e51161SHeiko Stübner  */
120614797189SHeiko Stübner static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
1207d3e51161SHeiko Stübner {
1208d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1209fc72c923SHeiko Stübner 	int iomux_num = (pin / 8);
121095ec8ae4SHeiko Stübner 	struct regmap *regmap;
1211ea262ad6Sdavid.wu 	int reg, ret, mask, mux_type;
1212d3e51161SHeiko Stübner 	u8 bit;
1213bd35b9bfSDavid Wu 	u32 data, rmask, route_reg, route_val;
1214d3e51161SHeiko Stübner 
121505709c3eSJohn Keeping 	ret = rockchip_verify_mux(bank, pin, mux);
121605709c3eSJohn Keeping 	if (ret < 0)
121705709c3eSJohn Keeping 		return ret;
1218fc72c923SHeiko Stübner 
121905709c3eSJohn Keeping 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
1220c4a532deSHeiko Stübner 		return 0;
1221c4a532deSHeiko Stübner 
1222d3e51161SHeiko Stübner 	dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n",
1223d3e51161SHeiko Stübner 						bank->bank_num, pin, mux);
1224d3e51161SHeiko Stübner 
122595ec8ae4SHeiko Stübner 	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
122695ec8ae4SHeiko Stübner 				? info->regmap_pmu : info->regmap_base;
122795ec8ae4SHeiko Stübner 
1228d3e51161SHeiko Stübner 	/* get basic quadrupel of mux registers and the correct reg inside */
1229ea262ad6Sdavid.wu 	mux_type = bank->iomux[iomux_num].type;
12306bc0d121SHeiko Stübner 	reg = bank->iomux[iomux_num].offset;
1231ea262ad6Sdavid.wu 	if (mux_type & IOMUX_WIDTH_4BIT) {
123203716e1dSHeiko Stübner 		if ((pin % 8) >= 4)
123303716e1dSHeiko Stübner 			reg += 0x4;
123403716e1dSHeiko Stübner 		bit = (pin % 4) * 4;
12358b6c6f93Sdavid.wu 		mask = 0xf;
1236ea262ad6Sdavid.wu 	} else if (mux_type & IOMUX_WIDTH_3BIT) {
12378b6c6f93Sdavid.wu 		if ((pin % 8) >= 5)
12388b6c6f93Sdavid.wu 			reg += 0x4;
12398b6c6f93Sdavid.wu 		bit = (pin % 8 % 5) * 3;
12408b6c6f93Sdavid.wu 		mask = 0x7;
124103716e1dSHeiko Stübner 	} else {
1242d3e51161SHeiko Stübner 		bit = (pin % 8) * 2;
12438b6c6f93Sdavid.wu 		mask = 0x3;
124403716e1dSHeiko Stübner 	}
1245d3e51161SHeiko Stübner 
1246c04c3fa6SDavid Wu 	if (bank->recalced_mask & BIT(pin))
1247c04c3fa6SDavid Wu 		rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
1248ea262ad6Sdavid.wu 
1249bd35b9bfSDavid Wu 	if (bank->route_mask & BIT(pin)) {
1250bd35b9bfSDavid Wu 		if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
1251bd35b9bfSDavid Wu 					   &route_val)) {
1252bd35b9bfSDavid Wu 			ret = regmap_write(regmap, route_reg, route_val);
1253bd35b9bfSDavid Wu 			if (ret)
1254bd35b9bfSDavid Wu 				return ret;
1255bd35b9bfSDavid Wu 		}
1256bd35b9bfSDavid Wu 	}
1257bd35b9bfSDavid Wu 
125803716e1dSHeiko Stübner 	data = (mask << (bit + 16));
125999e872d9SSonny Rao 	rmask = data | (data >> 16);
126003716e1dSHeiko Stübner 	data |= (mux & mask) << bit;
126199e872d9SSonny Rao 	ret = regmap_update_bits(regmap, reg, rmask, data);
1262d3e51161SHeiko Stübner 
1263751a99abSHeiko Stübner 	return ret;
1264d3e51161SHeiko Stübner }
1265d3e51161SHeiko Stübner 
126687065ca9SDavid Wu #define PX30_PULL_PMU_OFFSET		0x10
126787065ca9SDavid Wu #define PX30_PULL_GRF_OFFSET		0x60
126887065ca9SDavid Wu #define PX30_PULL_BITS_PER_PIN		2
126987065ca9SDavid Wu #define PX30_PULL_PINS_PER_REG		8
127087065ca9SDavid Wu #define PX30_PULL_BANK_STRIDE		16
127187065ca9SDavid Wu 
127287065ca9SDavid Wu static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
127387065ca9SDavid Wu 				       int pin_num, struct regmap **regmap,
127487065ca9SDavid Wu 				       int *reg, u8 *bit)
127587065ca9SDavid Wu {
127687065ca9SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
127787065ca9SDavid Wu 
127887065ca9SDavid Wu 	/* The first 32 pins of the first bank are located in PMU */
127987065ca9SDavid Wu 	if (bank->bank_num == 0) {
128087065ca9SDavid Wu 		*regmap = info->regmap_pmu;
128187065ca9SDavid Wu 		*reg = PX30_PULL_PMU_OFFSET;
128287065ca9SDavid Wu 	} else {
128387065ca9SDavid Wu 		*regmap = info->regmap_base;
128487065ca9SDavid Wu 		*reg = PX30_PULL_GRF_OFFSET;
128587065ca9SDavid Wu 
128687065ca9SDavid Wu 		/* correct the offset, as we're starting with the 2nd bank */
128787065ca9SDavid Wu 		*reg -= 0x10;
128887065ca9SDavid Wu 		*reg += bank->bank_num * PX30_PULL_BANK_STRIDE;
128987065ca9SDavid Wu 	}
129087065ca9SDavid Wu 
129187065ca9SDavid Wu 	*reg += ((pin_num / PX30_PULL_PINS_PER_REG) * 4);
129287065ca9SDavid Wu 	*bit = (pin_num % PX30_PULL_PINS_PER_REG);
129387065ca9SDavid Wu 	*bit *= PX30_PULL_BITS_PER_PIN;
129487065ca9SDavid Wu }
129587065ca9SDavid Wu 
129687065ca9SDavid Wu #define PX30_DRV_PMU_OFFSET		0x20
129787065ca9SDavid Wu #define PX30_DRV_GRF_OFFSET		0xf0
129887065ca9SDavid Wu #define PX30_DRV_BITS_PER_PIN		2
129987065ca9SDavid Wu #define PX30_DRV_PINS_PER_REG		8
130087065ca9SDavid Wu #define PX30_DRV_BANK_STRIDE		16
130187065ca9SDavid Wu 
130287065ca9SDavid Wu static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
130387065ca9SDavid Wu 				      int pin_num, struct regmap **regmap,
130487065ca9SDavid Wu 				      int *reg, u8 *bit)
130587065ca9SDavid Wu {
130687065ca9SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
130787065ca9SDavid Wu 
130887065ca9SDavid Wu 	/* The first 32 pins of the first bank are located in PMU */
130987065ca9SDavid Wu 	if (bank->bank_num == 0) {
131087065ca9SDavid Wu 		*regmap = info->regmap_pmu;
131187065ca9SDavid Wu 		*reg = PX30_DRV_PMU_OFFSET;
131287065ca9SDavid Wu 	} else {
131387065ca9SDavid Wu 		*regmap = info->regmap_base;
131487065ca9SDavid Wu 		*reg = PX30_DRV_GRF_OFFSET;
131587065ca9SDavid Wu 
131687065ca9SDavid Wu 		/* correct the offset, as we're starting with the 2nd bank */
131787065ca9SDavid Wu 		*reg -= 0x10;
131887065ca9SDavid Wu 		*reg += bank->bank_num * PX30_DRV_BANK_STRIDE;
131987065ca9SDavid Wu 	}
132087065ca9SDavid Wu 
132187065ca9SDavid Wu 	*reg += ((pin_num / PX30_DRV_PINS_PER_REG) * 4);
132287065ca9SDavid Wu 	*bit = (pin_num % PX30_DRV_PINS_PER_REG);
132387065ca9SDavid Wu 	*bit *= PX30_DRV_BITS_PER_PIN;
132487065ca9SDavid Wu }
132587065ca9SDavid Wu 
132687065ca9SDavid Wu #define PX30_SCHMITT_PMU_OFFSET			0x38
132787065ca9SDavid Wu #define PX30_SCHMITT_GRF_OFFSET			0xc0
132887065ca9SDavid Wu #define PX30_SCHMITT_PINS_PER_PMU_REG		16
132987065ca9SDavid Wu #define PX30_SCHMITT_BANK_STRIDE		16
133087065ca9SDavid Wu #define PX30_SCHMITT_PINS_PER_GRF_REG		8
133187065ca9SDavid Wu 
133287065ca9SDavid Wu static int px30_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
133387065ca9SDavid Wu 					 int pin_num,
133487065ca9SDavid Wu 					 struct regmap **regmap,
133587065ca9SDavid Wu 					 int *reg, u8 *bit)
133687065ca9SDavid Wu {
133787065ca9SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
133887065ca9SDavid Wu 	int pins_per_reg;
133987065ca9SDavid Wu 
134087065ca9SDavid Wu 	if (bank->bank_num == 0) {
134187065ca9SDavid Wu 		*regmap = info->regmap_pmu;
134287065ca9SDavid Wu 		*reg = PX30_SCHMITT_PMU_OFFSET;
134387065ca9SDavid Wu 		pins_per_reg = PX30_SCHMITT_PINS_PER_PMU_REG;
134487065ca9SDavid Wu 	} else {
134587065ca9SDavid Wu 		*regmap = info->regmap_base;
134687065ca9SDavid Wu 		*reg = PX30_SCHMITT_GRF_OFFSET;
134787065ca9SDavid Wu 		pins_per_reg = PX30_SCHMITT_PINS_PER_GRF_REG;
134887065ca9SDavid Wu 		*reg += (bank->bank_num  - 1) * PX30_SCHMITT_BANK_STRIDE;
134987065ca9SDavid Wu 	}
135087065ca9SDavid Wu 
135187065ca9SDavid Wu 	*reg += ((pin_num / pins_per_reg) * 4);
135287065ca9SDavid Wu 	*bit = pin_num % pins_per_reg;
135387065ca9SDavid Wu 
135487065ca9SDavid Wu 	return 0;
135587065ca9SDavid Wu }
135687065ca9SDavid Wu 
1357b9c6dcabSAndy Yan #define RV1108_PULL_PMU_OFFSET		0x10
1358b9c6dcabSAndy Yan #define RV1108_PULL_OFFSET		0x110
1359b9c6dcabSAndy Yan #define RV1108_PULL_PINS_PER_REG	8
1360b9c6dcabSAndy Yan #define RV1108_PULL_BITS_PER_PIN	2
1361b9c6dcabSAndy Yan #define RV1108_PULL_BANK_STRIDE		16
1362688daf23SAndy Yan 
1363b9c6dcabSAndy Yan static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1364688daf23SAndy Yan 					 int pin_num, struct regmap **regmap,
1365688daf23SAndy Yan 					 int *reg, u8 *bit)
1366688daf23SAndy Yan {
1367688daf23SAndy Yan 	struct rockchip_pinctrl *info = bank->drvdata;
1368688daf23SAndy Yan 
1369688daf23SAndy Yan 	/* The first 24 pins of the first bank are located in PMU */
1370688daf23SAndy Yan 	if (bank->bank_num == 0) {
1371688daf23SAndy Yan 		*regmap = info->regmap_pmu;
1372b9c6dcabSAndy Yan 		*reg = RV1108_PULL_PMU_OFFSET;
1373688daf23SAndy Yan 	} else {
1374b9c6dcabSAndy Yan 		*reg = RV1108_PULL_OFFSET;
1375688daf23SAndy Yan 		*regmap = info->regmap_base;
1376688daf23SAndy Yan 		/* correct the offset, as we're starting with the 2nd bank */
1377688daf23SAndy Yan 		*reg -= 0x10;
1378b9c6dcabSAndy Yan 		*reg += bank->bank_num * RV1108_PULL_BANK_STRIDE;
1379688daf23SAndy Yan 	}
1380688daf23SAndy Yan 
1381b9c6dcabSAndy Yan 	*reg += ((pin_num / RV1108_PULL_PINS_PER_REG) * 4);
1382b9c6dcabSAndy Yan 	*bit = (pin_num % RV1108_PULL_PINS_PER_REG);
1383b9c6dcabSAndy Yan 	*bit *= RV1108_PULL_BITS_PER_PIN;
1384688daf23SAndy Yan }
1385688daf23SAndy Yan 
1386b9c6dcabSAndy Yan #define RV1108_DRV_PMU_OFFSET		0x20
1387b9c6dcabSAndy Yan #define RV1108_DRV_GRF_OFFSET		0x210
1388b9c6dcabSAndy Yan #define RV1108_DRV_BITS_PER_PIN		2
1389b9c6dcabSAndy Yan #define RV1108_DRV_PINS_PER_REG		8
1390b9c6dcabSAndy Yan #define RV1108_DRV_BANK_STRIDE		16
1391688daf23SAndy Yan 
1392b9c6dcabSAndy Yan static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
1393688daf23SAndy Yan 					int pin_num, struct regmap **regmap,
1394688daf23SAndy Yan 					int *reg, u8 *bit)
1395688daf23SAndy Yan {
1396688daf23SAndy Yan 	struct rockchip_pinctrl *info = bank->drvdata;
1397688daf23SAndy Yan 
1398688daf23SAndy Yan 	/* The first 24 pins of the first bank are located in PMU */
1399688daf23SAndy Yan 	if (bank->bank_num == 0) {
1400688daf23SAndy Yan 		*regmap = info->regmap_pmu;
1401b9c6dcabSAndy Yan 		*reg = RV1108_DRV_PMU_OFFSET;
1402688daf23SAndy Yan 	} else {
1403688daf23SAndy Yan 		*regmap = info->regmap_base;
1404b9c6dcabSAndy Yan 		*reg = RV1108_DRV_GRF_OFFSET;
1405688daf23SAndy Yan 
1406688daf23SAndy Yan 		/* correct the offset, as we're starting with the 2nd bank */
1407688daf23SAndy Yan 		*reg -= 0x10;
1408b9c6dcabSAndy Yan 		*reg += bank->bank_num * RV1108_DRV_BANK_STRIDE;
1409688daf23SAndy Yan 	}
1410688daf23SAndy Yan 
1411b9c6dcabSAndy Yan 	*reg += ((pin_num / RV1108_DRV_PINS_PER_REG) * 4);
1412b9c6dcabSAndy Yan 	*bit = pin_num % RV1108_DRV_PINS_PER_REG;
1413b9c6dcabSAndy Yan 	*bit *= RV1108_DRV_BITS_PER_PIN;
1414688daf23SAndy Yan }
1415688daf23SAndy Yan 
14165caff7eaSAndy Yan #define RV1108_SCHMITT_PMU_OFFSET		0x30
14175caff7eaSAndy Yan #define RV1108_SCHMITT_GRF_OFFSET		0x388
14185caff7eaSAndy Yan #define RV1108_SCHMITT_BANK_STRIDE		8
14195caff7eaSAndy Yan #define RV1108_SCHMITT_PINS_PER_GRF_REG		16
14205caff7eaSAndy Yan #define RV1108_SCHMITT_PINS_PER_PMU_REG		8
14215caff7eaSAndy Yan 
14225caff7eaSAndy Yan static int rv1108_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
14235caff7eaSAndy Yan 					   int pin_num,
14245caff7eaSAndy Yan 					   struct regmap **regmap,
14255caff7eaSAndy Yan 					   int *reg, u8 *bit)
14265caff7eaSAndy Yan {
14275caff7eaSAndy Yan 	struct rockchip_pinctrl *info = bank->drvdata;
14285caff7eaSAndy Yan 	int pins_per_reg;
14295caff7eaSAndy Yan 
14305caff7eaSAndy Yan 	if (bank->bank_num == 0) {
14315caff7eaSAndy Yan 		*regmap = info->regmap_pmu;
14325caff7eaSAndy Yan 		*reg = RV1108_SCHMITT_PMU_OFFSET;
14335caff7eaSAndy Yan 		pins_per_reg = RV1108_SCHMITT_PINS_PER_PMU_REG;
14345caff7eaSAndy Yan 	} else {
14355caff7eaSAndy Yan 		*regmap = info->regmap_base;
14365caff7eaSAndy Yan 		*reg = RV1108_SCHMITT_GRF_OFFSET;
14375caff7eaSAndy Yan 		pins_per_reg = RV1108_SCHMITT_PINS_PER_GRF_REG;
14385caff7eaSAndy Yan 		*reg += (bank->bank_num  - 1) * RV1108_SCHMITT_BANK_STRIDE;
14395caff7eaSAndy Yan 	}
14405caff7eaSAndy Yan 	*reg += ((pin_num / pins_per_reg) * 4);
14415caff7eaSAndy Yan 	*bit = pin_num % pins_per_reg;
14425caff7eaSAndy Yan 
14435caff7eaSAndy Yan 	return 0;
14445caff7eaSAndy Yan }
14455caff7eaSAndy Yan 
1446a282926dSHeiko Stübner #define RK2928_PULL_OFFSET		0x118
1447a282926dSHeiko Stübner #define RK2928_PULL_PINS_PER_REG	16
1448a282926dSHeiko Stübner #define RK2928_PULL_BANK_STRIDE		8
1449a282926dSHeiko Stübner 
1450a282926dSHeiko Stübner static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1451751a99abSHeiko Stübner 				    int pin_num, struct regmap **regmap,
1452751a99abSHeiko Stübner 				    int *reg, u8 *bit)
1453a282926dSHeiko Stübner {
1454a282926dSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1455a282926dSHeiko Stübner 
1456751a99abSHeiko Stübner 	*regmap = info->regmap_base;
1457751a99abSHeiko Stübner 	*reg = RK2928_PULL_OFFSET;
1458a282926dSHeiko Stübner 	*reg += bank->bank_num * RK2928_PULL_BANK_STRIDE;
1459a282926dSHeiko Stübner 	*reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4;
1460a282926dSHeiko Stübner 
1461a282926dSHeiko Stübner 	*bit = pin_num % RK2928_PULL_PINS_PER_REG;
1462a282926dSHeiko Stübner };
1463a282926dSHeiko Stübner 
1464d23c66dfSDavid Wu #define RK3128_PULL_OFFSET	0x118
1465d23c66dfSDavid Wu 
1466d23c66dfSDavid Wu static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1467d23c66dfSDavid Wu 					 int pin_num, struct regmap **regmap,
1468d23c66dfSDavid Wu 					 int *reg, u8 *bit)
1469d23c66dfSDavid Wu {
1470d23c66dfSDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
1471d23c66dfSDavid Wu 
1472d23c66dfSDavid Wu 	*regmap = info->regmap_base;
1473d23c66dfSDavid Wu 	*reg = RK3128_PULL_OFFSET;
1474d23c66dfSDavid Wu 	*reg += bank->bank_num * RK2928_PULL_BANK_STRIDE;
1475d23c66dfSDavid Wu 	*reg += ((pin_num / RK2928_PULL_PINS_PER_REG) * 4);
1476d23c66dfSDavid Wu 
1477d23c66dfSDavid Wu 	*bit = pin_num % RK2928_PULL_PINS_PER_REG;
1478d23c66dfSDavid Wu }
1479d23c66dfSDavid Wu 
1480bfc7a42aSHeiko Stübner #define RK3188_PULL_OFFSET		0x164
14816ca5274dSHeiko Stübner #define RK3188_PULL_BITS_PER_PIN	2
14826ca5274dSHeiko Stübner #define RK3188_PULL_PINS_PER_REG	8
14836ca5274dSHeiko Stübner #define RK3188_PULL_BANK_STRIDE		16
148414dee867SHeiko Stübner #define RK3188_PULL_PMU_OFFSET		0x64
14856ca5274dSHeiko Stübner 
14866ca5274dSHeiko Stübner static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1487751a99abSHeiko Stübner 				    int pin_num, struct regmap **regmap,
1488751a99abSHeiko Stübner 				    int *reg, u8 *bit)
14896ca5274dSHeiko Stübner {
14906ca5274dSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
14916ca5274dSHeiko Stübner 
14926ca5274dSHeiko Stübner 	/* The first 12 pins of the first bank are located elsewhere */
1493fc72c923SHeiko Stübner 	if (bank->bank_num == 0 && pin_num < 12) {
149414dee867SHeiko Stübner 		*regmap = info->regmap_pmu ? info->regmap_pmu
149514dee867SHeiko Stübner 					   : bank->regmap_pull;
149614dee867SHeiko Stübner 		*reg = info->regmap_pmu ? RK3188_PULL_PMU_OFFSET : 0;
1497751a99abSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
14986ca5274dSHeiko Stübner 		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
14996ca5274dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
15006ca5274dSHeiko Stübner 	} else {
1501751a99abSHeiko Stübner 		*regmap = info->regmap_pull ? info->regmap_pull
1502751a99abSHeiko Stübner 					    : info->regmap_base;
1503751a99abSHeiko Stübner 		*reg = info->regmap_pull ? 0 : RK3188_PULL_OFFSET;
1504751a99abSHeiko Stübner 
1505bfc7a42aSHeiko Stübner 		/* correct the offset, as it is the 2nd pull register */
1506bfc7a42aSHeiko Stübner 		*reg -= 4;
15076ca5274dSHeiko Stübner 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
15086ca5274dSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
15096ca5274dSHeiko Stübner 
15106ca5274dSHeiko Stübner 		/*
15116ca5274dSHeiko Stübner 		 * The bits in these registers have an inverse ordering
15126ca5274dSHeiko Stübner 		 * with the lowest pin being in bits 15:14 and the highest
15136ca5274dSHeiko Stübner 		 * pin in bits 1:0
15146ca5274dSHeiko Stübner 		 */
15156ca5274dSHeiko Stübner 		*bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG);
15166ca5274dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
15176ca5274dSHeiko Stübner 	}
15186ca5274dSHeiko Stübner }
15196ca5274dSHeiko Stübner 
1520304f077dSHeiko Stübner #define RK3288_PULL_OFFSET		0x140
1521304f077dSHeiko Stübner static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1522304f077dSHeiko Stübner 				    int pin_num, struct regmap **regmap,
1523304f077dSHeiko Stübner 				    int *reg, u8 *bit)
1524304f077dSHeiko Stübner {
1525304f077dSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1526304f077dSHeiko Stübner 
1527304f077dSHeiko Stübner 	/* The first 24 pins of the first bank are located in PMU */
1528304f077dSHeiko Stübner 	if (bank->bank_num == 0) {
1529304f077dSHeiko Stübner 		*regmap = info->regmap_pmu;
1530304f077dSHeiko Stübner 		*reg = RK3188_PULL_PMU_OFFSET;
1531304f077dSHeiko Stübner 
1532304f077dSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
1533304f077dSHeiko Stübner 		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
1534304f077dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
1535304f077dSHeiko Stübner 	} else {
1536304f077dSHeiko Stübner 		*regmap = info->regmap_base;
1537304f077dSHeiko Stübner 		*reg = RK3288_PULL_OFFSET;
1538304f077dSHeiko Stübner 
1539304f077dSHeiko Stübner 		/* correct the offset, as we're starting with the 2nd bank */
1540304f077dSHeiko Stübner 		*reg -= 0x10;
1541304f077dSHeiko Stübner 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
1542304f077dSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
1543304f077dSHeiko Stübner 
1544304f077dSHeiko Stübner 		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
1545304f077dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
1546304f077dSHeiko Stübner 	}
1547304f077dSHeiko Stübner }
1548304f077dSHeiko Stübner 
1549b547c800SHeiko Stübner #define RK3288_DRV_PMU_OFFSET		0x70
1550b547c800SHeiko Stübner #define RK3288_DRV_GRF_OFFSET		0x1c0
1551b547c800SHeiko Stübner #define RK3288_DRV_BITS_PER_PIN		2
1552b547c800SHeiko Stübner #define RK3288_DRV_PINS_PER_REG		8
1553b547c800SHeiko Stübner #define RK3288_DRV_BANK_STRIDE		16
1554b547c800SHeiko Stübner 
1555b547c800SHeiko Stübner static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
1556b547c800SHeiko Stübner 				    int pin_num, struct regmap **regmap,
1557b547c800SHeiko Stübner 				    int *reg, u8 *bit)
1558b547c800SHeiko Stübner {
1559b547c800SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1560b547c800SHeiko Stübner 
1561b547c800SHeiko Stübner 	/* The first 24 pins of the first bank are located in PMU */
1562b547c800SHeiko Stübner 	if (bank->bank_num == 0) {
1563b547c800SHeiko Stübner 		*regmap = info->regmap_pmu;
1564b547c800SHeiko Stübner 		*reg = RK3288_DRV_PMU_OFFSET;
1565b547c800SHeiko Stübner 
1566b547c800SHeiko Stübner 		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
1567b547c800SHeiko Stübner 		*bit = pin_num % RK3288_DRV_PINS_PER_REG;
1568b547c800SHeiko Stübner 		*bit *= RK3288_DRV_BITS_PER_PIN;
1569b547c800SHeiko Stübner 	} else {
1570b547c800SHeiko Stübner 		*regmap = info->regmap_base;
1571b547c800SHeiko Stübner 		*reg = RK3288_DRV_GRF_OFFSET;
1572b547c800SHeiko Stübner 
1573b547c800SHeiko Stübner 		/* correct the offset, as we're starting with the 2nd bank */
1574b547c800SHeiko Stübner 		*reg -= 0x10;
1575b547c800SHeiko Stübner 		*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
1576b547c800SHeiko Stübner 		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
1577b547c800SHeiko Stübner 
1578b547c800SHeiko Stübner 		*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
1579b547c800SHeiko Stübner 		*bit *= RK3288_DRV_BITS_PER_PIN;
1580b547c800SHeiko Stübner 	}
1581b547c800SHeiko Stübner }
1582b547c800SHeiko Stübner 
1583fea0fe60SJeffy Chen #define RK3228_PULL_OFFSET		0x100
1584fea0fe60SJeffy Chen 
1585fea0fe60SJeffy Chen static void rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1586fea0fe60SJeffy Chen 				    int pin_num, struct regmap **regmap,
1587fea0fe60SJeffy Chen 				    int *reg, u8 *bit)
1588fea0fe60SJeffy Chen {
1589fea0fe60SJeffy Chen 	struct rockchip_pinctrl *info = bank->drvdata;
1590fea0fe60SJeffy Chen 
1591fea0fe60SJeffy Chen 	*regmap = info->regmap_base;
1592fea0fe60SJeffy Chen 	*reg = RK3228_PULL_OFFSET;
1593fea0fe60SJeffy Chen 	*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
1594fea0fe60SJeffy Chen 	*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
1595fea0fe60SJeffy Chen 
1596fea0fe60SJeffy Chen 	*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
1597fea0fe60SJeffy Chen 	*bit *= RK3188_PULL_BITS_PER_PIN;
1598fea0fe60SJeffy Chen }
1599fea0fe60SJeffy Chen 
1600fea0fe60SJeffy Chen #define RK3228_DRV_GRF_OFFSET		0x200
1601fea0fe60SJeffy Chen 
1602fea0fe60SJeffy Chen static void rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
1603fea0fe60SJeffy Chen 				    int pin_num, struct regmap **regmap,
1604fea0fe60SJeffy Chen 				    int *reg, u8 *bit)
1605fea0fe60SJeffy Chen {
1606fea0fe60SJeffy Chen 	struct rockchip_pinctrl *info = bank->drvdata;
1607fea0fe60SJeffy Chen 
1608fea0fe60SJeffy Chen 	*regmap = info->regmap_base;
1609fea0fe60SJeffy Chen 	*reg = RK3228_DRV_GRF_OFFSET;
1610fea0fe60SJeffy Chen 	*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
1611fea0fe60SJeffy Chen 	*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
1612fea0fe60SJeffy Chen 
1613fea0fe60SJeffy Chen 	*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
1614fea0fe60SJeffy Chen 	*bit *= RK3288_DRV_BITS_PER_PIN;
1615fea0fe60SJeffy Chen }
1616fea0fe60SJeffy Chen 
1617daecdc66SHeiko Stübner #define RK3368_PULL_GRF_OFFSET		0x100
1618daecdc66SHeiko Stübner #define RK3368_PULL_PMU_OFFSET		0x10
1619daecdc66SHeiko Stübner 
1620daecdc66SHeiko Stübner static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1621daecdc66SHeiko Stübner 				    int pin_num, struct regmap **regmap,
1622daecdc66SHeiko Stübner 				    int *reg, u8 *bit)
1623daecdc66SHeiko Stübner {
1624daecdc66SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1625daecdc66SHeiko Stübner 
1626daecdc66SHeiko Stübner 	/* The first 32 pins of the first bank are located in PMU */
1627daecdc66SHeiko Stübner 	if (bank->bank_num == 0) {
1628daecdc66SHeiko Stübner 		*regmap = info->regmap_pmu;
1629daecdc66SHeiko Stübner 		*reg = RK3368_PULL_PMU_OFFSET;
1630daecdc66SHeiko Stübner 
1631daecdc66SHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
1632daecdc66SHeiko Stübner 		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
1633daecdc66SHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
1634daecdc66SHeiko Stübner 	} else {
1635daecdc66SHeiko Stübner 		*regmap = info->regmap_base;
1636daecdc66SHeiko Stübner 		*reg = RK3368_PULL_GRF_OFFSET;
1637daecdc66SHeiko Stübner 
1638daecdc66SHeiko Stübner 		/* correct the offset, as we're starting with the 2nd bank */
1639daecdc66SHeiko Stübner 		*reg -= 0x10;
1640daecdc66SHeiko Stübner 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
1641daecdc66SHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
1642daecdc66SHeiko Stübner 
1643daecdc66SHeiko Stübner 		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
1644daecdc66SHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
1645daecdc66SHeiko Stübner 	}
1646daecdc66SHeiko Stübner }
1647daecdc66SHeiko Stübner 
1648daecdc66SHeiko Stübner #define RK3368_DRV_PMU_OFFSET		0x20
1649daecdc66SHeiko Stübner #define RK3368_DRV_GRF_OFFSET		0x200
1650daecdc66SHeiko Stübner 
1651daecdc66SHeiko Stübner static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
1652daecdc66SHeiko Stübner 				    int pin_num, struct regmap **regmap,
1653daecdc66SHeiko Stübner 				    int *reg, u8 *bit)
1654daecdc66SHeiko Stübner {
1655daecdc66SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1656daecdc66SHeiko Stübner 
1657daecdc66SHeiko Stübner 	/* The first 32 pins of the first bank are located in PMU */
1658daecdc66SHeiko Stübner 	if (bank->bank_num == 0) {
1659daecdc66SHeiko Stübner 		*regmap = info->regmap_pmu;
1660daecdc66SHeiko Stübner 		*reg = RK3368_DRV_PMU_OFFSET;
1661daecdc66SHeiko Stübner 
1662daecdc66SHeiko Stübner 		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
1663daecdc66SHeiko Stübner 		*bit = pin_num % RK3288_DRV_PINS_PER_REG;
1664daecdc66SHeiko Stübner 		*bit *= RK3288_DRV_BITS_PER_PIN;
1665daecdc66SHeiko Stübner 	} else {
1666daecdc66SHeiko Stübner 		*regmap = info->regmap_base;
1667daecdc66SHeiko Stübner 		*reg = RK3368_DRV_GRF_OFFSET;
1668daecdc66SHeiko Stübner 
1669daecdc66SHeiko Stübner 		/* correct the offset, as we're starting with the 2nd bank */
1670daecdc66SHeiko Stübner 		*reg -= 0x10;
1671daecdc66SHeiko Stübner 		*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
1672daecdc66SHeiko Stübner 		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
1673daecdc66SHeiko Stübner 
1674daecdc66SHeiko Stübner 		*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
1675daecdc66SHeiko Stübner 		*bit *= RK3288_DRV_BITS_PER_PIN;
1676daecdc66SHeiko Stübner 	}
1677daecdc66SHeiko Stübner }
1678daecdc66SHeiko Stübner 
1679b6c23275SDavid Wu #define RK3399_PULL_GRF_OFFSET		0xe040
1680b6c23275SDavid Wu #define RK3399_PULL_PMU_OFFSET		0x40
1681b6c23275SDavid Wu #define RK3399_DRV_3BITS_PER_PIN	3
1682b6c23275SDavid Wu 
1683b6c23275SDavid Wu static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1684b6c23275SDavid Wu 					 int pin_num, struct regmap **regmap,
1685b6c23275SDavid Wu 					 int *reg, u8 *bit)
1686b6c23275SDavid Wu {
1687b6c23275SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
1688b6c23275SDavid Wu 
1689b6c23275SDavid Wu 	/* The bank0:16 and bank1:32 pins are located in PMU */
1690b6c23275SDavid Wu 	if ((bank->bank_num == 0) || (bank->bank_num == 1)) {
1691b6c23275SDavid Wu 		*regmap = info->regmap_pmu;
1692b6c23275SDavid Wu 		*reg = RK3399_PULL_PMU_OFFSET;
1693b6c23275SDavid Wu 
1694b6c23275SDavid Wu 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
1695b6c23275SDavid Wu 
1696b6c23275SDavid Wu 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
1697b6c23275SDavid Wu 		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
1698b6c23275SDavid Wu 		*bit *= RK3188_PULL_BITS_PER_PIN;
1699b6c23275SDavid Wu 	} else {
1700b6c23275SDavid Wu 		*regmap = info->regmap_base;
1701b6c23275SDavid Wu 		*reg = RK3399_PULL_GRF_OFFSET;
1702b6c23275SDavid Wu 
1703b6c23275SDavid Wu 		/* correct the offset, as we're starting with the 3rd bank */
1704b6c23275SDavid Wu 		*reg -= 0x20;
1705b6c23275SDavid Wu 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
1706b6c23275SDavid Wu 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
1707b6c23275SDavid Wu 
1708b6c23275SDavid Wu 		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
1709b6c23275SDavid Wu 		*bit *= RK3188_PULL_BITS_PER_PIN;
1710b6c23275SDavid Wu 	}
1711b6c23275SDavid Wu }
1712b6c23275SDavid Wu 
1713b6c23275SDavid Wu static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
1714b6c23275SDavid Wu 					int pin_num, struct regmap **regmap,
1715b6c23275SDavid Wu 					int *reg, u8 *bit)
1716b6c23275SDavid Wu {
1717b6c23275SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
1718b6c23275SDavid Wu 	int drv_num = (pin_num / 8);
1719b6c23275SDavid Wu 
1720b6c23275SDavid Wu 	/*  The bank0:16 and bank1:32 pins are located in PMU */
1721b6c23275SDavid Wu 	if ((bank->bank_num == 0) || (bank->bank_num == 1))
1722b6c23275SDavid Wu 		*regmap = info->regmap_pmu;
1723b6c23275SDavid Wu 	else
1724b6c23275SDavid Wu 		*regmap = info->regmap_base;
1725b6c23275SDavid Wu 
1726b6c23275SDavid Wu 	*reg = bank->drv[drv_num].offset;
1727b6c23275SDavid Wu 	if ((bank->drv[drv_num].drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
1728b6c23275SDavid Wu 	    (bank->drv[drv_num].drv_type == DRV_TYPE_IO_3V3_ONLY))
1729b6c23275SDavid Wu 		*bit = (pin_num % 8) * 3;
1730b6c23275SDavid Wu 	else
1731b6c23275SDavid Wu 		*bit = (pin_num % 8) * 2;
1732b6c23275SDavid Wu }
1733b6c23275SDavid Wu 
1734b6c23275SDavid Wu static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = {
1735b6c23275SDavid Wu 	{ 2, 4, 8, 12, -1, -1, -1, -1 },
1736b6c23275SDavid Wu 	{ 3, 6, 9, 12, -1, -1, -1, -1 },
1737b6c23275SDavid Wu 	{ 5, 10, 15, 20, -1, -1, -1, -1 },
1738b6c23275SDavid Wu 	{ 4, 6, 8, 10, 12, 14, 16, 18 },
1739b6c23275SDavid Wu 	{ 4, 7, 10, 13, 16, 19, 22, 26 }
1740b6c23275SDavid Wu };
1741ef17f69fSHeiko Stübner 
1742ef17f69fSHeiko Stübner static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank,
1743ef17f69fSHeiko Stübner 				     int pin_num)
1744b547c800SHeiko Stübner {
1745ef17f69fSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1746ef17f69fSHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1747b547c800SHeiko Stübner 	struct regmap *regmap;
1748b547c800SHeiko Stübner 	int reg, ret;
1749b6c23275SDavid Wu 	u32 data, temp, rmask_bits;
1750b547c800SHeiko Stübner 	u8 bit;
1751b6c23275SDavid Wu 	int drv_type = bank->drv[pin_num / 8].drv_type;
1752b547c800SHeiko Stübner 
1753ef17f69fSHeiko Stübner 	ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
1754b547c800SHeiko Stübner 
1755b6c23275SDavid Wu 	switch (drv_type) {
1756b6c23275SDavid Wu 	case DRV_TYPE_IO_1V8_3V0_AUTO:
1757b6c23275SDavid Wu 	case DRV_TYPE_IO_3V3_ONLY:
1758b6c23275SDavid Wu 		rmask_bits = RK3399_DRV_3BITS_PER_PIN;
1759b6c23275SDavid Wu 		switch (bit) {
1760b6c23275SDavid Wu 		case 0 ... 12:
1761b6c23275SDavid Wu 			/* regular case, nothing to do */
1762b6c23275SDavid Wu 			break;
1763b6c23275SDavid Wu 		case 15:
1764b6c23275SDavid Wu 			/*
1765b6c23275SDavid Wu 			 * drive-strength offset is special, as it is
1766b6c23275SDavid Wu 			 * spread over 2 registers
1767b6c23275SDavid Wu 			 */
1768b6c23275SDavid Wu 			ret = regmap_read(regmap, reg, &data);
1769b6c23275SDavid Wu 			if (ret)
1770b6c23275SDavid Wu 				return ret;
1771b6c23275SDavid Wu 
1772b6c23275SDavid Wu 			ret = regmap_read(regmap, reg + 0x4, &temp);
1773b6c23275SDavid Wu 			if (ret)
1774b6c23275SDavid Wu 				return ret;
1775b6c23275SDavid Wu 
1776b6c23275SDavid Wu 			/*
1777b6c23275SDavid Wu 			 * the bit data[15] contains bit 0 of the value
1778b6c23275SDavid Wu 			 * while temp[1:0] contains bits 2 and 1
1779b6c23275SDavid Wu 			 */
1780b6c23275SDavid Wu 			data >>= 15;
1781b6c23275SDavid Wu 			temp &= 0x3;
1782b6c23275SDavid Wu 			temp <<= 1;
1783b6c23275SDavid Wu 			data |= temp;
1784b6c23275SDavid Wu 
1785b6c23275SDavid Wu 			return rockchip_perpin_drv_list[drv_type][data];
1786b6c23275SDavid Wu 		case 18 ... 21:
1787b6c23275SDavid Wu 			/* setting fully enclosed in the second register */
1788b6c23275SDavid Wu 			reg += 4;
1789b6c23275SDavid Wu 			bit -= 16;
1790b6c23275SDavid Wu 			break;
1791b6c23275SDavid Wu 		default:
1792b6c23275SDavid Wu 			dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n",
1793b6c23275SDavid Wu 				bit, drv_type);
1794b6c23275SDavid Wu 			return -EINVAL;
1795b6c23275SDavid Wu 		}
1796b6c23275SDavid Wu 
1797b6c23275SDavid Wu 		break;
1798b6c23275SDavid Wu 	case DRV_TYPE_IO_DEFAULT:
1799b6c23275SDavid Wu 	case DRV_TYPE_IO_1V8_OR_3V0:
1800b6c23275SDavid Wu 	case DRV_TYPE_IO_1V8_ONLY:
1801b6c23275SDavid Wu 		rmask_bits = RK3288_DRV_BITS_PER_PIN;
1802b6c23275SDavid Wu 		break;
1803b6c23275SDavid Wu 	default:
1804b6c23275SDavid Wu 		dev_err(info->dev, "unsupported pinctrl drive type: %d\n",
1805b6c23275SDavid Wu 			drv_type);
1806b6c23275SDavid Wu 		return -EINVAL;
1807b6c23275SDavid Wu 	}
1808b6c23275SDavid Wu 
1809b547c800SHeiko Stübner 	ret = regmap_read(regmap, reg, &data);
1810b547c800SHeiko Stübner 	if (ret)
1811b547c800SHeiko Stübner 		return ret;
1812b547c800SHeiko Stübner 
1813b547c800SHeiko Stübner 	data >>= bit;
1814b6c23275SDavid Wu 	data &= (1 << rmask_bits) - 1;
1815b547c800SHeiko Stübner 
1816b6c23275SDavid Wu 	return rockchip_perpin_drv_list[drv_type][data];
1817b547c800SHeiko Stübner }
1818b547c800SHeiko Stübner 
1819ef17f69fSHeiko Stübner static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
1820ef17f69fSHeiko Stübner 				     int pin_num, int strength)
1821b547c800SHeiko Stübner {
1822b547c800SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1823ef17f69fSHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1824b547c800SHeiko Stübner 	struct regmap *regmap;
1825b547c800SHeiko Stübner 	int reg, ret, i;
1826b6c23275SDavid Wu 	u32 data, rmask, rmask_bits, temp;
1827b547c800SHeiko Stübner 	u8 bit;
1828b6c23275SDavid Wu 	int drv_type = bank->drv[pin_num / 8].drv_type;
1829b6c23275SDavid Wu 
1830b6c23275SDavid Wu 	dev_dbg(info->dev, "setting drive of GPIO%d-%d to %d\n",
1831b6c23275SDavid Wu 		bank->bank_num, pin_num, strength);
1832b547c800SHeiko Stübner 
1833ef17f69fSHeiko Stübner 	ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
1834b547c800SHeiko Stübner 
1835b547c800SHeiko Stübner 	ret = -EINVAL;
1836b6c23275SDavid Wu 	for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[drv_type]); i++) {
1837b6c23275SDavid Wu 		if (rockchip_perpin_drv_list[drv_type][i] == strength) {
1838b547c800SHeiko Stübner 			ret = i;
1839b547c800SHeiko Stübner 			break;
1840b6c23275SDavid Wu 		} else if (rockchip_perpin_drv_list[drv_type][i] < 0) {
1841b6c23275SDavid Wu 			ret = rockchip_perpin_drv_list[drv_type][i];
1842b6c23275SDavid Wu 			break;
1843b547c800SHeiko Stübner 		}
1844b547c800SHeiko Stübner 	}
1845b547c800SHeiko Stübner 
1846b547c800SHeiko Stübner 	if (ret < 0) {
1847b547c800SHeiko Stübner 		dev_err(info->dev, "unsupported driver strength %d\n",
1848b547c800SHeiko Stübner 			strength);
1849b547c800SHeiko Stübner 		return ret;
1850b547c800SHeiko Stübner 	}
1851b547c800SHeiko Stübner 
1852b6c23275SDavid Wu 	switch (drv_type) {
1853b6c23275SDavid Wu 	case DRV_TYPE_IO_1V8_3V0_AUTO:
1854b6c23275SDavid Wu 	case DRV_TYPE_IO_3V3_ONLY:
1855b6c23275SDavid Wu 		rmask_bits = RK3399_DRV_3BITS_PER_PIN;
1856b6c23275SDavid Wu 		switch (bit) {
1857b6c23275SDavid Wu 		case 0 ... 12:
1858b6c23275SDavid Wu 			/* regular case, nothing to do */
1859b6c23275SDavid Wu 			break;
1860b6c23275SDavid Wu 		case 15:
1861b6c23275SDavid Wu 			/*
1862b6c23275SDavid Wu 			 * drive-strength offset is special, as it is spread
1863b6c23275SDavid Wu 			 * over 2 registers, the bit data[15] contains bit 0
1864b6c23275SDavid Wu 			 * of the value while temp[1:0] contains bits 2 and 1
1865b6c23275SDavid Wu 			 */
1866b6c23275SDavid Wu 			data = (ret & 0x1) << 15;
1867b6c23275SDavid Wu 			temp = (ret >> 0x1) & 0x3;
1868b6c23275SDavid Wu 
1869b6c23275SDavid Wu 			rmask = BIT(15) | BIT(31);
1870b6c23275SDavid Wu 			data |= BIT(31);
1871b6c23275SDavid Wu 			ret = regmap_update_bits(regmap, reg, rmask, data);
1872f07bedc3SJohn Keeping 			if (ret)
1873b6c23275SDavid Wu 				return ret;
1874b6c23275SDavid Wu 
1875b6c23275SDavid Wu 			rmask = 0x3 | (0x3 << 16);
1876b6c23275SDavid Wu 			temp |= (0x3 << 16);
1877b6c23275SDavid Wu 			reg += 0x4;
1878b6c23275SDavid Wu 			ret = regmap_update_bits(regmap, reg, rmask, temp);
1879b6c23275SDavid Wu 
1880b6c23275SDavid Wu 			return ret;
1881b6c23275SDavid Wu 		case 18 ... 21:
1882b6c23275SDavid Wu 			/* setting fully enclosed in the second register */
1883b6c23275SDavid Wu 			reg += 4;
1884b6c23275SDavid Wu 			bit -= 16;
1885b6c23275SDavid Wu 			break;
1886b6c23275SDavid Wu 		default:
1887b6c23275SDavid Wu 			dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n",
1888b6c23275SDavid Wu 				bit, drv_type);
1889b6c23275SDavid Wu 			return -EINVAL;
1890b6c23275SDavid Wu 		}
1891b6c23275SDavid Wu 		break;
1892b6c23275SDavid Wu 	case DRV_TYPE_IO_DEFAULT:
1893b6c23275SDavid Wu 	case DRV_TYPE_IO_1V8_OR_3V0:
1894b6c23275SDavid Wu 	case DRV_TYPE_IO_1V8_ONLY:
1895b6c23275SDavid Wu 		rmask_bits = RK3288_DRV_BITS_PER_PIN;
1896b6c23275SDavid Wu 		break;
1897b6c23275SDavid Wu 	default:
1898b6c23275SDavid Wu 		dev_err(info->dev, "unsupported pinctrl drive type: %d\n",
1899b6c23275SDavid Wu 			drv_type);
1900b6c23275SDavid Wu 		return -EINVAL;
1901b6c23275SDavid Wu 	}
1902b6c23275SDavid Wu 
1903b547c800SHeiko Stübner 	/* enable the write to the equivalent lower bits */
1904b6c23275SDavid Wu 	data = ((1 << rmask_bits) - 1) << (bit + 16);
190599e872d9SSonny Rao 	rmask = data | (data >> 16);
1906b547c800SHeiko Stübner 	data |= (ret << bit);
1907b547c800SHeiko Stübner 
190899e872d9SSonny Rao 	ret = regmap_update_bits(regmap, reg, rmask, data);
1909b547c800SHeiko Stübner 
1910b547c800SHeiko Stübner 	return ret;
1911b547c800SHeiko Stübner }
1912b547c800SHeiko Stübner 
19133ba6767aSDavid Wu static int rockchip_pull_list[PULL_TYPE_MAX][4] = {
19143ba6767aSDavid Wu 	{
19153ba6767aSDavid Wu 		PIN_CONFIG_BIAS_DISABLE,
19163ba6767aSDavid Wu 		PIN_CONFIG_BIAS_PULL_UP,
19173ba6767aSDavid Wu 		PIN_CONFIG_BIAS_PULL_DOWN,
19183ba6767aSDavid Wu 		PIN_CONFIG_BIAS_BUS_HOLD
19193ba6767aSDavid Wu 	},
19203ba6767aSDavid Wu 	{
19213ba6767aSDavid Wu 		PIN_CONFIG_BIAS_DISABLE,
19223ba6767aSDavid Wu 		PIN_CONFIG_BIAS_PULL_DOWN,
19233ba6767aSDavid Wu 		PIN_CONFIG_BIAS_DISABLE,
19243ba6767aSDavid Wu 		PIN_CONFIG_BIAS_PULL_UP
19253ba6767aSDavid Wu 	},
19263ba6767aSDavid Wu };
19273ba6767aSDavid Wu 
1928d3e51161SHeiko Stübner static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
1929d3e51161SHeiko Stübner {
1930d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1931d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1932751a99abSHeiko Stübner 	struct regmap *regmap;
19333ba6767aSDavid Wu 	int reg, ret, pull_type;
1934d3e51161SHeiko Stübner 	u8 bit;
19356ca5274dSHeiko Stübner 	u32 data;
1936d3e51161SHeiko Stübner 
1937d3e51161SHeiko Stübner 	/* rk3066b does support any pulls */
1938a282926dSHeiko Stübner 	if (ctrl->type == RK3066B)
1939d3e51161SHeiko Stübner 		return PIN_CONFIG_BIAS_DISABLE;
1940d3e51161SHeiko Stübner 
1941751a99abSHeiko Stübner 	ctrl->pull_calc_reg(bank, pin_num, &regmap, &reg, &bit);
1942751a99abSHeiko Stübner 
1943751a99abSHeiko Stübner 	ret = regmap_read(regmap, reg, &data);
1944751a99abSHeiko Stübner 	if (ret)
1945751a99abSHeiko Stübner 		return ret;
19466ca5274dSHeiko Stübner 
1947a282926dSHeiko Stübner 	switch (ctrl->type) {
1948a282926dSHeiko Stübner 	case RK2928:
1949d23c66dfSDavid Wu 	case RK3128:
1950751a99abSHeiko Stübner 		return !(data & BIT(bit))
1951d3e51161SHeiko Stübner 				? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
1952d3e51161SHeiko Stübner 				: PIN_CONFIG_BIAS_DISABLE;
195387065ca9SDavid Wu 	case PX30:
1954b9c6dcabSAndy Yan 	case RV1108:
1955a282926dSHeiko Stübner 	case RK3188:
195666d750e1SHeiko Stübner 	case RK3288:
1957daecdc66SHeiko Stübner 	case RK3368:
1958b6c23275SDavid Wu 	case RK3399:
19593ba6767aSDavid Wu 		pull_type = bank->pull_type[pin_num / 8];
1960751a99abSHeiko Stübner 		data >>= bit;
19616ca5274dSHeiko Stübner 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
19626ca5274dSHeiko Stübner 
19633ba6767aSDavid Wu 		return rockchip_pull_list[pull_type][data];
1964a282926dSHeiko Stübner 	default:
1965a282926dSHeiko Stübner 		dev_err(info->dev, "unsupported pinctrl type\n");
1966a282926dSHeiko Stübner 		return -EINVAL;
1967a282926dSHeiko Stübner 	};
1968d3e51161SHeiko Stübner }
1969d3e51161SHeiko Stübner 
1970d3e51161SHeiko Stübner static int rockchip_set_pull(struct rockchip_pin_bank *bank,
1971d3e51161SHeiko Stübner 					int pin_num, int pull)
1972d3e51161SHeiko Stübner {
1973d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
1974d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1975751a99abSHeiko Stübner 	struct regmap *regmap;
19763ba6767aSDavid Wu 	int reg, ret, i, pull_type;
1977d3e51161SHeiko Stübner 	u8 bit;
197899e872d9SSonny Rao 	u32 data, rmask;
1979d3e51161SHeiko Stübner 
1980d3e51161SHeiko Stübner 	dev_dbg(info->dev, "setting pull of GPIO%d-%d to %d\n",
1981d3e51161SHeiko Stübner 		 bank->bank_num, pin_num, pull);
1982d3e51161SHeiko Stübner 
1983d3e51161SHeiko Stübner 	/* rk3066b does support any pulls */
1984a282926dSHeiko Stübner 	if (ctrl->type == RK3066B)
1985d3e51161SHeiko Stübner 		return pull ? -EINVAL : 0;
1986d3e51161SHeiko Stübner 
1987751a99abSHeiko Stübner 	ctrl->pull_calc_reg(bank, pin_num, &regmap, &reg, &bit);
1988d3e51161SHeiko Stübner 
19896ca5274dSHeiko Stübner 	switch (ctrl->type) {
19906ca5274dSHeiko Stübner 	case RK2928:
1991d23c66dfSDavid Wu 	case RK3128:
1992d3e51161SHeiko Stübner 		data = BIT(bit + 16);
1993d3e51161SHeiko Stübner 		if (pull == PIN_CONFIG_BIAS_DISABLE)
1994d3e51161SHeiko Stübner 			data |= BIT(bit);
1995751a99abSHeiko Stübner 		ret = regmap_write(regmap, reg, data);
1996a282926dSHeiko Stübner 		break;
199787065ca9SDavid Wu 	case PX30:
1998b9c6dcabSAndy Yan 	case RV1108:
1999a282926dSHeiko Stübner 	case RK3188:
200066d750e1SHeiko Stübner 	case RK3288:
2001daecdc66SHeiko Stübner 	case RK3368:
2002b6c23275SDavid Wu 	case RK3399:
20033ba6767aSDavid Wu 		pull_type = bank->pull_type[pin_num / 8];
20043ba6767aSDavid Wu 		ret = -EINVAL;
20053ba6767aSDavid Wu 		for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]);
20063ba6767aSDavid Wu 			i++) {
20073ba6767aSDavid Wu 			if (rockchip_pull_list[pull_type][i] == pull) {
20083ba6767aSDavid Wu 				ret = i;
20093ba6767aSDavid Wu 				break;
20103ba6767aSDavid Wu 			}
20113ba6767aSDavid Wu 		}
20123ba6767aSDavid Wu 
20133ba6767aSDavid Wu 		if (ret < 0) {
20143ba6767aSDavid Wu 			dev_err(info->dev, "unsupported pull setting %d\n",
20153ba6767aSDavid Wu 				pull);
20163ba6767aSDavid Wu 			return ret;
20173ba6767aSDavid Wu 		}
20183ba6767aSDavid Wu 
20196ca5274dSHeiko Stübner 		/* enable the write to the equivalent lower bits */
20206ca5274dSHeiko Stübner 		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
202199e872d9SSonny Rao 		rmask = data | (data >> 16);
20223ba6767aSDavid Wu 		data |= (ret << bit);
20236ca5274dSHeiko Stübner 
202499e872d9SSonny Rao 		ret = regmap_update_bits(regmap, reg, rmask, data);
20256ca5274dSHeiko Stübner 		break;
2026a282926dSHeiko Stübner 	default:
2027a282926dSHeiko Stübner 		dev_err(info->dev, "unsupported pinctrl type\n");
2028a282926dSHeiko Stübner 		return -EINVAL;
2029d3e51161SHeiko Stübner 	}
2030d3e51161SHeiko Stübner 
2031751a99abSHeiko Stübner 	return ret;
2032d3e51161SHeiko Stübner }
2033d3e51161SHeiko Stübner 
2034728d3f5aSdavid.wu #define RK3328_SCHMITT_BITS_PER_PIN		1
2035728d3f5aSdavid.wu #define RK3328_SCHMITT_PINS_PER_REG		16
2036728d3f5aSdavid.wu #define RK3328_SCHMITT_BANK_STRIDE		8
2037728d3f5aSdavid.wu #define RK3328_SCHMITT_GRF_OFFSET		0x380
2038728d3f5aSdavid.wu 
2039728d3f5aSdavid.wu static int rk3328_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
2040728d3f5aSdavid.wu 					   int pin_num,
2041728d3f5aSdavid.wu 					   struct regmap **regmap,
2042728d3f5aSdavid.wu 					   int *reg, u8 *bit)
2043728d3f5aSdavid.wu {
2044728d3f5aSdavid.wu 	struct rockchip_pinctrl *info = bank->drvdata;
2045728d3f5aSdavid.wu 
2046728d3f5aSdavid.wu 	*regmap = info->regmap_base;
2047728d3f5aSdavid.wu 	*reg = RK3328_SCHMITT_GRF_OFFSET;
2048728d3f5aSdavid.wu 
2049728d3f5aSdavid.wu 	*reg += bank->bank_num * RK3328_SCHMITT_BANK_STRIDE;
2050728d3f5aSdavid.wu 	*reg += ((pin_num / RK3328_SCHMITT_PINS_PER_REG) * 4);
2051728d3f5aSdavid.wu 	*bit = pin_num % RK3328_SCHMITT_PINS_PER_REG;
2052728d3f5aSdavid.wu 
2053728d3f5aSdavid.wu 	return 0;
2054728d3f5aSdavid.wu }
2055728d3f5aSdavid.wu 
2056e3b357d7Sdavid.wu static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)
2057e3b357d7Sdavid.wu {
2058e3b357d7Sdavid.wu 	struct rockchip_pinctrl *info = bank->drvdata;
2059e3b357d7Sdavid.wu 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
2060e3b357d7Sdavid.wu 	struct regmap *regmap;
2061e3b357d7Sdavid.wu 	int reg, ret;
2062e3b357d7Sdavid.wu 	u8 bit;
2063e3b357d7Sdavid.wu 	u32 data;
2064e3b357d7Sdavid.wu 
2065e3b357d7Sdavid.wu 	ret = ctrl->schmitt_calc_reg(bank, pin_num, &regmap, &reg, &bit);
2066e3b357d7Sdavid.wu 	if (ret)
2067e3b357d7Sdavid.wu 		return ret;
2068e3b357d7Sdavid.wu 
2069e3b357d7Sdavid.wu 	ret = regmap_read(regmap, reg, &data);
2070e3b357d7Sdavid.wu 	if (ret)
2071e3b357d7Sdavid.wu 		return ret;
2072e3b357d7Sdavid.wu 
2073e3b357d7Sdavid.wu 	data >>= bit;
2074e3b357d7Sdavid.wu 	return data & 0x1;
2075e3b357d7Sdavid.wu }
2076e3b357d7Sdavid.wu 
2077e3b357d7Sdavid.wu static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
2078e3b357d7Sdavid.wu 				int pin_num, int enable)
2079e3b357d7Sdavid.wu {
2080e3b357d7Sdavid.wu 	struct rockchip_pinctrl *info = bank->drvdata;
2081e3b357d7Sdavid.wu 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
2082e3b357d7Sdavid.wu 	struct regmap *regmap;
2083e3b357d7Sdavid.wu 	int reg, ret;
2084e3b357d7Sdavid.wu 	u8 bit;
2085e3b357d7Sdavid.wu 	u32 data, rmask;
2086e3b357d7Sdavid.wu 
2087e3b357d7Sdavid.wu 	dev_dbg(info->dev, "setting input schmitt of GPIO%d-%d to %d\n",
2088e3b357d7Sdavid.wu 		bank->bank_num, pin_num, enable);
2089e3b357d7Sdavid.wu 
2090e3b357d7Sdavid.wu 	ret = ctrl->schmitt_calc_reg(bank, pin_num, &regmap, &reg, &bit);
2091e3b357d7Sdavid.wu 	if (ret)
2092e3b357d7Sdavid.wu 		return ret;
2093e3b357d7Sdavid.wu 
2094e3b357d7Sdavid.wu 	/* enable the write to the equivalent lower bits */
2095e3b357d7Sdavid.wu 	data = BIT(bit + 16) | (enable << bit);
2096e3b357d7Sdavid.wu 	rmask = BIT(bit + 16) | BIT(bit);
2097e3b357d7Sdavid.wu 
2098f07bedc3SJohn Keeping 	return regmap_update_bits(regmap, reg, rmask, data);
2099e3b357d7Sdavid.wu }
2100e3b357d7Sdavid.wu 
2101d3e51161SHeiko Stübner /*
2102d3e51161SHeiko Stübner  * Pinmux_ops handling
2103d3e51161SHeiko Stübner  */
2104d3e51161SHeiko Stübner 
2105d3e51161SHeiko Stübner static int rockchip_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
2106d3e51161SHeiko Stübner {
2107d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
2108d3e51161SHeiko Stübner 
2109d3e51161SHeiko Stübner 	return info->nfunctions;
2110d3e51161SHeiko Stübner }
2111d3e51161SHeiko Stübner 
2112d3e51161SHeiko Stübner static const char *rockchip_pmx_get_func_name(struct pinctrl_dev *pctldev,
2113d3e51161SHeiko Stübner 					  unsigned selector)
2114d3e51161SHeiko Stübner {
2115d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
2116d3e51161SHeiko Stübner 
2117d3e51161SHeiko Stübner 	return info->functions[selector].name;
2118d3e51161SHeiko Stübner }
2119d3e51161SHeiko Stübner 
2120d3e51161SHeiko Stübner static int rockchip_pmx_get_groups(struct pinctrl_dev *pctldev,
2121d3e51161SHeiko Stübner 				unsigned selector, const char * const **groups,
2122d3e51161SHeiko Stübner 				unsigned * const num_groups)
2123d3e51161SHeiko Stübner {
2124d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
2125d3e51161SHeiko Stübner 
2126d3e51161SHeiko Stübner 	*groups = info->functions[selector].groups;
2127d3e51161SHeiko Stübner 	*num_groups = info->functions[selector].ngroups;
2128d3e51161SHeiko Stübner 
2129d3e51161SHeiko Stübner 	return 0;
2130d3e51161SHeiko Stübner }
2131d3e51161SHeiko Stübner 
213203e9f0caSLinus Walleij static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
2133d3e51161SHeiko Stübner 			    unsigned group)
2134d3e51161SHeiko Stübner {
2135d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
2136d3e51161SHeiko Stübner 	const unsigned int *pins = info->groups[group].pins;
2137d3e51161SHeiko Stübner 	const struct rockchip_pin_config *data = info->groups[group].data;
2138d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
213914797189SHeiko Stübner 	int cnt, ret = 0;
2140d3e51161SHeiko Stübner 
2141d3e51161SHeiko Stübner 	dev_dbg(info->dev, "enable function %s group %s\n",
2142d3e51161SHeiko Stübner 		info->functions[selector].name, info->groups[group].name);
2143d3e51161SHeiko Stübner 
2144d3e51161SHeiko Stübner 	/*
214585dc397aSMarkus Elfring 	 * for each pin in the pin group selected, program the corresponding
2146d3e51161SHeiko Stübner 	 * pin function number in the config register.
2147d3e51161SHeiko Stübner 	 */
2148d3e51161SHeiko Stübner 	for (cnt = 0; cnt < info->groups[group].npins; cnt++) {
2149d3e51161SHeiko Stübner 		bank = pin_to_bank(info, pins[cnt]);
215014797189SHeiko Stübner 		ret = rockchip_set_mux(bank, pins[cnt] - bank->pin_base,
2151d3e51161SHeiko Stübner 				       data[cnt].func);
215214797189SHeiko Stübner 		if (ret)
215314797189SHeiko Stübner 			break;
215414797189SHeiko Stübner 	}
215514797189SHeiko Stübner 
215614797189SHeiko Stübner 	if (ret) {
215714797189SHeiko Stübner 		/* revert the already done pin settings */
215814797189SHeiko Stübner 		for (cnt--; cnt >= 0; cnt--)
215914797189SHeiko Stübner 			rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0);
216014797189SHeiko Stübner 
216114797189SHeiko Stübner 		return ret;
2162d3e51161SHeiko Stübner 	}
2163d3e51161SHeiko Stübner 
2164d3e51161SHeiko Stübner 	return 0;
2165d3e51161SHeiko Stübner }
2166d3e51161SHeiko Stübner 
21676ba20a00SCaesar Wang static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
21686ba20a00SCaesar Wang {
21696ba20a00SCaesar Wang 	struct rockchip_pin_bank *bank = gpiochip_get_data(chip);
21706ba20a00SCaesar Wang 	u32 data;
21715c9d8c4fSBrian Norris 	int ret;
21726ba20a00SCaesar Wang 
21735c9d8c4fSBrian Norris 	ret = clk_enable(bank->clk);
21745c9d8c4fSBrian Norris 	if (ret < 0) {
21755c9d8c4fSBrian Norris 		dev_err(bank->drvdata->dev,
21765c9d8c4fSBrian Norris 			"failed to enable clock for bank %s\n", bank->name);
21775c9d8c4fSBrian Norris 		return ret;
21785c9d8c4fSBrian Norris 	}
21796ba20a00SCaesar Wang 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
21805c9d8c4fSBrian Norris 	clk_disable(bank->clk);
21816ba20a00SCaesar Wang 
21826ba20a00SCaesar Wang 	return !(data & BIT(offset));
21836ba20a00SCaesar Wang }
21846ba20a00SCaesar Wang 
2185d3e51161SHeiko Stübner /*
2186d3e51161SHeiko Stübner  * The calls to gpio_direction_output() and gpio_direction_input()
2187d3e51161SHeiko Stübner  * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
2188d3e51161SHeiko Stübner  * function called from the gpiolib interface).
2189d3e51161SHeiko Stübner  */
2190e5c2c9dbSDoug Anderson static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
2191e5c2c9dbSDoug Anderson 					    int pin, bool input)
2192d3e51161SHeiko Stübner {
2193d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
2194e5c2c9dbSDoug Anderson 	int ret;
2195fab262f5SDoug Anderson 	unsigned long flags;
2196d3e51161SHeiko Stübner 	u32 data;
2197d3e51161SHeiko Stübner 
219803bf81f1SLinus Walleij 	bank = gpiochip_get_data(chip);
2199d3e51161SHeiko Stübner 
220014797189SHeiko Stübner 	ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
220114797189SHeiko Stübner 	if (ret < 0)
220214797189SHeiko Stübner 		return ret;
2203d3e51161SHeiko Stübner 
220407a06ae9SLin Huang 	clk_enable(bank->clk);
220570b7aa7aSJohn Keeping 	raw_spin_lock_irqsave(&bank->slock, flags);
2206fab262f5SDoug Anderson 
2207d3e51161SHeiko Stübner 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
2208d3e51161SHeiko Stübner 	/* set bit to 1 for output, 0 for input */
2209d3e51161SHeiko Stübner 	if (!input)
2210d3e51161SHeiko Stübner 		data |= BIT(pin);
2211d3e51161SHeiko Stübner 	else
2212d3e51161SHeiko Stübner 		data &= ~BIT(pin);
2213d3e51161SHeiko Stübner 	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
2214d3e51161SHeiko Stübner 
221570b7aa7aSJohn Keeping 	raw_spin_unlock_irqrestore(&bank->slock, flags);
221607a06ae9SLin Huang 	clk_disable(bank->clk);
2217fab262f5SDoug Anderson 
2218d3e51161SHeiko Stübner 	return 0;
2219d3e51161SHeiko Stübner }
2220d3e51161SHeiko Stübner 
2221e5c2c9dbSDoug Anderson static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
2222e5c2c9dbSDoug Anderson 					      struct pinctrl_gpio_range *range,
2223e5c2c9dbSDoug Anderson 					      unsigned offset, bool input)
2224e5c2c9dbSDoug Anderson {
2225e5c2c9dbSDoug Anderson 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
2226e5c2c9dbSDoug Anderson 	struct gpio_chip *chip;
2227e5c2c9dbSDoug Anderson 	int pin;
2228e5c2c9dbSDoug Anderson 
2229e5c2c9dbSDoug Anderson 	chip = range->gc;
2230e5c2c9dbSDoug Anderson 	pin = offset - chip->base;
2231e5c2c9dbSDoug Anderson 	dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n",
2232e5c2c9dbSDoug Anderson 		 offset, range->name, pin, input ? "input" : "output");
2233e5c2c9dbSDoug Anderson 
2234e5c2c9dbSDoug Anderson 	return _rockchip_pmx_gpio_set_direction(chip, offset - chip->base,
2235e5c2c9dbSDoug Anderson 						input);
2236e5c2c9dbSDoug Anderson }
2237e5c2c9dbSDoug Anderson 
2238d3e51161SHeiko Stübner static const struct pinmux_ops rockchip_pmx_ops = {
2239d3e51161SHeiko Stübner 	.get_functions_count	= rockchip_pmx_get_funcs_count,
2240d3e51161SHeiko Stübner 	.get_function_name	= rockchip_pmx_get_func_name,
2241d3e51161SHeiko Stübner 	.get_function_groups	= rockchip_pmx_get_groups,
224203e9f0caSLinus Walleij 	.set_mux		= rockchip_pmx_set,
2243d3e51161SHeiko Stübner 	.gpio_set_direction	= rockchip_pmx_gpio_set_direction,
2244d3e51161SHeiko Stübner };
2245d3e51161SHeiko Stübner 
2246d3e51161SHeiko Stübner /*
2247d3e51161SHeiko Stübner  * Pinconf_ops handling
2248d3e51161SHeiko Stübner  */
2249d3e51161SHeiko Stübner 
225044b6d930SHeiko Stübner static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
225144b6d930SHeiko Stübner 					enum pin_config_param pull)
225244b6d930SHeiko Stübner {
2253a282926dSHeiko Stübner 	switch (ctrl->type) {
2254a282926dSHeiko Stübner 	case RK2928:
2255d23c66dfSDavid Wu 	case RK3128:
2256a282926dSHeiko Stübner 		return (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT ||
2257a282926dSHeiko Stübner 					pull == PIN_CONFIG_BIAS_DISABLE);
2258a282926dSHeiko Stübner 	case RK3066B:
225944b6d930SHeiko Stübner 		return pull ? false : true;
226087065ca9SDavid Wu 	case PX30:
2261b9c6dcabSAndy Yan 	case RV1108:
2262a282926dSHeiko Stübner 	case RK3188:
226366d750e1SHeiko Stübner 	case RK3288:
2264daecdc66SHeiko Stübner 	case RK3368:
2265b6c23275SDavid Wu 	case RK3399:
2266a282926dSHeiko Stübner 		return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
226744b6d930SHeiko Stübner 	}
226844b6d930SHeiko Stübner 
2269a282926dSHeiko Stübner 	return false;
227044b6d930SHeiko Stübner }
227144b6d930SHeiko Stübner 
2272e5c2c9dbSDoug Anderson static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value);
2273a076e2edSHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset);
2274a076e2edSHeiko Stübner 
2275d3e51161SHeiko Stübner /* set the pin config settings for a specified pin */
2276d3e51161SHeiko Stübner static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
227703b054e9SSherman Yin 				unsigned long *configs, unsigned num_configs)
2278d3e51161SHeiko Stübner {
2279d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
2280d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = pin_to_bank(info, pin);
228103b054e9SSherman Yin 	enum pin_config_param param;
228258957d2eSMika Westerberg 	u32 arg;
228303b054e9SSherman Yin 	int i;
228403b054e9SSherman Yin 	int rc;
228503b054e9SSherman Yin 
228603b054e9SSherman Yin 	for (i = 0; i < num_configs; i++) {
228703b054e9SSherman Yin 		param = pinconf_to_config_param(configs[i]);
228803b054e9SSherman Yin 		arg = pinconf_to_config_argument(configs[i]);
2289d3e51161SHeiko Stübner 
2290d3e51161SHeiko Stübner 		switch (param) {
2291d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_DISABLE:
229203b054e9SSherman Yin 			rc =  rockchip_set_pull(bank, pin - bank->pin_base,
229303b054e9SSherman Yin 				param);
229403b054e9SSherman Yin 			if (rc)
229503b054e9SSherman Yin 				return rc;
229644b6d930SHeiko Stübner 			break;
2297d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_UP:
2298d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_DOWN:
2299d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
23006ca5274dSHeiko Stübner 		case PIN_CONFIG_BIAS_BUS_HOLD:
230144b6d930SHeiko Stübner 			if (!rockchip_pinconf_pull_valid(info->ctrl, param))
230244b6d930SHeiko Stübner 				return -ENOTSUPP;
230344b6d930SHeiko Stübner 
230444b6d930SHeiko Stübner 			if (!arg)
230544b6d930SHeiko Stübner 				return -EINVAL;
230644b6d930SHeiko Stübner 
230703b054e9SSherman Yin 			rc = rockchip_set_pull(bank, pin - bank->pin_base,
230803b054e9SSherman Yin 				param);
230903b054e9SSherman Yin 			if (rc)
231003b054e9SSherman Yin 				return rc;
2311d3e51161SHeiko Stübner 			break;
2312a076e2edSHeiko Stübner 		case PIN_CONFIG_OUTPUT:
2313e5c2c9dbSDoug Anderson 			rockchip_gpio_set(&bank->gpio_chip,
2314e5c2c9dbSDoug Anderson 					  pin - bank->pin_base, arg);
2315e5c2c9dbSDoug Anderson 			rc = _rockchip_pmx_gpio_set_direction(&bank->gpio_chip,
2316e5c2c9dbSDoug Anderson 					  pin - bank->pin_base, false);
2317a076e2edSHeiko Stübner 			if (rc)
2318a076e2edSHeiko Stübner 				return rc;
2319a076e2edSHeiko Stübner 			break;
2320b547c800SHeiko Stübner 		case PIN_CONFIG_DRIVE_STRENGTH:
2321b547c800SHeiko Stübner 			/* rk3288 is the first with per-pin drive-strength */
2322ef17f69fSHeiko Stübner 			if (!info->ctrl->drv_calc_reg)
2323b547c800SHeiko Stübner 				return -ENOTSUPP;
2324b547c800SHeiko Stübner 
2325ef17f69fSHeiko Stübner 			rc = rockchip_set_drive_perpin(bank,
2326ef17f69fSHeiko Stübner 						pin - bank->pin_base, arg);
2327b547c800SHeiko Stübner 			if (rc < 0)
2328b547c800SHeiko Stübner 				return rc;
2329b547c800SHeiko Stübner 			break;
2330e3b357d7Sdavid.wu 		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
2331e3b357d7Sdavid.wu 			if (!info->ctrl->schmitt_calc_reg)
2332e3b357d7Sdavid.wu 				return -ENOTSUPP;
2333e3b357d7Sdavid.wu 
2334e3b357d7Sdavid.wu 			rc = rockchip_set_schmitt(bank,
2335e3b357d7Sdavid.wu 						  pin - bank->pin_base, arg);
2336e3b357d7Sdavid.wu 			if (rc < 0)
2337e3b357d7Sdavid.wu 				return rc;
2338e3b357d7Sdavid.wu 			break;
2339d3e51161SHeiko Stübner 		default:
2340d3e51161SHeiko Stübner 			return -ENOTSUPP;
2341d3e51161SHeiko Stübner 			break;
2342d3e51161SHeiko Stübner 		}
234303b054e9SSherman Yin 	} /* for each config */
2344d3e51161SHeiko Stübner 
2345d3e51161SHeiko Stübner 	return 0;
2346d3e51161SHeiko Stübner }
2347d3e51161SHeiko Stübner 
2348d3e51161SHeiko Stübner /* get the pin config settings for a specified pin */
2349d3e51161SHeiko Stübner static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
2350d3e51161SHeiko Stübner 							unsigned long *config)
2351d3e51161SHeiko Stübner {
2352d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
2353d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = pin_to_bank(info, pin);
2354d3e51161SHeiko Stübner 	enum pin_config_param param = pinconf_to_config_param(*config);
2355dab3eba7SHeiko Stübner 	u16 arg;
2356a076e2edSHeiko Stübner 	int rc;
2357d3e51161SHeiko Stübner 
2358d3e51161SHeiko Stübner 	switch (param) {
2359d3e51161SHeiko Stübner 	case PIN_CONFIG_BIAS_DISABLE:
236044b6d930SHeiko Stübner 		if (rockchip_get_pull(bank, pin - bank->pin_base) != param)
2361d3e51161SHeiko Stübner 			return -EINVAL;
2362d3e51161SHeiko Stübner 
2363dab3eba7SHeiko Stübner 		arg = 0;
2364d3e51161SHeiko Stübner 		break;
236544b6d930SHeiko Stübner 	case PIN_CONFIG_BIAS_PULL_UP:
236644b6d930SHeiko Stübner 	case PIN_CONFIG_BIAS_PULL_DOWN:
236744b6d930SHeiko Stübner 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
23686ca5274dSHeiko Stübner 	case PIN_CONFIG_BIAS_BUS_HOLD:
236944b6d930SHeiko Stübner 		if (!rockchip_pinconf_pull_valid(info->ctrl, param))
237044b6d930SHeiko Stübner 			return -ENOTSUPP;
237144b6d930SHeiko Stübner 
237244b6d930SHeiko Stübner 		if (rockchip_get_pull(bank, pin - bank->pin_base) != param)
237344b6d930SHeiko Stübner 			return -EINVAL;
237444b6d930SHeiko Stübner 
2375dab3eba7SHeiko Stübner 		arg = 1;
237644b6d930SHeiko Stübner 		break;
2377a076e2edSHeiko Stübner 	case PIN_CONFIG_OUTPUT:
2378a076e2edSHeiko Stübner 		rc = rockchip_get_mux(bank, pin - bank->pin_base);
2379a076e2edSHeiko Stübner 		if (rc != RK_FUNC_GPIO)
2380a076e2edSHeiko Stübner 			return -EINVAL;
2381a076e2edSHeiko Stübner 
2382a076e2edSHeiko Stübner 		rc = rockchip_gpio_get(&bank->gpio_chip, pin - bank->pin_base);
2383a076e2edSHeiko Stübner 		if (rc < 0)
2384a076e2edSHeiko Stübner 			return rc;
2385a076e2edSHeiko Stübner 
2386a076e2edSHeiko Stübner 		arg = rc ? 1 : 0;
2387a076e2edSHeiko Stübner 		break;
2388b547c800SHeiko Stübner 	case PIN_CONFIG_DRIVE_STRENGTH:
2389b547c800SHeiko Stübner 		/* rk3288 is the first with per-pin drive-strength */
2390ef17f69fSHeiko Stübner 		if (!info->ctrl->drv_calc_reg)
2391b547c800SHeiko Stübner 			return -ENOTSUPP;
2392b547c800SHeiko Stübner 
2393ef17f69fSHeiko Stübner 		rc = rockchip_get_drive_perpin(bank, pin - bank->pin_base);
2394b547c800SHeiko Stübner 		if (rc < 0)
2395b547c800SHeiko Stübner 			return rc;
2396b547c800SHeiko Stübner 
2397b547c800SHeiko Stübner 		arg = rc;
2398b547c800SHeiko Stübner 		break;
2399e3b357d7Sdavid.wu 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
2400e3b357d7Sdavid.wu 		if (!info->ctrl->schmitt_calc_reg)
2401e3b357d7Sdavid.wu 			return -ENOTSUPP;
2402e3b357d7Sdavid.wu 
2403e3b357d7Sdavid.wu 		rc = rockchip_get_schmitt(bank, pin - bank->pin_base);
2404e3b357d7Sdavid.wu 		if (rc < 0)
2405e3b357d7Sdavid.wu 			return rc;
2406e3b357d7Sdavid.wu 
2407e3b357d7Sdavid.wu 		arg = rc;
2408e3b357d7Sdavid.wu 		break;
2409d3e51161SHeiko Stübner 	default:
2410d3e51161SHeiko Stübner 		return -ENOTSUPP;
2411d3e51161SHeiko Stübner 		break;
2412d3e51161SHeiko Stübner 	}
2413d3e51161SHeiko Stübner 
2414dab3eba7SHeiko Stübner 	*config = pinconf_to_config_packed(param, arg);
2415dab3eba7SHeiko Stübner 
2416d3e51161SHeiko Stübner 	return 0;
2417d3e51161SHeiko Stübner }
2418d3e51161SHeiko Stübner 
2419d3e51161SHeiko Stübner static const struct pinconf_ops rockchip_pinconf_ops = {
2420d3e51161SHeiko Stübner 	.pin_config_get			= rockchip_pinconf_get,
2421d3e51161SHeiko Stübner 	.pin_config_set			= rockchip_pinconf_set,
2422ed62f2f2SHeiko Stübner 	.is_generic			= true,
2423d3e51161SHeiko Stübner };
2424d3e51161SHeiko Stübner 
242565fca613SHeiko Stübner static const struct of_device_id rockchip_bank_match[] = {
242665fca613SHeiko Stübner 	{ .compatible = "rockchip,gpio-bank" },
24276ca5274dSHeiko Stübner 	{ .compatible = "rockchip,rk3188-gpio-bank0" },
242865fca613SHeiko Stübner 	{},
242965fca613SHeiko Stübner };
2430d3e51161SHeiko Stübner 
2431d3e51161SHeiko Stübner static void rockchip_pinctrl_child_count(struct rockchip_pinctrl *info,
2432d3e51161SHeiko Stübner 						struct device_node *np)
2433d3e51161SHeiko Stübner {
2434d3e51161SHeiko Stübner 	struct device_node *child;
2435d3e51161SHeiko Stübner 
2436d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
243765fca613SHeiko Stübner 		if (of_match_node(rockchip_bank_match, child))
2438d3e51161SHeiko Stübner 			continue;
2439d3e51161SHeiko Stübner 
2440d3e51161SHeiko Stübner 		info->nfunctions++;
2441d3e51161SHeiko Stübner 		info->ngroups += of_get_child_count(child);
2442d3e51161SHeiko Stübner 	}
2443d3e51161SHeiko Stübner }
2444d3e51161SHeiko Stübner 
2445d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_groups(struct device_node *np,
2446d3e51161SHeiko Stübner 					      struct rockchip_pin_group *grp,
2447d3e51161SHeiko Stübner 					      struct rockchip_pinctrl *info,
2448d3e51161SHeiko Stübner 					      u32 index)
2449d3e51161SHeiko Stübner {
2450d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
2451d3e51161SHeiko Stübner 	int size;
2452d3e51161SHeiko Stübner 	const __be32 *list;
2453d3e51161SHeiko Stübner 	int num;
2454d3e51161SHeiko Stübner 	int i, j;
2455d3e51161SHeiko Stübner 	int ret;
2456d3e51161SHeiko Stübner 
245794f4e54cSRob Herring 	dev_dbg(info->dev, "group(%d): %pOFn\n", index, np);
2458d3e51161SHeiko Stübner 
2459d3e51161SHeiko Stübner 	/* Initialise group */
2460d3e51161SHeiko Stübner 	grp->name = np->name;
2461d3e51161SHeiko Stübner 
2462d3e51161SHeiko Stübner 	/*
2463d3e51161SHeiko Stübner 	 * the binding format is rockchip,pins = <bank pin mux CONFIG>,
2464d3e51161SHeiko Stübner 	 * do sanity check and calculate pins number
2465d3e51161SHeiko Stübner 	 */
2466d3e51161SHeiko Stübner 	list = of_get_property(np, "rockchip,pins", &size);
2467d3e51161SHeiko Stübner 	/* we do not check return since it's safe node passed down */
2468d3e51161SHeiko Stübner 	size /= sizeof(*list);
2469d3e51161SHeiko Stübner 	if (!size || size % 4) {
2470d3e51161SHeiko Stübner 		dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n");
2471d3e51161SHeiko Stübner 		return -EINVAL;
2472d3e51161SHeiko Stübner 	}
2473d3e51161SHeiko Stübner 
2474d3e51161SHeiko Stübner 	grp->npins = size / 4;
2475d3e51161SHeiko Stübner 
2476a86854d0SKees Cook 	grp->pins = devm_kcalloc(info->dev, grp->npins, sizeof(unsigned int),
2477d3e51161SHeiko Stübner 						GFP_KERNEL);
2478a86854d0SKees Cook 	grp->data = devm_kcalloc(info->dev,
2479a86854d0SKees Cook 					grp->npins,
2480d3e51161SHeiko Stübner 					sizeof(struct rockchip_pin_config),
2481d3e51161SHeiko Stübner 					GFP_KERNEL);
2482d3e51161SHeiko Stübner 	if (!grp->pins || !grp->data)
2483d3e51161SHeiko Stübner 		return -ENOMEM;
2484d3e51161SHeiko Stübner 
2485d3e51161SHeiko Stübner 	for (i = 0, j = 0; i < size; i += 4, j++) {
2486d3e51161SHeiko Stübner 		const __be32 *phandle;
2487d3e51161SHeiko Stübner 		struct device_node *np_config;
2488d3e51161SHeiko Stübner 
2489d3e51161SHeiko Stübner 		num = be32_to_cpu(*list++);
2490d3e51161SHeiko Stübner 		bank = bank_num_to_bank(info, num);
2491d3e51161SHeiko Stübner 		if (IS_ERR(bank))
2492d3e51161SHeiko Stübner 			return PTR_ERR(bank);
2493d3e51161SHeiko Stübner 
2494d3e51161SHeiko Stübner 		grp->pins[j] = bank->pin_base + be32_to_cpu(*list++);
2495d3e51161SHeiko Stübner 		grp->data[j].func = be32_to_cpu(*list++);
2496d3e51161SHeiko Stübner 
2497d3e51161SHeiko Stübner 		phandle = list++;
2498d3e51161SHeiko Stübner 		if (!phandle)
2499d3e51161SHeiko Stübner 			return -EINVAL;
2500d3e51161SHeiko Stübner 
2501d3e51161SHeiko Stübner 		np_config = of_find_node_by_phandle(be32_to_cpup(phandle));
2502dd4d01f7SSoren Brinkmann 		ret = pinconf_generic_parse_dt_config(np_config, NULL,
2503d3e51161SHeiko Stübner 				&grp->data[j].configs, &grp->data[j].nconfigs);
2504d3e51161SHeiko Stübner 		if (ret)
2505d3e51161SHeiko Stübner 			return ret;
2506d3e51161SHeiko Stübner 	}
2507d3e51161SHeiko Stübner 
2508d3e51161SHeiko Stübner 	return 0;
2509d3e51161SHeiko Stübner }
2510d3e51161SHeiko Stübner 
2511d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_functions(struct device_node *np,
2512d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info,
2513d3e51161SHeiko Stübner 						u32 index)
2514d3e51161SHeiko Stübner {
2515d3e51161SHeiko Stübner 	struct device_node *child;
2516d3e51161SHeiko Stübner 	struct rockchip_pmx_func *func;
2517d3e51161SHeiko Stübner 	struct rockchip_pin_group *grp;
2518d3e51161SHeiko Stübner 	int ret;
2519d3e51161SHeiko Stübner 	static u32 grp_index;
2520d3e51161SHeiko Stübner 	u32 i = 0;
2521d3e51161SHeiko Stübner 
252294f4e54cSRob Herring 	dev_dbg(info->dev, "parse function(%d): %pOFn\n", index, np);
2523d3e51161SHeiko Stübner 
2524d3e51161SHeiko Stübner 	func = &info->functions[index];
2525d3e51161SHeiko Stübner 
2526d3e51161SHeiko Stübner 	/* Initialise function */
2527d3e51161SHeiko Stübner 	func->name = np->name;
2528d3e51161SHeiko Stübner 	func->ngroups = of_get_child_count(np);
2529d3e51161SHeiko Stübner 	if (func->ngroups <= 0)
2530d3e51161SHeiko Stübner 		return 0;
2531d3e51161SHeiko Stübner 
2532a86854d0SKees Cook 	func->groups = devm_kcalloc(info->dev,
2533a86854d0SKees Cook 			func->ngroups, sizeof(char *), GFP_KERNEL);
2534d3e51161SHeiko Stübner 	if (!func->groups)
2535d3e51161SHeiko Stübner 		return -ENOMEM;
2536d3e51161SHeiko Stübner 
2537d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
2538d3e51161SHeiko Stübner 		func->groups[i] = child->name;
2539d3e51161SHeiko Stübner 		grp = &info->groups[grp_index++];
2540d3e51161SHeiko Stübner 		ret = rockchip_pinctrl_parse_groups(child, grp, info, i++);
2541f7a81b7fSJulia Lawall 		if (ret) {
2542f7a81b7fSJulia Lawall 			of_node_put(child);
2543d3e51161SHeiko Stübner 			return ret;
2544d3e51161SHeiko Stübner 		}
2545f7a81b7fSJulia Lawall 	}
2546d3e51161SHeiko Stübner 
2547d3e51161SHeiko Stübner 	return 0;
2548d3e51161SHeiko Stübner }
2549d3e51161SHeiko Stübner 
2550d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_dt(struct platform_device *pdev,
2551d3e51161SHeiko Stübner 					      struct rockchip_pinctrl *info)
2552d3e51161SHeiko Stübner {
2553d3e51161SHeiko Stübner 	struct device *dev = &pdev->dev;
2554d3e51161SHeiko Stübner 	struct device_node *np = dev->of_node;
2555d3e51161SHeiko Stübner 	struct device_node *child;
2556d3e51161SHeiko Stübner 	int ret;
2557d3e51161SHeiko Stübner 	int i;
2558d3e51161SHeiko Stübner 
2559d3e51161SHeiko Stübner 	rockchip_pinctrl_child_count(info, np);
2560d3e51161SHeiko Stübner 
2561d3e51161SHeiko Stübner 	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
2562d3e51161SHeiko Stübner 	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
2563d3e51161SHeiko Stübner 
2564a86854d0SKees Cook 	info->functions = devm_kcalloc(dev,
2565a86854d0SKees Cook 					      info->nfunctions,
2566d3e51161SHeiko Stübner 					      sizeof(struct rockchip_pmx_func),
2567d3e51161SHeiko Stübner 					      GFP_KERNEL);
256898c8ee73SMarkus Elfring 	if (!info->functions)
2569d3e51161SHeiko Stübner 		return -EINVAL;
2570d3e51161SHeiko Stübner 
2571a86854d0SKees Cook 	info->groups = devm_kcalloc(dev,
2572a86854d0SKees Cook 					    info->ngroups,
2573d3e51161SHeiko Stübner 					    sizeof(struct rockchip_pin_group),
2574d3e51161SHeiko Stübner 					    GFP_KERNEL);
257598c8ee73SMarkus Elfring 	if (!info->groups)
2576d3e51161SHeiko Stübner 		return -EINVAL;
2577d3e51161SHeiko Stübner 
2578d3e51161SHeiko Stübner 	i = 0;
2579d3e51161SHeiko Stübner 
2580d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
258165fca613SHeiko Stübner 		if (of_match_node(rockchip_bank_match, child))
2582d3e51161SHeiko Stübner 			continue;
258365fca613SHeiko Stübner 
2584d3e51161SHeiko Stübner 		ret = rockchip_pinctrl_parse_functions(child, info, i++);
2585d3e51161SHeiko Stübner 		if (ret) {
2586d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "failed to parse function\n");
2587f7a81b7fSJulia Lawall 			of_node_put(child);
2588d3e51161SHeiko Stübner 			return ret;
2589d3e51161SHeiko Stübner 		}
2590d3e51161SHeiko Stübner 	}
2591d3e51161SHeiko Stübner 
2592d3e51161SHeiko Stübner 	return 0;
2593d3e51161SHeiko Stübner }
2594d3e51161SHeiko Stübner 
2595d3e51161SHeiko Stübner static int rockchip_pinctrl_register(struct platform_device *pdev,
2596d3e51161SHeiko Stübner 					struct rockchip_pinctrl *info)
2597d3e51161SHeiko Stübner {
2598d3e51161SHeiko Stübner 	struct pinctrl_desc *ctrldesc = &info->pctl;
2599d3e51161SHeiko Stübner 	struct pinctrl_pin_desc *pindesc, *pdesc;
2600d3e51161SHeiko Stübner 	struct rockchip_pin_bank *pin_bank;
2601d3e51161SHeiko Stübner 	int pin, bank, ret;
2602d3e51161SHeiko Stübner 	int k;
2603d3e51161SHeiko Stübner 
2604d3e51161SHeiko Stübner 	ctrldesc->name = "rockchip-pinctrl";
2605d3e51161SHeiko Stübner 	ctrldesc->owner = THIS_MODULE;
2606d3e51161SHeiko Stübner 	ctrldesc->pctlops = &rockchip_pctrl_ops;
2607d3e51161SHeiko Stübner 	ctrldesc->pmxops = &rockchip_pmx_ops;
2608d3e51161SHeiko Stübner 	ctrldesc->confops = &rockchip_pinconf_ops;
2609d3e51161SHeiko Stübner 
2610a86854d0SKees Cook 	pindesc = devm_kcalloc(&pdev->dev,
2611a86854d0SKees Cook 			       info->ctrl->nr_pins, sizeof(*pindesc),
2612a86854d0SKees Cook 			       GFP_KERNEL);
261398c8ee73SMarkus Elfring 	if (!pindesc)
2614d3e51161SHeiko Stübner 		return -ENOMEM;
261598c8ee73SMarkus Elfring 
2616d3e51161SHeiko Stübner 	ctrldesc->pins = pindesc;
2617d3e51161SHeiko Stübner 	ctrldesc->npins = info->ctrl->nr_pins;
2618d3e51161SHeiko Stübner 
2619d3e51161SHeiko Stübner 	pdesc = pindesc;
2620d3e51161SHeiko Stübner 	for (bank = 0 , k = 0; bank < info->ctrl->nr_banks; bank++) {
2621d3e51161SHeiko Stübner 		pin_bank = &info->ctrl->pin_banks[bank];
2622d3e51161SHeiko Stübner 		for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) {
2623d3e51161SHeiko Stübner 			pdesc->number = k;
2624d3e51161SHeiko Stübner 			pdesc->name = kasprintf(GFP_KERNEL, "%s-%d",
2625d3e51161SHeiko Stübner 						pin_bank->name, pin);
2626d3e51161SHeiko Stübner 			pdesc++;
2627d3e51161SHeiko Stübner 		}
2628d3e51161SHeiko Stübner 	}
2629d3e51161SHeiko Stübner 
26300fb7dcb1SDoug Anderson 	ret = rockchip_pinctrl_parse_dt(pdev, info);
26310fb7dcb1SDoug Anderson 	if (ret)
26320fb7dcb1SDoug Anderson 		return ret;
26330fb7dcb1SDoug Anderson 
26340085a2b4SLaxman Dewangan 	info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info);
2635323de9efSMasahiro Yamada 	if (IS_ERR(info->pctl_dev)) {
2636d3e51161SHeiko Stübner 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
2637323de9efSMasahiro Yamada 		return PTR_ERR(info->pctl_dev);
2638d3e51161SHeiko Stübner 	}
2639d3e51161SHeiko Stübner 
2640d3e51161SHeiko Stübner 	for (bank = 0; bank < info->ctrl->nr_banks; ++bank) {
2641d3e51161SHeiko Stübner 		pin_bank = &info->ctrl->pin_banks[bank];
2642d3e51161SHeiko Stübner 		pin_bank->grange.name = pin_bank->name;
2643d3e51161SHeiko Stübner 		pin_bank->grange.id = bank;
2644d3e51161SHeiko Stübner 		pin_bank->grange.pin_base = pin_bank->pin_base;
2645d3e51161SHeiko Stübner 		pin_bank->grange.base = pin_bank->gpio_chip.base;
2646d3e51161SHeiko Stübner 		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
2647d3e51161SHeiko Stübner 		pin_bank->grange.gc = &pin_bank->gpio_chip;
2648d3e51161SHeiko Stübner 		pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange);
2649d3e51161SHeiko Stübner 	}
2650d3e51161SHeiko Stübner 
2651d3e51161SHeiko Stübner 	return 0;
2652d3e51161SHeiko Stübner }
2653d3e51161SHeiko Stübner 
2654d3e51161SHeiko Stübner /*
2655d3e51161SHeiko Stübner  * GPIO handling
2656d3e51161SHeiko Stübner  */
2657d3e51161SHeiko Stübner 
2658d3e51161SHeiko Stübner static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
2659d3e51161SHeiko Stübner {
266003bf81f1SLinus Walleij 	struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
2661d3e51161SHeiko Stübner 	void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR;
2662d3e51161SHeiko Stübner 	unsigned long flags;
2663d3e51161SHeiko Stübner 	u32 data;
2664d3e51161SHeiko Stübner 
266507a06ae9SLin Huang 	clk_enable(bank->clk);
266670b7aa7aSJohn Keeping 	raw_spin_lock_irqsave(&bank->slock, flags);
2667d3e51161SHeiko Stübner 
2668d3e51161SHeiko Stübner 	data = readl(reg);
2669d3e51161SHeiko Stübner 	data &= ~BIT(offset);
2670d3e51161SHeiko Stübner 	if (value)
2671d3e51161SHeiko Stübner 		data |= BIT(offset);
2672d3e51161SHeiko Stübner 	writel(data, reg);
2673d3e51161SHeiko Stübner 
267470b7aa7aSJohn Keeping 	raw_spin_unlock_irqrestore(&bank->slock, flags);
267507a06ae9SLin Huang 	clk_disable(bank->clk);
2676d3e51161SHeiko Stübner }
2677d3e51161SHeiko Stübner 
2678d3e51161SHeiko Stübner /*
2679d3e51161SHeiko Stübner  * Returns the level of the pin for input direction and setting of the DR
2680d3e51161SHeiko Stübner  * register for output gpios.
2681d3e51161SHeiko Stübner  */
2682d3e51161SHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset)
2683d3e51161SHeiko Stübner {
268403bf81f1SLinus Walleij 	struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
2685d3e51161SHeiko Stübner 	u32 data;
2686d3e51161SHeiko Stübner 
268707a06ae9SLin Huang 	clk_enable(bank->clk);
2688d3e51161SHeiko Stübner 	data = readl(bank->reg_base + GPIO_EXT_PORT);
268907a06ae9SLin Huang 	clk_disable(bank->clk);
2690d3e51161SHeiko Stübner 	data >>= offset;
2691d3e51161SHeiko Stübner 	data &= 1;
2692d3e51161SHeiko Stübner 	return data;
2693d3e51161SHeiko Stübner }
2694d3e51161SHeiko Stübner 
2695d3e51161SHeiko Stübner /*
2696d3e51161SHeiko Stübner  * gpiolib gpio_direction_input callback function. The setting of the pin
269785dc397aSMarkus Elfring  * mux function as 'gpio input' will be handled by the pinctrl subsystem
2698d3e51161SHeiko Stübner  * interface.
2699d3e51161SHeiko Stübner  */
2700d3e51161SHeiko Stübner static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
2701d3e51161SHeiko Stübner {
2702d3e51161SHeiko Stübner 	return pinctrl_gpio_direction_input(gc->base + offset);
2703d3e51161SHeiko Stübner }
2704d3e51161SHeiko Stübner 
2705d3e51161SHeiko Stübner /*
2706d3e51161SHeiko Stübner  * gpiolib gpio_direction_output callback function. The setting of the pin
270785dc397aSMarkus Elfring  * mux function as 'gpio output' will be handled by the pinctrl subsystem
2708d3e51161SHeiko Stübner  * interface.
2709d3e51161SHeiko Stübner  */
2710d3e51161SHeiko Stübner static int rockchip_gpio_direction_output(struct gpio_chip *gc,
2711d3e51161SHeiko Stübner 					  unsigned offset, int value)
2712d3e51161SHeiko Stübner {
2713d3e51161SHeiko Stübner 	rockchip_gpio_set(gc, offset, value);
2714d3e51161SHeiko Stübner 	return pinctrl_gpio_direction_output(gc->base + offset);
2715d3e51161SHeiko Stübner }
2716d3e51161SHeiko Stübner 
2717b97038afSShawn Lin static void rockchip_gpio_set_debounce(struct gpio_chip *gc,
2718b97038afSShawn Lin 				       unsigned int offset, bool enable)
2719b97038afSShawn Lin {
2720b97038afSShawn Lin 	struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
2721b97038afSShawn Lin 	void __iomem *reg = bank->reg_base + GPIO_DEBOUNCE;
2722b97038afSShawn Lin 	unsigned long flags;
2723b97038afSShawn Lin 	u32 data;
2724b97038afSShawn Lin 
2725b97038afSShawn Lin 	clk_enable(bank->clk);
2726b97038afSShawn Lin 	raw_spin_lock_irqsave(&bank->slock, flags);
2727b97038afSShawn Lin 
2728b97038afSShawn Lin 	data = readl(reg);
2729b97038afSShawn Lin 	if (enable)
2730b97038afSShawn Lin 		data |= BIT(offset);
2731b97038afSShawn Lin 	else
2732b97038afSShawn Lin 		data &= ~BIT(offset);
2733b97038afSShawn Lin 	writel(data, reg);
2734b97038afSShawn Lin 
2735b97038afSShawn Lin 	raw_spin_unlock_irqrestore(&bank->slock, flags);
2736b97038afSShawn Lin 	clk_disable(bank->clk);
2737b97038afSShawn Lin }
2738b97038afSShawn Lin 
2739b97038afSShawn Lin /*
2740b97038afSShawn Lin  * gpiolib set_config callback function. The setting of the pin
2741b97038afSShawn Lin  * mux function as 'gpio output' will be handled by the pinctrl subsystem
2742b97038afSShawn Lin  * interface.
2743b97038afSShawn Lin  */
2744b97038afSShawn Lin static int rockchip_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
2745b97038afSShawn Lin 				  unsigned long config)
2746b97038afSShawn Lin {
2747b97038afSShawn Lin 	enum pin_config_param param = pinconf_to_config_param(config);
2748b97038afSShawn Lin 
2749b97038afSShawn Lin 	switch (param) {
2750b97038afSShawn Lin 	case PIN_CONFIG_INPUT_DEBOUNCE:
2751b97038afSShawn Lin 		rockchip_gpio_set_debounce(gc, offset, true);
2752b97038afSShawn Lin 		/*
2753b97038afSShawn Lin 		 * Rockchip's gpio could only support up to one period
2754b97038afSShawn Lin 		 * of the debounce clock(pclk), which is far away from
2755b97038afSShawn Lin 		 * satisftying the requirement, as pclk is usually near
2756b97038afSShawn Lin 		 * 100MHz shared by all peripherals. So the fact is it
2757b97038afSShawn Lin 		 * has crippled debounce capability could only be useful
2758b97038afSShawn Lin 		 * to prevent any spurious glitches from waking up the system
2759b97038afSShawn Lin 		 * if the gpio is conguired as wakeup interrupt source. Let's
2760b97038afSShawn Lin 		 * still return -ENOTSUPP as before, to make sure the caller
2761b97038afSShawn Lin 		 * of gpiod_set_debounce won't change its behaviour.
2762b97038afSShawn Lin 		 */
2763b97038afSShawn Lin 	default:
2764b97038afSShawn Lin 		return -ENOTSUPP;
2765b97038afSShawn Lin 	}
2766b97038afSShawn Lin }
2767b97038afSShawn Lin 
2768d3e51161SHeiko Stübner /*
2769d3e51161SHeiko Stübner  * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
2770d3e51161SHeiko Stübner  * and a virtual IRQ, if not already present.
2771d3e51161SHeiko Stübner  */
2772d3e51161SHeiko Stübner static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
2773d3e51161SHeiko Stübner {
277403bf81f1SLinus Walleij 	struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
2775d3e51161SHeiko Stübner 	unsigned int virq;
2776d3e51161SHeiko Stübner 
2777d3e51161SHeiko Stübner 	if (!bank->domain)
2778d3e51161SHeiko Stübner 		return -ENXIO;
2779d3e51161SHeiko Stübner 
2780d3e51161SHeiko Stübner 	virq = irq_create_mapping(bank->domain, offset);
2781d3e51161SHeiko Stübner 
2782d3e51161SHeiko Stübner 	return (virq) ? : -ENXIO;
2783d3e51161SHeiko Stübner }
2784d3e51161SHeiko Stübner 
2785d3e51161SHeiko Stübner static const struct gpio_chip rockchip_gpiolib_chip = {
278698c85d58SJonas Gorski 	.request = gpiochip_generic_request,
278798c85d58SJonas Gorski 	.free = gpiochip_generic_free,
2788d3e51161SHeiko Stübner 	.set = rockchip_gpio_set,
2789d3e51161SHeiko Stübner 	.get = rockchip_gpio_get,
27906ba20a00SCaesar Wang 	.get_direction	= rockchip_gpio_get_direction,
2791d3e51161SHeiko Stübner 	.direction_input = rockchip_gpio_direction_input,
2792d3e51161SHeiko Stübner 	.direction_output = rockchip_gpio_direction_output,
2793b97038afSShawn Lin 	.set_config = rockchip_gpio_set_config,
2794d3e51161SHeiko Stübner 	.to_irq = rockchip_gpio_to_irq,
2795d3e51161SHeiko Stübner 	.owner = THIS_MODULE,
2796d3e51161SHeiko Stübner };
2797d3e51161SHeiko Stübner 
2798d3e51161SHeiko Stübner /*
2799d3e51161SHeiko Stübner  * Interrupt handling
2800d3e51161SHeiko Stübner  */
2801d3e51161SHeiko Stübner 
2802bd0b9ac4SThomas Gleixner static void rockchip_irq_demux(struct irq_desc *desc)
2803d3e51161SHeiko Stübner {
28045663bb27SJiang Liu 	struct irq_chip *chip = irq_desc_get_chip(desc);
28055663bb27SJiang Liu 	struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
2806d3e51161SHeiko Stübner 	u32 pend;
2807d3e51161SHeiko Stübner 
2808d3e51161SHeiko Stübner 	dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
2809d3e51161SHeiko Stübner 
2810d3e51161SHeiko Stübner 	chained_irq_enter(chip, desc);
2811d3e51161SHeiko Stübner 
2812d3e51161SHeiko Stübner 	pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
2813d3e51161SHeiko Stübner 
2814d3e51161SHeiko Stübner 	while (pend) {
2815415f748cSThomas Gleixner 		unsigned int irq, virq;
2816d3e51161SHeiko Stübner 
2817d3e51161SHeiko Stübner 		irq = __ffs(pend);
2818d3e51161SHeiko Stübner 		pend &= ~BIT(irq);
2819d3e51161SHeiko Stübner 		virq = irq_linear_revmap(bank->domain, irq);
2820d3e51161SHeiko Stübner 
2821d3e51161SHeiko Stübner 		if (!virq) {
2822d3e51161SHeiko Stübner 			dev_err(bank->drvdata->dev, "unmapped irq %d\n", irq);
2823d3e51161SHeiko Stübner 			continue;
2824d3e51161SHeiko Stübner 		}
2825d3e51161SHeiko Stübner 
2826d3e51161SHeiko Stübner 		dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq);
2827d3e51161SHeiko Stübner 
28285a927501SHeiko Stübner 		/*
28295a927501SHeiko Stübner 		 * Triggering IRQ on both rising and falling edge
28305a927501SHeiko Stübner 		 * needs manual intervention.
28315a927501SHeiko Stübner 		 */
28325a927501SHeiko Stübner 		if (bank->toggle_edge_mode & BIT(irq)) {
283353b1bfc7SDoug Anderson 			u32 data, data_old, polarity;
283453b1bfc7SDoug Anderson 			unsigned long flags;
283553b1bfc7SDoug Anderson 
283653b1bfc7SDoug Anderson 			data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
283753b1bfc7SDoug Anderson 			do {
283870b7aa7aSJohn Keeping 				raw_spin_lock_irqsave(&bank->slock, flags);
283953b1bfc7SDoug Anderson 
284053b1bfc7SDoug Anderson 				polarity = readl_relaxed(bank->reg_base +
284153b1bfc7SDoug Anderson 							 GPIO_INT_POLARITY);
28425a927501SHeiko Stübner 				if (data & BIT(irq))
28435a927501SHeiko Stübner 					polarity &= ~BIT(irq);
28445a927501SHeiko Stübner 				else
28455a927501SHeiko Stübner 					polarity |= BIT(irq);
284653b1bfc7SDoug Anderson 				writel(polarity,
284753b1bfc7SDoug Anderson 				       bank->reg_base + GPIO_INT_POLARITY);
28485a927501SHeiko Stübner 
284970b7aa7aSJohn Keeping 				raw_spin_unlock_irqrestore(&bank->slock, flags);
285053b1bfc7SDoug Anderson 
285153b1bfc7SDoug Anderson 				data_old = data;
285253b1bfc7SDoug Anderson 				data = readl_relaxed(bank->reg_base +
285353b1bfc7SDoug Anderson 						     GPIO_EXT_PORT);
285453b1bfc7SDoug Anderson 			} while ((data & BIT(irq)) != (data_old & BIT(irq)));
28555a927501SHeiko Stübner 		}
28565a927501SHeiko Stübner 
2857d3e51161SHeiko Stübner 		generic_handle_irq(virq);
2858d3e51161SHeiko Stübner 	}
2859d3e51161SHeiko Stübner 
2860d3e51161SHeiko Stübner 	chained_irq_exit(chip, desc);
2861d3e51161SHeiko Stübner }
2862d3e51161SHeiko Stübner 
2863d3e51161SHeiko Stübner static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
2864d3e51161SHeiko Stübner {
2865d3e51161SHeiko Stübner 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
2866d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = gc->private;
2867d3e51161SHeiko Stübner 	u32 mask = BIT(d->hwirq);
2868d3e51161SHeiko Stübner 	u32 polarity;
2869d3e51161SHeiko Stübner 	u32 level;
2870d3e51161SHeiko Stübner 	u32 data;
2871fab262f5SDoug Anderson 	unsigned long flags;
287214797189SHeiko Stübner 	int ret;
2873d3e51161SHeiko Stübner 
28745a927501SHeiko Stübner 	/* make sure the pin is configured as gpio input */
28751d80df93SBrian Norris 	ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
287614797189SHeiko Stübner 	if (ret < 0)
287714797189SHeiko Stübner 		return ret;
287814797189SHeiko Stübner 
28791d80df93SBrian Norris 	clk_enable(bank->clk);
288070b7aa7aSJohn Keeping 	raw_spin_lock_irqsave(&bank->slock, flags);
2881fab262f5SDoug Anderson 
28825a927501SHeiko Stübner 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
28835a927501SHeiko Stübner 	data &= ~mask;
28845a927501SHeiko Stübner 	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
28855a927501SHeiko Stübner 
288670b7aa7aSJohn Keeping 	raw_spin_unlock_irqrestore(&bank->slock, flags);
2887fab262f5SDoug Anderson 
2888d3e51161SHeiko Stübner 	if (type & IRQ_TYPE_EDGE_BOTH)
28892dbf1bc5SThomas Gleixner 		irq_set_handler_locked(d, handle_edge_irq);
2890d3e51161SHeiko Stübner 	else
28912dbf1bc5SThomas Gleixner 		irq_set_handler_locked(d, handle_level_irq);
2892d3e51161SHeiko Stübner 
289370b7aa7aSJohn Keeping 	raw_spin_lock_irqsave(&bank->slock, flags);
2894d3e51161SHeiko Stübner 	irq_gc_lock(gc);
2895d3e51161SHeiko Stübner 
2896d3e51161SHeiko Stübner 	level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL);
2897d3e51161SHeiko Stübner 	polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY);
2898d3e51161SHeiko Stübner 
2899d3e51161SHeiko Stübner 	switch (type) {
29005a927501SHeiko Stübner 	case IRQ_TYPE_EDGE_BOTH:
29015a927501SHeiko Stübner 		bank->toggle_edge_mode |= mask;
29025a927501SHeiko Stübner 		level |= mask;
29035a927501SHeiko Stübner 
29045a927501SHeiko Stübner 		/*
29055a927501SHeiko Stübner 		 * Determine gpio state. If 1 next interrupt should be falling
29065a927501SHeiko Stübner 		 * otherwise rising.
29075a927501SHeiko Stübner 		 */
29085a927501SHeiko Stübner 		data = readl(bank->reg_base + GPIO_EXT_PORT);
29095a927501SHeiko Stübner 		if (data & mask)
29105a927501SHeiko Stübner 			polarity &= ~mask;
29115a927501SHeiko Stübner 		else
29125a927501SHeiko Stübner 			polarity |= mask;
29135a927501SHeiko Stübner 		break;
2914d3e51161SHeiko Stübner 	case IRQ_TYPE_EDGE_RISING:
29155a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2916d3e51161SHeiko Stübner 		level |= mask;
2917d3e51161SHeiko Stübner 		polarity |= mask;
2918d3e51161SHeiko Stübner 		break;
2919d3e51161SHeiko Stübner 	case IRQ_TYPE_EDGE_FALLING:
29205a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2921d3e51161SHeiko Stübner 		level |= mask;
2922d3e51161SHeiko Stübner 		polarity &= ~mask;
2923d3e51161SHeiko Stübner 		break;
2924d3e51161SHeiko Stübner 	case IRQ_TYPE_LEVEL_HIGH:
29255a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2926d3e51161SHeiko Stübner 		level &= ~mask;
2927d3e51161SHeiko Stübner 		polarity |= mask;
2928d3e51161SHeiko Stübner 		break;
2929d3e51161SHeiko Stübner 	case IRQ_TYPE_LEVEL_LOW:
29305a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2931d3e51161SHeiko Stübner 		level &= ~mask;
2932d3e51161SHeiko Stübner 		polarity &= ~mask;
2933d3e51161SHeiko Stübner 		break;
2934d3e51161SHeiko Stübner 	default:
29357cc5f970SAxel Lin 		irq_gc_unlock(gc);
293670b7aa7aSJohn Keeping 		raw_spin_unlock_irqrestore(&bank->slock, flags);
29371d80df93SBrian Norris 		clk_disable(bank->clk);
2938d3e51161SHeiko Stübner 		return -EINVAL;
2939d3e51161SHeiko Stübner 	}
2940d3e51161SHeiko Stübner 
2941d3e51161SHeiko Stübner 	writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL);
2942d3e51161SHeiko Stübner 	writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
2943d3e51161SHeiko Stübner 
2944d3e51161SHeiko Stübner 	irq_gc_unlock(gc);
294570b7aa7aSJohn Keeping 	raw_spin_unlock_irqrestore(&bank->slock, flags);
29461d80df93SBrian Norris 	clk_disable(bank->clk);
2947d3e51161SHeiko Stübner 
2948d3e51161SHeiko Stübner 	return 0;
2949d3e51161SHeiko Stübner }
2950d3e51161SHeiko Stübner 
295168bda47cSDoug Anderson static void rockchip_irq_suspend(struct irq_data *d)
295268bda47cSDoug Anderson {
295368bda47cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
295468bda47cSDoug Anderson 	struct rockchip_pin_bank *bank = gc->private;
295568bda47cSDoug Anderson 
295607a06ae9SLin Huang 	clk_enable(bank->clk);
29575ae0c7adSDoug Anderson 	bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK);
29585ae0c7adSDoug Anderson 	irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK);
295907a06ae9SLin Huang 	clk_disable(bank->clk);
296068bda47cSDoug Anderson }
296168bda47cSDoug Anderson 
296268bda47cSDoug Anderson static void rockchip_irq_resume(struct irq_data *d)
296368bda47cSDoug Anderson {
296468bda47cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
296568bda47cSDoug Anderson 	struct rockchip_pin_bank *bank = gc->private;
296668bda47cSDoug Anderson 
296707a06ae9SLin Huang 	clk_enable(bank->clk);
29685ae0c7adSDoug Anderson 	irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK);
296907a06ae9SLin Huang 	clk_disable(bank->clk);
297007a06ae9SLin Huang }
297107a06ae9SLin Huang 
2972d468289aSJeffy Chen static void rockchip_irq_enable(struct irq_data *d)
297307a06ae9SLin Huang {
297407a06ae9SLin Huang 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
297507a06ae9SLin Huang 	struct rockchip_pin_bank *bank = gc->private;
297607a06ae9SLin Huang 
297707a06ae9SLin Huang 	clk_enable(bank->clk);
297807a06ae9SLin Huang 	irq_gc_mask_clr_bit(d);
297907a06ae9SLin Huang }
298007a06ae9SLin Huang 
2981d468289aSJeffy Chen static void rockchip_irq_disable(struct irq_data *d)
298207a06ae9SLin Huang {
298307a06ae9SLin Huang 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
298407a06ae9SLin Huang 	struct rockchip_pin_bank *bank = gc->private;
298507a06ae9SLin Huang 
298607a06ae9SLin Huang 	irq_gc_mask_set_bit(d);
298707a06ae9SLin Huang 	clk_disable(bank->clk);
2988f2dd028cSDoug Anderson }
2989f2dd028cSDoug Anderson 
2990d3e51161SHeiko Stübner static int rockchip_interrupts_register(struct platform_device *pdev,
2991d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
2992d3e51161SHeiko Stübner {
2993d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
2994d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
2995d3e51161SHeiko Stübner 	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
2996d3e51161SHeiko Stübner 	struct irq_chip_generic *gc;
2997d3e51161SHeiko Stübner 	int ret;
299807a06ae9SLin Huang 	int i, j;
2999d3e51161SHeiko Stübner 
3000d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
3001d3e51161SHeiko Stübner 		if (!bank->valid) {
3002d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "bank %s is not valid\n",
3003d3e51161SHeiko Stübner 				 bank->name);
3004d3e51161SHeiko Stübner 			continue;
3005d3e51161SHeiko Stübner 		}
3006d3e51161SHeiko Stübner 
300707a06ae9SLin Huang 		ret = clk_enable(bank->clk);
300807a06ae9SLin Huang 		if (ret) {
300907a06ae9SLin Huang 			dev_err(&pdev->dev, "failed to enable clock for bank %s\n",
301007a06ae9SLin Huang 				bank->name);
301107a06ae9SLin Huang 			continue;
301207a06ae9SLin Huang 		}
301307a06ae9SLin Huang 
3014d3e51161SHeiko Stübner 		bank->domain = irq_domain_add_linear(bank->of_node, 32,
3015d3e51161SHeiko Stübner 						&irq_generic_chip_ops, NULL);
3016d3e51161SHeiko Stübner 		if (!bank->domain) {
3017d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n",
3018d3e51161SHeiko Stübner 				 bank->name);
301907a06ae9SLin Huang 			clk_disable(bank->clk);
3020d3e51161SHeiko Stübner 			continue;
3021d3e51161SHeiko Stübner 		}
3022d3e51161SHeiko Stübner 
3023d3e51161SHeiko Stübner 		ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1,
3024d3e51161SHeiko Stübner 					 "rockchip_gpio_irq", handle_level_irq,
3025d3e51161SHeiko Stübner 					 clr, 0, IRQ_GC_INIT_MASK_CACHE);
3026d3e51161SHeiko Stübner 		if (ret) {
3027d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n",
3028d3e51161SHeiko Stübner 				bank->name);
3029d3e51161SHeiko Stübner 			irq_domain_remove(bank->domain);
303007a06ae9SLin Huang 			clk_disable(bank->clk);
3031d3e51161SHeiko Stübner 			continue;
3032d3e51161SHeiko Stübner 		}
3033d3e51161SHeiko Stübner 
30345ae0c7adSDoug Anderson 		/*
30355ae0c7adSDoug Anderson 		 * Linux assumes that all interrupts start out disabled/masked.
30365ae0c7adSDoug Anderson 		 * Our driver only uses the concept of masked and always keeps
30375ae0c7adSDoug Anderson 		 * things enabled, so for us that's all masked and all enabled.
30385ae0c7adSDoug Anderson 		 */
30395ae0c7adSDoug Anderson 		writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK);
30405ae0c7adSDoug Anderson 		writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN);
30415ae0c7adSDoug Anderson 
3042d3e51161SHeiko Stübner 		gc = irq_get_domain_generic_chip(bank->domain, 0);
3043d3e51161SHeiko Stübner 		gc->reg_base = bank->reg_base;
3044d3e51161SHeiko Stübner 		gc->private = bank;
3045f2dd028cSDoug Anderson 		gc->chip_types[0].regs.mask = GPIO_INTMASK;
3046d3e51161SHeiko Stübner 		gc->chip_types[0].regs.ack = GPIO_PORTS_EOI;
3047d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
3048d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
3049d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
3050d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_enable = rockchip_irq_enable;
3051d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_disable = rockchip_irq_disable;
3052d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
305368bda47cSDoug Anderson 		gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
305468bda47cSDoug Anderson 		gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
3055d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
3056876d716bSDoug Anderson 		gc->wake_enabled = IRQ_MSK(bank->nr_pins);
3057d3e51161SHeiko Stübner 
305803051bc2SThomas Gleixner 		irq_set_chained_handler_and_data(bank->irq,
305903051bc2SThomas Gleixner 						 rockchip_irq_demux, bank);
306007a06ae9SLin Huang 
306107a06ae9SLin Huang 		/* map the gpio irqs here, when the clock is still running */
306207a06ae9SLin Huang 		for (j = 0 ; j < 32 ; j++)
306307a06ae9SLin Huang 			irq_create_mapping(bank->domain, j);
306407a06ae9SLin Huang 
306507a06ae9SLin Huang 		clk_disable(bank->clk);
3066d3e51161SHeiko Stübner 	}
3067d3e51161SHeiko Stübner 
3068d3e51161SHeiko Stübner 	return 0;
3069d3e51161SHeiko Stübner }
3070d3e51161SHeiko Stübner 
3071d3e51161SHeiko Stübner static int rockchip_gpiolib_register(struct platform_device *pdev,
3072d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
3073d3e51161SHeiko Stübner {
3074d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
3075d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
3076d3e51161SHeiko Stübner 	struct gpio_chip *gc;
3077d3e51161SHeiko Stübner 	int ret;
3078d3e51161SHeiko Stübner 	int i;
3079d3e51161SHeiko Stübner 
3080d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
3081d3e51161SHeiko Stübner 		if (!bank->valid) {
3082d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "bank %s is not valid\n",
3083d3e51161SHeiko Stübner 				 bank->name);
3084d3e51161SHeiko Stübner 			continue;
3085d3e51161SHeiko Stübner 		}
3086d3e51161SHeiko Stübner 
3087d3e51161SHeiko Stübner 		bank->gpio_chip = rockchip_gpiolib_chip;
3088d3e51161SHeiko Stübner 
3089d3e51161SHeiko Stübner 		gc = &bank->gpio_chip;
3090d3e51161SHeiko Stübner 		gc->base = bank->pin_base;
3091d3e51161SHeiko Stübner 		gc->ngpio = bank->nr_pins;
309258383c78SLinus Walleij 		gc->parent = &pdev->dev;
3093d3e51161SHeiko Stübner 		gc->of_node = bank->of_node;
3094d3e51161SHeiko Stübner 		gc->label = bank->name;
3095d3e51161SHeiko Stübner 
309603bf81f1SLinus Walleij 		ret = gpiochip_add_data(gc, bank);
3097d3e51161SHeiko Stübner 		if (ret) {
3098d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
3099d3e51161SHeiko Stübner 							gc->label, ret);
3100d3e51161SHeiko Stübner 			goto fail;
3101d3e51161SHeiko Stübner 		}
3102d3e51161SHeiko Stübner 	}
3103d3e51161SHeiko Stübner 
3104d3e51161SHeiko Stübner 	rockchip_interrupts_register(pdev, info);
3105d3e51161SHeiko Stübner 
3106d3e51161SHeiko Stübner 	return 0;
3107d3e51161SHeiko Stübner 
3108d3e51161SHeiko Stübner fail:
3109d3e51161SHeiko Stübner 	for (--i, --bank; i >= 0; --i, --bank) {
3110d3e51161SHeiko Stübner 		if (!bank->valid)
3111d3e51161SHeiko Stübner 			continue;
3112b4e7c55dSabdoulaye berthe 		gpiochip_remove(&bank->gpio_chip);
3113d3e51161SHeiko Stübner 	}
3114d3e51161SHeiko Stübner 	return ret;
3115d3e51161SHeiko Stübner }
3116d3e51161SHeiko Stübner 
3117d3e51161SHeiko Stübner static int rockchip_gpiolib_unregister(struct platform_device *pdev,
3118d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
3119d3e51161SHeiko Stübner {
3120d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
3121d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
3122d3e51161SHeiko Stübner 	int i;
3123d3e51161SHeiko Stübner 
3124b4e7c55dSabdoulaye berthe 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
3125d3e51161SHeiko Stübner 		if (!bank->valid)
3126d3e51161SHeiko Stübner 			continue;
3127b4e7c55dSabdoulaye berthe 		gpiochip_remove(&bank->gpio_chip);
3128d3e51161SHeiko Stübner 	}
3129d3e51161SHeiko Stübner 
3130b4e7c55dSabdoulaye berthe 	return 0;
3131d3e51161SHeiko Stübner }
3132d3e51161SHeiko Stübner 
3133d3e51161SHeiko Stübner static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
3134622f3237SHeiko Stübner 				  struct rockchip_pinctrl *info)
3135d3e51161SHeiko Stübner {
3136d3e51161SHeiko Stübner 	struct resource res;
3137751a99abSHeiko Stübner 	void __iomem *base;
3138d3e51161SHeiko Stübner 
3139d3e51161SHeiko Stübner 	if (of_address_to_resource(bank->of_node, 0, &res)) {
3140622f3237SHeiko Stübner 		dev_err(info->dev, "cannot find IO resource for bank\n");
3141d3e51161SHeiko Stübner 		return -ENOENT;
3142d3e51161SHeiko Stübner 	}
3143d3e51161SHeiko Stübner 
3144622f3237SHeiko Stübner 	bank->reg_base = devm_ioremap_resource(info->dev, &res);
3145d3e51161SHeiko Stübner 	if (IS_ERR(bank->reg_base))
3146d3e51161SHeiko Stübner 		return PTR_ERR(bank->reg_base);
3147d3e51161SHeiko Stübner 
31486ca5274dSHeiko Stübner 	/*
31496ca5274dSHeiko Stübner 	 * special case, where parts of the pull setting-registers are
31506ca5274dSHeiko Stübner 	 * part of the PMU register space
31516ca5274dSHeiko Stübner 	 */
31526ca5274dSHeiko Stübner 	if (of_device_is_compatible(bank->of_node,
31536ca5274dSHeiko Stübner 				    "rockchip,rk3188-gpio-bank0")) {
3154a658efaaSHeiko Stübner 		struct device_node *node;
3155bfc7a42aSHeiko Stübner 
3156a658efaaSHeiko Stübner 		node = of_parse_phandle(bank->of_node->parent,
3157a658efaaSHeiko Stübner 					"rockchip,pmu", 0);
3158a658efaaSHeiko Stübner 		if (!node) {
31596ca5274dSHeiko Stübner 			if (of_address_to_resource(bank->of_node, 1, &res)) {
3160622f3237SHeiko Stübner 				dev_err(info->dev, "cannot find IO resource for bank\n");
31616ca5274dSHeiko Stübner 				return -ENOENT;
31626ca5274dSHeiko Stübner 			}
31636ca5274dSHeiko Stübner 
3164622f3237SHeiko Stübner 			base = devm_ioremap_resource(info->dev, &res);
3165751a99abSHeiko Stübner 			if (IS_ERR(base))
3166751a99abSHeiko Stübner 				return PTR_ERR(base);
3167a658efaaSHeiko Stübner 			rockchip_regmap_config.max_register =
3168a658efaaSHeiko Stübner 						    resource_size(&res) - 4;
3169a658efaaSHeiko Stübner 			rockchip_regmap_config.name =
3170a658efaaSHeiko Stübner 					    "rockchip,rk3188-gpio-bank0-pull";
3171a658efaaSHeiko Stübner 			bank->regmap_pull = devm_regmap_init_mmio(info->dev,
3172a658efaaSHeiko Stübner 						    base,
3173751a99abSHeiko Stübner 						    &rockchip_regmap_config);
3174a658efaaSHeiko Stübner 		}
31756ca5274dSHeiko Stübner 	}
317665fca613SHeiko Stübner 
3177d3e51161SHeiko Stübner 	bank->irq = irq_of_parse_and_map(bank->of_node, 0);
3178d3e51161SHeiko Stübner 
3179d3e51161SHeiko Stübner 	bank->clk = of_clk_get(bank->of_node, 0);
3180d3e51161SHeiko Stübner 	if (IS_ERR(bank->clk))
3181d3e51161SHeiko Stübner 		return PTR_ERR(bank->clk);
3182d3e51161SHeiko Stübner 
318307a06ae9SLin Huang 	return clk_prepare(bank->clk);
3184d3e51161SHeiko Stübner }
3185d3e51161SHeiko Stübner 
3186d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[];
3187d3e51161SHeiko Stübner 
3188d3e51161SHeiko Stübner /* retrieve the soc specific data */
3189d3e51161SHeiko Stübner static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
3190d3e51161SHeiko Stübner 						struct rockchip_pinctrl *d,
3191d3e51161SHeiko Stübner 						struct platform_device *pdev)
3192d3e51161SHeiko Stübner {
3193d3e51161SHeiko Stübner 	const struct of_device_id *match;
3194d3e51161SHeiko Stübner 	struct device_node *node = pdev->dev.of_node;
3195d3e51161SHeiko Stübner 	struct device_node *np;
3196d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl;
3197d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
3198b6c23275SDavid Wu 	int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j;
3199d3e51161SHeiko Stübner 
3200d3e51161SHeiko Stübner 	match = of_match_node(rockchip_pinctrl_dt_match, node);
3201d3e51161SHeiko Stübner 	ctrl = (struct rockchip_pin_ctrl *)match->data;
3202d3e51161SHeiko Stübner 
3203d3e51161SHeiko Stübner 	for_each_child_of_node(node, np) {
3204d3e51161SHeiko Stübner 		if (!of_find_property(np, "gpio-controller", NULL))
3205d3e51161SHeiko Stübner 			continue;
3206d3e51161SHeiko Stübner 
3207d3e51161SHeiko Stübner 		bank = ctrl->pin_banks;
3208d3e51161SHeiko Stübner 		for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
3209d3e51161SHeiko Stübner 			if (!strcmp(bank->name, np->name)) {
3210d3e51161SHeiko Stübner 				bank->of_node = np;
3211d3e51161SHeiko Stübner 
3212622f3237SHeiko Stübner 				if (!rockchip_get_bank_data(bank, d))
3213d3e51161SHeiko Stübner 					bank->valid = true;
3214d3e51161SHeiko Stübner 
3215d3e51161SHeiko Stübner 				break;
3216d3e51161SHeiko Stübner 			}
3217d3e51161SHeiko Stübner 		}
3218d3e51161SHeiko Stübner 	}
3219d3e51161SHeiko Stübner 
322095ec8ae4SHeiko Stübner 	grf_offs = ctrl->grf_mux_offset;
322195ec8ae4SHeiko Stübner 	pmu_offs = ctrl->pmu_mux_offset;
3222b6c23275SDavid Wu 	drv_pmu_offs = ctrl->pmu_drv_offset;
3223b6c23275SDavid Wu 	drv_grf_offs = ctrl->grf_drv_offset;
3224d3e51161SHeiko Stübner 	bank = ctrl->pin_banks;
3225d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
32266bc0d121SHeiko Stübner 		int bank_pins = 0;
32276bc0d121SHeiko Stübner 
322870b7aa7aSJohn Keeping 		raw_spin_lock_init(&bank->slock);
3229d3e51161SHeiko Stübner 		bank->drvdata = d;
3230d3e51161SHeiko Stübner 		bank->pin_base = ctrl->nr_pins;
3231d3e51161SHeiko Stübner 		ctrl->nr_pins += bank->nr_pins;
32326bc0d121SHeiko Stübner 
3233b6c23275SDavid Wu 		/* calculate iomux and drv offsets */
32346bc0d121SHeiko Stübner 		for (j = 0; j < 4; j++) {
32356bc0d121SHeiko Stübner 			struct rockchip_iomux *iom = &bank->iomux[j];
3236b6c23275SDavid Wu 			struct rockchip_drv *drv = &bank->drv[j];
323703716e1dSHeiko Stübner 			int inc;
32386bc0d121SHeiko Stübner 
32396bc0d121SHeiko Stübner 			if (bank_pins >= bank->nr_pins)
32406bc0d121SHeiko Stübner 				break;
32416bc0d121SHeiko Stübner 
3242b6c23275SDavid Wu 			/* preset iomux offset value, set new start value */
32436bc0d121SHeiko Stübner 			if (iom->offset >= 0) {
324495ec8ae4SHeiko Stübner 				if (iom->type & IOMUX_SOURCE_PMU)
324595ec8ae4SHeiko Stübner 					pmu_offs = iom->offset;
324695ec8ae4SHeiko Stübner 				else
32476bc0d121SHeiko Stübner 					grf_offs = iom->offset;
3248b6c23275SDavid Wu 			} else { /* set current iomux offset */
324995ec8ae4SHeiko Stübner 				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
325095ec8ae4SHeiko Stübner 							pmu_offs : grf_offs;
32516bc0d121SHeiko Stübner 			}
32526bc0d121SHeiko Stübner 
3253b6c23275SDavid Wu 			/* preset drv offset value, set new start value */
3254b6c23275SDavid Wu 			if (drv->offset >= 0) {
3255b6c23275SDavid Wu 				if (iom->type & IOMUX_SOURCE_PMU)
3256b6c23275SDavid Wu 					drv_pmu_offs = drv->offset;
3257b6c23275SDavid Wu 				else
3258b6c23275SDavid Wu 					drv_grf_offs = drv->offset;
3259b6c23275SDavid Wu 			} else { /* set current drv offset */
3260b6c23275SDavid Wu 				drv->offset = (iom->type & IOMUX_SOURCE_PMU) ?
3261b6c23275SDavid Wu 						drv_pmu_offs : drv_grf_offs;
3262b6c23275SDavid Wu 			}
3263b6c23275SDavid Wu 
3264b6c23275SDavid Wu 			dev_dbg(d->dev, "bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n",
3265b6c23275SDavid Wu 				i, j, iom->offset, drv->offset);
32666bc0d121SHeiko Stübner 
32676bc0d121SHeiko Stübner 			/*
32686bc0d121SHeiko Stübner 			 * Increase offset according to iomux width.
326903716e1dSHeiko Stübner 			 * 4bit iomux'es are spread over two registers.
32706bc0d121SHeiko Stübner 			 */
32718b6c6f93Sdavid.wu 			inc = (iom->type & (IOMUX_WIDTH_4BIT |
32728b6c6f93Sdavid.wu 					    IOMUX_WIDTH_3BIT)) ? 8 : 4;
327395ec8ae4SHeiko Stübner 			if (iom->type & IOMUX_SOURCE_PMU)
327495ec8ae4SHeiko Stübner 				pmu_offs += inc;
327595ec8ae4SHeiko Stübner 			else
327603716e1dSHeiko Stübner 				grf_offs += inc;
32776bc0d121SHeiko Stübner 
3278b6c23275SDavid Wu 			/*
3279b6c23275SDavid Wu 			 * Increase offset according to drv width.
3280b6c23275SDavid Wu 			 * 3bit drive-strenth'es are spread over two registers.
3281b6c23275SDavid Wu 			 */
3282b6c23275SDavid Wu 			if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
3283b6c23275SDavid Wu 			    (drv->drv_type == DRV_TYPE_IO_3V3_ONLY))
3284b6c23275SDavid Wu 				inc = 8;
3285b6c23275SDavid Wu 			else
3286b6c23275SDavid Wu 				inc = 4;
3287b6c23275SDavid Wu 
3288b6c23275SDavid Wu 			if (iom->type & IOMUX_SOURCE_PMU)
3289b6c23275SDavid Wu 				drv_pmu_offs += inc;
3290b6c23275SDavid Wu 			else
3291b6c23275SDavid Wu 				drv_grf_offs += inc;
3292b6c23275SDavid Wu 
32936bc0d121SHeiko Stübner 			bank_pins += 8;
32946bc0d121SHeiko Stübner 		}
3295bd35b9bfSDavid Wu 
3296c04c3fa6SDavid Wu 		/* calculate the per-bank recalced_mask */
3297c04c3fa6SDavid Wu 		for (j = 0; j < ctrl->niomux_recalced; j++) {
3298c04c3fa6SDavid Wu 			int pin = 0;
3299c04c3fa6SDavid Wu 
3300c04c3fa6SDavid Wu 			if (ctrl->iomux_recalced[j].num == bank->bank_num) {
3301c04c3fa6SDavid Wu 				pin = ctrl->iomux_recalced[j].pin;
3302c04c3fa6SDavid Wu 				bank->recalced_mask |= BIT(pin);
3303c04c3fa6SDavid Wu 			}
3304c04c3fa6SDavid Wu 		}
3305c04c3fa6SDavid Wu 
3306bd35b9bfSDavid Wu 		/* calculate the per-bank route_mask */
3307bd35b9bfSDavid Wu 		for (j = 0; j < ctrl->niomux_routes; j++) {
3308bd35b9bfSDavid Wu 			int pin = 0;
3309bd35b9bfSDavid Wu 
3310bd35b9bfSDavid Wu 			if (ctrl->iomux_routes[j].bank_num == bank->bank_num) {
3311bd35b9bfSDavid Wu 				pin = ctrl->iomux_routes[j].pin;
3312bd35b9bfSDavid Wu 				bank->route_mask |= BIT(pin);
3313bd35b9bfSDavid Wu 			}
3314bd35b9bfSDavid Wu 		}
3315d3e51161SHeiko Stübner 	}
3316d3e51161SHeiko Stübner 
3317d3e51161SHeiko Stübner 	return ctrl;
3318d3e51161SHeiko Stübner }
3319d3e51161SHeiko Stübner 
33208dca9331SChris Zhong #define RK3288_GRF_GPIO6C_IOMUX		0x64
33218dca9331SChris Zhong #define GPIO6C6_SEL_WRITE_ENABLE	BIT(28)
33228dca9331SChris Zhong 
33238dca9331SChris Zhong static u32 rk3288_grf_gpio6c_iomux;
33248dca9331SChris Zhong 
33259198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev)
33269198f509SChris Zhong {
33279198f509SChris Zhong 	struct rockchip_pinctrl *info = dev_get_drvdata(dev);
33288dca9331SChris Zhong 	int ret = pinctrl_force_sleep(info->pctl_dev);
33299198f509SChris Zhong 
33308dca9331SChris Zhong 	if (ret)
33318dca9331SChris Zhong 		return ret;
33328dca9331SChris Zhong 
33338dca9331SChris Zhong 	/*
33348dca9331SChris Zhong 	 * RK3288 GPIO6_C6 mux would be modified by Maskrom when resume, so save
33358dca9331SChris Zhong 	 * the setting here, and restore it at resume.
33368dca9331SChris Zhong 	 */
33378dca9331SChris Zhong 	if (info->ctrl->type == RK3288) {
33388dca9331SChris Zhong 		ret = regmap_read(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
33398dca9331SChris Zhong 				  &rk3288_grf_gpio6c_iomux);
33408dca9331SChris Zhong 		if (ret) {
33418dca9331SChris Zhong 			pinctrl_force_default(info->pctl_dev);
33428dca9331SChris Zhong 			return ret;
33438dca9331SChris Zhong 		}
33448dca9331SChris Zhong 	}
33458dca9331SChris Zhong 
33468dca9331SChris Zhong 	return 0;
33479198f509SChris Zhong }
33489198f509SChris Zhong 
33499198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_resume(struct device *dev)
33509198f509SChris Zhong {
33519198f509SChris Zhong 	struct rockchip_pinctrl *info = dev_get_drvdata(dev);
33528dca9331SChris Zhong 	int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
33538dca9331SChris Zhong 			       rk3288_grf_gpio6c_iomux |
33548dca9331SChris Zhong 			       GPIO6C6_SEL_WRITE_ENABLE);
33558dca9331SChris Zhong 
33568dca9331SChris Zhong 	if (ret)
33578dca9331SChris Zhong 		return ret;
33589198f509SChris Zhong 
33599198f509SChris Zhong 	return pinctrl_force_default(info->pctl_dev);
33609198f509SChris Zhong }
33619198f509SChris Zhong 
33629198f509SChris Zhong static SIMPLE_DEV_PM_OPS(rockchip_pinctrl_dev_pm_ops, rockchip_pinctrl_suspend,
33639198f509SChris Zhong 			 rockchip_pinctrl_resume);
33649198f509SChris Zhong 
3365d3e51161SHeiko Stübner static int rockchip_pinctrl_probe(struct platform_device *pdev)
3366d3e51161SHeiko Stübner {
3367d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info;
3368d3e51161SHeiko Stübner 	struct device *dev = &pdev->dev;
3369d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl;
337014dee867SHeiko Stübner 	struct device_node *np = pdev->dev.of_node, *node;
3371d3e51161SHeiko Stübner 	struct resource *res;
3372751a99abSHeiko Stübner 	void __iomem *base;
3373d3e51161SHeiko Stübner 	int ret;
3374d3e51161SHeiko Stübner 
3375d3e51161SHeiko Stübner 	if (!dev->of_node) {
3376d3e51161SHeiko Stübner 		dev_err(dev, "device tree node not found\n");
3377d3e51161SHeiko Stübner 		return -ENODEV;
3378d3e51161SHeiko Stübner 	}
3379d3e51161SHeiko Stübner 
3380283b7ac9SMarkus Elfring 	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
3381d3e51161SHeiko Stübner 	if (!info)
3382d3e51161SHeiko Stübner 		return -ENOMEM;
3383d3e51161SHeiko Stübner 
3384622f3237SHeiko Stübner 	info->dev = dev;
3385622f3237SHeiko Stübner 
3386d3e51161SHeiko Stübner 	ctrl = rockchip_pinctrl_get_soc_data(info, pdev);
3387d3e51161SHeiko Stübner 	if (!ctrl) {
3388d3e51161SHeiko Stübner 		dev_err(dev, "driver data not available\n");
3389d3e51161SHeiko Stübner 		return -EINVAL;
3390d3e51161SHeiko Stübner 	}
3391d3e51161SHeiko Stübner 	info->ctrl = ctrl;
3392d3e51161SHeiko Stübner 
33931e747e59SHeiko Stübner 	node = of_parse_phandle(np, "rockchip,grf", 0);
33941e747e59SHeiko Stübner 	if (node) {
33951e747e59SHeiko Stübner 		info->regmap_base = syscon_node_to_regmap(node);
33961e747e59SHeiko Stübner 		if (IS_ERR(info->regmap_base))
33971e747e59SHeiko Stübner 			return PTR_ERR(info->regmap_base);
33981e747e59SHeiko Stübner 	} else {
3399d3e51161SHeiko Stübner 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3400751a99abSHeiko Stübner 		base = devm_ioremap_resource(&pdev->dev, res);
3401751a99abSHeiko Stübner 		if (IS_ERR(base))
3402751a99abSHeiko Stübner 			return PTR_ERR(base);
3403751a99abSHeiko Stübner 
3404751a99abSHeiko Stübner 		rockchip_regmap_config.max_register = resource_size(res) - 4;
3405751a99abSHeiko Stübner 		rockchip_regmap_config.name = "rockchip,pinctrl";
3406751a99abSHeiko Stübner 		info->regmap_base = devm_regmap_init_mmio(&pdev->dev, base,
3407751a99abSHeiko Stübner 						    &rockchip_regmap_config);
3408d3e51161SHeiko Stübner 
3409bfc7a42aSHeiko Stübner 		/* to check for the old dt-bindings */
3410bfc7a42aSHeiko Stübner 		info->reg_size = resource_size(res);
3411bfc7a42aSHeiko Stübner 
3412bfc7a42aSHeiko Stübner 		/* Honor the old binding, with pull registers as 2nd resource */
3413bfc7a42aSHeiko Stübner 		if (ctrl->type == RK3188 && info->reg_size < 0x200) {
34146ca5274dSHeiko Stübner 			res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
3415751a99abSHeiko Stübner 			base = devm_ioremap_resource(&pdev->dev, res);
3416751a99abSHeiko Stübner 			if (IS_ERR(base))
3417751a99abSHeiko Stübner 				return PTR_ERR(base);
3418751a99abSHeiko Stübner 
34191e747e59SHeiko Stübner 			rockchip_regmap_config.max_register =
34201e747e59SHeiko Stübner 							resource_size(res) - 4;
3421751a99abSHeiko Stübner 			rockchip_regmap_config.name = "rockchip,pinctrl-pull";
34221e747e59SHeiko Stübner 			info->regmap_pull = devm_regmap_init_mmio(&pdev->dev,
34231e747e59SHeiko Stübner 						    base,
3424751a99abSHeiko Stübner 						    &rockchip_regmap_config);
34256ca5274dSHeiko Stübner 		}
34261e747e59SHeiko Stübner 	}
34276ca5274dSHeiko Stübner 
342814dee867SHeiko Stübner 	/* try to find the optional reference to the pmu syscon */
342914dee867SHeiko Stübner 	node = of_parse_phandle(np, "rockchip,pmu", 0);
343014dee867SHeiko Stübner 	if (node) {
343114dee867SHeiko Stübner 		info->regmap_pmu = syscon_node_to_regmap(node);
343214dee867SHeiko Stübner 		if (IS_ERR(info->regmap_pmu))
343314dee867SHeiko Stübner 			return PTR_ERR(info->regmap_pmu);
343414dee867SHeiko Stübner 	}
343514dee867SHeiko Stübner 
3436d3e51161SHeiko Stübner 	ret = rockchip_gpiolib_register(pdev, info);
3437d3e51161SHeiko Stübner 	if (ret)
3438d3e51161SHeiko Stübner 		return ret;
3439d3e51161SHeiko Stübner 
3440d3e51161SHeiko Stübner 	ret = rockchip_pinctrl_register(pdev, info);
3441d3e51161SHeiko Stübner 	if (ret) {
3442d3e51161SHeiko Stübner 		rockchip_gpiolib_unregister(pdev, info);
3443d3e51161SHeiko Stübner 		return ret;
3444d3e51161SHeiko Stübner 	}
3445d3e51161SHeiko Stübner 
3446d3e51161SHeiko Stübner 	platform_set_drvdata(pdev, info);
3447d3e51161SHeiko Stübner 
3448d3e51161SHeiko Stübner 	return 0;
3449d3e51161SHeiko Stübner }
3450d3e51161SHeiko Stübner 
345187065ca9SDavid Wu static struct rockchip_pin_bank px30_pin_banks[] = {
345287065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
345387065ca9SDavid Wu 					     IOMUX_SOURCE_PMU,
345487065ca9SDavid Wu 					     IOMUX_SOURCE_PMU,
345587065ca9SDavid Wu 					     IOMUX_SOURCE_PMU
345687065ca9SDavid Wu 			    ),
345787065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
345887065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
345987065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
346087065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT
346187065ca9SDavid Wu 			    ),
346287065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
346387065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
346487065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
346587065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT
346687065ca9SDavid Wu 			    ),
346787065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
346887065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
346987065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
347087065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT
347187065ca9SDavid Wu 			    ),
347287065ca9SDavid Wu };
347387065ca9SDavid Wu 
347487065ca9SDavid Wu static struct rockchip_pin_ctrl px30_pin_ctrl = {
347587065ca9SDavid Wu 		.pin_banks		= px30_pin_banks,
347687065ca9SDavid Wu 		.nr_banks		= ARRAY_SIZE(px30_pin_banks),
347787065ca9SDavid Wu 		.label			= "PX30-GPIO",
347887065ca9SDavid Wu 		.type			= PX30,
347987065ca9SDavid Wu 		.grf_mux_offset		= 0x0,
348087065ca9SDavid Wu 		.pmu_mux_offset		= 0x0,
348187065ca9SDavid Wu 		.iomux_routes		= px30_mux_route_data,
348287065ca9SDavid Wu 		.niomux_routes		= ARRAY_SIZE(px30_mux_route_data),
348387065ca9SDavid Wu 		.pull_calc_reg		= px30_calc_pull_reg_and_bit,
348487065ca9SDavid Wu 		.drv_calc_reg		= px30_calc_drv_reg_and_bit,
348587065ca9SDavid Wu 		.schmitt_calc_reg	= px30_calc_schmitt_reg_and_bit,
348687065ca9SDavid Wu };
348787065ca9SDavid Wu 
3488b9c6dcabSAndy Yan static struct rockchip_pin_bank rv1108_pin_banks[] = {
3489688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
3490688daf23SAndy Yan 					     IOMUX_SOURCE_PMU,
3491688daf23SAndy Yan 					     IOMUX_SOURCE_PMU,
3492688daf23SAndy Yan 					     IOMUX_SOURCE_PMU),
3493688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
3494688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0),
3495688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
3496688daf23SAndy Yan };
3497688daf23SAndy Yan 
3498b9c6dcabSAndy Yan static struct rockchip_pin_ctrl rv1108_pin_ctrl = {
3499b9c6dcabSAndy Yan 	.pin_banks		= rv1108_pin_banks,
3500b9c6dcabSAndy Yan 	.nr_banks		= ARRAY_SIZE(rv1108_pin_banks),
3501b9c6dcabSAndy Yan 	.label			= "RV1108-GPIO",
3502b9c6dcabSAndy Yan 	.type			= RV1108,
3503688daf23SAndy Yan 	.grf_mux_offset		= 0x10,
3504688daf23SAndy Yan 	.pmu_mux_offset		= 0x0,
350512b8f018SDavid Wu 	.iomux_recalced		= rv1108_mux_recalced_data,
350612b8f018SDavid Wu 	.niomux_recalced	= ARRAY_SIZE(rv1108_mux_recalced_data),
3507b9c6dcabSAndy Yan 	.pull_calc_reg		= rv1108_calc_pull_reg_and_bit,
3508b9c6dcabSAndy Yan 	.drv_calc_reg		= rv1108_calc_drv_reg_and_bit,
35095caff7eaSAndy Yan 	.schmitt_calc_reg	= rv1108_calc_schmitt_reg_and_bit,
3510688daf23SAndy Yan };
3511688daf23SAndy Yan 
3512d3e51161SHeiko Stübner static struct rockchip_pin_bank rk2928_pin_banks[] = {
3513d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
3514d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3515d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3516d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3517d3e51161SHeiko Stübner };
3518d3e51161SHeiko Stübner 
3519d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
3520d3e51161SHeiko Stübner 		.pin_banks		= rk2928_pin_banks,
3521d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk2928_pin_banks),
3522d3e51161SHeiko Stübner 		.label			= "RK2928-GPIO",
3523a282926dSHeiko Stübner 		.type			= RK2928,
352495ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0xa8,
3525a282926dSHeiko Stübner 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
3526d3e51161SHeiko Stübner };
3527d3e51161SHeiko Stübner 
3528c5ce7670SXing Zheng static struct rockchip_pin_bank rk3036_pin_banks[] = {
3529c5ce7670SXing Zheng 	PIN_BANK(0, 32, "gpio0"),
3530c5ce7670SXing Zheng 	PIN_BANK(1, 32, "gpio1"),
3531c5ce7670SXing Zheng 	PIN_BANK(2, 32, "gpio2"),
3532c5ce7670SXing Zheng };
3533c5ce7670SXing Zheng 
3534c5ce7670SXing Zheng static struct rockchip_pin_ctrl rk3036_pin_ctrl = {
3535c5ce7670SXing Zheng 		.pin_banks		= rk3036_pin_banks,
3536c5ce7670SXing Zheng 		.nr_banks		= ARRAY_SIZE(rk3036_pin_banks),
3537c5ce7670SXing Zheng 		.label			= "RK3036-GPIO",
3538c5ce7670SXing Zheng 		.type			= RK2928,
3539c5ce7670SXing Zheng 		.grf_mux_offset		= 0xa8,
3540c5ce7670SXing Zheng 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
3541c5ce7670SXing Zheng };
3542c5ce7670SXing Zheng 
3543d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066a_pin_banks[] = {
3544d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
3545d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3546d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3547d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3548d3e51161SHeiko Stübner 	PIN_BANK(4, 32, "gpio4"),
3549d3e51161SHeiko Stübner 	PIN_BANK(6, 16, "gpio6"),
3550d3e51161SHeiko Stübner };
3551d3e51161SHeiko Stübner 
3552d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066a_pin_ctrl = {
3553d3e51161SHeiko Stübner 		.pin_banks		= rk3066a_pin_banks,
3554d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3066a_pin_banks),
3555d3e51161SHeiko Stübner 		.label			= "RK3066a-GPIO",
3556a282926dSHeiko Stübner 		.type			= RK2928,
355795ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0xa8,
3558a282926dSHeiko Stübner 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
3559d3e51161SHeiko Stübner };
3560d3e51161SHeiko Stübner 
3561d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066b_pin_banks[] = {
3562d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
3563d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3564d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3565d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3566d3e51161SHeiko Stübner };
3567d3e51161SHeiko Stübner 
3568d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066b_pin_ctrl = {
3569d3e51161SHeiko Stübner 		.pin_banks	= rk3066b_pin_banks,
3570d3e51161SHeiko Stübner 		.nr_banks	= ARRAY_SIZE(rk3066b_pin_banks),
3571d3e51161SHeiko Stübner 		.label		= "RK3066b-GPIO",
3572a282926dSHeiko Stübner 		.type		= RK3066B,
357395ec8ae4SHeiko Stübner 		.grf_mux_offset	= 0x60,
3574d3e51161SHeiko Stübner };
3575d3e51161SHeiko Stübner 
3576d23c66dfSDavid Wu static struct rockchip_pin_bank rk3128_pin_banks[] = {
3577d23c66dfSDavid Wu 	PIN_BANK(0, 32, "gpio0"),
3578d23c66dfSDavid Wu 	PIN_BANK(1, 32, "gpio1"),
3579d23c66dfSDavid Wu 	PIN_BANK(2, 32, "gpio2"),
3580d23c66dfSDavid Wu 	PIN_BANK(3, 32, "gpio3"),
3581d23c66dfSDavid Wu };
3582d23c66dfSDavid Wu 
3583d23c66dfSDavid Wu static struct rockchip_pin_ctrl rk3128_pin_ctrl = {
3584d23c66dfSDavid Wu 		.pin_banks		= rk3128_pin_banks,
3585d23c66dfSDavid Wu 		.nr_banks		= ARRAY_SIZE(rk3128_pin_banks),
3586d23c66dfSDavid Wu 		.label			= "RK3128-GPIO",
3587d23c66dfSDavid Wu 		.type			= RK3128,
3588d23c66dfSDavid Wu 		.grf_mux_offset		= 0xa8,
3589d23c66dfSDavid Wu 		.iomux_recalced		= rk3128_mux_recalced_data,
3590d23c66dfSDavid Wu 		.niomux_recalced	= ARRAY_SIZE(rk3128_mux_recalced_data),
3591d23c66dfSDavid Wu 		.iomux_routes		= rk3128_mux_route_data,
3592d23c66dfSDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3128_mux_route_data),
3593d23c66dfSDavid Wu 		.pull_calc_reg		= rk3128_calc_pull_reg_and_bit,
3594d23c66dfSDavid Wu };
3595d23c66dfSDavid Wu 
3596d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3188_pin_banks[] = {
3597fc72c923SHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0),
3598d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3599d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3600d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3601d3e51161SHeiko Stübner };
3602d3e51161SHeiko Stübner 
3603d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
3604d3e51161SHeiko Stübner 		.pin_banks		= rk3188_pin_banks,
3605d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3188_pin_banks),
3606d3e51161SHeiko Stübner 		.label			= "RK3188-GPIO",
3607a282926dSHeiko Stübner 		.type			= RK3188,
360895ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0x60,
36096ca5274dSHeiko Stübner 		.pull_calc_reg		= rk3188_calc_pull_reg_and_bit,
3610d3e51161SHeiko Stübner };
3611d3e51161SHeiko Stübner 
3612fea0fe60SJeffy Chen static struct rockchip_pin_bank rk3228_pin_banks[] = {
3613fea0fe60SJeffy Chen 	PIN_BANK(0, 32, "gpio0"),
3614fea0fe60SJeffy Chen 	PIN_BANK(1, 32, "gpio1"),
3615fea0fe60SJeffy Chen 	PIN_BANK(2, 32, "gpio2"),
3616fea0fe60SJeffy Chen 	PIN_BANK(3, 32, "gpio3"),
3617fea0fe60SJeffy Chen };
3618fea0fe60SJeffy Chen 
3619fea0fe60SJeffy Chen static struct rockchip_pin_ctrl rk3228_pin_ctrl = {
3620fea0fe60SJeffy Chen 		.pin_banks		= rk3228_pin_banks,
3621fea0fe60SJeffy Chen 		.nr_banks		= ARRAY_SIZE(rk3228_pin_banks),
3622fea0fe60SJeffy Chen 		.label			= "RK3228-GPIO",
3623fea0fe60SJeffy Chen 		.type			= RK3288,
3624fea0fe60SJeffy Chen 		.grf_mux_offset		= 0x0,
3625d4970ee0SDavid Wu 		.iomux_routes		= rk3228_mux_route_data,
3626d4970ee0SDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3228_mux_route_data),
3627fea0fe60SJeffy Chen 		.pull_calc_reg		= rk3228_calc_pull_reg_and_bit,
3628fea0fe60SJeffy Chen 		.drv_calc_reg		= rk3228_calc_drv_reg_and_bit,
3629fea0fe60SJeffy Chen };
3630fea0fe60SJeffy Chen 
3631304f077dSHeiko Stübner static struct rockchip_pin_bank rk3288_pin_banks[] = {
3632304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
3633304f077dSHeiko Stübner 					     IOMUX_SOURCE_PMU,
3634304f077dSHeiko Stübner 					     IOMUX_SOURCE_PMU,
3635304f077dSHeiko Stübner 					     IOMUX_UNROUTED
3636304f077dSHeiko Stübner 			    ),
3637304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED,
3638304f077dSHeiko Stübner 					     IOMUX_UNROUTED,
3639304f077dSHeiko Stübner 					     IOMUX_UNROUTED,
3640304f077dSHeiko Stübner 					     0
3641304f077dSHeiko Stübner 			    ),
3642304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED),
3643304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT),
3644304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
3645304f077dSHeiko Stübner 					     IOMUX_WIDTH_4BIT,
3646304f077dSHeiko Stübner 					     0,
3647304f077dSHeiko Stübner 					     0
3648304f077dSHeiko Stübner 			    ),
3649304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED,
3650304f077dSHeiko Stübner 					     0,
3651304f077dSHeiko Stübner 					     0,
3652304f077dSHeiko Stübner 					     IOMUX_UNROUTED
3653304f077dSHeiko Stübner 			    ),
3654304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED),
3655304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0,
3656304f077dSHeiko Stübner 					     0,
3657304f077dSHeiko Stübner 					     IOMUX_WIDTH_4BIT,
3658304f077dSHeiko Stübner 					     IOMUX_UNROUTED
3659304f077dSHeiko Stübner 			    ),
3660304f077dSHeiko Stübner 	PIN_BANK(8, 16, "gpio8"),
3661304f077dSHeiko Stübner };
3662304f077dSHeiko Stübner 
3663304f077dSHeiko Stübner static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
3664304f077dSHeiko Stübner 		.pin_banks		= rk3288_pin_banks,
3665304f077dSHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3288_pin_banks),
3666304f077dSHeiko Stübner 		.label			= "RK3288-GPIO",
366766d750e1SHeiko Stübner 		.type			= RK3288,
3668304f077dSHeiko Stübner 		.grf_mux_offset		= 0x0,
3669304f077dSHeiko Stübner 		.pmu_mux_offset		= 0x84,
36704e96fd30SHeiko Stuebner 		.iomux_routes		= rk3288_mux_route_data,
36714e96fd30SHeiko Stuebner 		.niomux_routes		= ARRAY_SIZE(rk3288_mux_route_data),
3672304f077dSHeiko Stübner 		.pull_calc_reg		= rk3288_calc_pull_reg_and_bit,
3673ef17f69fSHeiko Stübner 		.drv_calc_reg		= rk3288_calc_drv_reg_and_bit,
3674304f077dSHeiko Stübner };
3675304f077dSHeiko Stübner 
36763818e4a7Sdavid.wu static struct rockchip_pin_bank rk3328_pin_banks[] = {
36773818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0),
36783818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
36793818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0,
3680c04c3fa6SDavid Wu 			     IOMUX_WIDTH_3BIT,
3681c04c3fa6SDavid Wu 			     IOMUX_WIDTH_3BIT,
36823818e4a7Sdavid.wu 			     0),
36833818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
36843818e4a7Sdavid.wu 			     IOMUX_WIDTH_3BIT,
3685c04c3fa6SDavid Wu 			     IOMUX_WIDTH_3BIT,
36863818e4a7Sdavid.wu 			     0,
36873818e4a7Sdavid.wu 			     0),
36883818e4a7Sdavid.wu };
36893818e4a7Sdavid.wu 
36903818e4a7Sdavid.wu static struct rockchip_pin_ctrl rk3328_pin_ctrl = {
36913818e4a7Sdavid.wu 		.pin_banks		= rk3328_pin_banks,
36923818e4a7Sdavid.wu 		.nr_banks		= ARRAY_SIZE(rk3328_pin_banks),
36933818e4a7Sdavid.wu 		.label			= "RK3328-GPIO",
36943818e4a7Sdavid.wu 		.type			= RK3288,
36953818e4a7Sdavid.wu 		.grf_mux_offset		= 0x0,
3696c04c3fa6SDavid Wu 		.iomux_recalced		= rk3328_mux_recalced_data,
3697c04c3fa6SDavid Wu 		.niomux_recalced	= ARRAY_SIZE(rk3328_mux_recalced_data),
3698cedc964aSDavid Wu 		.iomux_routes		= rk3328_mux_route_data,
3699cedc964aSDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3328_mux_route_data),
37003818e4a7Sdavid.wu 		.pull_calc_reg		= rk3228_calc_pull_reg_and_bit,
37013818e4a7Sdavid.wu 		.drv_calc_reg		= rk3228_calc_drv_reg_and_bit,
3702728d3f5aSdavid.wu 		.schmitt_calc_reg	= rk3328_calc_schmitt_reg_and_bit,
37033818e4a7Sdavid.wu };
37043818e4a7Sdavid.wu 
3705daecdc66SHeiko Stübner static struct rockchip_pin_bank rk3368_pin_banks[] = {
3706daecdc66SHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
3707daecdc66SHeiko Stübner 					     IOMUX_SOURCE_PMU,
3708daecdc66SHeiko Stübner 					     IOMUX_SOURCE_PMU,
3709daecdc66SHeiko Stübner 					     IOMUX_SOURCE_PMU
3710daecdc66SHeiko Stübner 			    ),
3711daecdc66SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3712daecdc66SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3713daecdc66SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3714daecdc66SHeiko Stübner };
3715daecdc66SHeiko Stübner 
3716daecdc66SHeiko Stübner static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
3717daecdc66SHeiko Stübner 		.pin_banks		= rk3368_pin_banks,
3718daecdc66SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3368_pin_banks),
3719daecdc66SHeiko Stübner 		.label			= "RK3368-GPIO",
3720daecdc66SHeiko Stübner 		.type			= RK3368,
3721daecdc66SHeiko Stübner 		.grf_mux_offset		= 0x0,
3722daecdc66SHeiko Stübner 		.pmu_mux_offset		= 0x0,
3723daecdc66SHeiko Stübner 		.pull_calc_reg		= rk3368_calc_pull_reg_and_bit,
3724daecdc66SHeiko Stübner 		.drv_calc_reg		= rk3368_calc_drv_reg_and_bit,
3725daecdc66SHeiko Stübner };
3726daecdc66SHeiko Stübner 
3727b6c23275SDavid Wu static struct rockchip_pin_bank rk3399_pin_banks[] = {
37283ba6767aSDavid Wu 	PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0",
37293ba6767aSDavid Wu 							 IOMUX_SOURCE_PMU,
3730b6c23275SDavid Wu 							 IOMUX_SOURCE_PMU,
3731b6c23275SDavid Wu 							 IOMUX_SOURCE_PMU,
3732b6c23275SDavid Wu 							 IOMUX_SOURCE_PMU,
3733b6c23275SDavid Wu 							 DRV_TYPE_IO_1V8_ONLY,
3734b6c23275SDavid Wu 							 DRV_TYPE_IO_1V8_ONLY,
3735b6c23275SDavid Wu 							 DRV_TYPE_IO_DEFAULT,
3736b6c23275SDavid Wu 							 DRV_TYPE_IO_DEFAULT,
3737c437f65cSDavid Wu 							 0x80,
3738c437f65cSDavid Wu 							 0x88,
3739b6c23275SDavid Wu 							 -1,
37403ba6767aSDavid Wu 							 -1,
37413ba6767aSDavid Wu 							 PULL_TYPE_IO_1V8_ONLY,
37423ba6767aSDavid Wu 							 PULL_TYPE_IO_1V8_ONLY,
37433ba6767aSDavid Wu 							 PULL_TYPE_IO_DEFAULT,
37443ba6767aSDavid Wu 							 PULL_TYPE_IO_DEFAULT
3745b6c23275SDavid Wu 							),
3746b6c23275SDavid Wu 	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
3747b6c23275SDavid Wu 					IOMUX_SOURCE_PMU,
3748b6c23275SDavid Wu 					IOMUX_SOURCE_PMU,
3749b6c23275SDavid Wu 					IOMUX_SOURCE_PMU,
3750b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3751b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3752b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3753b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3754c437f65cSDavid Wu 					0xa0,
3755c437f65cSDavid Wu 					0xa8,
3756c437f65cSDavid Wu 					0xb0,
3757c437f65cSDavid Wu 					0xb8
3758b6c23275SDavid Wu 					),
37593ba6767aSDavid Wu 	PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
3760b6c23275SDavid Wu 				      DRV_TYPE_IO_1V8_OR_3V0,
3761b6c23275SDavid Wu 				      DRV_TYPE_IO_1V8_ONLY,
37623ba6767aSDavid Wu 				      DRV_TYPE_IO_1V8_ONLY,
37633ba6767aSDavid Wu 				      PULL_TYPE_IO_DEFAULT,
37643ba6767aSDavid Wu 				      PULL_TYPE_IO_DEFAULT,
37653ba6767aSDavid Wu 				      PULL_TYPE_IO_1V8_ONLY,
37663ba6767aSDavid Wu 				      PULL_TYPE_IO_1V8_ONLY
3767b6c23275SDavid Wu 				      ),
3768b6c23275SDavid Wu 	PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
3769b6c23275SDavid Wu 			   DRV_TYPE_IO_3V3_ONLY,
3770b6c23275SDavid Wu 			   DRV_TYPE_IO_3V3_ONLY,
3771b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_OR_3V0
3772b6c23275SDavid Wu 			   ),
3773b6c23275SDavid Wu 	PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0,
3774b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_3V0_AUTO,
3775b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_OR_3V0,
3776b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_OR_3V0
3777b6c23275SDavid Wu 			   ),
3778b6c23275SDavid Wu };
3779b6c23275SDavid Wu 
3780b6c23275SDavid Wu static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
3781b6c23275SDavid Wu 		.pin_banks		= rk3399_pin_banks,
3782b6c23275SDavid Wu 		.nr_banks		= ARRAY_SIZE(rk3399_pin_banks),
3783b6c23275SDavid Wu 		.label			= "RK3399-GPIO",
3784b6c23275SDavid Wu 		.type			= RK3399,
3785b6c23275SDavid Wu 		.grf_mux_offset		= 0xe000,
3786b6c23275SDavid Wu 		.pmu_mux_offset		= 0x0,
3787b6c23275SDavid Wu 		.grf_drv_offset		= 0xe100,
3788b6c23275SDavid Wu 		.pmu_drv_offset		= 0x80,
3789accc1ce7SDavid Wu 		.iomux_routes		= rk3399_mux_route_data,
3790accc1ce7SDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3399_mux_route_data),
3791b6c23275SDavid Wu 		.pull_calc_reg		= rk3399_calc_pull_reg_and_bit,
3792b6c23275SDavid Wu 		.drv_calc_reg		= rk3399_calc_drv_reg_and_bit,
3793b6c23275SDavid Wu };
3794daecdc66SHeiko Stübner 
3795d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[] = {
379687065ca9SDavid Wu 	{ .compatible = "rockchip,px30-pinctrl",
379787065ca9SDavid Wu 		.data = &px30_pin_ctrl },
3798b9c6dcabSAndy Yan 	{ .compatible = "rockchip,rv1108-pinctrl",
3799cdbbd26fSMasahiro Yamada 		.data = &rv1108_pin_ctrl },
3800d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk2928-pinctrl",
3801cdbbd26fSMasahiro Yamada 		.data = &rk2928_pin_ctrl },
3802c5ce7670SXing Zheng 	{ .compatible = "rockchip,rk3036-pinctrl",
3803cdbbd26fSMasahiro Yamada 		.data = &rk3036_pin_ctrl },
3804d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3066a-pinctrl",
3805cdbbd26fSMasahiro Yamada 		.data = &rk3066a_pin_ctrl },
3806d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3066b-pinctrl",
3807cdbbd26fSMasahiro Yamada 		.data = &rk3066b_pin_ctrl },
3808d23c66dfSDavid Wu 	{ .compatible = "rockchip,rk3128-pinctrl",
3809d23c66dfSDavid Wu 		.data = (void *)&rk3128_pin_ctrl },
3810d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3188-pinctrl",
3811cdbbd26fSMasahiro Yamada 		.data = &rk3188_pin_ctrl },
3812fea0fe60SJeffy Chen 	{ .compatible = "rockchip,rk3228-pinctrl",
3813cdbbd26fSMasahiro Yamada 		.data = &rk3228_pin_ctrl },
3814304f077dSHeiko Stübner 	{ .compatible = "rockchip,rk3288-pinctrl",
3815cdbbd26fSMasahiro Yamada 		.data = &rk3288_pin_ctrl },
38163818e4a7Sdavid.wu 	{ .compatible = "rockchip,rk3328-pinctrl",
3817cdbbd26fSMasahiro Yamada 		.data = &rk3328_pin_ctrl },
3818daecdc66SHeiko Stübner 	{ .compatible = "rockchip,rk3368-pinctrl",
3819cdbbd26fSMasahiro Yamada 		.data = &rk3368_pin_ctrl },
3820b6c23275SDavid Wu 	{ .compatible = "rockchip,rk3399-pinctrl",
3821cdbbd26fSMasahiro Yamada 		.data = &rk3399_pin_ctrl },
3822d3e51161SHeiko Stübner 	{},
3823d3e51161SHeiko Stübner };
3824d3e51161SHeiko Stübner 
3825d3e51161SHeiko Stübner static struct platform_driver rockchip_pinctrl_driver = {
3826d3e51161SHeiko Stübner 	.probe		= rockchip_pinctrl_probe,
3827d3e51161SHeiko Stübner 	.driver = {
3828d3e51161SHeiko Stübner 		.name	= "rockchip-pinctrl",
38299198f509SChris Zhong 		.pm = &rockchip_pinctrl_dev_pm_ops,
38300be9e70dSAxel Lin 		.of_match_table = rockchip_pinctrl_dt_match,
3831d3e51161SHeiko Stübner 	},
3832d3e51161SHeiko Stübner };
3833d3e51161SHeiko Stübner 
3834d3e51161SHeiko Stübner static int __init rockchip_pinctrl_drv_register(void)
3835d3e51161SHeiko Stübner {
3836d3e51161SHeiko Stübner 	return platform_driver_register(&rockchip_pinctrl_driver);
3837d3e51161SHeiko Stübner }
3838d3e51161SHeiko Stübner postcore_initcall(rockchip_pinctrl_drv_register);
3839