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 writel(mask, &pio->port[port].asr); 90 writel(mask, &pio->port[port].pdr); 91 } 92 return 0; 93 } 94 95 /* 96 * mux the pin to the "B" internal peripheral role. 97 */ 98 int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup) 99 { 100 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 101 u32 mask; 102 103 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 104 mask = 1 << pin; 105 writel(mask, &pio->port[port].idr); 106 at91_set_pio_pullup(port, pin, use_pullup); 107 writel(mask, &pio->port[port].bsr); 108 writel(mask, &pio->port[port].pdr); 109 } 110 return 0; 111 } 112 113 /* 114 * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and 115 * configure it for an input. 116 */ 117 int at91_set_pio_input(unsigned port, u32 pin, int use_pullup) 118 { 119 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 120 u32 mask; 121 122 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 123 mask = 1 << pin; 124 writel(mask, &pio->port[port].idr); 125 at91_set_pio_pullup(port, pin, use_pullup); 126 writel(mask, &pio->port[port].odr); 127 writel(mask, &pio->port[port].per); 128 } 129 return 0; 130 } 131 132 /* 133 * mux the pin to the gpio controller (instead of "A" or "B" peripheral), 134 * and configure it for an output. 135 */ 136 int at91_set_pio_output(unsigned port, u32 pin, int value) 137 { 138 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 139 u32 mask; 140 141 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 142 mask = 1 << pin; 143 writel(mask, &pio->port[port].idr); 144 writel(mask, &pio->port[port].pudr); 145 if (value) 146 writel(mask, &pio->port[port].sodr); 147 else 148 writel(mask, &pio->port[port].codr); 149 writel(mask, &pio->port[port].oer); 150 writel(mask, &pio->port[port].per); 151 } 152 return 0; 153 } 154 155 /* 156 * enable/disable the glitch filter. mostly used with IRQ handling. 157 */ 158 int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on) 159 { 160 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 161 u32 mask; 162 163 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 164 mask = 1 << pin; 165 if (is_on) 166 writel(mask, &pio->port[port].ifer); 167 else 168 writel(mask, &pio->port[port].ifdr); 169 } 170 return 0; 171 } 172 173 /* 174 * enable/disable the multi-driver. This is only valid for output and 175 * allows the output pin to run as an open collector output. 176 */ 177 int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on) 178 { 179 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 180 u32 mask; 181 182 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 183 mask = 1 << pin; 184 if (is_on) 185 writel(mask, &pio->port[port].mder); 186 else 187 writel(mask, &pio->port[port].mddr); 188 } 189 return 0; 190 } 191 192 /* 193 * assuming the pin is muxed as a gpio output, set its value. 194 */ 195 int at91_set_pio_value(unsigned port, unsigned pin, int value) 196 { 197 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 198 u32 mask; 199 200 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 201 mask = 1 << pin; 202 if (value) 203 writel(mask, &pio->port[port].sodr); 204 else 205 writel(mask, &pio->port[port].codr); 206 } 207 return 0; 208 } 209 210 /* 211 * read the pin's value (works even if it's not muxed as a gpio). 212 */ 213 int at91_get_pio_value(unsigned port, unsigned pin) 214 { 215 u32 pdsr = 0; 216 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; 217 u32 mask; 218 219 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { 220 mask = 1 << pin; 221 pdsr = readl(&pio->port[port].pdsr) & mask; 222 } 223 return pdsr != 0; 224 } 225