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