aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/include/mach/gpio.h
blob: c72c89a2285e4582c8b587bcacefac01b0831e60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
 * arch/arm/mach-pxa/include/mach/gpio.h
 *
 * PXA GPIO wrappers for arch-neutral GPIO calls
 *
 * Written by Philipp Zabel <philipp.zabel@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#ifndef __ASM_ARCH_PXA_GPIO_H
#define __ASM_ARCH_PXA_GPIO_H

#include <mach/irqs.h>
#include <mach/hardware.h>
#include <asm-generic/gpio.h>

#define GPIO_REGS_VIRT	io_p2v(0x40E00000)

#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))

/* GPIO Pin Level Registers */
#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)

/* GPIO Pin Direction Registers */
#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)

/* GPIO Pin Output Set Registers */
#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)

/* GPIO Pin Output Clear Registers */
#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)

/* GPIO Rising Edge Detect Registers */
#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)

/* GPIO Falling Edge Detect Registers */
#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)

/* GPIO Edge Detect Status Registers */
#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)

/* GPIO Alternate Function Select Registers */
#define GAFR0_L		GPIO_REG(0x0054)
#define GAFR0_U		GPIO_REG(0x0058)
#define GAFR1_L		GPIO_REG(0x005C)
#define GAFR1_U		GPIO_REG(0x0060)
#define GAFR2_L		GPIO_REG(0x0064)
#define GAFR2_U		GPIO_REG(0x0068)
#define GAFR3_L		GPIO_REG(0x006C)
#define GAFR3_U		GPIO_REG(0x0070)

/* More handy macros.  The argument is a literal GPIO number. */

#define GPIO_bit(x)	(1 << ((x) & 0x1f))

#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))


/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
 * Those cases currently cause holes in the GPIO number space, the
 * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
 */
extern int pxa_last_gpio;

#define NR_BUILTIN_GPIO 128

static inline int gpio_get_value(unsigned gpio)
{
	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO))
		return GPLR(gpio) & GPIO_bit(gpio);
	else
		return __gpio_get_value(gpio);
}

static inline void gpio_set_value(unsigned gpio, int value)
{
	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) {
		if (value)
			GPSR(gpio) = GPIO_bit(gpio);
		else
			GPCR(gpio) = GPIO_bit(gpio);
	} else {
		__gpio_set_value(gpio, value);
	}
}

#define gpio_cansleep		__gpio_cansleep
#define gpio_to_bank(gpio)	((gpio) >> 5)
#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