SELinux: Use dentry name in new object labeling
[pohmelfs.git] / drivers / gpio / cs5535-gpio.c
blobd3e55a0ae92be02e5f46ea7d6f7f82c87e75c807
1 /*
2 * AMD CS5535/CS5536 GPIO driver
3 * Copyright (C) 2006 Advanced Micro Devices, Inc.
4 * Copyright (C) 2007-2009 Andres Salomon <dilinger@collabora.co.uk>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public License
8 * as published by the Free Software Foundation.
9 */
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/module.h>
14 #include <linux/pci.h>
15 #include <linux/gpio.h>
16 #include <linux/io.h>
17 #include <linux/cs5535.h>
19 #define DRV_NAME "cs5535-gpio"
20 #define GPIO_BAR 1
23 * Some GPIO pins
24 * 31-29,23 : reserved (always mask out)
25 * 28 : Power Button
26 * 26 : PME#
27 * 22-16 : LPC
28 * 14,15 : SMBus
29 * 9,8 : UART1
30 * 7 : PCI INTB
31 * 3,4 : UART2/DDC
32 * 2 : IDE_IRQ0
33 * 1 : AC_BEEP
34 * 0 : PCI INTA
36 * If a mask was not specified, allow all except
37 * reserved and Power Button
39 #define GPIO_DEFAULT_MASK 0x0F7FFFFF
41 static ulong mask = GPIO_DEFAULT_MASK;
42 module_param_named(mask, mask, ulong, 0444);
43 MODULE_PARM_DESC(mask, "GPIO channel mask.");
45 static struct cs5535_gpio_chip {
46 struct gpio_chip chip;
47 resource_size_t base;
49 struct pci_dev *pdev;
50 spinlock_t lock;
51 } cs5535_gpio_chip;
54 * The CS5535/CS5536 GPIOs support a number of extra features not defined
55 * by the gpio_chip API, so these are exported. For a full list of the
56 * registers, see include/linux/cs5535.h.
59 static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
60 unsigned int reg)
62 unsigned long addr = chip->base + 0x80 + reg;
65 * According to the CS5536 errata (#36), after suspend
66 * a write to the high bank GPIO register will clear all
67 * non-selected bits; the recommended workaround is a
68 * read-modify-write operation.
70 * Don't apply this errata to the edge status GPIOs, as writing
71 * to their lower bits will clear them.
73 if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
74 if (val & 0xffff)
75 val |= (inl(addr) & 0xffff); /* ignore the high bits */
76 else
77 val |= (inl(addr) ^ (val >> 16));
79 outl(val, addr);
82 static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
83 unsigned int reg)
85 if (offset < 16)
86 /* low bank register */
87 outl(1 << offset, chip->base + reg);
88 else
89 /* high bank register */
90 errata_outl(chip, 1 << (offset - 16), reg);
93 void cs5535_gpio_set(unsigned offset, unsigned int reg)
95 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
96 unsigned long flags;
98 spin_lock_irqsave(&chip->lock, flags);
99 __cs5535_gpio_set(chip, offset, reg);
100 spin_unlock_irqrestore(&chip->lock, flags);
102 EXPORT_SYMBOL_GPL(cs5535_gpio_set);
104 static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
105 unsigned int reg)
107 if (offset < 16)
108 /* low bank register */
109 outl(1 << (offset + 16), chip->base + reg);
110 else
111 /* high bank register */
112 errata_outl(chip, 1 << offset, reg);
115 void cs5535_gpio_clear(unsigned offset, unsigned int reg)
117 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
118 unsigned long flags;
120 spin_lock_irqsave(&chip->lock, flags);
121 __cs5535_gpio_clear(chip, offset, reg);
122 spin_unlock_irqrestore(&chip->lock, flags);
124 EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
126 int cs5535_gpio_isset(unsigned offset, unsigned int reg)
128 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
129 unsigned long flags;
130 long val;
132 spin_lock_irqsave(&chip->lock, flags);
133 if (offset < 16)
134 /* low bank register */
135 val = inl(chip->base + reg);
136 else {
137 /* high bank register */
138 val = inl(chip->base + 0x80 + reg);
139 offset -= 16;
141 spin_unlock_irqrestore(&chip->lock, flags);
143 return (val & (1 << offset)) ? 1 : 0;
145 EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
148 * Generic gpio_chip API support.
151 static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
153 struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
154 unsigned long flags;
156 spin_lock_irqsave(&chip->lock, flags);
158 /* check if this pin is available */
159 if ((mask & (1 << offset)) == 0) {
160 dev_info(&chip->pdev->dev,
161 "pin %u is not available (check mask)\n", offset);
162 spin_unlock_irqrestore(&chip->lock, flags);
163 return -EINVAL;
166 /* disable output aux 1 & 2 on this pin */
167 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
168 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
170 /* disable input aux 1 on this pin */
171 __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
173 spin_unlock_irqrestore(&chip->lock, flags);
175 return 0;
178 static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
180 return cs5535_gpio_isset(offset, GPIO_READ_BACK);
183 static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
185 if (val)
186 cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
187 else
188 cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
191 static int chip_direction_input(struct gpio_chip *c, unsigned offset)
193 struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
194 unsigned long flags;
196 spin_lock_irqsave(&chip->lock, flags);
197 __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
198 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
199 spin_unlock_irqrestore(&chip->lock, flags);
201 return 0;
204 static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
206 struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
207 unsigned long flags;
209 spin_lock_irqsave(&chip->lock, flags);
211 __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
212 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
213 if (val)
214 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
215 else
216 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
218 spin_unlock_irqrestore(&chip->lock, flags);
220 return 0;
223 static const char * const cs5535_gpio_names[] = {
224 "GPIO0", "GPIO1", "GPIO2", "GPIO3",
225 "GPIO4", "GPIO5", "GPIO6", "GPIO7",
226 "GPIO8", "GPIO9", "GPIO10", "GPIO11",
227 "GPIO12", "GPIO13", "GPIO14", "GPIO15",
228 "GPIO16", "GPIO17", "GPIO18", "GPIO19",
229 "GPIO20", "GPIO21", "GPIO22", NULL,
230 "GPIO24", "GPIO25", "GPIO26", "GPIO27",
231 "GPIO28", NULL, NULL, NULL,
234 static struct cs5535_gpio_chip cs5535_gpio_chip = {
235 .chip = {
236 .owner = THIS_MODULE,
237 .label = DRV_NAME,
239 .base = 0,
240 .ngpio = 32,
241 .names = cs5535_gpio_names,
242 .request = chip_gpio_request,
244 .get = chip_gpio_get,
245 .set = chip_gpio_set,
247 .direction_input = chip_direction_input,
248 .direction_output = chip_direction_output,
252 static int __init cs5535_gpio_probe(struct pci_dev *pdev,
253 const struct pci_device_id *pci_id)
255 int err;
256 ulong mask_orig = mask;
258 /* There are two ways to get the GPIO base address; one is by
259 * fetching it from MSR_LBAR_GPIO, the other is by reading the
260 * PCI BAR info. The latter method is easier (especially across
261 * different architectures), so we'll stick with that for now. If
262 * it turns out to be unreliable in the face of crappy BIOSes, we
263 * can always go back to using MSRs.. */
265 err = pci_enable_device_io(pdev);
266 if (err) {
267 dev_err(&pdev->dev, "can't enable device IO\n");
268 goto done;
271 err = pci_request_region(pdev, GPIO_BAR, DRV_NAME);
272 if (err) {
273 dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
274 goto done;
277 /* set up the driver-specific struct */
278 cs5535_gpio_chip.base = pci_resource_start(pdev, GPIO_BAR);
279 cs5535_gpio_chip.pdev = pdev;
280 spin_lock_init(&cs5535_gpio_chip.lock);
282 dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR,
283 (unsigned long long) cs5535_gpio_chip.base);
285 /* mask out reserved pins */
286 mask &= 0x1F7FFFFF;
288 /* do not allow pin 28, Power Button, as there's special handling
289 * in the PMC needed. (note 12, p. 48) */
290 mask &= ~(1 << 28);
292 if (mask_orig != mask)
293 dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
294 mask_orig, mask);
296 /* finally, register with the generic GPIO API */
297 err = gpiochip_add(&cs5535_gpio_chip.chip);
298 if (err)
299 goto release_region;
301 dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n");
302 return 0;
304 release_region:
305 pci_release_region(pdev, GPIO_BAR);
306 done:
307 return err;
310 static void __exit cs5535_gpio_remove(struct pci_dev *pdev)
312 int err;
314 err = gpiochip_remove(&cs5535_gpio_chip.chip);
315 if (err) {
316 /* uhh? */
317 dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
319 pci_release_region(pdev, GPIO_BAR);
322 static struct pci_device_id cs5535_gpio_pci_tbl[] = {
323 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
324 { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
325 { 0, },
327 MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl);
330 * We can't use the standard PCI driver registration stuff here, since
331 * that allows only one driver to bind to each PCI device (and we want
332 * multiple drivers to be able to bind to the device). Instead, manually
333 * scan for the PCI device, request a single region, and keep track of the
334 * devices that we're using.
337 static int __init cs5535_gpio_scan_pci(void)
339 struct pci_dev *pdev;
340 int err = -ENODEV;
341 int i;
343 for (i = 0; i < ARRAY_SIZE(cs5535_gpio_pci_tbl); i++) {
344 pdev = pci_get_device(cs5535_gpio_pci_tbl[i].vendor,
345 cs5535_gpio_pci_tbl[i].device, NULL);
346 if (pdev) {
347 err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]);
348 if (err)
349 pci_dev_put(pdev);
351 /* we only support a single CS5535/6 southbridge */
352 break;
356 return err;
359 static void __exit cs5535_gpio_free_pci(void)
361 cs5535_gpio_remove(cs5535_gpio_chip.pdev);
362 pci_dev_put(cs5535_gpio_chip.pdev);
365 static int __init cs5535_gpio_init(void)
367 return cs5535_gpio_scan_pci();
370 static void __exit cs5535_gpio_exit(void)
372 cs5535_gpio_free_pci();
375 module_init(cs5535_gpio_init);
376 module_exit(cs5535_gpio_exit);
378 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
379 MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
380 MODULE_LICENSE("GPL");