Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 137188
b: refs/heads/master
c: a58fbcd
h: refs/heads/master
v: v3
  • Loading branch information
Eric Miao committed Mar 9, 2009
1 parent 53c196b commit d624345
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 99 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7ebc8d56f407184a457dd5fc739cf39e423a25aa
refs/heads/master: a58fbcd8ad17ddaa0c7aadbbbd20de4ebc807fa4
6 changes: 2 additions & 4 deletions trunk/arch/arm/mach-pxa/generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
* published by the Free Software Foundation.
*/

typedef int (*set_wake_t)(unsigned int, unsigned int);

struct sys_timer;

extern struct sys_timer pxa_timer;
extern void __init pxa_init_irq(int irq_nr, set_wake_t fn);
extern void __init pxa_init_gpio(int gpio_nr, set_wake_t fn);
extern void __init pxa_init_irq(int irq_nr,
int (*set_wake)(unsigned int, unsigned int));
extern void __init pxa25x_init_irq(void);
extern void __init pxa27x_init_irq(void);
extern void __init pxa3xx_init_irq(void);
Expand Down
113 changes: 25 additions & 88 deletions trunk/arch/arm/mach-pxa/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,6 @@ struct pxa_gpio_chip {

int pxa_last_gpio;

#ifdef CONFIG_CPU_PXA26x
/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
* as well as their Alternate Function value being '1' for GPIO in GAFRx.
*/
static int __gpio_is_inverted(unsigned gpio)
{
return cpu_is_pxa25x() && gpio > 85;
}
#else
#define __gpio_is_inverted(gpio) (0)
#endif

/*
* Configure pins for GPIO or other functions
*/
Expand Down Expand Up @@ -185,6 +173,20 @@ static struct pxa_gpio_chip pxa_gpio_chip[] = {
#endif
};

static void __init pxa_init_gpio_chip(int gpio_nr)
{
int i, gpio;

/* add a GPIO chip for each register bank.
* the last PXA25x register only contains 21 GPIOs
*/
for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) {
if (gpio + 32 > gpio_nr)
pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio;
gpiochip_add(&pxa_gpio_chip[i].chip);
}
}

/*
* PXA GPIO edge detection for IRQs:
* IRQs are generated on Falling-Edge, Rising-Edge, or both.
Expand All @@ -195,27 +197,6 @@ static unsigned long GPIO_IRQ_rising_edge[4];
static unsigned long GPIO_IRQ_falling_edge[4];
static unsigned long GPIO_IRQ_mask[4];

/*
* On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
* function of a GPIO, and GPDRx cannot be altered once configured. It
* is attributed as "occupied" here (I know this terminology isn't
* accurate, you are welcome to propose a better one :-)
*/
static int __gpio_is_occupied(unsigned gpio)
{
if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
int dir = GPDR(gpio) & GPIO_bit(gpio);

if (__gpio_is_inverted(gpio))
return af != 1 || dir == 0;
else
return af != 0 || dir != 0;
}

return 0;
}

static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{
int gpio, idx;
Expand Down Expand Up @@ -261,33 +242,6 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
return 0;
}

/*
* GPIO IRQs must be acknowledged. This is for GPIO 0 and 1.
*/

static void pxa_ack_low_gpio(unsigned int irq)
{
GEDR0 = (1 << (irq - IRQ_GPIO0));
}

static void pxa_mask_low_gpio(unsigned int irq)
{
ICMR &= ~(1 << (irq - PXA_IRQ(0)));
}

static void pxa_unmask_low_gpio(unsigned int irq)
{
ICMR |= 1 << (irq - PXA_IRQ(0));
}

static struct irq_chip pxa_low_gpio_chip = {
.name = "GPIO-l",
.ack = pxa_ack_low_gpio,
.mask = pxa_mask_low_gpio,
.unmask = pxa_unmask_low_gpio,
.set_type = pxa_gpio_irq_type,
};

/*
* Demux handler for GPIO>=2 edge detect interrupts
*/
Expand Down Expand Up @@ -352,48 +306,31 @@ static struct irq_chip pxa_muxed_gpio_chip = {
.set_type = pxa_gpio_irq_type,
};

void __init pxa_init_gpio(int gpio_nr, set_wake_t fn)
void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
{
int irq, i, gpio;
int irq, i;

pxa_last_gpio = gpio_nr - 1;
pxa_last_gpio = end;

/* clear all GPIO edge detects */
for (i = 0; i < gpio_nr; i += 32) {
GFER(i) = 0;
GRER(i) = 0;
GEDR(i) = GEDR(i);
for (i = start; i <= end; i += 32) {
GFER(i) &= ~GPIO_IRQ_mask[i];
GRER(i) &= ~GPIO_IRQ_mask[i];
GEDR(i) = GPIO_IRQ_mask[i];
}

/* GPIO 0 and 1 must have their mask bit always set */
GPIO_IRQ_mask[0] = 3;

for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
set_irq_chip(irq, &pxa_low_gpio_chip);
set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}

for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
set_irq_chip(irq, &pxa_muxed_gpio_chip);
set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}

/* Install handler for GPIO>=2 edge detect interrupts */
set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);

pxa_low_gpio_chip.set_wake = fn;
set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler);
pxa_muxed_gpio_chip.set_wake = fn;

/* add a GPIO chip for each register bank.
* the last PXA25x register only contains 21 GPIOs
*/
for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) {
if (gpio + 32 > gpio_nr)
pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio;
gpiochip_add(&pxa_gpio_chip[i].chip);
}
/* Initialize GPIO chips */
pxa_init_gpio_chip(end + 1);
}

#ifdef CONFIG_PM
Expand Down
38 changes: 36 additions & 2 deletions trunk/arch/arm/mach-pxa/include/mach/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,44 @@ static inline void gpio_set_value(unsigned gpio, int value)
}
}

#define gpio_cansleep __gpio_cansleep

#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq(gpio) IRQ_GPIO(gpio)
#define irq_to_gpio(irq) IRQ_TO_GPIO(irq)


#ifdef CONFIG_CPU_PXA26x
/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
* as well as their Alternate Function value being '1' for GPIO in GAFRx.
*/
static inline int __gpio_is_inverted(unsigned gpio)
{
return cpu_is_pxa25x() && gpio > 85;
}
#else
static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
#endif

/*
* On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
* function of a GPIO, and GPDRx cannot be altered once configured. It
* is attributed as "occupied" here (I know this terminology isn't
* accurate, you are welcome to propose a better one :-)
*/
static inline int __gpio_is_occupied(unsigned gpio)
{
if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
int dir = GPDR(gpio) & GPIO_bit(gpio);

if (__gpio_is_inverted(gpio))
return af != 1 || dir == 0;
else
return af != 0 || dir != 0;
} else
return GPDR(gpio) & GPIO_bit(gpio);
}

typedef int (*set_wake_t)(unsigned int irq, unsigned int on);

extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
#endif
68 changes: 68 additions & 0 deletions trunk/arch/arm/mach-pxa/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <mach/pxa-regs.h>
#include <mach/gpio.h>

#include "generic.h"

Expand Down Expand Up @@ -51,6 +52,72 @@ static struct irq_chip pxa_internal_irq_chip = {
.unmask = pxa_unmask_irq,
};

/*
* GPIO IRQs for GPIO 0 and 1
*/
static int pxa_set_low_gpio_type(unsigned int irq, unsigned int type)
{
int gpio = irq - IRQ_GPIO0;

if (__gpio_is_occupied(gpio)) {
pr_err("%s failed: GPIO is configured\n", __func__);
return -EINVAL;
}

if (type & IRQ_TYPE_EDGE_RISING)
GRER0 |= GPIO_bit(gpio);
else
GRER0 &= ~GPIO_bit(gpio);

if (type & IRQ_TYPE_EDGE_FALLING)
GFER0 |= GPIO_bit(gpio);
else
GFER0 &= ~GPIO_bit(gpio);

return 0;
}

static void pxa_ack_low_gpio(unsigned int irq)
{
GEDR0 = (1 << (irq - IRQ_GPIO0));
}

static void pxa_mask_low_gpio(unsigned int irq)
{
ICMR &= ~(1 << (irq - PXA_IRQ(0)));
}

static void pxa_unmask_low_gpio(unsigned int irq)
{
ICMR |= 1 << (irq - PXA_IRQ(0));
}

static struct irq_chip pxa_low_gpio_chip = {
.name = "GPIO-l",
.ack = pxa_ack_low_gpio,
.mask = pxa_mask_low_gpio,
.unmask = pxa_unmask_low_gpio,
.set_type = pxa_set_low_gpio_type,
};

static void __init pxa_init_low_gpio_irq(set_wake_t fn)
{
int irq;

/* clear edge detection on GPIO 0 and 1 */
GFER0 &= ~0x3;
GRER0 &= ~0x3;
GEDR0 = 0x3;

for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
set_irq_chip(irq, &pxa_low_gpio_chip);
set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID);
}

pxa_low_gpio_chip.set_wake = fn;
}

void __init pxa_init_irq(int irq_nr, set_wake_t fn)
{
int irq;
Expand All @@ -72,6 +139,7 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn)
}

pxa_internal_irq_chip.set_wake = fn;
pxa_init_low_gpio_irq(fn);
}

#ifdef CONFIG_PM
Expand Down
5 changes: 3 additions & 2 deletions trunk/arch/arm/mach-pxa/pxa25x.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
#include <mach/pxa25x.h>
#include <mach/reset.h>
#include <mach/pm.h>
Expand Down Expand Up @@ -308,14 +309,14 @@ static int pxa25x_set_wake(unsigned int irq, unsigned int on)
void __init pxa25x_init_irq(void)
{
pxa_init_irq(32, pxa25x_set_wake);
pxa_init_gpio(85, pxa25x_set_wake);
pxa_init_gpio(IRQ_GPIO_2_x, 2, 84, pxa25x_set_wake);
}

#ifdef CONFIG_CPU_PXA26x
void __init pxa26x_init_irq(void)
{
pxa_init_irq(32, pxa25x_set_wake);
pxa_init_gpio(90, pxa25x_set_wake);
pxa_init_gpio(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake);
}
#endif

Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/arm/mach-pxa/pxa27x.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <mach/hardware.h>
#include <asm/irq.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
#include <mach/pxa27x.h>
#include <mach/reset.h>
#include <mach/ohci.h>
Expand Down Expand Up @@ -330,7 +331,7 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on)
void __init pxa27x_init_irq(void)
{
pxa_init_irq(34, pxa27x_set_wake);
pxa_init_gpio(121, pxa27x_set_wake);
pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake);
}

/*
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/arm/mach-pxa/pxa3xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/sysdev.h>

#include <mach/hardware.h>
#include <mach/gpio.h>
#include <mach/pxa3xx-regs.h>
#include <mach/reset.h>
#include <mach/ohci.h>
Expand Down Expand Up @@ -538,7 +539,7 @@ void __init pxa3xx_init_irq(void)
__asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));

pxa_init_irq(56, pxa3xx_set_wake);
pxa_init_gpio(128, NULL);
pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
}

/*
Expand Down

0 comments on commit d624345

Please sign in to comment.