summaryrefslogtreecommitdiff
path: root/include/asm-avr32/arch-common/portmux-gpio.h
blob: 24943ecdbd4dfdcb362987a5f3a2ada56b8682a9 (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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*
 * Copyright (C) 2008 Atmel Corporation
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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 __AVR32_PORTMUX_GPIO_H__
#define __AVR32_PORTMUX_GPIO_H__

#include <asm/io.h>

/* Register offsets */
struct gpio_regs {
	u32	GPER;
	u32	GPERS;
	u32	GPERC;
	u32	GPERT;
	u32	PMR0;
	u32	PMR0S;
	u32	PMR0C;
	u32	PMR0T;
	u32	PMR1;
	u32	PMR1S;
	u32	PMR1C;
	u32	PMR1T;
	u32	__reserved0[4];
	u32	ODER;
	u32	ODERS;
	u32	ODERC;
	u32	ODERT;
	u32	OVR;
	u32	OVRS;
	u32	OVRC;
	u32	OVRT;
	u32	PVR;
	u32	__reserved_PVRS;
	u32	__reserved_PVRC;
	u32	__reserved_PVRT;
	u32	PUER;
	u32	PUERS;
	u32	PUERC;
	u32	PUERT;
	u32	PDER;
	u32	PDERS;
	u32	PDERC;
	u32	PDERT;
	u32	IER;
	u32	IERS;
	u32	IERC;
	u32	IERT;
	u32	IMR0;
	u32	IMR0S;
	u32	IMR0C;
	u32	IMR0T;
	u32	IMR1;
	u32	IMR1S;
	u32	IMR1C;
	u32	IMR1T;
	u32	GFER;
	u32	GFERS;
	u32	GFERC;
	u32	GFERT;
	u32	IFR;
	u32	__reserved_IFRS;
	u32	IFRC;
	u32	__reserved_IFRT;
	u32	ODMER;
	u32	ODMERS;
	u32	ODMERC;
	u32	ODMERT;
	u32	__reserved1[4];
	u32	ODCR0;
	u32	ODCR0S;
	u32	ODCR0C;
	u32	ODCR0T;
	u32	ODCR1;
	u32	ODCR1S;
	u32	ODCR1C;
	u32	ODCR1T;
	u32	__reserved2[4];
	u32	OSRR0;
	u32	OSRR0S;
	u32	OSRR0C;
	u32	OSRR0T;
	u32	__reserved3[8];
	u32	STER;
	u32	STERS;
	u32	STERC;
	u32	STERT;
	u32	__reserved4[35];
	u32	VERSION;
};

/* Register access macros */
#define gpio_readl(port, reg)						\
	__raw_readl(&((struct gpio_regs *)port)->reg)
#define gpio_writel(gpio, reg, value)					\
	__raw_writel(value, &((struct gpio_regs *)port)->reg)

/* Portmux API starts here. See doc/README.AVR32-port-muxing */

enum portmux_function {
	PORTMUX_FUNC_A,
	PORTMUX_FUNC_B,
	PORTMUX_FUNC_C,
	PORTMUX_FUNC_D,
};

#define PORTMUX_DIR_INPUT	(0 << 0)
#define PORTMUX_DIR_OUTPUT	(1 << 0)
#define PORTMUX_INIT_LOW	(0 << 1)
#define PORTMUX_INIT_HIGH	(1 << 1)
#define PORTMUX_PULL_UP		(1 << 2)
#define PORTMUX_PULL_DOWN	(2 << 2)
#define PORTMUX_BUSKEEPER	(3 << 2)
#define PORTMUX_DRIVE_MIN	(0 << 4)
#define PORTMUX_DRIVE_LOW	(1 << 4)
#define PORTMUX_DRIVE_HIGH	(2 << 4)
#define PORTMUX_DRIVE_MAX	(3 << 4)
#define PORTMUX_OPEN_DRAIN	(1 << 6)

void portmux_select_peripheral(void *port, unsigned long pin_mask,
		enum portmux_function func, unsigned long flags);
void portmux_select_gpio(void *port, unsigned long pin_mask,
		unsigned long flags);

/* Internal helper functions */

static inline void *gpio_pin_to_port(unsigned int pin)
{
	return (void *)GPIO_BASE + (pin >> 5) * 0x200;
}

static inline void __gpio_set_output_value(void *port, unsigned int pin,
		int value)
{
	if (value)
		gpio_writel(port, OVRS, 1 << pin);
	else
		gpio_writel(port, OVRC, 1 << pin);
}

static inline int __gpio_get_input_value(void *port, unsigned int pin)
{
	return (gpio_readl(port, PVR) >> pin) & 1;
}

void gpio_set_output_value(unsigned int pin, int value);
int gpio_get_input_value(unsigned int pin);

/* GPIO API starts here */

/*
 * GCC doesn't realize that the constant case is extremely trivial,
 * so we need to help it make the right decision by using
 * always_inline.
 */
__attribute__((always_inline))
static inline void gpio_set_value(unsigned int pin, int value)
{
	if (__builtin_constant_p(pin))
		__gpio_set_output_value(gpio_pin_to_port(pin),
				pin & 0x1f, value);
	else
		gpio_set_output_value(pin, value);
}

__attribute__((always_inline))
static inline int gpio_get_value(unsigned int pin)
{
	if (__builtin_constant_p(pin))
		return __gpio_get_input_value(gpio_pin_to_port(pin),
				pin & 0x1f);
	else
		return gpio_get_input_value(pin);
}

#endif /* __AVR32_PORTMUX_GPIO_H__ */