1 /* 2 * Memory Setup stuff - taken from blob memsetup.S 3 * 4 * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de) 5 * 6 * Copyright (C) 2005 HP Labs 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 */ 26 27 /* 28 * WARNING: 29 * 30 * As the code is right now, it expects all PIO ports A,B,C,... 31 * to be evenly spaced in the memory map: 32 * ATMEL_BASE_PIOA + port * sizeof at91pio_t 33 * This might not necessaryly be true in future Atmel SoCs. 34 * This code should be fixed to use a pointer array to the ports. 35 */ 36 37 #include <config.h> 38 #include <common.h> 39 #include <asm/io.h> 40 #include <asm/sizes.h> 41 #include <asm/arch/hardware.h> 42 #include <asm/arch/at91_pio.h> 43 44 int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup) 45 { 46 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 47 u32 mask; 48 49 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 50 mask = 1 << pin; 51 if (use_pullup) 52 writel(1 << pin, &pio->port[port].puer); 53 else 54 writel(1 << pin, &pio->port[port].pudr); 55 writel(mask, &pio->port[port].per); 56 } 57 return 0; 58 } 59 60 /* 61 * mux the pin to the "GPIO" peripheral role. 62 */ 63 int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup) 64 { 65 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 66 u32 mask; 67 68 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 69 mask = 1 << pin; 70 writel(mask, &pio->port[port].idr); 71 at91_set_pio_pullup(port, pin, use_pullup); 72 writel(mask, &pio->port[port].per); 73 } 74 return 0; 75 } 76 77 /* 78 * mux the pin to the "A" internal peripheral role. 79 */ 80 int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup) 81 { 82 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 83 u32 mask; 84 85 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 86 mask = 1 << pin; 87 writel(mask, &pio->port[port].idr); 88 at91_set_pio_pullup(port, pin, use_pullup); 89 #if defined(CPU_HAS_PIO3) 90 writel(readl(&pio->port[port].abcdsr1) & ~mask, 91 &pio->port[port].abcdsr1); 92 writel(readl(&pio->port[port].abcdsr2) & ~mask, 93 &pio->port[port].abcdsr2); 94 #else 95 writel(mask, &pio->port[port].asr); 96 #endif 97 writel(mask, &pio->port[port].pdr); 98 } 99 return 0; 100 } 101 102 /* 103 * mux the pin to the "B" internal peripheral role. 104 */ 105 int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup) 106 { 107 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 108 u32 mask; 109 110 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 111 mask = 1 << pin; 112 writel(mask, &pio->port[port].idr); 113 at91_set_pio_pullup(port, pin, use_pullup); 114 #if defined(CPU_HAS_PIO3) 115 writel(readl(&pio->port[port].abcdsr1) | mask, 116 &pio->port[port].abcdsr1); 117 writel(readl(&pio->port[port].abcdsr2) & ~mask, 118 &pio->port[port].abcdsr2); 119 #else 120 writel(mask, &pio->port[port].bsr); 121 #endif 122 writel(mask, &pio->port[port].pdr); 123 } 124 return 0; 125 } 126 127 #if defined(CPU_HAS_PIO3) 128 /* 129 * mux the pin to the "C" internal peripheral role. 130 */ 131 int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup) 132 { 133 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 134 u32 mask; 135 136 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 137 mask = 1 << pin; 138 writel(mask, &pio->port[port].idr); 139 at91_set_pio_pullup(port, pin, use_pullup); 140 writel(readl(&pio->port[port].abcdsr1) & ~mask, 141 &pio->port[port].abcdsr1); 142 writel(readl(&pio->port[port].abcdsr2) | mask, 143 &pio->port[port].abcdsr2); 144 writel(mask, &pio->port[port].pdr); 145 } 146 return 0; 147 } 148 149 /* 150 * mux the pin to the "D" internal peripheral role. 151 */ 152 int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup) 153 { 154 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 155 u32 mask; 156 157 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 158 mask = 1 << pin; 159 writel(mask, &pio->port[port].idr); 160 at91_set_pio_pullup(port, pin, use_pullup); 161 writel(readl(&pio->port[port].abcdsr1) | mask, 162 &pio->port[port].abcdsr1); 163 writel(readl(&pio->port[port].abcdsr2) | mask, 164 &pio->port[port].abcdsr2); 165 writel(mask, &pio->port[port].pdr); 166 } 167 return 0; 168 } 169 #endif 170 171 /* 172 * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and 173 * configure it for an input. 174 */ 175 int at91_set_pio_input(unsigned port, u32 pin, int use_pullup) 176 { 177 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 178 u32 mask; 179 180 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 181 mask = 1 << pin; 182 writel(mask, &pio->port[port].idr); 183 at91_set_pio_pullup(port, pin, use_pullup); 184 writel(mask, &pio->port[port].odr); 185 writel(mask, &pio->port[port].per); 186 } 187 return 0; 188 } 189 190 /* 191 * mux the pin to the gpio controller (instead of "A" or "B" peripheral), 192 * and configure it for an output. 193 */ 194 int at91_set_pio_output(unsigned port, u32 pin, int value) 195 { 196 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 197 u32 mask; 198 199 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 200 mask = 1 << pin; 201 writel(mask, &pio->port[port].idr); 202 writel(mask, &pio->port[port].pudr); 203 if (value) 204 writel(mask, &pio->port[port].sodr); 205 else 206 writel(mask, &pio->port[port].codr); 207 writel(mask, &pio->port[port].oer); 208 writel(mask, &pio->port[port].per); 209 } 210 return 0; 211 } 212 213 /* 214 * enable/disable the glitch filter. mostly used with IRQ handling. 215 */ 216 int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on) 217 { 218 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 219 u32 mask; 220 221 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 222 mask = 1 << pin; 223 if (is_on) { 224 #if defined(CPU_HAS_PIO3) 225 writel(mask, &pio->port[port].ifscdr); 226 #endif 227 writel(mask, &pio->port[port].ifer); 228 } else { 229 writel(mask, &pio->port[port].ifdr); 230 } 231 } 232 return 0; 233 } 234 235 #if defined(CPU_HAS_PIO3) 236 /* 237 * enable/disable the debounce filter. 238 */ 239 int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) 240 { 241 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 242 u32 mask; 243 244 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 245 mask = 1 << pin; 246 if (is_on) { 247 writel(mask, &pio->port[port].ifscer); 248 writel(div & PIO_SCDR_DIV, &pio->port[port].scdr); 249 writel(mask, &pio->port[port].ifer); 250 } else { 251 writel(mask, &pio->port[port].ifdr); 252 } 253 } 254 return 0; 255 } 256 257 /* 258 * enable/disable the pull-down. 259 * If pull-up already enabled while calling the function, we disable it. 260 */ 261 int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on) 262 { 263 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 264 u32 mask; 265 266 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 267 mask = 1 << pin; 268 writel(mask, &pio->port[port].pudr); 269 if (is_on) 270 writel(mask, &pio->port[port].ppder); 271 else 272 writel(mask, &pio->port[port].ppddr); 273 } 274 return 0; 275 } 276 277 /* 278 * disable Schmitt trigger 279 */ 280 int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin) 281 { 282 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 283 u32 mask; 284 285 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 286 mask = 1 << pin; 287 writel(readl(&pio->port[port].schmitt) | mask, 288 &pio->port[port].schmitt); 289 } 290 return 0; 291 } 292 #endif 293 294 /* 295 * enable/disable the multi-driver. This is only valid for output and 296 * allows the output pin to run as an open collector output. 297 */ 298 int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on) 299 { 300 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 301 u32 mask; 302 303 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 304 mask = 1 << pin; 305 if (is_on) 306 writel(mask, &pio->port[port].mder); 307 else 308 writel(mask, &pio->port[port].mddr); 309 } 310 return 0; 311 } 312 313 /* 314 * assuming the pin is muxed as a gpio output, set its value. 315 */ 316 int at91_set_pio_value(unsigned port, unsigned pin, int value) 317 { 318 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 319 u32 mask; 320 321 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 322 mask = 1 << pin; 323 if (value) 324 writel(mask, &pio->port[port].sodr); 325 else 326 writel(mask, &pio->port[port].codr); 327 } 328 return 0; 329 } 330 331 /* 332 * read the pin's value (works even if it's not muxed as a gpio). 333 */ 334 int at91_get_pio_value(unsigned port, unsigned pin) 335 { 336 u32 pdsr = 0; 337 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 338 u32 mask; 339 340 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 341 mask = 1 << pin; 342 pdsr = readl(&pio->port[port].pdsr) & mask; 343 } 344 return pdsr != 0; 345 } 346