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>
30d3e51161SHeiko Stübner #include <linux/gpio.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 {
62*87065ca9SDavid 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) {
504d3e51161SHeiko Stübner 		dev_err(info->dev, "unable to find group for node %s\n",
505d3e51161SHeiko Stübner 			np->name);
506d3e51161SHeiko Stübner 		return -EINVAL;
507d3e51161SHeiko Stübner 	}
508d3e51161SHeiko Stübner 
509d3e51161SHeiko Stübner 	map_num += grp->npins;
510d3e51161SHeiko Stübner 	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
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 
705*87065ca9SDavid Wu static struct rockchip_mux_route_data px30_mux_route_data[] = {
706*87065ca9SDavid Wu 	{
707*87065ca9SDavid Wu 		/* cif-d2m0 */
708*87065ca9SDavid Wu 		.bank_num = 2,
709*87065ca9SDavid Wu 		.pin = 0,
710*87065ca9SDavid Wu 		.func = 1,
711*87065ca9SDavid Wu 		.route_offset = 0x184,
712*87065ca9SDavid Wu 		.route_val = BIT(16 + 7),
713*87065ca9SDavid Wu 	}, {
714*87065ca9SDavid Wu 		/* cif-d2m1 */
715*87065ca9SDavid Wu 		.bank_num = 3,
716*87065ca9SDavid Wu 		.pin = 3,
717*87065ca9SDavid Wu 		.func = 3,
718*87065ca9SDavid Wu 		.route_offset = 0x184,
719*87065ca9SDavid Wu 		.route_val = BIT(16 + 7) | BIT(7),
720*87065ca9SDavid Wu 	}, {
721*87065ca9SDavid Wu 		/* pdm-m0 */
722*87065ca9SDavid Wu 		.bank_num = 3,
723*87065ca9SDavid Wu 		.pin = 22,
724*87065ca9SDavid Wu 		.func = 2,
725*87065ca9SDavid Wu 		.route_offset = 0x184,
726*87065ca9SDavid Wu 		.route_val = BIT(16 + 8),
727*87065ca9SDavid Wu 	}, {
728*87065ca9SDavid Wu 		/* pdm-m1 */
729*87065ca9SDavid Wu 		.bank_num = 2,
730*87065ca9SDavid Wu 		.pin = 22,
731*87065ca9SDavid Wu 		.func = 1,
732*87065ca9SDavid Wu 		.route_offset = 0x184,
733*87065ca9SDavid Wu 		.route_val = BIT(16 + 8) | BIT(8),
734*87065ca9SDavid Wu 	}, {
735*87065ca9SDavid Wu 		/* uart2-rxm0 */
736*87065ca9SDavid Wu 		.bank_num = 1,
737*87065ca9SDavid Wu 		.pin = 27,
738*87065ca9SDavid Wu 		.func = 2,
739*87065ca9SDavid Wu 		.route_offset = 0x184,
740*87065ca9SDavid Wu 		.route_val = BIT(16 + 10),
741*87065ca9SDavid Wu 	}, {
742*87065ca9SDavid Wu 		/* uart2-rxm1 */
743*87065ca9SDavid Wu 		.bank_num = 2,
744*87065ca9SDavid Wu 		.pin = 14,
745*87065ca9SDavid Wu 		.func = 2,
746*87065ca9SDavid Wu 		.route_offset = 0x184,
747*87065ca9SDavid Wu 		.route_val = BIT(16 + 10) | BIT(10),
748*87065ca9SDavid Wu 	}, {
749*87065ca9SDavid Wu 		/* uart3-rxm0 */
750*87065ca9SDavid Wu 		.bank_num = 0,
751*87065ca9SDavid Wu 		.pin = 17,
752*87065ca9SDavid Wu 		.func = 2,
753*87065ca9SDavid Wu 		.route_offset = 0x184,
754*87065ca9SDavid Wu 		.route_val = BIT(16 + 9),
755*87065ca9SDavid Wu 	}, {
756*87065ca9SDavid Wu 		/* uart3-rxm1 */
757*87065ca9SDavid Wu 		.bank_num = 1,
758*87065ca9SDavid Wu 		.pin = 15,
759*87065ca9SDavid Wu 		.func = 2,
760*87065ca9SDavid Wu 		.route_offset = 0x184,
761*87065ca9SDavid Wu 		.route_val = BIT(16 + 9) | BIT(9),
762*87065ca9SDavid Wu 	},
763*87065ca9SDavid Wu };
764*87065ca9SDavid 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 
1266*87065ca9SDavid Wu #define PX30_PULL_PMU_OFFSET		0x10
1267*87065ca9SDavid Wu #define PX30_PULL_GRF_OFFSET		0x60
1268*87065ca9SDavid Wu #define PX30_PULL_BITS_PER_PIN		2
1269*87065ca9SDavid Wu #define PX30_PULL_PINS_PER_REG		8
1270*87065ca9SDavid Wu #define PX30_PULL_BANK_STRIDE		16
1271*87065ca9SDavid Wu 
1272*87065ca9SDavid Wu static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
1273*87065ca9SDavid Wu 				       int pin_num, struct regmap **regmap,
1274*87065ca9SDavid Wu 				       int *reg, u8 *bit)
1275*87065ca9SDavid Wu {
1276*87065ca9SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
1277*87065ca9SDavid Wu 
1278*87065ca9SDavid Wu 	/* The first 32 pins of the first bank are located in PMU */
1279*87065ca9SDavid Wu 	if (bank->bank_num == 0) {
1280*87065ca9SDavid Wu 		*regmap = info->regmap_pmu;
1281*87065ca9SDavid Wu 		*reg = PX30_PULL_PMU_OFFSET;
1282*87065ca9SDavid Wu 	} else {
1283*87065ca9SDavid Wu 		*regmap = info->regmap_base;
1284*87065ca9SDavid Wu 		*reg = PX30_PULL_GRF_OFFSET;
1285*87065ca9SDavid Wu 
1286*87065ca9SDavid Wu 		/* correct the offset, as we're starting with the 2nd bank */
1287*87065ca9SDavid Wu 		*reg -= 0x10;
1288*87065ca9SDavid Wu 		*reg += bank->bank_num * PX30_PULL_BANK_STRIDE;
1289*87065ca9SDavid Wu 	}
1290*87065ca9SDavid Wu 
1291*87065ca9SDavid Wu 	*reg += ((pin_num / PX30_PULL_PINS_PER_REG) * 4);
1292*87065ca9SDavid Wu 	*bit = (pin_num % PX30_PULL_PINS_PER_REG);
1293*87065ca9SDavid Wu 	*bit *= PX30_PULL_BITS_PER_PIN;
1294*87065ca9SDavid Wu }
1295*87065ca9SDavid Wu 
1296*87065ca9SDavid Wu #define PX30_DRV_PMU_OFFSET		0x20
1297*87065ca9SDavid Wu #define PX30_DRV_GRF_OFFSET		0xf0
1298*87065ca9SDavid Wu #define PX30_DRV_BITS_PER_PIN		2
1299*87065ca9SDavid Wu #define PX30_DRV_PINS_PER_REG		8
1300*87065ca9SDavid Wu #define PX30_DRV_BANK_STRIDE		16
1301*87065ca9SDavid Wu 
1302*87065ca9SDavid Wu static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
1303*87065ca9SDavid Wu 				      int pin_num, struct regmap **regmap,
1304*87065ca9SDavid Wu 				      int *reg, u8 *bit)
1305*87065ca9SDavid Wu {
1306*87065ca9SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
1307*87065ca9SDavid Wu 
1308*87065ca9SDavid Wu 	/* The first 32 pins of the first bank are located in PMU */
1309*87065ca9SDavid Wu 	if (bank->bank_num == 0) {
1310*87065ca9SDavid Wu 		*regmap = info->regmap_pmu;
1311*87065ca9SDavid Wu 		*reg = PX30_DRV_PMU_OFFSET;
1312*87065ca9SDavid Wu 	} else {
1313*87065ca9SDavid Wu 		*regmap = info->regmap_base;
1314*87065ca9SDavid Wu 		*reg = PX30_DRV_GRF_OFFSET;
1315*87065ca9SDavid Wu 
1316*87065ca9SDavid Wu 		/* correct the offset, as we're starting with the 2nd bank */
1317*87065ca9SDavid Wu 		*reg -= 0x10;
1318*87065ca9SDavid Wu 		*reg += bank->bank_num * PX30_DRV_BANK_STRIDE;
1319*87065ca9SDavid Wu 	}
1320*87065ca9SDavid Wu 
1321*87065ca9SDavid Wu 	*reg += ((pin_num / PX30_DRV_PINS_PER_REG) * 4);
1322*87065ca9SDavid Wu 	*bit = (pin_num % PX30_DRV_PINS_PER_REG);
1323*87065ca9SDavid Wu 	*bit *= PX30_DRV_BITS_PER_PIN;
1324*87065ca9SDavid Wu }
1325*87065ca9SDavid Wu 
1326*87065ca9SDavid Wu #define PX30_SCHMITT_PMU_OFFSET			0x38
1327*87065ca9SDavid Wu #define PX30_SCHMITT_GRF_OFFSET			0xc0
1328*87065ca9SDavid Wu #define PX30_SCHMITT_PINS_PER_PMU_REG		16
1329*87065ca9SDavid Wu #define PX30_SCHMITT_BANK_STRIDE		16
1330*87065ca9SDavid Wu #define PX30_SCHMITT_PINS_PER_GRF_REG		8
1331*87065ca9SDavid Wu 
1332*87065ca9SDavid Wu static int px30_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
1333*87065ca9SDavid Wu 					 int pin_num,
1334*87065ca9SDavid Wu 					 struct regmap **regmap,
1335*87065ca9SDavid Wu 					 int *reg, u8 *bit)
1336*87065ca9SDavid Wu {
1337*87065ca9SDavid Wu 	struct rockchip_pinctrl *info = bank->drvdata;
1338*87065ca9SDavid Wu 	int pins_per_reg;
1339*87065ca9SDavid Wu 
1340*87065ca9SDavid Wu 	if (bank->bank_num == 0) {
1341*87065ca9SDavid Wu 		*regmap = info->regmap_pmu;
1342*87065ca9SDavid Wu 		*reg = PX30_SCHMITT_PMU_OFFSET;
1343*87065ca9SDavid Wu 		pins_per_reg = PX30_SCHMITT_PINS_PER_PMU_REG;
1344*87065ca9SDavid Wu 	} else {
1345*87065ca9SDavid Wu 		*regmap = info->regmap_base;
1346*87065ca9SDavid Wu 		*reg = PX30_SCHMITT_GRF_OFFSET;
1347*87065ca9SDavid Wu 		pins_per_reg = PX30_SCHMITT_PINS_PER_GRF_REG;
1348*87065ca9SDavid Wu 		*reg += (bank->bank_num  - 1) * PX30_SCHMITT_BANK_STRIDE;
1349*87065ca9SDavid Wu 	}
1350*87065ca9SDavid Wu 
1351*87065ca9SDavid Wu 	*reg += ((pin_num / pins_per_reg) * 4);
1352*87065ca9SDavid Wu 	*bit = pin_num % pins_per_reg;
1353*87065ca9SDavid Wu 
1354*87065ca9SDavid Wu 	return 0;
1355*87065ca9SDavid Wu }
1356*87065ca9SDavid 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;
1953*87065ca9SDavid 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;
1997*87065ca9SDavid 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;
2260*87065ca9SDavid 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 
2457d3e51161SHeiko Stübner 	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
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 
2476d3e51161SHeiko Stübner 	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
2477d3e51161SHeiko Stübner 						GFP_KERNEL);
2478d3e51161SHeiko Stübner 	grp->data = devm_kzalloc(info->dev, grp->npins *
2479d3e51161SHeiko Stübner 					  sizeof(struct rockchip_pin_config),
2480d3e51161SHeiko Stübner 					GFP_KERNEL);
2481d3e51161SHeiko Stübner 	if (!grp->pins || !grp->data)
2482d3e51161SHeiko Stübner 		return -ENOMEM;
2483d3e51161SHeiko Stübner 
2484d3e51161SHeiko Stübner 	for (i = 0, j = 0; i < size; i += 4, j++) {
2485d3e51161SHeiko Stübner 		const __be32 *phandle;
2486d3e51161SHeiko Stübner 		struct device_node *np_config;
2487d3e51161SHeiko Stübner 
2488d3e51161SHeiko Stübner 		num = be32_to_cpu(*list++);
2489d3e51161SHeiko Stübner 		bank = bank_num_to_bank(info, num);
2490d3e51161SHeiko Stübner 		if (IS_ERR(bank))
2491d3e51161SHeiko Stübner 			return PTR_ERR(bank);
2492d3e51161SHeiko Stübner 
2493d3e51161SHeiko Stübner 		grp->pins[j] = bank->pin_base + be32_to_cpu(*list++);
2494d3e51161SHeiko Stübner 		grp->data[j].func = be32_to_cpu(*list++);
2495d3e51161SHeiko Stübner 
2496d3e51161SHeiko Stübner 		phandle = list++;
2497d3e51161SHeiko Stübner 		if (!phandle)
2498d3e51161SHeiko Stübner 			return -EINVAL;
2499d3e51161SHeiko Stübner 
2500d3e51161SHeiko Stübner 		np_config = of_find_node_by_phandle(be32_to_cpup(phandle));
2501dd4d01f7SSoren Brinkmann 		ret = pinconf_generic_parse_dt_config(np_config, NULL,
2502d3e51161SHeiko Stübner 				&grp->data[j].configs, &grp->data[j].nconfigs);
2503d3e51161SHeiko Stübner 		if (ret)
2504d3e51161SHeiko Stübner 			return ret;
2505d3e51161SHeiko Stübner 	}
2506d3e51161SHeiko Stübner 
2507d3e51161SHeiko Stübner 	return 0;
2508d3e51161SHeiko Stübner }
2509d3e51161SHeiko Stübner 
2510d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_functions(struct device_node *np,
2511d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info,
2512d3e51161SHeiko Stübner 						u32 index)
2513d3e51161SHeiko Stübner {
2514d3e51161SHeiko Stübner 	struct device_node *child;
2515d3e51161SHeiko Stübner 	struct rockchip_pmx_func *func;
2516d3e51161SHeiko Stübner 	struct rockchip_pin_group *grp;
2517d3e51161SHeiko Stübner 	int ret;
2518d3e51161SHeiko Stübner 	static u32 grp_index;
2519d3e51161SHeiko Stübner 	u32 i = 0;
2520d3e51161SHeiko Stübner 
2521d3e51161SHeiko Stübner 	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
2522d3e51161SHeiko Stübner 
2523d3e51161SHeiko Stübner 	func = &info->functions[index];
2524d3e51161SHeiko Stübner 
2525d3e51161SHeiko Stübner 	/* Initialise function */
2526d3e51161SHeiko Stübner 	func->name = np->name;
2527d3e51161SHeiko Stübner 	func->ngroups = of_get_child_count(np);
2528d3e51161SHeiko Stübner 	if (func->ngroups <= 0)
2529d3e51161SHeiko Stübner 		return 0;
2530d3e51161SHeiko Stübner 
2531d3e51161SHeiko Stübner 	func->groups = devm_kzalloc(info->dev,
2532d3e51161SHeiko Stübner 			func->ngroups * sizeof(char *), GFP_KERNEL);
2533d3e51161SHeiko Stübner 	if (!func->groups)
2534d3e51161SHeiko Stübner 		return -ENOMEM;
2535d3e51161SHeiko Stübner 
2536d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
2537d3e51161SHeiko Stübner 		func->groups[i] = child->name;
2538d3e51161SHeiko Stübner 		grp = &info->groups[grp_index++];
2539d3e51161SHeiko Stübner 		ret = rockchip_pinctrl_parse_groups(child, grp, info, i++);
2540f7a81b7fSJulia Lawall 		if (ret) {
2541f7a81b7fSJulia Lawall 			of_node_put(child);
2542d3e51161SHeiko Stübner 			return ret;
2543d3e51161SHeiko Stübner 		}
2544f7a81b7fSJulia Lawall 	}
2545d3e51161SHeiko Stübner 
2546d3e51161SHeiko Stübner 	return 0;
2547d3e51161SHeiko Stübner }
2548d3e51161SHeiko Stübner 
2549d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_dt(struct platform_device *pdev,
2550d3e51161SHeiko Stübner 					      struct rockchip_pinctrl *info)
2551d3e51161SHeiko Stübner {
2552d3e51161SHeiko Stübner 	struct device *dev = &pdev->dev;
2553d3e51161SHeiko Stübner 	struct device_node *np = dev->of_node;
2554d3e51161SHeiko Stübner 	struct device_node *child;
2555d3e51161SHeiko Stübner 	int ret;
2556d3e51161SHeiko Stübner 	int i;
2557d3e51161SHeiko Stübner 
2558d3e51161SHeiko Stübner 	rockchip_pinctrl_child_count(info, np);
2559d3e51161SHeiko Stübner 
2560d3e51161SHeiko Stübner 	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
2561d3e51161SHeiko Stübner 	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
2562d3e51161SHeiko Stübner 
2563d3e51161SHeiko Stübner 	info->functions = devm_kzalloc(dev, info->nfunctions *
2564d3e51161SHeiko Stübner 					      sizeof(struct rockchip_pmx_func),
2565d3e51161SHeiko Stübner 					      GFP_KERNEL);
256698c8ee73SMarkus Elfring 	if (!info->functions)
2567d3e51161SHeiko Stübner 		return -EINVAL;
2568d3e51161SHeiko Stübner 
2569d3e51161SHeiko Stübner 	info->groups = devm_kzalloc(dev, info->ngroups *
2570d3e51161SHeiko Stübner 					    sizeof(struct rockchip_pin_group),
2571d3e51161SHeiko Stübner 					    GFP_KERNEL);
257298c8ee73SMarkus Elfring 	if (!info->groups)
2573d3e51161SHeiko Stübner 		return -EINVAL;
2574d3e51161SHeiko Stübner 
2575d3e51161SHeiko Stübner 	i = 0;
2576d3e51161SHeiko Stübner 
2577d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
257865fca613SHeiko Stübner 		if (of_match_node(rockchip_bank_match, child))
2579d3e51161SHeiko Stübner 			continue;
258065fca613SHeiko Stübner 
2581d3e51161SHeiko Stübner 		ret = rockchip_pinctrl_parse_functions(child, info, i++);
2582d3e51161SHeiko Stübner 		if (ret) {
2583d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "failed to parse function\n");
2584f7a81b7fSJulia Lawall 			of_node_put(child);
2585d3e51161SHeiko Stübner 			return ret;
2586d3e51161SHeiko Stübner 		}
2587d3e51161SHeiko Stübner 	}
2588d3e51161SHeiko Stübner 
2589d3e51161SHeiko Stübner 	return 0;
2590d3e51161SHeiko Stübner }
2591d3e51161SHeiko Stübner 
2592d3e51161SHeiko Stübner static int rockchip_pinctrl_register(struct platform_device *pdev,
2593d3e51161SHeiko Stübner 					struct rockchip_pinctrl *info)
2594d3e51161SHeiko Stübner {
2595d3e51161SHeiko Stübner 	struct pinctrl_desc *ctrldesc = &info->pctl;
2596d3e51161SHeiko Stübner 	struct pinctrl_pin_desc *pindesc, *pdesc;
2597d3e51161SHeiko Stübner 	struct rockchip_pin_bank *pin_bank;
2598d3e51161SHeiko Stübner 	int pin, bank, ret;
2599d3e51161SHeiko Stübner 	int k;
2600d3e51161SHeiko Stübner 
2601d3e51161SHeiko Stübner 	ctrldesc->name = "rockchip-pinctrl";
2602d3e51161SHeiko Stübner 	ctrldesc->owner = THIS_MODULE;
2603d3e51161SHeiko Stübner 	ctrldesc->pctlops = &rockchip_pctrl_ops;
2604d3e51161SHeiko Stübner 	ctrldesc->pmxops = &rockchip_pmx_ops;
2605d3e51161SHeiko Stübner 	ctrldesc->confops = &rockchip_pinconf_ops;
2606d3e51161SHeiko Stübner 
2607d3e51161SHeiko Stübner 	pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
2608d3e51161SHeiko Stübner 			info->ctrl->nr_pins, GFP_KERNEL);
260998c8ee73SMarkus Elfring 	if (!pindesc)
2610d3e51161SHeiko Stübner 		return -ENOMEM;
261198c8ee73SMarkus Elfring 
2612d3e51161SHeiko Stübner 	ctrldesc->pins = pindesc;
2613d3e51161SHeiko Stübner 	ctrldesc->npins = info->ctrl->nr_pins;
2614d3e51161SHeiko Stübner 
2615d3e51161SHeiko Stübner 	pdesc = pindesc;
2616d3e51161SHeiko Stübner 	for (bank = 0 , k = 0; bank < info->ctrl->nr_banks; bank++) {
2617d3e51161SHeiko Stübner 		pin_bank = &info->ctrl->pin_banks[bank];
2618d3e51161SHeiko Stübner 		for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) {
2619d3e51161SHeiko Stübner 			pdesc->number = k;
2620d3e51161SHeiko Stübner 			pdesc->name = kasprintf(GFP_KERNEL, "%s-%d",
2621d3e51161SHeiko Stübner 						pin_bank->name, pin);
2622d3e51161SHeiko Stübner 			pdesc++;
2623d3e51161SHeiko Stübner 		}
2624d3e51161SHeiko Stübner 	}
2625d3e51161SHeiko Stübner 
26260fb7dcb1SDoug Anderson 	ret = rockchip_pinctrl_parse_dt(pdev, info);
26270fb7dcb1SDoug Anderson 	if (ret)
26280fb7dcb1SDoug Anderson 		return ret;
26290fb7dcb1SDoug Anderson 
26300085a2b4SLaxman Dewangan 	info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info);
2631323de9efSMasahiro Yamada 	if (IS_ERR(info->pctl_dev)) {
2632d3e51161SHeiko Stübner 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
2633323de9efSMasahiro Yamada 		return PTR_ERR(info->pctl_dev);
2634d3e51161SHeiko Stübner 	}
2635d3e51161SHeiko Stübner 
2636d3e51161SHeiko Stübner 	for (bank = 0; bank < info->ctrl->nr_banks; ++bank) {
2637d3e51161SHeiko Stübner 		pin_bank = &info->ctrl->pin_banks[bank];
2638d3e51161SHeiko Stübner 		pin_bank->grange.name = pin_bank->name;
2639d3e51161SHeiko Stübner 		pin_bank->grange.id = bank;
2640d3e51161SHeiko Stübner 		pin_bank->grange.pin_base = pin_bank->pin_base;
2641d3e51161SHeiko Stübner 		pin_bank->grange.base = pin_bank->gpio_chip.base;
2642d3e51161SHeiko Stübner 		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
2643d3e51161SHeiko Stübner 		pin_bank->grange.gc = &pin_bank->gpio_chip;
2644d3e51161SHeiko Stübner 		pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange);
2645d3e51161SHeiko Stübner 	}
2646d3e51161SHeiko Stübner 
2647d3e51161SHeiko Stübner 	return 0;
2648d3e51161SHeiko Stübner }
2649d3e51161SHeiko Stübner 
2650d3e51161SHeiko Stübner /*
2651d3e51161SHeiko Stübner  * GPIO handling
2652d3e51161SHeiko Stübner  */
2653d3e51161SHeiko Stübner 
2654d3e51161SHeiko Stübner static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
2655d3e51161SHeiko Stübner {
265603bf81f1SLinus Walleij 	struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
2657d3e51161SHeiko Stübner 	void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR;
2658d3e51161SHeiko Stübner 	unsigned long flags;
2659d3e51161SHeiko Stübner 	u32 data;
2660d3e51161SHeiko Stübner 
266107a06ae9SLin Huang 	clk_enable(bank->clk);
266270b7aa7aSJohn Keeping 	raw_spin_lock_irqsave(&bank->slock, flags);
2663d3e51161SHeiko Stübner 
2664d3e51161SHeiko Stübner 	data = readl(reg);
2665d3e51161SHeiko Stübner 	data &= ~BIT(offset);
2666d3e51161SHeiko Stübner 	if (value)
2667d3e51161SHeiko Stübner 		data |= BIT(offset);
2668d3e51161SHeiko Stübner 	writel(data, reg);
2669d3e51161SHeiko Stübner 
267070b7aa7aSJohn Keeping 	raw_spin_unlock_irqrestore(&bank->slock, flags);
267107a06ae9SLin Huang 	clk_disable(bank->clk);
2672d3e51161SHeiko Stübner }
2673d3e51161SHeiko Stübner 
2674d3e51161SHeiko Stübner /*
2675d3e51161SHeiko Stübner  * Returns the level of the pin for input direction and setting of the DR
2676d3e51161SHeiko Stübner  * register for output gpios.
2677d3e51161SHeiko Stübner  */
2678d3e51161SHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset)
2679d3e51161SHeiko Stübner {
268003bf81f1SLinus Walleij 	struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
2681d3e51161SHeiko Stübner 	u32 data;
2682d3e51161SHeiko Stübner 
268307a06ae9SLin Huang 	clk_enable(bank->clk);
2684d3e51161SHeiko Stübner 	data = readl(bank->reg_base + GPIO_EXT_PORT);
268507a06ae9SLin Huang 	clk_disable(bank->clk);
2686d3e51161SHeiko Stübner 	data >>= offset;
2687d3e51161SHeiko Stübner 	data &= 1;
2688d3e51161SHeiko Stübner 	return data;
2689d3e51161SHeiko Stübner }
2690d3e51161SHeiko Stübner 
2691d3e51161SHeiko Stübner /*
2692d3e51161SHeiko Stübner  * gpiolib gpio_direction_input callback function. The setting of the pin
269385dc397aSMarkus Elfring  * mux function as 'gpio input' will be handled by the pinctrl subsystem
2694d3e51161SHeiko Stübner  * interface.
2695d3e51161SHeiko Stübner  */
2696d3e51161SHeiko Stübner static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
2697d3e51161SHeiko Stübner {
2698d3e51161SHeiko Stübner 	return pinctrl_gpio_direction_input(gc->base + offset);
2699d3e51161SHeiko Stübner }
2700d3e51161SHeiko Stübner 
2701d3e51161SHeiko Stübner /*
2702d3e51161SHeiko Stübner  * gpiolib gpio_direction_output callback function. The setting of the pin
270385dc397aSMarkus Elfring  * mux function as 'gpio output' will be handled by the pinctrl subsystem
2704d3e51161SHeiko Stübner  * interface.
2705d3e51161SHeiko Stübner  */
2706d3e51161SHeiko Stübner static int rockchip_gpio_direction_output(struct gpio_chip *gc,
2707d3e51161SHeiko Stübner 					  unsigned offset, int value)
2708d3e51161SHeiko Stübner {
2709d3e51161SHeiko Stübner 	rockchip_gpio_set(gc, offset, value);
2710d3e51161SHeiko Stübner 	return pinctrl_gpio_direction_output(gc->base + offset);
2711d3e51161SHeiko Stübner }
2712d3e51161SHeiko Stübner 
2713d3e51161SHeiko Stübner /*
2714d3e51161SHeiko Stübner  * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
2715d3e51161SHeiko Stübner  * and a virtual IRQ, if not already present.
2716d3e51161SHeiko Stübner  */
2717d3e51161SHeiko Stübner static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
2718d3e51161SHeiko Stübner {
271903bf81f1SLinus Walleij 	struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
2720d3e51161SHeiko Stübner 	unsigned int virq;
2721d3e51161SHeiko Stübner 
2722d3e51161SHeiko Stübner 	if (!bank->domain)
2723d3e51161SHeiko Stübner 		return -ENXIO;
2724d3e51161SHeiko Stübner 
2725d3e51161SHeiko Stübner 	virq = irq_create_mapping(bank->domain, offset);
2726d3e51161SHeiko Stübner 
2727d3e51161SHeiko Stübner 	return (virq) ? : -ENXIO;
2728d3e51161SHeiko Stübner }
2729d3e51161SHeiko Stübner 
2730d3e51161SHeiko Stübner static const struct gpio_chip rockchip_gpiolib_chip = {
273198c85d58SJonas Gorski 	.request = gpiochip_generic_request,
273298c85d58SJonas Gorski 	.free = gpiochip_generic_free,
2733d3e51161SHeiko Stübner 	.set = rockchip_gpio_set,
2734d3e51161SHeiko Stübner 	.get = rockchip_gpio_get,
27356ba20a00SCaesar Wang 	.get_direction	= rockchip_gpio_get_direction,
2736d3e51161SHeiko Stübner 	.direction_input = rockchip_gpio_direction_input,
2737d3e51161SHeiko Stübner 	.direction_output = rockchip_gpio_direction_output,
2738d3e51161SHeiko Stübner 	.to_irq = rockchip_gpio_to_irq,
2739d3e51161SHeiko Stübner 	.owner = THIS_MODULE,
2740d3e51161SHeiko Stübner };
2741d3e51161SHeiko Stübner 
2742d3e51161SHeiko Stübner /*
2743d3e51161SHeiko Stübner  * Interrupt handling
2744d3e51161SHeiko Stübner  */
2745d3e51161SHeiko Stübner 
2746bd0b9ac4SThomas Gleixner static void rockchip_irq_demux(struct irq_desc *desc)
2747d3e51161SHeiko Stübner {
27485663bb27SJiang Liu 	struct irq_chip *chip = irq_desc_get_chip(desc);
27495663bb27SJiang Liu 	struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
2750d3e51161SHeiko Stübner 	u32 pend;
2751d3e51161SHeiko Stübner 
2752d3e51161SHeiko Stübner 	dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
2753d3e51161SHeiko Stübner 
2754d3e51161SHeiko Stübner 	chained_irq_enter(chip, desc);
2755d3e51161SHeiko Stübner 
2756d3e51161SHeiko Stübner 	pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
2757d3e51161SHeiko Stübner 
2758d3e51161SHeiko Stübner 	while (pend) {
2759415f748cSThomas Gleixner 		unsigned int irq, virq;
2760d3e51161SHeiko Stübner 
2761d3e51161SHeiko Stübner 		irq = __ffs(pend);
2762d3e51161SHeiko Stübner 		pend &= ~BIT(irq);
2763d3e51161SHeiko Stübner 		virq = irq_linear_revmap(bank->domain, irq);
2764d3e51161SHeiko Stübner 
2765d3e51161SHeiko Stübner 		if (!virq) {
2766d3e51161SHeiko Stübner 			dev_err(bank->drvdata->dev, "unmapped irq %d\n", irq);
2767d3e51161SHeiko Stübner 			continue;
2768d3e51161SHeiko Stübner 		}
2769d3e51161SHeiko Stübner 
2770d3e51161SHeiko Stübner 		dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq);
2771d3e51161SHeiko Stübner 
27725a927501SHeiko Stübner 		/*
27735a927501SHeiko Stübner 		 * Triggering IRQ on both rising and falling edge
27745a927501SHeiko Stübner 		 * needs manual intervention.
27755a927501SHeiko Stübner 		 */
27765a927501SHeiko Stübner 		if (bank->toggle_edge_mode & BIT(irq)) {
277753b1bfc7SDoug Anderson 			u32 data, data_old, polarity;
277853b1bfc7SDoug Anderson 			unsigned long flags;
277953b1bfc7SDoug Anderson 
278053b1bfc7SDoug Anderson 			data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
278153b1bfc7SDoug Anderson 			do {
278270b7aa7aSJohn Keeping 				raw_spin_lock_irqsave(&bank->slock, flags);
278353b1bfc7SDoug Anderson 
278453b1bfc7SDoug Anderson 				polarity = readl_relaxed(bank->reg_base +
278553b1bfc7SDoug Anderson 							 GPIO_INT_POLARITY);
27865a927501SHeiko Stübner 				if (data & BIT(irq))
27875a927501SHeiko Stübner 					polarity &= ~BIT(irq);
27885a927501SHeiko Stübner 				else
27895a927501SHeiko Stübner 					polarity |= BIT(irq);
279053b1bfc7SDoug Anderson 				writel(polarity,
279153b1bfc7SDoug Anderson 				       bank->reg_base + GPIO_INT_POLARITY);
27925a927501SHeiko Stübner 
279370b7aa7aSJohn Keeping 				raw_spin_unlock_irqrestore(&bank->slock, flags);
279453b1bfc7SDoug Anderson 
279553b1bfc7SDoug Anderson 				data_old = data;
279653b1bfc7SDoug Anderson 				data = readl_relaxed(bank->reg_base +
279753b1bfc7SDoug Anderson 						     GPIO_EXT_PORT);
279853b1bfc7SDoug Anderson 			} while ((data & BIT(irq)) != (data_old & BIT(irq)));
27995a927501SHeiko Stübner 		}
28005a927501SHeiko Stübner 
2801d3e51161SHeiko Stübner 		generic_handle_irq(virq);
2802d3e51161SHeiko Stübner 	}
2803d3e51161SHeiko Stübner 
2804d3e51161SHeiko Stübner 	chained_irq_exit(chip, desc);
2805d3e51161SHeiko Stübner }
2806d3e51161SHeiko Stübner 
2807d3e51161SHeiko Stübner static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
2808d3e51161SHeiko Stübner {
2809d3e51161SHeiko Stübner 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
2810d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = gc->private;
2811d3e51161SHeiko Stübner 	u32 mask = BIT(d->hwirq);
2812d3e51161SHeiko Stübner 	u32 polarity;
2813d3e51161SHeiko Stübner 	u32 level;
2814d3e51161SHeiko Stübner 	u32 data;
2815fab262f5SDoug Anderson 	unsigned long flags;
281614797189SHeiko Stübner 	int ret;
2817d3e51161SHeiko Stübner 
28185a927501SHeiko Stübner 	/* make sure the pin is configured as gpio input */
28191d80df93SBrian Norris 	ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
282014797189SHeiko Stübner 	if (ret < 0)
282114797189SHeiko Stübner 		return ret;
282214797189SHeiko Stübner 
28231d80df93SBrian Norris 	clk_enable(bank->clk);
282470b7aa7aSJohn Keeping 	raw_spin_lock_irqsave(&bank->slock, flags);
2825fab262f5SDoug Anderson 
28265a927501SHeiko Stübner 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
28275a927501SHeiko Stübner 	data &= ~mask;
28285a927501SHeiko Stübner 	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
28295a927501SHeiko Stübner 
283070b7aa7aSJohn Keeping 	raw_spin_unlock_irqrestore(&bank->slock, flags);
2831fab262f5SDoug Anderson 
2832d3e51161SHeiko Stübner 	if (type & IRQ_TYPE_EDGE_BOTH)
28332dbf1bc5SThomas Gleixner 		irq_set_handler_locked(d, handle_edge_irq);
2834d3e51161SHeiko Stübner 	else
28352dbf1bc5SThomas Gleixner 		irq_set_handler_locked(d, handle_level_irq);
2836d3e51161SHeiko Stübner 
283770b7aa7aSJohn Keeping 	raw_spin_lock_irqsave(&bank->slock, flags);
2838d3e51161SHeiko Stübner 	irq_gc_lock(gc);
2839d3e51161SHeiko Stübner 
2840d3e51161SHeiko Stübner 	level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL);
2841d3e51161SHeiko Stübner 	polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY);
2842d3e51161SHeiko Stübner 
2843d3e51161SHeiko Stübner 	switch (type) {
28445a927501SHeiko Stübner 	case IRQ_TYPE_EDGE_BOTH:
28455a927501SHeiko Stübner 		bank->toggle_edge_mode |= mask;
28465a927501SHeiko Stübner 		level |= mask;
28475a927501SHeiko Stübner 
28485a927501SHeiko Stübner 		/*
28495a927501SHeiko Stübner 		 * Determine gpio state. If 1 next interrupt should be falling
28505a927501SHeiko Stübner 		 * otherwise rising.
28515a927501SHeiko Stübner 		 */
28525a927501SHeiko Stübner 		data = readl(bank->reg_base + GPIO_EXT_PORT);
28535a927501SHeiko Stübner 		if (data & mask)
28545a927501SHeiko Stübner 			polarity &= ~mask;
28555a927501SHeiko Stübner 		else
28565a927501SHeiko Stübner 			polarity |= mask;
28575a927501SHeiko Stübner 		break;
2858d3e51161SHeiko Stübner 	case IRQ_TYPE_EDGE_RISING:
28595a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2860d3e51161SHeiko Stübner 		level |= mask;
2861d3e51161SHeiko Stübner 		polarity |= mask;
2862d3e51161SHeiko Stübner 		break;
2863d3e51161SHeiko Stübner 	case IRQ_TYPE_EDGE_FALLING:
28645a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2865d3e51161SHeiko Stübner 		level |= mask;
2866d3e51161SHeiko Stübner 		polarity &= ~mask;
2867d3e51161SHeiko Stübner 		break;
2868d3e51161SHeiko Stübner 	case IRQ_TYPE_LEVEL_HIGH:
28695a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2870d3e51161SHeiko Stübner 		level &= ~mask;
2871d3e51161SHeiko Stübner 		polarity |= mask;
2872d3e51161SHeiko Stübner 		break;
2873d3e51161SHeiko Stübner 	case IRQ_TYPE_LEVEL_LOW:
28745a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
2875d3e51161SHeiko Stübner 		level &= ~mask;
2876d3e51161SHeiko Stübner 		polarity &= ~mask;
2877d3e51161SHeiko Stübner 		break;
2878d3e51161SHeiko Stübner 	default:
28797cc5f970SAxel Lin 		irq_gc_unlock(gc);
288070b7aa7aSJohn Keeping 		raw_spin_unlock_irqrestore(&bank->slock, flags);
28811d80df93SBrian Norris 		clk_disable(bank->clk);
2882d3e51161SHeiko Stübner 		return -EINVAL;
2883d3e51161SHeiko Stübner 	}
2884d3e51161SHeiko Stübner 
2885d3e51161SHeiko Stübner 	writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL);
2886d3e51161SHeiko Stübner 	writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
2887d3e51161SHeiko Stübner 
2888d3e51161SHeiko Stübner 	irq_gc_unlock(gc);
288970b7aa7aSJohn Keeping 	raw_spin_unlock_irqrestore(&bank->slock, flags);
28901d80df93SBrian Norris 	clk_disable(bank->clk);
2891d3e51161SHeiko Stübner 
2892d3e51161SHeiko Stübner 	return 0;
2893d3e51161SHeiko Stübner }
2894d3e51161SHeiko Stübner 
289568bda47cSDoug Anderson static void rockchip_irq_suspend(struct irq_data *d)
289668bda47cSDoug Anderson {
289768bda47cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
289868bda47cSDoug Anderson 	struct rockchip_pin_bank *bank = gc->private;
289968bda47cSDoug Anderson 
290007a06ae9SLin Huang 	clk_enable(bank->clk);
29015ae0c7adSDoug Anderson 	bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK);
29025ae0c7adSDoug Anderson 	irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK);
290307a06ae9SLin Huang 	clk_disable(bank->clk);
290468bda47cSDoug Anderson }
290568bda47cSDoug Anderson 
290668bda47cSDoug Anderson static void rockchip_irq_resume(struct irq_data *d)
290768bda47cSDoug Anderson {
290868bda47cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
290968bda47cSDoug Anderson 	struct rockchip_pin_bank *bank = gc->private;
291068bda47cSDoug Anderson 
291107a06ae9SLin Huang 	clk_enable(bank->clk);
29125ae0c7adSDoug Anderson 	irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK);
291307a06ae9SLin Huang 	clk_disable(bank->clk);
291407a06ae9SLin Huang }
291507a06ae9SLin Huang 
2916d468289aSJeffy Chen static void rockchip_irq_enable(struct irq_data *d)
291707a06ae9SLin Huang {
291807a06ae9SLin Huang 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
291907a06ae9SLin Huang 	struct rockchip_pin_bank *bank = gc->private;
292007a06ae9SLin Huang 
292107a06ae9SLin Huang 	clk_enable(bank->clk);
292207a06ae9SLin Huang 	irq_gc_mask_clr_bit(d);
292307a06ae9SLin Huang }
292407a06ae9SLin Huang 
2925d468289aSJeffy Chen static void rockchip_irq_disable(struct irq_data *d)
292607a06ae9SLin Huang {
292707a06ae9SLin Huang 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
292807a06ae9SLin Huang 	struct rockchip_pin_bank *bank = gc->private;
292907a06ae9SLin Huang 
293007a06ae9SLin Huang 	irq_gc_mask_set_bit(d);
293107a06ae9SLin Huang 	clk_disable(bank->clk);
2932f2dd028cSDoug Anderson }
2933f2dd028cSDoug Anderson 
2934d3e51161SHeiko Stübner static int rockchip_interrupts_register(struct platform_device *pdev,
2935d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
2936d3e51161SHeiko Stübner {
2937d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
2938d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
2939d3e51161SHeiko Stübner 	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
2940d3e51161SHeiko Stübner 	struct irq_chip_generic *gc;
2941d3e51161SHeiko Stübner 	int ret;
294207a06ae9SLin Huang 	int i, j;
2943d3e51161SHeiko Stübner 
2944d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
2945d3e51161SHeiko Stübner 		if (!bank->valid) {
2946d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "bank %s is not valid\n",
2947d3e51161SHeiko Stübner 				 bank->name);
2948d3e51161SHeiko Stübner 			continue;
2949d3e51161SHeiko Stübner 		}
2950d3e51161SHeiko Stübner 
295107a06ae9SLin Huang 		ret = clk_enable(bank->clk);
295207a06ae9SLin Huang 		if (ret) {
295307a06ae9SLin Huang 			dev_err(&pdev->dev, "failed to enable clock for bank %s\n",
295407a06ae9SLin Huang 				bank->name);
295507a06ae9SLin Huang 			continue;
295607a06ae9SLin Huang 		}
295707a06ae9SLin Huang 
2958d3e51161SHeiko Stübner 		bank->domain = irq_domain_add_linear(bank->of_node, 32,
2959d3e51161SHeiko Stübner 						&irq_generic_chip_ops, NULL);
2960d3e51161SHeiko Stübner 		if (!bank->domain) {
2961d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n",
2962d3e51161SHeiko Stübner 				 bank->name);
296307a06ae9SLin Huang 			clk_disable(bank->clk);
2964d3e51161SHeiko Stübner 			continue;
2965d3e51161SHeiko Stübner 		}
2966d3e51161SHeiko Stübner 
2967d3e51161SHeiko Stübner 		ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1,
2968d3e51161SHeiko Stübner 					 "rockchip_gpio_irq", handle_level_irq,
2969d3e51161SHeiko Stübner 					 clr, 0, IRQ_GC_INIT_MASK_CACHE);
2970d3e51161SHeiko Stübner 		if (ret) {
2971d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n",
2972d3e51161SHeiko Stübner 				bank->name);
2973d3e51161SHeiko Stübner 			irq_domain_remove(bank->domain);
297407a06ae9SLin Huang 			clk_disable(bank->clk);
2975d3e51161SHeiko Stübner 			continue;
2976d3e51161SHeiko Stübner 		}
2977d3e51161SHeiko Stübner 
29785ae0c7adSDoug Anderson 		/*
29795ae0c7adSDoug Anderson 		 * Linux assumes that all interrupts start out disabled/masked.
29805ae0c7adSDoug Anderson 		 * Our driver only uses the concept of masked and always keeps
29815ae0c7adSDoug Anderson 		 * things enabled, so for us that's all masked and all enabled.
29825ae0c7adSDoug Anderson 		 */
29835ae0c7adSDoug Anderson 		writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK);
29845ae0c7adSDoug Anderson 		writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN);
29855ae0c7adSDoug Anderson 
2986d3e51161SHeiko Stübner 		gc = irq_get_domain_generic_chip(bank->domain, 0);
2987d3e51161SHeiko Stübner 		gc->reg_base = bank->reg_base;
2988d3e51161SHeiko Stübner 		gc->private = bank;
2989f2dd028cSDoug Anderson 		gc->chip_types[0].regs.mask = GPIO_INTMASK;
2990d3e51161SHeiko Stübner 		gc->chip_types[0].regs.ack = GPIO_PORTS_EOI;
2991d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
2992d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
2993d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
2994d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_enable = rockchip_irq_enable;
2995d468289aSJeffy Chen 		gc->chip_types[0].chip.irq_disable = rockchip_irq_disable;
2996d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
299768bda47cSDoug Anderson 		gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
299868bda47cSDoug Anderson 		gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
2999d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
3000876d716bSDoug Anderson 		gc->wake_enabled = IRQ_MSK(bank->nr_pins);
3001d3e51161SHeiko Stübner 
300203051bc2SThomas Gleixner 		irq_set_chained_handler_and_data(bank->irq,
300303051bc2SThomas Gleixner 						 rockchip_irq_demux, bank);
300407a06ae9SLin Huang 
300507a06ae9SLin Huang 		/* map the gpio irqs here, when the clock is still running */
300607a06ae9SLin Huang 		for (j = 0 ; j < 32 ; j++)
300707a06ae9SLin Huang 			irq_create_mapping(bank->domain, j);
300807a06ae9SLin Huang 
300907a06ae9SLin Huang 		clk_disable(bank->clk);
3010d3e51161SHeiko Stübner 	}
3011d3e51161SHeiko Stübner 
3012d3e51161SHeiko Stübner 	return 0;
3013d3e51161SHeiko Stübner }
3014d3e51161SHeiko Stübner 
3015d3e51161SHeiko Stübner static int rockchip_gpiolib_register(struct platform_device *pdev,
3016d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
3017d3e51161SHeiko Stübner {
3018d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
3019d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
3020d3e51161SHeiko Stübner 	struct gpio_chip *gc;
3021d3e51161SHeiko Stübner 	int ret;
3022d3e51161SHeiko Stübner 	int i;
3023d3e51161SHeiko Stübner 
3024d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
3025d3e51161SHeiko Stübner 		if (!bank->valid) {
3026d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "bank %s is not valid\n",
3027d3e51161SHeiko Stübner 				 bank->name);
3028d3e51161SHeiko Stübner 			continue;
3029d3e51161SHeiko Stübner 		}
3030d3e51161SHeiko Stübner 
3031d3e51161SHeiko Stübner 		bank->gpio_chip = rockchip_gpiolib_chip;
3032d3e51161SHeiko Stübner 
3033d3e51161SHeiko Stübner 		gc = &bank->gpio_chip;
3034d3e51161SHeiko Stübner 		gc->base = bank->pin_base;
3035d3e51161SHeiko Stübner 		gc->ngpio = bank->nr_pins;
303658383c78SLinus Walleij 		gc->parent = &pdev->dev;
3037d3e51161SHeiko Stübner 		gc->of_node = bank->of_node;
3038d3e51161SHeiko Stübner 		gc->label = bank->name;
3039d3e51161SHeiko Stübner 
304003bf81f1SLinus Walleij 		ret = gpiochip_add_data(gc, bank);
3041d3e51161SHeiko Stübner 		if (ret) {
3042d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
3043d3e51161SHeiko Stübner 							gc->label, ret);
3044d3e51161SHeiko Stübner 			goto fail;
3045d3e51161SHeiko Stübner 		}
3046d3e51161SHeiko Stübner 	}
3047d3e51161SHeiko Stübner 
3048d3e51161SHeiko Stübner 	rockchip_interrupts_register(pdev, info);
3049d3e51161SHeiko Stübner 
3050d3e51161SHeiko Stübner 	return 0;
3051d3e51161SHeiko Stübner 
3052d3e51161SHeiko Stübner fail:
3053d3e51161SHeiko Stübner 	for (--i, --bank; i >= 0; --i, --bank) {
3054d3e51161SHeiko Stübner 		if (!bank->valid)
3055d3e51161SHeiko Stübner 			continue;
3056b4e7c55dSabdoulaye berthe 		gpiochip_remove(&bank->gpio_chip);
3057d3e51161SHeiko Stübner 	}
3058d3e51161SHeiko Stübner 	return ret;
3059d3e51161SHeiko Stübner }
3060d3e51161SHeiko Stübner 
3061d3e51161SHeiko Stübner static int rockchip_gpiolib_unregister(struct platform_device *pdev,
3062d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
3063d3e51161SHeiko Stübner {
3064d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
3065d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
3066d3e51161SHeiko Stübner 	int i;
3067d3e51161SHeiko Stübner 
3068b4e7c55dSabdoulaye berthe 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
3069d3e51161SHeiko Stübner 		if (!bank->valid)
3070d3e51161SHeiko Stübner 			continue;
3071b4e7c55dSabdoulaye berthe 		gpiochip_remove(&bank->gpio_chip);
3072d3e51161SHeiko Stübner 	}
3073d3e51161SHeiko Stübner 
3074b4e7c55dSabdoulaye berthe 	return 0;
3075d3e51161SHeiko Stübner }
3076d3e51161SHeiko Stübner 
3077d3e51161SHeiko Stübner static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
3078622f3237SHeiko Stübner 				  struct rockchip_pinctrl *info)
3079d3e51161SHeiko Stübner {
3080d3e51161SHeiko Stübner 	struct resource res;
3081751a99abSHeiko Stübner 	void __iomem *base;
3082d3e51161SHeiko Stübner 
3083d3e51161SHeiko Stübner 	if (of_address_to_resource(bank->of_node, 0, &res)) {
3084622f3237SHeiko Stübner 		dev_err(info->dev, "cannot find IO resource for bank\n");
3085d3e51161SHeiko Stübner 		return -ENOENT;
3086d3e51161SHeiko Stübner 	}
3087d3e51161SHeiko Stübner 
3088622f3237SHeiko Stübner 	bank->reg_base = devm_ioremap_resource(info->dev, &res);
3089d3e51161SHeiko Stübner 	if (IS_ERR(bank->reg_base))
3090d3e51161SHeiko Stübner 		return PTR_ERR(bank->reg_base);
3091d3e51161SHeiko Stübner 
30926ca5274dSHeiko Stübner 	/*
30936ca5274dSHeiko Stübner 	 * special case, where parts of the pull setting-registers are
30946ca5274dSHeiko Stübner 	 * part of the PMU register space
30956ca5274dSHeiko Stübner 	 */
30966ca5274dSHeiko Stübner 	if (of_device_is_compatible(bank->of_node,
30976ca5274dSHeiko Stübner 				    "rockchip,rk3188-gpio-bank0")) {
3098a658efaaSHeiko Stübner 		struct device_node *node;
3099bfc7a42aSHeiko Stübner 
3100a658efaaSHeiko Stübner 		node = of_parse_phandle(bank->of_node->parent,
3101a658efaaSHeiko Stübner 					"rockchip,pmu", 0);
3102a658efaaSHeiko Stübner 		if (!node) {
31036ca5274dSHeiko Stübner 			if (of_address_to_resource(bank->of_node, 1, &res)) {
3104622f3237SHeiko Stübner 				dev_err(info->dev, "cannot find IO resource for bank\n");
31056ca5274dSHeiko Stübner 				return -ENOENT;
31066ca5274dSHeiko Stübner 			}
31076ca5274dSHeiko Stübner 
3108622f3237SHeiko Stübner 			base = devm_ioremap_resource(info->dev, &res);
3109751a99abSHeiko Stübner 			if (IS_ERR(base))
3110751a99abSHeiko Stübner 				return PTR_ERR(base);
3111a658efaaSHeiko Stübner 			rockchip_regmap_config.max_register =
3112a658efaaSHeiko Stübner 						    resource_size(&res) - 4;
3113a658efaaSHeiko Stübner 			rockchip_regmap_config.name =
3114a658efaaSHeiko Stübner 					    "rockchip,rk3188-gpio-bank0-pull";
3115a658efaaSHeiko Stübner 			bank->regmap_pull = devm_regmap_init_mmio(info->dev,
3116a658efaaSHeiko Stübner 						    base,
3117751a99abSHeiko Stübner 						    &rockchip_regmap_config);
3118a658efaaSHeiko Stübner 		}
31196ca5274dSHeiko Stübner 	}
312065fca613SHeiko Stübner 
3121d3e51161SHeiko Stübner 	bank->irq = irq_of_parse_and_map(bank->of_node, 0);
3122d3e51161SHeiko Stübner 
3123d3e51161SHeiko Stübner 	bank->clk = of_clk_get(bank->of_node, 0);
3124d3e51161SHeiko Stübner 	if (IS_ERR(bank->clk))
3125d3e51161SHeiko Stübner 		return PTR_ERR(bank->clk);
3126d3e51161SHeiko Stübner 
312707a06ae9SLin Huang 	return clk_prepare(bank->clk);
3128d3e51161SHeiko Stübner }
3129d3e51161SHeiko Stübner 
3130d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[];
3131d3e51161SHeiko Stübner 
3132d3e51161SHeiko Stübner /* retrieve the soc specific data */
3133d3e51161SHeiko Stübner static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
3134d3e51161SHeiko Stübner 						struct rockchip_pinctrl *d,
3135d3e51161SHeiko Stübner 						struct platform_device *pdev)
3136d3e51161SHeiko Stübner {
3137d3e51161SHeiko Stübner 	const struct of_device_id *match;
3138d3e51161SHeiko Stübner 	struct device_node *node = pdev->dev.of_node;
3139d3e51161SHeiko Stübner 	struct device_node *np;
3140d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl;
3141d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
3142b6c23275SDavid Wu 	int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j;
3143d3e51161SHeiko Stübner 
3144d3e51161SHeiko Stübner 	match = of_match_node(rockchip_pinctrl_dt_match, node);
3145d3e51161SHeiko Stübner 	ctrl = (struct rockchip_pin_ctrl *)match->data;
3146d3e51161SHeiko Stübner 
3147d3e51161SHeiko Stübner 	for_each_child_of_node(node, np) {
3148d3e51161SHeiko Stübner 		if (!of_find_property(np, "gpio-controller", NULL))
3149d3e51161SHeiko Stübner 			continue;
3150d3e51161SHeiko Stübner 
3151d3e51161SHeiko Stübner 		bank = ctrl->pin_banks;
3152d3e51161SHeiko Stübner 		for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
3153d3e51161SHeiko Stübner 			if (!strcmp(bank->name, np->name)) {
3154d3e51161SHeiko Stübner 				bank->of_node = np;
3155d3e51161SHeiko Stübner 
3156622f3237SHeiko Stübner 				if (!rockchip_get_bank_data(bank, d))
3157d3e51161SHeiko Stübner 					bank->valid = true;
3158d3e51161SHeiko Stübner 
3159d3e51161SHeiko Stübner 				break;
3160d3e51161SHeiko Stübner 			}
3161d3e51161SHeiko Stübner 		}
3162d3e51161SHeiko Stübner 	}
3163d3e51161SHeiko Stübner 
316495ec8ae4SHeiko Stübner 	grf_offs = ctrl->grf_mux_offset;
316595ec8ae4SHeiko Stübner 	pmu_offs = ctrl->pmu_mux_offset;
3166b6c23275SDavid Wu 	drv_pmu_offs = ctrl->pmu_drv_offset;
3167b6c23275SDavid Wu 	drv_grf_offs = ctrl->grf_drv_offset;
3168d3e51161SHeiko Stübner 	bank = ctrl->pin_banks;
3169d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
31706bc0d121SHeiko Stübner 		int bank_pins = 0;
31716bc0d121SHeiko Stübner 
317270b7aa7aSJohn Keeping 		raw_spin_lock_init(&bank->slock);
3173d3e51161SHeiko Stübner 		bank->drvdata = d;
3174d3e51161SHeiko Stübner 		bank->pin_base = ctrl->nr_pins;
3175d3e51161SHeiko Stübner 		ctrl->nr_pins += bank->nr_pins;
31766bc0d121SHeiko Stübner 
3177b6c23275SDavid Wu 		/* calculate iomux and drv offsets */
31786bc0d121SHeiko Stübner 		for (j = 0; j < 4; j++) {
31796bc0d121SHeiko Stübner 			struct rockchip_iomux *iom = &bank->iomux[j];
3180b6c23275SDavid Wu 			struct rockchip_drv *drv = &bank->drv[j];
318103716e1dSHeiko Stübner 			int inc;
31826bc0d121SHeiko Stübner 
31836bc0d121SHeiko Stübner 			if (bank_pins >= bank->nr_pins)
31846bc0d121SHeiko Stübner 				break;
31856bc0d121SHeiko Stübner 
3186b6c23275SDavid Wu 			/* preset iomux offset value, set new start value */
31876bc0d121SHeiko Stübner 			if (iom->offset >= 0) {
318895ec8ae4SHeiko Stübner 				if (iom->type & IOMUX_SOURCE_PMU)
318995ec8ae4SHeiko Stübner 					pmu_offs = iom->offset;
319095ec8ae4SHeiko Stübner 				else
31916bc0d121SHeiko Stübner 					grf_offs = iom->offset;
3192b6c23275SDavid Wu 			} else { /* set current iomux offset */
319395ec8ae4SHeiko Stübner 				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
319495ec8ae4SHeiko Stübner 							pmu_offs : grf_offs;
31956bc0d121SHeiko Stübner 			}
31966bc0d121SHeiko Stübner 
3197b6c23275SDavid Wu 			/* preset drv offset value, set new start value */
3198b6c23275SDavid Wu 			if (drv->offset >= 0) {
3199b6c23275SDavid Wu 				if (iom->type & IOMUX_SOURCE_PMU)
3200b6c23275SDavid Wu 					drv_pmu_offs = drv->offset;
3201b6c23275SDavid Wu 				else
3202b6c23275SDavid Wu 					drv_grf_offs = drv->offset;
3203b6c23275SDavid Wu 			} else { /* set current drv offset */
3204b6c23275SDavid Wu 				drv->offset = (iom->type & IOMUX_SOURCE_PMU) ?
3205b6c23275SDavid Wu 						drv_pmu_offs : drv_grf_offs;
3206b6c23275SDavid Wu 			}
3207b6c23275SDavid Wu 
3208b6c23275SDavid Wu 			dev_dbg(d->dev, "bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n",
3209b6c23275SDavid Wu 				i, j, iom->offset, drv->offset);
32106bc0d121SHeiko Stübner 
32116bc0d121SHeiko Stübner 			/*
32126bc0d121SHeiko Stübner 			 * Increase offset according to iomux width.
321303716e1dSHeiko Stübner 			 * 4bit iomux'es are spread over two registers.
32146bc0d121SHeiko Stübner 			 */
32158b6c6f93Sdavid.wu 			inc = (iom->type & (IOMUX_WIDTH_4BIT |
32168b6c6f93Sdavid.wu 					    IOMUX_WIDTH_3BIT)) ? 8 : 4;
321795ec8ae4SHeiko Stübner 			if (iom->type & IOMUX_SOURCE_PMU)
321895ec8ae4SHeiko Stübner 				pmu_offs += inc;
321995ec8ae4SHeiko Stübner 			else
322003716e1dSHeiko Stübner 				grf_offs += inc;
32216bc0d121SHeiko Stübner 
3222b6c23275SDavid Wu 			/*
3223b6c23275SDavid Wu 			 * Increase offset according to drv width.
3224b6c23275SDavid Wu 			 * 3bit drive-strenth'es are spread over two registers.
3225b6c23275SDavid Wu 			 */
3226b6c23275SDavid Wu 			if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
3227b6c23275SDavid Wu 			    (drv->drv_type == DRV_TYPE_IO_3V3_ONLY))
3228b6c23275SDavid Wu 				inc = 8;
3229b6c23275SDavid Wu 			else
3230b6c23275SDavid Wu 				inc = 4;
3231b6c23275SDavid Wu 
3232b6c23275SDavid Wu 			if (iom->type & IOMUX_SOURCE_PMU)
3233b6c23275SDavid Wu 				drv_pmu_offs += inc;
3234b6c23275SDavid Wu 			else
3235b6c23275SDavid Wu 				drv_grf_offs += inc;
3236b6c23275SDavid Wu 
32376bc0d121SHeiko Stübner 			bank_pins += 8;
32386bc0d121SHeiko Stübner 		}
3239bd35b9bfSDavid Wu 
3240c04c3fa6SDavid Wu 		/* calculate the per-bank recalced_mask */
3241c04c3fa6SDavid Wu 		for (j = 0; j < ctrl->niomux_recalced; j++) {
3242c04c3fa6SDavid Wu 			int pin = 0;
3243c04c3fa6SDavid Wu 
3244c04c3fa6SDavid Wu 			if (ctrl->iomux_recalced[j].num == bank->bank_num) {
3245c04c3fa6SDavid Wu 				pin = ctrl->iomux_recalced[j].pin;
3246c04c3fa6SDavid Wu 				bank->recalced_mask |= BIT(pin);
3247c04c3fa6SDavid Wu 			}
3248c04c3fa6SDavid Wu 		}
3249c04c3fa6SDavid Wu 
3250bd35b9bfSDavid Wu 		/* calculate the per-bank route_mask */
3251bd35b9bfSDavid Wu 		for (j = 0; j < ctrl->niomux_routes; j++) {
3252bd35b9bfSDavid Wu 			int pin = 0;
3253bd35b9bfSDavid Wu 
3254bd35b9bfSDavid Wu 			if (ctrl->iomux_routes[j].bank_num == bank->bank_num) {
3255bd35b9bfSDavid Wu 				pin = ctrl->iomux_routes[j].pin;
3256bd35b9bfSDavid Wu 				bank->route_mask |= BIT(pin);
3257bd35b9bfSDavid Wu 			}
3258bd35b9bfSDavid Wu 		}
3259d3e51161SHeiko Stübner 	}
3260d3e51161SHeiko Stübner 
3261d3e51161SHeiko Stübner 	return ctrl;
3262d3e51161SHeiko Stübner }
3263d3e51161SHeiko Stübner 
32648dca9331SChris Zhong #define RK3288_GRF_GPIO6C_IOMUX		0x64
32658dca9331SChris Zhong #define GPIO6C6_SEL_WRITE_ENABLE	BIT(28)
32668dca9331SChris Zhong 
32678dca9331SChris Zhong static u32 rk3288_grf_gpio6c_iomux;
32688dca9331SChris Zhong 
32699198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev)
32709198f509SChris Zhong {
32719198f509SChris Zhong 	struct rockchip_pinctrl *info = dev_get_drvdata(dev);
32728dca9331SChris Zhong 	int ret = pinctrl_force_sleep(info->pctl_dev);
32739198f509SChris Zhong 
32748dca9331SChris Zhong 	if (ret)
32758dca9331SChris Zhong 		return ret;
32768dca9331SChris Zhong 
32778dca9331SChris Zhong 	/*
32788dca9331SChris Zhong 	 * RK3288 GPIO6_C6 mux would be modified by Maskrom when resume, so save
32798dca9331SChris Zhong 	 * the setting here, and restore it at resume.
32808dca9331SChris Zhong 	 */
32818dca9331SChris Zhong 	if (info->ctrl->type == RK3288) {
32828dca9331SChris Zhong 		ret = regmap_read(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
32838dca9331SChris Zhong 				  &rk3288_grf_gpio6c_iomux);
32848dca9331SChris Zhong 		if (ret) {
32858dca9331SChris Zhong 			pinctrl_force_default(info->pctl_dev);
32868dca9331SChris Zhong 			return ret;
32878dca9331SChris Zhong 		}
32888dca9331SChris Zhong 	}
32898dca9331SChris Zhong 
32908dca9331SChris Zhong 	return 0;
32919198f509SChris Zhong }
32929198f509SChris Zhong 
32939198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_resume(struct device *dev)
32949198f509SChris Zhong {
32959198f509SChris Zhong 	struct rockchip_pinctrl *info = dev_get_drvdata(dev);
32968dca9331SChris Zhong 	int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
32978dca9331SChris Zhong 			       rk3288_grf_gpio6c_iomux |
32988dca9331SChris Zhong 			       GPIO6C6_SEL_WRITE_ENABLE);
32998dca9331SChris Zhong 
33008dca9331SChris Zhong 	if (ret)
33018dca9331SChris Zhong 		return ret;
33029198f509SChris Zhong 
33039198f509SChris Zhong 	return pinctrl_force_default(info->pctl_dev);
33049198f509SChris Zhong }
33059198f509SChris Zhong 
33069198f509SChris Zhong static SIMPLE_DEV_PM_OPS(rockchip_pinctrl_dev_pm_ops, rockchip_pinctrl_suspend,
33079198f509SChris Zhong 			 rockchip_pinctrl_resume);
33089198f509SChris Zhong 
3309d3e51161SHeiko Stübner static int rockchip_pinctrl_probe(struct platform_device *pdev)
3310d3e51161SHeiko Stübner {
3311d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info;
3312d3e51161SHeiko Stübner 	struct device *dev = &pdev->dev;
3313d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl;
331414dee867SHeiko Stübner 	struct device_node *np = pdev->dev.of_node, *node;
3315d3e51161SHeiko Stübner 	struct resource *res;
3316751a99abSHeiko Stübner 	void __iomem *base;
3317d3e51161SHeiko Stübner 	int ret;
3318d3e51161SHeiko Stübner 
3319d3e51161SHeiko Stübner 	if (!dev->of_node) {
3320d3e51161SHeiko Stübner 		dev_err(dev, "device tree node not found\n");
3321d3e51161SHeiko Stübner 		return -ENODEV;
3322d3e51161SHeiko Stübner 	}
3323d3e51161SHeiko Stübner 
3324283b7ac9SMarkus Elfring 	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
3325d3e51161SHeiko Stübner 	if (!info)
3326d3e51161SHeiko Stübner 		return -ENOMEM;
3327d3e51161SHeiko Stübner 
3328622f3237SHeiko Stübner 	info->dev = dev;
3329622f3237SHeiko Stübner 
3330d3e51161SHeiko Stübner 	ctrl = rockchip_pinctrl_get_soc_data(info, pdev);
3331d3e51161SHeiko Stübner 	if (!ctrl) {
3332d3e51161SHeiko Stübner 		dev_err(dev, "driver data not available\n");
3333d3e51161SHeiko Stübner 		return -EINVAL;
3334d3e51161SHeiko Stübner 	}
3335d3e51161SHeiko Stübner 	info->ctrl = ctrl;
3336d3e51161SHeiko Stübner 
33371e747e59SHeiko Stübner 	node = of_parse_phandle(np, "rockchip,grf", 0);
33381e747e59SHeiko Stübner 	if (node) {
33391e747e59SHeiko Stübner 		info->regmap_base = syscon_node_to_regmap(node);
33401e747e59SHeiko Stübner 		if (IS_ERR(info->regmap_base))
33411e747e59SHeiko Stübner 			return PTR_ERR(info->regmap_base);
33421e747e59SHeiko Stübner 	} else {
3343d3e51161SHeiko Stübner 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3344751a99abSHeiko Stübner 		base = devm_ioremap_resource(&pdev->dev, res);
3345751a99abSHeiko Stübner 		if (IS_ERR(base))
3346751a99abSHeiko Stübner 			return PTR_ERR(base);
3347751a99abSHeiko Stübner 
3348751a99abSHeiko Stübner 		rockchip_regmap_config.max_register = resource_size(res) - 4;
3349751a99abSHeiko Stübner 		rockchip_regmap_config.name = "rockchip,pinctrl";
3350751a99abSHeiko Stübner 		info->regmap_base = devm_regmap_init_mmio(&pdev->dev, base,
3351751a99abSHeiko Stübner 						    &rockchip_regmap_config);
3352d3e51161SHeiko Stübner 
3353bfc7a42aSHeiko Stübner 		/* to check for the old dt-bindings */
3354bfc7a42aSHeiko Stübner 		info->reg_size = resource_size(res);
3355bfc7a42aSHeiko Stübner 
3356bfc7a42aSHeiko Stübner 		/* Honor the old binding, with pull registers as 2nd resource */
3357bfc7a42aSHeiko Stübner 		if (ctrl->type == RK3188 && info->reg_size < 0x200) {
33586ca5274dSHeiko Stübner 			res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
3359751a99abSHeiko Stübner 			base = devm_ioremap_resource(&pdev->dev, res);
3360751a99abSHeiko Stübner 			if (IS_ERR(base))
3361751a99abSHeiko Stübner 				return PTR_ERR(base);
3362751a99abSHeiko Stübner 
33631e747e59SHeiko Stübner 			rockchip_regmap_config.max_register =
33641e747e59SHeiko Stübner 							resource_size(res) - 4;
3365751a99abSHeiko Stübner 			rockchip_regmap_config.name = "rockchip,pinctrl-pull";
33661e747e59SHeiko Stübner 			info->regmap_pull = devm_regmap_init_mmio(&pdev->dev,
33671e747e59SHeiko Stübner 						    base,
3368751a99abSHeiko Stübner 						    &rockchip_regmap_config);
33696ca5274dSHeiko Stübner 		}
33701e747e59SHeiko Stübner 	}
33716ca5274dSHeiko Stübner 
337214dee867SHeiko Stübner 	/* try to find the optional reference to the pmu syscon */
337314dee867SHeiko Stübner 	node = of_parse_phandle(np, "rockchip,pmu", 0);
337414dee867SHeiko Stübner 	if (node) {
337514dee867SHeiko Stübner 		info->regmap_pmu = syscon_node_to_regmap(node);
337614dee867SHeiko Stübner 		if (IS_ERR(info->regmap_pmu))
337714dee867SHeiko Stübner 			return PTR_ERR(info->regmap_pmu);
337814dee867SHeiko Stübner 	}
337914dee867SHeiko Stübner 
3380d3e51161SHeiko Stübner 	ret = rockchip_gpiolib_register(pdev, info);
3381d3e51161SHeiko Stübner 	if (ret)
3382d3e51161SHeiko Stübner 		return ret;
3383d3e51161SHeiko Stübner 
3384d3e51161SHeiko Stübner 	ret = rockchip_pinctrl_register(pdev, info);
3385d3e51161SHeiko Stübner 	if (ret) {
3386d3e51161SHeiko Stübner 		rockchip_gpiolib_unregister(pdev, info);
3387d3e51161SHeiko Stübner 		return ret;
3388d3e51161SHeiko Stübner 	}
3389d3e51161SHeiko Stübner 
3390d3e51161SHeiko Stübner 	platform_set_drvdata(pdev, info);
3391d3e51161SHeiko Stübner 
3392d3e51161SHeiko Stübner 	return 0;
3393d3e51161SHeiko Stübner }
3394d3e51161SHeiko Stübner 
3395*87065ca9SDavid Wu static struct rockchip_pin_bank px30_pin_banks[] = {
3396*87065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
3397*87065ca9SDavid Wu 					     IOMUX_SOURCE_PMU,
3398*87065ca9SDavid Wu 					     IOMUX_SOURCE_PMU,
3399*87065ca9SDavid Wu 					     IOMUX_SOURCE_PMU
3400*87065ca9SDavid Wu 			    ),
3401*87065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
3402*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
3403*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
3404*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT
3405*87065ca9SDavid Wu 			    ),
3406*87065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
3407*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
3408*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
3409*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT
3410*87065ca9SDavid Wu 			    ),
3411*87065ca9SDavid Wu 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
3412*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
3413*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT,
3414*87065ca9SDavid Wu 					     IOMUX_WIDTH_4BIT
3415*87065ca9SDavid Wu 			    ),
3416*87065ca9SDavid Wu };
3417*87065ca9SDavid Wu 
3418*87065ca9SDavid Wu static struct rockchip_pin_ctrl px30_pin_ctrl = {
3419*87065ca9SDavid Wu 		.pin_banks		= px30_pin_banks,
3420*87065ca9SDavid Wu 		.nr_banks		= ARRAY_SIZE(px30_pin_banks),
3421*87065ca9SDavid Wu 		.label			= "PX30-GPIO",
3422*87065ca9SDavid Wu 		.type			= PX30,
3423*87065ca9SDavid Wu 		.grf_mux_offset		= 0x0,
3424*87065ca9SDavid Wu 		.pmu_mux_offset		= 0x0,
3425*87065ca9SDavid Wu 		.iomux_routes		= px30_mux_route_data,
3426*87065ca9SDavid Wu 		.niomux_routes		= ARRAY_SIZE(px30_mux_route_data),
3427*87065ca9SDavid Wu 		.pull_calc_reg		= px30_calc_pull_reg_and_bit,
3428*87065ca9SDavid Wu 		.drv_calc_reg		= px30_calc_drv_reg_and_bit,
3429*87065ca9SDavid Wu 		.schmitt_calc_reg	= px30_calc_schmitt_reg_and_bit,
3430*87065ca9SDavid Wu };
3431*87065ca9SDavid Wu 
3432b9c6dcabSAndy Yan static struct rockchip_pin_bank rv1108_pin_banks[] = {
3433688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
3434688daf23SAndy Yan 					     IOMUX_SOURCE_PMU,
3435688daf23SAndy Yan 					     IOMUX_SOURCE_PMU,
3436688daf23SAndy Yan 					     IOMUX_SOURCE_PMU),
3437688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
3438688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0),
3439688daf23SAndy Yan 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
3440688daf23SAndy Yan };
3441688daf23SAndy Yan 
3442b9c6dcabSAndy Yan static struct rockchip_pin_ctrl rv1108_pin_ctrl = {
3443b9c6dcabSAndy Yan 	.pin_banks		= rv1108_pin_banks,
3444b9c6dcabSAndy Yan 	.nr_banks		= ARRAY_SIZE(rv1108_pin_banks),
3445b9c6dcabSAndy Yan 	.label			= "RV1108-GPIO",
3446b9c6dcabSAndy Yan 	.type			= RV1108,
3447688daf23SAndy Yan 	.grf_mux_offset		= 0x10,
3448688daf23SAndy Yan 	.pmu_mux_offset		= 0x0,
344912b8f018SDavid Wu 	.iomux_recalced		= rv1108_mux_recalced_data,
345012b8f018SDavid Wu 	.niomux_recalced	= ARRAY_SIZE(rv1108_mux_recalced_data),
3451b9c6dcabSAndy Yan 	.pull_calc_reg		= rv1108_calc_pull_reg_and_bit,
3452b9c6dcabSAndy Yan 	.drv_calc_reg		= rv1108_calc_drv_reg_and_bit,
34535caff7eaSAndy Yan 	.schmitt_calc_reg	= rv1108_calc_schmitt_reg_and_bit,
3454688daf23SAndy Yan };
3455688daf23SAndy Yan 
3456d3e51161SHeiko Stübner static struct rockchip_pin_bank rk2928_pin_banks[] = {
3457d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
3458d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3459d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3460d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3461d3e51161SHeiko Stübner };
3462d3e51161SHeiko Stübner 
3463d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
3464d3e51161SHeiko Stübner 		.pin_banks		= rk2928_pin_banks,
3465d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk2928_pin_banks),
3466d3e51161SHeiko Stübner 		.label			= "RK2928-GPIO",
3467a282926dSHeiko Stübner 		.type			= RK2928,
346895ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0xa8,
3469a282926dSHeiko Stübner 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
3470d3e51161SHeiko Stübner };
3471d3e51161SHeiko Stübner 
3472c5ce7670SXing Zheng static struct rockchip_pin_bank rk3036_pin_banks[] = {
3473c5ce7670SXing Zheng 	PIN_BANK(0, 32, "gpio0"),
3474c5ce7670SXing Zheng 	PIN_BANK(1, 32, "gpio1"),
3475c5ce7670SXing Zheng 	PIN_BANK(2, 32, "gpio2"),
3476c5ce7670SXing Zheng };
3477c5ce7670SXing Zheng 
3478c5ce7670SXing Zheng static struct rockchip_pin_ctrl rk3036_pin_ctrl = {
3479c5ce7670SXing Zheng 		.pin_banks		= rk3036_pin_banks,
3480c5ce7670SXing Zheng 		.nr_banks		= ARRAY_SIZE(rk3036_pin_banks),
3481c5ce7670SXing Zheng 		.label			= "RK3036-GPIO",
3482c5ce7670SXing Zheng 		.type			= RK2928,
3483c5ce7670SXing Zheng 		.grf_mux_offset		= 0xa8,
3484c5ce7670SXing Zheng 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
3485c5ce7670SXing Zheng };
3486c5ce7670SXing Zheng 
3487d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066a_pin_banks[] = {
3488d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
3489d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3490d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3491d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3492d3e51161SHeiko Stübner 	PIN_BANK(4, 32, "gpio4"),
3493d3e51161SHeiko Stübner 	PIN_BANK(6, 16, "gpio6"),
3494d3e51161SHeiko Stübner };
3495d3e51161SHeiko Stübner 
3496d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066a_pin_ctrl = {
3497d3e51161SHeiko Stübner 		.pin_banks		= rk3066a_pin_banks,
3498d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3066a_pin_banks),
3499d3e51161SHeiko Stübner 		.label			= "RK3066a-GPIO",
3500a282926dSHeiko Stübner 		.type			= RK2928,
350195ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0xa8,
3502a282926dSHeiko Stübner 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
3503d3e51161SHeiko Stübner };
3504d3e51161SHeiko Stübner 
3505d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066b_pin_banks[] = {
3506d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
3507d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3508d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3509d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3510d3e51161SHeiko Stübner };
3511d3e51161SHeiko Stübner 
3512d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066b_pin_ctrl = {
3513d3e51161SHeiko Stübner 		.pin_banks	= rk3066b_pin_banks,
3514d3e51161SHeiko Stübner 		.nr_banks	= ARRAY_SIZE(rk3066b_pin_banks),
3515d3e51161SHeiko Stübner 		.label		= "RK3066b-GPIO",
3516a282926dSHeiko Stübner 		.type		= RK3066B,
351795ec8ae4SHeiko Stübner 		.grf_mux_offset	= 0x60,
3518d3e51161SHeiko Stübner };
3519d3e51161SHeiko Stübner 
3520d23c66dfSDavid Wu static struct rockchip_pin_bank rk3128_pin_banks[] = {
3521d23c66dfSDavid Wu 	PIN_BANK(0, 32, "gpio0"),
3522d23c66dfSDavid Wu 	PIN_BANK(1, 32, "gpio1"),
3523d23c66dfSDavid Wu 	PIN_BANK(2, 32, "gpio2"),
3524d23c66dfSDavid Wu 	PIN_BANK(3, 32, "gpio3"),
3525d23c66dfSDavid Wu };
3526d23c66dfSDavid Wu 
3527d23c66dfSDavid Wu static struct rockchip_pin_ctrl rk3128_pin_ctrl = {
3528d23c66dfSDavid Wu 		.pin_banks		= rk3128_pin_banks,
3529d23c66dfSDavid Wu 		.nr_banks		= ARRAY_SIZE(rk3128_pin_banks),
3530d23c66dfSDavid Wu 		.label			= "RK3128-GPIO",
3531d23c66dfSDavid Wu 		.type			= RK3128,
3532d23c66dfSDavid Wu 		.grf_mux_offset		= 0xa8,
3533d23c66dfSDavid Wu 		.iomux_recalced		= rk3128_mux_recalced_data,
3534d23c66dfSDavid Wu 		.niomux_recalced	= ARRAY_SIZE(rk3128_mux_recalced_data),
3535d23c66dfSDavid Wu 		.iomux_routes		= rk3128_mux_route_data,
3536d23c66dfSDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3128_mux_route_data),
3537d23c66dfSDavid Wu 		.pull_calc_reg		= rk3128_calc_pull_reg_and_bit,
3538d23c66dfSDavid Wu };
3539d23c66dfSDavid Wu 
3540d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3188_pin_banks[] = {
3541fc72c923SHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0),
3542d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3543d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3544d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3545d3e51161SHeiko Stübner };
3546d3e51161SHeiko Stübner 
3547d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
3548d3e51161SHeiko Stübner 		.pin_banks		= rk3188_pin_banks,
3549d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3188_pin_banks),
3550d3e51161SHeiko Stübner 		.label			= "RK3188-GPIO",
3551a282926dSHeiko Stübner 		.type			= RK3188,
355295ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0x60,
35536ca5274dSHeiko Stübner 		.pull_calc_reg		= rk3188_calc_pull_reg_and_bit,
3554d3e51161SHeiko Stübner };
3555d3e51161SHeiko Stübner 
3556fea0fe60SJeffy Chen static struct rockchip_pin_bank rk3228_pin_banks[] = {
3557fea0fe60SJeffy Chen 	PIN_BANK(0, 32, "gpio0"),
3558fea0fe60SJeffy Chen 	PIN_BANK(1, 32, "gpio1"),
3559fea0fe60SJeffy Chen 	PIN_BANK(2, 32, "gpio2"),
3560fea0fe60SJeffy Chen 	PIN_BANK(3, 32, "gpio3"),
3561fea0fe60SJeffy Chen };
3562fea0fe60SJeffy Chen 
3563fea0fe60SJeffy Chen static struct rockchip_pin_ctrl rk3228_pin_ctrl = {
3564fea0fe60SJeffy Chen 		.pin_banks		= rk3228_pin_banks,
3565fea0fe60SJeffy Chen 		.nr_banks		= ARRAY_SIZE(rk3228_pin_banks),
3566fea0fe60SJeffy Chen 		.label			= "RK3228-GPIO",
3567fea0fe60SJeffy Chen 		.type			= RK3288,
3568fea0fe60SJeffy Chen 		.grf_mux_offset		= 0x0,
3569d4970ee0SDavid Wu 		.iomux_routes		= rk3228_mux_route_data,
3570d4970ee0SDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3228_mux_route_data),
3571fea0fe60SJeffy Chen 		.pull_calc_reg		= rk3228_calc_pull_reg_and_bit,
3572fea0fe60SJeffy Chen 		.drv_calc_reg		= rk3228_calc_drv_reg_and_bit,
3573fea0fe60SJeffy Chen };
3574fea0fe60SJeffy Chen 
3575304f077dSHeiko Stübner static struct rockchip_pin_bank rk3288_pin_banks[] = {
3576304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
3577304f077dSHeiko Stübner 					     IOMUX_SOURCE_PMU,
3578304f077dSHeiko Stübner 					     IOMUX_SOURCE_PMU,
3579304f077dSHeiko Stübner 					     IOMUX_UNROUTED
3580304f077dSHeiko Stübner 			    ),
3581304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED,
3582304f077dSHeiko Stübner 					     IOMUX_UNROUTED,
3583304f077dSHeiko Stübner 					     IOMUX_UNROUTED,
3584304f077dSHeiko Stübner 					     0
3585304f077dSHeiko Stübner 			    ),
3586304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED),
3587304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT),
3588304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
3589304f077dSHeiko Stübner 					     IOMUX_WIDTH_4BIT,
3590304f077dSHeiko Stübner 					     0,
3591304f077dSHeiko Stübner 					     0
3592304f077dSHeiko Stübner 			    ),
3593304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED,
3594304f077dSHeiko Stübner 					     0,
3595304f077dSHeiko Stübner 					     0,
3596304f077dSHeiko Stübner 					     IOMUX_UNROUTED
3597304f077dSHeiko Stübner 			    ),
3598304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED),
3599304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0,
3600304f077dSHeiko Stübner 					     0,
3601304f077dSHeiko Stübner 					     IOMUX_WIDTH_4BIT,
3602304f077dSHeiko Stübner 					     IOMUX_UNROUTED
3603304f077dSHeiko Stübner 			    ),
3604304f077dSHeiko Stübner 	PIN_BANK(8, 16, "gpio8"),
3605304f077dSHeiko Stübner };
3606304f077dSHeiko Stübner 
3607304f077dSHeiko Stübner static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
3608304f077dSHeiko Stübner 		.pin_banks		= rk3288_pin_banks,
3609304f077dSHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3288_pin_banks),
3610304f077dSHeiko Stübner 		.label			= "RK3288-GPIO",
361166d750e1SHeiko Stübner 		.type			= RK3288,
3612304f077dSHeiko Stübner 		.grf_mux_offset		= 0x0,
3613304f077dSHeiko Stübner 		.pmu_mux_offset		= 0x84,
36144e96fd30SHeiko Stuebner 		.iomux_routes		= rk3288_mux_route_data,
36154e96fd30SHeiko Stuebner 		.niomux_routes		= ARRAY_SIZE(rk3288_mux_route_data),
3616304f077dSHeiko Stübner 		.pull_calc_reg		= rk3288_calc_pull_reg_and_bit,
3617ef17f69fSHeiko Stübner 		.drv_calc_reg		= rk3288_calc_drv_reg_and_bit,
3618304f077dSHeiko Stübner };
3619304f077dSHeiko Stübner 
36203818e4a7Sdavid.wu static struct rockchip_pin_bank rk3328_pin_banks[] = {
36213818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0),
36223818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
36233818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0,
3624c04c3fa6SDavid Wu 			     IOMUX_WIDTH_3BIT,
3625c04c3fa6SDavid Wu 			     IOMUX_WIDTH_3BIT,
36263818e4a7Sdavid.wu 			     0),
36273818e4a7Sdavid.wu 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
36283818e4a7Sdavid.wu 			     IOMUX_WIDTH_3BIT,
3629c04c3fa6SDavid Wu 			     IOMUX_WIDTH_3BIT,
36303818e4a7Sdavid.wu 			     0,
36313818e4a7Sdavid.wu 			     0),
36323818e4a7Sdavid.wu };
36333818e4a7Sdavid.wu 
36343818e4a7Sdavid.wu static struct rockchip_pin_ctrl rk3328_pin_ctrl = {
36353818e4a7Sdavid.wu 		.pin_banks		= rk3328_pin_banks,
36363818e4a7Sdavid.wu 		.nr_banks		= ARRAY_SIZE(rk3328_pin_banks),
36373818e4a7Sdavid.wu 		.label			= "RK3328-GPIO",
36383818e4a7Sdavid.wu 		.type			= RK3288,
36393818e4a7Sdavid.wu 		.grf_mux_offset		= 0x0,
3640c04c3fa6SDavid Wu 		.iomux_recalced		= rk3328_mux_recalced_data,
3641c04c3fa6SDavid Wu 		.niomux_recalced	= ARRAY_SIZE(rk3328_mux_recalced_data),
3642cedc964aSDavid Wu 		.iomux_routes		= rk3328_mux_route_data,
3643cedc964aSDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3328_mux_route_data),
36443818e4a7Sdavid.wu 		.pull_calc_reg		= rk3228_calc_pull_reg_and_bit,
36453818e4a7Sdavid.wu 		.drv_calc_reg		= rk3228_calc_drv_reg_and_bit,
3646728d3f5aSdavid.wu 		.schmitt_calc_reg	= rk3328_calc_schmitt_reg_and_bit,
36473818e4a7Sdavid.wu };
36483818e4a7Sdavid.wu 
3649daecdc66SHeiko Stübner static struct rockchip_pin_bank rk3368_pin_banks[] = {
3650daecdc66SHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
3651daecdc66SHeiko Stübner 					     IOMUX_SOURCE_PMU,
3652daecdc66SHeiko Stübner 					     IOMUX_SOURCE_PMU,
3653daecdc66SHeiko Stübner 					     IOMUX_SOURCE_PMU
3654daecdc66SHeiko Stübner 			    ),
3655daecdc66SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
3656daecdc66SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
3657daecdc66SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
3658daecdc66SHeiko Stübner };
3659daecdc66SHeiko Stübner 
3660daecdc66SHeiko Stübner static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
3661daecdc66SHeiko Stübner 		.pin_banks		= rk3368_pin_banks,
3662daecdc66SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3368_pin_banks),
3663daecdc66SHeiko Stübner 		.label			= "RK3368-GPIO",
3664daecdc66SHeiko Stübner 		.type			= RK3368,
3665daecdc66SHeiko Stübner 		.grf_mux_offset		= 0x0,
3666daecdc66SHeiko Stübner 		.pmu_mux_offset		= 0x0,
3667daecdc66SHeiko Stübner 		.pull_calc_reg		= rk3368_calc_pull_reg_and_bit,
3668daecdc66SHeiko Stübner 		.drv_calc_reg		= rk3368_calc_drv_reg_and_bit,
3669daecdc66SHeiko Stübner };
3670daecdc66SHeiko Stübner 
3671b6c23275SDavid Wu static struct rockchip_pin_bank rk3399_pin_banks[] = {
36723ba6767aSDavid Wu 	PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0",
36733ba6767aSDavid Wu 							 IOMUX_SOURCE_PMU,
3674b6c23275SDavid Wu 							 IOMUX_SOURCE_PMU,
3675b6c23275SDavid Wu 							 IOMUX_SOURCE_PMU,
3676b6c23275SDavid Wu 							 IOMUX_SOURCE_PMU,
3677b6c23275SDavid Wu 							 DRV_TYPE_IO_1V8_ONLY,
3678b6c23275SDavid Wu 							 DRV_TYPE_IO_1V8_ONLY,
3679b6c23275SDavid Wu 							 DRV_TYPE_IO_DEFAULT,
3680b6c23275SDavid Wu 							 DRV_TYPE_IO_DEFAULT,
3681c437f65cSDavid Wu 							 0x80,
3682c437f65cSDavid Wu 							 0x88,
3683b6c23275SDavid Wu 							 -1,
36843ba6767aSDavid Wu 							 -1,
36853ba6767aSDavid Wu 							 PULL_TYPE_IO_1V8_ONLY,
36863ba6767aSDavid Wu 							 PULL_TYPE_IO_1V8_ONLY,
36873ba6767aSDavid Wu 							 PULL_TYPE_IO_DEFAULT,
36883ba6767aSDavid Wu 							 PULL_TYPE_IO_DEFAULT
3689b6c23275SDavid Wu 							),
3690b6c23275SDavid Wu 	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
3691b6c23275SDavid Wu 					IOMUX_SOURCE_PMU,
3692b6c23275SDavid Wu 					IOMUX_SOURCE_PMU,
3693b6c23275SDavid Wu 					IOMUX_SOURCE_PMU,
3694b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3695b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3696b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3697b6c23275SDavid Wu 					DRV_TYPE_IO_1V8_OR_3V0,
3698c437f65cSDavid Wu 					0xa0,
3699c437f65cSDavid Wu 					0xa8,
3700c437f65cSDavid Wu 					0xb0,
3701c437f65cSDavid Wu 					0xb8
3702b6c23275SDavid Wu 					),
37033ba6767aSDavid Wu 	PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
3704b6c23275SDavid Wu 				      DRV_TYPE_IO_1V8_OR_3V0,
3705b6c23275SDavid Wu 				      DRV_TYPE_IO_1V8_ONLY,
37063ba6767aSDavid Wu 				      DRV_TYPE_IO_1V8_ONLY,
37073ba6767aSDavid Wu 				      PULL_TYPE_IO_DEFAULT,
37083ba6767aSDavid Wu 				      PULL_TYPE_IO_DEFAULT,
37093ba6767aSDavid Wu 				      PULL_TYPE_IO_1V8_ONLY,
37103ba6767aSDavid Wu 				      PULL_TYPE_IO_1V8_ONLY
3711b6c23275SDavid Wu 				      ),
3712b6c23275SDavid Wu 	PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
3713b6c23275SDavid Wu 			   DRV_TYPE_IO_3V3_ONLY,
3714b6c23275SDavid Wu 			   DRV_TYPE_IO_3V3_ONLY,
3715b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_OR_3V0
3716b6c23275SDavid Wu 			   ),
3717b6c23275SDavid Wu 	PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0,
3718b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_3V0_AUTO,
3719b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_OR_3V0,
3720b6c23275SDavid Wu 			   DRV_TYPE_IO_1V8_OR_3V0
3721b6c23275SDavid Wu 			   ),
3722b6c23275SDavid Wu };
3723b6c23275SDavid Wu 
3724b6c23275SDavid Wu static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
3725b6c23275SDavid Wu 		.pin_banks		= rk3399_pin_banks,
3726b6c23275SDavid Wu 		.nr_banks		= ARRAY_SIZE(rk3399_pin_banks),
3727b6c23275SDavid Wu 		.label			= "RK3399-GPIO",
3728b6c23275SDavid Wu 		.type			= RK3399,
3729b6c23275SDavid Wu 		.grf_mux_offset		= 0xe000,
3730b6c23275SDavid Wu 		.pmu_mux_offset		= 0x0,
3731b6c23275SDavid Wu 		.grf_drv_offset		= 0xe100,
3732b6c23275SDavid Wu 		.pmu_drv_offset		= 0x80,
3733accc1ce7SDavid Wu 		.iomux_routes		= rk3399_mux_route_data,
3734accc1ce7SDavid Wu 		.niomux_routes		= ARRAY_SIZE(rk3399_mux_route_data),
3735b6c23275SDavid Wu 		.pull_calc_reg		= rk3399_calc_pull_reg_and_bit,
3736b6c23275SDavid Wu 		.drv_calc_reg		= rk3399_calc_drv_reg_and_bit,
3737b6c23275SDavid Wu };
3738daecdc66SHeiko Stübner 
3739d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[] = {
3740*87065ca9SDavid Wu 	{ .compatible = "rockchip,px30-pinctrl",
3741*87065ca9SDavid Wu 		.data = &px30_pin_ctrl },
3742b9c6dcabSAndy Yan 	{ .compatible = "rockchip,rv1108-pinctrl",
3743cdbbd26fSMasahiro Yamada 		.data = &rv1108_pin_ctrl },
3744d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk2928-pinctrl",
3745cdbbd26fSMasahiro Yamada 		.data = &rk2928_pin_ctrl },
3746c5ce7670SXing Zheng 	{ .compatible = "rockchip,rk3036-pinctrl",
3747cdbbd26fSMasahiro Yamada 		.data = &rk3036_pin_ctrl },
3748d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3066a-pinctrl",
3749cdbbd26fSMasahiro Yamada 		.data = &rk3066a_pin_ctrl },
3750d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3066b-pinctrl",
3751cdbbd26fSMasahiro Yamada 		.data = &rk3066b_pin_ctrl },
3752d23c66dfSDavid Wu 	{ .compatible = "rockchip,rk3128-pinctrl",
3753d23c66dfSDavid Wu 		.data = (void *)&rk3128_pin_ctrl },
3754d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3188-pinctrl",
3755cdbbd26fSMasahiro Yamada 		.data = &rk3188_pin_ctrl },
3756fea0fe60SJeffy Chen 	{ .compatible = "rockchip,rk3228-pinctrl",
3757cdbbd26fSMasahiro Yamada 		.data = &rk3228_pin_ctrl },
3758304f077dSHeiko Stübner 	{ .compatible = "rockchip,rk3288-pinctrl",
3759cdbbd26fSMasahiro Yamada 		.data = &rk3288_pin_ctrl },
37603818e4a7Sdavid.wu 	{ .compatible = "rockchip,rk3328-pinctrl",
3761cdbbd26fSMasahiro Yamada 		.data = &rk3328_pin_ctrl },
3762daecdc66SHeiko Stübner 	{ .compatible = "rockchip,rk3368-pinctrl",
3763cdbbd26fSMasahiro Yamada 		.data = &rk3368_pin_ctrl },
3764b6c23275SDavid Wu 	{ .compatible = "rockchip,rk3399-pinctrl",
3765cdbbd26fSMasahiro Yamada 		.data = &rk3399_pin_ctrl },
3766d3e51161SHeiko Stübner 	{},
3767d3e51161SHeiko Stübner };
3768d3e51161SHeiko Stübner 
3769d3e51161SHeiko Stübner static struct platform_driver rockchip_pinctrl_driver = {
3770d3e51161SHeiko Stübner 	.probe		= rockchip_pinctrl_probe,
3771d3e51161SHeiko Stübner 	.driver = {
3772d3e51161SHeiko Stübner 		.name	= "rockchip-pinctrl",
37739198f509SChris Zhong 		.pm = &rockchip_pinctrl_dev_pm_ops,
37740be9e70dSAxel Lin 		.of_match_table = rockchip_pinctrl_dt_match,
3775d3e51161SHeiko Stübner 	},
3776d3e51161SHeiko Stübner };
3777d3e51161SHeiko Stübner 
3778d3e51161SHeiko Stübner static int __init rockchip_pinctrl_drv_register(void)
3779d3e51161SHeiko Stübner {
3780d3e51161SHeiko Stübner 	return platform_driver_register(&rockchip_pinctrl_driver);
3781d3e51161SHeiko Stübner }
3782d3e51161SHeiko Stübner postcore_initcall(rockchip_pinctrl_drv_register);
3783