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