1ea8fbba7SJens Scharsig /* 2ea8fbba7SJens Scharsig * Memory Setup stuff - taken from blob memsetup.S 3ea8fbba7SJens Scharsig * 4ea8fbba7SJens Scharsig * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de) 5ea8fbba7SJens Scharsig * 6ea8fbba7SJens Scharsig * Copyright (C) 2005 HP Labs 7ea8fbba7SJens Scharsig * 81a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 9ea8fbba7SJens Scharsig */ 10ea8fbba7SJens Scharsig 11ea8fbba7SJens Scharsig #include <config.h> 12ea8fbba7SJens Scharsig #include <common.h> 1386592f60SReinhard Meyer #include <asm/io.h> 14ea8fbba7SJens Scharsig #include <asm/sizes.h> 15ea8fbba7SJens Scharsig #include <asm/arch/hardware.h> 16ea8fbba7SJens Scharsig #include <asm/arch/at91_pio.h> 17ea8fbba7SJens Scharsig 184bc9b7a5SBo Shen static struct at91_port *at91_pio_get_port(unsigned port) 194bc9b7a5SBo Shen { 204bc9b7a5SBo Shen switch (port) { 214bc9b7a5SBo Shen case AT91_PIO_PORTA: 224bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOA; 234bc9b7a5SBo Shen case AT91_PIO_PORTB: 244bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOB; 254bc9b7a5SBo Shen case AT91_PIO_PORTC: 264bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOC; 274bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 3) 284bc9b7a5SBo Shen case AT91_PIO_PORTD: 294bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOD; 304bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 4) 314bc9b7a5SBo Shen case AT91_PIO_PORTE: 324bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOE; 334bc9b7a5SBo Shen #endif 344bc9b7a5SBo Shen #endif 354bc9b7a5SBo Shen default: 364bc9b7a5SBo Shen return NULL; 374bc9b7a5SBo Shen } 384bc9b7a5SBo Shen } 394bc9b7a5SBo Shen 40ea8fbba7SJens Scharsig int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup) 41ea8fbba7SJens Scharsig { 424bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 43ea8fbba7SJens Scharsig u32 mask; 44ea8fbba7SJens Scharsig 454bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 46ea8fbba7SJens Scharsig mask = 1 << pin; 47ea8fbba7SJens Scharsig if (use_pullup) 484bc9b7a5SBo Shen writel(1 << pin, &at91_port->puer); 49ea8fbba7SJens Scharsig else 504bc9b7a5SBo Shen writel(1 << pin, &at91_port->pudr); 514bc9b7a5SBo Shen writel(mask, &at91_port->per); 52ea8fbba7SJens Scharsig } 534bc9b7a5SBo Shen 54ea8fbba7SJens Scharsig return 0; 55ea8fbba7SJens Scharsig } 56ea8fbba7SJens Scharsig 57ea8fbba7SJens Scharsig /* 58ea8fbba7SJens Scharsig * mux the pin to the "GPIO" peripheral role. 59ea8fbba7SJens Scharsig */ 60ea8fbba7SJens Scharsig int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup) 61ea8fbba7SJens Scharsig { 624bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 63ea8fbba7SJens Scharsig u32 mask; 64ea8fbba7SJens Scharsig 654bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 66ea8fbba7SJens Scharsig mask = 1 << pin; 674bc9b7a5SBo Shen writel(mask, &at91_port->idr); 68ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 694bc9b7a5SBo Shen writel(mask, &at91_port->per); 70ea8fbba7SJens Scharsig } 714bc9b7a5SBo Shen 72ea8fbba7SJens Scharsig return 0; 73ea8fbba7SJens Scharsig } 74ea8fbba7SJens Scharsig 75ea8fbba7SJens Scharsig /* 76ea8fbba7SJens Scharsig * mux the pin to the "A" internal peripheral role. 77ea8fbba7SJens Scharsig */ 78ea8fbba7SJens Scharsig int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup) 79ea8fbba7SJens Scharsig { 804bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 81ea8fbba7SJens Scharsig u32 mask; 82ea8fbba7SJens Scharsig 834bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 84ea8fbba7SJens Scharsig mask = 1 << pin; 854bc9b7a5SBo Shen writel(mask, &at91_port->idr); 86ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 872b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 884bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) & ~mask, 894bc9b7a5SBo Shen &at91_port->abcdsr1); 904bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) & ~mask, 914bc9b7a5SBo Shen &at91_port->abcdsr2); 922b3b1c66SBo Shen #else 934bc9b7a5SBo Shen writel(mask, &at91_port->asr); 942b3b1c66SBo Shen #endif 954bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 96ea8fbba7SJens Scharsig } 974bc9b7a5SBo Shen 98ea8fbba7SJens Scharsig return 0; 99ea8fbba7SJens Scharsig } 100ea8fbba7SJens Scharsig 101ea8fbba7SJens Scharsig /* 102ea8fbba7SJens Scharsig * mux the pin to the "B" internal peripheral role. 103ea8fbba7SJens Scharsig */ 104ea8fbba7SJens Scharsig int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup) 105ea8fbba7SJens Scharsig { 1064bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 107ea8fbba7SJens Scharsig u32 mask; 108ea8fbba7SJens Scharsig 1094bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 110ea8fbba7SJens Scharsig mask = 1 << pin; 1114bc9b7a5SBo Shen writel(mask, &at91_port->idr); 112ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 1132b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 1144bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) | mask, 1154bc9b7a5SBo Shen &at91_port->abcdsr1); 1164bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) & ~mask, 1174bc9b7a5SBo Shen &at91_port->abcdsr2); 1182b3b1c66SBo Shen #else 1194bc9b7a5SBo Shen writel(mask, &at91_port->bsr); 1202b3b1c66SBo Shen #endif 1214bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 122ea8fbba7SJens Scharsig } 1234bc9b7a5SBo Shen 124ea8fbba7SJens Scharsig return 0; 125ea8fbba7SJens Scharsig } 126ea8fbba7SJens Scharsig 1272b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 1282b3b1c66SBo Shen /* 1292b3b1c66SBo Shen * mux the pin to the "C" internal peripheral role. 1302b3b1c66SBo Shen */ 1312b3b1c66SBo Shen int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup) 1322b3b1c66SBo Shen { 1334bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 1342b3b1c66SBo Shen u32 mask; 1352b3b1c66SBo Shen 1364bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 1372b3b1c66SBo Shen mask = 1 << pin; 1384bc9b7a5SBo Shen writel(mask, &at91_port->idr); 1392b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup); 1404bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) & ~mask, 1414bc9b7a5SBo Shen &at91_port->abcdsr1); 1424bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) | mask, 1434bc9b7a5SBo Shen &at91_port->abcdsr2); 1444bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 1452b3b1c66SBo Shen } 1464bc9b7a5SBo Shen 1472b3b1c66SBo Shen return 0; 1482b3b1c66SBo Shen } 1492b3b1c66SBo Shen 1502b3b1c66SBo Shen /* 1512b3b1c66SBo Shen * mux the pin to the "D" internal peripheral role. 1522b3b1c66SBo Shen */ 1532b3b1c66SBo Shen int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup) 1542b3b1c66SBo Shen { 1554bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 1562b3b1c66SBo Shen u32 mask; 1572b3b1c66SBo Shen 1584bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 1592b3b1c66SBo Shen mask = 1 << pin; 1604bc9b7a5SBo Shen writel(mask, &at91_port->idr); 1612b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup); 1624bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) | mask, 1634bc9b7a5SBo Shen &at91_port->abcdsr1); 1644bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) | mask, 1654bc9b7a5SBo Shen &at91_port->abcdsr2); 1664bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 1672b3b1c66SBo Shen } 1684bc9b7a5SBo Shen 1692b3b1c66SBo Shen return 0; 1702b3b1c66SBo Shen } 1712b3b1c66SBo Shen #endif 1722b3b1c66SBo Shen 173ea8fbba7SJens Scharsig /* 174ea8fbba7SJens Scharsig * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and 175ea8fbba7SJens Scharsig * configure it for an input. 176ea8fbba7SJens Scharsig */ 177ea8fbba7SJens Scharsig int at91_set_pio_input(unsigned port, u32 pin, int use_pullup) 178ea8fbba7SJens Scharsig { 1794bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 180ea8fbba7SJens Scharsig u32 mask; 181ea8fbba7SJens Scharsig 1824bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 183ea8fbba7SJens Scharsig mask = 1 << pin; 1844bc9b7a5SBo Shen writel(mask, &at91_port->idr); 185ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 1864bc9b7a5SBo Shen writel(mask, &at91_port->odr); 1874bc9b7a5SBo Shen writel(mask, &at91_port->per); 188ea8fbba7SJens Scharsig } 1894bc9b7a5SBo Shen 190ea8fbba7SJens Scharsig return 0; 191ea8fbba7SJens Scharsig } 192ea8fbba7SJens Scharsig 193ea8fbba7SJens Scharsig /* 194ea8fbba7SJens Scharsig * mux the pin to the gpio controller (instead of "A" or "B" peripheral), 195ea8fbba7SJens Scharsig * and configure it for an output. 196ea8fbba7SJens Scharsig */ 197ea8fbba7SJens Scharsig int at91_set_pio_output(unsigned port, u32 pin, int value) 198ea8fbba7SJens Scharsig { 1994bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 200ea8fbba7SJens Scharsig u32 mask; 201ea8fbba7SJens Scharsig 202372f2783SReinhard Meyer if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 203ea8fbba7SJens Scharsig mask = 1 << pin; 2044bc9b7a5SBo Shen writel(mask, &at91_port->idr); 2054bc9b7a5SBo Shen writel(mask, &at91_port->pudr); 206ea8fbba7SJens Scharsig if (value) 2074bc9b7a5SBo Shen writel(mask, &at91_port->sodr); 208ea8fbba7SJens Scharsig else 2094bc9b7a5SBo Shen writel(mask, &at91_port->codr); 2104bc9b7a5SBo Shen writel(mask, &at91_port->oer); 2114bc9b7a5SBo Shen writel(mask, &at91_port->per); 212ea8fbba7SJens Scharsig } 2134bc9b7a5SBo Shen 214ea8fbba7SJens Scharsig return 0; 215ea8fbba7SJens Scharsig } 216ea8fbba7SJens Scharsig 217ea8fbba7SJens Scharsig /* 218ea8fbba7SJens Scharsig * enable/disable the glitch filter. mostly used with IRQ handling. 219ea8fbba7SJens Scharsig */ 220ea8fbba7SJens Scharsig int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on) 221ea8fbba7SJens Scharsig { 2224bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 223ea8fbba7SJens Scharsig u32 mask; 224ea8fbba7SJens Scharsig 2254bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 226ea8fbba7SJens Scharsig mask = 1 << pin; 2272b3b1c66SBo Shen if (is_on) { 2282b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 2294bc9b7a5SBo Shen writel(mask, &at91_port->ifscdr); 2302b3b1c66SBo Shen #endif 2314bc9b7a5SBo Shen writel(mask, &at91_port->ifer); 2322b3b1c66SBo Shen } else { 2334bc9b7a5SBo Shen writel(mask, &at91_port->ifdr); 234ea8fbba7SJens Scharsig } 2352b3b1c66SBo Shen } 2364bc9b7a5SBo Shen 237ea8fbba7SJens Scharsig return 0; 238ea8fbba7SJens Scharsig } 239ea8fbba7SJens Scharsig 2402b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 2412b3b1c66SBo Shen /* 2422b3b1c66SBo Shen * enable/disable the debounce filter. 2432b3b1c66SBo Shen */ 2442b3b1c66SBo Shen int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) 2452b3b1c66SBo Shen { 2464bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 2472b3b1c66SBo Shen u32 mask; 2482b3b1c66SBo Shen 2494bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 2502b3b1c66SBo Shen mask = 1 << pin; 2512b3b1c66SBo Shen if (is_on) { 2524bc9b7a5SBo Shen writel(mask, &at91_port->ifscer); 2534bc9b7a5SBo Shen writel(div & PIO_SCDR_DIV, &at91_port->scdr); 2544bc9b7a5SBo Shen writel(mask, &at91_port->ifer); 2552b3b1c66SBo Shen } else { 2564bc9b7a5SBo Shen writel(mask, &at91_port->ifdr); 2572b3b1c66SBo Shen } 2582b3b1c66SBo Shen } 2594bc9b7a5SBo Shen 2602b3b1c66SBo Shen return 0; 2612b3b1c66SBo Shen } 2622b3b1c66SBo Shen 2632b3b1c66SBo Shen /* 2642b3b1c66SBo Shen * enable/disable the pull-down. 2652b3b1c66SBo Shen * If pull-up already enabled while calling the function, we disable it. 2662b3b1c66SBo Shen */ 2672b3b1c66SBo Shen int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on) 2682b3b1c66SBo Shen { 2694bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 2702b3b1c66SBo Shen u32 mask; 2712b3b1c66SBo Shen 2724bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 2732b3b1c66SBo Shen mask = 1 << pin; 2744bc9b7a5SBo Shen writel(mask, &at91_port->pudr); 2752b3b1c66SBo Shen if (is_on) 2764bc9b7a5SBo Shen writel(mask, &at91_port->ppder); 2772b3b1c66SBo Shen else 2784bc9b7a5SBo Shen writel(mask, &at91_port->ppddr); 2792b3b1c66SBo Shen } 2804bc9b7a5SBo Shen 2812b3b1c66SBo Shen return 0; 2822b3b1c66SBo Shen } 2832b3b1c66SBo Shen 2842b3b1c66SBo Shen /* 2852b3b1c66SBo Shen * disable Schmitt trigger 2862b3b1c66SBo Shen */ 2872b3b1c66SBo Shen int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin) 2882b3b1c66SBo Shen { 2894bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 2902b3b1c66SBo Shen u32 mask; 2912b3b1c66SBo Shen 2924bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 2932b3b1c66SBo Shen mask = 1 << pin; 2944bc9b7a5SBo Shen writel(readl(&at91_port->schmitt) | mask, 2954bc9b7a5SBo Shen &at91_port->schmitt); 2962b3b1c66SBo Shen } 2974bc9b7a5SBo Shen 2982b3b1c66SBo Shen return 0; 2992b3b1c66SBo Shen } 3002b3b1c66SBo Shen #endif 3012b3b1c66SBo Shen 302ea8fbba7SJens Scharsig /* 303ea8fbba7SJens Scharsig * enable/disable the multi-driver. This is only valid for output and 304ea8fbba7SJens Scharsig * allows the output pin to run as an open collector output. 305ea8fbba7SJens Scharsig */ 306ea8fbba7SJens Scharsig int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on) 307ea8fbba7SJens Scharsig { 3084bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 309ea8fbba7SJens Scharsig u32 mask; 310ea8fbba7SJens Scharsig 3114bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 312ea8fbba7SJens Scharsig mask = 1 << pin; 313ea8fbba7SJens Scharsig if (is_on) 3144bc9b7a5SBo Shen writel(mask, &at91_port->mder); 315ea8fbba7SJens Scharsig else 3164bc9b7a5SBo Shen writel(mask, &at91_port->mddr); 317ea8fbba7SJens Scharsig } 3184bc9b7a5SBo Shen 319ea8fbba7SJens Scharsig return 0; 320ea8fbba7SJens Scharsig } 321ea8fbba7SJens Scharsig 322ea8fbba7SJens Scharsig /* 323ea8fbba7SJens Scharsig * assuming the pin is muxed as a gpio output, set its value. 324ea8fbba7SJens Scharsig */ 325ea8fbba7SJens Scharsig int at91_set_pio_value(unsigned port, unsigned pin, int value) 326ea8fbba7SJens Scharsig { 3274bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 328ea8fbba7SJens Scharsig u32 mask; 329ea8fbba7SJens Scharsig 3304bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 331ea8fbba7SJens Scharsig mask = 1 << pin; 332ea8fbba7SJens Scharsig if (value) 3334bc9b7a5SBo Shen writel(mask, &at91_port->sodr); 334ea8fbba7SJens Scharsig else 3354bc9b7a5SBo Shen writel(mask, &at91_port->codr); 336ea8fbba7SJens Scharsig } 3374bc9b7a5SBo Shen 338ea8fbba7SJens Scharsig return 0; 339ea8fbba7SJens Scharsig } 340ea8fbba7SJens Scharsig 341ea8fbba7SJens Scharsig /* 342ea8fbba7SJens Scharsig * read the pin's value (works even if it's not muxed as a gpio). 343ea8fbba7SJens Scharsig */ 344ea8fbba7SJens Scharsig int at91_get_pio_value(unsigned port, unsigned pin) 345ea8fbba7SJens Scharsig { 3464bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 3474bc9b7a5SBo Shen u32 pdsr = 0, mask; 348ea8fbba7SJens Scharsig 3494bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 350ea8fbba7SJens Scharsig mask = 1 << pin; 3514bc9b7a5SBo Shen pdsr = readl(&at91_port->pdsr) & mask; 352ea8fbba7SJens Scharsig } 3534bc9b7a5SBo Shen 354ea8fbba7SJens Scharsig return pdsr != 0; 355ea8fbba7SJens Scharsig } 356*6edaea87SBo Shen 357*6edaea87SBo Shen /* Common GPIO API */ 358*6edaea87SBo Shen 359*6edaea87SBo Shen #define at91_gpio_to_port(gpio) (gpio / 32) 360*6edaea87SBo Shen #define at91_gpio_to_pin(gpio) (gpio % 32) 361*6edaea87SBo Shen 362*6edaea87SBo Shen int gpio_request(unsigned gpio, const char *label) 363*6edaea87SBo Shen { 364*6edaea87SBo Shen return 0; 365*6edaea87SBo Shen } 366*6edaea87SBo Shen 367*6edaea87SBo Shen int gpio_free(unsigned gpio) 368*6edaea87SBo Shen { 369*6edaea87SBo Shen return 0; 370*6edaea87SBo Shen } 371*6edaea87SBo Shen 372*6edaea87SBo Shen int gpio_direction_input(unsigned gpio) 373*6edaea87SBo Shen { 374*6edaea87SBo Shen at91_set_pio_input(at91_gpio_to_port(gpio), 375*6edaea87SBo Shen at91_gpio_to_pin(gpio), 0); 376*6edaea87SBo Shen return 0; 377*6edaea87SBo Shen } 378*6edaea87SBo Shen 379*6edaea87SBo Shen int gpio_direction_output(unsigned gpio, int value) 380*6edaea87SBo Shen { 381*6edaea87SBo Shen at91_set_pio_output(at91_gpio_to_port(gpio), 382*6edaea87SBo Shen at91_gpio_to_pin(gpio), value); 383*6edaea87SBo Shen return 0; 384*6edaea87SBo Shen } 385*6edaea87SBo Shen 386*6edaea87SBo Shen int gpio_get_value(unsigned gpio) 387*6edaea87SBo Shen { 388*6edaea87SBo Shen return at91_get_pio_value(at91_gpio_to_port(gpio), 389*6edaea87SBo Shen at91_gpio_to_pin(gpio)); 390*6edaea87SBo Shen } 391*6edaea87SBo Shen 392*6edaea87SBo Shen int gpio_set_value(unsigned gpio, int value) 393*6edaea87SBo Shen { 394*6edaea87SBo Shen at91_set_pio_value(at91_gpio_to_port(gpio), 395*6edaea87SBo Shen at91_gpio_to_pin(gpio), value); 396*6edaea87SBo Shen 397*6edaea87SBo Shen return 0; 398*6edaea87SBo Shen } 399