1e6cbbe42SPatrick Rudolph // SPDX-License-Identifier: GPL-2.0-only
2e6cbbe42SPatrick Rudolph /*
3e6cbbe42SPatrick Rudolph  * CY8C95X0 20/40/60 pin I2C GPIO port expander with interrupt support
4e6cbbe42SPatrick Rudolph  *
5e6cbbe42SPatrick Rudolph  * Copyright (C) 2022 9elements GmbH
6e6cbbe42SPatrick Rudolph  * Author: Patrick Rudolph <patrick.rudolph@9elements.com>
7e6cbbe42SPatrick Rudolph  * Author: Naresh Solanki <Naresh.Solanki@9elements.com>
8e6cbbe42SPatrick Rudolph  */
9e6cbbe42SPatrick Rudolph 
10e6cbbe42SPatrick Rudolph #include <linux/bitmap.h>
11e6cbbe42SPatrick Rudolph #include <linux/gpio/driver.h>
12e6cbbe42SPatrick Rudolph #include <linux/gpio/consumer.h>
13e6cbbe42SPatrick Rudolph #include <linux/i2c.h>
14e6cbbe42SPatrick Rudolph #include <linux/init.h>
15e6cbbe42SPatrick Rudolph #include <linux/interrupt.h>
16*8586466eSAndy Shevchenko #include <linux/mod_devicetable.h>
17e6cbbe42SPatrick Rudolph #include <linux/module.h>
18*8586466eSAndy Shevchenko #include <linux/property.h>
19*8586466eSAndy Shevchenko #include <linux/regmap.h>
20*8586466eSAndy Shevchenko #include <linux/regulator/consumer.h>
21*8586466eSAndy Shevchenko 
22e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinctrl.h>
23e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinconf.h>
24e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinconf-generic.h>
25e6cbbe42SPatrick Rudolph #include <linux/pinctrl/pinmux.h>
26e6cbbe42SPatrick Rudolph 
27e6cbbe42SPatrick Rudolph /* Fast access registers */
28e6cbbe42SPatrick Rudolph #define CY8C95X0_INPUT		0x00
29e6cbbe42SPatrick Rudolph #define CY8C95X0_OUTPUT		0x08
30e6cbbe42SPatrick Rudolph #define CY8C95X0_INTSTATUS	0x10
31e6cbbe42SPatrick Rudolph 
32e6cbbe42SPatrick Rudolph #define CY8C95X0_INPUT_(x)	(CY8C95X0_INPUT + (x))
33e6cbbe42SPatrick Rudolph #define CY8C95X0_OUTPUT_(x)	(CY8C95X0_OUTPUT + (x))
34e6cbbe42SPatrick Rudolph #define CY8C95X0_INTSTATUS_(x)	(CY8C95X0_INTSTATUS + (x))
35e6cbbe42SPatrick Rudolph 
36e6cbbe42SPatrick Rudolph /* Port Select configures the port */
37e6cbbe42SPatrick Rudolph #define CY8C95X0_PORTSEL	0x18
38e6cbbe42SPatrick Rudolph /* port settings, write PORTSEL first */
39e6cbbe42SPatrick Rudolph #define CY8C95X0_INTMASK	0x19
40e6cbbe42SPatrick Rudolph #define CY8C95X0_PWMSEL		0x1A
41e6cbbe42SPatrick Rudolph #define CY8C95X0_INVERT		0x1B
42e6cbbe42SPatrick Rudolph #define CY8C95X0_DIRECTION	0x1C
43e6cbbe42SPatrick Rudolph /* Drive mode register change state on writing '1' */
44e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PU		0x1D
45e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PD		0x1E
46e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_ODH	0x1F
47e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_ODL	0x20
48e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PP_FAST	0x21
49e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_PP_SLOW	0x22
50e6cbbe42SPatrick Rudolph #define CY8C95X0_DRV_HIZ	0x23
51e6cbbe42SPatrick Rudolph #define CY8C95X0_DEVID		0x2E
52e6cbbe42SPatrick Rudolph #define CY8C95X0_WATCHDOG	0x2F
53e6cbbe42SPatrick Rudolph #define CY8C95X0_COMMAND	0x30
54e6cbbe42SPatrick Rudolph 
55e6cbbe42SPatrick Rudolph #define CY8C95X0_PIN_TO_OFFSET(x) (((x) >= 20) ? ((x) + 4) : (x))
56e6cbbe42SPatrick Rudolph 
57e6cbbe42SPatrick Rudolph static const struct i2c_device_id cy8c95x0_id[] = {
58e6cbbe42SPatrick Rudolph 	{ "cy8c9520", 20, },
59e6cbbe42SPatrick Rudolph 	{ "cy8c9540", 40, },
60e6cbbe42SPatrick Rudolph 	{ "cy8c9560", 60, },
61e6cbbe42SPatrick Rudolph 	{ }
62e6cbbe42SPatrick Rudolph };
63e6cbbe42SPatrick Rudolph MODULE_DEVICE_TABLE(i2c, cy8c95x0_id);
64e6cbbe42SPatrick Rudolph 
65e6cbbe42SPatrick Rudolph #define OF_CY8C95X(__nrgpio) ((void *)(__nrgpio))
66e6cbbe42SPatrick Rudolph 
67e6cbbe42SPatrick Rudolph static const struct of_device_id cy8c95x0_dt_ids[] = {
68e6cbbe42SPatrick Rudolph 	{ .compatible = "cypress,cy8c9520", .data = OF_CY8C95X(20), },
69e6cbbe42SPatrick Rudolph 	{ .compatible = "cypress,cy8c9540", .data = OF_CY8C95X(40), },
70e6cbbe42SPatrick Rudolph 	{ .compatible = "cypress,cy8c9560", .data = OF_CY8C95X(60), },
71e6cbbe42SPatrick Rudolph 	{ }
72e6cbbe42SPatrick Rudolph };
73e6cbbe42SPatrick Rudolph 
74e6cbbe42SPatrick Rudolph MODULE_DEVICE_TABLE(of, cy8c95x0_dt_ids);
75e6cbbe42SPatrick Rudolph 
76e6cbbe42SPatrick Rudolph #define MAX_BANK 8
77e6cbbe42SPatrick Rudolph #define BANK_SZ 8
78e6cbbe42SPatrick Rudolph #define MAX_LINE	(MAX_BANK * BANK_SZ)
79e6cbbe42SPatrick Rudolph 
80e6cbbe42SPatrick Rudolph #define CY8C95X0_GPIO_MASK		GENMASK(7, 0)
81e6cbbe42SPatrick Rudolph 
82e6cbbe42SPatrick Rudolph /**
83e6cbbe42SPatrick Rudolph  * struct cy8c95x0_pinctrl - driver data
84e6cbbe42SPatrick Rudolph  * @regmap:         Device's regmap
85e6cbbe42SPatrick Rudolph  * @irq_lock:       IRQ bus lock
86e6cbbe42SPatrick Rudolph  * @i2c_lock:       Mutex for the device internal mux register
87e6cbbe42SPatrick Rudolph  * @irq_mask:       I/O bits affected by interrupts
88e6cbbe42SPatrick Rudolph  * @irq_trig_raise: I/O bits affected by raising voltage level
89e6cbbe42SPatrick Rudolph  * @irq_trig_fall:  I/O bits affected by falling voltage level
90e6cbbe42SPatrick Rudolph  * @irq_trig_low:   I/O bits affected by a low voltage level
91e6cbbe42SPatrick Rudolph  * @irq_trig_high:  I/O bits affected by a high voltage level
92e6cbbe42SPatrick Rudolph  * @push_pull:      I/O bits configured as push pull driver
93e6cbbe42SPatrick Rudolph  * @shiftmask:      Mask used to compensate for Gport2 width
94e6cbbe42SPatrick Rudolph  * @nport:          Number of Gports in this chip
95e6cbbe42SPatrick Rudolph  * @gpio_chip:      gpiolib chip
96e6cbbe42SPatrick Rudolph  * @driver_data:    private driver data
97e6cbbe42SPatrick Rudolph  * @regulator:      Pointer to the regulator for the IC
98e6cbbe42SPatrick Rudolph  * @dev:            struct device
99e6cbbe42SPatrick Rudolph  * @pctldev:        pin controller device
100e6cbbe42SPatrick Rudolph  * @pinctrl_desc:   pin controller description
101e6cbbe42SPatrick Rudolph  * @name:           Chip controller name
102e6cbbe42SPatrick Rudolph  * @tpin:           Total number of pins
103e6cbbe42SPatrick Rudolph  */
104e6cbbe42SPatrick Rudolph struct cy8c95x0_pinctrl {
105e6cbbe42SPatrick Rudolph 	struct regmap *regmap;
106e6cbbe42SPatrick Rudolph 	struct mutex irq_lock;
107e6cbbe42SPatrick Rudolph 	struct mutex i2c_lock;
108e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(irq_mask, MAX_LINE);
109e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(irq_trig_raise, MAX_LINE);
110e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(irq_trig_fall, MAX_LINE);
111e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(irq_trig_low, MAX_LINE);
112e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(irq_trig_high, MAX_LINE);
113e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(push_pull, MAX_LINE);
114e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(shiftmask, MAX_LINE);
115e6cbbe42SPatrick Rudolph 	int nport;
116e6cbbe42SPatrick Rudolph 	struct gpio_chip gpio_chip;
117e6cbbe42SPatrick Rudolph 	unsigned long driver_data;
118e6cbbe42SPatrick Rudolph 	struct regulator *regulator;
119e6cbbe42SPatrick Rudolph 	struct device *dev;
120e6cbbe42SPatrick Rudolph 	struct pinctrl_dev *pctldev;
121e6cbbe42SPatrick Rudolph 	struct pinctrl_desc pinctrl_desc;
122e6cbbe42SPatrick Rudolph 	char name[32];
123e6cbbe42SPatrick Rudolph 	unsigned int tpin;
124e6cbbe42SPatrick Rudolph };
125e6cbbe42SPatrick Rudolph 
126e6cbbe42SPatrick Rudolph static const struct pinctrl_pin_desc cy8c9560_pins[] = {
127e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(0, "gp00"),
128e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(1, "gp01"),
129e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(2, "gp02"),
130e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(3, "gp03"),
131e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(4, "gp04"),
132e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(5, "gp05"),
133e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(6, "gp06"),
134e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(7, "gp07"),
135e6cbbe42SPatrick Rudolph 
136e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(8, "gp10"),
137e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(9, "gp11"),
138e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(10, "gp12"),
139e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(11, "gp13"),
140e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(12, "gp14"),
141e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(13, "gp15"),
142e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(14, "gp16"),
143e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(15, "gp17"),
144e6cbbe42SPatrick Rudolph 
145e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(16, "gp20"),
146e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(17, "gp21"),
147e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(18, "gp22"),
148e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(19, "gp23"),
149e6cbbe42SPatrick Rudolph 
150e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(20, "gp30"),
151e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(21, "gp31"),
152e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(22, "gp32"),
153e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(23, "gp33"),
154e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(24, "gp34"),
155e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(25, "gp35"),
156e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(26, "gp36"),
157e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(27, "gp37"),
158e6cbbe42SPatrick Rudolph 
159e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(28, "gp40"),
160e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(29, "gp41"),
161e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(30, "gp42"),
162e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(31, "gp43"),
163e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(32, "gp44"),
164e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(33, "gp45"),
165e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(34, "gp46"),
166e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(35, "gp47"),
167e6cbbe42SPatrick Rudolph 
168e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(36, "gp50"),
169e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(37, "gp51"),
170e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(38, "gp52"),
171e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(39, "gp53"),
172e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(40, "gp54"),
173e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(41, "gp55"),
174e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(42, "gp56"),
175e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(43, "gp57"),
176e6cbbe42SPatrick Rudolph 
177e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(44, "gp60"),
178e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(45, "gp61"),
179e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(46, "gp62"),
180e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(47, "gp63"),
181e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(48, "gp64"),
182e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(49, "gp65"),
183e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(50, "gp66"),
184e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(51, "gp67"),
185e6cbbe42SPatrick Rudolph 
186e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(52, "gp70"),
187e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(53, "gp71"),
188e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(54, "gp72"),
189e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(55, "gp73"),
190e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(56, "gp74"),
191e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(57, "gp75"),
192e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(58, "gp76"),
193e6cbbe42SPatrick Rudolph 	PINCTRL_PIN(59, "gp77"),
194e6cbbe42SPatrick Rudolph };
195e6cbbe42SPatrick Rudolph 
196e6cbbe42SPatrick Rudolph static const char * const cy8c95x0_groups[] = {
197e6cbbe42SPatrick Rudolph 	"gp00",
198e6cbbe42SPatrick Rudolph 	"gp01",
199e6cbbe42SPatrick Rudolph 	"gp02",
200e6cbbe42SPatrick Rudolph 	"gp03",
201e6cbbe42SPatrick Rudolph 	"gp04",
202e6cbbe42SPatrick Rudolph 	"gp05",
203e6cbbe42SPatrick Rudolph 	"gp06",
204e6cbbe42SPatrick Rudolph 	"gp07",
205e6cbbe42SPatrick Rudolph 
206e6cbbe42SPatrick Rudolph 	"gp10",
207e6cbbe42SPatrick Rudolph 	"gp11",
208e6cbbe42SPatrick Rudolph 	"gp12",
209e6cbbe42SPatrick Rudolph 	"gp13",
210e6cbbe42SPatrick Rudolph 	"gp14",
211e6cbbe42SPatrick Rudolph 	"gp15",
212e6cbbe42SPatrick Rudolph 	"gp16",
213e6cbbe42SPatrick Rudolph 	"gp17",
214e6cbbe42SPatrick Rudolph 
215e6cbbe42SPatrick Rudolph 	"gp20",
216e6cbbe42SPatrick Rudolph 	"gp21",
217e6cbbe42SPatrick Rudolph 	"gp22",
218e6cbbe42SPatrick Rudolph 	"gp23",
219e6cbbe42SPatrick Rudolph 
220e6cbbe42SPatrick Rudolph 	"gp30",
221e6cbbe42SPatrick Rudolph 	"gp31",
222e6cbbe42SPatrick Rudolph 	"gp32",
223e6cbbe42SPatrick Rudolph 	"gp33",
224e6cbbe42SPatrick Rudolph 	"gp34",
225e6cbbe42SPatrick Rudolph 	"gp35",
226e6cbbe42SPatrick Rudolph 	"gp36",
227e6cbbe42SPatrick Rudolph 	"gp37",
228e6cbbe42SPatrick Rudolph 
229e6cbbe42SPatrick Rudolph 	"gp40",
230e6cbbe42SPatrick Rudolph 	"gp41",
231e6cbbe42SPatrick Rudolph 	"gp42",
232e6cbbe42SPatrick Rudolph 	"gp43",
233e6cbbe42SPatrick Rudolph 	"gp44",
234e6cbbe42SPatrick Rudolph 	"gp45",
235e6cbbe42SPatrick Rudolph 	"gp46",
236e6cbbe42SPatrick Rudolph 	"gp47",
237e6cbbe42SPatrick Rudolph 
238e6cbbe42SPatrick Rudolph 	"gp50",
239e6cbbe42SPatrick Rudolph 	"gp51",
240e6cbbe42SPatrick Rudolph 	"gp52",
241e6cbbe42SPatrick Rudolph 	"gp53",
242e6cbbe42SPatrick Rudolph 	"gp54",
243e6cbbe42SPatrick Rudolph 	"gp55",
244e6cbbe42SPatrick Rudolph 	"gp56",
245e6cbbe42SPatrick Rudolph 	"gp57",
246e6cbbe42SPatrick Rudolph 
247e6cbbe42SPatrick Rudolph 	"gp60",
248e6cbbe42SPatrick Rudolph 	"gp61",
249e6cbbe42SPatrick Rudolph 	"gp62",
250e6cbbe42SPatrick Rudolph 	"gp63",
251e6cbbe42SPatrick Rudolph 	"gp64",
252e6cbbe42SPatrick Rudolph 	"gp65",
253e6cbbe42SPatrick Rudolph 	"gp66",
254e6cbbe42SPatrick Rudolph 	"gp67",
255e6cbbe42SPatrick Rudolph 
256e6cbbe42SPatrick Rudolph 	"gp70",
257e6cbbe42SPatrick Rudolph 	"gp71",
258e6cbbe42SPatrick Rudolph 	"gp72",
259e6cbbe42SPatrick Rudolph 	"gp73",
260e6cbbe42SPatrick Rudolph 	"gp74",
261e6cbbe42SPatrick Rudolph 	"gp75",
262e6cbbe42SPatrick Rudolph 	"gp76",
263e6cbbe42SPatrick Rudolph 	"gp77",
264e6cbbe42SPatrick Rudolph };
265e6cbbe42SPatrick Rudolph 
266e6cbbe42SPatrick Rudolph static inline u8 cypress_get_port(struct cy8c95x0_pinctrl *chip, unsigned int pin)
267e6cbbe42SPatrick Rudolph {
268e6cbbe42SPatrick Rudolph 	/* Account for GPORT2 which only has 4 bits */
269e6cbbe42SPatrick Rudolph 	return CY8C95X0_PIN_TO_OFFSET(pin) / BANK_SZ;
270e6cbbe42SPatrick Rudolph }
271e6cbbe42SPatrick Rudolph 
272e6cbbe42SPatrick Rudolph static int cypress_get_pin_mask(struct cy8c95x0_pinctrl *chip, unsigned int pin)
273e6cbbe42SPatrick Rudolph {
274e6cbbe42SPatrick Rudolph 	/* Account for GPORT2 which only has 4 bits */
275e6cbbe42SPatrick Rudolph 	return BIT(CY8C95X0_PIN_TO_OFFSET(pin) % BANK_SZ);
276e6cbbe42SPatrick Rudolph }
277e6cbbe42SPatrick Rudolph 
278e6cbbe42SPatrick Rudolph static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg)
279e6cbbe42SPatrick Rudolph {
280e6cbbe42SPatrick Rudolph 	switch (reg) {
281e6cbbe42SPatrick Rudolph 	case 0x24 ... 0x27:
282e6cbbe42SPatrick Rudolph 		return false;
283c3e40952SAndy Shevchenko 	default:
284e6cbbe42SPatrick Rudolph 		return true;
285e6cbbe42SPatrick Rudolph 	}
286c3e40952SAndy Shevchenko }
287e6cbbe42SPatrick Rudolph 
288e6cbbe42SPatrick Rudolph static bool cy8c95x0_writeable_register(struct device *dev, unsigned int reg)
289e6cbbe42SPatrick Rudolph {
290e6cbbe42SPatrick Rudolph 	switch (reg) {
291e6cbbe42SPatrick Rudolph 	case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7):
292e6cbbe42SPatrick Rudolph 		return false;
293e6cbbe42SPatrick Rudolph 	case CY8C95X0_DEVID:
294e6cbbe42SPatrick Rudolph 		return false;
295e6cbbe42SPatrick Rudolph 	case 0x24 ... 0x27:
296e6cbbe42SPatrick Rudolph 		return false;
297c3e40952SAndy Shevchenko 	default:
298e6cbbe42SPatrick Rudolph 		return true;
299e6cbbe42SPatrick Rudolph 	}
300c3e40952SAndy Shevchenko }
301e6cbbe42SPatrick Rudolph 
302e6cbbe42SPatrick Rudolph static bool cy8c95x0_volatile_register(struct device *dev, unsigned int reg)
303e6cbbe42SPatrick Rudolph {
304e6cbbe42SPatrick Rudolph 	switch (reg) {
305e6cbbe42SPatrick Rudolph 	case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7):
306e6cbbe42SPatrick Rudolph 	case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7):
307e6cbbe42SPatrick Rudolph 	case CY8C95X0_INTMASK:
308e6cbbe42SPatrick Rudolph 	case CY8C95X0_INVERT:
309e6cbbe42SPatrick Rudolph 	case CY8C95X0_PWMSEL:
310e6cbbe42SPatrick Rudolph 	case CY8C95X0_DIRECTION:
311e6cbbe42SPatrick Rudolph 	case CY8C95X0_DRV_PU:
312e6cbbe42SPatrick Rudolph 	case CY8C95X0_DRV_PD:
313e6cbbe42SPatrick Rudolph 	case CY8C95X0_DRV_ODH:
314e6cbbe42SPatrick Rudolph 	case CY8C95X0_DRV_ODL:
315e6cbbe42SPatrick Rudolph 	case CY8C95X0_DRV_PP_FAST:
316e6cbbe42SPatrick Rudolph 	case CY8C95X0_DRV_PP_SLOW:
317e6cbbe42SPatrick Rudolph 	case CY8C95X0_DRV_HIZ:
318e6cbbe42SPatrick Rudolph 		return true;
319e6cbbe42SPatrick Rudolph 	}
320e6cbbe42SPatrick Rudolph 
321e6cbbe42SPatrick Rudolph 	return false;
322e6cbbe42SPatrick Rudolph }
323e6cbbe42SPatrick Rudolph 
324e6cbbe42SPatrick Rudolph static bool cy8c95x0_precious_register(struct device *dev, unsigned int reg)
325e6cbbe42SPatrick Rudolph {
326e6cbbe42SPatrick Rudolph 	switch (reg) {
327e6cbbe42SPatrick Rudolph 	case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7):
328e6cbbe42SPatrick Rudolph 		return true;
329c3e40952SAndy Shevchenko 	default:
330e6cbbe42SPatrick Rudolph 		return false;
331e6cbbe42SPatrick Rudolph 	}
332c3e40952SAndy Shevchenko }
333e6cbbe42SPatrick Rudolph 
334e6cbbe42SPatrick Rudolph static const struct reg_default cy8c95x0_reg_defaults[] = {
335e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(0), 0xff },
336e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(1), 0xff },
337e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(2), 0xff },
338e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(3), 0xff },
339e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(4), 0xff },
340e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(5), 0xff },
341e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(6), 0xff },
342e6cbbe42SPatrick Rudolph 	{ CY8C95X0_OUTPUT_(7), 0xff },
343e6cbbe42SPatrick Rudolph 	{ CY8C95X0_PORTSEL, 0 },
344e6cbbe42SPatrick Rudolph 	{ CY8C95X0_PWMSEL, 0 },
345e6cbbe42SPatrick Rudolph };
346e6cbbe42SPatrick Rudolph 
347e6cbbe42SPatrick Rudolph static const struct regmap_config cy8c95x0_i2c_regmap = {
348e6cbbe42SPatrick Rudolph 	.reg_bits = 8,
349e6cbbe42SPatrick Rudolph 	.val_bits = 8,
350e6cbbe42SPatrick Rudolph 
351e6cbbe42SPatrick Rudolph 	.reg_defaults = cy8c95x0_reg_defaults,
352e6cbbe42SPatrick Rudolph 	.num_reg_defaults = ARRAY_SIZE(cy8c95x0_reg_defaults),
353e6cbbe42SPatrick Rudolph 
354e6cbbe42SPatrick Rudolph 	.readable_reg = cy8c95x0_readable_register,
355e6cbbe42SPatrick Rudolph 	.writeable_reg = cy8c95x0_writeable_register,
356e6cbbe42SPatrick Rudolph 	.volatile_reg = cy8c95x0_volatile_register,
357e6cbbe42SPatrick Rudolph 	.precious_reg = cy8c95x0_precious_register,
358e6cbbe42SPatrick Rudolph 
359e6cbbe42SPatrick Rudolph 	.cache_type = REGCACHE_FLAT,
360e6cbbe42SPatrick Rudolph 	.max_register = CY8C95X0_COMMAND,
361e6cbbe42SPatrick Rudolph };
362e6cbbe42SPatrick Rudolph 
363e6cbbe42SPatrick Rudolph static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
364e6cbbe42SPatrick Rudolph 				    unsigned long *val, unsigned long *mask)
365e6cbbe42SPatrick Rudolph {
366e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(tmask, MAX_LINE);
367e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(tval, MAX_LINE);
368e6cbbe42SPatrick Rudolph 	int write_val;
369e6cbbe42SPatrick Rudolph 	int ret = 0;
370e6cbbe42SPatrick Rudolph 	int i, off = 0;
371e6cbbe42SPatrick Rudolph 	u8 bits;
372e6cbbe42SPatrick Rudolph 
373e6cbbe42SPatrick Rudolph 	/* Add the 4 bit gap of Gport2 */
374e6cbbe42SPatrick Rudolph 	bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE);
375e6cbbe42SPatrick Rudolph 	bitmap_shift_left(tmask, tmask, 4, MAX_LINE);
376e6cbbe42SPatrick Rudolph 	bitmap_replace(tmask, tmask, mask, chip->shiftmask, BANK_SZ * 3);
377e6cbbe42SPatrick Rudolph 
378e6cbbe42SPatrick Rudolph 	bitmap_andnot(tval, val, chip->shiftmask, MAX_LINE);
379e6cbbe42SPatrick Rudolph 	bitmap_shift_left(tval, tval, 4, MAX_LINE);
380e6cbbe42SPatrick Rudolph 	bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
381e6cbbe42SPatrick Rudolph 
382e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
383e6cbbe42SPatrick Rudolph 	for (i = 0; i < chip->nport; i++) {
384e6cbbe42SPatrick Rudolph 		/* Skip over unused banks */
385e6cbbe42SPatrick Rudolph 		bits = bitmap_get_value8(tmask, i * BANK_SZ);
386e6cbbe42SPatrick Rudolph 		if (!bits)
387e6cbbe42SPatrick Rudolph 			continue;
388e6cbbe42SPatrick Rudolph 
389e6cbbe42SPatrick Rudolph 		switch (reg) {
390e6cbbe42SPatrick Rudolph 		/* muxed registers */
391e6cbbe42SPatrick Rudolph 		case CY8C95X0_INTMASK:
392e6cbbe42SPatrick Rudolph 		case CY8C95X0_PWMSEL:
393e6cbbe42SPatrick Rudolph 		case CY8C95X0_INVERT:
394e6cbbe42SPatrick Rudolph 		case CY8C95X0_DIRECTION:
395e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PU:
396e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PD:
397e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_ODH:
398e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_ODL:
399e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PP_FAST:
400e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PP_SLOW:
401e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_HIZ:
402e6cbbe42SPatrick Rudolph 			ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, i);
403e6cbbe42SPatrick Rudolph 			if (ret < 0)
404e6cbbe42SPatrick Rudolph 				goto out;
405e6cbbe42SPatrick Rudolph 			off = reg;
406e6cbbe42SPatrick Rudolph 			break;
407e6cbbe42SPatrick Rudolph 		/* direct access registers */
408e6cbbe42SPatrick Rudolph 		case CY8C95X0_INPUT:
409e6cbbe42SPatrick Rudolph 		case CY8C95X0_OUTPUT:
410e6cbbe42SPatrick Rudolph 		case CY8C95X0_INTSTATUS:
411e6cbbe42SPatrick Rudolph 			off = reg + i;
412e6cbbe42SPatrick Rudolph 			break;
413e6cbbe42SPatrick Rudolph 		default:
414e6cbbe42SPatrick Rudolph 			ret = -EINVAL;
415e6cbbe42SPatrick Rudolph 			goto out;
416e6cbbe42SPatrick Rudolph 		}
417e6cbbe42SPatrick Rudolph 
418e6cbbe42SPatrick Rudolph 		write_val = bitmap_get_value8(tval, i * BANK_SZ);
419e6cbbe42SPatrick Rudolph 
420e6cbbe42SPatrick Rudolph 		ret = regmap_update_bits(chip->regmap, off, bits, write_val);
421e6cbbe42SPatrick Rudolph 		if (ret < 0)
422e6cbbe42SPatrick Rudolph 			goto out;
423e6cbbe42SPatrick Rudolph 	}
424e6cbbe42SPatrick Rudolph out:
425e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
426e6cbbe42SPatrick Rudolph 
427e6cbbe42SPatrick Rudolph 	if (ret < 0)
428e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "failed writing register %d: err %d\n", off, ret);
429e6cbbe42SPatrick Rudolph 
430e6cbbe42SPatrick Rudolph 	return ret;
431e6cbbe42SPatrick Rudolph }
432e6cbbe42SPatrick Rudolph 
433e6cbbe42SPatrick Rudolph static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
434e6cbbe42SPatrick Rudolph 				   unsigned long *val, unsigned long *mask)
435e6cbbe42SPatrick Rudolph {
436e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(tmask, MAX_LINE);
437e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(tval, MAX_LINE);
438e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(tmp, MAX_LINE);
439e6cbbe42SPatrick Rudolph 	int read_val;
440e6cbbe42SPatrick Rudolph 	int ret = 0;
441e6cbbe42SPatrick Rudolph 	int i, off = 0;
442e6cbbe42SPatrick Rudolph 	u8 bits;
443e6cbbe42SPatrick Rudolph 
444e6cbbe42SPatrick Rudolph 	/* Add the 4 bit gap of Gport2 */
445e6cbbe42SPatrick Rudolph 	bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE);
446e6cbbe42SPatrick Rudolph 	bitmap_shift_left(tmask, tmask, 4, MAX_LINE);
447e6cbbe42SPatrick Rudolph 	bitmap_replace(tmask, tmask, mask, chip->shiftmask, BANK_SZ * 3);
448e6cbbe42SPatrick Rudolph 
449e6cbbe42SPatrick Rudolph 	bitmap_andnot(tval, val, chip->shiftmask, MAX_LINE);
450e6cbbe42SPatrick Rudolph 	bitmap_shift_left(tval, tval, 4, MAX_LINE);
451e6cbbe42SPatrick Rudolph 	bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
452e6cbbe42SPatrick Rudolph 
453e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
454e6cbbe42SPatrick Rudolph 	for (i = 0; i < chip->nport; i++) {
455e6cbbe42SPatrick Rudolph 		/* Skip over unused banks */
456e6cbbe42SPatrick Rudolph 		bits = bitmap_get_value8(tmask, i * BANK_SZ);
457e6cbbe42SPatrick Rudolph 		if (!bits)
458e6cbbe42SPatrick Rudolph 			continue;
459e6cbbe42SPatrick Rudolph 
460e6cbbe42SPatrick Rudolph 		switch (reg) {
461e6cbbe42SPatrick Rudolph 		/* muxed registers */
462e6cbbe42SPatrick Rudolph 		case CY8C95X0_INTMASK:
463e6cbbe42SPatrick Rudolph 		case CY8C95X0_PWMSEL:
464e6cbbe42SPatrick Rudolph 		case CY8C95X0_INVERT:
465e6cbbe42SPatrick Rudolph 		case CY8C95X0_DIRECTION:
466e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PU:
467e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PD:
468e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_ODH:
469e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_ODL:
470e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PP_FAST:
471e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_PP_SLOW:
472e6cbbe42SPatrick Rudolph 		case CY8C95X0_DRV_HIZ:
473e6cbbe42SPatrick Rudolph 			ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, i);
474e6cbbe42SPatrick Rudolph 			if (ret < 0)
475e6cbbe42SPatrick Rudolph 				goto out;
476e6cbbe42SPatrick Rudolph 			off = reg;
477e6cbbe42SPatrick Rudolph 			break;
478e6cbbe42SPatrick Rudolph 		/* direct access registers */
479e6cbbe42SPatrick Rudolph 		case CY8C95X0_INPUT:
480e6cbbe42SPatrick Rudolph 		case CY8C95X0_OUTPUT:
481e6cbbe42SPatrick Rudolph 		case CY8C95X0_INTSTATUS:
482e6cbbe42SPatrick Rudolph 			off = reg + i;
483e6cbbe42SPatrick Rudolph 			break;
484e6cbbe42SPatrick Rudolph 		default:
485e6cbbe42SPatrick Rudolph 			ret = -EINVAL;
486e6cbbe42SPatrick Rudolph 			goto out;
487e6cbbe42SPatrick Rudolph 		}
488e6cbbe42SPatrick Rudolph 
489e6cbbe42SPatrick Rudolph 		ret = regmap_read(chip->regmap, off, &read_val);
490e6cbbe42SPatrick Rudolph 		if (ret < 0)
491e6cbbe42SPatrick Rudolph 			goto out;
492e6cbbe42SPatrick Rudolph 
493e6cbbe42SPatrick Rudolph 		read_val &= bits;
494e6cbbe42SPatrick Rudolph 		read_val |= bitmap_get_value8(tval, i * BANK_SZ) & ~bits;
495e6cbbe42SPatrick Rudolph 		bitmap_set_value8(tval, read_val, i * BANK_SZ);
496e6cbbe42SPatrick Rudolph 	}
497e6cbbe42SPatrick Rudolph 
498e6cbbe42SPatrick Rudolph 	/* Fill the 4 bit gap of Gport2 */
499e6cbbe42SPatrick Rudolph 	bitmap_shift_right(tmp, tval, 4, MAX_LINE);
500e6cbbe42SPatrick Rudolph 	bitmap_replace(val, tmp, tval, chip->shiftmask, MAX_LINE);
501e6cbbe42SPatrick Rudolph 
502e6cbbe42SPatrick Rudolph out:
503e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
504e6cbbe42SPatrick Rudolph 
505e6cbbe42SPatrick Rudolph 	if (ret < 0)
506e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "failed reading register %d: err %d\n", off, ret);
507e6cbbe42SPatrick Rudolph 
508e6cbbe42SPatrick Rudolph 	return ret;
509e6cbbe42SPatrick Rudolph }
510e6cbbe42SPatrick Rudolph 
511e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
512e6cbbe42SPatrick Rudolph {
513e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
514e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
515e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
516e6cbbe42SPatrick Rudolph 	int ret;
517e6cbbe42SPatrick Rudolph 
518e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
519e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
520e6cbbe42SPatrick Rudolph 	if (ret)
521e6cbbe42SPatrick Rudolph 		goto out;
522e6cbbe42SPatrick Rudolph 
523e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, bit);
524e6cbbe42SPatrick Rudolph 	if (ret)
525e6cbbe42SPatrick Rudolph 		goto out;
526e6cbbe42SPatrick Rudolph 
527e6cbbe42SPatrick Rudolph 	if (test_bit(off, chip->push_pull)) {
528e6cbbe42SPatrick Rudolph 		/*
529e6cbbe42SPatrick Rudolph 		 * Disable driving the pin by forcing it to HighZ. Only setting the
530e6cbbe42SPatrick Rudolph 		 * direction register isn't sufficient in Push-Pull mode.
531e6cbbe42SPatrick Rudolph 		 */
532e6cbbe42SPatrick Rudolph 		ret = regmap_write_bits(chip->regmap, CY8C95X0_DRV_HIZ, bit, bit);
533e6cbbe42SPatrick Rudolph 		if (ret)
534e6cbbe42SPatrick Rudolph 			goto out;
535e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
536e6cbbe42SPatrick Rudolph 	}
537e6cbbe42SPatrick Rudolph 
538e6cbbe42SPatrick Rudolph out:
539e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
540e6cbbe42SPatrick Rudolph 
541e6cbbe42SPatrick Rudolph 	return ret;
542e6cbbe42SPatrick Rudolph }
543e6cbbe42SPatrick Rudolph 
544e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_direction_output(struct gpio_chip *gc,
545e6cbbe42SPatrick Rudolph 					  unsigned int off, int val)
546e6cbbe42SPatrick Rudolph {
547e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
548e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
549e6cbbe42SPatrick Rudolph 	u8 outreg = CY8C95X0_OUTPUT_(port);
550e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
551e6cbbe42SPatrick Rudolph 	int ret;
552e6cbbe42SPatrick Rudolph 
553e6cbbe42SPatrick Rudolph 	/* set output level */
554e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
555e6cbbe42SPatrick Rudolph 	if (ret)
556e6cbbe42SPatrick Rudolph 		return ret;
557e6cbbe42SPatrick Rudolph 
558e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
559e6cbbe42SPatrick Rudolph 	/* select port */
560e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
561e6cbbe42SPatrick Rudolph 	if (ret)
562e6cbbe42SPatrick Rudolph 		goto out;
563e6cbbe42SPatrick Rudolph 
564e6cbbe42SPatrick Rudolph 	/* then direction */
565e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, 0);
566e6cbbe42SPatrick Rudolph 
567e6cbbe42SPatrick Rudolph out:
568e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
569e6cbbe42SPatrick Rudolph 
570e6cbbe42SPatrick Rudolph 	return ret;
571e6cbbe42SPatrick Rudolph }
572e6cbbe42SPatrick Rudolph 
573e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_value(struct gpio_chip *gc, unsigned int off)
574e6cbbe42SPatrick Rudolph {
575e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
576e6cbbe42SPatrick Rudolph 	u8 inreg = CY8C95X0_INPUT_(cypress_get_port(chip, off));
577e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
578e6cbbe42SPatrick Rudolph 	u32 reg_val;
579e6cbbe42SPatrick Rudolph 	int ret;
580e6cbbe42SPatrick Rudolph 
581e6cbbe42SPatrick Rudolph 	ret = regmap_read(chip->regmap, inreg, &reg_val);
582e6cbbe42SPatrick Rudolph 	if (ret < 0) {
583e6cbbe42SPatrick Rudolph 		/*
584e6cbbe42SPatrick Rudolph 		 * NOTE:
585e6cbbe42SPatrick Rudolph 		 * diagnostic already emitted; that's all we should
586e6cbbe42SPatrick Rudolph 		 * do unless gpio_*_value_cansleep() calls become different
587e6cbbe42SPatrick Rudolph 		 * from their nonsleeping siblings (and report faults).
588e6cbbe42SPatrick Rudolph 		 */
589e6cbbe42SPatrick Rudolph 		return 0;
590e6cbbe42SPatrick Rudolph 	}
591e6cbbe42SPatrick Rudolph 
592e6cbbe42SPatrick Rudolph 	return !!(reg_val & bit);
593e6cbbe42SPatrick Rudolph }
594e6cbbe42SPatrick Rudolph 
595e6cbbe42SPatrick Rudolph static void cy8c95x0_gpio_set_value(struct gpio_chip *gc, unsigned int off,
596e6cbbe42SPatrick Rudolph 				    int val)
597e6cbbe42SPatrick Rudolph {
598e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
599e6cbbe42SPatrick Rudolph 	u8 outreg = CY8C95X0_OUTPUT_(cypress_get_port(chip, off));
600e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
601e6cbbe42SPatrick Rudolph 
602e6cbbe42SPatrick Rudolph 	regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
603e6cbbe42SPatrick Rudolph }
604e6cbbe42SPatrick Rudolph 
605e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
606e6cbbe42SPatrick Rudolph {
607e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
608e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
609e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
610e6cbbe42SPatrick Rudolph 	u32 reg_val;
611e6cbbe42SPatrick Rudolph 	int ret;
612e6cbbe42SPatrick Rudolph 
613e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
614e6cbbe42SPatrick Rudolph 
615e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
616e6cbbe42SPatrick Rudolph 	if (ret < 0)
617e6cbbe42SPatrick Rudolph 		goto out;
618e6cbbe42SPatrick Rudolph 
619e6cbbe42SPatrick Rudolph 	ret = regmap_read(chip->regmap, CY8C95X0_DIRECTION, &reg_val);
620e6cbbe42SPatrick Rudolph 	if (ret < 0)
621e6cbbe42SPatrick Rudolph 		goto out;
622e6cbbe42SPatrick Rudolph 
623e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
624e6cbbe42SPatrick Rudolph 
625e6cbbe42SPatrick Rudolph 	if (reg_val & bit)
626e6cbbe42SPatrick Rudolph 		return GPIO_LINE_DIRECTION_IN;
627e6cbbe42SPatrick Rudolph 
628e6cbbe42SPatrick Rudolph 	return GPIO_LINE_DIRECTION_OUT;
629e6cbbe42SPatrick Rudolph out:
630e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
631e6cbbe42SPatrick Rudolph 	return ret;
632e6cbbe42SPatrick Rudolph }
633e6cbbe42SPatrick Rudolph 
634e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
635e6cbbe42SPatrick Rudolph 				    unsigned int off,
636e6cbbe42SPatrick Rudolph 				    unsigned long *config)
637e6cbbe42SPatrick Rudolph {
638e6cbbe42SPatrick Rudolph 	enum pin_config_param param = pinconf_to_config_param(*config);
639e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
640e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
641e6cbbe42SPatrick Rudolph 	unsigned int reg;
642e6cbbe42SPatrick Rudolph 	u32 reg_val;
643e6cbbe42SPatrick Rudolph 	u16 arg = 0;
644e6cbbe42SPatrick Rudolph 	int ret;
645e6cbbe42SPatrick Rudolph 
646e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
647e6cbbe42SPatrick Rudolph 
648e6cbbe42SPatrick Rudolph 	/* select port */
649e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
650e6cbbe42SPatrick Rudolph 	if (ret < 0)
651e6cbbe42SPatrick Rudolph 		goto out;
652e6cbbe42SPatrick Rudolph 
653e6cbbe42SPatrick Rudolph 	switch (param) {
654e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_UP:
655e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PU;
656e6cbbe42SPatrick Rudolph 		break;
657e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_DOWN:
658e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PD;
659e6cbbe42SPatrick Rudolph 		break;
660e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_DISABLE:
661e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_HIZ;
662e6cbbe42SPatrick Rudolph 		break;
663e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
664e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODL;
665e6cbbe42SPatrick Rudolph 		break;
666e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_SOURCE:
667e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODH;
668e6cbbe42SPatrick Rudolph 		break;
669e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_PUSH_PULL:
670e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PP_FAST;
671e6cbbe42SPatrick Rudolph 		break;
672e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_ENABLE:
673e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DIRECTION;
674e6cbbe42SPatrick Rudolph 		break;
675e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_MODE_PWM:
676e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_PWMSEL;
677e6cbbe42SPatrick Rudolph 		break;
678e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_OUTPUT:
679e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_OUTPUT_(port);
680e6cbbe42SPatrick Rudolph 		break;
681e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_OUTPUT_ENABLE:
682e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DIRECTION;
683e6cbbe42SPatrick Rudolph 		break;
684e6cbbe42SPatrick Rudolph 
685e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
686e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_BUS_HOLD:
687e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
688e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_STRENGTH:
689e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_STRENGTH_UA:
690e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_DEBOUNCE:
691e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_SCHMITT:
692e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
693e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_MODE_LOW_POWER:
694e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_PERSIST_STATE:
695e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_POWER_SOURCE:
696e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_SKEW_DELAY:
697e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_SLEEP_HARDWARE_STATE:
698e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_SLEW_RATE:
699e6cbbe42SPatrick Rudolph 	default:
700e6cbbe42SPatrick Rudolph 		ret = -ENOTSUPP;
701e6cbbe42SPatrick Rudolph 		goto out;
702e6cbbe42SPatrick Rudolph 	}
703e6cbbe42SPatrick Rudolph 	/* Writing 1 to one of the drive mode registers will automatically
704e6cbbe42SPatrick Rudolph 	 * clear conflicting set bits in the other drive mode registers.
705e6cbbe42SPatrick Rudolph 	 */
706e6cbbe42SPatrick Rudolph 	ret = regmap_read(chip->regmap, reg, &reg_val);
707e6cbbe42SPatrick Rudolph 	if (reg_val & bit)
708e6cbbe42SPatrick Rudolph 		arg = 1;
709e6cbbe42SPatrick Rudolph 
710e6cbbe42SPatrick Rudolph 	*config = pinconf_to_config_packed(param, (u16)arg);
711e6cbbe42SPatrick Rudolph out:
712e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
713e6cbbe42SPatrick Rudolph 
714e6cbbe42SPatrick Rudolph 	return ret;
715e6cbbe42SPatrick Rudolph }
716e6cbbe42SPatrick Rudolph 
717e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip,
718e6cbbe42SPatrick Rudolph 				    unsigned int off,
719e6cbbe42SPatrick Rudolph 				    unsigned long config)
720e6cbbe42SPatrick Rudolph {
721e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
722e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
723e6cbbe42SPatrick Rudolph 	unsigned long param = pinconf_to_config_param(config);
724e6cbbe42SPatrick Rudolph 	unsigned int reg;
725e6cbbe42SPatrick Rudolph 	int ret;
726e6cbbe42SPatrick Rudolph 
727e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
728e6cbbe42SPatrick Rudolph 
729e6cbbe42SPatrick Rudolph 	/* select port */
730e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
731e6cbbe42SPatrick Rudolph 	if (ret < 0)
732e6cbbe42SPatrick Rudolph 		goto out;
733e6cbbe42SPatrick Rudolph 
734e6cbbe42SPatrick Rudolph 	switch (param) {
735e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_UP:
736e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
737e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PU;
738e6cbbe42SPatrick Rudolph 		break;
739e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_DOWN:
740e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
741e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PD;
742e6cbbe42SPatrick Rudolph 		break;
743e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_DISABLE:
744e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
745e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_HIZ;
746e6cbbe42SPatrick Rudolph 		break;
747e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
748e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
749e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODL;
750e6cbbe42SPatrick Rudolph 		break;
751e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_SOURCE:
752e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
753e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODH;
754e6cbbe42SPatrick Rudolph 		break;
755e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_PUSH_PULL:
756e6cbbe42SPatrick Rudolph 		set_bit(off, chip->push_pull);
757e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PP_FAST;
758e6cbbe42SPatrick Rudolph 		break;
759e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_MODE_PWM:
760e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_PWMSEL;
761e6cbbe42SPatrick Rudolph 		break;
762e6cbbe42SPatrick Rudolph 	default:
763e6cbbe42SPatrick Rudolph 		ret = -ENOTSUPP;
764e6cbbe42SPatrick Rudolph 		goto out;
765e6cbbe42SPatrick Rudolph 	}
766e6cbbe42SPatrick Rudolph 	/* Writing 1 to one of the drive mode registers will automatically
767e6cbbe42SPatrick Rudolph 	 * clear conflicting set bits in the other drive mode registers.
768e6cbbe42SPatrick Rudolph 	 */
769e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, reg, bit, bit);
770e6cbbe42SPatrick Rudolph 
771e6cbbe42SPatrick Rudolph out:
772e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
773e6cbbe42SPatrick Rudolph 	return ret;
774e6cbbe42SPatrick Rudolph }
775e6cbbe42SPatrick Rudolph 
776e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_multiple(struct gpio_chip *gc,
777e6cbbe42SPatrick Rudolph 				      unsigned long *mask, unsigned long *bits)
778e6cbbe42SPatrick Rudolph {
779e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
780e6cbbe42SPatrick Rudolph 
781e6cbbe42SPatrick Rudolph 	return cy8c95x0_read_regs_mask(chip, CY8C95X0_INPUT, bits, mask);
782e6cbbe42SPatrick Rudolph }
783e6cbbe42SPatrick Rudolph 
784e6cbbe42SPatrick Rudolph static void cy8c95x0_gpio_set_multiple(struct gpio_chip *gc,
785e6cbbe42SPatrick Rudolph 				       unsigned long *mask, unsigned long *bits)
786e6cbbe42SPatrick Rudolph {
787e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
788e6cbbe42SPatrick Rudolph 
789e6cbbe42SPatrick Rudolph 	cy8c95x0_write_regs_mask(chip, CY8C95X0_OUTPUT, bits, mask);
790e6cbbe42SPatrick Rudolph }
791e6cbbe42SPatrick Rudolph 
792d86e0344SAndy Shevchenko static int cy8c95x0_add_pin_ranges(struct gpio_chip *gc)
793d86e0344SAndy Shevchenko {
794d86e0344SAndy Shevchenko 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
795d86e0344SAndy Shevchenko 	struct device *dev = chip->dev;
796d86e0344SAndy Shevchenko 	int ret;
797d86e0344SAndy Shevchenko 
798d86e0344SAndy Shevchenko 	ret = gpiochip_add_pin_range(gc, dev_name(dev), 0, 0, chip->tpin);
799d86e0344SAndy Shevchenko 	if (ret)
800d86e0344SAndy Shevchenko 		dev_err(dev, "failed to add GPIO pin range\n");
801d86e0344SAndy Shevchenko 
802d86e0344SAndy Shevchenko 	return ret;
803d86e0344SAndy Shevchenko }
804d86e0344SAndy Shevchenko 
805d86e0344SAndy Shevchenko static int cy8c95x0_setup_gpiochip(struct cy8c95x0_pinctrl *chip)
806e6cbbe42SPatrick Rudolph {
807e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = &chip->gpio_chip;
808e6cbbe42SPatrick Rudolph 
809e6cbbe42SPatrick Rudolph 	gc->direction_input  = cy8c95x0_gpio_direction_input;
810e6cbbe42SPatrick Rudolph 	gc->direction_output = cy8c95x0_gpio_direction_output;
811e6cbbe42SPatrick Rudolph 	gc->get = cy8c95x0_gpio_get_value;
812e6cbbe42SPatrick Rudolph 	gc->set = cy8c95x0_gpio_set_value;
813e6cbbe42SPatrick Rudolph 	gc->get_direction = cy8c95x0_gpio_get_direction;
814e6cbbe42SPatrick Rudolph 	gc->get_multiple = cy8c95x0_gpio_get_multiple;
815e6cbbe42SPatrick Rudolph 	gc->set_multiple = cy8c95x0_gpio_set_multiple;
8161fa3df90SAndy Shevchenko 	gc->set_config = gpiochip_generic_config,
817e6cbbe42SPatrick Rudolph 	gc->can_sleep = true;
818d86e0344SAndy Shevchenko 	gc->add_pin_ranges = cy8c95x0_add_pin_ranges;
819e6cbbe42SPatrick Rudolph 
820e6cbbe42SPatrick Rudolph 	gc->base = -1;
821d86e0344SAndy Shevchenko 	gc->ngpio = chip->tpin;
822e6cbbe42SPatrick Rudolph 
823e6cbbe42SPatrick Rudolph 	gc->parent = chip->dev;
824e6cbbe42SPatrick Rudolph 	gc->owner = THIS_MODULE;
825e6cbbe42SPatrick Rudolph 	gc->names = NULL;
826e6cbbe42SPatrick Rudolph 
827e6cbbe42SPatrick Rudolph 	gc->label = dev_name(chip->dev);
828e6cbbe42SPatrick Rudolph 
829e6cbbe42SPatrick Rudolph 	return devm_gpiochip_add_data(chip->dev, gc, chip);
830e6cbbe42SPatrick Rudolph }
831e6cbbe42SPatrick Rudolph 
832e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_mask(struct irq_data *d)
833e6cbbe42SPatrick Rudolph {
834e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
835e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
836f5d62025SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
837e6cbbe42SPatrick Rudolph 
838f5d62025SAndy Shevchenko 	set_bit(hwirq, chip->irq_mask);
839f5d62025SAndy Shevchenko 	gpiochip_disable_irq(gc, hwirq);
840e6cbbe42SPatrick Rudolph }
841e6cbbe42SPatrick Rudolph 
842e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_unmask(struct irq_data *d)
843e6cbbe42SPatrick Rudolph {
844e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
845e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
846f5d62025SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
847e6cbbe42SPatrick Rudolph 
848f5d62025SAndy Shevchenko 	gpiochip_enable_irq(gc, hwirq);
849f5d62025SAndy Shevchenko 	clear_bit(hwirq, chip->irq_mask);
850e6cbbe42SPatrick Rudolph }
851e6cbbe42SPatrick Rudolph 
852e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_bus_lock(struct irq_data *d)
853e6cbbe42SPatrick Rudolph {
854e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
855e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
856e6cbbe42SPatrick Rudolph 
857e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->irq_lock);
858e6cbbe42SPatrick Rudolph }
859e6cbbe42SPatrick Rudolph 
860e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_bus_sync_unlock(struct irq_data *d)
861e6cbbe42SPatrick Rudolph {
862e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
863e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
864e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(ones, MAX_LINE);
865e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(irq_mask, MAX_LINE);
866e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(reg_direction, MAX_LINE);
867e6cbbe42SPatrick Rudolph 
868e6cbbe42SPatrick Rudolph 	bitmap_fill(ones, MAX_LINE);
869e6cbbe42SPatrick Rudolph 
870e6cbbe42SPatrick Rudolph 	cy8c95x0_write_regs_mask(chip, CY8C95X0_INTMASK, chip->irq_mask, ones);
871e6cbbe42SPatrick Rudolph 
872e6cbbe42SPatrick Rudolph 	/* Switch direction to input if needed */
873e6cbbe42SPatrick Rudolph 	cy8c95x0_read_regs_mask(chip, CY8C95X0_DIRECTION, reg_direction, chip->irq_mask);
874e6cbbe42SPatrick Rudolph 	bitmap_or(irq_mask, chip->irq_mask, reg_direction, MAX_LINE);
875e6cbbe42SPatrick Rudolph 	bitmap_complement(irq_mask, irq_mask, MAX_LINE);
876e6cbbe42SPatrick Rudolph 
877e6cbbe42SPatrick Rudolph 	/* Look for any newly setup interrupt */
878e6cbbe42SPatrick Rudolph 	cy8c95x0_write_regs_mask(chip, CY8C95X0_DIRECTION, ones, irq_mask);
879e6cbbe42SPatrick Rudolph 
880e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->irq_lock);
881e6cbbe42SPatrick Rudolph }
882e6cbbe42SPatrick Rudolph 
883e6cbbe42SPatrick Rudolph static int cy8c95x0_irq_set_type(struct irq_data *d, unsigned int type)
884e6cbbe42SPatrick Rudolph {
885e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
886e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
887e6cbbe42SPatrick Rudolph 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
888e6cbbe42SPatrick Rudolph 	unsigned int trig_type;
889e6cbbe42SPatrick Rudolph 
890e6cbbe42SPatrick Rudolph 	switch (type) {
891e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_EDGE_RISING:
892e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_EDGE_FALLING:
893e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_EDGE_BOTH:
894e6cbbe42SPatrick Rudolph 		trig_type = type;
895e6cbbe42SPatrick Rudolph 		break;
896e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_LEVEL_HIGH:
897e6cbbe42SPatrick Rudolph 		trig_type = IRQ_TYPE_EDGE_RISING;
898e6cbbe42SPatrick Rudolph 		break;
899e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_LEVEL_LOW:
900e6cbbe42SPatrick Rudolph 		trig_type = IRQ_TYPE_EDGE_FALLING;
901e6cbbe42SPatrick Rudolph 		break;
902e6cbbe42SPatrick Rudolph 	default:
903e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "irq %d: unsupported type %d\n", d->irq, type);
904e6cbbe42SPatrick Rudolph 		return -EINVAL;
905e6cbbe42SPatrick Rudolph 	}
906e6cbbe42SPatrick Rudolph 
907e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_fall, trig_type & IRQ_TYPE_EDGE_FALLING);
908e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_raise, trig_type & IRQ_TYPE_EDGE_RISING);
909e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_low, type == IRQ_TYPE_LEVEL_LOW);
910e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_high, type == IRQ_TYPE_LEVEL_HIGH);
911e6cbbe42SPatrick Rudolph 
912e6cbbe42SPatrick Rudolph 	return 0;
913e6cbbe42SPatrick Rudolph }
914e6cbbe42SPatrick Rudolph 
915e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_shutdown(struct irq_data *d)
916e6cbbe42SPatrick Rudolph {
917e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
918e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
919e6cbbe42SPatrick Rudolph 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
920e6cbbe42SPatrick Rudolph 
921e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_raise);
922e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_fall);
923e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_low);
924e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_high);
925e6cbbe42SPatrick Rudolph }
926e6cbbe42SPatrick Rudolph 
927f5d62025SAndy Shevchenko static const struct irq_chip cy8c95x0_irqchip = {
928f5d62025SAndy Shevchenko 	.name = "cy8c95x0-irq",
929f5d62025SAndy Shevchenko 	.irq_mask = cy8c95x0_irq_mask,
930f5d62025SAndy Shevchenko 	.irq_unmask = cy8c95x0_irq_unmask,
931f5d62025SAndy Shevchenko 	.irq_bus_lock = cy8c95x0_irq_bus_lock,
932f5d62025SAndy Shevchenko 	.irq_bus_sync_unlock = cy8c95x0_irq_bus_sync_unlock,
933f5d62025SAndy Shevchenko 	.irq_set_type = cy8c95x0_irq_set_type,
934f5d62025SAndy Shevchenko 	.irq_shutdown = cy8c95x0_irq_shutdown,
935f5d62025SAndy Shevchenko 	.flags = IRQCHIP_IMMUTABLE,
936f5d62025SAndy Shevchenko 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
937f5d62025SAndy Shevchenko };
938f5d62025SAndy Shevchenko 
939e6cbbe42SPatrick Rudolph static bool cy8c95x0_irq_pending(struct cy8c95x0_pinctrl *chip, unsigned long *pending)
940e6cbbe42SPatrick Rudolph {
941e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(ones, MAX_LINE);
942e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(cur_stat, MAX_LINE);
943e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(new_stat, MAX_LINE);
944e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(trigger, MAX_LINE);
945e6cbbe42SPatrick Rudolph 
946e6cbbe42SPatrick Rudolph 	bitmap_fill(ones, MAX_LINE);
947e6cbbe42SPatrick Rudolph 
948e6cbbe42SPatrick Rudolph 	/* Read the current interrupt status from the device */
949e6cbbe42SPatrick Rudolph 	if (cy8c95x0_read_regs_mask(chip, CY8C95X0_INTSTATUS, trigger, ones))
950e6cbbe42SPatrick Rudolph 		return false;
951e6cbbe42SPatrick Rudolph 
952e6cbbe42SPatrick Rudolph 	/* Check latched inputs */
953e6cbbe42SPatrick Rudolph 	if (cy8c95x0_read_regs_mask(chip, CY8C95X0_INPUT, cur_stat, trigger))
954e6cbbe42SPatrick Rudolph 		return false;
955e6cbbe42SPatrick Rudolph 
956e6cbbe42SPatrick Rudolph 	/* Apply filter for rising/falling edge selection */
957e6cbbe42SPatrick Rudolph 	bitmap_replace(new_stat, chip->irq_trig_fall, chip->irq_trig_raise,
958e6cbbe42SPatrick Rudolph 		       cur_stat, MAX_LINE);
959e6cbbe42SPatrick Rudolph 
960e6cbbe42SPatrick Rudolph 	bitmap_and(pending, new_stat, trigger, MAX_LINE);
961e6cbbe42SPatrick Rudolph 
962e6cbbe42SPatrick Rudolph 	return !bitmap_empty(pending, MAX_LINE);
963e6cbbe42SPatrick Rudolph }
964e6cbbe42SPatrick Rudolph 
965e6cbbe42SPatrick Rudolph static irqreturn_t cy8c95x0_irq_handler(int irq, void *devid)
966e6cbbe42SPatrick Rudolph {
967e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = devid;
968e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = &chip->gpio_chip;
969e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(pending, MAX_LINE);
970e6cbbe42SPatrick Rudolph 	int nested_irq, level;
971e6cbbe42SPatrick Rudolph 	bool ret;
972e6cbbe42SPatrick Rudolph 
973e6cbbe42SPatrick Rudolph 	ret = cy8c95x0_irq_pending(chip, pending);
974e6cbbe42SPatrick Rudolph 	if (!ret)
975e6cbbe42SPatrick Rudolph 		return IRQ_RETVAL(0);
976e6cbbe42SPatrick Rudolph 
977e6cbbe42SPatrick Rudolph 	ret = 0;
978e6cbbe42SPatrick Rudolph 	for_each_set_bit(level, pending, MAX_LINE) {
979e6cbbe42SPatrick Rudolph 		/* Already accounted for 4bit gap in GPort2 */
980e6cbbe42SPatrick Rudolph 		nested_irq = irq_find_mapping(gc->irq.domain, level);
981e6cbbe42SPatrick Rudolph 
982e6cbbe42SPatrick Rudolph 		if (unlikely(nested_irq <= 0)) {
983e6cbbe42SPatrick Rudolph 			dev_warn_ratelimited(gc->parent, "unmapped interrupt %d\n", level);
984e6cbbe42SPatrick Rudolph 			continue;
985e6cbbe42SPatrick Rudolph 		}
986e6cbbe42SPatrick Rudolph 
987e6cbbe42SPatrick Rudolph 		if (test_bit(level, chip->irq_trig_low))
988e6cbbe42SPatrick Rudolph 			while (!cy8c95x0_gpio_get_value(gc, level))
989e6cbbe42SPatrick Rudolph 				handle_nested_irq(nested_irq);
990e6cbbe42SPatrick Rudolph 		else if (test_bit(level, chip->irq_trig_high))
991e6cbbe42SPatrick Rudolph 			while (cy8c95x0_gpio_get_value(gc, level))
992e6cbbe42SPatrick Rudolph 				handle_nested_irq(nested_irq);
993e6cbbe42SPatrick Rudolph 		else
994e6cbbe42SPatrick Rudolph 			handle_nested_irq(nested_irq);
995e6cbbe42SPatrick Rudolph 
996e6cbbe42SPatrick Rudolph 		ret = 1;
997e6cbbe42SPatrick Rudolph 	}
998e6cbbe42SPatrick Rudolph 
999e6cbbe42SPatrick Rudolph 	return IRQ_RETVAL(ret);
1000e6cbbe42SPatrick Rudolph }
1001e6cbbe42SPatrick Rudolph 
1002e6cbbe42SPatrick Rudolph static int cy8c95x0_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
1003e6cbbe42SPatrick Rudolph {
1004e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1005e6cbbe42SPatrick Rudolph 
1006e6cbbe42SPatrick Rudolph 	return chip->tpin;
1007e6cbbe42SPatrick Rudolph }
1008e6cbbe42SPatrick Rudolph 
1009e6cbbe42SPatrick Rudolph static const char *cy8c95x0_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
1010e6cbbe42SPatrick Rudolph 						   unsigned int group)
1011e6cbbe42SPatrick Rudolph {
1012e6cbbe42SPatrick Rudolph 	return cy8c95x0_groups[group];
1013e6cbbe42SPatrick Rudolph }
1014e6cbbe42SPatrick Rudolph 
1015e6cbbe42SPatrick Rudolph static int cy8c95x0_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
1016e6cbbe42SPatrick Rudolph 					   unsigned int group,
1017e6cbbe42SPatrick Rudolph 					   const unsigned int **pins,
1018e6cbbe42SPatrick Rudolph 					   unsigned int *num_pins)
1019e6cbbe42SPatrick Rudolph {
1020e6cbbe42SPatrick Rudolph 	*pins = &cy8c9560_pins[group].number;
1021e6cbbe42SPatrick Rudolph 	*num_pins = 1;
1022e6cbbe42SPatrick Rudolph 	return 0;
1023e6cbbe42SPatrick Rudolph }
1024e6cbbe42SPatrick Rudolph 
1025f12352f3SAndy Shevchenko static const char *cy8c95x0_get_fname(unsigned int selector)
1026f12352f3SAndy Shevchenko {
1027f12352f3SAndy Shevchenko 	if (selector == 0)
1028f12352f3SAndy Shevchenko 		return "gpio";
1029f12352f3SAndy Shevchenko 	else
1030f12352f3SAndy Shevchenko 		return "pwm";
1031f12352f3SAndy Shevchenko }
1032f12352f3SAndy Shevchenko 
1033f12352f3SAndy Shevchenko static void cy8c95x0_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
1034f12352f3SAndy Shevchenko 				  unsigned int pin)
1035f12352f3SAndy Shevchenko {
1036f12352f3SAndy Shevchenko 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1037f12352f3SAndy Shevchenko 	DECLARE_BITMAP(mask, MAX_LINE);
1038f12352f3SAndy Shevchenko 	DECLARE_BITMAP(pwm, MAX_LINE);
1039f12352f3SAndy Shevchenko 
1040f12352f3SAndy Shevchenko 	bitmap_zero(mask, MAX_LINE);
1041f12352f3SAndy Shevchenko 	__set_bit(pin, mask);
1042f12352f3SAndy Shevchenko 
1043f12352f3SAndy Shevchenko 	if (cy8c95x0_read_regs_mask(chip, CY8C95X0_PWMSEL, pwm, mask)) {
1044f12352f3SAndy Shevchenko 		seq_puts(s, "not available");
1045f12352f3SAndy Shevchenko 		return;
1046f12352f3SAndy Shevchenko 	}
1047f12352f3SAndy Shevchenko 
1048f12352f3SAndy Shevchenko 	seq_printf(s, "MODE:%s", cy8c95x0_get_fname(test_bit(pin, pwm)));
1049f12352f3SAndy Shevchenko }
1050f12352f3SAndy Shevchenko 
1051e6cbbe42SPatrick Rudolph static const struct pinctrl_ops cy8c95x0_pinctrl_ops = {
1052e6cbbe42SPatrick Rudolph 	.get_groups_count = cy8c95x0_pinctrl_get_groups_count,
1053e6cbbe42SPatrick Rudolph 	.get_group_name = cy8c95x0_pinctrl_get_group_name,
1054e6cbbe42SPatrick Rudolph 	.get_group_pins = cy8c95x0_pinctrl_get_group_pins,
1055*8586466eSAndy Shevchenko #ifdef CONFIG_OF
1056e6cbbe42SPatrick Rudolph 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
1057e6cbbe42SPatrick Rudolph 	.dt_free_map = pinconf_generic_dt_free_map,
1058*8586466eSAndy Shevchenko #endif
1059f12352f3SAndy Shevchenko 	.pin_dbg_show = cy8c95x0_pin_dbg_show,
1060e6cbbe42SPatrick Rudolph };
1061e6cbbe42SPatrick Rudolph 
1062f12352f3SAndy Shevchenko static const char *cy8c95x0_get_functions_name(struct pinctrl_dev *pctldev, unsigned int selector)
1063f12352f3SAndy Shevchenko {
1064f12352f3SAndy Shevchenko 	return cy8c95x0_get_fname(selector);
1065f12352f3SAndy Shevchenko }
1066f12352f3SAndy Shevchenko 
1067e6cbbe42SPatrick Rudolph static int cy8c95x0_get_functions_count(struct pinctrl_dev *pctldev)
1068e6cbbe42SPatrick Rudolph {
1069e6cbbe42SPatrick Rudolph 	return 2;
1070e6cbbe42SPatrick Rudolph }
1071e6cbbe42SPatrick Rudolph 
1072e6cbbe42SPatrick Rudolph static int cy8c95x0_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
1073e6cbbe42SPatrick Rudolph 			       const char * const **groups,
1074e6cbbe42SPatrick Rudolph 			       unsigned int * const num_groups)
1075e6cbbe42SPatrick Rudolph {
1076e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1077e6cbbe42SPatrick Rudolph 
1078e6cbbe42SPatrick Rudolph 	*groups = cy8c95x0_groups;
1079e6cbbe42SPatrick Rudolph 	*num_groups = chip->tpin;
1080e6cbbe42SPatrick Rudolph 	return 0;
1081e6cbbe42SPatrick Rudolph }
1082e6cbbe42SPatrick Rudolph 
1083e6cbbe42SPatrick Rudolph static int cy8c95x0_pinmux_cfg(struct cy8c95x0_pinctrl *chip,
1084e6cbbe42SPatrick Rudolph 			       unsigned int val,
1085e6cbbe42SPatrick Rudolph 			       unsigned long off)
1086e6cbbe42SPatrick Rudolph {
1087e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
1088e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
1089e6cbbe42SPatrick Rudolph 	int ret;
1090e6cbbe42SPatrick Rudolph 
1091e6cbbe42SPatrick Rudolph 	/* select port */
1092e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
1093e6cbbe42SPatrick Rudolph 	if (ret < 0)
1094e6cbbe42SPatrick Rudolph 		return ret;
1095e6cbbe42SPatrick Rudolph 
1096e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, CY8C95X0_PWMSEL, bit, val ? bit : 0);
1097e6cbbe42SPatrick Rudolph 	if (ret < 0)
1098e6cbbe42SPatrick Rudolph 		return ret;
1099e6cbbe42SPatrick Rudolph 
1100e6cbbe42SPatrick Rudolph 	/* Set direction to output & set output to 1 so that PWM can work */
1101e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, bit);
1102e6cbbe42SPatrick Rudolph 	if (ret < 0)
1103e6cbbe42SPatrick Rudolph 		return ret;
1104e6cbbe42SPatrick Rudolph 
1105e6cbbe42SPatrick Rudolph 	return regmap_write_bits(chip->regmap, CY8C95X0_OUTPUT_(port), bit, bit);
1106e6cbbe42SPatrick Rudolph }
1107e6cbbe42SPatrick Rudolph 
1108e6cbbe42SPatrick Rudolph static int cy8c95x0_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
1109e6cbbe42SPatrick Rudolph 			    unsigned int group)
1110e6cbbe42SPatrick Rudolph {
1111e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1112e6cbbe42SPatrick Rudolph 
1113e6cbbe42SPatrick Rudolph 	return cy8c95x0_pinmux_cfg(chip, selector, group);
1114e6cbbe42SPatrick Rudolph }
1115e6cbbe42SPatrick Rudolph 
1116e6cbbe42SPatrick Rudolph static const struct pinmux_ops cy8c95x0_pmxops = {
1117e6cbbe42SPatrick Rudolph 	.get_functions_count = cy8c95x0_get_functions_count,
1118f12352f3SAndy Shevchenko 	.get_function_name = cy8c95x0_get_functions_name,
1119e6cbbe42SPatrick Rudolph 	.get_function_groups = cy8c95x0_get_groups,
1120e6cbbe42SPatrick Rudolph 	.set_mux = cy8c95x0_set_mux,
1121e6cbbe42SPatrick Rudolph 	.strict = true,
1122e6cbbe42SPatrick Rudolph };
1123e6cbbe42SPatrick Rudolph 
1124e6cbbe42SPatrick Rudolph static int cy8c95x0_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
1125e6cbbe42SPatrick Rudolph 				unsigned long *config)
1126e6cbbe42SPatrick Rudolph {
1127e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1128e6cbbe42SPatrick Rudolph 
1129e6cbbe42SPatrick Rudolph 	return cy8c95x0_gpio_get_pincfg(chip, pin, config);
1130e6cbbe42SPatrick Rudolph }
1131e6cbbe42SPatrick Rudolph 
1132e6cbbe42SPatrick Rudolph static int cy8c95x0_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
1133e6cbbe42SPatrick Rudolph 				unsigned long *configs, unsigned int num_configs)
1134e6cbbe42SPatrick Rudolph {
1135e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1136e6cbbe42SPatrick Rudolph 	int ret = 0;
1137e6cbbe42SPatrick Rudolph 	int i;
1138e6cbbe42SPatrick Rudolph 
1139e6cbbe42SPatrick Rudolph 	for (i = 0; i < num_configs; i++) {
1140e6cbbe42SPatrick Rudolph 		ret = cy8c95x0_gpio_set_pincfg(chip, pin, configs[i]);
1141e6cbbe42SPatrick Rudolph 		if (ret)
1142e6cbbe42SPatrick Rudolph 			return ret;
1143e6cbbe42SPatrick Rudolph 	}
1144e6cbbe42SPatrick Rudolph 
1145e6cbbe42SPatrick Rudolph 	return ret;
1146e6cbbe42SPatrick Rudolph }
1147e6cbbe42SPatrick Rudolph 
1148e6cbbe42SPatrick Rudolph static const struct pinconf_ops cy8c95x0_pinconf_ops = {
1149e6cbbe42SPatrick Rudolph 	.pin_config_get = cy8c95x0_pinconf_get,
1150e6cbbe42SPatrick Rudolph 	.pin_config_set = cy8c95x0_pinconf_set,
1151e6cbbe42SPatrick Rudolph 	.is_generic = true,
1152e6cbbe42SPatrick Rudolph };
1153e6cbbe42SPatrick Rudolph 
1154e6cbbe42SPatrick Rudolph static int cy8c95x0_irq_setup(struct cy8c95x0_pinctrl *chip, int irq)
1155e6cbbe42SPatrick Rudolph {
1156e6cbbe42SPatrick Rudolph 	struct gpio_irq_chip *girq = &chip->gpio_chip.irq;
1157e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(pending_irqs, MAX_LINE);
1158e6cbbe42SPatrick Rudolph 	int ret;
1159e6cbbe42SPatrick Rudolph 
1160e6cbbe42SPatrick Rudolph 	mutex_init(&chip->irq_lock);
1161e6cbbe42SPatrick Rudolph 
1162e6cbbe42SPatrick Rudolph 	bitmap_zero(pending_irqs, MAX_LINE);
1163e6cbbe42SPatrick Rudolph 
1164e6cbbe42SPatrick Rudolph 	/* Read IRQ status register to clear all pending interrupts */
1165e6cbbe42SPatrick Rudolph 	ret = cy8c95x0_irq_pending(chip, pending_irqs);
1166e6cbbe42SPatrick Rudolph 	if (ret) {
1167e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "failed to clear irq status register\n");
1168e6cbbe42SPatrick Rudolph 		return ret;
1169e6cbbe42SPatrick Rudolph 	}
1170e6cbbe42SPatrick Rudolph 
1171e6cbbe42SPatrick Rudolph 	/* Mask all interrupts */
1172e6cbbe42SPatrick Rudolph 	bitmap_fill(chip->irq_mask, MAX_LINE);
1173e6cbbe42SPatrick Rudolph 
1174f5d62025SAndy Shevchenko 	gpio_irq_chip_set_chip(girq, &cy8c95x0_irqchip);
1175e6cbbe42SPatrick Rudolph 
1176e6cbbe42SPatrick Rudolph 	/* This will let us handle the parent IRQ in the driver */
1177e6cbbe42SPatrick Rudolph 	girq->parent_handler = NULL;
1178e6cbbe42SPatrick Rudolph 	girq->num_parents = 0;
1179e6cbbe42SPatrick Rudolph 	girq->parents = NULL;
1180e6cbbe42SPatrick Rudolph 	girq->default_type = IRQ_TYPE_NONE;
1181e6cbbe42SPatrick Rudolph 	girq->handler = handle_simple_irq;
1182e6cbbe42SPatrick Rudolph 	girq->threaded = true;
1183e6cbbe42SPatrick Rudolph 
1184e6cbbe42SPatrick Rudolph 	ret = devm_request_threaded_irq(chip->dev, irq,
1185e6cbbe42SPatrick Rudolph 					NULL, cy8c95x0_irq_handler,
1186e6cbbe42SPatrick Rudolph 					IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_HIGH,
1187e6cbbe42SPatrick Rudolph 					dev_name(chip->dev), chip);
1188e6cbbe42SPatrick Rudolph 	if (ret) {
1189e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "failed to request irq %d\n", irq);
1190e6cbbe42SPatrick Rudolph 		return ret;
1191e6cbbe42SPatrick Rudolph 	}
1192e6cbbe42SPatrick Rudolph 	dev_info(chip->dev, "Registered threaded IRQ\n");
1193e6cbbe42SPatrick Rudolph 
1194e6cbbe42SPatrick Rudolph 	return 0;
1195e6cbbe42SPatrick Rudolph }
1196e6cbbe42SPatrick Rudolph 
1197e6cbbe42SPatrick Rudolph static int cy8c95x0_setup_pinctrl(struct cy8c95x0_pinctrl *chip)
1198e6cbbe42SPatrick Rudolph {
1199e6cbbe42SPatrick Rudolph 	struct pinctrl_desc *pd = &chip->pinctrl_desc;
1200e6cbbe42SPatrick Rudolph 
1201e6cbbe42SPatrick Rudolph 	pd->pctlops = &cy8c95x0_pinctrl_ops;
1202e6cbbe42SPatrick Rudolph 	pd->confops = &cy8c95x0_pinconf_ops;
1203e6cbbe42SPatrick Rudolph 	pd->pmxops = &cy8c95x0_pmxops;
1204641d6cc6SAndy Shevchenko 	pd->name = dev_name(chip->dev);
1205e6cbbe42SPatrick Rudolph 	pd->pins = cy8c9560_pins;
1206e6cbbe42SPatrick Rudolph 	pd->npins = chip->tpin;
1207e6cbbe42SPatrick Rudolph 	pd->owner = THIS_MODULE;
1208e6cbbe42SPatrick Rudolph 	chip->pctldev = devm_pinctrl_register(chip->dev, pd, chip);
1209e6cbbe42SPatrick Rudolph 
1210e6cbbe42SPatrick Rudolph 	if (IS_ERR(chip->pctldev))
1211e6cbbe42SPatrick Rudolph 		return dev_err_probe(chip->dev, PTR_ERR(chip->pctldev),
1212e6cbbe42SPatrick Rudolph 			"can't register controller\n");
1213e6cbbe42SPatrick Rudolph 	return 0;
1214e6cbbe42SPatrick Rudolph }
1215e6cbbe42SPatrick Rudolph 
1216e6cbbe42SPatrick Rudolph static int cy8c95x0_detect(struct i2c_client *client,
1217e6cbbe42SPatrick Rudolph 			   struct i2c_board_info *info)
1218e6cbbe42SPatrick Rudolph {
1219e6cbbe42SPatrick Rudolph 	struct i2c_adapter *adapter = client->adapter;
1220e6cbbe42SPatrick Rudolph 	int ret;
1221e6cbbe42SPatrick Rudolph 	const char *name;
1222e6cbbe42SPatrick Rudolph 
1223e6cbbe42SPatrick Rudolph 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1224e6cbbe42SPatrick Rudolph 		return -ENODEV;
1225e6cbbe42SPatrick Rudolph 
1226e6cbbe42SPatrick Rudolph 	ret = i2c_smbus_read_byte_data(client, CY8C95X0_DEVID);
1227e6cbbe42SPatrick Rudolph 	if (ret < 0)
1228e6cbbe42SPatrick Rudolph 		return ret;
1229e6cbbe42SPatrick Rudolph 	switch (ret & 0xf0) {
1230e6cbbe42SPatrick Rudolph 	case 0x20:
1231e6cbbe42SPatrick Rudolph 		name = cy8c95x0_id[0].name;
1232e6cbbe42SPatrick Rudolph 		break;
1233e6cbbe42SPatrick Rudolph 	case 0x40:
1234e6cbbe42SPatrick Rudolph 		name = cy8c95x0_id[1].name;
1235e6cbbe42SPatrick Rudolph 		break;
1236e6cbbe42SPatrick Rudolph 	case 0x60:
1237e6cbbe42SPatrick Rudolph 		name = cy8c95x0_id[2].name;
1238e6cbbe42SPatrick Rudolph 		break;
1239e6cbbe42SPatrick Rudolph 	default:
1240e6cbbe42SPatrick Rudolph 		return -ENODEV;
1241e6cbbe42SPatrick Rudolph 	}
1242e6cbbe42SPatrick Rudolph 
1243e6cbbe42SPatrick Rudolph 	dev_info(&client->dev, "Found a %s chip at 0x%02x.\n", name, client->addr);
1244e6cbbe42SPatrick Rudolph 	strscpy(info->type, name, I2C_NAME_SIZE);
1245e6cbbe42SPatrick Rudolph 
124643dcf873SAndy Shevchenko 	return 0;
1247e6cbbe42SPatrick Rudolph }
1248e6cbbe42SPatrick Rudolph 
1249e6cbbe42SPatrick Rudolph static int cy8c95x0_probe(struct i2c_client *client)
1250e6cbbe42SPatrick Rudolph {
1251e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip;
1252e6cbbe42SPatrick Rudolph 	struct regulator *reg;
1253e6cbbe42SPatrick Rudolph 	int ret;
1254e6cbbe42SPatrick Rudolph 
1255e6cbbe42SPatrick Rudolph 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
1256e6cbbe42SPatrick Rudolph 	if (!chip)
1257e6cbbe42SPatrick Rudolph 		return -ENOMEM;
1258e6cbbe42SPatrick Rudolph 
1259e6cbbe42SPatrick Rudolph 	chip->dev = &client->dev;
1260e6cbbe42SPatrick Rudolph 
1261e6cbbe42SPatrick Rudolph 	/* Set the device type */
1262*8586466eSAndy Shevchenko 	chip->driver_data = (unsigned long)device_get_match_data(&client->dev);
1263*8586466eSAndy Shevchenko 	if (!chip->driver_data)
1264e6cbbe42SPatrick Rudolph 		chip->driver_data = i2c_match_id(cy8c95x0_id, client)->driver_data;
1265e6cbbe42SPatrick Rudolph 
1266e6cbbe42SPatrick Rudolph 	if (!chip->driver_data)
1267e6cbbe42SPatrick Rudolph 		return -ENODEV;
1268e6cbbe42SPatrick Rudolph 
1269e6cbbe42SPatrick Rudolph 	i2c_set_clientdata(client, chip);
1270e6cbbe42SPatrick Rudolph 
1271e6cbbe42SPatrick Rudolph 	chip->tpin = chip->driver_data & CY8C95X0_GPIO_MASK;
1272e6cbbe42SPatrick Rudolph 	chip->nport = DIV_ROUND_UP(CY8C95X0_PIN_TO_OFFSET(chip->tpin), BANK_SZ);
1273e6cbbe42SPatrick Rudolph 
1274e6cbbe42SPatrick Rudolph 	switch (chip->tpin) {
1275e6cbbe42SPatrick Rudolph 	case 20:
1276e6cbbe42SPatrick Rudolph 		strscpy(chip->name, cy8c95x0_id[0].name, I2C_NAME_SIZE);
1277e6cbbe42SPatrick Rudolph 		break;
1278e6cbbe42SPatrick Rudolph 	case 40:
1279e6cbbe42SPatrick Rudolph 		strscpy(chip->name, cy8c95x0_id[1].name, I2C_NAME_SIZE);
1280e6cbbe42SPatrick Rudolph 		break;
1281e6cbbe42SPatrick Rudolph 	case 60:
1282e6cbbe42SPatrick Rudolph 		strscpy(chip->name, cy8c95x0_id[2].name, I2C_NAME_SIZE);
1283e6cbbe42SPatrick Rudolph 		break;
1284c3e40952SAndy Shevchenko 	default:
1285c3e40952SAndy Shevchenko 		return -ENODEV;
1286e6cbbe42SPatrick Rudolph 	}
1287e6cbbe42SPatrick Rudolph 
1288e6cbbe42SPatrick Rudolph 	reg = devm_regulator_get(&client->dev, "vdd");
1289e6cbbe42SPatrick Rudolph 	if (IS_ERR(reg)) {
1290e6cbbe42SPatrick Rudolph 		if (PTR_ERR(reg) == -EPROBE_DEFER)
1291e6cbbe42SPatrick Rudolph 			return -EPROBE_DEFER;
1292e6cbbe42SPatrick Rudolph 	} else {
1293e6cbbe42SPatrick Rudolph 		ret = regulator_enable(reg);
1294e6cbbe42SPatrick Rudolph 		if (ret) {
1295e6cbbe42SPatrick Rudolph 			dev_err(&client->dev, "failed to enable regulator vdd: %d\n", ret);
1296e6cbbe42SPatrick Rudolph 			return ret;
1297e6cbbe42SPatrick Rudolph 		}
1298e6cbbe42SPatrick Rudolph 		chip->regulator = reg;
1299e6cbbe42SPatrick Rudolph 	}
1300e6cbbe42SPatrick Rudolph 
1301e6cbbe42SPatrick Rudolph 	chip->regmap = devm_regmap_init_i2c(client, &cy8c95x0_i2c_regmap);
1302e6cbbe42SPatrick Rudolph 	if (IS_ERR(chip->regmap)) {
1303e6cbbe42SPatrick Rudolph 		ret = PTR_ERR(chip->regmap);
1304e6cbbe42SPatrick Rudolph 		goto err_exit;
1305e6cbbe42SPatrick Rudolph 	}
1306e6cbbe42SPatrick Rudolph 
1307e6cbbe42SPatrick Rudolph 	bitmap_zero(chip->push_pull, MAX_LINE);
1308e6cbbe42SPatrick Rudolph 	bitmap_zero(chip->shiftmask, MAX_LINE);
1309e6cbbe42SPatrick Rudolph 	bitmap_set(chip->shiftmask, 0, 20);
1310e6cbbe42SPatrick Rudolph 	mutex_init(&chip->i2c_lock);
1311e6cbbe42SPatrick Rudolph 
1312e6cbbe42SPatrick Rudolph 	if (client->irq) {
1313e6cbbe42SPatrick Rudolph 		ret = cy8c95x0_irq_setup(chip, client->irq);
1314e6cbbe42SPatrick Rudolph 		if (ret)
1315e6cbbe42SPatrick Rudolph 			goto err_exit;
1316e6cbbe42SPatrick Rudolph 	}
1317e6cbbe42SPatrick Rudolph 
1318d86e0344SAndy Shevchenko 	ret = cy8c95x0_setup_pinctrl(chip);
1319e6cbbe42SPatrick Rudolph 	if (ret)
1320e6cbbe42SPatrick Rudolph 		goto err_exit;
1321e6cbbe42SPatrick Rudolph 
1322d86e0344SAndy Shevchenko 	ret = cy8c95x0_setup_gpiochip(chip);
1323e6cbbe42SPatrick Rudolph 	if (ret)
1324e6cbbe42SPatrick Rudolph 		goto err_exit;
1325e6cbbe42SPatrick Rudolph 
1326e6cbbe42SPatrick Rudolph 	return 0;
1327e6cbbe42SPatrick Rudolph 
1328e6cbbe42SPatrick Rudolph err_exit:
1329e6cbbe42SPatrick Rudolph 	if (!IS_ERR_OR_NULL(chip->regulator))
1330e6cbbe42SPatrick Rudolph 		regulator_disable(chip->regulator);
1331e6cbbe42SPatrick Rudolph 	return ret;
1332e6cbbe42SPatrick Rudolph }
1333e6cbbe42SPatrick Rudolph 
1334bbe2a5d8SStephen Rothwell static void cy8c95x0_remove(struct i2c_client *client)
1335e6cbbe42SPatrick Rudolph {
1336e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = i2c_get_clientdata(client);
1337e6cbbe42SPatrick Rudolph 
1338e6cbbe42SPatrick Rudolph 	if (!IS_ERR_OR_NULL(chip->regulator))
1339e6cbbe42SPatrick Rudolph 		regulator_disable(chip->regulator);
1340e6cbbe42SPatrick Rudolph }
1341e6cbbe42SPatrick Rudolph 
1342e6cbbe42SPatrick Rudolph static struct i2c_driver cy8c95x0_driver = {
1343e6cbbe42SPatrick Rudolph 	.driver = {
1344e6cbbe42SPatrick Rudolph 		.name	= "cy8c95x0-pinctrl",
1345e6cbbe42SPatrick Rudolph 		.of_match_table = cy8c95x0_dt_ids,
1346e6cbbe42SPatrick Rudolph 	},
1347e6cbbe42SPatrick Rudolph 	.probe_new	= cy8c95x0_probe,
1348e6cbbe42SPatrick Rudolph 	.remove		= cy8c95x0_remove,
1349e6cbbe42SPatrick Rudolph 	.id_table	= cy8c95x0_id,
1350e6cbbe42SPatrick Rudolph 	.detect		= cy8c95x0_detect,
1351e6cbbe42SPatrick Rudolph };
1352e6cbbe42SPatrick Rudolph 
1353e6cbbe42SPatrick Rudolph module_i2c_driver(cy8c95x0_driver);
1354e6cbbe42SPatrick Rudolph 
1355e6cbbe42SPatrick Rudolph MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>");
1356e6cbbe42SPatrick Rudolph MODULE_AUTHOR("Naresh Solanki <naresh.solanki@9elements.com>");
1357e6cbbe42SPatrick Rudolph MODULE_DESCRIPTION("Pinctrl driver for CY8C95X0");
1358e6cbbe42SPatrick Rudolph MODULE_LICENSE("GPL");
1359