Home | History | Annotate | Download | only in mcf5373l
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2006
      4  * Wolfgang Wegner, ASTRO Strobel Kommunikationssysteme GmbH,
      5  * w.wegner (at) astro-kom.de
      6  *
      7  * based on the files by
      8  * Heiko Schocher, DENX Software Engineering, hs (at) denx.de
      9  * and
     10  * Rich Ireland, Enterasys Networks, rireland (at) enterasys.com.
     11  * Keith Outwater, keith_outwater (at) 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