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 
26d3e51161SHeiko Stübner #include <linux/module.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 {
62a282926dSHeiko Stübner 	RK2928,
63a282926dSHeiko Stübner 	RK3066B,
64a282926dSHeiko Stübner 	RK3188,
6566d750e1SHeiko Stübner 	RK3288,
66a282926dSHeiko Stübner };
67a282926dSHeiko Stübner 
68fc72c923SHeiko Stübner /**
69fc72c923SHeiko Stübner  * Encode variants of iomux registers into a type variable
70fc72c923SHeiko Stübner  */
71fc72c923SHeiko Stübner #define IOMUX_GPIO_ONLY		BIT(0)
7203716e1dSHeiko Stübner #define IOMUX_WIDTH_4BIT	BIT(1)
7395ec8ae4SHeiko Stübner #define IOMUX_SOURCE_PMU	BIT(2)
7462f49226SHeiko Stübner #define IOMUX_UNROUTED		BIT(3)
75fc72c923SHeiko Stübner 
76fc72c923SHeiko Stübner /**
77fc72c923SHeiko Stübner  * @type: iomux variant using IOMUX_* constants
786bc0d121SHeiko Stübner  * @offset: if initialized to -1 it will be autocalculated, by specifying
796bc0d121SHeiko Stübner  *	    an initial offset value the relevant source offset can be reset
806bc0d121SHeiko Stübner  *	    to a new value for autocalculating the following iomux registers.
81fc72c923SHeiko Stübner  */
82fc72c923SHeiko Stübner struct rockchip_iomux {
83fc72c923SHeiko Stübner 	int				type;
846bc0d121SHeiko Stübner 	int				offset;
8565fca613SHeiko Stübner };
8665fca613SHeiko Stübner 
87d3e51161SHeiko Stübner /**
88d3e51161SHeiko Stübner  * @reg_base: register base of the gpio bank
896ca5274dSHeiko Stübner  * @reg_pull: optional separate register for additional pull settings
90d3e51161SHeiko Stübner  * @clk: clock of the gpio bank
91d3e51161SHeiko Stübner  * @irq: interrupt of the gpio bank
9268bda47cSDoug Anderson  * @saved_enables: Saved content of GPIO_INTEN at suspend time.
93d3e51161SHeiko Stübner  * @pin_base: first pin number
94d3e51161SHeiko Stübner  * @nr_pins: number of pins in this bank
95d3e51161SHeiko Stübner  * @name: name of the bank
96d3e51161SHeiko Stübner  * @bank_num: number of the bank, to account for holes
97fc72c923SHeiko Stübner  * @iomux: array describing the 4 iomux sources of the bank
98d3e51161SHeiko Stübner  * @valid: are all necessary informations present
99d3e51161SHeiko Stübner  * @of_node: dt node of this bank
100d3e51161SHeiko Stübner  * @drvdata: common pinctrl basedata
101d3e51161SHeiko Stübner  * @domain: irqdomain of the gpio bank
102d3e51161SHeiko Stübner  * @gpio_chip: gpiolib chip
103d3e51161SHeiko Stübner  * @grange: gpio range
104d3e51161SHeiko Stübner  * @slock: spinlock for the gpio bank
105d3e51161SHeiko Stübner  */
106d3e51161SHeiko Stübner struct rockchip_pin_bank {
107d3e51161SHeiko Stübner 	void __iomem			*reg_base;
108751a99abSHeiko Stübner 	struct regmap			*regmap_pull;
109d3e51161SHeiko Stübner 	struct clk			*clk;
110d3e51161SHeiko Stübner 	int				irq;
11168bda47cSDoug Anderson 	u32				saved_enables;
112d3e51161SHeiko Stübner 	u32				pin_base;
113d3e51161SHeiko Stübner 	u8				nr_pins;
114d3e51161SHeiko Stübner 	char				*name;
115d3e51161SHeiko Stübner 	u8				bank_num;
116fc72c923SHeiko Stübner 	struct rockchip_iomux		iomux[4];
117d3e51161SHeiko Stübner 	bool				valid;
118d3e51161SHeiko Stübner 	struct device_node		*of_node;
119d3e51161SHeiko Stübner 	struct rockchip_pinctrl		*drvdata;
120d3e51161SHeiko Stübner 	struct irq_domain		*domain;
121d3e51161SHeiko Stübner 	struct gpio_chip		gpio_chip;
122d3e51161SHeiko Stübner 	struct pinctrl_gpio_range	grange;
123d3e51161SHeiko Stübner 	spinlock_t			slock;
1245a927501SHeiko Stübner 	u32				toggle_edge_mode;
125d3e51161SHeiko Stübner };
126d3e51161SHeiko Stübner 
127d3e51161SHeiko Stübner #define PIN_BANK(id, pins, label)			\
128d3e51161SHeiko Stübner 	{						\
129d3e51161SHeiko Stübner 		.bank_num	= id,			\
130d3e51161SHeiko Stübner 		.nr_pins	= pins,			\
131d3e51161SHeiko Stübner 		.name		= label,		\
1326bc0d121SHeiko Stübner 		.iomux		= {			\
1336bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1346bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1356bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1366bc0d121SHeiko Stübner 			{ .offset = -1 },		\
1376bc0d121SHeiko Stübner 		},					\
138d3e51161SHeiko Stübner 	}
139d3e51161SHeiko Stübner 
140fc72c923SHeiko Stübner #define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3)	\
141fc72c923SHeiko Stübner 	{								\
142fc72c923SHeiko Stübner 		.bank_num	= id,					\
143fc72c923SHeiko Stübner 		.nr_pins	= pins,					\
144fc72c923SHeiko Stübner 		.name		= label,				\
145fc72c923SHeiko Stübner 		.iomux		= {					\
1466bc0d121SHeiko Stübner 			{ .type = iom0, .offset = -1 },			\
1476bc0d121SHeiko Stübner 			{ .type = iom1, .offset = -1 },			\
1486bc0d121SHeiko Stübner 			{ .type = iom2, .offset = -1 },			\
1496bc0d121SHeiko Stübner 			{ .type = iom3, .offset = -1 },			\
150fc72c923SHeiko Stübner 		},							\
151fc72c923SHeiko Stübner 	}
152fc72c923SHeiko Stübner 
153d3e51161SHeiko Stübner /**
154d3e51161SHeiko Stübner  */
155d3e51161SHeiko Stübner struct rockchip_pin_ctrl {
156d3e51161SHeiko Stübner 	struct rockchip_pin_bank	*pin_banks;
157d3e51161SHeiko Stübner 	u32				nr_banks;
158d3e51161SHeiko Stübner 	u32				nr_pins;
159d3e51161SHeiko Stübner 	char				*label;
160a282926dSHeiko Stübner 	enum rockchip_pinctrl_type	type;
16195ec8ae4SHeiko Stübner 	int				grf_mux_offset;
16295ec8ae4SHeiko Stübner 	int				pmu_mux_offset;
163751a99abSHeiko Stübner 	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank,
164751a99abSHeiko Stübner 				    int pin_num, struct regmap **regmap,
165751a99abSHeiko Stübner 				    int *reg, u8 *bit);
166d3e51161SHeiko Stübner };
167d3e51161SHeiko Stübner 
168d3e51161SHeiko Stübner struct rockchip_pin_config {
169d3e51161SHeiko Stübner 	unsigned int		func;
170d3e51161SHeiko Stübner 	unsigned long		*configs;
171d3e51161SHeiko Stübner 	unsigned int		nconfigs;
172d3e51161SHeiko Stübner };
173d3e51161SHeiko Stübner 
174d3e51161SHeiko Stübner /**
175d3e51161SHeiko Stübner  * struct rockchip_pin_group: represent group of pins of a pinmux function.
176d3e51161SHeiko Stübner  * @name: name of the pin group, used to lookup the group.
177d3e51161SHeiko Stübner  * @pins: the pins included in this group.
178d3e51161SHeiko Stübner  * @npins: number of pins included in this group.
179d3e51161SHeiko Stübner  * @func: the mux function number to be programmed when selected.
180d3e51161SHeiko Stübner  * @configs: the config values to be set for each pin
181d3e51161SHeiko Stübner  * @nconfigs: number of configs for each pin
182d3e51161SHeiko Stübner  */
183d3e51161SHeiko Stübner struct rockchip_pin_group {
184d3e51161SHeiko Stübner 	const char			*name;
185d3e51161SHeiko Stübner 	unsigned int			npins;
186d3e51161SHeiko Stübner 	unsigned int			*pins;
187d3e51161SHeiko Stübner 	struct rockchip_pin_config	*data;
188d3e51161SHeiko Stübner };
189d3e51161SHeiko Stübner 
190d3e51161SHeiko Stübner /**
191d3e51161SHeiko Stübner  * struct rockchip_pmx_func: represent a pin function.
192d3e51161SHeiko Stübner  * @name: name of the pin function, used to lookup the function.
193d3e51161SHeiko Stübner  * @groups: one or more names of pin groups that provide this function.
194d3e51161SHeiko Stübner  * @num_groups: number of groups included in @groups.
195d3e51161SHeiko Stübner  */
196d3e51161SHeiko Stübner struct rockchip_pmx_func {
197d3e51161SHeiko Stübner 	const char		*name;
198d3e51161SHeiko Stübner 	const char		**groups;
199d3e51161SHeiko Stübner 	u8			ngroups;
200d3e51161SHeiko Stübner };
201d3e51161SHeiko Stübner 
202d3e51161SHeiko Stübner struct rockchip_pinctrl {
203751a99abSHeiko Stübner 	struct regmap			*regmap_base;
204bfc7a42aSHeiko Stübner 	int				reg_size;
205751a99abSHeiko Stübner 	struct regmap			*regmap_pull;
20614dee867SHeiko Stübner 	struct regmap			*regmap_pmu;
207d3e51161SHeiko Stübner 	struct device			*dev;
208d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl	*ctrl;
209d3e51161SHeiko Stübner 	struct pinctrl_desc		pctl;
210d3e51161SHeiko Stübner 	struct pinctrl_dev		*pctl_dev;
211d3e51161SHeiko Stübner 	struct rockchip_pin_group	*groups;
212d3e51161SHeiko Stübner 	unsigned int			ngroups;
213d3e51161SHeiko Stübner 	struct rockchip_pmx_func	*functions;
214d3e51161SHeiko Stübner 	unsigned int			nfunctions;
215d3e51161SHeiko Stübner };
216d3e51161SHeiko Stübner 
217751a99abSHeiko Stübner static struct regmap_config rockchip_regmap_config = {
218751a99abSHeiko Stübner 	.reg_bits = 32,
219751a99abSHeiko Stübner 	.val_bits = 32,
220751a99abSHeiko Stübner 	.reg_stride = 4,
221751a99abSHeiko Stübner };
222751a99abSHeiko Stübner 
223d3e51161SHeiko Stübner static inline struct rockchip_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
224d3e51161SHeiko Stübner {
225d3e51161SHeiko Stübner 	return container_of(gc, struct rockchip_pin_bank, gpio_chip);
226d3e51161SHeiko Stübner }
227d3e51161SHeiko Stübner 
228d3e51161SHeiko Stübner static const inline struct rockchip_pin_group *pinctrl_name_to_group(
229d3e51161SHeiko Stübner 					const struct rockchip_pinctrl *info,
230d3e51161SHeiko Stübner 					const char *name)
231d3e51161SHeiko Stübner {
232d3e51161SHeiko Stübner 	int i;
233d3e51161SHeiko Stübner 
234d3e51161SHeiko Stübner 	for (i = 0; i < info->ngroups; i++) {
2351cb95395SAxel Lin 		if (!strcmp(info->groups[i].name, name))
2361cb95395SAxel Lin 			return &info->groups[i];
237d3e51161SHeiko Stübner 	}
238d3e51161SHeiko Stübner 
2391cb95395SAxel Lin 	return NULL;
240d3e51161SHeiko Stübner }
241d3e51161SHeiko Stübner 
242d3e51161SHeiko Stübner /*
243d3e51161SHeiko Stübner  * given a pin number that is local to a pin controller, find out the pin bank
244d3e51161SHeiko Stübner  * and the register base of the pin bank.
245d3e51161SHeiko Stübner  */
246d3e51161SHeiko Stübner static struct rockchip_pin_bank *pin_to_bank(struct rockchip_pinctrl *info,
247d3e51161SHeiko Stübner 								unsigned pin)
248d3e51161SHeiko Stübner {
249d3e51161SHeiko Stübner 	struct rockchip_pin_bank *b = info->ctrl->pin_banks;
250d3e51161SHeiko Stübner 
25151578b9bSAxel Lin 	while (pin >= (b->pin_base + b->nr_pins))
252d3e51161SHeiko Stübner 		b++;
253d3e51161SHeiko Stübner 
254d3e51161SHeiko Stübner 	return b;
255d3e51161SHeiko Stübner }
256d3e51161SHeiko Stübner 
257d3e51161SHeiko Stübner static struct rockchip_pin_bank *bank_num_to_bank(
258d3e51161SHeiko Stübner 					struct rockchip_pinctrl *info,
259d3e51161SHeiko Stübner 					unsigned num)
260d3e51161SHeiko Stübner {
261d3e51161SHeiko Stübner 	struct rockchip_pin_bank *b = info->ctrl->pin_banks;
262d3e51161SHeiko Stübner 	int i;
263d3e51161SHeiko Stübner 
2641cb95395SAxel Lin 	for (i = 0; i < info->ctrl->nr_banks; i++, b++) {
265d3e51161SHeiko Stübner 		if (b->bank_num == num)
2661cb95395SAxel Lin 			return b;
267d3e51161SHeiko Stübner 	}
268d3e51161SHeiko Stübner 
269d3e51161SHeiko Stübner 	return ERR_PTR(-EINVAL);
270d3e51161SHeiko Stübner }
271d3e51161SHeiko Stübner 
272d3e51161SHeiko Stübner /*
273d3e51161SHeiko Stübner  * Pinctrl_ops handling
274d3e51161SHeiko Stübner  */
275d3e51161SHeiko Stübner 
276d3e51161SHeiko Stübner static int rockchip_get_groups_count(struct pinctrl_dev *pctldev)
277d3e51161SHeiko Stübner {
278d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
279d3e51161SHeiko Stübner 
280d3e51161SHeiko Stübner 	return info->ngroups;
281d3e51161SHeiko Stübner }
282d3e51161SHeiko Stübner 
283d3e51161SHeiko Stübner static const char *rockchip_get_group_name(struct pinctrl_dev *pctldev,
284d3e51161SHeiko Stübner 							unsigned selector)
285d3e51161SHeiko Stübner {
286d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
287d3e51161SHeiko Stübner 
288d3e51161SHeiko Stübner 	return info->groups[selector].name;
289d3e51161SHeiko Stübner }
290d3e51161SHeiko Stübner 
291d3e51161SHeiko Stübner static int rockchip_get_group_pins(struct pinctrl_dev *pctldev,
292d3e51161SHeiko Stübner 				      unsigned selector, const unsigned **pins,
293d3e51161SHeiko Stübner 				      unsigned *npins)
294d3e51161SHeiko Stübner {
295d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
296d3e51161SHeiko Stübner 
297d3e51161SHeiko Stübner 	if (selector >= info->ngroups)
298d3e51161SHeiko Stübner 		return -EINVAL;
299d3e51161SHeiko Stübner 
300d3e51161SHeiko Stübner 	*pins = info->groups[selector].pins;
301d3e51161SHeiko Stübner 	*npins = info->groups[selector].npins;
302d3e51161SHeiko Stübner 
303d3e51161SHeiko Stübner 	return 0;
304d3e51161SHeiko Stübner }
305d3e51161SHeiko Stübner 
306d3e51161SHeiko Stübner static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev,
307d3e51161SHeiko Stübner 				 struct device_node *np,
308d3e51161SHeiko Stübner 				 struct pinctrl_map **map, unsigned *num_maps)
309d3e51161SHeiko Stübner {
310d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
311d3e51161SHeiko Stübner 	const struct rockchip_pin_group *grp;
312d3e51161SHeiko Stübner 	struct pinctrl_map *new_map;
313d3e51161SHeiko Stübner 	struct device_node *parent;
314d3e51161SHeiko Stübner 	int map_num = 1;
315d3e51161SHeiko Stübner 	int i;
316d3e51161SHeiko Stübner 
317d3e51161SHeiko Stübner 	/*
318d3e51161SHeiko Stübner 	 * first find the group of this node and check if we need to create
319d3e51161SHeiko Stübner 	 * config maps for pins
320d3e51161SHeiko Stübner 	 */
321d3e51161SHeiko Stübner 	grp = pinctrl_name_to_group(info, np->name);
322d3e51161SHeiko Stübner 	if (!grp) {
323d3e51161SHeiko Stübner 		dev_err(info->dev, "unable to find group for node %s\n",
324d3e51161SHeiko Stübner 			np->name);
325d3e51161SHeiko Stübner 		return -EINVAL;
326d3e51161SHeiko Stübner 	}
327d3e51161SHeiko Stübner 
328d3e51161SHeiko Stübner 	map_num += grp->npins;
329d3e51161SHeiko Stübner 	new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
330d3e51161SHeiko Stübner 								GFP_KERNEL);
331d3e51161SHeiko Stübner 	if (!new_map)
332d3e51161SHeiko Stübner 		return -ENOMEM;
333d3e51161SHeiko Stübner 
334d3e51161SHeiko Stübner 	*map = new_map;
335d3e51161SHeiko Stübner 	*num_maps = map_num;
336d3e51161SHeiko Stübner 
337d3e51161SHeiko Stübner 	/* create mux map */
338d3e51161SHeiko Stübner 	parent = of_get_parent(np);
339d3e51161SHeiko Stübner 	if (!parent) {
340d3e51161SHeiko Stübner 		devm_kfree(pctldev->dev, new_map);
341d3e51161SHeiko Stübner 		return -EINVAL;
342d3e51161SHeiko Stübner 	}
343d3e51161SHeiko Stübner 	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
344d3e51161SHeiko Stübner 	new_map[0].data.mux.function = parent->name;
345d3e51161SHeiko Stübner 	new_map[0].data.mux.group = np->name;
346d3e51161SHeiko Stübner 	of_node_put(parent);
347d3e51161SHeiko Stübner 
348d3e51161SHeiko Stübner 	/* create config map */
349d3e51161SHeiko Stübner 	new_map++;
350d3e51161SHeiko Stübner 	for (i = 0; i < grp->npins; i++) {
351d3e51161SHeiko Stübner 		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
352d3e51161SHeiko Stübner 		new_map[i].data.configs.group_or_pin =
353d3e51161SHeiko Stübner 				pin_get_name(pctldev, grp->pins[i]);
354d3e51161SHeiko Stübner 		new_map[i].data.configs.configs = grp->data[i].configs;
355d3e51161SHeiko Stübner 		new_map[i].data.configs.num_configs = grp->data[i].nconfigs;
356d3e51161SHeiko Stübner 	}
357d3e51161SHeiko Stübner 
358d3e51161SHeiko Stübner 	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
359d3e51161SHeiko Stübner 		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
360d3e51161SHeiko Stübner 
361d3e51161SHeiko Stübner 	return 0;
362d3e51161SHeiko Stübner }
363d3e51161SHeiko Stübner 
364d3e51161SHeiko Stübner static void rockchip_dt_free_map(struct pinctrl_dev *pctldev,
365d3e51161SHeiko Stübner 				    struct pinctrl_map *map, unsigned num_maps)
366d3e51161SHeiko Stübner {
367d3e51161SHeiko Stübner }
368d3e51161SHeiko Stübner 
369d3e51161SHeiko Stübner static const struct pinctrl_ops rockchip_pctrl_ops = {
370d3e51161SHeiko Stübner 	.get_groups_count	= rockchip_get_groups_count,
371d3e51161SHeiko Stübner 	.get_group_name		= rockchip_get_group_name,
372d3e51161SHeiko Stübner 	.get_group_pins		= rockchip_get_group_pins,
373d3e51161SHeiko Stübner 	.dt_node_to_map		= rockchip_dt_node_to_map,
374d3e51161SHeiko Stübner 	.dt_free_map		= rockchip_dt_free_map,
375d3e51161SHeiko Stübner };
376d3e51161SHeiko Stübner 
377d3e51161SHeiko Stübner /*
378d3e51161SHeiko Stübner  * Hardware access
379d3e51161SHeiko Stübner  */
380d3e51161SHeiko Stübner 
381a076e2edSHeiko Stübner static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
382a076e2edSHeiko Stübner {
383a076e2edSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
384fc72c923SHeiko Stübner 	int iomux_num = (pin / 8);
38595ec8ae4SHeiko Stübner 	struct regmap *regmap;
386751a99abSHeiko Stübner 	unsigned int val;
38703716e1dSHeiko Stübner 	int reg, ret, mask;
388a076e2edSHeiko Stübner 	u8 bit;
389a076e2edSHeiko Stübner 
390fc72c923SHeiko Stübner 	if (iomux_num > 3)
391fc72c923SHeiko Stübner 		return -EINVAL;
392fc72c923SHeiko Stübner 
39362f49226SHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
39462f49226SHeiko Stübner 		dev_err(info->dev, "pin %d is unrouted\n", pin);
39562f49226SHeiko Stübner 		return -EINVAL;
39662f49226SHeiko Stübner 	}
39762f49226SHeiko Stübner 
398fc72c923SHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
399a076e2edSHeiko Stübner 		return RK_FUNC_GPIO;
400a076e2edSHeiko Stübner 
40195ec8ae4SHeiko Stübner 	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
40295ec8ae4SHeiko Stübner 				? info->regmap_pmu : info->regmap_base;
40395ec8ae4SHeiko Stübner 
404a076e2edSHeiko Stübner 	/* get basic quadrupel of mux registers and the correct reg inside */
40503716e1dSHeiko Stübner 	mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
4066bc0d121SHeiko Stübner 	reg = bank->iomux[iomux_num].offset;
40703716e1dSHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
40803716e1dSHeiko Stübner 		if ((pin % 8) >= 4)
40903716e1dSHeiko Stübner 			reg += 0x4;
41003716e1dSHeiko Stübner 		bit = (pin % 4) * 4;
41103716e1dSHeiko Stübner 	} else {
412a076e2edSHeiko Stübner 		bit = (pin % 8) * 2;
41303716e1dSHeiko Stübner 	}
414a076e2edSHeiko Stübner 
41595ec8ae4SHeiko Stübner 	ret = regmap_read(regmap, reg, &val);
416751a99abSHeiko Stübner 	if (ret)
417751a99abSHeiko Stübner 		return ret;
418751a99abSHeiko Stübner 
41903716e1dSHeiko Stübner 	return ((val >> bit) & mask);
420a076e2edSHeiko Stübner }
421a076e2edSHeiko Stübner 
422d3e51161SHeiko Stübner /*
423d3e51161SHeiko Stübner  * Set a new mux function for a pin.
424d3e51161SHeiko Stübner  *
425d3e51161SHeiko Stübner  * The register is divided into the upper and lower 16 bit. When changing
426d3e51161SHeiko Stübner  * a value, the previous register value is not read and changed. Instead
427d3e51161SHeiko Stübner  * it seems the changed bits are marked in the upper 16 bit, while the
428d3e51161SHeiko Stübner  * changed value gets set in the same offset in the lower 16 bit.
429d3e51161SHeiko Stübner  * All pin settings seem to be 2 bit wide in both the upper and lower
430d3e51161SHeiko Stübner  * parts.
431d3e51161SHeiko Stübner  * @bank: pin bank to change
432d3e51161SHeiko Stübner  * @pin: pin to change
433d3e51161SHeiko Stübner  * @mux: new mux function to set
434d3e51161SHeiko Stübner  */
43514797189SHeiko Stübner static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
436d3e51161SHeiko Stübner {
437d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
438fc72c923SHeiko Stübner 	int iomux_num = (pin / 8);
43995ec8ae4SHeiko Stübner 	struct regmap *regmap;
44003716e1dSHeiko Stübner 	int reg, ret, mask;
441d3e51161SHeiko Stübner 	unsigned long flags;
442d3e51161SHeiko Stübner 	u8 bit;
44399e872d9SSonny Rao 	u32 data, rmask;
444d3e51161SHeiko Stübner 
445fc72c923SHeiko Stübner 	if (iomux_num > 3)
446fc72c923SHeiko Stübner 		return -EINVAL;
447fc72c923SHeiko Stübner 
44862f49226SHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
44962f49226SHeiko Stübner 		dev_err(info->dev, "pin %d is unrouted\n", pin);
45062f49226SHeiko Stübner 		return -EINVAL;
45162f49226SHeiko Stübner 	}
45262f49226SHeiko Stübner 
453fc72c923SHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
454c4a532deSHeiko Stübner 		if (mux != RK_FUNC_GPIO) {
455c4a532deSHeiko Stübner 			dev_err(info->dev,
456c4a532deSHeiko Stübner 				"pin %d only supports a gpio mux\n", pin);
457c4a532deSHeiko Stübner 			return -ENOTSUPP;
458c4a532deSHeiko Stübner 		} else {
459c4a532deSHeiko Stübner 			return 0;
460c4a532deSHeiko Stübner 		}
461c4a532deSHeiko Stübner 	}
462c4a532deSHeiko Stübner 
463d3e51161SHeiko Stübner 	dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n",
464d3e51161SHeiko Stübner 						bank->bank_num, pin, mux);
465d3e51161SHeiko Stübner 
46695ec8ae4SHeiko Stübner 	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
46795ec8ae4SHeiko Stübner 				? info->regmap_pmu : info->regmap_base;
46895ec8ae4SHeiko Stübner 
469d3e51161SHeiko Stübner 	/* get basic quadrupel of mux registers and the correct reg inside */
47003716e1dSHeiko Stübner 	mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
4716bc0d121SHeiko Stübner 	reg = bank->iomux[iomux_num].offset;
47203716e1dSHeiko Stübner 	if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
47303716e1dSHeiko Stübner 		if ((pin % 8) >= 4)
47403716e1dSHeiko Stübner 			reg += 0x4;
47503716e1dSHeiko Stübner 		bit = (pin % 4) * 4;
47603716e1dSHeiko Stübner 	} else {
477d3e51161SHeiko Stübner 		bit = (pin % 8) * 2;
47803716e1dSHeiko Stübner 	}
479d3e51161SHeiko Stübner 
480d3e51161SHeiko Stübner 	spin_lock_irqsave(&bank->slock, flags);
481d3e51161SHeiko Stübner 
48203716e1dSHeiko Stübner 	data = (mask << (bit + 16));
48399e872d9SSonny Rao 	rmask = data | (data >> 16);
48403716e1dSHeiko Stübner 	data |= (mux & mask) << bit;
48599e872d9SSonny Rao 	ret = regmap_update_bits(regmap, reg, rmask, data);
486d3e51161SHeiko Stübner 
487d3e51161SHeiko Stübner 	spin_unlock_irqrestore(&bank->slock, flags);
48814797189SHeiko Stübner 
489751a99abSHeiko Stübner 	return ret;
490d3e51161SHeiko Stübner }
491d3e51161SHeiko Stübner 
492a282926dSHeiko Stübner #define RK2928_PULL_OFFSET		0x118
493a282926dSHeiko Stübner #define RK2928_PULL_PINS_PER_REG	16
494a282926dSHeiko Stübner #define RK2928_PULL_BANK_STRIDE		8
495a282926dSHeiko Stübner 
496a282926dSHeiko Stübner static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
497751a99abSHeiko Stübner 				    int pin_num, struct regmap **regmap,
498751a99abSHeiko Stübner 				    int *reg, u8 *bit)
499a282926dSHeiko Stübner {
500a282926dSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
501a282926dSHeiko Stübner 
502751a99abSHeiko Stübner 	*regmap = info->regmap_base;
503751a99abSHeiko Stübner 	*reg = RK2928_PULL_OFFSET;
504a282926dSHeiko Stübner 	*reg += bank->bank_num * RK2928_PULL_BANK_STRIDE;
505a282926dSHeiko Stübner 	*reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4;
506a282926dSHeiko Stübner 
507a282926dSHeiko Stübner 	*bit = pin_num % RK2928_PULL_PINS_PER_REG;
508a282926dSHeiko Stübner };
509a282926dSHeiko Stübner 
510bfc7a42aSHeiko Stübner #define RK3188_PULL_OFFSET		0x164
5116ca5274dSHeiko Stübner #define RK3188_PULL_BITS_PER_PIN	2
5126ca5274dSHeiko Stübner #define RK3188_PULL_PINS_PER_REG	8
5136ca5274dSHeiko Stübner #define RK3188_PULL_BANK_STRIDE		16
51414dee867SHeiko Stübner #define RK3188_PULL_PMU_OFFSET		0x64
5156ca5274dSHeiko Stübner 
5166ca5274dSHeiko Stübner static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
517751a99abSHeiko Stübner 				    int pin_num, struct regmap **regmap,
518751a99abSHeiko Stübner 				    int *reg, u8 *bit)
5196ca5274dSHeiko Stübner {
5206ca5274dSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
5216ca5274dSHeiko Stübner 
5226ca5274dSHeiko Stübner 	/* The first 12 pins of the first bank are located elsewhere */
523fc72c923SHeiko Stübner 	if (bank->bank_num == 0 && pin_num < 12) {
52414dee867SHeiko Stübner 		*regmap = info->regmap_pmu ? info->regmap_pmu
52514dee867SHeiko Stübner 					   : bank->regmap_pull;
52614dee867SHeiko Stübner 		*reg = info->regmap_pmu ? RK3188_PULL_PMU_OFFSET : 0;
527751a99abSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
5286ca5274dSHeiko Stübner 		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
5296ca5274dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
5306ca5274dSHeiko Stübner 	} else {
531751a99abSHeiko Stübner 		*regmap = info->regmap_pull ? info->regmap_pull
532751a99abSHeiko Stübner 					    : info->regmap_base;
533751a99abSHeiko Stübner 		*reg = info->regmap_pull ? 0 : RK3188_PULL_OFFSET;
534751a99abSHeiko Stübner 
535bfc7a42aSHeiko Stübner 		/* correct the offset, as it is the 2nd pull register */
536bfc7a42aSHeiko Stübner 		*reg -= 4;
5376ca5274dSHeiko Stübner 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
5386ca5274dSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
5396ca5274dSHeiko Stübner 
5406ca5274dSHeiko Stübner 		/*
5416ca5274dSHeiko Stübner 		 * The bits in these registers have an inverse ordering
5426ca5274dSHeiko Stübner 		 * with the lowest pin being in bits 15:14 and the highest
5436ca5274dSHeiko Stübner 		 * pin in bits 1:0
5446ca5274dSHeiko Stübner 		 */
5456ca5274dSHeiko Stübner 		*bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG);
5466ca5274dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
5476ca5274dSHeiko Stübner 	}
5486ca5274dSHeiko Stübner }
5496ca5274dSHeiko Stübner 
550304f077dSHeiko Stübner #define RK3288_PULL_OFFSET		0x140
551304f077dSHeiko Stübner static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
552304f077dSHeiko Stübner 				    int pin_num, struct regmap **regmap,
553304f077dSHeiko Stübner 				    int *reg, u8 *bit)
554304f077dSHeiko Stübner {
555304f077dSHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
556304f077dSHeiko Stübner 
557304f077dSHeiko Stübner 	/* The first 24 pins of the first bank are located in PMU */
558304f077dSHeiko Stübner 	if (bank->bank_num == 0) {
559304f077dSHeiko Stübner 		*regmap = info->regmap_pmu;
560304f077dSHeiko Stübner 		*reg = RK3188_PULL_PMU_OFFSET;
561304f077dSHeiko Stübner 
562304f077dSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
563304f077dSHeiko Stübner 		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
564304f077dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
565304f077dSHeiko Stübner 	} else {
566304f077dSHeiko Stübner 		*regmap = info->regmap_base;
567304f077dSHeiko Stübner 		*reg = RK3288_PULL_OFFSET;
568304f077dSHeiko Stübner 
569304f077dSHeiko Stübner 		/* correct the offset, as we're starting with the 2nd bank */
570304f077dSHeiko Stübner 		*reg -= 0x10;
571304f077dSHeiko Stübner 		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
572304f077dSHeiko Stübner 		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
573304f077dSHeiko Stübner 
574304f077dSHeiko Stübner 		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
575304f077dSHeiko Stübner 		*bit *= RK3188_PULL_BITS_PER_PIN;
576304f077dSHeiko Stübner 	}
577304f077dSHeiko Stübner }
578304f077dSHeiko Stübner 
579b547c800SHeiko Stübner #define RK3288_DRV_PMU_OFFSET		0x70
580b547c800SHeiko Stübner #define RK3288_DRV_GRF_OFFSET		0x1c0
581b547c800SHeiko Stübner #define RK3288_DRV_BITS_PER_PIN		2
582b547c800SHeiko Stübner #define RK3288_DRV_PINS_PER_REG		8
583b547c800SHeiko Stübner #define RK3288_DRV_BANK_STRIDE		16
584b547c800SHeiko Stübner static int rk3288_drv_list[] = { 2, 4, 8, 12 };
585b547c800SHeiko Stübner 
586b547c800SHeiko Stübner static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
587b547c800SHeiko Stübner 				    int pin_num, struct regmap **regmap,
588b547c800SHeiko Stübner 				    int *reg, u8 *bit)
589b547c800SHeiko Stübner {
590b547c800SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
591b547c800SHeiko Stübner 
592b547c800SHeiko Stübner 	/* The first 24 pins of the first bank are located in PMU */
593b547c800SHeiko Stübner 	if (bank->bank_num == 0) {
594b547c800SHeiko Stübner 		*regmap = info->regmap_pmu;
595b547c800SHeiko Stübner 		*reg = RK3288_DRV_PMU_OFFSET;
596b547c800SHeiko Stübner 
597b547c800SHeiko Stübner 		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
598b547c800SHeiko Stübner 		*bit = pin_num % RK3288_DRV_PINS_PER_REG;
599b547c800SHeiko Stübner 		*bit *= RK3288_DRV_BITS_PER_PIN;
600b547c800SHeiko Stübner 	} else {
601b547c800SHeiko Stübner 		*regmap = info->regmap_base;
602b547c800SHeiko Stübner 		*reg = RK3288_DRV_GRF_OFFSET;
603b547c800SHeiko Stübner 
604b547c800SHeiko Stübner 		/* correct the offset, as we're starting with the 2nd bank */
605b547c800SHeiko Stübner 		*reg -= 0x10;
606b547c800SHeiko Stübner 		*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
607b547c800SHeiko Stübner 		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
608b547c800SHeiko Stübner 
609b547c800SHeiko Stübner 		*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
610b547c800SHeiko Stübner 		*bit *= RK3288_DRV_BITS_PER_PIN;
611b547c800SHeiko Stübner 	}
612b547c800SHeiko Stübner }
613b547c800SHeiko Stübner 
614b547c800SHeiko Stübner static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num)
615b547c800SHeiko Stübner {
616b547c800SHeiko Stübner 	struct regmap *regmap;
617b547c800SHeiko Stübner 	int reg, ret;
618b547c800SHeiko Stübner 	u32 data;
619b547c800SHeiko Stübner 	u8 bit;
620b547c800SHeiko Stübner 
621b547c800SHeiko Stübner 	rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
622b547c800SHeiko Stübner 
623b547c800SHeiko Stübner 	ret = regmap_read(regmap, reg, &data);
624b547c800SHeiko Stübner 	if (ret)
625b547c800SHeiko Stübner 		return ret;
626b547c800SHeiko Stübner 
627b547c800SHeiko Stübner 	data >>= bit;
628b547c800SHeiko Stübner 	data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1;
629b547c800SHeiko Stübner 
630b547c800SHeiko Stübner 	return rk3288_drv_list[data];
631b547c800SHeiko Stübner }
632b547c800SHeiko Stübner 
633b547c800SHeiko Stübner static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num,
634b547c800SHeiko Stübner 			    int strength)
635b547c800SHeiko Stübner {
636b547c800SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
637b547c800SHeiko Stübner 	struct regmap *regmap;
638b547c800SHeiko Stübner 	unsigned long flags;
639b547c800SHeiko Stübner 	int reg, ret, i;
64099e872d9SSonny Rao 	u32 data, rmask;
641b547c800SHeiko Stübner 	u8 bit;
642b547c800SHeiko Stübner 
643b547c800SHeiko Stübner 	rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
644b547c800SHeiko Stübner 
645b547c800SHeiko Stübner 	ret = -EINVAL;
646b547c800SHeiko Stübner 	for (i = 0; i < ARRAY_SIZE(rk3288_drv_list); i++) {
647b547c800SHeiko Stübner 		if (rk3288_drv_list[i] == strength) {
648b547c800SHeiko Stübner 			ret = i;
649b547c800SHeiko Stübner 			break;
650b547c800SHeiko Stübner 		}
651b547c800SHeiko Stübner 	}
652b547c800SHeiko Stübner 
653b547c800SHeiko Stübner 	if (ret < 0) {
654b547c800SHeiko Stübner 		dev_err(info->dev, "unsupported driver strength %d\n",
655b547c800SHeiko Stübner 			strength);
656b547c800SHeiko Stübner 		return ret;
657b547c800SHeiko Stübner 	}
658b547c800SHeiko Stübner 
659b547c800SHeiko Stübner 	spin_lock_irqsave(&bank->slock, flags);
660b547c800SHeiko Stübner 
661b547c800SHeiko Stübner 	/* enable the write to the equivalent lower bits */
662b547c800SHeiko Stübner 	data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16);
66399e872d9SSonny Rao 	rmask = data | (data >> 16);
664b547c800SHeiko Stübner 	data |= (ret << bit);
665b547c800SHeiko Stübner 
66699e872d9SSonny Rao 	ret = regmap_update_bits(regmap, reg, rmask, data);
667b547c800SHeiko Stübner 	spin_unlock_irqrestore(&bank->slock, flags);
668b547c800SHeiko Stübner 
669b547c800SHeiko Stübner 	return ret;
670b547c800SHeiko Stübner }
671b547c800SHeiko Stübner 
672d3e51161SHeiko Stübner static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
673d3e51161SHeiko Stübner {
674d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
675d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
676751a99abSHeiko Stübner 	struct regmap *regmap;
677751a99abSHeiko Stübner 	int reg, ret;
678d3e51161SHeiko Stübner 	u8 bit;
6796ca5274dSHeiko Stübner 	u32 data;
680d3e51161SHeiko Stübner 
681d3e51161SHeiko Stübner 	/* rk3066b does support any pulls */
682a282926dSHeiko Stübner 	if (ctrl->type == RK3066B)
683d3e51161SHeiko Stübner 		return PIN_CONFIG_BIAS_DISABLE;
684d3e51161SHeiko Stübner 
685751a99abSHeiko Stübner 	ctrl->pull_calc_reg(bank, pin_num, &regmap, &reg, &bit);
686751a99abSHeiko Stübner 
687751a99abSHeiko Stübner 	ret = regmap_read(regmap, reg, &data);
688751a99abSHeiko Stübner 	if (ret)
689751a99abSHeiko Stübner 		return ret;
6906ca5274dSHeiko Stübner 
691a282926dSHeiko Stübner 	switch (ctrl->type) {
692a282926dSHeiko Stübner 	case RK2928:
693751a99abSHeiko Stübner 		return !(data & BIT(bit))
694d3e51161SHeiko Stübner 				? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
695d3e51161SHeiko Stübner 				: PIN_CONFIG_BIAS_DISABLE;
696a282926dSHeiko Stübner 	case RK3188:
69766d750e1SHeiko Stübner 	case RK3288:
698751a99abSHeiko Stübner 		data >>= bit;
6996ca5274dSHeiko Stübner 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
7006ca5274dSHeiko Stübner 
7016ca5274dSHeiko Stübner 		switch (data) {
7026ca5274dSHeiko Stübner 		case 0:
7036ca5274dSHeiko Stübner 			return PIN_CONFIG_BIAS_DISABLE;
7046ca5274dSHeiko Stübner 		case 1:
7056ca5274dSHeiko Stübner 			return PIN_CONFIG_BIAS_PULL_UP;
7066ca5274dSHeiko Stübner 		case 2:
7076ca5274dSHeiko Stübner 			return PIN_CONFIG_BIAS_PULL_DOWN;
7086ca5274dSHeiko Stübner 		case 3:
7096ca5274dSHeiko Stübner 			return PIN_CONFIG_BIAS_BUS_HOLD;
7106ca5274dSHeiko Stübner 		}
7116ca5274dSHeiko Stübner 
7126ca5274dSHeiko Stübner 		dev_err(info->dev, "unknown pull setting\n");
713d3e51161SHeiko Stübner 		return -EIO;
714a282926dSHeiko Stübner 	default:
715a282926dSHeiko Stübner 		dev_err(info->dev, "unsupported pinctrl type\n");
716a282926dSHeiko Stübner 		return -EINVAL;
717a282926dSHeiko Stübner 	};
718d3e51161SHeiko Stübner }
719d3e51161SHeiko Stübner 
720d3e51161SHeiko Stübner static int rockchip_set_pull(struct rockchip_pin_bank *bank,
721d3e51161SHeiko Stübner 					int pin_num, int pull)
722d3e51161SHeiko Stübner {
723d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = bank->drvdata;
724d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
725751a99abSHeiko Stübner 	struct regmap *regmap;
726751a99abSHeiko Stübner 	int reg, ret;
727d3e51161SHeiko Stübner 	unsigned long flags;
728d3e51161SHeiko Stübner 	u8 bit;
72999e872d9SSonny Rao 	u32 data, rmask;
730d3e51161SHeiko Stübner 
731d3e51161SHeiko Stübner 	dev_dbg(info->dev, "setting pull of GPIO%d-%d to %d\n",
732d3e51161SHeiko Stübner 		 bank->bank_num, pin_num, pull);
733d3e51161SHeiko Stübner 
734d3e51161SHeiko Stübner 	/* rk3066b does support any pulls */
735a282926dSHeiko Stübner 	if (ctrl->type == RK3066B)
736d3e51161SHeiko Stübner 		return pull ? -EINVAL : 0;
737d3e51161SHeiko Stübner 
738751a99abSHeiko Stübner 	ctrl->pull_calc_reg(bank, pin_num, &regmap, &reg, &bit);
739d3e51161SHeiko Stübner 
7406ca5274dSHeiko Stübner 	switch (ctrl->type) {
7416ca5274dSHeiko Stübner 	case RK2928:
742d3e51161SHeiko Stübner 		spin_lock_irqsave(&bank->slock, flags);
743d3e51161SHeiko Stübner 
744d3e51161SHeiko Stübner 		data = BIT(bit + 16);
745d3e51161SHeiko Stübner 		if (pull == PIN_CONFIG_BIAS_DISABLE)
746d3e51161SHeiko Stübner 			data |= BIT(bit);
747751a99abSHeiko Stübner 		ret = regmap_write(regmap, reg, data);
748d3e51161SHeiko Stübner 
749d3e51161SHeiko Stübner 		spin_unlock_irqrestore(&bank->slock, flags);
750a282926dSHeiko Stübner 		break;
751a282926dSHeiko Stübner 	case RK3188:
75266d750e1SHeiko Stübner 	case RK3288:
7536ca5274dSHeiko Stübner 		spin_lock_irqsave(&bank->slock, flags);
7546ca5274dSHeiko Stübner 
7556ca5274dSHeiko Stübner 		/* enable the write to the equivalent lower bits */
7566ca5274dSHeiko Stübner 		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
75799e872d9SSonny Rao 		rmask = data | (data >> 16);
7586ca5274dSHeiko Stübner 
7596ca5274dSHeiko Stübner 		switch (pull) {
7606ca5274dSHeiko Stübner 		case PIN_CONFIG_BIAS_DISABLE:
7616ca5274dSHeiko Stübner 			break;
7626ca5274dSHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_UP:
7636ca5274dSHeiko Stübner 			data |= (1 << bit);
7646ca5274dSHeiko Stübner 			break;
7656ca5274dSHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_DOWN:
7666ca5274dSHeiko Stübner 			data |= (2 << bit);
7676ca5274dSHeiko Stübner 			break;
7686ca5274dSHeiko Stübner 		case PIN_CONFIG_BIAS_BUS_HOLD:
7696ca5274dSHeiko Stübner 			data |= (3 << bit);
7706ca5274dSHeiko Stübner 			break;
7716ca5274dSHeiko Stübner 		default:
772d32c3e26SDan Carpenter 			spin_unlock_irqrestore(&bank->slock, flags);
7736ca5274dSHeiko Stübner 			dev_err(info->dev, "unsupported pull setting %d\n",
7746ca5274dSHeiko Stübner 				pull);
7756ca5274dSHeiko Stübner 			return -EINVAL;
7766ca5274dSHeiko Stübner 		}
7776ca5274dSHeiko Stübner 
77899e872d9SSonny Rao 		ret = regmap_update_bits(regmap, reg, rmask, data);
7796ca5274dSHeiko Stübner 
7806ca5274dSHeiko Stübner 		spin_unlock_irqrestore(&bank->slock, flags);
7816ca5274dSHeiko Stübner 		break;
782a282926dSHeiko Stübner 	default:
783a282926dSHeiko Stübner 		dev_err(info->dev, "unsupported pinctrl type\n");
784a282926dSHeiko Stübner 		return -EINVAL;
785d3e51161SHeiko Stübner 	}
786d3e51161SHeiko Stübner 
787751a99abSHeiko Stübner 	return ret;
788d3e51161SHeiko Stübner }
789d3e51161SHeiko Stübner 
790d3e51161SHeiko Stübner /*
791d3e51161SHeiko Stübner  * Pinmux_ops handling
792d3e51161SHeiko Stübner  */
793d3e51161SHeiko Stübner 
794d3e51161SHeiko Stübner static int rockchip_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
795d3e51161SHeiko Stübner {
796d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
797d3e51161SHeiko Stübner 
798d3e51161SHeiko Stübner 	return info->nfunctions;
799d3e51161SHeiko Stübner }
800d3e51161SHeiko Stübner 
801d3e51161SHeiko Stübner static const char *rockchip_pmx_get_func_name(struct pinctrl_dev *pctldev,
802d3e51161SHeiko Stübner 					  unsigned selector)
803d3e51161SHeiko Stübner {
804d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
805d3e51161SHeiko Stübner 
806d3e51161SHeiko Stübner 	return info->functions[selector].name;
807d3e51161SHeiko Stübner }
808d3e51161SHeiko Stübner 
809d3e51161SHeiko Stübner static int rockchip_pmx_get_groups(struct pinctrl_dev *pctldev,
810d3e51161SHeiko Stübner 				unsigned selector, const char * const **groups,
811d3e51161SHeiko Stübner 				unsigned * const num_groups)
812d3e51161SHeiko Stübner {
813d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
814d3e51161SHeiko Stübner 
815d3e51161SHeiko Stübner 	*groups = info->functions[selector].groups;
816d3e51161SHeiko Stübner 	*num_groups = info->functions[selector].ngroups;
817d3e51161SHeiko Stübner 
818d3e51161SHeiko Stübner 	return 0;
819d3e51161SHeiko Stübner }
820d3e51161SHeiko Stübner 
82103e9f0caSLinus Walleij static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
822d3e51161SHeiko Stübner 			    unsigned group)
823d3e51161SHeiko Stübner {
824d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
825d3e51161SHeiko Stübner 	const unsigned int *pins = info->groups[group].pins;
826d3e51161SHeiko Stübner 	const struct rockchip_pin_config *data = info->groups[group].data;
827d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
82814797189SHeiko Stübner 	int cnt, ret = 0;
829d3e51161SHeiko Stübner 
830d3e51161SHeiko Stübner 	dev_dbg(info->dev, "enable function %s group %s\n",
831d3e51161SHeiko Stübner 		info->functions[selector].name, info->groups[group].name);
832d3e51161SHeiko Stübner 
833d3e51161SHeiko Stübner 	/*
834d3e51161SHeiko Stübner 	 * for each pin in the pin group selected, program the correspoding pin
835d3e51161SHeiko Stübner 	 * pin function number in the config register.
836d3e51161SHeiko Stübner 	 */
837d3e51161SHeiko Stübner 	for (cnt = 0; cnt < info->groups[group].npins; cnt++) {
838d3e51161SHeiko Stübner 		bank = pin_to_bank(info, pins[cnt]);
83914797189SHeiko Stübner 		ret = rockchip_set_mux(bank, pins[cnt] - bank->pin_base,
840d3e51161SHeiko Stübner 				       data[cnt].func);
84114797189SHeiko Stübner 		if (ret)
84214797189SHeiko Stübner 			break;
84314797189SHeiko Stübner 	}
84414797189SHeiko Stübner 
84514797189SHeiko Stübner 	if (ret) {
84614797189SHeiko Stübner 		/* revert the already done pin settings */
84714797189SHeiko Stübner 		for (cnt--; cnt >= 0; cnt--)
84814797189SHeiko Stübner 			rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0);
84914797189SHeiko Stübner 
85014797189SHeiko Stübner 		return ret;
851d3e51161SHeiko Stübner 	}
852d3e51161SHeiko Stübner 
853d3e51161SHeiko Stübner 	return 0;
854d3e51161SHeiko Stübner }
855d3e51161SHeiko Stübner 
856d3e51161SHeiko Stübner /*
857d3e51161SHeiko Stübner  * The calls to gpio_direction_output() and gpio_direction_input()
858d3e51161SHeiko Stübner  * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
859d3e51161SHeiko Stübner  * function called from the gpiolib interface).
860d3e51161SHeiko Stübner  */
861e5c2c9dbSDoug Anderson static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip,
862e5c2c9dbSDoug Anderson 					    int pin, bool input)
863d3e51161SHeiko Stübner {
864d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
865e5c2c9dbSDoug Anderson 	int ret;
866fab262f5SDoug Anderson 	unsigned long flags;
867d3e51161SHeiko Stübner 	u32 data;
868d3e51161SHeiko Stübner 
869d3e51161SHeiko Stübner 	bank = gc_to_pin_bank(chip);
870d3e51161SHeiko Stübner 
87114797189SHeiko Stübner 	ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO);
87214797189SHeiko Stübner 	if (ret < 0)
87314797189SHeiko Stübner 		return ret;
874d3e51161SHeiko Stübner 
875fab262f5SDoug Anderson 	spin_lock_irqsave(&bank->slock, flags);
876fab262f5SDoug Anderson 
877d3e51161SHeiko Stübner 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
878d3e51161SHeiko Stübner 	/* set bit to 1 for output, 0 for input */
879d3e51161SHeiko Stübner 	if (!input)
880d3e51161SHeiko Stübner 		data |= BIT(pin);
881d3e51161SHeiko Stübner 	else
882d3e51161SHeiko Stübner 		data &= ~BIT(pin);
883d3e51161SHeiko Stübner 	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
884d3e51161SHeiko Stübner 
885fab262f5SDoug Anderson 	spin_unlock_irqrestore(&bank->slock, flags);
886fab262f5SDoug Anderson 
887d3e51161SHeiko Stübner 	return 0;
888d3e51161SHeiko Stübner }
889d3e51161SHeiko Stübner 
890e5c2c9dbSDoug Anderson static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
891e5c2c9dbSDoug Anderson 					      struct pinctrl_gpio_range *range,
892e5c2c9dbSDoug Anderson 					      unsigned offset, bool input)
893e5c2c9dbSDoug Anderson {
894e5c2c9dbSDoug Anderson 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
895e5c2c9dbSDoug Anderson 	struct gpio_chip *chip;
896e5c2c9dbSDoug Anderson 	int pin;
897e5c2c9dbSDoug Anderson 
898e5c2c9dbSDoug Anderson 	chip = range->gc;
899e5c2c9dbSDoug Anderson 	pin = offset - chip->base;
900e5c2c9dbSDoug Anderson 	dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n",
901e5c2c9dbSDoug Anderson 		 offset, range->name, pin, input ? "input" : "output");
902e5c2c9dbSDoug Anderson 
903e5c2c9dbSDoug Anderson 	return _rockchip_pmx_gpio_set_direction(chip, offset - chip->base,
904e5c2c9dbSDoug Anderson 						input);
905e5c2c9dbSDoug Anderson }
906e5c2c9dbSDoug Anderson 
907d3e51161SHeiko Stübner static const struct pinmux_ops rockchip_pmx_ops = {
908d3e51161SHeiko Stübner 	.get_functions_count	= rockchip_pmx_get_funcs_count,
909d3e51161SHeiko Stübner 	.get_function_name	= rockchip_pmx_get_func_name,
910d3e51161SHeiko Stübner 	.get_function_groups	= rockchip_pmx_get_groups,
91103e9f0caSLinus Walleij 	.set_mux		= rockchip_pmx_set,
912d3e51161SHeiko Stübner 	.gpio_set_direction	= rockchip_pmx_gpio_set_direction,
913d3e51161SHeiko Stübner };
914d3e51161SHeiko Stübner 
915d3e51161SHeiko Stübner /*
916d3e51161SHeiko Stübner  * Pinconf_ops handling
917d3e51161SHeiko Stübner  */
918d3e51161SHeiko Stübner 
91944b6d930SHeiko Stübner static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
92044b6d930SHeiko Stübner 					enum pin_config_param pull)
92144b6d930SHeiko Stübner {
922a282926dSHeiko Stübner 	switch (ctrl->type) {
923a282926dSHeiko Stübner 	case RK2928:
924a282926dSHeiko Stübner 		return (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT ||
925a282926dSHeiko Stübner 					pull == PIN_CONFIG_BIAS_DISABLE);
926a282926dSHeiko Stübner 	case RK3066B:
92744b6d930SHeiko Stübner 		return pull ? false : true;
928a282926dSHeiko Stübner 	case RK3188:
92966d750e1SHeiko Stübner 	case RK3288:
930a282926dSHeiko Stübner 		return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
93144b6d930SHeiko Stübner 	}
93244b6d930SHeiko Stübner 
933a282926dSHeiko Stübner 	return false;
93444b6d930SHeiko Stübner }
93544b6d930SHeiko Stübner 
936e5c2c9dbSDoug Anderson static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value);
937a076e2edSHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset);
938a076e2edSHeiko Stübner 
939d3e51161SHeiko Stübner /* set the pin config settings for a specified pin */
940d3e51161SHeiko Stübner static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
94103b054e9SSherman Yin 				unsigned long *configs, unsigned num_configs)
942d3e51161SHeiko Stübner {
943d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
944d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = pin_to_bank(info, pin);
94503b054e9SSherman Yin 	enum pin_config_param param;
94603b054e9SSherman Yin 	u16 arg;
94703b054e9SSherman Yin 	int i;
94803b054e9SSherman Yin 	int rc;
94903b054e9SSherman Yin 
95003b054e9SSherman Yin 	for (i = 0; i < num_configs; i++) {
95103b054e9SSherman Yin 		param = pinconf_to_config_param(configs[i]);
95203b054e9SSherman Yin 		arg = pinconf_to_config_argument(configs[i]);
953d3e51161SHeiko Stübner 
954d3e51161SHeiko Stübner 		switch (param) {
955d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_DISABLE:
95603b054e9SSherman Yin 			rc =  rockchip_set_pull(bank, pin - bank->pin_base,
95703b054e9SSherman Yin 				param);
95803b054e9SSherman Yin 			if (rc)
95903b054e9SSherman Yin 				return rc;
96044b6d930SHeiko Stübner 			break;
961d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_UP:
962d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_DOWN:
963d3e51161SHeiko Stübner 		case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
9646ca5274dSHeiko Stübner 		case PIN_CONFIG_BIAS_BUS_HOLD:
96544b6d930SHeiko Stübner 			if (!rockchip_pinconf_pull_valid(info->ctrl, param))
96644b6d930SHeiko Stübner 				return -ENOTSUPP;
96744b6d930SHeiko Stübner 
96844b6d930SHeiko Stübner 			if (!arg)
96944b6d930SHeiko Stübner 				return -EINVAL;
97044b6d930SHeiko Stübner 
97103b054e9SSherman Yin 			rc = rockchip_set_pull(bank, pin - bank->pin_base,
97203b054e9SSherman Yin 				param);
97303b054e9SSherman Yin 			if (rc)
97403b054e9SSherman Yin 				return rc;
975d3e51161SHeiko Stübner 			break;
976a076e2edSHeiko Stübner 		case PIN_CONFIG_OUTPUT:
977e5c2c9dbSDoug Anderson 			rockchip_gpio_set(&bank->gpio_chip,
978e5c2c9dbSDoug Anderson 					  pin - bank->pin_base, arg);
979e5c2c9dbSDoug Anderson 			rc = _rockchip_pmx_gpio_set_direction(&bank->gpio_chip,
980e5c2c9dbSDoug Anderson 					  pin - bank->pin_base, false);
981a076e2edSHeiko Stübner 			if (rc)
982a076e2edSHeiko Stübner 				return rc;
983a076e2edSHeiko Stübner 			break;
984b547c800SHeiko Stübner 		case PIN_CONFIG_DRIVE_STRENGTH:
985b547c800SHeiko Stübner 			/* rk3288 is the first with per-pin drive-strength */
986b547c800SHeiko Stübner 			if (info->ctrl->type != RK3288)
987b547c800SHeiko Stübner 				return -ENOTSUPP;
988b547c800SHeiko Stübner 
989b547c800SHeiko Stübner 			rc = rk3288_set_drive(bank, pin - bank->pin_base, arg);
990b547c800SHeiko Stübner 			if (rc < 0)
991b547c800SHeiko Stübner 				return rc;
992b547c800SHeiko Stübner 			break;
993d3e51161SHeiko Stübner 		default:
994d3e51161SHeiko Stübner 			return -ENOTSUPP;
995d3e51161SHeiko Stübner 			break;
996d3e51161SHeiko Stübner 		}
99703b054e9SSherman Yin 	} /* for each config */
998d3e51161SHeiko Stübner 
999d3e51161SHeiko Stübner 	return 0;
1000d3e51161SHeiko Stübner }
1001d3e51161SHeiko Stübner 
1002d3e51161SHeiko Stübner /* get the pin config settings for a specified pin */
1003d3e51161SHeiko Stübner static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
1004d3e51161SHeiko Stübner 							unsigned long *config)
1005d3e51161SHeiko Stübner {
1006d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
1007d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = pin_to_bank(info, pin);
1008d3e51161SHeiko Stübner 	enum pin_config_param param = pinconf_to_config_param(*config);
1009dab3eba7SHeiko Stübner 	u16 arg;
1010a076e2edSHeiko Stübner 	int rc;
1011d3e51161SHeiko Stübner 
1012d3e51161SHeiko Stübner 	switch (param) {
1013d3e51161SHeiko Stübner 	case PIN_CONFIG_BIAS_DISABLE:
101444b6d930SHeiko Stübner 		if (rockchip_get_pull(bank, pin - bank->pin_base) != param)
1015d3e51161SHeiko Stübner 			return -EINVAL;
1016d3e51161SHeiko Stübner 
1017dab3eba7SHeiko Stübner 		arg = 0;
1018d3e51161SHeiko Stübner 		break;
101944b6d930SHeiko Stübner 	case PIN_CONFIG_BIAS_PULL_UP:
102044b6d930SHeiko Stübner 	case PIN_CONFIG_BIAS_PULL_DOWN:
102144b6d930SHeiko Stübner 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
10226ca5274dSHeiko Stübner 	case PIN_CONFIG_BIAS_BUS_HOLD:
102344b6d930SHeiko Stübner 		if (!rockchip_pinconf_pull_valid(info->ctrl, param))
102444b6d930SHeiko Stübner 			return -ENOTSUPP;
102544b6d930SHeiko Stübner 
102644b6d930SHeiko Stübner 		if (rockchip_get_pull(bank, pin - bank->pin_base) != param)
102744b6d930SHeiko Stübner 			return -EINVAL;
102844b6d930SHeiko Stübner 
1029dab3eba7SHeiko Stübner 		arg = 1;
103044b6d930SHeiko Stübner 		break;
1031a076e2edSHeiko Stübner 	case PIN_CONFIG_OUTPUT:
1032a076e2edSHeiko Stübner 		rc = rockchip_get_mux(bank, pin - bank->pin_base);
1033a076e2edSHeiko Stübner 		if (rc != RK_FUNC_GPIO)
1034a076e2edSHeiko Stübner 			return -EINVAL;
1035a076e2edSHeiko Stübner 
1036a076e2edSHeiko Stübner 		rc = rockchip_gpio_get(&bank->gpio_chip, pin - bank->pin_base);
1037a076e2edSHeiko Stübner 		if (rc < 0)
1038a076e2edSHeiko Stübner 			return rc;
1039a076e2edSHeiko Stübner 
1040a076e2edSHeiko Stübner 		arg = rc ? 1 : 0;
1041a076e2edSHeiko Stübner 		break;
1042b547c800SHeiko Stübner 	case PIN_CONFIG_DRIVE_STRENGTH:
1043b547c800SHeiko Stübner 		/* rk3288 is the first with per-pin drive-strength */
1044b547c800SHeiko Stübner 		if (info->ctrl->type != RK3288)
1045b547c800SHeiko Stübner 			return -ENOTSUPP;
1046b547c800SHeiko Stübner 
1047b547c800SHeiko Stübner 		rc = rk3288_get_drive(bank, pin - bank->pin_base);
1048b547c800SHeiko Stübner 		if (rc < 0)
1049b547c800SHeiko Stübner 			return rc;
1050b547c800SHeiko Stübner 
1051b547c800SHeiko Stübner 		arg = rc;
1052b547c800SHeiko Stübner 		break;
1053d3e51161SHeiko Stübner 	default:
1054d3e51161SHeiko Stübner 		return -ENOTSUPP;
1055d3e51161SHeiko Stübner 		break;
1056d3e51161SHeiko Stübner 	}
1057d3e51161SHeiko Stübner 
1058dab3eba7SHeiko Stübner 	*config = pinconf_to_config_packed(param, arg);
1059dab3eba7SHeiko Stübner 
1060d3e51161SHeiko Stübner 	return 0;
1061d3e51161SHeiko Stübner }
1062d3e51161SHeiko Stübner 
1063d3e51161SHeiko Stübner static const struct pinconf_ops rockchip_pinconf_ops = {
1064d3e51161SHeiko Stübner 	.pin_config_get			= rockchip_pinconf_get,
1065d3e51161SHeiko Stübner 	.pin_config_set			= rockchip_pinconf_set,
1066ed62f2f2SHeiko Stübner 	.is_generic			= true,
1067d3e51161SHeiko Stübner };
1068d3e51161SHeiko Stübner 
106965fca613SHeiko Stübner static const struct of_device_id rockchip_bank_match[] = {
107065fca613SHeiko Stübner 	{ .compatible = "rockchip,gpio-bank" },
10716ca5274dSHeiko Stübner 	{ .compatible = "rockchip,rk3188-gpio-bank0" },
107265fca613SHeiko Stübner 	{},
107365fca613SHeiko Stübner };
1074d3e51161SHeiko Stübner 
1075d3e51161SHeiko Stübner static void rockchip_pinctrl_child_count(struct rockchip_pinctrl *info,
1076d3e51161SHeiko Stübner 						struct device_node *np)
1077d3e51161SHeiko Stübner {
1078d3e51161SHeiko Stübner 	struct device_node *child;
1079d3e51161SHeiko Stübner 
1080d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
108165fca613SHeiko Stübner 		if (of_match_node(rockchip_bank_match, child))
1082d3e51161SHeiko Stübner 			continue;
1083d3e51161SHeiko Stübner 
1084d3e51161SHeiko Stübner 		info->nfunctions++;
1085d3e51161SHeiko Stübner 		info->ngroups += of_get_child_count(child);
1086d3e51161SHeiko Stübner 	}
1087d3e51161SHeiko Stübner }
1088d3e51161SHeiko Stübner 
1089d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_groups(struct device_node *np,
1090d3e51161SHeiko Stübner 					      struct rockchip_pin_group *grp,
1091d3e51161SHeiko Stübner 					      struct rockchip_pinctrl *info,
1092d3e51161SHeiko Stübner 					      u32 index)
1093d3e51161SHeiko Stübner {
1094d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
1095d3e51161SHeiko Stübner 	int size;
1096d3e51161SHeiko Stübner 	const __be32 *list;
1097d3e51161SHeiko Stübner 	int num;
1098d3e51161SHeiko Stübner 	int i, j;
1099d3e51161SHeiko Stübner 	int ret;
1100d3e51161SHeiko Stübner 
1101d3e51161SHeiko Stübner 	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
1102d3e51161SHeiko Stübner 
1103d3e51161SHeiko Stübner 	/* Initialise group */
1104d3e51161SHeiko Stübner 	grp->name = np->name;
1105d3e51161SHeiko Stübner 
1106d3e51161SHeiko Stübner 	/*
1107d3e51161SHeiko Stübner 	 * the binding format is rockchip,pins = <bank pin mux CONFIG>,
1108d3e51161SHeiko Stübner 	 * do sanity check and calculate pins number
1109d3e51161SHeiko Stübner 	 */
1110d3e51161SHeiko Stübner 	list = of_get_property(np, "rockchip,pins", &size);
1111d3e51161SHeiko Stübner 	/* we do not check return since it's safe node passed down */
1112d3e51161SHeiko Stübner 	size /= sizeof(*list);
1113d3e51161SHeiko Stübner 	if (!size || size % 4) {
1114d3e51161SHeiko Stübner 		dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n");
1115d3e51161SHeiko Stübner 		return -EINVAL;
1116d3e51161SHeiko Stübner 	}
1117d3e51161SHeiko Stübner 
1118d3e51161SHeiko Stübner 	grp->npins = size / 4;
1119d3e51161SHeiko Stübner 
1120d3e51161SHeiko Stübner 	grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
1121d3e51161SHeiko Stübner 						GFP_KERNEL);
1122d3e51161SHeiko Stübner 	grp->data = devm_kzalloc(info->dev, grp->npins *
1123d3e51161SHeiko Stübner 					  sizeof(struct rockchip_pin_config),
1124d3e51161SHeiko Stübner 					GFP_KERNEL);
1125d3e51161SHeiko Stübner 	if (!grp->pins || !grp->data)
1126d3e51161SHeiko Stübner 		return -ENOMEM;
1127d3e51161SHeiko Stübner 
1128d3e51161SHeiko Stübner 	for (i = 0, j = 0; i < size; i += 4, j++) {
1129d3e51161SHeiko Stübner 		const __be32 *phandle;
1130d3e51161SHeiko Stübner 		struct device_node *np_config;
1131d3e51161SHeiko Stübner 
1132d3e51161SHeiko Stübner 		num = be32_to_cpu(*list++);
1133d3e51161SHeiko Stübner 		bank = bank_num_to_bank(info, num);
1134d3e51161SHeiko Stübner 		if (IS_ERR(bank))
1135d3e51161SHeiko Stübner 			return PTR_ERR(bank);
1136d3e51161SHeiko Stübner 
1137d3e51161SHeiko Stübner 		grp->pins[j] = bank->pin_base + be32_to_cpu(*list++);
1138d3e51161SHeiko Stübner 		grp->data[j].func = be32_to_cpu(*list++);
1139d3e51161SHeiko Stübner 
1140d3e51161SHeiko Stübner 		phandle = list++;
1141d3e51161SHeiko Stübner 		if (!phandle)
1142d3e51161SHeiko Stübner 			return -EINVAL;
1143d3e51161SHeiko Stübner 
1144d3e51161SHeiko Stübner 		np_config = of_find_node_by_phandle(be32_to_cpup(phandle));
1145d3e51161SHeiko Stübner 		ret = pinconf_generic_parse_dt_config(np_config,
1146d3e51161SHeiko Stübner 				&grp->data[j].configs, &grp->data[j].nconfigs);
1147d3e51161SHeiko Stübner 		if (ret)
1148d3e51161SHeiko Stübner 			return ret;
1149d3e51161SHeiko Stübner 	}
1150d3e51161SHeiko Stübner 
1151d3e51161SHeiko Stübner 	return 0;
1152d3e51161SHeiko Stübner }
1153d3e51161SHeiko Stübner 
1154d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_functions(struct device_node *np,
1155d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info,
1156d3e51161SHeiko Stübner 						u32 index)
1157d3e51161SHeiko Stübner {
1158d3e51161SHeiko Stübner 	struct device_node *child;
1159d3e51161SHeiko Stübner 	struct rockchip_pmx_func *func;
1160d3e51161SHeiko Stübner 	struct rockchip_pin_group *grp;
1161d3e51161SHeiko Stübner 	int ret;
1162d3e51161SHeiko Stübner 	static u32 grp_index;
1163d3e51161SHeiko Stübner 	u32 i = 0;
1164d3e51161SHeiko Stübner 
1165d3e51161SHeiko Stübner 	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
1166d3e51161SHeiko Stübner 
1167d3e51161SHeiko Stübner 	func = &info->functions[index];
1168d3e51161SHeiko Stübner 
1169d3e51161SHeiko Stübner 	/* Initialise function */
1170d3e51161SHeiko Stübner 	func->name = np->name;
1171d3e51161SHeiko Stübner 	func->ngroups = of_get_child_count(np);
1172d3e51161SHeiko Stübner 	if (func->ngroups <= 0)
1173d3e51161SHeiko Stübner 		return 0;
1174d3e51161SHeiko Stübner 
1175d3e51161SHeiko Stübner 	func->groups = devm_kzalloc(info->dev,
1176d3e51161SHeiko Stübner 			func->ngroups * sizeof(char *), GFP_KERNEL);
1177d3e51161SHeiko Stübner 	if (!func->groups)
1178d3e51161SHeiko Stübner 		return -ENOMEM;
1179d3e51161SHeiko Stübner 
1180d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
1181d3e51161SHeiko Stübner 		func->groups[i] = child->name;
1182d3e51161SHeiko Stübner 		grp = &info->groups[grp_index++];
1183d3e51161SHeiko Stübner 		ret = rockchip_pinctrl_parse_groups(child, grp, info, i++);
1184d3e51161SHeiko Stübner 		if (ret)
1185d3e51161SHeiko Stübner 			return ret;
1186d3e51161SHeiko Stübner 	}
1187d3e51161SHeiko Stübner 
1188d3e51161SHeiko Stübner 	return 0;
1189d3e51161SHeiko Stübner }
1190d3e51161SHeiko Stübner 
1191d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_dt(struct platform_device *pdev,
1192d3e51161SHeiko Stübner 					      struct rockchip_pinctrl *info)
1193d3e51161SHeiko Stübner {
1194d3e51161SHeiko Stübner 	struct device *dev = &pdev->dev;
1195d3e51161SHeiko Stübner 	struct device_node *np = dev->of_node;
1196d3e51161SHeiko Stübner 	struct device_node *child;
1197d3e51161SHeiko Stübner 	int ret;
1198d3e51161SHeiko Stübner 	int i;
1199d3e51161SHeiko Stübner 
1200d3e51161SHeiko Stübner 	rockchip_pinctrl_child_count(info, np);
1201d3e51161SHeiko Stübner 
1202d3e51161SHeiko Stübner 	dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
1203d3e51161SHeiko Stübner 	dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
1204d3e51161SHeiko Stübner 
1205d3e51161SHeiko Stübner 	info->functions = devm_kzalloc(dev, info->nfunctions *
1206d3e51161SHeiko Stübner 					      sizeof(struct rockchip_pmx_func),
1207d3e51161SHeiko Stübner 					      GFP_KERNEL);
1208d3e51161SHeiko Stübner 	if (!info->functions) {
1209d3e51161SHeiko Stübner 		dev_err(dev, "failed to allocate memory for function list\n");
1210d3e51161SHeiko Stübner 		return -EINVAL;
1211d3e51161SHeiko Stübner 	}
1212d3e51161SHeiko Stübner 
1213d3e51161SHeiko Stübner 	info->groups = devm_kzalloc(dev, info->ngroups *
1214d3e51161SHeiko Stübner 					    sizeof(struct rockchip_pin_group),
1215d3e51161SHeiko Stübner 					    GFP_KERNEL);
1216d3e51161SHeiko Stübner 	if (!info->groups) {
1217d3e51161SHeiko Stübner 		dev_err(dev, "failed allocate memory for ping group list\n");
1218d3e51161SHeiko Stübner 		return -EINVAL;
1219d3e51161SHeiko Stübner 	}
1220d3e51161SHeiko Stübner 
1221d3e51161SHeiko Stübner 	i = 0;
1222d3e51161SHeiko Stübner 
1223d3e51161SHeiko Stübner 	for_each_child_of_node(np, child) {
122465fca613SHeiko Stübner 		if (of_match_node(rockchip_bank_match, child))
1225d3e51161SHeiko Stübner 			continue;
122665fca613SHeiko Stübner 
1227d3e51161SHeiko Stübner 		ret = rockchip_pinctrl_parse_functions(child, info, i++);
1228d3e51161SHeiko Stübner 		if (ret) {
1229d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "failed to parse function\n");
1230d3e51161SHeiko Stübner 			return ret;
1231d3e51161SHeiko Stübner 		}
1232d3e51161SHeiko Stübner 	}
1233d3e51161SHeiko Stübner 
1234d3e51161SHeiko Stübner 	return 0;
1235d3e51161SHeiko Stübner }
1236d3e51161SHeiko Stübner 
1237d3e51161SHeiko Stübner static int rockchip_pinctrl_register(struct platform_device *pdev,
1238d3e51161SHeiko Stübner 					struct rockchip_pinctrl *info)
1239d3e51161SHeiko Stübner {
1240d3e51161SHeiko Stübner 	struct pinctrl_desc *ctrldesc = &info->pctl;
1241d3e51161SHeiko Stübner 	struct pinctrl_pin_desc *pindesc, *pdesc;
1242d3e51161SHeiko Stübner 	struct rockchip_pin_bank *pin_bank;
1243d3e51161SHeiko Stübner 	int pin, bank, ret;
1244d3e51161SHeiko Stübner 	int k;
1245d3e51161SHeiko Stübner 
1246d3e51161SHeiko Stübner 	ctrldesc->name = "rockchip-pinctrl";
1247d3e51161SHeiko Stübner 	ctrldesc->owner = THIS_MODULE;
1248d3e51161SHeiko Stübner 	ctrldesc->pctlops = &rockchip_pctrl_ops;
1249d3e51161SHeiko Stübner 	ctrldesc->pmxops = &rockchip_pmx_ops;
1250d3e51161SHeiko Stübner 	ctrldesc->confops = &rockchip_pinconf_ops;
1251d3e51161SHeiko Stübner 
1252d3e51161SHeiko Stübner 	pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
1253d3e51161SHeiko Stübner 			info->ctrl->nr_pins, GFP_KERNEL);
1254d3e51161SHeiko Stübner 	if (!pindesc) {
1255d3e51161SHeiko Stübner 		dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n");
1256d3e51161SHeiko Stübner 		return -ENOMEM;
1257d3e51161SHeiko Stübner 	}
1258d3e51161SHeiko Stübner 	ctrldesc->pins = pindesc;
1259d3e51161SHeiko Stübner 	ctrldesc->npins = info->ctrl->nr_pins;
1260d3e51161SHeiko Stübner 
1261d3e51161SHeiko Stübner 	pdesc = pindesc;
1262d3e51161SHeiko Stübner 	for (bank = 0 , k = 0; bank < info->ctrl->nr_banks; bank++) {
1263d3e51161SHeiko Stübner 		pin_bank = &info->ctrl->pin_banks[bank];
1264d3e51161SHeiko Stübner 		for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) {
1265d3e51161SHeiko Stübner 			pdesc->number = k;
1266d3e51161SHeiko Stübner 			pdesc->name = kasprintf(GFP_KERNEL, "%s-%d",
1267d3e51161SHeiko Stübner 						pin_bank->name, pin);
1268d3e51161SHeiko Stübner 			pdesc++;
1269d3e51161SHeiko Stübner 		}
1270d3e51161SHeiko Stübner 	}
1271d3e51161SHeiko Stübner 
12720fb7dcb1SDoug Anderson 	ret = rockchip_pinctrl_parse_dt(pdev, info);
12730fb7dcb1SDoug Anderson 	if (ret)
12740fb7dcb1SDoug Anderson 		return ret;
12750fb7dcb1SDoug Anderson 
1276d3e51161SHeiko Stübner 	info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info);
1277d3e51161SHeiko Stübner 	if (!info->pctl_dev) {
1278d3e51161SHeiko Stübner 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
1279d3e51161SHeiko Stübner 		return -EINVAL;
1280d3e51161SHeiko Stübner 	}
1281d3e51161SHeiko Stübner 
1282d3e51161SHeiko Stübner 	for (bank = 0; bank < info->ctrl->nr_banks; ++bank) {
1283d3e51161SHeiko Stübner 		pin_bank = &info->ctrl->pin_banks[bank];
1284d3e51161SHeiko Stübner 		pin_bank->grange.name = pin_bank->name;
1285d3e51161SHeiko Stübner 		pin_bank->grange.id = bank;
1286d3e51161SHeiko Stübner 		pin_bank->grange.pin_base = pin_bank->pin_base;
1287d3e51161SHeiko Stübner 		pin_bank->grange.base = pin_bank->gpio_chip.base;
1288d3e51161SHeiko Stübner 		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
1289d3e51161SHeiko Stübner 		pin_bank->grange.gc = &pin_bank->gpio_chip;
1290d3e51161SHeiko Stübner 		pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange);
1291d3e51161SHeiko Stübner 	}
1292d3e51161SHeiko Stübner 
1293d3e51161SHeiko Stübner 	return 0;
1294d3e51161SHeiko Stübner }
1295d3e51161SHeiko Stübner 
1296d3e51161SHeiko Stübner /*
1297d3e51161SHeiko Stübner  * GPIO handling
1298d3e51161SHeiko Stübner  */
1299d3e51161SHeiko Stübner 
13000351c287SAxel Lin static int rockchip_gpio_request(struct gpio_chip *chip, unsigned offset)
13010351c287SAxel Lin {
13020351c287SAxel Lin 	return pinctrl_request_gpio(chip->base + offset);
13030351c287SAxel Lin }
13040351c287SAxel Lin 
13050351c287SAxel Lin static void rockchip_gpio_free(struct gpio_chip *chip, unsigned offset)
13060351c287SAxel Lin {
13070351c287SAxel Lin 	pinctrl_free_gpio(chip->base + offset);
13080351c287SAxel Lin }
13090351c287SAxel Lin 
1310d3e51161SHeiko Stübner static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
1311d3e51161SHeiko Stübner {
1312d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
1313d3e51161SHeiko Stübner 	void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR;
1314d3e51161SHeiko Stübner 	unsigned long flags;
1315d3e51161SHeiko Stübner 	u32 data;
1316d3e51161SHeiko Stübner 
1317d3e51161SHeiko Stübner 	spin_lock_irqsave(&bank->slock, flags);
1318d3e51161SHeiko Stübner 
1319d3e51161SHeiko Stübner 	data = readl(reg);
1320d3e51161SHeiko Stübner 	data &= ~BIT(offset);
1321d3e51161SHeiko Stübner 	if (value)
1322d3e51161SHeiko Stübner 		data |= BIT(offset);
1323d3e51161SHeiko Stübner 	writel(data, reg);
1324d3e51161SHeiko Stübner 
1325d3e51161SHeiko Stübner 	spin_unlock_irqrestore(&bank->slock, flags);
1326d3e51161SHeiko Stübner }
1327d3e51161SHeiko Stübner 
1328d3e51161SHeiko Stübner /*
1329d3e51161SHeiko Stübner  * Returns the level of the pin for input direction and setting of the DR
1330d3e51161SHeiko Stübner  * register for output gpios.
1331d3e51161SHeiko Stübner  */
1332d3e51161SHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset)
1333d3e51161SHeiko Stübner {
1334d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
1335d3e51161SHeiko Stübner 	u32 data;
1336d3e51161SHeiko Stübner 
1337d3e51161SHeiko Stübner 	data = readl(bank->reg_base + GPIO_EXT_PORT);
1338d3e51161SHeiko Stübner 	data >>= offset;
1339d3e51161SHeiko Stübner 	data &= 1;
1340d3e51161SHeiko Stübner 	return data;
1341d3e51161SHeiko Stübner }
1342d3e51161SHeiko Stübner 
1343d3e51161SHeiko Stübner /*
1344d3e51161SHeiko Stübner  * gpiolib gpio_direction_input callback function. The setting of the pin
1345d3e51161SHeiko Stübner  * mux function as 'gpio input' will be handled by the pinctrl susbsystem
1346d3e51161SHeiko Stübner  * interface.
1347d3e51161SHeiko Stübner  */
1348d3e51161SHeiko Stübner static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
1349d3e51161SHeiko Stübner {
1350d3e51161SHeiko Stübner 	return pinctrl_gpio_direction_input(gc->base + offset);
1351d3e51161SHeiko Stübner }
1352d3e51161SHeiko Stübner 
1353d3e51161SHeiko Stübner /*
1354d3e51161SHeiko Stübner  * gpiolib gpio_direction_output callback function. The setting of the pin
1355d3e51161SHeiko Stübner  * mux function as 'gpio output' will be handled by the pinctrl susbsystem
1356d3e51161SHeiko Stübner  * interface.
1357d3e51161SHeiko Stübner  */
1358d3e51161SHeiko Stübner static int rockchip_gpio_direction_output(struct gpio_chip *gc,
1359d3e51161SHeiko Stübner 					  unsigned offset, int value)
1360d3e51161SHeiko Stübner {
1361d3e51161SHeiko Stübner 	rockchip_gpio_set(gc, offset, value);
1362d3e51161SHeiko Stübner 	return pinctrl_gpio_direction_output(gc->base + offset);
1363d3e51161SHeiko Stübner }
1364d3e51161SHeiko Stübner 
1365d3e51161SHeiko Stübner /*
1366d3e51161SHeiko Stübner  * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
1367d3e51161SHeiko Stübner  * and a virtual IRQ, if not already present.
1368d3e51161SHeiko Stübner  */
1369d3e51161SHeiko Stübner static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
1370d3e51161SHeiko Stübner {
1371d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
1372d3e51161SHeiko Stübner 	unsigned int virq;
1373d3e51161SHeiko Stübner 
1374d3e51161SHeiko Stübner 	if (!bank->domain)
1375d3e51161SHeiko Stübner 		return -ENXIO;
1376d3e51161SHeiko Stübner 
1377d3e51161SHeiko Stübner 	virq = irq_create_mapping(bank->domain, offset);
1378d3e51161SHeiko Stübner 
1379d3e51161SHeiko Stübner 	return (virq) ? : -ENXIO;
1380d3e51161SHeiko Stübner }
1381d3e51161SHeiko Stübner 
1382d3e51161SHeiko Stübner static const struct gpio_chip rockchip_gpiolib_chip = {
13830351c287SAxel Lin 	.request = rockchip_gpio_request,
13840351c287SAxel Lin 	.free = rockchip_gpio_free,
1385d3e51161SHeiko Stübner 	.set = rockchip_gpio_set,
1386d3e51161SHeiko Stübner 	.get = rockchip_gpio_get,
1387d3e51161SHeiko Stübner 	.direction_input = rockchip_gpio_direction_input,
1388d3e51161SHeiko Stübner 	.direction_output = rockchip_gpio_direction_output,
1389d3e51161SHeiko Stübner 	.to_irq = rockchip_gpio_to_irq,
1390d3e51161SHeiko Stübner 	.owner = THIS_MODULE,
1391d3e51161SHeiko Stübner };
1392d3e51161SHeiko Stübner 
1393d3e51161SHeiko Stübner /*
1394d3e51161SHeiko Stübner  * Interrupt handling
1395d3e51161SHeiko Stübner  */
1396d3e51161SHeiko Stübner 
1397d3e51161SHeiko Stübner static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
1398d3e51161SHeiko Stübner {
1399d3e51161SHeiko Stübner 	struct irq_chip *chip = irq_get_chip(irq);
1400d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
1401d3e51161SHeiko Stübner 	u32 pend;
1402d3e51161SHeiko Stübner 
1403d3e51161SHeiko Stübner 	dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
1404d3e51161SHeiko Stübner 
1405d3e51161SHeiko Stübner 	chained_irq_enter(chip, desc);
1406d3e51161SHeiko Stübner 
1407d3e51161SHeiko Stübner 	pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
1408d3e51161SHeiko Stübner 
1409d3e51161SHeiko Stübner 	while (pend) {
1410d3e51161SHeiko Stübner 		unsigned int virq;
1411d3e51161SHeiko Stübner 
1412d3e51161SHeiko Stübner 		irq = __ffs(pend);
1413d3e51161SHeiko Stübner 		pend &= ~BIT(irq);
1414d3e51161SHeiko Stübner 		virq = irq_linear_revmap(bank->domain, irq);
1415d3e51161SHeiko Stübner 
1416d3e51161SHeiko Stübner 		if (!virq) {
1417d3e51161SHeiko Stübner 			dev_err(bank->drvdata->dev, "unmapped irq %d\n", irq);
1418d3e51161SHeiko Stübner 			continue;
1419d3e51161SHeiko Stübner 		}
1420d3e51161SHeiko Stübner 
1421d3e51161SHeiko Stübner 		dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq);
1422d3e51161SHeiko Stübner 
14235a927501SHeiko Stübner 		/*
14245a927501SHeiko Stübner 		 * Triggering IRQ on both rising and falling edge
14255a927501SHeiko Stübner 		 * needs manual intervention.
14265a927501SHeiko Stübner 		 */
14275a927501SHeiko Stübner 		if (bank->toggle_edge_mode & BIT(irq)) {
1428*53b1bfc7SDoug Anderson 			u32 data, data_old, polarity;
1429*53b1bfc7SDoug Anderson 			unsigned long flags;
1430*53b1bfc7SDoug Anderson 
1431*53b1bfc7SDoug Anderson 			data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
1432*53b1bfc7SDoug Anderson 			do {
1433*53b1bfc7SDoug Anderson 				spin_lock_irqsave(&bank->slock, flags);
1434*53b1bfc7SDoug Anderson 
1435*53b1bfc7SDoug Anderson 				polarity = readl_relaxed(bank->reg_base +
1436*53b1bfc7SDoug Anderson 							 GPIO_INT_POLARITY);
14375a927501SHeiko Stübner 				if (data & BIT(irq))
14385a927501SHeiko Stübner 					polarity &= ~BIT(irq);
14395a927501SHeiko Stübner 				else
14405a927501SHeiko Stübner 					polarity |= BIT(irq);
1441*53b1bfc7SDoug Anderson 				writel(polarity,
1442*53b1bfc7SDoug Anderson 				       bank->reg_base + GPIO_INT_POLARITY);
14435a927501SHeiko Stübner 
1444*53b1bfc7SDoug Anderson 				spin_unlock_irqrestore(&bank->slock, flags);
1445*53b1bfc7SDoug Anderson 
1446*53b1bfc7SDoug Anderson 				data_old = data;
1447*53b1bfc7SDoug Anderson 				data = readl_relaxed(bank->reg_base +
1448*53b1bfc7SDoug Anderson 						     GPIO_EXT_PORT);
1449*53b1bfc7SDoug Anderson 			} while ((data & BIT(irq)) != (data_old & BIT(irq)));
14505a927501SHeiko Stübner 		}
14515a927501SHeiko Stübner 
1452d3e51161SHeiko Stübner 		generic_handle_irq(virq);
1453d3e51161SHeiko Stübner 	}
1454d3e51161SHeiko Stübner 
1455d3e51161SHeiko Stübner 	chained_irq_exit(chip, desc);
1456d3e51161SHeiko Stübner }
1457d3e51161SHeiko Stübner 
1458d3e51161SHeiko Stübner static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
1459d3e51161SHeiko Stübner {
1460d3e51161SHeiko Stübner 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
1461d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = gc->private;
1462d3e51161SHeiko Stübner 	u32 mask = BIT(d->hwirq);
1463d3e51161SHeiko Stübner 	u32 polarity;
1464d3e51161SHeiko Stübner 	u32 level;
1465d3e51161SHeiko Stübner 	u32 data;
1466fab262f5SDoug Anderson 	unsigned long flags;
146714797189SHeiko Stübner 	int ret;
1468d3e51161SHeiko Stübner 
14695a927501SHeiko Stübner 	/* make sure the pin is configured as gpio input */
147014797189SHeiko Stübner 	ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
147114797189SHeiko Stübner 	if (ret < 0)
147214797189SHeiko Stübner 		return ret;
147314797189SHeiko Stübner 
1474fab262f5SDoug Anderson 	spin_lock_irqsave(&bank->slock, flags);
1475fab262f5SDoug Anderson 
14765a927501SHeiko Stübner 	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
14775a927501SHeiko Stübner 	data &= ~mask;
14785a927501SHeiko Stübner 	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
14795a927501SHeiko Stübner 
1480fab262f5SDoug Anderson 	spin_unlock_irqrestore(&bank->slock, flags);
1481fab262f5SDoug Anderson 
1482d3e51161SHeiko Stübner 	if (type & IRQ_TYPE_EDGE_BOTH)
1483d3e51161SHeiko Stübner 		__irq_set_handler_locked(d->irq, handle_edge_irq);
1484d3e51161SHeiko Stübner 	else
1485d3e51161SHeiko Stübner 		__irq_set_handler_locked(d->irq, handle_level_irq);
1486d3e51161SHeiko Stübner 
1487fab262f5SDoug Anderson 	spin_lock_irqsave(&bank->slock, flags);
1488d3e51161SHeiko Stübner 	irq_gc_lock(gc);
1489d3e51161SHeiko Stübner 
1490d3e51161SHeiko Stübner 	level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL);
1491d3e51161SHeiko Stübner 	polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY);
1492d3e51161SHeiko Stübner 
1493d3e51161SHeiko Stübner 	switch (type) {
14945a927501SHeiko Stübner 	case IRQ_TYPE_EDGE_BOTH:
14955a927501SHeiko Stübner 		bank->toggle_edge_mode |= mask;
14965a927501SHeiko Stübner 		level |= mask;
14975a927501SHeiko Stübner 
14985a927501SHeiko Stübner 		/*
14995a927501SHeiko Stübner 		 * Determine gpio state. If 1 next interrupt should be falling
15005a927501SHeiko Stübner 		 * otherwise rising.
15015a927501SHeiko Stübner 		 */
15025a927501SHeiko Stübner 		data = readl(bank->reg_base + GPIO_EXT_PORT);
15035a927501SHeiko Stübner 		if (data & mask)
15045a927501SHeiko Stübner 			polarity &= ~mask;
15055a927501SHeiko Stübner 		else
15065a927501SHeiko Stübner 			polarity |= mask;
15075a927501SHeiko Stübner 		break;
1508d3e51161SHeiko Stübner 	case IRQ_TYPE_EDGE_RISING:
15095a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
1510d3e51161SHeiko Stübner 		level |= mask;
1511d3e51161SHeiko Stübner 		polarity |= mask;
1512d3e51161SHeiko Stübner 		break;
1513d3e51161SHeiko Stübner 	case IRQ_TYPE_EDGE_FALLING:
15145a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
1515d3e51161SHeiko Stübner 		level |= mask;
1516d3e51161SHeiko Stübner 		polarity &= ~mask;
1517d3e51161SHeiko Stübner 		break;
1518d3e51161SHeiko Stübner 	case IRQ_TYPE_LEVEL_HIGH:
15195a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
1520d3e51161SHeiko Stübner 		level &= ~mask;
1521d3e51161SHeiko Stübner 		polarity |= mask;
1522d3e51161SHeiko Stübner 		break;
1523d3e51161SHeiko Stübner 	case IRQ_TYPE_LEVEL_LOW:
15245a927501SHeiko Stübner 		bank->toggle_edge_mode &= ~mask;
1525d3e51161SHeiko Stübner 		level &= ~mask;
1526d3e51161SHeiko Stübner 		polarity &= ~mask;
1527d3e51161SHeiko Stübner 		break;
1528d3e51161SHeiko Stübner 	default:
15297cc5f970SAxel Lin 		irq_gc_unlock(gc);
1530fab262f5SDoug Anderson 		spin_unlock_irqrestore(&bank->slock, flags);
1531d3e51161SHeiko Stübner 		return -EINVAL;
1532d3e51161SHeiko Stübner 	}
1533d3e51161SHeiko Stübner 
1534d3e51161SHeiko Stübner 	writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL);
1535d3e51161SHeiko Stübner 	writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY);
1536d3e51161SHeiko Stübner 
1537d3e51161SHeiko Stübner 	irq_gc_unlock(gc);
1538fab262f5SDoug Anderson 	spin_unlock_irqrestore(&bank->slock, flags);
1539d3e51161SHeiko Stübner 
1540d3e51161SHeiko Stübner 	return 0;
1541d3e51161SHeiko Stübner }
1542d3e51161SHeiko Stübner 
154368bda47cSDoug Anderson static void rockchip_irq_suspend(struct irq_data *d)
154468bda47cSDoug Anderson {
154568bda47cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
154668bda47cSDoug Anderson 	struct rockchip_pin_bank *bank = gc->private;
154768bda47cSDoug Anderson 
154868bda47cSDoug Anderson 	bank->saved_enables = irq_reg_readl(gc, GPIO_INTEN);
154968bda47cSDoug Anderson 	irq_reg_writel(gc, gc->wake_active, GPIO_INTEN);
155068bda47cSDoug Anderson }
155168bda47cSDoug Anderson 
155268bda47cSDoug Anderson static void rockchip_irq_resume(struct irq_data *d)
155368bda47cSDoug Anderson {
155468bda47cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
155568bda47cSDoug Anderson 	struct rockchip_pin_bank *bank = gc->private;
155668bda47cSDoug Anderson 
155768bda47cSDoug Anderson 	irq_reg_writel(gc, bank->saved_enables, GPIO_INTEN);
155868bda47cSDoug Anderson }
155968bda47cSDoug Anderson 
1560f2dd028cSDoug Anderson static void rockchip_irq_disable(struct irq_data *d)
1561f2dd028cSDoug Anderson {
1562f2dd028cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
1563f2dd028cSDoug Anderson 	u32 val;
1564f2dd028cSDoug Anderson 
1565f2dd028cSDoug Anderson 	irq_gc_lock(gc);
1566f2dd028cSDoug Anderson 
1567f2dd028cSDoug Anderson 	val = irq_reg_readl(gc, GPIO_INTEN);
1568f2dd028cSDoug Anderson 	val &= ~d->mask;
1569f2dd028cSDoug Anderson 	irq_reg_writel(gc, val, GPIO_INTEN);
1570f2dd028cSDoug Anderson 
1571f2dd028cSDoug Anderson 	irq_gc_unlock(gc);
1572f2dd028cSDoug Anderson }
1573f2dd028cSDoug Anderson 
1574f2dd028cSDoug Anderson static void rockchip_irq_enable(struct irq_data *d)
1575f2dd028cSDoug Anderson {
1576f2dd028cSDoug Anderson 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
1577f2dd028cSDoug Anderson 	u32 val;
1578f2dd028cSDoug Anderson 
1579f2dd028cSDoug Anderson 	irq_gc_lock(gc);
1580f2dd028cSDoug Anderson 
1581f2dd028cSDoug Anderson 	val = irq_reg_readl(gc, GPIO_INTEN);
1582f2dd028cSDoug Anderson 	val |= d->mask;
1583f2dd028cSDoug Anderson 	irq_reg_writel(gc, val, GPIO_INTEN);
1584f2dd028cSDoug Anderson 
1585f2dd028cSDoug Anderson 	irq_gc_unlock(gc);
1586f2dd028cSDoug Anderson }
1587f2dd028cSDoug Anderson 
1588d3e51161SHeiko Stübner static int rockchip_interrupts_register(struct platform_device *pdev,
1589d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
1590d3e51161SHeiko Stübner {
1591d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1592d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
1593d3e51161SHeiko Stübner 	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
1594d3e51161SHeiko Stübner 	struct irq_chip_generic *gc;
1595d3e51161SHeiko Stübner 	int ret;
1596d3e51161SHeiko Stübner 	int i;
1597d3e51161SHeiko Stübner 
1598d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
1599d3e51161SHeiko Stübner 		if (!bank->valid) {
1600d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "bank %s is not valid\n",
1601d3e51161SHeiko Stübner 				 bank->name);
1602d3e51161SHeiko Stübner 			continue;
1603d3e51161SHeiko Stübner 		}
1604d3e51161SHeiko Stübner 
1605d3e51161SHeiko Stübner 		bank->domain = irq_domain_add_linear(bank->of_node, 32,
1606d3e51161SHeiko Stübner 						&irq_generic_chip_ops, NULL);
1607d3e51161SHeiko Stübner 		if (!bank->domain) {
1608d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n",
1609d3e51161SHeiko Stübner 				 bank->name);
1610d3e51161SHeiko Stübner 			continue;
1611d3e51161SHeiko Stübner 		}
1612d3e51161SHeiko Stübner 
1613d3e51161SHeiko Stübner 		ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1,
1614d3e51161SHeiko Stübner 					 "rockchip_gpio_irq", handle_level_irq,
1615d3e51161SHeiko Stübner 					 clr, 0, IRQ_GC_INIT_MASK_CACHE);
1616d3e51161SHeiko Stübner 		if (ret) {
1617d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n",
1618d3e51161SHeiko Stübner 				bank->name);
1619d3e51161SHeiko Stübner 			irq_domain_remove(bank->domain);
1620d3e51161SHeiko Stübner 			continue;
1621d3e51161SHeiko Stübner 		}
1622d3e51161SHeiko Stübner 
1623d3e51161SHeiko Stübner 		gc = irq_get_domain_generic_chip(bank->domain, 0);
1624d3e51161SHeiko Stübner 		gc->reg_base = bank->reg_base;
1625d3e51161SHeiko Stübner 		gc->private = bank;
1626f2dd028cSDoug Anderson 		gc->chip_types[0].regs.mask = GPIO_INTMASK;
1627d3e51161SHeiko Stübner 		gc->chip_types[0].regs.ack = GPIO_PORTS_EOI;
1628d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
1629f2dd028cSDoug Anderson 		gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
1630f2dd028cSDoug Anderson 		gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
1631f2dd028cSDoug Anderson 		gc->chip_types[0].chip.irq_enable = rockchip_irq_enable;
1632f2dd028cSDoug Anderson 		gc->chip_types[0].chip.irq_disable = rockchip_irq_disable;
1633d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
163468bda47cSDoug Anderson 		gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
163568bda47cSDoug Anderson 		gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
1636d3e51161SHeiko Stübner 		gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
1637876d716bSDoug Anderson 		gc->wake_enabled = IRQ_MSK(bank->nr_pins);
1638d3e51161SHeiko Stübner 
1639d3e51161SHeiko Stübner 		irq_set_handler_data(bank->irq, bank);
1640d3e51161SHeiko Stübner 		irq_set_chained_handler(bank->irq, rockchip_irq_demux);
1641d3e51161SHeiko Stübner 	}
1642d3e51161SHeiko Stübner 
1643d3e51161SHeiko Stübner 	return 0;
1644d3e51161SHeiko Stübner }
1645d3e51161SHeiko Stübner 
1646d3e51161SHeiko Stübner static int rockchip_gpiolib_register(struct platform_device *pdev,
1647d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
1648d3e51161SHeiko Stübner {
1649d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1650d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
1651d3e51161SHeiko Stübner 	struct gpio_chip *gc;
1652d3e51161SHeiko Stübner 	int ret;
1653d3e51161SHeiko Stübner 	int i;
1654d3e51161SHeiko Stübner 
1655d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
1656d3e51161SHeiko Stübner 		if (!bank->valid) {
1657d3e51161SHeiko Stübner 			dev_warn(&pdev->dev, "bank %s is not valid\n",
1658d3e51161SHeiko Stübner 				 bank->name);
1659d3e51161SHeiko Stübner 			continue;
1660d3e51161SHeiko Stübner 		}
1661d3e51161SHeiko Stübner 
1662d3e51161SHeiko Stübner 		bank->gpio_chip = rockchip_gpiolib_chip;
1663d3e51161SHeiko Stübner 
1664d3e51161SHeiko Stübner 		gc = &bank->gpio_chip;
1665d3e51161SHeiko Stübner 		gc->base = bank->pin_base;
1666d3e51161SHeiko Stübner 		gc->ngpio = bank->nr_pins;
1667d3e51161SHeiko Stübner 		gc->dev = &pdev->dev;
1668d3e51161SHeiko Stübner 		gc->of_node = bank->of_node;
1669d3e51161SHeiko Stübner 		gc->label = bank->name;
1670d3e51161SHeiko Stübner 
1671d3e51161SHeiko Stübner 		ret = gpiochip_add(gc);
1672d3e51161SHeiko Stübner 		if (ret) {
1673d3e51161SHeiko Stübner 			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
1674d3e51161SHeiko Stübner 							gc->label, ret);
1675d3e51161SHeiko Stübner 			goto fail;
1676d3e51161SHeiko Stübner 		}
1677d3e51161SHeiko Stübner 	}
1678d3e51161SHeiko Stübner 
1679d3e51161SHeiko Stübner 	rockchip_interrupts_register(pdev, info);
1680d3e51161SHeiko Stübner 
1681d3e51161SHeiko Stübner 	return 0;
1682d3e51161SHeiko Stübner 
1683d3e51161SHeiko Stübner fail:
1684d3e51161SHeiko Stübner 	for (--i, --bank; i >= 0; --i, --bank) {
1685d3e51161SHeiko Stübner 		if (!bank->valid)
1686d3e51161SHeiko Stübner 			continue;
1687b4e7c55dSabdoulaye berthe 		gpiochip_remove(&bank->gpio_chip);
1688d3e51161SHeiko Stübner 	}
1689d3e51161SHeiko Stübner 	return ret;
1690d3e51161SHeiko Stübner }
1691d3e51161SHeiko Stübner 
1692d3e51161SHeiko Stübner static int rockchip_gpiolib_unregister(struct platform_device *pdev,
1693d3e51161SHeiko Stübner 						struct rockchip_pinctrl *info)
1694d3e51161SHeiko Stübner {
1695d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
1696d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank = ctrl->pin_banks;
1697d3e51161SHeiko Stübner 	int i;
1698d3e51161SHeiko Stübner 
1699b4e7c55dSabdoulaye berthe 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
1700d3e51161SHeiko Stübner 		if (!bank->valid)
1701d3e51161SHeiko Stübner 			continue;
1702b4e7c55dSabdoulaye berthe 		gpiochip_remove(&bank->gpio_chip);
1703d3e51161SHeiko Stübner 	}
1704d3e51161SHeiko Stübner 
1705b4e7c55dSabdoulaye berthe 	return 0;
1706d3e51161SHeiko Stübner }
1707d3e51161SHeiko Stübner 
1708d3e51161SHeiko Stübner static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
1709622f3237SHeiko Stübner 				  struct rockchip_pinctrl *info)
1710d3e51161SHeiko Stübner {
1711d3e51161SHeiko Stübner 	struct resource res;
1712751a99abSHeiko Stübner 	void __iomem *base;
1713d3e51161SHeiko Stübner 
1714d3e51161SHeiko Stübner 	if (of_address_to_resource(bank->of_node, 0, &res)) {
1715622f3237SHeiko Stübner 		dev_err(info->dev, "cannot find IO resource for bank\n");
1716d3e51161SHeiko Stübner 		return -ENOENT;
1717d3e51161SHeiko Stübner 	}
1718d3e51161SHeiko Stübner 
1719622f3237SHeiko Stübner 	bank->reg_base = devm_ioremap_resource(info->dev, &res);
1720d3e51161SHeiko Stübner 	if (IS_ERR(bank->reg_base))
1721d3e51161SHeiko Stübner 		return PTR_ERR(bank->reg_base);
1722d3e51161SHeiko Stübner 
17236ca5274dSHeiko Stübner 	/*
17246ca5274dSHeiko Stübner 	 * special case, where parts of the pull setting-registers are
17256ca5274dSHeiko Stübner 	 * part of the PMU register space
17266ca5274dSHeiko Stübner 	 */
17276ca5274dSHeiko Stübner 	if (of_device_is_compatible(bank->of_node,
17286ca5274dSHeiko Stübner 				    "rockchip,rk3188-gpio-bank0")) {
1729a658efaaSHeiko Stübner 		struct device_node *node;
1730bfc7a42aSHeiko Stübner 
1731a658efaaSHeiko Stübner 		node = of_parse_phandle(bank->of_node->parent,
1732a658efaaSHeiko Stübner 					"rockchip,pmu", 0);
1733a658efaaSHeiko Stübner 		if (!node) {
17346ca5274dSHeiko Stübner 			if (of_address_to_resource(bank->of_node, 1, &res)) {
1735622f3237SHeiko Stübner 				dev_err(info->dev, "cannot find IO resource for bank\n");
17366ca5274dSHeiko Stübner 				return -ENOENT;
17376ca5274dSHeiko Stübner 			}
17386ca5274dSHeiko Stübner 
1739622f3237SHeiko Stübner 			base = devm_ioremap_resource(info->dev, &res);
1740751a99abSHeiko Stübner 			if (IS_ERR(base))
1741751a99abSHeiko Stübner 				return PTR_ERR(base);
1742a658efaaSHeiko Stübner 			rockchip_regmap_config.max_register =
1743a658efaaSHeiko Stübner 						    resource_size(&res) - 4;
1744a658efaaSHeiko Stübner 			rockchip_regmap_config.name =
1745a658efaaSHeiko Stübner 					    "rockchip,rk3188-gpio-bank0-pull";
1746a658efaaSHeiko Stübner 			bank->regmap_pull = devm_regmap_init_mmio(info->dev,
1747a658efaaSHeiko Stübner 						    base,
1748751a99abSHeiko Stübner 						    &rockchip_regmap_config);
1749a658efaaSHeiko Stübner 		}
17506ca5274dSHeiko Stübner 	}
175165fca613SHeiko Stübner 
1752d3e51161SHeiko Stübner 	bank->irq = irq_of_parse_and_map(bank->of_node, 0);
1753d3e51161SHeiko Stübner 
1754d3e51161SHeiko Stübner 	bank->clk = of_clk_get(bank->of_node, 0);
1755d3e51161SHeiko Stübner 	if (IS_ERR(bank->clk))
1756d3e51161SHeiko Stübner 		return PTR_ERR(bank->clk);
1757d3e51161SHeiko Stübner 
1758d3e51161SHeiko Stübner 	return clk_prepare_enable(bank->clk);
1759d3e51161SHeiko Stübner }
1760d3e51161SHeiko Stübner 
1761d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[];
1762d3e51161SHeiko Stübner 
1763d3e51161SHeiko Stübner /* retrieve the soc specific data */
1764d3e51161SHeiko Stübner static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
1765d3e51161SHeiko Stübner 						struct rockchip_pinctrl *d,
1766d3e51161SHeiko Stübner 						struct platform_device *pdev)
1767d3e51161SHeiko Stübner {
1768d3e51161SHeiko Stübner 	const struct of_device_id *match;
1769d3e51161SHeiko Stübner 	struct device_node *node = pdev->dev.of_node;
1770d3e51161SHeiko Stübner 	struct device_node *np;
1771d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl;
1772d3e51161SHeiko Stübner 	struct rockchip_pin_bank *bank;
177395ec8ae4SHeiko Stübner 	int grf_offs, pmu_offs, i, j;
1774d3e51161SHeiko Stübner 
1775d3e51161SHeiko Stübner 	match = of_match_node(rockchip_pinctrl_dt_match, node);
1776d3e51161SHeiko Stübner 	ctrl = (struct rockchip_pin_ctrl *)match->data;
1777d3e51161SHeiko Stübner 
1778d3e51161SHeiko Stübner 	for_each_child_of_node(node, np) {
1779d3e51161SHeiko Stübner 		if (!of_find_property(np, "gpio-controller", NULL))
1780d3e51161SHeiko Stübner 			continue;
1781d3e51161SHeiko Stübner 
1782d3e51161SHeiko Stübner 		bank = ctrl->pin_banks;
1783d3e51161SHeiko Stübner 		for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
1784d3e51161SHeiko Stübner 			if (!strcmp(bank->name, np->name)) {
1785d3e51161SHeiko Stübner 				bank->of_node = np;
1786d3e51161SHeiko Stübner 
1787622f3237SHeiko Stübner 				if (!rockchip_get_bank_data(bank, d))
1788d3e51161SHeiko Stübner 					bank->valid = true;
1789d3e51161SHeiko Stübner 
1790d3e51161SHeiko Stübner 				break;
1791d3e51161SHeiko Stübner 			}
1792d3e51161SHeiko Stübner 		}
1793d3e51161SHeiko Stübner 	}
1794d3e51161SHeiko Stübner 
179595ec8ae4SHeiko Stübner 	grf_offs = ctrl->grf_mux_offset;
179695ec8ae4SHeiko Stübner 	pmu_offs = ctrl->pmu_mux_offset;
1797d3e51161SHeiko Stübner 	bank = ctrl->pin_banks;
1798d3e51161SHeiko Stübner 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
17996bc0d121SHeiko Stübner 		int bank_pins = 0;
18006bc0d121SHeiko Stübner 
1801d3e51161SHeiko Stübner 		spin_lock_init(&bank->slock);
1802d3e51161SHeiko Stübner 		bank->drvdata = d;
1803d3e51161SHeiko Stübner 		bank->pin_base = ctrl->nr_pins;
1804d3e51161SHeiko Stübner 		ctrl->nr_pins += bank->nr_pins;
18056bc0d121SHeiko Stübner 
18066bc0d121SHeiko Stübner 		/* calculate iomux offsets */
18076bc0d121SHeiko Stübner 		for (j = 0; j < 4; j++) {
18086bc0d121SHeiko Stübner 			struct rockchip_iomux *iom = &bank->iomux[j];
180903716e1dSHeiko Stübner 			int inc;
18106bc0d121SHeiko Stübner 
18116bc0d121SHeiko Stübner 			if (bank_pins >= bank->nr_pins)
18126bc0d121SHeiko Stübner 				break;
18136bc0d121SHeiko Stübner 
18146bc0d121SHeiko Stübner 			/* preset offset value, set new start value */
18156bc0d121SHeiko Stübner 			if (iom->offset >= 0) {
181695ec8ae4SHeiko Stübner 				if (iom->type & IOMUX_SOURCE_PMU)
181795ec8ae4SHeiko Stübner 					pmu_offs = iom->offset;
181895ec8ae4SHeiko Stübner 				else
18196bc0d121SHeiko Stübner 					grf_offs = iom->offset;
18206bc0d121SHeiko Stübner 			} else { /* set current offset */
182195ec8ae4SHeiko Stübner 				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
182295ec8ae4SHeiko Stübner 							pmu_offs : grf_offs;
18236bc0d121SHeiko Stübner 			}
18246bc0d121SHeiko Stübner 
18256bc0d121SHeiko Stübner 			dev_dbg(d->dev, "bank %d, iomux %d has offset 0x%x\n",
18266bc0d121SHeiko Stübner 				 i, j, iom->offset);
18276bc0d121SHeiko Stübner 
18286bc0d121SHeiko Stübner 			/*
18296bc0d121SHeiko Stübner 			 * Increase offset according to iomux width.
183003716e1dSHeiko Stübner 			 * 4bit iomux'es are spread over two registers.
18316bc0d121SHeiko Stübner 			 */
183203716e1dSHeiko Stübner 			inc = (iom->type & IOMUX_WIDTH_4BIT) ? 8 : 4;
183395ec8ae4SHeiko Stübner 			if (iom->type & IOMUX_SOURCE_PMU)
183495ec8ae4SHeiko Stübner 				pmu_offs += inc;
183595ec8ae4SHeiko Stübner 			else
183603716e1dSHeiko Stübner 				grf_offs += inc;
18376bc0d121SHeiko Stübner 
18386bc0d121SHeiko Stübner 			bank_pins += 8;
18396bc0d121SHeiko Stübner 		}
1840d3e51161SHeiko Stübner 	}
1841d3e51161SHeiko Stübner 
1842d3e51161SHeiko Stübner 	return ctrl;
1843d3e51161SHeiko Stübner }
1844d3e51161SHeiko Stübner 
18458dca9331SChris Zhong #define RK3288_GRF_GPIO6C_IOMUX		0x64
18468dca9331SChris Zhong #define GPIO6C6_SEL_WRITE_ENABLE	BIT(28)
18478dca9331SChris Zhong 
18488dca9331SChris Zhong static u32 rk3288_grf_gpio6c_iomux;
18498dca9331SChris Zhong 
18509198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev)
18519198f509SChris Zhong {
18529198f509SChris Zhong 	struct rockchip_pinctrl *info = dev_get_drvdata(dev);
18538dca9331SChris Zhong 	int ret = pinctrl_force_sleep(info->pctl_dev);
18549198f509SChris Zhong 
18558dca9331SChris Zhong 	if (ret)
18568dca9331SChris Zhong 		return ret;
18578dca9331SChris Zhong 
18588dca9331SChris Zhong 	/*
18598dca9331SChris Zhong 	 * RK3288 GPIO6_C6 mux would be modified by Maskrom when resume, so save
18608dca9331SChris Zhong 	 * the setting here, and restore it at resume.
18618dca9331SChris Zhong 	 */
18628dca9331SChris Zhong 	if (info->ctrl->type == RK3288) {
18638dca9331SChris Zhong 		ret = regmap_read(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
18648dca9331SChris Zhong 				  &rk3288_grf_gpio6c_iomux);
18658dca9331SChris Zhong 		if (ret) {
18668dca9331SChris Zhong 			pinctrl_force_default(info->pctl_dev);
18678dca9331SChris Zhong 			return ret;
18688dca9331SChris Zhong 		}
18698dca9331SChris Zhong 	}
18708dca9331SChris Zhong 
18718dca9331SChris Zhong 	return 0;
18729198f509SChris Zhong }
18739198f509SChris Zhong 
18749198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_resume(struct device *dev)
18759198f509SChris Zhong {
18769198f509SChris Zhong 	struct rockchip_pinctrl *info = dev_get_drvdata(dev);
18778dca9331SChris Zhong 	int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
18788dca9331SChris Zhong 			       rk3288_grf_gpio6c_iomux |
18798dca9331SChris Zhong 			       GPIO6C6_SEL_WRITE_ENABLE);
18808dca9331SChris Zhong 
18818dca9331SChris Zhong 	if (ret)
18828dca9331SChris Zhong 		return ret;
18839198f509SChris Zhong 
18849198f509SChris Zhong 	return pinctrl_force_default(info->pctl_dev);
18859198f509SChris Zhong }
18869198f509SChris Zhong 
18879198f509SChris Zhong static SIMPLE_DEV_PM_OPS(rockchip_pinctrl_dev_pm_ops, rockchip_pinctrl_suspend,
18889198f509SChris Zhong 			 rockchip_pinctrl_resume);
18899198f509SChris Zhong 
1890d3e51161SHeiko Stübner static int rockchip_pinctrl_probe(struct platform_device *pdev)
1891d3e51161SHeiko Stübner {
1892d3e51161SHeiko Stübner 	struct rockchip_pinctrl *info;
1893d3e51161SHeiko Stübner 	struct device *dev = &pdev->dev;
1894d3e51161SHeiko Stübner 	struct rockchip_pin_ctrl *ctrl;
189514dee867SHeiko Stübner 	struct device_node *np = pdev->dev.of_node, *node;
1896d3e51161SHeiko Stübner 	struct resource *res;
1897751a99abSHeiko Stübner 	void __iomem *base;
1898d3e51161SHeiko Stübner 	int ret;
1899d3e51161SHeiko Stübner 
1900d3e51161SHeiko Stübner 	if (!dev->of_node) {
1901d3e51161SHeiko Stübner 		dev_err(dev, "device tree node not found\n");
1902d3e51161SHeiko Stübner 		return -ENODEV;
1903d3e51161SHeiko Stübner 	}
1904d3e51161SHeiko Stübner 
1905d3e51161SHeiko Stübner 	info = devm_kzalloc(dev, sizeof(struct rockchip_pinctrl), GFP_KERNEL);
1906d3e51161SHeiko Stübner 	if (!info)
1907d3e51161SHeiko Stübner 		return -ENOMEM;
1908d3e51161SHeiko Stübner 
1909622f3237SHeiko Stübner 	info->dev = dev;
1910622f3237SHeiko Stübner 
1911d3e51161SHeiko Stübner 	ctrl = rockchip_pinctrl_get_soc_data(info, pdev);
1912d3e51161SHeiko Stübner 	if (!ctrl) {
1913d3e51161SHeiko Stübner 		dev_err(dev, "driver data not available\n");
1914d3e51161SHeiko Stübner 		return -EINVAL;
1915d3e51161SHeiko Stübner 	}
1916d3e51161SHeiko Stübner 	info->ctrl = ctrl;
1917d3e51161SHeiko Stübner 
19181e747e59SHeiko Stübner 	node = of_parse_phandle(np, "rockchip,grf", 0);
19191e747e59SHeiko Stübner 	if (node) {
19201e747e59SHeiko Stübner 		info->regmap_base = syscon_node_to_regmap(node);
19211e747e59SHeiko Stübner 		if (IS_ERR(info->regmap_base))
19221e747e59SHeiko Stübner 			return PTR_ERR(info->regmap_base);
19231e747e59SHeiko Stübner 	} else {
1924d3e51161SHeiko Stübner 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1925751a99abSHeiko Stübner 		base = devm_ioremap_resource(&pdev->dev, res);
1926751a99abSHeiko Stübner 		if (IS_ERR(base))
1927751a99abSHeiko Stübner 			return PTR_ERR(base);
1928751a99abSHeiko Stübner 
1929751a99abSHeiko Stübner 		rockchip_regmap_config.max_register = resource_size(res) - 4;
1930751a99abSHeiko Stübner 		rockchip_regmap_config.name = "rockchip,pinctrl";
1931751a99abSHeiko Stübner 		info->regmap_base = devm_regmap_init_mmio(&pdev->dev, base,
1932751a99abSHeiko Stübner 						    &rockchip_regmap_config);
1933d3e51161SHeiko Stübner 
1934bfc7a42aSHeiko Stübner 		/* to check for the old dt-bindings */
1935bfc7a42aSHeiko Stübner 		info->reg_size = resource_size(res);
1936bfc7a42aSHeiko Stübner 
1937bfc7a42aSHeiko Stübner 		/* Honor the old binding, with pull registers as 2nd resource */
1938bfc7a42aSHeiko Stübner 		if (ctrl->type == RK3188 && info->reg_size < 0x200) {
19396ca5274dSHeiko Stübner 			res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1940751a99abSHeiko Stübner 			base = devm_ioremap_resource(&pdev->dev, res);
1941751a99abSHeiko Stübner 			if (IS_ERR(base))
1942751a99abSHeiko Stübner 				return PTR_ERR(base);
1943751a99abSHeiko Stübner 
19441e747e59SHeiko Stübner 			rockchip_regmap_config.max_register =
19451e747e59SHeiko Stübner 							resource_size(res) - 4;
1946751a99abSHeiko Stübner 			rockchip_regmap_config.name = "rockchip,pinctrl-pull";
19471e747e59SHeiko Stübner 			info->regmap_pull = devm_regmap_init_mmio(&pdev->dev,
19481e747e59SHeiko Stübner 						    base,
1949751a99abSHeiko Stübner 						    &rockchip_regmap_config);
19506ca5274dSHeiko Stübner 		}
19511e747e59SHeiko Stübner 	}
19526ca5274dSHeiko Stübner 
195314dee867SHeiko Stübner 	/* try to find the optional reference to the pmu syscon */
195414dee867SHeiko Stübner 	node = of_parse_phandle(np, "rockchip,pmu", 0);
195514dee867SHeiko Stübner 	if (node) {
195614dee867SHeiko Stübner 		info->regmap_pmu = syscon_node_to_regmap(node);
195714dee867SHeiko Stübner 		if (IS_ERR(info->regmap_pmu))
195814dee867SHeiko Stübner 			return PTR_ERR(info->regmap_pmu);
195914dee867SHeiko Stübner 	}
196014dee867SHeiko Stübner 
1961d3e51161SHeiko Stübner 	ret = rockchip_gpiolib_register(pdev, info);
1962d3e51161SHeiko Stübner 	if (ret)
1963d3e51161SHeiko Stübner 		return ret;
1964d3e51161SHeiko Stübner 
1965d3e51161SHeiko Stübner 	ret = rockchip_pinctrl_register(pdev, info);
1966d3e51161SHeiko Stübner 	if (ret) {
1967d3e51161SHeiko Stübner 		rockchip_gpiolib_unregister(pdev, info);
1968d3e51161SHeiko Stübner 		return ret;
1969d3e51161SHeiko Stübner 	}
1970d3e51161SHeiko Stübner 
1971d3e51161SHeiko Stübner 	platform_set_drvdata(pdev, info);
1972d3e51161SHeiko Stübner 
1973d3e51161SHeiko Stübner 	return 0;
1974d3e51161SHeiko Stübner }
1975d3e51161SHeiko Stübner 
1976d3e51161SHeiko Stübner static struct rockchip_pin_bank rk2928_pin_banks[] = {
1977d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
1978d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
1979d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
1980d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
1981d3e51161SHeiko Stübner };
1982d3e51161SHeiko Stübner 
1983d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
1984d3e51161SHeiko Stübner 		.pin_banks		= rk2928_pin_banks,
1985d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk2928_pin_banks),
1986d3e51161SHeiko Stübner 		.label			= "RK2928-GPIO",
1987a282926dSHeiko Stübner 		.type			= RK2928,
198895ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0xa8,
1989a282926dSHeiko Stübner 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
1990d3e51161SHeiko Stübner };
1991d3e51161SHeiko Stübner 
1992d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066a_pin_banks[] = {
1993d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
1994d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
1995d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
1996d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
1997d3e51161SHeiko Stübner 	PIN_BANK(4, 32, "gpio4"),
1998d3e51161SHeiko Stübner 	PIN_BANK(6, 16, "gpio6"),
1999d3e51161SHeiko Stübner };
2000d3e51161SHeiko Stübner 
2001d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066a_pin_ctrl = {
2002d3e51161SHeiko Stübner 		.pin_banks		= rk3066a_pin_banks,
2003d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3066a_pin_banks),
2004d3e51161SHeiko Stübner 		.label			= "RK3066a-GPIO",
2005a282926dSHeiko Stübner 		.type			= RK2928,
200695ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0xa8,
2007a282926dSHeiko Stübner 		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
2008d3e51161SHeiko Stübner };
2009d3e51161SHeiko Stübner 
2010d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066b_pin_banks[] = {
2011d3e51161SHeiko Stübner 	PIN_BANK(0, 32, "gpio0"),
2012d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
2013d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
2014d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
2015d3e51161SHeiko Stübner };
2016d3e51161SHeiko Stübner 
2017d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066b_pin_ctrl = {
2018d3e51161SHeiko Stübner 		.pin_banks	= rk3066b_pin_banks,
2019d3e51161SHeiko Stübner 		.nr_banks	= ARRAY_SIZE(rk3066b_pin_banks),
2020d3e51161SHeiko Stübner 		.label		= "RK3066b-GPIO",
2021a282926dSHeiko Stübner 		.type		= RK3066B,
202295ec8ae4SHeiko Stübner 		.grf_mux_offset	= 0x60,
2023d3e51161SHeiko Stübner };
2024d3e51161SHeiko Stübner 
2025d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3188_pin_banks[] = {
2026fc72c923SHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0),
2027d3e51161SHeiko Stübner 	PIN_BANK(1, 32, "gpio1"),
2028d3e51161SHeiko Stübner 	PIN_BANK(2, 32, "gpio2"),
2029d3e51161SHeiko Stübner 	PIN_BANK(3, 32, "gpio3"),
2030d3e51161SHeiko Stübner };
2031d3e51161SHeiko Stübner 
2032d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
2033d3e51161SHeiko Stübner 		.pin_banks		= rk3188_pin_banks,
2034d3e51161SHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3188_pin_banks),
2035d3e51161SHeiko Stübner 		.label			= "RK3188-GPIO",
2036a282926dSHeiko Stübner 		.type			= RK3188,
203795ec8ae4SHeiko Stübner 		.grf_mux_offset		= 0x60,
20386ca5274dSHeiko Stübner 		.pull_calc_reg		= rk3188_calc_pull_reg_and_bit,
2039d3e51161SHeiko Stübner };
2040d3e51161SHeiko Stübner 
2041304f077dSHeiko Stübner static struct rockchip_pin_bank rk3288_pin_banks[] = {
2042304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
2043304f077dSHeiko Stübner 					     IOMUX_SOURCE_PMU,
2044304f077dSHeiko Stübner 					     IOMUX_SOURCE_PMU,
2045304f077dSHeiko Stübner 					     IOMUX_UNROUTED
2046304f077dSHeiko Stübner 			    ),
2047304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED,
2048304f077dSHeiko Stübner 					     IOMUX_UNROUTED,
2049304f077dSHeiko Stübner 					     IOMUX_UNROUTED,
2050304f077dSHeiko Stübner 					     0
2051304f077dSHeiko Stübner 			    ),
2052304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED),
2053304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT),
2054304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
2055304f077dSHeiko Stübner 					     IOMUX_WIDTH_4BIT,
2056304f077dSHeiko Stübner 					     0,
2057304f077dSHeiko Stübner 					     0
2058304f077dSHeiko Stübner 			    ),
2059304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED,
2060304f077dSHeiko Stübner 					     0,
2061304f077dSHeiko Stübner 					     0,
2062304f077dSHeiko Stübner 					     IOMUX_UNROUTED
2063304f077dSHeiko Stübner 			    ),
2064304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED),
2065304f077dSHeiko Stübner 	PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0,
2066304f077dSHeiko Stübner 					     0,
2067304f077dSHeiko Stübner 					     IOMUX_WIDTH_4BIT,
2068304f077dSHeiko Stübner 					     IOMUX_UNROUTED
2069304f077dSHeiko Stübner 			    ),
2070304f077dSHeiko Stübner 	PIN_BANK(8, 16, "gpio8"),
2071304f077dSHeiko Stübner };
2072304f077dSHeiko Stübner 
2073304f077dSHeiko Stübner static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
2074304f077dSHeiko Stübner 		.pin_banks		= rk3288_pin_banks,
2075304f077dSHeiko Stübner 		.nr_banks		= ARRAY_SIZE(rk3288_pin_banks),
2076304f077dSHeiko Stübner 		.label			= "RK3288-GPIO",
207766d750e1SHeiko Stübner 		.type			= RK3288,
2078304f077dSHeiko Stübner 		.grf_mux_offset		= 0x0,
2079304f077dSHeiko Stübner 		.pmu_mux_offset		= 0x84,
2080304f077dSHeiko Stübner 		.pull_calc_reg		= rk3288_calc_pull_reg_and_bit,
2081304f077dSHeiko Stübner };
2082304f077dSHeiko Stübner 
2083d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[] = {
2084d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk2928-pinctrl",
2085d3e51161SHeiko Stübner 		.data = (void *)&rk2928_pin_ctrl },
2086d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3066a-pinctrl",
2087d3e51161SHeiko Stübner 		.data = (void *)&rk3066a_pin_ctrl },
2088d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3066b-pinctrl",
2089d3e51161SHeiko Stübner 		.data = (void *)&rk3066b_pin_ctrl },
2090d3e51161SHeiko Stübner 	{ .compatible = "rockchip,rk3188-pinctrl",
2091d3e51161SHeiko Stübner 		.data = (void *)&rk3188_pin_ctrl },
2092304f077dSHeiko Stübner 	{ .compatible = "rockchip,rk3288-pinctrl",
2093304f077dSHeiko Stübner 		.data = (void *)&rk3288_pin_ctrl },
2094d3e51161SHeiko Stübner 	{},
2095d3e51161SHeiko Stübner };
2096d3e51161SHeiko Stübner MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);
2097d3e51161SHeiko Stübner 
2098d3e51161SHeiko Stübner static struct platform_driver rockchip_pinctrl_driver = {
2099d3e51161SHeiko Stübner 	.probe		= rockchip_pinctrl_probe,
2100d3e51161SHeiko Stübner 	.driver = {
2101d3e51161SHeiko Stübner 		.name	= "rockchip-pinctrl",
21029198f509SChris Zhong 		.pm = &rockchip_pinctrl_dev_pm_ops,
21030be9e70dSAxel Lin 		.of_match_table = rockchip_pinctrl_dt_match,
2104d3e51161SHeiko Stübner 	},
2105d3e51161SHeiko Stübner };
2106d3e51161SHeiko Stübner 
2107d3e51161SHeiko Stübner static int __init rockchip_pinctrl_drv_register(void)
2108d3e51161SHeiko Stübner {
2109d3e51161SHeiko Stübner 	return platform_driver_register(&rockchip_pinctrl_driver);
2110d3e51161SHeiko Stübner }
2111d3e51161SHeiko Stübner postcore_initcall(rockchip_pinctrl_drv_register);
2112d3e51161SHeiko Stübner 
2113d3e51161SHeiko Stübner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
2114d3e51161SHeiko Stübner MODULE_DESCRIPTION("Rockchip pinctrl driver");
2115d3e51161SHeiko Stübner MODULE_LICENSE("GPL v2");
2116