diff options
Diffstat (limited to 'arch/mips/include')
-rw-r--r-- | arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h new file mode 100644 index 000000000000..156f320c69e7 --- /dev/null +++ b/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Macros for external SMP-safe access to the PMC MSP71xx reference | ||
4 | * board GPIO pins | ||
5 | * | ||
6 | * Copyright 2010 PMC-Sierra, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
14 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
15 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
16 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
17 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
18 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
19 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License along | ||
25 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
26 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | */ | ||
28 | |||
29 | #ifndef __MSP_GPIO_MACROS_H__ | ||
30 | #define __MSP_GPIO_MACROS_H__ | ||
31 | |||
32 | #include <msp_regops.h> | ||
33 | #include <msp_regs.h> | ||
34 | |||
35 | #ifdef CONFIG_PMC_MSP7120_GW | ||
36 | #define MSP_NUM_GPIOS 20 | ||
37 | #else | ||
38 | #define MSP_NUM_GPIOS 28 | ||
39 | #endif | ||
40 | |||
41 | /* -- GPIO Enumerations -- */ | ||
42 | enum msp_gpio_data { | ||
43 | MSP_GPIO_LO = 0, | ||
44 | MSP_GPIO_HI = 1, | ||
45 | MSP_GPIO_NONE, /* Special - Means pin is out of range */ | ||
46 | MSP_GPIO_TOGGLE, /* Special - Sets pin to opposite */ | ||
47 | }; | ||
48 | |||
49 | enum msp_gpio_mode { | ||
50 | MSP_GPIO_INPUT = 0x0, | ||
51 | /* MSP_GPIO_ INTERRUPT = 0x1, Not supported yet */ | ||
52 | MSP_GPIO_UART_INPUT = 0x2, /* Only GPIO 4 or 5 */ | ||
53 | MSP_GPIO_OUTPUT = 0x8, | ||
54 | MSP_GPIO_UART_OUTPUT = 0x9, /* Only GPIO 2 or 3 */ | ||
55 | MSP_GPIO_PERIF_TIMERA = 0x9, /* Only GPIO 0 or 1 */ | ||
56 | MSP_GPIO_PERIF_TIMERB = 0xa, /* Only GPIO 0 or 1 */ | ||
57 | MSP_GPIO_UNKNOWN = 0xb, /* No such GPIO or mode */ | ||
58 | }; | ||
59 | |||
60 | /* -- Static Tables -- */ | ||
61 | |||
62 | /* Maps pins to data register */ | ||
63 | static volatile u32 * const MSP_GPIO_DATA_REGISTER[] = { | ||
64 | /* GPIO 0 and 1 on the first register */ | ||
65 | GPIO_DATA1_REG, GPIO_DATA1_REG, | ||
66 | /* GPIO 2, 3, 4, and 5 on the second register */ | ||
67 | GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG, | ||
68 | /* GPIO 6, 7, 8, and 9 on the third register */ | ||
69 | GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG, | ||
70 | /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */ | ||
71 | GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG, | ||
72 | GPIO_DATA4_REG, GPIO_DATA4_REG, | ||
73 | /* GPIO 16 - 23 on the first strange EXTENDED register */ | ||
74 | EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, | ||
75 | EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, | ||
76 | EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, | ||
77 | /* GPIO 24 - 27 on the second strange EXTENDED register */ | ||
78 | EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, | ||
79 | EXTENDED_GPIO2_REG, | ||
80 | }; | ||
81 | |||
82 | /* Maps pins to mode register */ | ||
83 | static volatile u32 * const MSP_GPIO_MODE_REGISTER[] = { | ||
84 | /* GPIO 0 and 1 on the first register */ | ||
85 | GPIO_CFG1_REG, GPIO_CFG1_REG, | ||
86 | /* GPIO 2, 3, 4, and 5 on the second register */ | ||
87 | GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG, | ||
88 | /* GPIO 6, 7, 8, and 9 on the third register */ | ||
89 | GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG, | ||
90 | /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */ | ||
91 | GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG, | ||
92 | GPIO_CFG4_REG, GPIO_CFG4_REG, | ||
93 | /* GPIO 16 - 23 on the first strange EXTENDED register */ | ||
94 | EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, | ||
95 | EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, | ||
96 | EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, | ||
97 | /* GPIO 24 - 27 on the second strange EXTENDED register */ | ||
98 | EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, | ||
99 | EXTENDED_GPIO2_REG, | ||
100 | }; | ||
101 | |||
102 | /* Maps 'basic' pins to relative offset from 0 per register */ | ||
103 | static int MSP_GPIO_OFFSET[] = { | ||
104 | /* GPIO 0 and 1 on the first register */ | ||
105 | 0, 0, | ||
106 | /* GPIO 2, 3, 4, and 5 on the second register */ | ||
107 | 2, 2, 2, 2, | ||
108 | /* GPIO 6, 7, 8, and 9 on the third register */ | ||
109 | 6, 6, 6, 6, | ||
110 | /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */ | ||
111 | 10, 10, 10, 10, 10, 10, | ||
112 | }; | ||
113 | |||
114 | /* Maps MODE to allowed pin mask */ | ||
115 | static unsigned int MSP_GPIO_MODE_ALLOWED[] = { | ||
116 | 0xffffffff, /* Mode 0 - INPUT */ | ||
117 | 0x00000, /* Mode 1 - INTERRUPT */ | ||
118 | 0x00030, /* Mode 2 - UART_INPUT (GPIO 4, 5)*/ | ||
119 | 0, 0, 0, 0, 0, /* Modes 3, 4, 5, 6, and 7 are reserved */ | ||
120 | 0xffffffff, /* Mode 8 - OUTPUT */ | ||
121 | 0x0000f, /* Mode 9 - UART_OUTPUT/ | ||
122 | PERF_TIMERA (GPIO 0, 1, 2, 3) */ | ||
123 | 0x00003, /* Mode a - PERF_TIMERB (GPIO 0, 1) */ | ||
124 | 0x00000, /* Mode b - Not really a mode! */ | ||
125 | }; | ||
126 | |||
127 | /* -- Bit masks -- */ | ||
128 | |||
129 | /* This gives you the 'register relative offset gpio' number */ | ||
130 | #define OFFSET_GPIO_NUMBER(gpio) (gpio - MSP_GPIO_OFFSET[gpio]) | ||
131 | |||
132 | /* These take the 'register relative offset gpio' number */ | ||
133 | #define BASIC_DATA_REG_MASK(ogpio) (1 << ogpio) | ||
134 | #define BASIC_MODE_REG_VALUE(mode, ogpio) \ | ||
135 | (mode << BASIC_MODE_REG_SHIFT(ogpio)) | ||
136 | #define BASIC_MODE_REG_MASK(ogpio) \ | ||
137 | BASIC_MODE_REG_VALUE(0xf, ogpio) | ||
138 | #define BASIC_MODE_REG_SHIFT(ogpio) (ogpio * 4) | ||
139 | #define BASIC_MODE_REG_FROM_REG(data, ogpio) \ | ||
140 | ((data & BASIC_MODE_REG_MASK(ogpio)) >> BASIC_MODE_REG_SHIFT(ogpio)) | ||
141 | |||
142 | /* These take the actual GPIO number (0 through 15) */ | ||
143 | #define BASIC_DATA_MASK(gpio) \ | ||
144 | BASIC_DATA_REG_MASK(OFFSET_GPIO_NUMBER(gpio)) | ||
145 | #define BASIC_MODE_MASK(gpio) \ | ||
146 | BASIC_MODE_REG_MASK(OFFSET_GPIO_NUMBER(gpio)) | ||
147 | #define BASIC_MODE(mode, gpio) \ | ||
148 | BASIC_MODE_REG_VALUE(mode, OFFSET_GPIO_NUMBER(gpio)) | ||
149 | #define BASIC_MODE_SHIFT(gpio) \ | ||
150 | BASIC_MODE_REG_SHIFT(OFFSET_GPIO_NUMBER(gpio)) | ||
151 | #define BASIC_MODE_FROM_REG(data, gpio) \ | ||
152 | BASIC_MODE_REG_FROM_REG(data, OFFSET_GPIO_NUMBER(gpio)) | ||
153 | |||
154 | /* | ||
155 | * Each extended GPIO register is 32 bits long and is responsible for up to | ||
156 | * eight GPIOs. The least significant 16 bits contain the set and clear bit | ||
157 | * pair for each of the GPIOs. The most significant 16 bits contain the | ||
158 | * disable and enable bit pair for each of the GPIOs. For example, the | ||
159 | * extended GPIO reg for GPIOs 16-23 is as follows: | ||
160 | * | ||
161 | * 31: GPIO23_DISABLE | ||
162 | * ... | ||
163 | * 19: GPIO17_DISABLE | ||
164 | * 18: GPIO17_ENABLE | ||
165 | * 17: GPIO16_DISABLE | ||
166 | * 16: GPIO16_ENABLE | ||
167 | * ... | ||
168 | * 3: GPIO17_SET | ||
169 | * 2: GPIO17_CLEAR | ||
170 | * 1: GPIO16_SET | ||
171 | * 0: GPIO16_CLEAR | ||
172 | */ | ||
173 | |||
174 | /* This gives the 'register relative offset gpio' number */ | ||
175 | #define EXTENDED_OFFSET_GPIO(gpio) (gpio < 24 ? gpio - 16 : gpio - 24) | ||
176 | |||
177 | /* These take the 'register relative offset gpio' number */ | ||
178 | #define EXTENDED_REG_DISABLE(ogpio) (0x2 << ((ogpio * 2) + 16)) | ||
179 | #define EXTENDED_REG_ENABLE(ogpio) (0x1 << ((ogpio * 2) + 16)) | ||
180 | #define EXTENDED_REG_SET(ogpio) (0x2 << (ogpio * 2)) | ||
181 | #define EXTENDED_REG_CLR(ogpio) (0x1 << (ogpio * 2)) | ||
182 | |||
183 | /* These take the actual GPIO number (16 through 27) */ | ||
184 | #define EXTENDED_DISABLE(gpio) \ | ||
185 | EXTENDED_REG_DISABLE(EXTENDED_OFFSET_GPIO(gpio)) | ||
186 | #define EXTENDED_ENABLE(gpio) \ | ||
187 | EXTENDED_REG_ENABLE(EXTENDED_OFFSET_GPIO(gpio)) | ||
188 | #define EXTENDED_SET(gpio) \ | ||
189 | EXTENDED_REG_SET(EXTENDED_OFFSET_GPIO(gpio)) | ||
190 | #define EXTENDED_CLR(gpio) \ | ||
191 | EXTENDED_REG_CLR(EXTENDED_OFFSET_GPIO(gpio)) | ||
192 | |||
193 | #define EXTENDED_FULL_MASK (0xffffffff) | ||
194 | |||
195 | /* -- API inline-functions -- */ | ||
196 | |||
197 | /* | ||
198 | * Gets the current value of the specified pin | ||
199 | */ | ||
200 | static inline enum msp_gpio_data msp_gpio_pin_get(unsigned int gpio) | ||
201 | { | ||
202 | u32 pinhi_mask = 0, pinhi_mask2 = 0; | ||
203 | |||
204 | if (gpio >= MSP_NUM_GPIOS) | ||
205 | return MSP_GPIO_NONE; | ||
206 | |||
207 | if (gpio < 16) { | ||
208 | pinhi_mask = BASIC_DATA_MASK(gpio); | ||
209 | } else { | ||
210 | /* | ||
211 | * Two cases are possible with the EXTENDED register: | ||
212 | * - In output mode (ENABLED flag set), check the CLR bit | ||
213 | * - In input mode (ENABLED flag not set), check the SET bit | ||
214 | */ | ||
215 | pinhi_mask = EXTENDED_ENABLE(gpio) | EXTENDED_CLR(gpio); | ||
216 | pinhi_mask2 = EXTENDED_SET(gpio); | ||
217 | } | ||
218 | if (((*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask) == pinhi_mask) || | ||
219 | (*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask2)) | ||
220 | return MSP_GPIO_HI; | ||
221 | else | ||
222 | return MSP_GPIO_LO; | ||
223 | } | ||
224 | |||
225 | /* Sets the specified pin to the specified value */ | ||
226 | static inline void msp_gpio_pin_set(enum msp_gpio_data data, unsigned int gpio) | ||
227 | { | ||
228 | if (gpio >= MSP_NUM_GPIOS) | ||
229 | return; | ||
230 | |||
231 | if (gpio < 16) { | ||
232 | if (data == MSP_GPIO_TOGGLE) | ||
233 | toggle_reg32(MSP_GPIO_DATA_REGISTER[gpio], | ||
234 | BASIC_DATA_MASK(gpio)); | ||
235 | else if (data == MSP_GPIO_HI) | ||
236 | set_reg32(MSP_GPIO_DATA_REGISTER[gpio], | ||
237 | BASIC_DATA_MASK(gpio)); | ||
238 | else | ||
239 | clear_reg32(MSP_GPIO_DATA_REGISTER[gpio], | ||
240 | BASIC_DATA_MASK(gpio)); | ||
241 | } else { | ||
242 | if (data == MSP_GPIO_TOGGLE) { | ||
243 | /* Special ugly case: | ||
244 | * We have to read the CLR bit. | ||
245 | * If set, we write the CLR bit. | ||
246 | * If not, we write the SET bit. | ||
247 | */ | ||
248 | u32 tmpdata; | ||
249 | |||
250 | custom_read_reg32(MSP_GPIO_DATA_REGISTER[gpio], | ||
251 | tmpdata); | ||
252 | if (tmpdata & EXTENDED_CLR(gpio)) | ||
253 | tmpdata = EXTENDED_CLR(gpio); | ||
254 | else | ||
255 | tmpdata = EXTENDED_SET(gpio); | ||
256 | custom_write_reg32(MSP_GPIO_DATA_REGISTER[gpio], | ||
257 | tmpdata); | ||
258 | } else { | ||
259 | u32 newdata; | ||
260 | |||
261 | if (data == MSP_GPIO_HI) | ||
262 | newdata = EXTENDED_SET(gpio); | ||
263 | else | ||
264 | newdata = EXTENDED_CLR(gpio); | ||
265 | set_value_reg32(MSP_GPIO_DATA_REGISTER[gpio], | ||
266 | EXTENDED_FULL_MASK, newdata); | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | |||
271 | /* Sets the specified pin to the specified value */ | ||
272 | static inline void msp_gpio_pin_hi(unsigned int gpio) | ||
273 | { | ||
274 | msp_gpio_pin_set(MSP_GPIO_HI, gpio); | ||
275 | } | ||
276 | |||
277 | /* Sets the specified pin to the specified value */ | ||
278 | static inline void msp_gpio_pin_lo(unsigned int gpio) | ||
279 | { | ||
280 | msp_gpio_pin_set(MSP_GPIO_LO, gpio); | ||
281 | } | ||
282 | |||
283 | /* Sets the specified pin to the opposite value */ | ||
284 | static inline void msp_gpio_pin_toggle(unsigned int gpio) | ||
285 | { | ||
286 | msp_gpio_pin_set(MSP_GPIO_TOGGLE, gpio); | ||
287 | } | ||
288 | |||
289 | /* Gets the mode of the specified pin */ | ||
290 | static inline enum msp_gpio_mode msp_gpio_pin_get_mode(unsigned int gpio) | ||
291 | { | ||
292 | enum msp_gpio_mode retval = MSP_GPIO_UNKNOWN; | ||
293 | uint32_t data; | ||
294 | |||
295 | if (gpio >= MSP_NUM_GPIOS) | ||
296 | return retval; | ||
297 | |||
298 | data = *MSP_GPIO_MODE_REGISTER[gpio]; | ||
299 | |||
300 | if (gpio < 16) { | ||
301 | retval = BASIC_MODE_FROM_REG(data, gpio); | ||
302 | } else { | ||
303 | /* Extended pins can only be either INPUT or OUTPUT */ | ||
304 | if (data & EXTENDED_ENABLE(gpio)) | ||
305 | retval = MSP_GPIO_OUTPUT; | ||
306 | else | ||
307 | retval = MSP_GPIO_INPUT; | ||
308 | } | ||
309 | |||
310 | return retval; | ||
311 | } | ||
312 | |||
313 | /* | ||
314 | * Sets the specified mode on the requested pin | ||
315 | * Returns 0 on success, or -1 if that mode is not allowed on this pin | ||
316 | */ | ||
317 | static inline int msp_gpio_pin_mode(enum msp_gpio_mode mode, unsigned int gpio) | ||
318 | { | ||
319 | u32 modemask, newmode; | ||
320 | |||
321 | if ((1 << gpio) & ~MSP_GPIO_MODE_ALLOWED[mode]) | ||
322 | return -1; | ||
323 | |||
324 | if (gpio >= MSP_NUM_GPIOS) | ||
325 | return -1; | ||
326 | |||
327 | if (gpio < 16) { | ||
328 | modemask = BASIC_MODE_MASK(gpio); | ||
329 | newmode = BASIC_MODE(mode, gpio); | ||
330 | } else { | ||
331 | modemask = EXTENDED_FULL_MASK; | ||
332 | if (mode == MSP_GPIO_INPUT) | ||
333 | newmode = EXTENDED_DISABLE(gpio); | ||
334 | else | ||
335 | newmode = EXTENDED_ENABLE(gpio); | ||
336 | } | ||
337 | /* Do the set atomically */ | ||
338 | set_value_reg32(MSP_GPIO_MODE_REGISTER[gpio], modemask, newmode); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | #endif /* __MSP_GPIO_MACROS_H__ */ | ||