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