Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b912c1b authored by Andres Salomon's avatar Andres Salomon Committed by Linus Torvalds
Browse files

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: default avatarAndres Salomon <dilinger@queued.net>
Signed-off-by: default avatarDaniel Drake <dsd@laptop.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5f003feb
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -295,7 +295,7 @@ comment "PCI GPIO expanders:"


config GPIO_CS5535
config GPIO_CS5535
	tristate "AMD CS5535/CS5536 GPIO support"
	tristate "AMD CS5535/CS5536 GPIO support"
	depends on PCI && !CS5535_GPIO
	depends on PCI && X86 && !CS5535_GPIO
	help
	help
	  The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
	  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
	  can be used for quite a number of things.  The CS5535/6 is found on
+52 −0
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/gpio.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/io.h>
#include <linux/cs5535.h>
#include <linux/cs5535.h>
#include <asm/msr.h>


#define DRV_NAME "cs5535-gpio"
#define DRV_NAME "cs5535-gpio"
#define GPIO_BAR 1
#define GPIO_BAR 1
@@ -144,6 +145,57 @@ int cs5535_gpio_isset(unsigned offset, unsigned int reg)
}
}
EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
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.
 * Generic gpio_chip API support.
 */
 */
+2 −0
Original line number Original line Diff line number Diff line
@@ -111,6 +111,8 @@ static inline int cs5535_has_vsa2(void)
void cs5535_gpio_set(unsigned offset, unsigned int reg);
void cs5535_gpio_set(unsigned offset, unsigned int reg);
void cs5535_gpio_clear(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_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 */
/* MFGPTs */