aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndres Salomon <dilinger@queued.net>2011-01-12 20:00:10 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 11:03:13 -0500
commit1b912c1bca5c162e611384fe7d39c916e081701a (patch)
treeae3a1c48954cec0a7f9d0b16207e9bfe6c4d22e6 /drivers
parent5f003feba2a8761d2ee7b367df5a0fe6b729dc8f (diff)
drivers/gpio/cs5535-gpio.c: add some additional cs5535-specific GPIO functionality
This adds (well, re-adds actually) handling for events/IRQs through cs5535 GPIOs. In the wild and wooly world of CS5535, setup_event() is for assigning an IRQ to a GPIO filter/event pair, and set_irq() sets up the pair to trigger IRQs. These should really only be used in highly platform-specific drivers (such as OLPC's DCON driver). Sadly, because set_irq() uses MSRs, this causes the driver to become X86-specific. Signed-off-by: Andres Salomon <dilinger@queued.net> Signed-off-by: Daniel Drake <dsd@laptop.org> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig2
-rw-r--r--drivers/gpio/cs5535-gpio.c52
2 files changed, 53 insertions, 1 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 082495bb08a7..bfa276a95411 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -295,7 +295,7 @@ comment "PCI GPIO expanders:"
295 295
296config GPIO_CS5535 296config GPIO_CS5535
297 tristate "AMD CS5535/CS5536 GPIO support" 297 tristate "AMD CS5535/CS5536 GPIO support"
298 depends on PCI && !CS5535_GPIO 298 depends on PCI && X86 && !CS5535_GPIO
299 help 299 help
300 The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that 300 The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
301 can be used for quite a number of things. The CS5535/6 is found on 301 can be used for quite a number of things. The CS5535/6 is found on
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
index d3e55a0ae92b..815d98b2c1ba 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/cs5535-gpio.c
@@ -15,6 +15,7 @@
15#include <linux/gpio.h> 15#include <linux/gpio.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/cs5535.h> 17#include <linux/cs5535.h>
18#include <asm/msr.h>
18 19
19#define DRV_NAME "cs5535-gpio" 20#define DRV_NAME "cs5535-gpio"
20#define GPIO_BAR 1 21#define GPIO_BAR 1
@@ -144,6 +145,57 @@ int cs5535_gpio_isset(unsigned offset, unsigned int reg)
144} 145}
145EXPORT_SYMBOL_GPL(cs5535_gpio_isset); 146EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
146 147
148int 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}
163EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
164
165void 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}
197EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
198
147/* 199/*
148 * Generic gpio_chip API support. 200 * Generic gpio_chip API support.
149 */ 201 */