mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 10:01:41 +00:00
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>
This commit is contained in:
parent
5f003feba2
commit
1b912c1bca
@ -295,7 +295,7 @@ comment "PCI GPIO expanders:"
|
||||
|
||||
config GPIO_CS5535
|
||||
tristate "AMD CS5535/CS5536 GPIO support"
|
||||
depends on PCI && !CS5535_GPIO
|
||||
depends on PCI && X86 && !CS5535_GPIO
|
||||
help
|
||||
The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
|
||||
can be used for quite a number of things. The CS5535/6 is found on
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/cs5535.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
#define DRV_NAME "cs5535-gpio"
|
||||
#define GPIO_BAR 1
|
||||
@ -144,6 +145,57 @@ int cs5535_gpio_isset(unsigned offset, unsigned int reg)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
|
||||
|
||||
int cs5535_gpio_set_irq(unsigned group, unsigned irq)
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
|
||||
if (group > 7 || irq > 15)
|
||||
return -EINVAL;
|
||||
|
||||
rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
|
||||
|
||||
lo &= ~(0xF << (group * 4));
|
||||
lo |= (irq & 0xF) << (group * 4);
|
||||
|
||||
wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq);
|
||||
|
||||
void cs5535_gpio_setup_event(unsigned offset, int pair, int pme)
|
||||
{
|
||||
struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
|
||||
uint32_t shift = (offset % 8) * 4;
|
||||
unsigned long flags;
|
||||
uint32_t val;
|
||||
|
||||
if (offset >= 24)
|
||||
offset = GPIO_MAP_W;
|
||||
else if (offset >= 16)
|
||||
offset = GPIO_MAP_Z;
|
||||
else if (offset >= 8)
|
||||
offset = GPIO_MAP_Y;
|
||||
else
|
||||
offset = GPIO_MAP_X;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
val = inl(chip->base + offset);
|
||||
|
||||
/* Clear whatever was there before */
|
||||
val &= ~(0xF << shift);
|
||||
|
||||
/* Set the new value */
|
||||
val |= ((pair & 7) << shift);
|
||||
|
||||
/* Set the PME bit if this is a PME event */
|
||||
if (pme)
|
||||
val |= (1 << (shift + 3));
|
||||
|
||||
outl(val, chip->base + offset);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
|
||||
|
||||
/*
|
||||
* Generic gpio_chip API support.
|
||||
*/
|
||||
|
@ -111,6 +111,8 @@ static inline int cs5535_has_vsa2(void)
|
||||
void cs5535_gpio_set(unsigned offset, unsigned int reg);
|
||||
void cs5535_gpio_clear(unsigned offset, unsigned int reg);
|
||||
int cs5535_gpio_isset(unsigned offset, unsigned int reg);
|
||||
int cs5535_gpio_set_irq(unsigned group, unsigned irq);
|
||||
void cs5535_gpio_setup_event(unsigned offset, int pair, int pme);
|
||||
|
||||
/* MFGPTs */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user