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