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
6*63e23304SAndy Shevchenko  * Authors: Patrick Rudolph <patrick.rudolph@9elements.com>
7*63e23304SAndy 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
40*63e23304SAndy 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;
360e6cbbe42SPatrick Rudolph 	}
361e6cbbe42SPatrick Rudolph 
362e6cbbe42SPatrick Rudolph 	return false;
363e6cbbe42SPatrick Rudolph }
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) {
431*63e23304SAndy 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;
448*63e23304SAndy 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) {
502*63e23304SAndy 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;
519*63e23304SAndy 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;
576e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
577e6cbbe42SPatrick Rudolph 	}
578e6cbbe42SPatrick Rudolph 
579e6cbbe42SPatrick Rudolph out:
580e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
581e6cbbe42SPatrick Rudolph 
582e6cbbe42SPatrick Rudolph 	return ret;
583e6cbbe42SPatrick Rudolph }
584e6cbbe42SPatrick Rudolph 
585e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_direction_output(struct gpio_chip *gc,
586e6cbbe42SPatrick Rudolph 					  unsigned int off, int val)
587e6cbbe42SPatrick Rudolph {
588e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
589e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
590e6cbbe42SPatrick Rudolph 	u8 outreg = CY8C95X0_OUTPUT_(port);
591e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
592e6cbbe42SPatrick Rudolph 	int ret;
593e6cbbe42SPatrick Rudolph 
594*63e23304SAndy Shevchenko 	/* Set output level */
595e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
596e6cbbe42SPatrick Rudolph 	if (ret)
597e6cbbe42SPatrick Rudolph 		return ret;
598e6cbbe42SPatrick Rudolph 
599e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
600*63e23304SAndy Shevchenko 	/* Select port... */
601e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
602e6cbbe42SPatrick Rudolph 	if (ret)
603e6cbbe42SPatrick Rudolph 		goto out;
604e6cbbe42SPatrick Rudolph 
605*63e23304SAndy Shevchenko 	/* ...then direction */
606e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, 0);
607e6cbbe42SPatrick Rudolph 
608e6cbbe42SPatrick Rudolph out:
609e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
610e6cbbe42SPatrick Rudolph 
611e6cbbe42SPatrick Rudolph 	return ret;
612e6cbbe42SPatrick Rudolph }
613e6cbbe42SPatrick Rudolph 
614e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_value(struct gpio_chip *gc, unsigned int off)
615e6cbbe42SPatrick Rudolph {
616e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
617e6cbbe42SPatrick Rudolph 	u8 inreg = CY8C95X0_INPUT_(cypress_get_port(chip, off));
618e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
619e6cbbe42SPatrick Rudolph 	u32 reg_val;
620e6cbbe42SPatrick Rudolph 	int ret;
621e6cbbe42SPatrick Rudolph 
622e6cbbe42SPatrick Rudolph 	ret = regmap_read(chip->regmap, inreg, &reg_val);
623e6cbbe42SPatrick Rudolph 	if (ret < 0) {
624e6cbbe42SPatrick Rudolph 		/*
625e6cbbe42SPatrick Rudolph 		 * NOTE:
626*63e23304SAndy Shevchenko 		 * Diagnostic already emitted; that's all we should
627e6cbbe42SPatrick Rudolph 		 * do unless gpio_*_value_cansleep() calls become different
628e6cbbe42SPatrick Rudolph 		 * from their nonsleeping siblings (and report faults).
629e6cbbe42SPatrick Rudolph 		 */
630e6cbbe42SPatrick Rudolph 		return 0;
631e6cbbe42SPatrick Rudolph 	}
632e6cbbe42SPatrick Rudolph 
633e6cbbe42SPatrick Rudolph 	return !!(reg_val & bit);
634e6cbbe42SPatrick Rudolph }
635e6cbbe42SPatrick Rudolph 
636e6cbbe42SPatrick Rudolph static void cy8c95x0_gpio_set_value(struct gpio_chip *gc, unsigned int off,
637e6cbbe42SPatrick Rudolph 				    int val)
638e6cbbe42SPatrick Rudolph {
639e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
640e6cbbe42SPatrick Rudolph 	u8 outreg = CY8C95X0_OUTPUT_(cypress_get_port(chip, off));
641e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
642e6cbbe42SPatrick Rudolph 
643e6cbbe42SPatrick Rudolph 	regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
644e6cbbe42SPatrick Rudolph }
645e6cbbe42SPatrick Rudolph 
646e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
647e6cbbe42SPatrick Rudolph {
648e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
649e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
650e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
651e6cbbe42SPatrick Rudolph 	u32 reg_val;
652e6cbbe42SPatrick Rudolph 	int ret;
653e6cbbe42SPatrick Rudolph 
654e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
655e6cbbe42SPatrick Rudolph 
656e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
657e6cbbe42SPatrick Rudolph 	if (ret < 0)
658e6cbbe42SPatrick Rudolph 		goto out;
659e6cbbe42SPatrick Rudolph 
660e6cbbe42SPatrick Rudolph 	ret = regmap_read(chip->regmap, CY8C95X0_DIRECTION, &reg_val);
661e6cbbe42SPatrick Rudolph 	if (ret < 0)
662e6cbbe42SPatrick Rudolph 		goto out;
663e6cbbe42SPatrick Rudolph 
664e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
665e6cbbe42SPatrick Rudolph 
666e6cbbe42SPatrick Rudolph 	if (reg_val & bit)
667e6cbbe42SPatrick Rudolph 		return GPIO_LINE_DIRECTION_IN;
668e6cbbe42SPatrick Rudolph 
669e6cbbe42SPatrick Rudolph 	return GPIO_LINE_DIRECTION_OUT;
670e6cbbe42SPatrick Rudolph out:
671e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
672e6cbbe42SPatrick Rudolph 	return ret;
673e6cbbe42SPatrick Rudolph }
674e6cbbe42SPatrick Rudolph 
675e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
676e6cbbe42SPatrick Rudolph 				    unsigned int off,
677e6cbbe42SPatrick Rudolph 				    unsigned long *config)
678e6cbbe42SPatrick Rudolph {
679e6cbbe42SPatrick Rudolph 	enum pin_config_param param = pinconf_to_config_param(*config);
680e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
681e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
682e6cbbe42SPatrick Rudolph 	unsigned int reg;
683e6cbbe42SPatrick Rudolph 	u32 reg_val;
684e6cbbe42SPatrick Rudolph 	u16 arg = 0;
685e6cbbe42SPatrick Rudolph 	int ret;
686e6cbbe42SPatrick Rudolph 
687e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
688e6cbbe42SPatrick Rudolph 
689*63e23304SAndy Shevchenko 	/* Select port */
690e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
691e6cbbe42SPatrick Rudolph 	if (ret < 0)
692e6cbbe42SPatrick Rudolph 		goto out;
693e6cbbe42SPatrick Rudolph 
694e6cbbe42SPatrick Rudolph 	switch (param) {
695e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_UP:
696e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PU;
697e6cbbe42SPatrick Rudolph 		break;
698e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_DOWN:
699e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PD;
700e6cbbe42SPatrick Rudolph 		break;
701e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_DISABLE:
702e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_HIZ;
703e6cbbe42SPatrick Rudolph 		break;
704e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
705e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODL;
706e6cbbe42SPatrick Rudolph 		break;
707e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_SOURCE:
708e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODH;
709e6cbbe42SPatrick Rudolph 		break;
710e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_PUSH_PULL:
711e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PP_FAST;
712e6cbbe42SPatrick Rudolph 		break;
713e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_ENABLE:
714e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DIRECTION;
715e6cbbe42SPatrick Rudolph 		break;
716e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_MODE_PWM:
717e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_PWMSEL;
718e6cbbe42SPatrick Rudolph 		break;
719e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_OUTPUT:
720e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_OUTPUT_(port);
721e6cbbe42SPatrick Rudolph 		break;
722e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_OUTPUT_ENABLE:
723e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DIRECTION;
724e6cbbe42SPatrick Rudolph 		break;
725e6cbbe42SPatrick Rudolph 
726e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
727e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_BUS_HOLD:
728e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
729e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_STRENGTH:
730e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_STRENGTH_UA:
731e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_DEBOUNCE:
732e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_SCHMITT:
733e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
734e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_MODE_LOW_POWER:
735e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_PERSIST_STATE:
736e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_POWER_SOURCE:
737e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_SKEW_DELAY:
738e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_SLEEP_HARDWARE_STATE:
739e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_SLEW_RATE:
740e6cbbe42SPatrick Rudolph 	default:
741e6cbbe42SPatrick Rudolph 		ret = -ENOTSUPP;
742e6cbbe42SPatrick Rudolph 		goto out;
743e6cbbe42SPatrick Rudolph 	}
744*63e23304SAndy Shevchenko 	/*
745*63e23304SAndy Shevchenko 	 * Writing 1 to one of the drive mode registers will automatically
746e6cbbe42SPatrick Rudolph 	 * clear conflicting set bits in the other drive mode registers.
747e6cbbe42SPatrick Rudolph 	 */
748e6cbbe42SPatrick Rudolph 	ret = regmap_read(chip->regmap, reg, &reg_val);
749e6cbbe42SPatrick Rudolph 	if (reg_val & bit)
750e6cbbe42SPatrick Rudolph 		arg = 1;
751e6cbbe42SPatrick Rudolph 
752e6cbbe42SPatrick Rudolph 	*config = pinconf_to_config_packed(param, (u16)arg);
753e6cbbe42SPatrick Rudolph out:
754e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
755e6cbbe42SPatrick Rudolph 
756e6cbbe42SPatrick Rudolph 	return ret;
757e6cbbe42SPatrick Rudolph }
758e6cbbe42SPatrick Rudolph 
759e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip,
760e6cbbe42SPatrick Rudolph 				    unsigned int off,
761e6cbbe42SPatrick Rudolph 				    unsigned long config)
762e6cbbe42SPatrick Rudolph {
763e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
764e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
765e6cbbe42SPatrick Rudolph 	unsigned long param = pinconf_to_config_param(config);
766e6cbbe42SPatrick Rudolph 	unsigned int reg;
767e6cbbe42SPatrick Rudolph 	int ret;
768e6cbbe42SPatrick Rudolph 
769e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->i2c_lock);
770e6cbbe42SPatrick Rudolph 
771*63e23304SAndy Shevchenko 	/* Select port */
772e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
773e6cbbe42SPatrick Rudolph 	if (ret < 0)
774e6cbbe42SPatrick Rudolph 		goto out;
775e6cbbe42SPatrick Rudolph 
776e6cbbe42SPatrick Rudolph 	switch (param) {
777e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_UP:
778e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
779e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PU;
780e6cbbe42SPatrick Rudolph 		break;
781e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_PULL_DOWN:
782e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
783e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PD;
784e6cbbe42SPatrick Rudolph 		break;
785e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_BIAS_DISABLE:
786e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
787e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_HIZ;
788e6cbbe42SPatrick Rudolph 		break;
789e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
790e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
791e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODL;
792e6cbbe42SPatrick Rudolph 		break;
793e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_OPEN_SOURCE:
794e6cbbe42SPatrick Rudolph 		clear_bit(off, chip->push_pull);
795e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_ODH;
796e6cbbe42SPatrick Rudolph 		break;
797e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_DRIVE_PUSH_PULL:
798e6cbbe42SPatrick Rudolph 		set_bit(off, chip->push_pull);
799e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_DRV_PP_FAST;
800e6cbbe42SPatrick Rudolph 		break;
801e6cbbe42SPatrick Rudolph 	case PIN_CONFIG_MODE_PWM:
802e6cbbe42SPatrick Rudolph 		reg = CY8C95X0_PWMSEL;
803e6cbbe42SPatrick Rudolph 		break;
804e6cbbe42SPatrick Rudolph 	default:
805e6cbbe42SPatrick Rudolph 		ret = -ENOTSUPP;
806e6cbbe42SPatrick Rudolph 		goto out;
807e6cbbe42SPatrick Rudolph 	}
808*63e23304SAndy Shevchenko 	/*
809*63e23304SAndy Shevchenko 	 * Writing 1 to one of the drive mode registers will automatically
810e6cbbe42SPatrick Rudolph 	 * clear conflicting set bits in the other drive mode registers.
811e6cbbe42SPatrick Rudolph 	 */
812e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, reg, bit, bit);
813e6cbbe42SPatrick Rudolph 
814e6cbbe42SPatrick Rudolph out:
815e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->i2c_lock);
816e6cbbe42SPatrick Rudolph 	return ret;
817e6cbbe42SPatrick Rudolph }
818e6cbbe42SPatrick Rudolph 
819e6cbbe42SPatrick Rudolph static int cy8c95x0_gpio_get_multiple(struct gpio_chip *gc,
820e6cbbe42SPatrick Rudolph 				      unsigned long *mask, unsigned long *bits)
821e6cbbe42SPatrick Rudolph {
822e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
823e6cbbe42SPatrick Rudolph 
824e6cbbe42SPatrick Rudolph 	return cy8c95x0_read_regs_mask(chip, CY8C95X0_INPUT, bits, mask);
825e6cbbe42SPatrick Rudolph }
826e6cbbe42SPatrick Rudolph 
827e6cbbe42SPatrick Rudolph static void cy8c95x0_gpio_set_multiple(struct gpio_chip *gc,
828e6cbbe42SPatrick Rudolph 				       unsigned long *mask, unsigned long *bits)
829e6cbbe42SPatrick Rudolph {
830e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
831e6cbbe42SPatrick Rudolph 
832e6cbbe42SPatrick Rudolph 	cy8c95x0_write_regs_mask(chip, CY8C95X0_OUTPUT, bits, mask);
833e6cbbe42SPatrick Rudolph }
834e6cbbe42SPatrick Rudolph 
835d86e0344SAndy Shevchenko static int cy8c95x0_add_pin_ranges(struct gpio_chip *gc)
836d86e0344SAndy Shevchenko {
837d86e0344SAndy Shevchenko 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
838d86e0344SAndy Shevchenko 	struct device *dev = chip->dev;
839d86e0344SAndy Shevchenko 	int ret;
840d86e0344SAndy Shevchenko 
841d86e0344SAndy Shevchenko 	ret = gpiochip_add_pin_range(gc, dev_name(dev), 0, 0, chip->tpin);
842d86e0344SAndy Shevchenko 	if (ret)
843d86e0344SAndy Shevchenko 		dev_err(dev, "failed to add GPIO pin range\n");
844d86e0344SAndy Shevchenko 
845d86e0344SAndy Shevchenko 	return ret;
846d86e0344SAndy Shevchenko }
847d86e0344SAndy Shevchenko 
848d86e0344SAndy Shevchenko static int cy8c95x0_setup_gpiochip(struct cy8c95x0_pinctrl *chip)
849e6cbbe42SPatrick Rudolph {
850e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = &chip->gpio_chip;
851e6cbbe42SPatrick Rudolph 
852e6cbbe42SPatrick Rudolph 	gc->direction_input  = cy8c95x0_gpio_direction_input;
853e6cbbe42SPatrick Rudolph 	gc->direction_output = cy8c95x0_gpio_direction_output;
854e6cbbe42SPatrick Rudolph 	gc->get = cy8c95x0_gpio_get_value;
855e6cbbe42SPatrick Rudolph 	gc->set = cy8c95x0_gpio_set_value;
856e6cbbe42SPatrick Rudolph 	gc->get_direction = cy8c95x0_gpio_get_direction;
857e6cbbe42SPatrick Rudolph 	gc->get_multiple = cy8c95x0_gpio_get_multiple;
858e6cbbe42SPatrick Rudolph 	gc->set_multiple = cy8c95x0_gpio_set_multiple;
8591fa3df90SAndy Shevchenko 	gc->set_config = gpiochip_generic_config,
860e6cbbe42SPatrick Rudolph 	gc->can_sleep = true;
861d86e0344SAndy Shevchenko 	gc->add_pin_ranges = cy8c95x0_add_pin_ranges;
862e6cbbe42SPatrick Rudolph 
863e6cbbe42SPatrick Rudolph 	gc->base = -1;
864d86e0344SAndy Shevchenko 	gc->ngpio = chip->tpin;
865e6cbbe42SPatrick Rudolph 
866e6cbbe42SPatrick Rudolph 	gc->parent = chip->dev;
867e6cbbe42SPatrick Rudolph 	gc->owner = THIS_MODULE;
868e6cbbe42SPatrick Rudolph 	gc->names = NULL;
869e6cbbe42SPatrick Rudolph 
870e6cbbe42SPatrick Rudolph 	gc->label = dev_name(chip->dev);
871e6cbbe42SPatrick Rudolph 
872e6cbbe42SPatrick Rudolph 	return devm_gpiochip_add_data(chip->dev, gc, chip);
873e6cbbe42SPatrick Rudolph }
874e6cbbe42SPatrick Rudolph 
875e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_mask(struct irq_data *d)
876e6cbbe42SPatrick Rudolph {
877e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
878e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
879f5d62025SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
880e6cbbe42SPatrick Rudolph 
881f5d62025SAndy Shevchenko 	set_bit(hwirq, chip->irq_mask);
882f5d62025SAndy Shevchenko 	gpiochip_disable_irq(gc, hwirq);
883e6cbbe42SPatrick Rudolph }
884e6cbbe42SPatrick Rudolph 
885e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_unmask(struct irq_data *d)
886e6cbbe42SPatrick Rudolph {
887e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
888e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
889f5d62025SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
890e6cbbe42SPatrick Rudolph 
891f5d62025SAndy Shevchenko 	gpiochip_enable_irq(gc, hwirq);
892f5d62025SAndy Shevchenko 	clear_bit(hwirq, chip->irq_mask);
893e6cbbe42SPatrick Rudolph }
894e6cbbe42SPatrick Rudolph 
895e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_bus_lock(struct irq_data *d)
896e6cbbe42SPatrick Rudolph {
897e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
898e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
899e6cbbe42SPatrick Rudolph 
900e6cbbe42SPatrick Rudolph 	mutex_lock(&chip->irq_lock);
901e6cbbe42SPatrick Rudolph }
902e6cbbe42SPatrick Rudolph 
903e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_bus_sync_unlock(struct irq_data *d)
904e6cbbe42SPatrick Rudolph {
905e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
906e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
907e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(ones, MAX_LINE);
908e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(irq_mask, MAX_LINE);
909e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(reg_direction, MAX_LINE);
910e6cbbe42SPatrick Rudolph 
911e6cbbe42SPatrick Rudolph 	bitmap_fill(ones, MAX_LINE);
912e6cbbe42SPatrick Rudolph 
913e6cbbe42SPatrick Rudolph 	cy8c95x0_write_regs_mask(chip, CY8C95X0_INTMASK, chip->irq_mask, ones);
914e6cbbe42SPatrick Rudolph 
915e6cbbe42SPatrick Rudolph 	/* Switch direction to input if needed */
916e6cbbe42SPatrick Rudolph 	cy8c95x0_read_regs_mask(chip, CY8C95X0_DIRECTION, reg_direction, chip->irq_mask);
917e6cbbe42SPatrick Rudolph 	bitmap_or(irq_mask, chip->irq_mask, reg_direction, MAX_LINE);
918e6cbbe42SPatrick Rudolph 	bitmap_complement(irq_mask, irq_mask, MAX_LINE);
919e6cbbe42SPatrick Rudolph 
920e6cbbe42SPatrick Rudolph 	/* Look for any newly setup interrupt */
921e6cbbe42SPatrick Rudolph 	cy8c95x0_write_regs_mask(chip, CY8C95X0_DIRECTION, ones, irq_mask);
922e6cbbe42SPatrick Rudolph 
923e6cbbe42SPatrick Rudolph 	mutex_unlock(&chip->irq_lock);
924e6cbbe42SPatrick Rudolph }
925e6cbbe42SPatrick Rudolph 
926e6cbbe42SPatrick Rudolph static int cy8c95x0_irq_set_type(struct irq_data *d, unsigned int type)
927e6cbbe42SPatrick Rudolph {
928e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
929e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
930e6cbbe42SPatrick Rudolph 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
931e6cbbe42SPatrick Rudolph 	unsigned int trig_type;
932e6cbbe42SPatrick Rudolph 
933e6cbbe42SPatrick Rudolph 	switch (type) {
934e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_EDGE_RISING:
935e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_EDGE_FALLING:
936e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_EDGE_BOTH:
937e6cbbe42SPatrick Rudolph 		trig_type = type;
938e6cbbe42SPatrick Rudolph 		break;
939e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_LEVEL_HIGH:
940e6cbbe42SPatrick Rudolph 		trig_type = IRQ_TYPE_EDGE_RISING;
941e6cbbe42SPatrick Rudolph 		break;
942e6cbbe42SPatrick Rudolph 	case IRQ_TYPE_LEVEL_LOW:
943e6cbbe42SPatrick Rudolph 		trig_type = IRQ_TYPE_EDGE_FALLING;
944e6cbbe42SPatrick Rudolph 		break;
945e6cbbe42SPatrick Rudolph 	default:
946e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "irq %d: unsupported type %d\n", d->irq, type);
947e6cbbe42SPatrick Rudolph 		return -EINVAL;
948e6cbbe42SPatrick Rudolph 	}
949e6cbbe42SPatrick Rudolph 
950e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_fall, trig_type & IRQ_TYPE_EDGE_FALLING);
951e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_raise, trig_type & IRQ_TYPE_EDGE_RISING);
952e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_low, type == IRQ_TYPE_LEVEL_LOW);
953e6cbbe42SPatrick Rudolph 	assign_bit(hwirq, chip->irq_trig_high, type == IRQ_TYPE_LEVEL_HIGH);
954e6cbbe42SPatrick Rudolph 
955e6cbbe42SPatrick Rudolph 	return 0;
956e6cbbe42SPatrick Rudolph }
957e6cbbe42SPatrick Rudolph 
958e6cbbe42SPatrick Rudolph static void cy8c95x0_irq_shutdown(struct irq_data *d)
959e6cbbe42SPatrick Rudolph {
960e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
961e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
962e6cbbe42SPatrick Rudolph 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
963e6cbbe42SPatrick Rudolph 
964e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_raise);
965e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_fall);
966e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_low);
967e6cbbe42SPatrick Rudolph 	clear_bit(hwirq, chip->irq_trig_high);
968e6cbbe42SPatrick Rudolph }
969e6cbbe42SPatrick Rudolph 
970f5d62025SAndy Shevchenko static const struct irq_chip cy8c95x0_irqchip = {
971f5d62025SAndy Shevchenko 	.name = "cy8c95x0-irq",
972f5d62025SAndy Shevchenko 	.irq_mask = cy8c95x0_irq_mask,
973f5d62025SAndy Shevchenko 	.irq_unmask = cy8c95x0_irq_unmask,
974f5d62025SAndy Shevchenko 	.irq_bus_lock = cy8c95x0_irq_bus_lock,
975f5d62025SAndy Shevchenko 	.irq_bus_sync_unlock = cy8c95x0_irq_bus_sync_unlock,
976f5d62025SAndy Shevchenko 	.irq_set_type = cy8c95x0_irq_set_type,
977f5d62025SAndy Shevchenko 	.irq_shutdown = cy8c95x0_irq_shutdown,
978f5d62025SAndy Shevchenko 	.flags = IRQCHIP_IMMUTABLE,
979f5d62025SAndy Shevchenko 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
980f5d62025SAndy Shevchenko };
981f5d62025SAndy Shevchenko 
982e6cbbe42SPatrick Rudolph static bool cy8c95x0_irq_pending(struct cy8c95x0_pinctrl *chip, unsigned long *pending)
983e6cbbe42SPatrick Rudolph {
984e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(ones, MAX_LINE);
985e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(cur_stat, MAX_LINE);
986e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(new_stat, MAX_LINE);
987e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(trigger, MAX_LINE);
988e6cbbe42SPatrick Rudolph 
989e6cbbe42SPatrick Rudolph 	bitmap_fill(ones, MAX_LINE);
990e6cbbe42SPatrick Rudolph 
991e6cbbe42SPatrick Rudolph 	/* Read the current interrupt status from the device */
992e6cbbe42SPatrick Rudolph 	if (cy8c95x0_read_regs_mask(chip, CY8C95X0_INTSTATUS, trigger, ones))
993e6cbbe42SPatrick Rudolph 		return false;
994e6cbbe42SPatrick Rudolph 
995e6cbbe42SPatrick Rudolph 	/* Check latched inputs */
996e6cbbe42SPatrick Rudolph 	if (cy8c95x0_read_regs_mask(chip, CY8C95X0_INPUT, cur_stat, trigger))
997e6cbbe42SPatrick Rudolph 		return false;
998e6cbbe42SPatrick Rudolph 
999e6cbbe42SPatrick Rudolph 	/* Apply filter for rising/falling edge selection */
1000e6cbbe42SPatrick Rudolph 	bitmap_replace(new_stat, chip->irq_trig_fall, chip->irq_trig_raise,
1001e6cbbe42SPatrick Rudolph 		       cur_stat, MAX_LINE);
1002e6cbbe42SPatrick Rudolph 
1003e6cbbe42SPatrick Rudolph 	bitmap_and(pending, new_stat, trigger, MAX_LINE);
1004e6cbbe42SPatrick Rudolph 
1005e6cbbe42SPatrick Rudolph 	return !bitmap_empty(pending, MAX_LINE);
1006e6cbbe42SPatrick Rudolph }
1007e6cbbe42SPatrick Rudolph 
1008e6cbbe42SPatrick Rudolph static irqreturn_t cy8c95x0_irq_handler(int irq, void *devid)
1009e6cbbe42SPatrick Rudolph {
1010e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = devid;
1011e6cbbe42SPatrick Rudolph 	struct gpio_chip *gc = &chip->gpio_chip;
1012e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(pending, MAX_LINE);
1013e6cbbe42SPatrick Rudolph 	int nested_irq, level;
1014e6cbbe42SPatrick Rudolph 	bool ret;
1015e6cbbe42SPatrick Rudolph 
1016e6cbbe42SPatrick Rudolph 	ret = cy8c95x0_irq_pending(chip, pending);
1017e6cbbe42SPatrick Rudolph 	if (!ret)
1018e6cbbe42SPatrick Rudolph 		return IRQ_RETVAL(0);
1019e6cbbe42SPatrick Rudolph 
1020e6cbbe42SPatrick Rudolph 	ret = 0;
1021e6cbbe42SPatrick Rudolph 	for_each_set_bit(level, pending, MAX_LINE) {
1022e6cbbe42SPatrick Rudolph 		/* Already accounted for 4bit gap in GPort2 */
1023e6cbbe42SPatrick Rudolph 		nested_irq = irq_find_mapping(gc->irq.domain, level);
1024e6cbbe42SPatrick Rudolph 
1025e6cbbe42SPatrick Rudolph 		if (unlikely(nested_irq <= 0)) {
1026e6cbbe42SPatrick Rudolph 			dev_warn_ratelimited(gc->parent, "unmapped interrupt %d\n", level);
1027e6cbbe42SPatrick Rudolph 			continue;
1028e6cbbe42SPatrick Rudolph 		}
1029e6cbbe42SPatrick Rudolph 
1030e6cbbe42SPatrick Rudolph 		if (test_bit(level, chip->irq_trig_low))
1031e6cbbe42SPatrick Rudolph 			while (!cy8c95x0_gpio_get_value(gc, level))
1032e6cbbe42SPatrick Rudolph 				handle_nested_irq(nested_irq);
1033e6cbbe42SPatrick Rudolph 		else if (test_bit(level, chip->irq_trig_high))
1034e6cbbe42SPatrick Rudolph 			while (cy8c95x0_gpio_get_value(gc, level))
1035e6cbbe42SPatrick Rudolph 				handle_nested_irq(nested_irq);
1036e6cbbe42SPatrick Rudolph 		else
1037e6cbbe42SPatrick Rudolph 			handle_nested_irq(nested_irq);
1038e6cbbe42SPatrick Rudolph 
1039e6cbbe42SPatrick Rudolph 		ret = 1;
1040e6cbbe42SPatrick Rudolph 	}
1041e6cbbe42SPatrick Rudolph 
1042e6cbbe42SPatrick Rudolph 	return IRQ_RETVAL(ret);
1043e6cbbe42SPatrick Rudolph }
1044e6cbbe42SPatrick Rudolph 
1045e6cbbe42SPatrick Rudolph static int cy8c95x0_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
1046e6cbbe42SPatrick Rudolph {
1047e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1048e6cbbe42SPatrick Rudolph 
1049e6cbbe42SPatrick Rudolph 	return chip->tpin;
1050e6cbbe42SPatrick Rudolph }
1051e6cbbe42SPatrick Rudolph 
1052e6cbbe42SPatrick Rudolph static const char *cy8c95x0_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
1053e6cbbe42SPatrick Rudolph 						   unsigned int group)
1054e6cbbe42SPatrick Rudolph {
1055e6cbbe42SPatrick Rudolph 	return cy8c95x0_groups[group];
1056e6cbbe42SPatrick Rudolph }
1057e6cbbe42SPatrick Rudolph 
1058e6cbbe42SPatrick Rudolph static int cy8c95x0_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
1059e6cbbe42SPatrick Rudolph 					   unsigned int group,
1060e6cbbe42SPatrick Rudolph 					   const unsigned int **pins,
1061e6cbbe42SPatrick Rudolph 					   unsigned int *num_pins)
1062e6cbbe42SPatrick Rudolph {
1063e6cbbe42SPatrick Rudolph 	*pins = &cy8c9560_pins[group].number;
1064e6cbbe42SPatrick Rudolph 	*num_pins = 1;
1065e6cbbe42SPatrick Rudolph 	return 0;
1066e6cbbe42SPatrick Rudolph }
1067e6cbbe42SPatrick Rudolph 
1068f12352f3SAndy Shevchenko static const char *cy8c95x0_get_fname(unsigned int selector)
1069f12352f3SAndy Shevchenko {
1070f12352f3SAndy Shevchenko 	if (selector == 0)
1071f12352f3SAndy Shevchenko 		return "gpio";
1072f12352f3SAndy Shevchenko 	else
1073f12352f3SAndy Shevchenko 		return "pwm";
1074f12352f3SAndy Shevchenko }
1075f12352f3SAndy Shevchenko 
1076f12352f3SAndy Shevchenko static void cy8c95x0_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
1077f12352f3SAndy Shevchenko 				  unsigned int pin)
1078f12352f3SAndy Shevchenko {
1079f12352f3SAndy Shevchenko 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1080f12352f3SAndy Shevchenko 	DECLARE_BITMAP(mask, MAX_LINE);
1081f12352f3SAndy Shevchenko 	DECLARE_BITMAP(pwm, MAX_LINE);
1082f12352f3SAndy Shevchenko 
1083f12352f3SAndy Shevchenko 	bitmap_zero(mask, MAX_LINE);
1084f12352f3SAndy Shevchenko 	__set_bit(pin, mask);
1085f12352f3SAndy Shevchenko 
1086f12352f3SAndy Shevchenko 	if (cy8c95x0_read_regs_mask(chip, CY8C95X0_PWMSEL, pwm, mask)) {
1087f12352f3SAndy Shevchenko 		seq_puts(s, "not available");
1088f12352f3SAndy Shevchenko 		return;
1089f12352f3SAndy Shevchenko 	}
1090f12352f3SAndy Shevchenko 
1091f12352f3SAndy Shevchenko 	seq_printf(s, "MODE:%s", cy8c95x0_get_fname(test_bit(pin, pwm)));
1092f12352f3SAndy Shevchenko }
1093f12352f3SAndy Shevchenko 
1094e6cbbe42SPatrick Rudolph static const struct pinctrl_ops cy8c95x0_pinctrl_ops = {
1095e6cbbe42SPatrick Rudolph 	.get_groups_count = cy8c95x0_pinctrl_get_groups_count,
1096e6cbbe42SPatrick Rudolph 	.get_group_name = cy8c95x0_pinctrl_get_group_name,
1097e6cbbe42SPatrick Rudolph 	.get_group_pins = cy8c95x0_pinctrl_get_group_pins,
10988586466eSAndy Shevchenko #ifdef CONFIG_OF
1099e6cbbe42SPatrick Rudolph 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
1100e6cbbe42SPatrick Rudolph 	.dt_free_map = pinconf_generic_dt_free_map,
11018586466eSAndy Shevchenko #endif
1102f12352f3SAndy Shevchenko 	.pin_dbg_show = cy8c95x0_pin_dbg_show,
1103e6cbbe42SPatrick Rudolph };
1104e6cbbe42SPatrick Rudolph 
1105f12352f3SAndy Shevchenko static const char *cy8c95x0_get_functions_name(struct pinctrl_dev *pctldev, unsigned int selector)
1106f12352f3SAndy Shevchenko {
1107f12352f3SAndy Shevchenko 	return cy8c95x0_get_fname(selector);
1108f12352f3SAndy Shevchenko }
1109f12352f3SAndy Shevchenko 
1110e6cbbe42SPatrick Rudolph static int cy8c95x0_get_functions_count(struct pinctrl_dev *pctldev)
1111e6cbbe42SPatrick Rudolph {
1112e6cbbe42SPatrick Rudolph 	return 2;
1113e6cbbe42SPatrick Rudolph }
1114e6cbbe42SPatrick Rudolph 
1115e6cbbe42SPatrick Rudolph static int cy8c95x0_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
1116e6cbbe42SPatrick Rudolph 			       const char * const **groups,
1117e6cbbe42SPatrick Rudolph 			       unsigned int * const num_groups)
1118e6cbbe42SPatrick Rudolph {
1119e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1120e6cbbe42SPatrick Rudolph 
1121e6cbbe42SPatrick Rudolph 	*groups = cy8c95x0_groups;
1122e6cbbe42SPatrick Rudolph 	*num_groups = chip->tpin;
1123e6cbbe42SPatrick Rudolph 	return 0;
1124e6cbbe42SPatrick Rudolph }
1125e6cbbe42SPatrick Rudolph 
1126e6cbbe42SPatrick Rudolph static int cy8c95x0_pinmux_cfg(struct cy8c95x0_pinctrl *chip,
1127e6cbbe42SPatrick Rudolph 			       unsigned int val,
1128e6cbbe42SPatrick Rudolph 			       unsigned long off)
1129e6cbbe42SPatrick Rudolph {
1130e6cbbe42SPatrick Rudolph 	u8 port = cypress_get_port(chip, off);
1131e6cbbe42SPatrick Rudolph 	u8 bit = cypress_get_pin_mask(chip, off);
1132e6cbbe42SPatrick Rudolph 	int ret;
1133e6cbbe42SPatrick Rudolph 
1134*63e23304SAndy Shevchenko 	/* Select port */
1135e6cbbe42SPatrick Rudolph 	ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
1136e6cbbe42SPatrick Rudolph 	if (ret < 0)
1137e6cbbe42SPatrick Rudolph 		return ret;
1138e6cbbe42SPatrick Rudolph 
1139e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, CY8C95X0_PWMSEL, bit, val ? bit : 0);
1140e6cbbe42SPatrick Rudolph 	if (ret < 0)
1141e6cbbe42SPatrick Rudolph 		return ret;
1142e6cbbe42SPatrick Rudolph 
1143e6cbbe42SPatrick Rudolph 	/* Set direction to output & set output to 1 so that PWM can work */
1144e6cbbe42SPatrick Rudolph 	ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, bit);
1145e6cbbe42SPatrick Rudolph 	if (ret < 0)
1146e6cbbe42SPatrick Rudolph 		return ret;
1147e6cbbe42SPatrick Rudolph 
1148e6cbbe42SPatrick Rudolph 	return regmap_write_bits(chip->regmap, CY8C95X0_OUTPUT_(port), bit, bit);
1149e6cbbe42SPatrick Rudolph }
1150e6cbbe42SPatrick Rudolph 
1151e6cbbe42SPatrick Rudolph static int cy8c95x0_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
1152e6cbbe42SPatrick Rudolph 			    unsigned int group)
1153e6cbbe42SPatrick Rudolph {
1154e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1155e6cbbe42SPatrick Rudolph 
1156e6cbbe42SPatrick Rudolph 	return cy8c95x0_pinmux_cfg(chip, selector, group);
1157e6cbbe42SPatrick Rudolph }
1158e6cbbe42SPatrick Rudolph 
1159e6cbbe42SPatrick Rudolph static const struct pinmux_ops cy8c95x0_pmxops = {
1160e6cbbe42SPatrick Rudolph 	.get_functions_count = cy8c95x0_get_functions_count,
1161f12352f3SAndy Shevchenko 	.get_function_name = cy8c95x0_get_functions_name,
1162e6cbbe42SPatrick Rudolph 	.get_function_groups = cy8c95x0_get_groups,
1163e6cbbe42SPatrick Rudolph 	.set_mux = cy8c95x0_set_mux,
1164e6cbbe42SPatrick Rudolph 	.strict = true,
1165e6cbbe42SPatrick Rudolph };
1166e6cbbe42SPatrick Rudolph 
1167e6cbbe42SPatrick Rudolph static int cy8c95x0_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
1168e6cbbe42SPatrick Rudolph 				unsigned long *config)
1169e6cbbe42SPatrick Rudolph {
1170e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1171e6cbbe42SPatrick Rudolph 
1172e6cbbe42SPatrick Rudolph 	return cy8c95x0_gpio_get_pincfg(chip, pin, config);
1173e6cbbe42SPatrick Rudolph }
1174e6cbbe42SPatrick Rudolph 
1175e6cbbe42SPatrick Rudolph static int cy8c95x0_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
1176e6cbbe42SPatrick Rudolph 				unsigned long *configs, unsigned int num_configs)
1177e6cbbe42SPatrick Rudolph {
1178e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
1179e6cbbe42SPatrick Rudolph 	int ret = 0;
1180e6cbbe42SPatrick Rudolph 	int i;
1181e6cbbe42SPatrick Rudolph 
1182e6cbbe42SPatrick Rudolph 	for (i = 0; i < num_configs; i++) {
1183e6cbbe42SPatrick Rudolph 		ret = cy8c95x0_gpio_set_pincfg(chip, pin, configs[i]);
1184e6cbbe42SPatrick Rudolph 		if (ret)
1185e6cbbe42SPatrick Rudolph 			return ret;
1186e6cbbe42SPatrick Rudolph 	}
1187e6cbbe42SPatrick Rudolph 
1188e6cbbe42SPatrick Rudolph 	return ret;
1189e6cbbe42SPatrick Rudolph }
1190e6cbbe42SPatrick Rudolph 
1191e6cbbe42SPatrick Rudolph static const struct pinconf_ops cy8c95x0_pinconf_ops = {
1192e6cbbe42SPatrick Rudolph 	.pin_config_get = cy8c95x0_pinconf_get,
1193e6cbbe42SPatrick Rudolph 	.pin_config_set = cy8c95x0_pinconf_set,
1194e6cbbe42SPatrick Rudolph 	.is_generic = true,
1195e6cbbe42SPatrick Rudolph };
1196e6cbbe42SPatrick Rudolph 
1197e6cbbe42SPatrick Rudolph static int cy8c95x0_irq_setup(struct cy8c95x0_pinctrl *chip, int irq)
1198e6cbbe42SPatrick Rudolph {
1199e6cbbe42SPatrick Rudolph 	struct gpio_irq_chip *girq = &chip->gpio_chip.irq;
1200e6cbbe42SPatrick Rudolph 	DECLARE_BITMAP(pending_irqs, MAX_LINE);
1201e6cbbe42SPatrick Rudolph 	int ret;
1202e6cbbe42SPatrick Rudolph 
1203e6cbbe42SPatrick Rudolph 	mutex_init(&chip->irq_lock);
1204e6cbbe42SPatrick Rudolph 
1205e6cbbe42SPatrick Rudolph 	bitmap_zero(pending_irqs, MAX_LINE);
1206e6cbbe42SPatrick Rudolph 
1207e6cbbe42SPatrick Rudolph 	/* Read IRQ status register to clear all pending interrupts */
1208e6cbbe42SPatrick Rudolph 	ret = cy8c95x0_irq_pending(chip, pending_irqs);
1209e6cbbe42SPatrick Rudolph 	if (ret) {
1210e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "failed to clear irq status register\n");
1211e6cbbe42SPatrick Rudolph 		return ret;
1212e6cbbe42SPatrick Rudolph 	}
1213e6cbbe42SPatrick Rudolph 
1214e6cbbe42SPatrick Rudolph 	/* Mask all interrupts */
1215e6cbbe42SPatrick Rudolph 	bitmap_fill(chip->irq_mask, MAX_LINE);
1216e6cbbe42SPatrick Rudolph 
1217f5d62025SAndy Shevchenko 	gpio_irq_chip_set_chip(girq, &cy8c95x0_irqchip);
1218e6cbbe42SPatrick Rudolph 
1219e6cbbe42SPatrick Rudolph 	/* This will let us handle the parent IRQ in the driver */
1220e6cbbe42SPatrick Rudolph 	girq->parent_handler = NULL;
1221e6cbbe42SPatrick Rudolph 	girq->num_parents = 0;
1222e6cbbe42SPatrick Rudolph 	girq->parents = NULL;
1223e6cbbe42SPatrick Rudolph 	girq->default_type = IRQ_TYPE_NONE;
1224e6cbbe42SPatrick Rudolph 	girq->handler = handle_simple_irq;
1225e6cbbe42SPatrick Rudolph 	girq->threaded = true;
1226e6cbbe42SPatrick Rudolph 
1227e6cbbe42SPatrick Rudolph 	ret = devm_request_threaded_irq(chip->dev, irq,
1228e6cbbe42SPatrick Rudolph 					NULL, cy8c95x0_irq_handler,
1229e6cbbe42SPatrick Rudolph 					IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_HIGH,
1230e6cbbe42SPatrick Rudolph 					dev_name(chip->dev), chip);
1231e6cbbe42SPatrick Rudolph 	if (ret) {
1232e6cbbe42SPatrick Rudolph 		dev_err(chip->dev, "failed to request irq %d\n", irq);
1233e6cbbe42SPatrick Rudolph 		return ret;
1234e6cbbe42SPatrick Rudolph 	}
1235e6cbbe42SPatrick Rudolph 	dev_info(chip->dev, "Registered threaded IRQ\n");
1236e6cbbe42SPatrick Rudolph 
1237e6cbbe42SPatrick Rudolph 	return 0;
1238e6cbbe42SPatrick Rudolph }
1239e6cbbe42SPatrick Rudolph 
1240e6cbbe42SPatrick Rudolph static int cy8c95x0_setup_pinctrl(struct cy8c95x0_pinctrl *chip)
1241e6cbbe42SPatrick Rudolph {
1242e6cbbe42SPatrick Rudolph 	struct pinctrl_desc *pd = &chip->pinctrl_desc;
1243e6cbbe42SPatrick Rudolph 
1244e6cbbe42SPatrick Rudolph 	pd->pctlops = &cy8c95x0_pinctrl_ops;
1245e6cbbe42SPatrick Rudolph 	pd->confops = &cy8c95x0_pinconf_ops;
1246e6cbbe42SPatrick Rudolph 	pd->pmxops = &cy8c95x0_pmxops;
1247641d6cc6SAndy Shevchenko 	pd->name = dev_name(chip->dev);
1248e6cbbe42SPatrick Rudolph 	pd->pins = cy8c9560_pins;
1249e6cbbe42SPatrick Rudolph 	pd->npins = chip->tpin;
1250e6cbbe42SPatrick Rudolph 	pd->owner = THIS_MODULE;
1251e6cbbe42SPatrick Rudolph 
1252*63e23304SAndy Shevchenko 	chip->pctldev = devm_pinctrl_register(chip->dev, pd, chip);
1253e6cbbe42SPatrick Rudolph 	if (IS_ERR(chip->pctldev))
1254e6cbbe42SPatrick Rudolph 		return dev_err_probe(chip->dev, PTR_ERR(chip->pctldev),
1255e6cbbe42SPatrick Rudolph 			"can't register controller\n");
1256*63e23304SAndy Shevchenko 
1257e6cbbe42SPatrick Rudolph 	return 0;
1258e6cbbe42SPatrick Rudolph }
1259e6cbbe42SPatrick Rudolph 
1260e6cbbe42SPatrick Rudolph static int cy8c95x0_detect(struct i2c_client *client,
1261e6cbbe42SPatrick Rudolph 			   struct i2c_board_info *info)
1262e6cbbe42SPatrick Rudolph {
1263e6cbbe42SPatrick Rudolph 	struct i2c_adapter *adapter = client->adapter;
1264e6cbbe42SPatrick Rudolph 	int ret;
1265e6cbbe42SPatrick Rudolph 	const char *name;
1266e6cbbe42SPatrick Rudolph 
1267e6cbbe42SPatrick Rudolph 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1268e6cbbe42SPatrick Rudolph 		return -ENODEV;
1269e6cbbe42SPatrick Rudolph 
1270e6cbbe42SPatrick Rudolph 	ret = i2c_smbus_read_byte_data(client, CY8C95X0_DEVID);
1271e6cbbe42SPatrick Rudolph 	if (ret < 0)
1272e6cbbe42SPatrick Rudolph 		return ret;
12739540a836SAndy Shevchenko 	switch (ret & GENMASK(7, 4)) {
1274e6cbbe42SPatrick Rudolph 	case 0x20:
1275e6cbbe42SPatrick Rudolph 		name = cy8c95x0_id[0].name;
1276e6cbbe42SPatrick Rudolph 		break;
1277e6cbbe42SPatrick Rudolph 	case 0x40:
1278e6cbbe42SPatrick Rudolph 		name = cy8c95x0_id[1].name;
1279e6cbbe42SPatrick Rudolph 		break;
1280e6cbbe42SPatrick Rudolph 	case 0x60:
1281e6cbbe42SPatrick Rudolph 		name = cy8c95x0_id[2].name;
1282e6cbbe42SPatrick Rudolph 		break;
1283e6cbbe42SPatrick Rudolph 	default:
1284e6cbbe42SPatrick Rudolph 		return -ENODEV;
1285e6cbbe42SPatrick Rudolph 	}
1286e6cbbe42SPatrick Rudolph 
1287e6cbbe42SPatrick Rudolph 	dev_info(&client->dev, "Found a %s chip at 0x%02x.\n", name, client->addr);
1288e6cbbe42SPatrick Rudolph 	strscpy(info->type, name, I2C_NAME_SIZE);
1289e6cbbe42SPatrick Rudolph 
129043dcf873SAndy Shevchenko 	return 0;
1291e6cbbe42SPatrick Rudolph }
1292e6cbbe42SPatrick Rudolph 
1293e6cbbe42SPatrick Rudolph static int cy8c95x0_probe(struct i2c_client *client)
1294e6cbbe42SPatrick Rudolph {
1295e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip;
1296e6cbbe42SPatrick Rudolph 	struct regulator *reg;
1297e6cbbe42SPatrick Rudolph 	int ret;
1298e6cbbe42SPatrick Rudolph 
1299e6cbbe42SPatrick Rudolph 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
1300e6cbbe42SPatrick Rudolph 	if (!chip)
1301e6cbbe42SPatrick Rudolph 		return -ENOMEM;
1302e6cbbe42SPatrick Rudolph 
1303e6cbbe42SPatrick Rudolph 	chip->dev = &client->dev;
1304e6cbbe42SPatrick Rudolph 
1305e6cbbe42SPatrick Rudolph 	/* Set the device type */
13068586466eSAndy Shevchenko 	chip->driver_data = (unsigned long)device_get_match_data(&client->dev);
13078586466eSAndy Shevchenko 	if (!chip->driver_data)
1308e6cbbe42SPatrick Rudolph 		chip->driver_data = i2c_match_id(cy8c95x0_id, client)->driver_data;
1309e6cbbe42SPatrick Rudolph 	if (!chip->driver_data)
1310e6cbbe42SPatrick Rudolph 		return -ENODEV;
1311e6cbbe42SPatrick Rudolph 
1312e6cbbe42SPatrick Rudolph 	i2c_set_clientdata(client, chip);
1313e6cbbe42SPatrick Rudolph 
1314e6cbbe42SPatrick Rudolph 	chip->tpin = chip->driver_data & CY8C95X0_GPIO_MASK;
1315e6cbbe42SPatrick Rudolph 	chip->nport = DIV_ROUND_UP(CY8C95X0_PIN_TO_OFFSET(chip->tpin), BANK_SZ);
1316e6cbbe42SPatrick Rudolph 
1317e6cbbe42SPatrick Rudolph 	switch (chip->tpin) {
1318e6cbbe42SPatrick Rudolph 	case 20:
1319e6cbbe42SPatrick Rudolph 		strscpy(chip->name, cy8c95x0_id[0].name, I2C_NAME_SIZE);
1320e6cbbe42SPatrick Rudolph 		break;
1321e6cbbe42SPatrick Rudolph 	case 40:
1322e6cbbe42SPatrick Rudolph 		strscpy(chip->name, cy8c95x0_id[1].name, I2C_NAME_SIZE);
1323e6cbbe42SPatrick Rudolph 		break;
1324e6cbbe42SPatrick Rudolph 	case 60:
1325e6cbbe42SPatrick Rudolph 		strscpy(chip->name, cy8c95x0_id[2].name, I2C_NAME_SIZE);
1326e6cbbe42SPatrick Rudolph 		break;
1327c3e40952SAndy Shevchenko 	default:
1328c3e40952SAndy Shevchenko 		return -ENODEV;
1329e6cbbe42SPatrick Rudolph 	}
1330e6cbbe42SPatrick Rudolph 
1331e6cbbe42SPatrick Rudolph 	reg = devm_regulator_get(&client->dev, "vdd");
1332e6cbbe42SPatrick Rudolph 	if (IS_ERR(reg)) {
1333e6cbbe42SPatrick Rudolph 		if (PTR_ERR(reg) == -EPROBE_DEFER)
1334e6cbbe42SPatrick Rudolph 			return -EPROBE_DEFER;
1335e6cbbe42SPatrick Rudolph 	} else {
1336e6cbbe42SPatrick Rudolph 		ret = regulator_enable(reg);
1337e6cbbe42SPatrick Rudolph 		if (ret) {
1338e6cbbe42SPatrick Rudolph 			dev_err(&client->dev, "failed to enable regulator vdd: %d\n", ret);
1339e6cbbe42SPatrick Rudolph 			return ret;
1340e6cbbe42SPatrick Rudolph 		}
1341e6cbbe42SPatrick Rudolph 		chip->regulator = reg;
1342e6cbbe42SPatrick Rudolph 	}
1343e6cbbe42SPatrick Rudolph 
1344e6cbbe42SPatrick Rudolph 	chip->regmap = devm_regmap_init_i2c(client, &cy8c95x0_i2c_regmap);
1345e6cbbe42SPatrick Rudolph 	if (IS_ERR(chip->regmap)) {
1346e6cbbe42SPatrick Rudolph 		ret = PTR_ERR(chip->regmap);
1347e6cbbe42SPatrick Rudolph 		goto err_exit;
1348e6cbbe42SPatrick Rudolph 	}
1349e6cbbe42SPatrick Rudolph 
1350e6cbbe42SPatrick Rudolph 	bitmap_zero(chip->push_pull, MAX_LINE);
1351e6cbbe42SPatrick Rudolph 	bitmap_zero(chip->shiftmask, MAX_LINE);
1352e6cbbe42SPatrick Rudolph 	bitmap_set(chip->shiftmask, 0, 20);
1353e6cbbe42SPatrick Rudolph 	mutex_init(&chip->i2c_lock);
1354e6cbbe42SPatrick Rudolph 
1355785b1bd8SAndy Shevchenko 	if (dmi_first_match(cy8c95x0_dmi_acpi_irq_info)) {
1356785b1bd8SAndy Shevchenko 		ret = cy8c95x0_acpi_get_irq(&client->dev);
1357785b1bd8SAndy Shevchenko 		if (ret > 0)
1358785b1bd8SAndy Shevchenko 			client->irq = ret;
1359785b1bd8SAndy Shevchenko 	}
1360785b1bd8SAndy Shevchenko 
1361e6cbbe42SPatrick Rudolph 	if (client->irq) {
1362e6cbbe42SPatrick Rudolph 		ret = cy8c95x0_irq_setup(chip, client->irq);
1363e6cbbe42SPatrick Rudolph 		if (ret)
1364e6cbbe42SPatrick Rudolph 			goto err_exit;
1365e6cbbe42SPatrick Rudolph 	}
1366e6cbbe42SPatrick Rudolph 
1367d86e0344SAndy Shevchenko 	ret = cy8c95x0_setup_pinctrl(chip);
1368e6cbbe42SPatrick Rudolph 	if (ret)
1369e6cbbe42SPatrick Rudolph 		goto err_exit;
1370e6cbbe42SPatrick Rudolph 
1371d86e0344SAndy Shevchenko 	ret = cy8c95x0_setup_gpiochip(chip);
1372e6cbbe42SPatrick Rudolph 	if (ret)
1373e6cbbe42SPatrick Rudolph 		goto err_exit;
1374e6cbbe42SPatrick Rudolph 
1375e6cbbe42SPatrick Rudolph 	return 0;
1376e6cbbe42SPatrick Rudolph 
1377e6cbbe42SPatrick Rudolph err_exit:
1378e6cbbe42SPatrick Rudolph 	if (!IS_ERR_OR_NULL(chip->regulator))
1379e6cbbe42SPatrick Rudolph 		regulator_disable(chip->regulator);
1380e6cbbe42SPatrick Rudolph 	return ret;
1381e6cbbe42SPatrick Rudolph }
1382e6cbbe42SPatrick Rudolph 
1383bbe2a5d8SStephen Rothwell static void cy8c95x0_remove(struct i2c_client *client)
1384e6cbbe42SPatrick Rudolph {
1385e6cbbe42SPatrick Rudolph 	struct cy8c95x0_pinctrl *chip = i2c_get_clientdata(client);
1386e6cbbe42SPatrick Rudolph 
1387e6cbbe42SPatrick Rudolph 	if (!IS_ERR_OR_NULL(chip->regulator))
1388e6cbbe42SPatrick Rudolph 		regulator_disable(chip->regulator);
1389e6cbbe42SPatrick Rudolph }
1390e6cbbe42SPatrick Rudolph 
1391618a43ffSAndy Shevchenko static const struct acpi_device_id cy8c95x0_acpi_ids[] = {
1392618a43ffSAndy Shevchenko 	{ "INT3490", 40, },
1393618a43ffSAndy Shevchenko 	{ }
1394618a43ffSAndy Shevchenko };
1395618a43ffSAndy Shevchenko MODULE_DEVICE_TABLE(acpi, cy8c95x0_acpi_ids);
1396618a43ffSAndy Shevchenko 
1397e6cbbe42SPatrick Rudolph static struct i2c_driver cy8c95x0_driver = {
1398e6cbbe42SPatrick Rudolph 	.driver = {
1399e6cbbe42SPatrick Rudolph 		.name	= "cy8c95x0-pinctrl",
1400e6cbbe42SPatrick Rudolph 		.of_match_table = cy8c95x0_dt_ids,
1401618a43ffSAndy Shevchenko 		.acpi_match_table = cy8c95x0_acpi_ids,
1402e6cbbe42SPatrick Rudolph 	},
1403e6cbbe42SPatrick Rudolph 	.probe_new	= cy8c95x0_probe,
1404e6cbbe42SPatrick Rudolph 	.remove		= cy8c95x0_remove,
1405e6cbbe42SPatrick Rudolph 	.id_table	= cy8c95x0_id,
1406e6cbbe42SPatrick Rudolph 	.detect		= cy8c95x0_detect,
1407e6cbbe42SPatrick Rudolph };
1408e6cbbe42SPatrick Rudolph module_i2c_driver(cy8c95x0_driver);
1409e6cbbe42SPatrick Rudolph 
1410e6cbbe42SPatrick Rudolph MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>");
1411e6cbbe42SPatrick Rudolph MODULE_AUTHOR("Naresh Solanki <naresh.solanki@9elements.com>");
1412e6cbbe42SPatrick Rudolph MODULE_DESCRIPTION("Pinctrl driver for CY8C95X0");
1413e6cbbe42SPatrick Rudolph MODULE_LICENSE("GPL");
1414