1 /* 2 * (C) Copyright 2006 3 * Wolfgang Wegner, ASTRO Strobel Kommunikationssysteme GmbH, 4 * w.wegner@astro-kom.de 5 * 6 * based on the files by 7 * Heiko Schocher, DENX Software Engineering, hs@denx.de 8 * and 9 * Rich Ireland, Enterasys Networks, rireland@enterasys.com. 10 * Keith Outwater, keith_outwater@mvis.com. 11 * 12 * See file CREDITS for list of people who contributed to this 13 * project. 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License as 17 * published by the Free Software Foundation; either version 2 of 18 * the License, or (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 28 * MA 02111-1307 USA 29 * 30 */ 31 32 /* Altera/Xilinx FPGA configuration support for the ASTRO "URMEL" board */ 33 34 #include <common.h> 35 #include <watchdog.h> 36 #include <altera.h> 37 #include <ACEX1K.h> 38 #include <spartan3.h> 39 #include <command.h> 40 #include <asm/immap_5329.h> 41 #include <asm/io.h> 42 #include "fpga.h" 43 44 DECLARE_GLOBAL_DATA_PTR; 45 46 int altera_pre_fn(int cookie) 47 { 48 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 49 unsigned char tmp_char; 50 unsigned short tmp_short; 51 52 /* first, set the required pins to GPIO function */ 53 /* PAR_T0IN -> GPIO */ 54 tmp_char = readb(&gpiop->par_timer); 55 tmp_char &= 0xfc; 56 writeb(tmp_char, &gpiop->par_timer); 57 /* all QSPI pins -> GPIO */ 58 writew(0x0000, &gpiop->par_qspi); 59 /* U0RTS, U0CTS -> GPIO */ 60 tmp_short = __raw_readw(&gpiop->par_uart); 61 tmp_short &= 0xfff3; 62 __raw_writew(tmp_short, &gpiop->par_uart); 63 /* all PWM pins -> GPIO */ 64 writeb(0x00, &gpiop->par_pwm); 65 /* next, set data direction registers */ 66 writeb(0x01, &gpiop->pddr_timer); 67 writeb(0x25, &gpiop->pddr_qspi); 68 writeb(0x0c, &gpiop->pddr_uart); 69 writeb(0x04, &gpiop->pddr_pwm); 70 71 /* ensure other SPI peripherals are deselected */ 72 writeb(0x08, &gpiop->ppd_uart); 73 writeb(0x38, &gpiop->ppd_qspi); 74 75 /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */ 76 writeb(0xFB, &gpiop->pclrr_uart); 77 /* enable Altera configuration by clearing QSPI_CS2 and DT0IN */ 78 writeb(0xFE, &gpiop->pclrr_timer); 79 writeb(0xDF, &gpiop->pclrr_qspi); 80 return FPGA_SUCCESS; 81 } 82 83 /* Set the state of CONFIG Pin */ 84 int altera_config_fn(int assert_config, int flush, int cookie) 85 { 86 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 87 88 if (assert_config) 89 writeb(0x04, &gpiop->ppd_uart); 90 else 91 writeb(0xFB, &gpiop->pclrr_uart); 92 return FPGA_SUCCESS; 93 } 94 95 /* Returns the state of STATUS Pin */ 96 int altera_status_fn(int cookie) 97 { 98 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 99 100 if (readb(&gpiop->ppd_pwm) & 0x08) 101 return FPGA_FAIL; 102 return FPGA_SUCCESS; 103 } 104 105 /* Returns the state of CONF_DONE Pin */ 106 int altera_done_fn(int cookie) 107 { 108 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 109 110 if (readb(&gpiop->ppd_pwm) & 0x20) 111 return FPGA_FAIL; 112 return FPGA_SUCCESS; 113 } 114 115 /* 116 * writes the complete buffer to the FPGA 117 * writing the complete buffer in one function is much faster, 118 * then calling it for every bit 119 */ 120 int altera_write_fn(void *buf, size_t len, int flush, int cookie) 121 { 122 size_t bytecount = 0; 123 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 124 unsigned char *data = (unsigned char *)buf; 125 unsigned char val = 0; 126 int i; 127 int len_40 = len / 40; 128 129 while (bytecount < len) { 130 val = data[bytecount++]; 131 i = 8; 132 do { 133 writeb(0xFB, &gpiop->pclrr_qspi); 134 if (val & 0x01) 135 writeb(0x01, &gpiop->ppd_qspi); 136 else 137 writeb(0xFE, &gpiop->pclrr_qspi); 138 writeb(0x04, &gpiop->ppd_qspi); 139 val >>= 1; 140 i--; 141 } while (i > 0); 142 143 if (bytecount % len_40 == 0) { 144 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 145 WATCHDOG_RESET(); 146 #endif 147 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 148 putc('.'); /* let them know we are alive */ 149 #endif 150 #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC 151 if (ctrlc()) 152 return FPGA_FAIL; 153 #endif 154 } 155 } 156 return FPGA_SUCCESS; 157 } 158 159 /* called, when programming is aborted */ 160 int altera_abort_fn(int cookie) 161 { 162 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 163 164 writeb(0x20, &gpiop->ppd_qspi); 165 writeb(0x08, &gpiop->ppd_uart); 166 return FPGA_SUCCESS; 167 } 168 169 /* called, when programming was succesful */ 170 int altera_post_fn(int cookie) 171 { 172 return altera_abort_fn(cookie); 173 } 174 175 /* 176 * Note that these are pointers to code that is in Flash. They will be 177 * relocated at runtime. 178 * FIXME: relocation not yet working for coldfire, see below! 179 */ 180 Altera_CYC2_Passive_Serial_fns altera_fns = { 181 altera_pre_fn, 182 altera_config_fn, 183 altera_status_fn, 184 altera_done_fn, 185 altera_write_fn, 186 altera_abort_fn, 187 altera_post_fn 188 }; 189 190 Altera_desc altera_fpga[CONFIG_FPGA_COUNT] = { 191 {Altera_CYC2, 192 passive_serial, 193 85903, 194 (void *)&altera_fns, 195 NULL, 196 0} 197 }; 198 199 /* Initialize the fpga. Return 1 on success, 0 on failure. */ 200 int astro5373l_altera_load(void) 201 { 202 int i; 203 204 for (i = 0; i < CONFIG_FPGA_COUNT; i++) { 205 /* 206 * I did not yet manage to get relocation work properly, 207 * so set stuff here instead of static initialisation: 208 */ 209 altera_fns.pre = altera_pre_fn; 210 altera_fns.config = altera_config_fn; 211 altera_fns.status = altera_status_fn; 212 altera_fns.done = altera_done_fn; 213 altera_fns.write = altera_write_fn; 214 altera_fns.abort = altera_abort_fn; 215 altera_fns.post = altera_post_fn; 216 altera_fpga[i].iface_fns = (void *)&altera_fns; 217 fpga_add(fpga_altera, &altera_fpga[i]); 218 } 219 return 1; 220 } 221 222 /* Set the FPGA's PROG_B line to the specified level */ 223 int xilinx_pgm_fn(int assert, int flush, int cookie) 224 { 225 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 226 227 if (assert) 228 writeb(0xFB, &gpiop->pclrr_uart); 229 else 230 writeb(0x04, &gpiop->ppd_uart); 231 return assert; 232 } 233 234 /* 235 * Test the state of the active-low FPGA INIT line. Return 1 on INIT 236 * asserted (low). 237 */ 238 int xilinx_init_fn(int cookie) 239 { 240 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 241 242 return (readb(&gpiop->ppd_pwm) & 0x08) == 0; 243 } 244 245 /* Test the state of the active-high FPGA DONE pin */ 246 int xilinx_done_fn(int cookie) 247 { 248 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 249 250 return (readb(&gpiop->ppd_pwm) & 0x20) >> 5; 251 } 252 253 /* Abort an FPGA operation */ 254 int xilinx_abort_fn(int cookie) 255 { 256 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 257 /* ensure all SPI peripherals and FPGAs are deselected */ 258 writeb(0x08, &gpiop->ppd_uart); 259 writeb(0x01, &gpiop->ppd_timer); 260 writeb(0x38, &gpiop->ppd_qspi); 261 return FPGA_FAIL; 262 } 263 264 /* 265 * FPGA pre-configuration function. Just make sure that 266 * FPGA reset is asserted to keep the FPGA from starting up after 267 * configuration. 268 */ 269 int xilinx_pre_config_fn(int cookie) 270 { 271 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 272 unsigned char tmp_char; 273 unsigned short tmp_short; 274 275 /* first, set the required pins to GPIO function */ 276 /* PAR_T0IN -> GPIO */ 277 tmp_char = readb(&gpiop->par_timer); 278 tmp_char &= 0xfc; 279 writeb(tmp_char, &gpiop->par_timer); 280 /* all QSPI pins -> GPIO */ 281 writew(0x0000, &gpiop->par_qspi); 282 /* U0RTS, U0CTS -> GPIO */ 283 tmp_short = __raw_readw(&gpiop->par_uart); 284 tmp_short &= 0xfff3; 285 __raw_writew(tmp_short, &gpiop->par_uart); 286 /* all PWM pins -> GPIO */ 287 writeb(0x00, &gpiop->par_pwm); 288 /* next, set data direction registers */ 289 writeb(0x01, &gpiop->pddr_timer); 290 writeb(0x25, &gpiop->pddr_qspi); 291 writeb(0x0c, &gpiop->pddr_uart); 292 writeb(0x04, &gpiop->pddr_pwm); 293 294 /* ensure other SPI peripherals are deselected */ 295 writeb(0x08, &gpiop->ppd_uart); 296 writeb(0x38, &gpiop->ppd_qspi); 297 writeb(0x01, &gpiop->ppd_timer); 298 299 /* CONFIG = 0, STATUS = 0 -> FPGA in reset state */ 300 writeb(0xFB, &gpiop->pclrr_uart); 301 /* enable Xilinx configuration by clearing QSPI_CS2 and U0CTS */ 302 writeb(0xF7, &gpiop->pclrr_uart); 303 writeb(0xDF, &gpiop->pclrr_qspi); 304 return 0; 305 } 306 307 /* 308 * FPGA post configuration function. Should perform a test if FPGA is running. 309 */ 310 int xilinx_post_config_fn(int cookie) 311 { 312 int rc = 0; 313 314 /* 315 * no test yet 316 */ 317 return rc; 318 } 319 320 int xilinx_clk_fn(int assert_clk, int flush, int cookie) 321 { 322 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 323 324 if (assert_clk) 325 writeb(0x04, &gpiop->ppd_qspi); 326 else 327 writeb(0xFB, &gpiop->pclrr_qspi); 328 return assert_clk; 329 } 330 331 int xilinx_wr_fn(int assert_write, int flush, int cookie) 332 { 333 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 334 335 if (assert_write) 336 writeb(0x01, &gpiop->ppd_qspi); 337 else 338 writeb(0xFE, &gpiop->pclrr_qspi); 339 return assert_write; 340 } 341 342 int xilinx_fastwr_fn(void *buf, size_t len, int flush, int cookie) 343 { 344 size_t bytecount = 0; 345 gpio_t *gpiop = (gpio_t *)MMAP_GPIO; 346 unsigned char *data = (unsigned char *)buf; 347 unsigned char val = 0; 348 int i; 349 int len_40 = len / 40; 350 351 for (bytecount = 0; bytecount < len; bytecount++) { 352 val = *(data++); 353 for (i = 8; i > 0; i--) { 354 writeb(0xFB, &gpiop->pclrr_qspi); 355 if (val & 0x80) 356 writeb(0x01, &gpiop->ppd_qspi); 357 else 358 writeb(0xFE, &gpiop->pclrr_qspi); 359 writeb(0x04, &gpiop->ppd_qspi); 360 val <<= 1; 361 } 362 if (bytecount % len_40 == 0) { 363 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 364 WATCHDOG_RESET(); 365 #endif 366 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK 367 putc('.'); /* let them know we are alive */ 368 #endif 369 #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC 370 if (ctrlc()) 371 return FPGA_FAIL; 372 #endif 373 } 374 } 375 return FPGA_SUCCESS; 376 } 377 378 /* 379 * Note that these are pointers to code that is in Flash. They will be 380 * relocated at runtime. 381 * FIXME: relocation not yet working for coldfire, see below! 382 */ 383 Xilinx_Spartan3_Slave_Serial_fns xilinx_fns = { 384 xilinx_pre_config_fn, 385 xilinx_pgm_fn, 386 xilinx_clk_fn, 387 xilinx_init_fn, 388 xilinx_done_fn, 389 xilinx_wr_fn, 390 0, 391 xilinx_fastwr_fn 392 }; 393 394 Xilinx_desc xilinx_fpga[CONFIG_FPGA_COUNT] = { 395 {Xilinx_Spartan3, 396 slave_serial, 397 XILINX_XC3S4000_SIZE, 398 (void *)&xilinx_fns, 399 0} 400 }; 401 402 /* Initialize the fpga. Return 1 on success, 0 on failure. */ 403 int astro5373l_xilinx_load(void) 404 { 405 int i; 406 407 fpga_init(); 408 409 for (i = 0; i < CONFIG_FPGA_COUNT; i++) { 410 /* 411 * I did not yet manage to get relocation work properly, 412 * so set stuff here instead of static initialisation: 413 */ 414 xilinx_fns.pre = xilinx_pre_config_fn; 415 xilinx_fns.pgm = xilinx_pgm_fn; 416 xilinx_fns.clk = xilinx_clk_fn; 417 xilinx_fns.init = xilinx_init_fn; 418 xilinx_fns.done = xilinx_done_fn; 419 xilinx_fns.wr = xilinx_wr_fn; 420 xilinx_fns.bwr = xilinx_fastwr_fn; 421 xilinx_fpga[i].iface_fns = (void *)&xilinx_fns; 422 fpga_add(fpga_xilinx, &xilinx_fpga[i]); 423 } 424 return 1; 425 } 426