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