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 27int 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 */ 65int 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 */ 77int 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 */ 87int 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 */ 101int 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 schedule(); 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 */ 141int 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 */ 151int 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 */ 161Altera_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#define FPGA_COUNT 1 172Altera_desc altera_fpga[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. */ 182int astro5373l_altera_load(void) 183{ 184 int i; 185 186 for (i = 0; i < 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 */ 205int 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 */ 220int 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 */ 228int 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 */ 236int 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 */ 251int 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 */ 292int xilinx_post_config_fn(int cookie) 293{ 294 int rc = 0; 295 296 /* 297 * no test yet 298 */ 299 return rc; 300} 301 302int 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 313int 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 324int 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 schedule(); 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 */ 365xilinx_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 376xilinx_desc xilinx_fpga[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. */ 386int astro5373l_xilinx_load(void) 387{ 388 int i; 389 390 fpga_init(); 391 392 for (i = 0; i < 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