xref: /linux/drivers/gpio/gpio-rtd1625.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1*6435d21cSTzuyi Chang // SPDX-License-Identifier: GPL-2.0-or-later
2*6435d21cSTzuyi Chang /*
3*6435d21cSTzuyi Chang  * Realtek DHC RTD1625 gpio driver
4*6435d21cSTzuyi Chang  *
5*6435d21cSTzuyi Chang  * Copyright (c) 2023-2026 Realtek Semiconductor Corp.
6*6435d21cSTzuyi Chang  */
7*6435d21cSTzuyi Chang 
8*6435d21cSTzuyi Chang #include <linux/bitfield.h>
9*6435d21cSTzuyi Chang #include <linux/bitops.h>
10*6435d21cSTzuyi Chang #include <linux/cleanup.h>
11*6435d21cSTzuyi Chang #include <linux/gpio/driver.h>
12*6435d21cSTzuyi Chang #include <linux/gpio/regmap.h>
13*6435d21cSTzuyi Chang #include <linux/interrupt.h>
14*6435d21cSTzuyi Chang #include <linux/irqchip.h>
15*6435d21cSTzuyi Chang #include <linux/irqchip/chained_irq.h>
16*6435d21cSTzuyi Chang #include <linux/irqdomain.h>
17*6435d21cSTzuyi Chang #include <linux/module.h>
18*6435d21cSTzuyi Chang #include <linux/platform_device.h>
19*6435d21cSTzuyi Chang #include <linux/property.h>
20*6435d21cSTzuyi Chang #include <linux/regmap.h>
21*6435d21cSTzuyi Chang #include <linux/spinlock.h>
22*6435d21cSTzuyi Chang #include <linux/types.h>
23*6435d21cSTzuyi Chang 
24*6435d21cSTzuyi Chang #define RTD1625_GPIO_DIR BIT(0)
25*6435d21cSTzuyi Chang #define RTD1625_GPIO_OUT BIT(2)
26*6435d21cSTzuyi Chang #define RTD1625_GPIO_IN BIT(4)
27*6435d21cSTzuyi Chang #define RTD1625_GPIO_EDGE_INT_DP BIT(6)
28*6435d21cSTzuyi Chang #define RTD1625_GPIO_EDGE_INT_EN BIT(8)
29*6435d21cSTzuyi Chang #define RTD1625_GPIO_LEVEL_INT_EN BIT(16)
30*6435d21cSTzuyi Chang #define RTD1625_GPIO_LEVEL_INT_DP BIT(18)
31*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE GENMASK(30, 28)
32*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_WREN BIT(31)
33*6435d21cSTzuyi Chang 
34*6435d21cSTzuyi Chang #define RTD1625_GPIO_WREN(x) ((x) << 1)
35*6435d21cSTzuyi Chang 
36*6435d21cSTzuyi Chang /* Write-enable masks for all GPIO configs and reserved hardware bits */
37*6435d21cSTzuyi Chang #define RTD1625_ISO_GPIO_WREN_ALL 0x8000aa8a
38*6435d21cSTzuyi Chang #define RTD1625_ISOM_GPIO_WREN_ALL 0x800aaa8a
39*6435d21cSTzuyi Chang 
40*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_1US 0
41*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_10US 1
42*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_100US 2
43*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_1MS 3
44*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_10MS 4
45*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_20MS 5
46*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_30MS 6
47*6435d21cSTzuyi Chang #define RTD1625_GPIO_DEBOUNCE_50MS 7
48*6435d21cSTzuyi Chang 
49*6435d21cSTzuyi Chang #define GPIO_CONTROL(gpio) ((gpio) * 4)
50*6435d21cSTzuyi Chang 
51*6435d21cSTzuyi Chang static struct lock_class_key rtd1625_gpio_irq_lock_class;
52*6435d21cSTzuyi Chang static struct lock_class_key rtd1625_gpio_irq_request_class;
53*6435d21cSTzuyi Chang 
54*6435d21cSTzuyi Chang enum rtd1625_irq_index {
55*6435d21cSTzuyi Chang 	RTD1625_IRQ_ASSERT,
56*6435d21cSTzuyi Chang 	RTD1625_IRQ_DEASSERT,
57*6435d21cSTzuyi Chang 	RTD1625_IRQ_LEVEL,
58*6435d21cSTzuyi Chang 	RTD1625_MAX_IRQS
59*6435d21cSTzuyi Chang };
60*6435d21cSTzuyi Chang 
61*6435d21cSTzuyi Chang /**
62*6435d21cSTzuyi Chang  * struct rtd1625_gpio_info - Specific GPIO register information
63*6435d21cSTzuyi Chang  * @num_gpios: The number of GPIOs
64*6435d21cSTzuyi Chang  * @irq_type_support: Supported IRQ types
65*6435d21cSTzuyi Chang  * @base_offset: Offset for GPIO controller register
66*6435d21cSTzuyi Chang  * @gpa_offset: Offset for GPIO assert interrupt status register
67*6435d21cSTzuyi Chang  * @gpda_offset: Offset for GPIO deassert interrupt status register
68*6435d21cSTzuyi Chang  * @level_offset: Offset of level interrupt status register
69*6435d21cSTzuyi Chang  * @write_en_all: Write-enable mask for all configurable bits
70*6435d21cSTzuyi Chang  */
71*6435d21cSTzuyi Chang struct rtd1625_gpio_info {
72*6435d21cSTzuyi Chang 	unsigned int num_gpios;
73*6435d21cSTzuyi Chang 	unsigned int irq_type_support;
74*6435d21cSTzuyi Chang 	unsigned int base_offset;
75*6435d21cSTzuyi Chang 	unsigned int gpa_offset;
76*6435d21cSTzuyi Chang 	unsigned int gpda_offset;
77*6435d21cSTzuyi Chang 	unsigned int level_offset;
78*6435d21cSTzuyi Chang 	unsigned int write_en_all;
79*6435d21cSTzuyi Chang };
80*6435d21cSTzuyi Chang 
81*6435d21cSTzuyi Chang struct rtd1625_gpio {
82*6435d21cSTzuyi Chang 	struct gpio_regmap *gpio_reg;
83*6435d21cSTzuyi Chang 	const struct rtd1625_gpio_info *info;
84*6435d21cSTzuyi Chang 	struct regmap *regmap;
85*6435d21cSTzuyi Chang 	unsigned int irqs[RTD1625_MAX_IRQS];
86*6435d21cSTzuyi Chang 	raw_spinlock_t lock;
87*6435d21cSTzuyi Chang 	struct irq_domain *domain;
88*6435d21cSTzuyi Chang 	unsigned int *save_regs;
89*6435d21cSTzuyi Chang };
90*6435d21cSTzuyi Chang 
91*6435d21cSTzuyi Chang static unsigned int rtd1625_gpio_gpa_offset(struct rtd1625_gpio *data, unsigned int offset)
92*6435d21cSTzuyi Chang {
93*6435d21cSTzuyi Chang 	return data->info->gpa_offset + ((offset / 32) * 4);
94*6435d21cSTzuyi Chang }
95*6435d21cSTzuyi Chang 
96*6435d21cSTzuyi Chang static unsigned int rtd1625_gpio_gpda_offset(struct rtd1625_gpio *data, unsigned int offset)
97*6435d21cSTzuyi Chang {
98*6435d21cSTzuyi Chang 	return data->info->gpda_offset + ((offset / 32) * 4);
99*6435d21cSTzuyi Chang }
100*6435d21cSTzuyi Chang 
101*6435d21cSTzuyi Chang static unsigned int rtd1625_gpio_level_offset(struct rtd1625_gpio *data, unsigned int offset)
102*6435d21cSTzuyi Chang {
103*6435d21cSTzuyi Chang 	return data->info->level_offset + ((offset / 32) * 4);
104*6435d21cSTzuyi Chang }
105*6435d21cSTzuyi Chang 
106*6435d21cSTzuyi Chang static int rtd1625_reg_mask_xlate(struct gpio_regmap *gpio, enum gpio_regmap_operation op,
107*6435d21cSTzuyi Chang 				  unsigned int base, unsigned int offset, unsigned int *reg,
108*6435d21cSTzuyi Chang 				  unsigned int *mask)
109*6435d21cSTzuyi Chang {
110*6435d21cSTzuyi Chang 	/* Each GPIO has its own dedicated 32-bit register */
111*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = gpio_regmap_get_drvdata(gpio);
112*6435d21cSTzuyi Chang 	int val = 0, ret = 0;
113*6435d21cSTzuyi Chang 	*reg = base + offset * 4;
114*6435d21cSTzuyi Chang 
115*6435d21cSTzuyi Chang 	switch (op) {
116*6435d21cSTzuyi Chang 	case GPIO_REGMAP_SET_OP:
117*6435d21cSTzuyi Chang 		*mask = RTD1625_GPIO_OUT;
118*6435d21cSTzuyi Chang 		return 0;
119*6435d21cSTzuyi Chang 
120*6435d21cSTzuyi Chang 	case GPIO_REGMAP_GET_OP:
121*6435d21cSTzuyi Chang 		ret = regmap_read(data->regmap, *reg, &val);
122*6435d21cSTzuyi Chang 		if (ret)
123*6435d21cSTzuyi Chang 			return ret;
124*6435d21cSTzuyi Chang 
125*6435d21cSTzuyi Chang 		if (val & RTD1625_GPIO_DIR)
126*6435d21cSTzuyi Chang 			*mask = RTD1625_GPIO_OUT;
127*6435d21cSTzuyi Chang 		else
128*6435d21cSTzuyi Chang 			*mask = RTD1625_GPIO_IN;
129*6435d21cSTzuyi Chang 		return 0;
130*6435d21cSTzuyi Chang 
131*6435d21cSTzuyi Chang 	case GPIO_REGMAP_GET_DIR_OP:
132*6435d21cSTzuyi Chang 	case GPIO_REGMAP_SET_DIR_OP:
133*6435d21cSTzuyi Chang 		*mask = RTD1625_GPIO_DIR;
134*6435d21cSTzuyi Chang 		return 0;
135*6435d21cSTzuyi Chang 
136*6435d21cSTzuyi Chang 	default:
137*6435d21cSTzuyi Chang 		return -ENOTSUPP;
138*6435d21cSTzuyi Chang 	}
139*6435d21cSTzuyi Chang }
140*6435d21cSTzuyi Chang 
141*6435d21cSTzuyi Chang static int rtd1625_value_xlate(struct gpio_regmap *gpio,
142*6435d21cSTzuyi Chang 			       enum gpio_regmap_operation op,
143*6435d21cSTzuyi Chang 			       unsigned int base, unsigned int offset,
144*6435d21cSTzuyi Chang 			       unsigned int reg, unsigned int *mask,
145*6435d21cSTzuyi Chang 			       unsigned int *val)
146*6435d21cSTzuyi Chang {
147*6435d21cSTzuyi Chang 	switch (op) {
148*6435d21cSTzuyi Chang 	case GPIO_REGMAP_SET_OP:
149*6435d21cSTzuyi Chang 		*val |= RTD1625_GPIO_WREN(RTD1625_GPIO_OUT);
150*6435d21cSTzuyi Chang 		*mask |= RTD1625_GPIO_WREN(RTD1625_GPIO_OUT);
151*6435d21cSTzuyi Chang 		return 0;
152*6435d21cSTzuyi Chang 
153*6435d21cSTzuyi Chang 	case GPIO_REGMAP_SET_DIR_OP:
154*6435d21cSTzuyi Chang 		*val |= RTD1625_GPIO_WREN(RTD1625_GPIO_DIR);
155*6435d21cSTzuyi Chang 		*mask |= RTD1625_GPIO_WREN(RTD1625_GPIO_DIR);
156*6435d21cSTzuyi Chang 		return 0;
157*6435d21cSTzuyi Chang 
158*6435d21cSTzuyi Chang 	default:
159*6435d21cSTzuyi Chang 		return -ENOTSUPP;
160*6435d21cSTzuyi Chang 	}
161*6435d21cSTzuyi Chang }
162*6435d21cSTzuyi Chang 
163*6435d21cSTzuyi Chang static int rtd1625_gpio_set_debounce(struct rtd1625_gpio *data, unsigned int offset,
164*6435d21cSTzuyi Chang 				     unsigned int debounce)
165*6435d21cSTzuyi Chang {
166*6435d21cSTzuyi Chang 	u8 deb_val;
167*6435d21cSTzuyi Chang 	u32 val;
168*6435d21cSTzuyi Chang 
169*6435d21cSTzuyi Chang 	switch (debounce) {
170*6435d21cSTzuyi Chang 	case 1:
171*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_1US;
172*6435d21cSTzuyi Chang 		break;
173*6435d21cSTzuyi Chang 	case 10:
174*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_10US;
175*6435d21cSTzuyi Chang 		break;
176*6435d21cSTzuyi Chang 	case 100:
177*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_100US;
178*6435d21cSTzuyi Chang 		break;
179*6435d21cSTzuyi Chang 	case 1000:
180*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_1MS;
181*6435d21cSTzuyi Chang 		break;
182*6435d21cSTzuyi Chang 	case 10000:
183*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_10MS;
184*6435d21cSTzuyi Chang 		break;
185*6435d21cSTzuyi Chang 	case 20000:
186*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_20MS;
187*6435d21cSTzuyi Chang 		break;
188*6435d21cSTzuyi Chang 	case 30000:
189*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_30MS;
190*6435d21cSTzuyi Chang 		break;
191*6435d21cSTzuyi Chang 	case 50000:
192*6435d21cSTzuyi Chang 		deb_val = RTD1625_GPIO_DEBOUNCE_50MS;
193*6435d21cSTzuyi Chang 		break;
194*6435d21cSTzuyi Chang 	default:
195*6435d21cSTzuyi Chang 		return -ENOTSUPP;
196*6435d21cSTzuyi Chang 	}
197*6435d21cSTzuyi Chang 
198*6435d21cSTzuyi Chang 	val = FIELD_PREP(RTD1625_GPIO_DEBOUNCE, deb_val) | RTD1625_GPIO_DEBOUNCE_WREN;
199*6435d21cSTzuyi Chang 
200*6435d21cSTzuyi Chang 	guard(raw_spinlock_irqsave)(&data->lock);
201*6435d21cSTzuyi Chang 
202*6435d21cSTzuyi Chang 	return regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(offset), val);
203*6435d21cSTzuyi Chang }
204*6435d21cSTzuyi Chang 
205*6435d21cSTzuyi Chang static int rtd1625_gpio_set_config(struct gpio_regmap *gpio, struct gpio_chip *chip,
206*6435d21cSTzuyi Chang 				   unsigned int offset, unsigned long config)
207*6435d21cSTzuyi Chang {
208*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = gpio_regmap_get_drvdata(gpio);
209*6435d21cSTzuyi Chang 	u32 debounce;
210*6435d21cSTzuyi Chang 
211*6435d21cSTzuyi Chang 	if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) {
212*6435d21cSTzuyi Chang 		debounce = pinconf_to_config_argument(config);
213*6435d21cSTzuyi Chang 		return rtd1625_gpio_set_debounce(data, offset, debounce);
214*6435d21cSTzuyi Chang 	}
215*6435d21cSTzuyi Chang 
216*6435d21cSTzuyi Chang 	return gpiochip_generic_config(chip, offset, config);
217*6435d21cSTzuyi Chang }
218*6435d21cSTzuyi Chang 
219*6435d21cSTzuyi Chang static void rtd1625_gpio_irq_handle(struct irq_desc *desc)
220*6435d21cSTzuyi Chang {
221*6435d21cSTzuyi Chang 	unsigned int (*get_reg_offset)(struct rtd1625_gpio *gpio, unsigned int offset);
222*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = irq_desc_get_handler_data(desc);
223*6435d21cSTzuyi Chang 	struct irq_chip *chip = irq_desc_get_chip(desc);
224*6435d21cSTzuyi Chang 	unsigned int irq = irq_desc_get_irq(desc);
225*6435d21cSTzuyi Chang 	struct irq_domain *domain = data->domain;
226*6435d21cSTzuyi Chang 	unsigned int reg_offset, i, j, val;
227*6435d21cSTzuyi Chang 	irq_hw_number_t hwirq;
228*6435d21cSTzuyi Chang 	unsigned long status;
229*6435d21cSTzuyi Chang 	u32 irq_type;
230*6435d21cSTzuyi Chang 	int ret;
231*6435d21cSTzuyi Chang 
232*6435d21cSTzuyi Chang 	if (irq == data->irqs[RTD1625_IRQ_ASSERT])
233*6435d21cSTzuyi Chang 		get_reg_offset = &rtd1625_gpio_gpa_offset;
234*6435d21cSTzuyi Chang 	else if (irq == data->irqs[RTD1625_IRQ_DEASSERT])
235*6435d21cSTzuyi Chang 		get_reg_offset = &rtd1625_gpio_gpda_offset;
236*6435d21cSTzuyi Chang 	else if (irq == data->irqs[RTD1625_IRQ_LEVEL])
237*6435d21cSTzuyi Chang 		get_reg_offset = &rtd1625_gpio_level_offset;
238*6435d21cSTzuyi Chang 	else
239*6435d21cSTzuyi Chang 		return;
240*6435d21cSTzuyi Chang 
241*6435d21cSTzuyi Chang 	chained_irq_enter(chip, desc);
242*6435d21cSTzuyi Chang 
243*6435d21cSTzuyi Chang 	for (i = 0; i < data->info->num_gpios; i += 32) {
244*6435d21cSTzuyi Chang 		reg_offset = get_reg_offset(data, i);
245*6435d21cSTzuyi Chang 		ret = regmap_read(data->regmap, reg_offset, &val);
246*6435d21cSTzuyi Chang 		if (ret) {
247*6435d21cSTzuyi Chang 			pr_err_ratelimited("Failed to read IRQ status for GPIO %u: %d\n", i, ret);
248*6435d21cSTzuyi Chang 			continue;
249*6435d21cSTzuyi Chang 		}
250*6435d21cSTzuyi Chang 
251*6435d21cSTzuyi Chang 		status = val;
252*6435d21cSTzuyi Chang 
253*6435d21cSTzuyi Chang 		/*
254*6435d21cSTzuyi Chang 		 * Hardware quirk: The controller fires both "assert" and "de-assert"
255*6435d21cSTzuyi Chang 		 * interrupts simultaneously on any edge toggle.
256*6435d21cSTzuyi Chang 		 * We must pre-clear edge interrupts here. If we drop an unwanted
257*6435d21cSTzuyi Chang 		 * de-assert interrupt below, it will never reach the IRQ core
258*6435d21cSTzuyi Chang 		 * (generic_handle_domain_irq), meaning ->irq_ack() won't be called.
259*6435d21cSTzuyi Chang 		 * Failing to clear it here leads to an interrupt storm.
260*6435d21cSTzuyi Chang 		 */
261*6435d21cSTzuyi Chang 		if (irq != data->irqs[RTD1625_IRQ_LEVEL]) {
262*6435d21cSTzuyi Chang 			ret = regmap_write(data->regmap, reg_offset, status);
263*6435d21cSTzuyi Chang 			if (ret)
264*6435d21cSTzuyi Chang 				pr_err_ratelimited("Failed to clear edge IRQ for GPIO %u: %d\n",
265*6435d21cSTzuyi Chang 						   i, ret);
266*6435d21cSTzuyi Chang 		}
267*6435d21cSTzuyi Chang 
268*6435d21cSTzuyi Chang 		for_each_set_bit(j, &status, 32) {
269*6435d21cSTzuyi Chang 			hwirq = i + j;
270*6435d21cSTzuyi Chang 			irq_type = irq_get_trigger_type(irq_find_mapping(domain, hwirq));
271*6435d21cSTzuyi Chang 
272*6435d21cSTzuyi Chang 			/*
273*6435d21cSTzuyi Chang 			 * Filter out the hardware-forced de-assert interrupt unless
274*6435d21cSTzuyi Chang 			 * the user explicitly requested IRQ_TYPE_EDGE_BOTH.
275*6435d21cSTzuyi Chang 			 */
276*6435d21cSTzuyi Chang 			if (irq == data->irqs[RTD1625_IRQ_DEASSERT] &&
277*6435d21cSTzuyi Chang 			    irq_type != IRQ_TYPE_EDGE_BOTH)
278*6435d21cSTzuyi Chang 				continue;
279*6435d21cSTzuyi Chang 
280*6435d21cSTzuyi Chang 			generic_handle_domain_irq(domain, hwirq);
281*6435d21cSTzuyi Chang 		}
282*6435d21cSTzuyi Chang 	}
283*6435d21cSTzuyi Chang 
284*6435d21cSTzuyi Chang 	chained_irq_exit(chip, desc);
285*6435d21cSTzuyi Chang }
286*6435d21cSTzuyi Chang 
287*6435d21cSTzuyi Chang static void rtd1625_gpio_ack_irq(struct irq_data *d)
288*6435d21cSTzuyi Chang {
289*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
290*6435d21cSTzuyi Chang 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
291*6435d21cSTzuyi Chang 	u32 irq_type = irqd_get_trigger_type(d);
292*6435d21cSTzuyi Chang 	u32 bit_mask = BIT(hwirq % 32);
293*6435d21cSTzuyi Chang 	int reg_offset;
294*6435d21cSTzuyi Chang 
295*6435d21cSTzuyi Chang 	if (irq_type & IRQ_TYPE_LEVEL_MASK) {
296*6435d21cSTzuyi Chang 		reg_offset = rtd1625_gpio_level_offset(data, hwirq);
297*6435d21cSTzuyi Chang 		regmap_write(data->regmap, reg_offset, bit_mask);
298*6435d21cSTzuyi Chang 	}
299*6435d21cSTzuyi Chang }
300*6435d21cSTzuyi Chang 
301*6435d21cSTzuyi Chang static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
302*6435d21cSTzuyi Chang {
303*6435d21cSTzuyi Chang 	int gpda_reg_offset = rtd1625_gpio_gpda_offset(data, hwirq);
304*6435d21cSTzuyi Chang 	int gpa_reg_offset = rtd1625_gpio_gpa_offset(data, hwirq);
305*6435d21cSTzuyi Chang 	u32 clr_mask = BIT(hwirq % 32);
306*6435d21cSTzuyi Chang 	u32 val;
307*6435d21cSTzuyi Chang 
308*6435d21cSTzuyi Chang 	guard(raw_spinlock_irqsave)(&data->lock);
309*6435d21cSTzuyi Chang 
310*6435d21cSTzuyi Chang 	regmap_write(data->regmap, gpa_reg_offset, clr_mask);
311*6435d21cSTzuyi Chang 	regmap_write(data->regmap, gpda_reg_offset, clr_mask);
312*6435d21cSTzuyi Chang 	val = RTD1625_GPIO_EDGE_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);
313*6435d21cSTzuyi Chang 	regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq), val);
314*6435d21cSTzuyi Chang }
315*6435d21cSTzuyi Chang 
316*6435d21cSTzuyi Chang static void rtd1625_gpio_disable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
317*6435d21cSTzuyi Chang {
318*6435d21cSTzuyi Chang 	u32 val;
319*6435d21cSTzuyi Chang 
320*6435d21cSTzuyi Chang 	guard(raw_spinlock_irqsave)(&data->lock);
321*6435d21cSTzuyi Chang 
322*6435d21cSTzuyi Chang 	val = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);
323*6435d21cSTzuyi Chang 	regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq), val);
324*6435d21cSTzuyi Chang }
325*6435d21cSTzuyi Chang 
326*6435d21cSTzuyi Chang static void rtd1625_gpio_enable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
327*6435d21cSTzuyi Chang {
328*6435d21cSTzuyi Chang 	int level_reg_offset = rtd1625_gpio_level_offset(data, hwirq);
329*6435d21cSTzuyi Chang 	u32 clr_mask = BIT(hwirq % 32);
330*6435d21cSTzuyi Chang 	u32 val;
331*6435d21cSTzuyi Chang 
332*6435d21cSTzuyi Chang 	guard(raw_spinlock_irqsave)(&data->lock);
333*6435d21cSTzuyi Chang 
334*6435d21cSTzuyi Chang 	regmap_write(data->regmap, level_reg_offset, clr_mask);
335*6435d21cSTzuyi Chang 	val = RTD1625_GPIO_LEVEL_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);
336*6435d21cSTzuyi Chang 	regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq), val);
337*6435d21cSTzuyi Chang }
338*6435d21cSTzuyi Chang 
339*6435d21cSTzuyi Chang static void rtd1625_gpio_disable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
340*6435d21cSTzuyi Chang {
341*6435d21cSTzuyi Chang 	u32 val;
342*6435d21cSTzuyi Chang 
343*6435d21cSTzuyi Chang 	guard(raw_spinlock_irqsave)(&data->lock);
344*6435d21cSTzuyi Chang 
345*6435d21cSTzuyi Chang 	val = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);
346*6435d21cSTzuyi Chang 	regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq), val);
347*6435d21cSTzuyi Chang }
348*6435d21cSTzuyi Chang 
349*6435d21cSTzuyi Chang static void rtd1625_gpio_enable_irq(struct irq_data *d)
350*6435d21cSTzuyi Chang {
351*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
352*6435d21cSTzuyi Chang 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
353*6435d21cSTzuyi Chang 	u32 irq_type = irqd_get_trigger_type(d);
354*6435d21cSTzuyi Chang 
355*6435d21cSTzuyi Chang 	gpio_regmap_enable_irq(data->gpio_reg, hwirq);
356*6435d21cSTzuyi Chang 
357*6435d21cSTzuyi Chang 	if (irq_type & IRQ_TYPE_EDGE_BOTH)
358*6435d21cSTzuyi Chang 		rtd1625_gpio_enable_edge_irq(data, hwirq);
359*6435d21cSTzuyi Chang 	else if (irq_type & IRQ_TYPE_LEVEL_MASK)
360*6435d21cSTzuyi Chang 		rtd1625_gpio_enable_level_irq(data, hwirq);
361*6435d21cSTzuyi Chang }
362*6435d21cSTzuyi Chang 
363*6435d21cSTzuyi Chang static void rtd1625_gpio_disable_irq(struct irq_data *d)
364*6435d21cSTzuyi Chang {
365*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
366*6435d21cSTzuyi Chang 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
367*6435d21cSTzuyi Chang 	u32 irq_type = irqd_get_trigger_type(d);
368*6435d21cSTzuyi Chang 
369*6435d21cSTzuyi Chang 	if (irq_type & IRQ_TYPE_EDGE_BOTH)
370*6435d21cSTzuyi Chang 		rtd1625_gpio_disable_edge_irq(data, hwirq);
371*6435d21cSTzuyi Chang 	else if (irq_type & IRQ_TYPE_LEVEL_MASK)
372*6435d21cSTzuyi Chang 		rtd1625_gpio_disable_level_irq(data, hwirq);
373*6435d21cSTzuyi Chang 
374*6435d21cSTzuyi Chang 	gpio_regmap_disable_irq(data->gpio_reg, hwirq);
375*6435d21cSTzuyi Chang }
376*6435d21cSTzuyi Chang 
377*6435d21cSTzuyi Chang static int rtd1625_gpio_irq_set_level_type(struct irq_data *d, bool level)
378*6435d21cSTzuyi Chang {
379*6435d21cSTzuyi Chang 	u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_DP);
380*6435d21cSTzuyi Chang 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
381*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data;
382*6435d21cSTzuyi Chang 	int ret;
383*6435d21cSTzuyi Chang 
384*6435d21cSTzuyi Chang 	data = irq_data_get_irq_chip_data(d);
385*6435d21cSTzuyi Chang 	if (!(data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK))
386*6435d21cSTzuyi Chang 		return -EINVAL;
387*6435d21cSTzuyi Chang 
388*6435d21cSTzuyi Chang 	if (level)
389*6435d21cSTzuyi Chang 		val |= RTD1625_GPIO_LEVEL_INT_DP;
390*6435d21cSTzuyi Chang 
391*6435d21cSTzuyi Chang 	scoped_guard(raw_spinlock_irqsave, &data->lock) {
392*6435d21cSTzuyi Chang 		ret = regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq),
393*6435d21cSTzuyi Chang 				   val);
394*6435d21cSTzuyi Chang 		if (ret)
395*6435d21cSTzuyi Chang 			return ret;
396*6435d21cSTzuyi Chang 	}
397*6435d21cSTzuyi Chang 
398*6435d21cSTzuyi Chang 	irq_set_handler_locked(d, handle_level_irq);
399*6435d21cSTzuyi Chang 
400*6435d21cSTzuyi Chang 	return 0;
401*6435d21cSTzuyi Chang }
402*6435d21cSTzuyi Chang 
403*6435d21cSTzuyi Chang static int rtd1625_gpio_irq_set_edge_type(struct irq_data *d, bool polarity)
404*6435d21cSTzuyi Chang {
405*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
406*6435d21cSTzuyi Chang 	u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_DP);
407*6435d21cSTzuyi Chang 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
408*6435d21cSTzuyi Chang 	int ret;
409*6435d21cSTzuyi Chang 
410*6435d21cSTzuyi Chang 	if (!(data->info->irq_type_support & IRQ_TYPE_EDGE_BOTH))
411*6435d21cSTzuyi Chang 		return -EINVAL;
412*6435d21cSTzuyi Chang 
413*6435d21cSTzuyi Chang 	if (polarity)
414*6435d21cSTzuyi Chang 		val |= RTD1625_GPIO_EDGE_INT_DP;
415*6435d21cSTzuyi Chang 
416*6435d21cSTzuyi Chang 	scoped_guard(raw_spinlock_irqsave, &data->lock) {
417*6435d21cSTzuyi Chang 		ret = regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(hwirq),
418*6435d21cSTzuyi Chang 				   val);
419*6435d21cSTzuyi Chang 		if (ret)
420*6435d21cSTzuyi Chang 			return ret;
421*6435d21cSTzuyi Chang 	}
422*6435d21cSTzuyi Chang 
423*6435d21cSTzuyi Chang 	irq_set_handler_locked(d, handle_edge_irq);
424*6435d21cSTzuyi Chang 
425*6435d21cSTzuyi Chang 	return 0;
426*6435d21cSTzuyi Chang }
427*6435d21cSTzuyi Chang 
428*6435d21cSTzuyi Chang static int rtd1625_gpio_irq_set_type(struct irq_data *d, unsigned int type)
429*6435d21cSTzuyi Chang {
430*6435d21cSTzuyi Chang 	switch (type & IRQ_TYPE_SENSE_MASK) {
431*6435d21cSTzuyi Chang 	case IRQ_TYPE_EDGE_RISING:
432*6435d21cSTzuyi Chang 		return rtd1625_gpio_irq_set_edge_type(d, 1);
433*6435d21cSTzuyi Chang 
434*6435d21cSTzuyi Chang 	case IRQ_TYPE_EDGE_FALLING:
435*6435d21cSTzuyi Chang 		return rtd1625_gpio_irq_set_edge_type(d, 0);
436*6435d21cSTzuyi Chang 
437*6435d21cSTzuyi Chang 	case IRQ_TYPE_EDGE_BOTH:
438*6435d21cSTzuyi Chang 		return rtd1625_gpio_irq_set_edge_type(d, 1);
439*6435d21cSTzuyi Chang 
440*6435d21cSTzuyi Chang 	case IRQ_TYPE_LEVEL_HIGH:
441*6435d21cSTzuyi Chang 		return rtd1625_gpio_irq_set_level_type(d, 0);
442*6435d21cSTzuyi Chang 
443*6435d21cSTzuyi Chang 	case IRQ_TYPE_LEVEL_LOW:
444*6435d21cSTzuyi Chang 		return rtd1625_gpio_irq_set_level_type(d, 1);
445*6435d21cSTzuyi Chang 
446*6435d21cSTzuyi Chang 	default:
447*6435d21cSTzuyi Chang 		return -EINVAL;
448*6435d21cSTzuyi Chang 	}
449*6435d21cSTzuyi Chang }
450*6435d21cSTzuyi Chang 
451*6435d21cSTzuyi Chang static int rtd1625_gpio_irq_request_resources(struct irq_data *d)
452*6435d21cSTzuyi Chang {
453*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
454*6435d21cSTzuyi Chang 
455*6435d21cSTzuyi Chang 	return gpio_regmap_reqres_irq(data->gpio_reg, d->hwirq);
456*6435d21cSTzuyi Chang }
457*6435d21cSTzuyi Chang 
458*6435d21cSTzuyi Chang static void rtd1625_gpio_irq_release_resources(struct irq_data *d)
459*6435d21cSTzuyi Chang {
460*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
461*6435d21cSTzuyi Chang 
462*6435d21cSTzuyi Chang 	gpio_regmap_relres_irq(data->gpio_reg, d->hwirq);
463*6435d21cSTzuyi Chang }
464*6435d21cSTzuyi Chang 
465*6435d21cSTzuyi Chang static struct irq_chip rtd1625_iso_gpio_irq_chip = {
466*6435d21cSTzuyi Chang 	.name = "rtd1625-gpio",
467*6435d21cSTzuyi Chang 	.irq_ack = rtd1625_gpio_ack_irq,
468*6435d21cSTzuyi Chang 	.irq_mask = rtd1625_gpio_disable_irq,
469*6435d21cSTzuyi Chang 	.irq_unmask = rtd1625_gpio_enable_irq,
470*6435d21cSTzuyi Chang 	.irq_set_type = rtd1625_gpio_irq_set_type,
471*6435d21cSTzuyi Chang 	.flags = IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE,
472*6435d21cSTzuyi Chang 	.irq_request_resources = rtd1625_gpio_irq_request_resources,
473*6435d21cSTzuyi Chang 	.irq_release_resources = rtd1625_gpio_irq_release_resources,
474*6435d21cSTzuyi Chang };
475*6435d21cSTzuyi Chang 
476*6435d21cSTzuyi Chang static int rtd1625_gpio_setup_irq(struct platform_device *pdev, struct rtd1625_gpio *data)
477*6435d21cSTzuyi Chang {
478*6435d21cSTzuyi Chang 	unsigned int num_irqs;
479*6435d21cSTzuyi Chang 	int irq;
480*6435d21cSTzuyi Chang 
481*6435d21cSTzuyi Chang 	/* IRQ is optional; operate as basic GPIO if absent */
482*6435d21cSTzuyi Chang 	irq = platform_get_irq_optional(pdev, 0);
483*6435d21cSTzuyi Chang 	if (irq == -ENXIO)
484*6435d21cSTzuyi Chang 		return 0;
485*6435d21cSTzuyi Chang 	if (irq < 0)
486*6435d21cSTzuyi Chang 		return irq;
487*6435d21cSTzuyi Chang 
488*6435d21cSTzuyi Chang 	num_irqs = (data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK) ? 3 : 2;
489*6435d21cSTzuyi Chang 
490*6435d21cSTzuyi Chang 	for (unsigned int i = 0; i < num_irqs; i++) {
491*6435d21cSTzuyi Chang 		irq = platform_get_irq(pdev, i);
492*6435d21cSTzuyi Chang 		if (irq < 0)
493*6435d21cSTzuyi Chang 			return irq;
494*6435d21cSTzuyi Chang 
495*6435d21cSTzuyi Chang 		data->irqs[i] = irq;
496*6435d21cSTzuyi Chang 		irq_set_chained_handler_and_data(data->irqs[i], rtd1625_gpio_irq_handle, data);
497*6435d21cSTzuyi Chang 	}
498*6435d21cSTzuyi Chang 
499*6435d21cSTzuyi Chang 	return 0;
500*6435d21cSTzuyi Chang }
501*6435d21cSTzuyi Chang 
502*6435d21cSTzuyi Chang static int rtd1625_gpio_irq_map(struct irq_domain *domain, unsigned int irq,
503*6435d21cSTzuyi Chang 				irq_hw_number_t hwirq)
504*6435d21cSTzuyi Chang {
505*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = domain->host_data;
506*6435d21cSTzuyi Chang 
507*6435d21cSTzuyi Chang 	irq_set_chip_data(irq, data);
508*6435d21cSTzuyi Chang 
509*6435d21cSTzuyi Chang 	irq_set_chip_and_handler(irq, &rtd1625_iso_gpio_irq_chip, handle_bad_irq);
510*6435d21cSTzuyi Chang 
511*6435d21cSTzuyi Chang 	irq_set_noprobe(irq);
512*6435d21cSTzuyi Chang 
513*6435d21cSTzuyi Chang 	irq_set_lockdep_class(irq, &rtd1625_gpio_irq_lock_class,
514*6435d21cSTzuyi Chang 			      &rtd1625_gpio_irq_request_class);
515*6435d21cSTzuyi Chang 
516*6435d21cSTzuyi Chang 	return 0;
517*6435d21cSTzuyi Chang }
518*6435d21cSTzuyi Chang 
519*6435d21cSTzuyi Chang static const struct irq_domain_ops rtd1625_gpio_irq_domain_ops = {
520*6435d21cSTzuyi Chang 	.map = rtd1625_gpio_irq_map,
521*6435d21cSTzuyi Chang 	.xlate = irq_domain_xlate_twocell,
522*6435d21cSTzuyi Chang };
523*6435d21cSTzuyi Chang 
524*6435d21cSTzuyi Chang static const struct regmap_config rtd1625_gpio_regmap_config = {
525*6435d21cSTzuyi Chang 	.reg_bits = 32,
526*6435d21cSTzuyi Chang 	.reg_stride = 4,
527*6435d21cSTzuyi Chang 	.val_bits = 32,
528*6435d21cSTzuyi Chang #ifndef CONFIG_DEBUG_GPIO
529*6435d21cSTzuyi Chang 	.disable_locking = true,
530*6435d21cSTzuyi Chang #endif
531*6435d21cSTzuyi Chang };
532*6435d21cSTzuyi Chang 
533*6435d21cSTzuyi Chang static int rtd1625_gpio_probe(struct platform_device *pdev)
534*6435d21cSTzuyi Chang {
535*6435d21cSTzuyi Chang 	struct gpio_regmap_config config = {};
536*6435d21cSTzuyi Chang 	struct irq_domain_info d_info = {};
537*6435d21cSTzuyi Chang 	struct device *dev = &pdev->dev;
538*6435d21cSTzuyi Chang 	struct gpio_regmap *gpio_reg;
539*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data;
540*6435d21cSTzuyi Chang 	void __iomem *irq_base;
541*6435d21cSTzuyi Chang 	int ret;
542*6435d21cSTzuyi Chang 
543*6435d21cSTzuyi Chang 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
544*6435d21cSTzuyi Chang 	if (!data)
545*6435d21cSTzuyi Chang 		return -ENOMEM;
546*6435d21cSTzuyi Chang 
547*6435d21cSTzuyi Chang 	data->info = device_get_match_data(dev);
548*6435d21cSTzuyi Chang 	if (!data->info)
549*6435d21cSTzuyi Chang 		return -ENODATA;
550*6435d21cSTzuyi Chang 
551*6435d21cSTzuyi Chang 	irq_base = devm_platform_ioremap_resource(pdev, 0);
552*6435d21cSTzuyi Chang 	if (IS_ERR(irq_base))
553*6435d21cSTzuyi Chang 		return PTR_ERR(irq_base);
554*6435d21cSTzuyi Chang 
555*6435d21cSTzuyi Chang 	data->regmap = devm_regmap_init_mmio(dev, irq_base, &rtd1625_gpio_regmap_config);
556*6435d21cSTzuyi Chang 	if (IS_ERR(data->regmap))
557*6435d21cSTzuyi Chang 		return PTR_ERR(data->regmap);
558*6435d21cSTzuyi Chang 
559*6435d21cSTzuyi Chang 	raw_spin_lock_init(&data->lock);
560*6435d21cSTzuyi Chang 	platform_set_drvdata(pdev, data);
561*6435d21cSTzuyi Chang 
562*6435d21cSTzuyi Chang 	data->save_regs = devm_kcalloc(dev, data->info->num_gpios, sizeof(*data->save_regs),
563*6435d21cSTzuyi Chang 				       GFP_KERNEL);
564*6435d21cSTzuyi Chang 	if (!data->save_regs)
565*6435d21cSTzuyi Chang 		return -ENOMEM;
566*6435d21cSTzuyi Chang 
567*6435d21cSTzuyi Chang 	config.parent = dev;
568*6435d21cSTzuyi Chang 	config.regmap = data->regmap;
569*6435d21cSTzuyi Chang 	config.ngpio = data->info->num_gpios;
570*6435d21cSTzuyi Chang 	config.reg_dat_base = data->info->base_offset;
571*6435d21cSTzuyi Chang 	config.reg_set_base = data->info->base_offset;
572*6435d21cSTzuyi Chang 	config.reg_dir_out_base = data->info->base_offset;
573*6435d21cSTzuyi Chang 
574*6435d21cSTzuyi Chang 	config.reg_mask_xlate = rtd1625_reg_mask_xlate;
575*6435d21cSTzuyi Chang 	config.set_config = rtd1625_gpio_set_config;
576*6435d21cSTzuyi Chang 	config.value_xlate = rtd1625_value_xlate;
577*6435d21cSTzuyi Chang 
578*6435d21cSTzuyi Chang 	d_info.fwnode = dev_fwnode(&pdev->dev);
579*6435d21cSTzuyi Chang 	d_info.size = data->info->num_gpios;
580*6435d21cSTzuyi Chang 	d_info.hwirq_max = data->info->num_gpios;
581*6435d21cSTzuyi Chang 	d_info.ops = &rtd1625_gpio_irq_domain_ops;
582*6435d21cSTzuyi Chang 	d_info.host_data = data;
583*6435d21cSTzuyi Chang 
584*6435d21cSTzuyi Chang 	data->domain = devm_irq_domain_instantiate(dev, &d_info);
585*6435d21cSTzuyi Chang 	if (IS_ERR(data->domain))
586*6435d21cSTzuyi Chang 		return PTR_ERR(data->domain);
587*6435d21cSTzuyi Chang 
588*6435d21cSTzuyi Chang 	ret = rtd1625_gpio_setup_irq(pdev, data);
589*6435d21cSTzuyi Chang 	if (ret)
590*6435d21cSTzuyi Chang 		return ret;
591*6435d21cSTzuyi Chang 
592*6435d21cSTzuyi Chang 	config.irq_domain = data->domain;
593*6435d21cSTzuyi Chang 	config.drvdata = data;
594*6435d21cSTzuyi Chang 
595*6435d21cSTzuyi Chang 	gpio_reg = devm_gpio_regmap_register(dev, &config);
596*6435d21cSTzuyi Chang 	if (IS_ERR(gpio_reg))
597*6435d21cSTzuyi Chang 		return PTR_ERR(gpio_reg);
598*6435d21cSTzuyi Chang 
599*6435d21cSTzuyi Chang 	data->gpio_reg = gpio_reg;
600*6435d21cSTzuyi Chang 
601*6435d21cSTzuyi Chang 	return 0;
602*6435d21cSTzuyi Chang }
603*6435d21cSTzuyi Chang 
604*6435d21cSTzuyi Chang static const struct rtd1625_gpio_info rtd1625_iso_gpio_info = {
605*6435d21cSTzuyi Chang 	.num_gpios        = 166,
606*6435d21cSTzuyi Chang 	.irq_type_support = IRQ_TYPE_EDGE_BOTH,
607*6435d21cSTzuyi Chang 	.base_offset      = 0x100,
608*6435d21cSTzuyi Chang 	.gpa_offset       = 0x000,
609*6435d21cSTzuyi Chang 	.gpda_offset      = 0x020,
610*6435d21cSTzuyi Chang 	.write_en_all     = RTD1625_ISO_GPIO_WREN_ALL,
611*6435d21cSTzuyi Chang };
612*6435d21cSTzuyi Chang 
613*6435d21cSTzuyi Chang static const struct rtd1625_gpio_info rtd1625_isom_gpio_info = {
614*6435d21cSTzuyi Chang 	.num_gpios        = 4,
615*6435d21cSTzuyi Chang 	.irq_type_support = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_LOW |
616*6435d21cSTzuyi Chang 			    IRQ_TYPE_LEVEL_HIGH,
617*6435d21cSTzuyi Chang 	.base_offset      = 0x20,
618*6435d21cSTzuyi Chang 	.gpa_offset       = 0x00,
619*6435d21cSTzuyi Chang 	.gpda_offset      = 0x04,
620*6435d21cSTzuyi Chang 	.level_offset     = 0x18,
621*6435d21cSTzuyi Chang 	.write_en_all     = RTD1625_ISOM_GPIO_WREN_ALL,
622*6435d21cSTzuyi Chang };
623*6435d21cSTzuyi Chang 
624*6435d21cSTzuyi Chang static int rtd1625_gpio_suspend(struct device *dev)
625*6435d21cSTzuyi Chang {
626*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = dev_get_drvdata(dev);
627*6435d21cSTzuyi Chang 	const struct rtd1625_gpio_info *info = data->info;
628*6435d21cSTzuyi Chang 	int ret;
629*6435d21cSTzuyi Chang 
630*6435d21cSTzuyi Chang 	for (unsigned int i = 0; i < info->num_gpios; i++) {
631*6435d21cSTzuyi Chang 		ret = regmap_read(data->regmap, data->info->base_offset + GPIO_CONTROL(i),
632*6435d21cSTzuyi Chang 				  &data->save_regs[i]);
633*6435d21cSTzuyi Chang 		if (ret)
634*6435d21cSTzuyi Chang 			return ret;
635*6435d21cSTzuyi Chang 	}
636*6435d21cSTzuyi Chang 
637*6435d21cSTzuyi Chang 	return 0;
638*6435d21cSTzuyi Chang }
639*6435d21cSTzuyi Chang 
640*6435d21cSTzuyi Chang static int rtd1625_gpio_resume(struct device *dev)
641*6435d21cSTzuyi Chang {
642*6435d21cSTzuyi Chang 	struct rtd1625_gpio *data = dev_get_drvdata(dev);
643*6435d21cSTzuyi Chang 	const struct rtd1625_gpio_info *info = data->info;
644*6435d21cSTzuyi Chang 	int ret;
645*6435d21cSTzuyi Chang 
646*6435d21cSTzuyi Chang 	for (unsigned int i = 0; i < info->num_gpios; i++) {
647*6435d21cSTzuyi Chang 		ret = regmap_write(data->regmap, data->info->base_offset + GPIO_CONTROL(i),
648*6435d21cSTzuyi Chang 				   data->save_regs[i] | info->write_en_all);
649*6435d21cSTzuyi Chang 		if (ret)
650*6435d21cSTzuyi Chang 			return ret;
651*6435d21cSTzuyi Chang 	}
652*6435d21cSTzuyi Chang 
653*6435d21cSTzuyi Chang 	return 0;
654*6435d21cSTzuyi Chang }
655*6435d21cSTzuyi Chang 
656*6435d21cSTzuyi Chang static DEFINE_NOIRQ_DEV_PM_OPS(rtd1625_gpio_pm_ops, rtd1625_gpio_suspend, rtd1625_gpio_resume);
657*6435d21cSTzuyi Chang 
658*6435d21cSTzuyi Chang static const struct of_device_id rtd1625_gpio_of_matches[] = {
659*6435d21cSTzuyi Chang 	{ .compatible = "realtek,rtd1625-iso-gpio", .data = &rtd1625_iso_gpio_info },
660*6435d21cSTzuyi Chang 	{ .compatible = "realtek,rtd1625-isom-gpio", .data = &rtd1625_isom_gpio_info },
661*6435d21cSTzuyi Chang 	{ }
662*6435d21cSTzuyi Chang };
663*6435d21cSTzuyi Chang MODULE_DEVICE_TABLE(of, rtd1625_gpio_of_matches);
664*6435d21cSTzuyi Chang 
665*6435d21cSTzuyi Chang static struct platform_driver rtd1625_gpio_platform_driver = {
666*6435d21cSTzuyi Chang 	.driver = {
667*6435d21cSTzuyi Chang 		.name = "gpio-rtd1625",
668*6435d21cSTzuyi Chang 		.of_match_table = rtd1625_gpio_of_matches,
669*6435d21cSTzuyi Chang 		.pm = pm_sleep_ptr(&rtd1625_gpio_pm_ops),
670*6435d21cSTzuyi Chang 	},
671*6435d21cSTzuyi Chang 	.probe = rtd1625_gpio_probe,
672*6435d21cSTzuyi Chang };
673*6435d21cSTzuyi Chang module_platform_driver(rtd1625_gpio_platform_driver);
674*6435d21cSTzuyi Chang 
675*6435d21cSTzuyi Chang MODULE_LICENSE("GPL");
676*6435d21cSTzuyi Chang MODULE_AUTHOR("Realtek Semiconductor Corporation");
677*6435d21cSTzuyi Chang MODULE_DESCRIPTION("Realtek DHC SoC RTD1625 gpio driver");
678