xref: /OK3568_Linux_fs/kernel/drivers/gpio/gpio-cs5535.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * AMD CS5535/CS5536 GPIO driver
4*4882a593Smuzhiyun  * Copyright (C) 2006  Advanced Micro Devices, Inc.
5*4882a593Smuzhiyun  * Copyright (C) 2007-2009  Andres Salomon <dilinger@collabora.co.uk>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/spinlock.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/platform_device.h>
12*4882a593Smuzhiyun #include <linux/gpio/driver.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <linux/cs5535.h>
15*4882a593Smuzhiyun #include <asm/msr.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define DRV_NAME "cs5535-gpio"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * Some GPIO pins
21*4882a593Smuzhiyun  *  31-29,23 : reserved (always mask out)
22*4882a593Smuzhiyun  *  28       : Power Button
23*4882a593Smuzhiyun  *  26       : PME#
24*4882a593Smuzhiyun  *  22-16    : LPC
25*4882a593Smuzhiyun  *  14,15    : SMBus
26*4882a593Smuzhiyun  *  9,8      : UART1
27*4882a593Smuzhiyun  *  7        : PCI INTB
28*4882a593Smuzhiyun  *  3,4      : UART2/DDC
29*4882a593Smuzhiyun  *  2        : IDE_IRQ0
30*4882a593Smuzhiyun  *  1        : AC_BEEP
31*4882a593Smuzhiyun  *  0        : PCI INTA
32*4882a593Smuzhiyun  *
33*4882a593Smuzhiyun  * If a mask was not specified, allow all except
34*4882a593Smuzhiyun  * reserved and Power Button
35*4882a593Smuzhiyun  */
36*4882a593Smuzhiyun #define GPIO_DEFAULT_MASK 0x0F7FFFFF
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static ulong mask = GPIO_DEFAULT_MASK;
39*4882a593Smuzhiyun module_param_named(mask, mask, ulong, 0444);
40*4882a593Smuzhiyun MODULE_PARM_DESC(mask, "GPIO channel mask.");
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun  * FIXME: convert this singleton driver to use the state container
44*4882a593Smuzhiyun  * design pattern, see Documentation/driver-api/driver-model/design-patterns.rst
45*4882a593Smuzhiyun  */
46*4882a593Smuzhiyun static struct cs5535_gpio_chip {
47*4882a593Smuzhiyun 	struct gpio_chip chip;
48*4882a593Smuzhiyun 	resource_size_t base;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	struct platform_device *pdev;
51*4882a593Smuzhiyun 	spinlock_t lock;
52*4882a593Smuzhiyun } cs5535_gpio_chip;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /*
55*4882a593Smuzhiyun  * The CS5535/CS5536 GPIOs support a number of extra features not defined
56*4882a593Smuzhiyun  * by the gpio_chip API, so these are exported.  For a full list of the
57*4882a593Smuzhiyun  * registers, see include/linux/cs5535.h.
58*4882a593Smuzhiyun  */
59*4882a593Smuzhiyun 
errata_outl(struct cs5535_gpio_chip * chip,u32 val,unsigned int reg)60*4882a593Smuzhiyun static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
61*4882a593Smuzhiyun 		unsigned int reg)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	unsigned long addr = chip->base + 0x80 + reg;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	/*
66*4882a593Smuzhiyun 	 * According to the CS5536 errata (#36), after suspend
67*4882a593Smuzhiyun 	 * a write to the high bank GPIO register will clear all
68*4882a593Smuzhiyun 	 * non-selected bits; the recommended workaround is a
69*4882a593Smuzhiyun 	 * read-modify-write operation.
70*4882a593Smuzhiyun 	 *
71*4882a593Smuzhiyun 	 * Don't apply this errata to the edge status GPIOs, as writing
72*4882a593Smuzhiyun 	 * to their lower bits will clear them.
73*4882a593Smuzhiyun 	 */
74*4882a593Smuzhiyun 	if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
75*4882a593Smuzhiyun 		if (val & 0xffff)
76*4882a593Smuzhiyun 			val |= (inl(addr) & 0xffff); /* ignore the high bits */
77*4882a593Smuzhiyun 		else
78*4882a593Smuzhiyun 			val |= (inl(addr) ^ (val >> 16));
79*4882a593Smuzhiyun 	}
80*4882a593Smuzhiyun 	outl(val, addr);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
__cs5535_gpio_set(struct cs5535_gpio_chip * chip,unsigned offset,unsigned int reg)83*4882a593Smuzhiyun static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
84*4882a593Smuzhiyun 		unsigned int reg)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	if (offset < 16)
87*4882a593Smuzhiyun 		/* low bank register */
88*4882a593Smuzhiyun 		outl(1 << offset, chip->base + reg);
89*4882a593Smuzhiyun 	else
90*4882a593Smuzhiyun 		/* high bank register */
91*4882a593Smuzhiyun 		errata_outl(chip, 1 << (offset - 16), reg);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
cs5535_gpio_set(unsigned offset,unsigned int reg)94*4882a593Smuzhiyun void cs5535_gpio_set(unsigned offset, unsigned int reg)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
97*4882a593Smuzhiyun 	unsigned long flags;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
100*4882a593Smuzhiyun 	__cs5535_gpio_set(chip, offset, reg);
101*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(cs5535_gpio_set);
104*4882a593Smuzhiyun 
__cs5535_gpio_clear(struct cs5535_gpio_chip * chip,unsigned offset,unsigned int reg)105*4882a593Smuzhiyun static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
106*4882a593Smuzhiyun 		unsigned int reg)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	if (offset < 16)
109*4882a593Smuzhiyun 		/* low bank register */
110*4882a593Smuzhiyun 		outl(1 << (offset + 16), chip->base + reg);
111*4882a593Smuzhiyun 	else
112*4882a593Smuzhiyun 		/* high bank register */
113*4882a593Smuzhiyun 		errata_outl(chip, 1 << offset, reg);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
cs5535_gpio_clear(unsigned offset,unsigned int reg)116*4882a593Smuzhiyun void cs5535_gpio_clear(unsigned offset, unsigned int reg)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
119*4882a593Smuzhiyun 	unsigned long flags;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
122*4882a593Smuzhiyun 	__cs5535_gpio_clear(chip, offset, reg);
123*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
126*4882a593Smuzhiyun 
cs5535_gpio_isset(unsigned offset,unsigned int reg)127*4882a593Smuzhiyun int cs5535_gpio_isset(unsigned offset, unsigned int reg)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
130*4882a593Smuzhiyun 	unsigned long flags;
131*4882a593Smuzhiyun 	long val;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
134*4882a593Smuzhiyun 	if (offset < 16)
135*4882a593Smuzhiyun 		/* low bank register */
136*4882a593Smuzhiyun 		val = inl(chip->base + reg);
137*4882a593Smuzhiyun 	else {
138*4882a593Smuzhiyun 		/* high bank register */
139*4882a593Smuzhiyun 		val = inl(chip->base + 0x80 + reg);
140*4882a593Smuzhiyun 		offset -= 16;
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	return (val & (1 << offset)) ? 1 : 0;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
147*4882a593Smuzhiyun 
cs5535_gpio_set_irq(unsigned group,unsigned irq)148*4882a593Smuzhiyun int cs5535_gpio_set_irq(unsigned group, unsigned irq)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	uint32_t lo, hi;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	if (group > 7 || irq > 15)
153*4882a593Smuzhiyun 		return -EINVAL;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	lo &= ~(0xF << (group * 4));
158*4882a593Smuzhiyun 	lo |= (irq & 0xF) << (group * 4);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
161*4882a593Smuzhiyun 	return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
164*4882a593Smuzhiyun 
cs5535_gpio_setup_event(unsigned offset,int pair,int pme)165*4882a593Smuzhiyun void cs5535_gpio_setup_event(unsigned offset, int pair, int pme)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
168*4882a593Smuzhiyun 	uint32_t shift = (offset % 8) * 4;
169*4882a593Smuzhiyun 	unsigned long flags;
170*4882a593Smuzhiyun 	uint32_t val;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (offset >= 24)
173*4882a593Smuzhiyun 		offset = GPIO_MAP_W;
174*4882a593Smuzhiyun 	else if (offset >= 16)
175*4882a593Smuzhiyun 		offset = GPIO_MAP_Z;
176*4882a593Smuzhiyun 	else if (offset >= 8)
177*4882a593Smuzhiyun 		offset = GPIO_MAP_Y;
178*4882a593Smuzhiyun 	else
179*4882a593Smuzhiyun 		offset = GPIO_MAP_X;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
182*4882a593Smuzhiyun 	val = inl(chip->base + offset);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	/* Clear whatever was there before */
185*4882a593Smuzhiyun 	val &= ~(0xF << shift);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	/* Set the new value */
188*4882a593Smuzhiyun 	val |= ((pair & 7) << shift);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* Set the PME bit if this is a PME event */
191*4882a593Smuzhiyun 	if (pme)
192*4882a593Smuzhiyun 		val |= (1 << (shift + 3));
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	outl(val, chip->base + offset);
195*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun /*
200*4882a593Smuzhiyun  * Generic gpio_chip API support.
201*4882a593Smuzhiyun  */
202*4882a593Smuzhiyun 
chip_gpio_request(struct gpio_chip * c,unsigned offset)203*4882a593Smuzhiyun static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	struct cs5535_gpio_chip *chip = gpiochip_get_data(c);
206*4882a593Smuzhiyun 	unsigned long flags;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	/* check if this pin is available */
211*4882a593Smuzhiyun 	if ((mask & (1 << offset)) == 0) {
212*4882a593Smuzhiyun 		dev_info(&chip->pdev->dev,
213*4882a593Smuzhiyun 			"pin %u is not available (check mask)\n", offset);
214*4882a593Smuzhiyun 		spin_unlock_irqrestore(&chip->lock, flags);
215*4882a593Smuzhiyun 		return -EINVAL;
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/* disable output aux 1 & 2 on this pin */
219*4882a593Smuzhiyun 	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
220*4882a593Smuzhiyun 	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	/* disable input aux 1 on this pin */
223*4882a593Smuzhiyun 	__cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	return 0;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
chip_gpio_get(struct gpio_chip * chip,unsigned offset)230*4882a593Smuzhiyun static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	return cs5535_gpio_isset(offset, GPIO_READ_BACK);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
chip_gpio_set(struct gpio_chip * chip,unsigned offset,int val)235*4882a593Smuzhiyun static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	if (val)
238*4882a593Smuzhiyun 		cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
239*4882a593Smuzhiyun 	else
240*4882a593Smuzhiyun 		cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
chip_direction_input(struct gpio_chip * c,unsigned offset)243*4882a593Smuzhiyun static int chip_direction_input(struct gpio_chip *c, unsigned offset)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	struct cs5535_gpio_chip *chip = gpiochip_get_data(c);
246*4882a593Smuzhiyun 	unsigned long flags;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
249*4882a593Smuzhiyun 	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
250*4882a593Smuzhiyun 	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
251*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	return 0;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
chip_direction_output(struct gpio_chip * c,unsigned offset,int val)256*4882a593Smuzhiyun static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	struct cs5535_gpio_chip *chip = gpiochip_get_data(c);
259*4882a593Smuzhiyun 	unsigned long flags;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	spin_lock_irqsave(&chip->lock, flags);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
264*4882a593Smuzhiyun 	__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
265*4882a593Smuzhiyun 	if (val)
266*4882a593Smuzhiyun 		__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
267*4882a593Smuzhiyun 	else
268*4882a593Smuzhiyun 		__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	spin_unlock_irqrestore(&chip->lock, flags);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	return 0;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun static const char * const cs5535_gpio_names[] = {
276*4882a593Smuzhiyun 	"GPIO0", "GPIO1", "GPIO2", "GPIO3",
277*4882a593Smuzhiyun 	"GPIO4", "GPIO5", "GPIO6", "GPIO7",
278*4882a593Smuzhiyun 	"GPIO8", "GPIO9", "GPIO10", "GPIO11",
279*4882a593Smuzhiyun 	"GPIO12", "GPIO13", "GPIO14", "GPIO15",
280*4882a593Smuzhiyun 	"GPIO16", "GPIO17", "GPIO18", "GPIO19",
281*4882a593Smuzhiyun 	"GPIO20", "GPIO21", "GPIO22", NULL,
282*4882a593Smuzhiyun 	"GPIO24", "GPIO25", "GPIO26", "GPIO27",
283*4882a593Smuzhiyun 	"GPIO28", NULL, NULL, NULL,
284*4882a593Smuzhiyun };
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun static struct cs5535_gpio_chip cs5535_gpio_chip = {
287*4882a593Smuzhiyun 	.chip = {
288*4882a593Smuzhiyun 		.owner = THIS_MODULE,
289*4882a593Smuzhiyun 		.label = DRV_NAME,
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 		.base = 0,
292*4882a593Smuzhiyun 		.ngpio = 32,
293*4882a593Smuzhiyun 		.names = cs5535_gpio_names,
294*4882a593Smuzhiyun 		.request = chip_gpio_request,
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 		.get = chip_gpio_get,
297*4882a593Smuzhiyun 		.set = chip_gpio_set,
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 		.direction_input = chip_direction_input,
300*4882a593Smuzhiyun 		.direction_output = chip_direction_output,
301*4882a593Smuzhiyun 	},
302*4882a593Smuzhiyun };
303*4882a593Smuzhiyun 
cs5535_gpio_probe(struct platform_device * pdev)304*4882a593Smuzhiyun static int cs5535_gpio_probe(struct platform_device *pdev)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun 	struct resource *res;
307*4882a593Smuzhiyun 	int err = -EIO;
308*4882a593Smuzhiyun 	ulong mask_orig = mask;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	/* There are two ways to get the GPIO base address; one is by
311*4882a593Smuzhiyun 	 * fetching it from MSR_LBAR_GPIO, the other is by reading the
312*4882a593Smuzhiyun 	 * PCI BAR info.  The latter method is easier (especially across
313*4882a593Smuzhiyun 	 * different architectures), so we'll stick with that for now.  If
314*4882a593Smuzhiyun 	 * it turns out to be unreliable in the face of crappy BIOSes, we
315*4882a593Smuzhiyun 	 * can always go back to using MSRs.. */
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
318*4882a593Smuzhiyun 	if (!res) {
319*4882a593Smuzhiyun 		dev_err(&pdev->dev, "can't fetch device resource info\n");
320*4882a593Smuzhiyun 		return err;
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
324*4882a593Smuzhiyun 				 pdev->name)) {
325*4882a593Smuzhiyun 		dev_err(&pdev->dev, "can't request region\n");
326*4882a593Smuzhiyun 		return err;
327*4882a593Smuzhiyun 	}
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	/* set up the driver-specific struct */
330*4882a593Smuzhiyun 	cs5535_gpio_chip.base = res->start;
331*4882a593Smuzhiyun 	cs5535_gpio_chip.pdev = pdev;
332*4882a593Smuzhiyun 	spin_lock_init(&cs5535_gpio_chip.lock);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	dev_info(&pdev->dev, "reserved resource region %pR\n", res);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	/* mask out reserved pins */
337*4882a593Smuzhiyun 	mask &= 0x1F7FFFFF;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	/* do not allow pin 28, Power Button, as there's special handling
340*4882a593Smuzhiyun 	 * in the PMC needed. (note 12, p. 48) */
341*4882a593Smuzhiyun 	mask &= ~(1 << 28);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	if (mask_orig != mask)
344*4882a593Smuzhiyun 		dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
345*4882a593Smuzhiyun 				mask_orig, mask);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	/* finally, register with the generic GPIO API */
348*4882a593Smuzhiyun 	err = devm_gpiochip_add_data(&pdev->dev, &cs5535_gpio_chip.chip,
349*4882a593Smuzhiyun 				     &cs5535_gpio_chip);
350*4882a593Smuzhiyun 	if (err)
351*4882a593Smuzhiyun 		return err;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun static struct platform_driver cs5535_gpio_driver = {
357*4882a593Smuzhiyun 	.driver = {
358*4882a593Smuzhiyun 		.name = DRV_NAME,
359*4882a593Smuzhiyun 	},
360*4882a593Smuzhiyun 	.probe = cs5535_gpio_probe,
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun module_platform_driver(cs5535_gpio_driver);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
366*4882a593Smuzhiyun MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
367*4882a593Smuzhiyun MODULE_LICENSE("GPL");
368*4882a593Smuzhiyun MODULE_ALIAS("platform:" DRV_NAME);
369