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 18*4bc9b7a5SBo Shen static struct at91_port *at91_pio_get_port(unsigned port) 19*4bc9b7a5SBo Shen { 20*4bc9b7a5SBo Shen switch (port) { 21*4bc9b7a5SBo Shen case AT91_PIO_PORTA: 22*4bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOA; 23*4bc9b7a5SBo Shen case AT91_PIO_PORTB: 24*4bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOB; 25*4bc9b7a5SBo Shen case AT91_PIO_PORTC: 26*4bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOC; 27*4bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 3) 28*4bc9b7a5SBo Shen case AT91_PIO_PORTD: 29*4bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOD; 30*4bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 4) 31*4bc9b7a5SBo Shen case AT91_PIO_PORTE: 32*4bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOE; 33*4bc9b7a5SBo Shen #endif 34*4bc9b7a5SBo Shen #endif 35*4bc9b7a5SBo Shen default: 36*4bc9b7a5SBo Shen return NULL; 37*4bc9b7a5SBo Shen } 38*4bc9b7a5SBo Shen } 39*4bc9b7a5SBo Shen 40ea8fbba7SJens Scharsig int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup) 41ea8fbba7SJens Scharsig { 42*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 43ea8fbba7SJens Scharsig u32 mask; 44ea8fbba7SJens Scharsig 45*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 46ea8fbba7SJens Scharsig mask = 1 << pin; 47ea8fbba7SJens Scharsig if (use_pullup) 48*4bc9b7a5SBo Shen writel(1 << pin, &at91_port->puer); 49ea8fbba7SJens Scharsig else 50*4bc9b7a5SBo Shen writel(1 << pin, &at91_port->pudr); 51*4bc9b7a5SBo Shen writel(mask, &at91_port->per); 52ea8fbba7SJens Scharsig } 53*4bc9b7a5SBo 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 { 62*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 63ea8fbba7SJens Scharsig u32 mask; 64ea8fbba7SJens Scharsig 65*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 66ea8fbba7SJens Scharsig mask = 1 << pin; 67*4bc9b7a5SBo Shen writel(mask, &at91_port->idr); 68ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 69*4bc9b7a5SBo Shen writel(mask, &at91_port->per); 70ea8fbba7SJens Scharsig } 71*4bc9b7a5SBo 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 { 80*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 81ea8fbba7SJens Scharsig u32 mask; 82ea8fbba7SJens Scharsig 83*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 84ea8fbba7SJens Scharsig mask = 1 << pin; 85*4bc9b7a5SBo Shen writel(mask, &at91_port->idr); 86ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 872b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 88*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) & ~mask, 89*4bc9b7a5SBo Shen &at91_port->abcdsr1); 90*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) & ~mask, 91*4bc9b7a5SBo Shen &at91_port->abcdsr2); 922b3b1c66SBo Shen #else 93*4bc9b7a5SBo Shen writel(mask, &at91_port->asr); 942b3b1c66SBo Shen #endif 95*4bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 96ea8fbba7SJens Scharsig } 97*4bc9b7a5SBo 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 { 106*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 107ea8fbba7SJens Scharsig u32 mask; 108ea8fbba7SJens Scharsig 109*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 110ea8fbba7SJens Scharsig mask = 1 << pin; 111*4bc9b7a5SBo Shen writel(mask, &at91_port->idr); 112ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 1132b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 114*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) | mask, 115*4bc9b7a5SBo Shen &at91_port->abcdsr1); 116*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) & ~mask, 117*4bc9b7a5SBo Shen &at91_port->abcdsr2); 1182b3b1c66SBo Shen #else 119*4bc9b7a5SBo Shen writel(mask, &at91_port->bsr); 1202b3b1c66SBo Shen #endif 121*4bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 122ea8fbba7SJens Scharsig } 123*4bc9b7a5SBo 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 { 133*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 1342b3b1c66SBo Shen u32 mask; 1352b3b1c66SBo Shen 136*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 1372b3b1c66SBo Shen mask = 1 << pin; 138*4bc9b7a5SBo Shen writel(mask, &at91_port->idr); 1392b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup); 140*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) & ~mask, 141*4bc9b7a5SBo Shen &at91_port->abcdsr1); 142*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) | mask, 143*4bc9b7a5SBo Shen &at91_port->abcdsr2); 144*4bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 1452b3b1c66SBo Shen } 146*4bc9b7a5SBo 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 { 155*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 1562b3b1c66SBo Shen u32 mask; 1572b3b1c66SBo Shen 158*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 1592b3b1c66SBo Shen mask = 1 << pin; 160*4bc9b7a5SBo Shen writel(mask, &at91_port->idr); 1612b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup); 162*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr1) | mask, 163*4bc9b7a5SBo Shen &at91_port->abcdsr1); 164*4bc9b7a5SBo Shen writel(readl(&at91_port->abcdsr2) | mask, 165*4bc9b7a5SBo Shen &at91_port->abcdsr2); 166*4bc9b7a5SBo Shen writel(mask, &at91_port->pdr); 1672b3b1c66SBo Shen } 168*4bc9b7a5SBo 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 { 179*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 180ea8fbba7SJens Scharsig u32 mask; 181ea8fbba7SJens Scharsig 182*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 183ea8fbba7SJens Scharsig mask = 1 << pin; 184*4bc9b7a5SBo Shen writel(mask, &at91_port->idr); 185ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup); 186*4bc9b7a5SBo Shen writel(mask, &at91_port->odr); 187*4bc9b7a5SBo Shen writel(mask, &at91_port->per); 188ea8fbba7SJens Scharsig } 189*4bc9b7a5SBo 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 { 199*4bc9b7a5SBo 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; 204*4bc9b7a5SBo Shen writel(mask, &at91_port->idr); 205*4bc9b7a5SBo Shen writel(mask, &at91_port->pudr); 206ea8fbba7SJens Scharsig if (value) 207*4bc9b7a5SBo Shen writel(mask, &at91_port->sodr); 208ea8fbba7SJens Scharsig else 209*4bc9b7a5SBo Shen writel(mask, &at91_port->codr); 210*4bc9b7a5SBo Shen writel(mask, &at91_port->oer); 211*4bc9b7a5SBo Shen writel(mask, &at91_port->per); 212ea8fbba7SJens Scharsig } 213*4bc9b7a5SBo 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 { 222*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 223ea8fbba7SJens Scharsig u32 mask; 224ea8fbba7SJens Scharsig 225*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 226ea8fbba7SJens Scharsig mask = 1 << pin; 2272b3b1c66SBo Shen if (is_on) { 2282b3b1c66SBo Shen #if defined(CPU_HAS_PIO3) 229*4bc9b7a5SBo Shen writel(mask, &at91_port->ifscdr); 2302b3b1c66SBo Shen #endif 231*4bc9b7a5SBo Shen writel(mask, &at91_port->ifer); 2322b3b1c66SBo Shen } else { 233*4bc9b7a5SBo Shen writel(mask, &at91_port->ifdr); 234ea8fbba7SJens Scharsig } 2352b3b1c66SBo Shen } 236*4bc9b7a5SBo 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 { 246*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 2472b3b1c66SBo Shen u32 mask; 2482b3b1c66SBo Shen 249*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 2502b3b1c66SBo Shen mask = 1 << pin; 2512b3b1c66SBo Shen if (is_on) { 252*4bc9b7a5SBo Shen writel(mask, &at91_port->ifscer); 253*4bc9b7a5SBo Shen writel(div & PIO_SCDR_DIV, &at91_port->scdr); 254*4bc9b7a5SBo Shen writel(mask, &at91_port->ifer); 2552b3b1c66SBo Shen } else { 256*4bc9b7a5SBo Shen writel(mask, &at91_port->ifdr); 2572b3b1c66SBo Shen } 2582b3b1c66SBo Shen } 259*4bc9b7a5SBo 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 { 269*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 2702b3b1c66SBo Shen u32 mask; 2712b3b1c66SBo Shen 272*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 2732b3b1c66SBo Shen mask = 1 << pin; 274*4bc9b7a5SBo Shen writel(mask, &at91_port->pudr); 2752b3b1c66SBo Shen if (is_on) 276*4bc9b7a5SBo Shen writel(mask, &at91_port->ppder); 2772b3b1c66SBo Shen else 278*4bc9b7a5SBo Shen writel(mask, &at91_port->ppddr); 2792b3b1c66SBo Shen } 280*4bc9b7a5SBo 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 { 289*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 2902b3b1c66SBo Shen u32 mask; 2912b3b1c66SBo Shen 292*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 2932b3b1c66SBo Shen mask = 1 << pin; 294*4bc9b7a5SBo Shen writel(readl(&at91_port->schmitt) | mask, 295*4bc9b7a5SBo Shen &at91_port->schmitt); 2962b3b1c66SBo Shen } 297*4bc9b7a5SBo 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 { 308*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 309ea8fbba7SJens Scharsig u32 mask; 310ea8fbba7SJens Scharsig 311*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 312ea8fbba7SJens Scharsig mask = 1 << pin; 313ea8fbba7SJens Scharsig if (is_on) 314*4bc9b7a5SBo Shen writel(mask, &at91_port->mder); 315ea8fbba7SJens Scharsig else 316*4bc9b7a5SBo Shen writel(mask, &at91_port->mddr); 317ea8fbba7SJens Scharsig } 318*4bc9b7a5SBo 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 { 327*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 328ea8fbba7SJens Scharsig u32 mask; 329ea8fbba7SJens Scharsig 330*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 331ea8fbba7SJens Scharsig mask = 1 << pin; 332ea8fbba7SJens Scharsig if (value) 333*4bc9b7a5SBo Shen writel(mask, &at91_port->sodr); 334ea8fbba7SJens Scharsig else 335*4bc9b7a5SBo Shen writel(mask, &at91_port->codr); 336ea8fbba7SJens Scharsig } 337*4bc9b7a5SBo 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 { 346*4bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port); 347*4bc9b7a5SBo Shen u32 pdsr = 0, mask; 348ea8fbba7SJens Scharsig 349*4bc9b7a5SBo Shen if (at91_port && (pin < 32)) { 350ea8fbba7SJens Scharsig mask = 1 << pin; 351*4bc9b7a5SBo Shen pdsr = readl(&at91_port->pdsr) & mask; 352ea8fbba7SJens Scharsig } 353*4bc9b7a5SBo Shen 354ea8fbba7SJens Scharsig return pdsr != 0; 355ea8fbba7SJens Scharsig } 356