diff options
author | Andres Salomon <dilinger@queued.net> | 2011-01-12 20:00:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 11:03:13 -0500 |
commit | 1b912c1bca5c162e611384fe7d39c916e081701a (patch) | |
tree | ae3a1c48954cec0a7f9d0b16207e9bfe6c4d22e6 | |
parent | 5f003feba2a8761d2ee7b367df5a0fe6b729dc8f (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>
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/cs5535-gpio.c | 52 | ||||
-rw-r--r-- | include/linux/cs5535.h | 2 |
3 files changed, 55 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 | ||
296 | config GPIO_CS5535 | 296 | config 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 | } |
145 | EXPORT_SYMBOL_GPL(cs5535_gpio_isset); | 146 | EXPORT_SYMBOL_GPL(cs5535_gpio_isset); |
146 | 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 | |||
147 | /* | 199 | /* |
148 | * Generic gpio_chip API support. | 200 | * Generic gpio_chip API support. |
149 | */ | 201 | */ |
diff --git a/include/linux/cs5535.h b/include/linux/cs5535.h index d5a1d4810b80..213cc50b5809 100644 --- a/include/linux/cs5535.h +++ b/include/linux/cs5535.h | |||
@@ -111,6 +111,8 @@ static inline int cs5535_has_vsa2(void) | |||
111 | void cs5535_gpio_set(unsigned offset, unsigned int reg); | 111 | void cs5535_gpio_set(unsigned offset, unsigned int reg); |
112 | void cs5535_gpio_clear(unsigned offset, unsigned int reg); | 112 | void cs5535_gpio_clear(unsigned offset, unsigned int reg); |
113 | int cs5535_gpio_isset(unsigned offset, unsigned int reg); | 113 | int cs5535_gpio_isset(unsigned offset, unsigned int reg); |
114 | int cs5535_gpio_set_irq(unsigned group, unsigned irq); | ||
115 | void cs5535_gpio_setup_event(unsigned offset, int pair, int pme); | ||
114 | 116 | ||
115 | /* MFGPTs */ | 117 | /* MFGPTs */ |
116 | 118 | ||