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