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