1d5dae85fSMichal Simek /* 2d5dae85fSMichal Simek * (C) Copyright 2012-2013, Xilinx, Michal Simek 3d5dae85fSMichal Simek * 4d5dae85fSMichal Simek * (C) Copyright 2012 5d5dae85fSMichal Simek * Joe Hershberger <joe.hershberger@ni.com> 6d5dae85fSMichal Simek * 71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 8d5dae85fSMichal Simek */ 9d5dae85fSMichal Simek 10d5dae85fSMichal Simek #include <common.h> 11d5dae85fSMichal Simek #include <asm/io.h> 12d5dae85fSMichal Simek #include <zynqpl.h> 13d5dae85fSMichal Simek #include <asm/arch/hardware.h> 14d5dae85fSMichal Simek #include <asm/arch/sys_proto.h> 15d5dae85fSMichal Simek 16d5dae85fSMichal Simek #define DEVCFG_CTRL_PCFG_PROG_B 0x40000000 17d5dae85fSMichal Simek #define DEVCFG_ISR_FATAL_ERROR_MASK 0x00740040 18d5dae85fSMichal Simek #define DEVCFG_ISR_ERROR_FLAGS_MASK 0x00340840 19d5dae85fSMichal Simek #define DEVCFG_ISR_RX_FIFO_OV 0x00040000 20d5dae85fSMichal Simek #define DEVCFG_ISR_DMA_DONE 0x00002000 21d5dae85fSMichal Simek #define DEVCFG_ISR_PCFG_DONE 0x00000004 22d5dae85fSMichal Simek #define DEVCFG_STATUS_DMA_CMD_Q_F 0x80000000 23d5dae85fSMichal Simek #define DEVCFG_STATUS_DMA_CMD_Q_E 0x40000000 24d5dae85fSMichal Simek #define DEVCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 25d5dae85fSMichal Simek #define DEVCFG_STATUS_PCFG_INIT 0x00000010 26d5dae85fSMichal Simek #define DEVCFG_MCTRL_RFIFO_FLUSH 0x00000002 27d5dae85fSMichal Simek #define DEVCFG_MCTRL_WFIFO_FLUSH 0x00000001 28d5dae85fSMichal Simek 29d5dae85fSMichal Simek #ifndef CONFIG_SYS_FPGA_WAIT 30d5dae85fSMichal Simek #define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */ 31d5dae85fSMichal Simek #endif 32d5dae85fSMichal Simek 33d5dae85fSMichal Simek #ifndef CONFIG_SYS_FPGA_PROG_TIME 34*fd2b10b6SMichal Simek #define CONFIG_SYS_FPGA_PROG_TIME (CONFIG_SYS_HZ * 4) /* 4 s */ 35d5dae85fSMichal Simek #endif 36d5dae85fSMichal Simek 37d5dae85fSMichal Simek int zynq_info(Xilinx_desc *desc) 38d5dae85fSMichal Simek { 39d5dae85fSMichal Simek return FPGA_SUCCESS; 40d5dae85fSMichal Simek } 41d5dae85fSMichal Simek 42d5dae85fSMichal Simek #define DUMMY_WORD 0xffffffff 43d5dae85fSMichal Simek 44d5dae85fSMichal Simek /* Xilinx binary format header */ 45d5dae85fSMichal Simek static const u32 bin_format[] = { 46d5dae85fSMichal Simek DUMMY_WORD, /* Dummy words */ 47d5dae85fSMichal Simek DUMMY_WORD, 48d5dae85fSMichal Simek DUMMY_WORD, 49d5dae85fSMichal Simek DUMMY_WORD, 50d5dae85fSMichal Simek DUMMY_WORD, 51d5dae85fSMichal Simek DUMMY_WORD, 52d5dae85fSMichal Simek DUMMY_WORD, 53d5dae85fSMichal Simek DUMMY_WORD, 54d5dae85fSMichal Simek 0x000000bb, /* Sync word */ 55d5dae85fSMichal Simek 0x11220044, /* Sync word */ 56d5dae85fSMichal Simek DUMMY_WORD, 57d5dae85fSMichal Simek DUMMY_WORD, 58d5dae85fSMichal Simek 0xaa995566, /* Sync word */ 59d5dae85fSMichal Simek }; 60d5dae85fSMichal Simek 61d5dae85fSMichal Simek #define SWAP_NO 1 62d5dae85fSMichal Simek #define SWAP_DONE 2 63d5dae85fSMichal Simek 64d5dae85fSMichal Simek /* 65d5dae85fSMichal Simek * Load the whole word from unaligned buffer 66d5dae85fSMichal Simek * Keep in your mind that it is byte loading on little-endian system 67d5dae85fSMichal Simek */ 68d5dae85fSMichal Simek static u32 load_word(const void *buf, u32 swap) 69d5dae85fSMichal Simek { 70d5dae85fSMichal Simek u32 word = 0; 71d5dae85fSMichal Simek u8 *bitc = (u8 *)buf; 72d5dae85fSMichal Simek int p; 73d5dae85fSMichal Simek 74d5dae85fSMichal Simek if (swap == SWAP_NO) { 75d5dae85fSMichal Simek for (p = 0; p < 4; p++) { 76d5dae85fSMichal Simek word <<= 8; 77d5dae85fSMichal Simek word |= bitc[p]; 78d5dae85fSMichal Simek } 79d5dae85fSMichal Simek } else { 80d5dae85fSMichal Simek for (p = 3; p >= 0; p--) { 81d5dae85fSMichal Simek word <<= 8; 82d5dae85fSMichal Simek word |= bitc[p]; 83d5dae85fSMichal Simek } 84d5dae85fSMichal Simek } 85d5dae85fSMichal Simek 86d5dae85fSMichal Simek return word; 87d5dae85fSMichal Simek } 88d5dae85fSMichal Simek 89d5dae85fSMichal Simek static u32 check_header(const void *buf) 90d5dae85fSMichal Simek { 91d5dae85fSMichal Simek u32 i, pattern; 92d5dae85fSMichal Simek int swap = SWAP_NO; 93d5dae85fSMichal Simek u32 *test = (u32 *)buf; 94d5dae85fSMichal Simek 95d5dae85fSMichal Simek debug("%s: Let's check bitstream header\n", __func__); 96d5dae85fSMichal Simek 97d5dae85fSMichal Simek /* Checking that passing bin is not a bitstream */ 98d5dae85fSMichal Simek for (i = 0; i < ARRAY_SIZE(bin_format); i++) { 99d5dae85fSMichal Simek pattern = load_word(&test[i], swap); 100d5dae85fSMichal Simek 101d5dae85fSMichal Simek /* 102d5dae85fSMichal Simek * Bitstreams in binary format are swapped 103d5dae85fSMichal Simek * compare to regular bistream. 104d5dae85fSMichal Simek * Do not swap dummy word but if swap is done assume 105d5dae85fSMichal Simek * that parsing buffer is binary format 106d5dae85fSMichal Simek */ 107d5dae85fSMichal Simek if ((__swab32(pattern) != DUMMY_WORD) && 108d5dae85fSMichal Simek (__swab32(pattern) == bin_format[i])) { 109d5dae85fSMichal Simek pattern = __swab32(pattern); 110d5dae85fSMichal Simek swap = SWAP_DONE; 111d5dae85fSMichal Simek debug("%s: data swapped - let's swap\n", __func__); 112d5dae85fSMichal Simek } 113d5dae85fSMichal Simek 114d5dae85fSMichal Simek debug("%s: %d/%x: pattern %x/%x bin_format\n", __func__, i, 115d5dae85fSMichal Simek (u32)&test[i], pattern, bin_format[i]); 116d5dae85fSMichal Simek if (pattern != bin_format[i]) { 117d5dae85fSMichal Simek debug("%s: Bitstream is not recognized\n", __func__); 118d5dae85fSMichal Simek return 0; 119d5dae85fSMichal Simek } 120d5dae85fSMichal Simek } 121d5dae85fSMichal Simek debug("%s: Found bitstream header at %x %s swapinng\n", __func__, 122d5dae85fSMichal Simek (u32)buf, swap == SWAP_NO ? "without" : "with"); 123d5dae85fSMichal Simek 124d5dae85fSMichal Simek return swap; 125d5dae85fSMichal Simek } 126d5dae85fSMichal Simek 127d5dae85fSMichal Simek static void *check_data(u8 *buf, size_t bsize, u32 *swap) 128d5dae85fSMichal Simek { 129d5dae85fSMichal Simek u32 word, p = 0; /* possition */ 130d5dae85fSMichal Simek 131d5dae85fSMichal Simek /* Because buf doesn't need to be aligned let's read it by chars */ 132d5dae85fSMichal Simek for (p = 0; p < bsize; p++) { 133d5dae85fSMichal Simek word = load_word(&buf[p], SWAP_NO); 134d5dae85fSMichal Simek debug("%s: word %x %x/%x\n", __func__, word, p, (u32)&buf[p]); 135d5dae85fSMichal Simek 136d5dae85fSMichal Simek /* Find the first bitstream dummy word */ 137d5dae85fSMichal Simek if (word == DUMMY_WORD) { 138d5dae85fSMichal Simek debug("%s: Found dummy word at position %x/%x\n", 139d5dae85fSMichal Simek __func__, p, (u32)&buf[p]); 140d5dae85fSMichal Simek *swap = check_header(&buf[p]); 141d5dae85fSMichal Simek if (*swap) { 142d5dae85fSMichal Simek /* FIXME add full bitstream checking here */ 143d5dae85fSMichal Simek return &buf[p]; 144d5dae85fSMichal Simek } 145d5dae85fSMichal Simek } 146d5dae85fSMichal Simek /* Loop can be huge - support CTRL + C */ 147d5dae85fSMichal Simek if (ctrlc()) 148d5dae85fSMichal Simek return 0; 149d5dae85fSMichal Simek } 150d5dae85fSMichal Simek return 0; 151d5dae85fSMichal Simek } 152d5dae85fSMichal Simek 153d5dae85fSMichal Simek 154d5dae85fSMichal Simek int zynq_load(Xilinx_desc *desc, const void *buf, size_t bsize) 155d5dae85fSMichal Simek { 156d5dae85fSMichal Simek unsigned long ts; /* Timestamp */ 157d5dae85fSMichal Simek u32 partialbit = 0; 158d5dae85fSMichal Simek u32 i, control, isr_status, status, swap, diff; 159d5dae85fSMichal Simek u32 *buf_start; 160d5dae85fSMichal Simek 161d5dae85fSMichal Simek /* Detect if we are going working with partial or full bitstream */ 162d5dae85fSMichal Simek if (bsize != desc->size) { 163d5dae85fSMichal Simek printf("%s: Working with partial bitstream\n", __func__); 164d5dae85fSMichal Simek partialbit = 1; 165d5dae85fSMichal Simek } 166d5dae85fSMichal Simek 167d5dae85fSMichal Simek buf_start = check_data((u8 *)buf, bsize, &swap); 168d5dae85fSMichal Simek if (!buf_start) 169d5dae85fSMichal Simek return FPGA_FAIL; 170d5dae85fSMichal Simek 171d5dae85fSMichal Simek /* Check if data is postpone from start */ 172d5dae85fSMichal Simek diff = (u32)buf_start - (u32)buf; 173d5dae85fSMichal Simek if (diff) { 174d5dae85fSMichal Simek printf("%s: Bitstream is not validated yet (diff %x)\n", 175d5dae85fSMichal Simek __func__, diff); 176d5dae85fSMichal Simek return FPGA_FAIL; 177d5dae85fSMichal Simek } 178d5dae85fSMichal Simek 179d5dae85fSMichal Simek if ((u32)buf_start & 0x3) { 180d5dae85fSMichal Simek u32 *new_buf = (u32 *)((u32)buf & ~0x3); 181d5dae85fSMichal Simek 182d5dae85fSMichal Simek printf("%s: Align buffer at %x to %x(swap %d)\n", __func__, 183d5dae85fSMichal Simek (u32)buf_start, (u32)new_buf, swap); 184d5dae85fSMichal Simek 185d5dae85fSMichal Simek for (i = 0; i < (bsize/4); i++) 186d5dae85fSMichal Simek new_buf[i] = load_word(&buf_start[i], swap); 187d5dae85fSMichal Simek 188d5dae85fSMichal Simek swap = SWAP_DONE; 189d5dae85fSMichal Simek buf = new_buf; 190d5dae85fSMichal Simek } else if (swap != SWAP_DONE) { 191d5dae85fSMichal Simek /* For bitstream which are aligned */ 192d5dae85fSMichal Simek u32 *new_buf = (u32 *)buf; 193d5dae85fSMichal Simek 194d5dae85fSMichal Simek printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__, 195d5dae85fSMichal Simek swap); 196d5dae85fSMichal Simek 197d5dae85fSMichal Simek for (i = 0; i < (bsize/4); i++) 198d5dae85fSMichal Simek new_buf[i] = load_word(&buf_start[i], swap); 199d5dae85fSMichal Simek 200d5dae85fSMichal Simek swap = SWAP_DONE; 201d5dae85fSMichal Simek } 202d5dae85fSMichal Simek 203d5dae85fSMichal Simek if (!partialbit) { 204d5dae85fSMichal Simek zynq_slcr_devcfg_disable(); 205d5dae85fSMichal Simek 206d5dae85fSMichal Simek /* Setting PCFG_PROG_B signal to high */ 207d5dae85fSMichal Simek control = readl(&devcfg_base->ctrl); 208d5dae85fSMichal Simek writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); 209d5dae85fSMichal Simek /* Setting PCFG_PROG_B signal to low */ 210d5dae85fSMichal Simek writel(control & ~DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); 211d5dae85fSMichal Simek 212d5dae85fSMichal Simek /* Polling the PCAP_INIT status for Reset */ 213d5dae85fSMichal Simek ts = get_timer(0); 214d5dae85fSMichal Simek while (readl(&devcfg_base->status) & DEVCFG_STATUS_PCFG_INIT) { 215d5dae85fSMichal Simek if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { 216d5dae85fSMichal Simek printf("%s: Timeout wait for INIT to clear\n", 217d5dae85fSMichal Simek __func__); 218d5dae85fSMichal Simek return FPGA_FAIL; 219d5dae85fSMichal Simek } 220d5dae85fSMichal Simek } 221d5dae85fSMichal Simek 222d5dae85fSMichal Simek /* Setting PCFG_PROG_B signal to high */ 223d5dae85fSMichal Simek writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); 224d5dae85fSMichal Simek 225d5dae85fSMichal Simek /* Polling the PCAP_INIT status for Set */ 226d5dae85fSMichal Simek ts = get_timer(0); 227d5dae85fSMichal Simek while (!(readl(&devcfg_base->status) & 228d5dae85fSMichal Simek DEVCFG_STATUS_PCFG_INIT)) { 229d5dae85fSMichal Simek if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { 230d5dae85fSMichal Simek printf("%s: Timeout wait for INIT to set\n", 231d5dae85fSMichal Simek __func__); 232d5dae85fSMichal Simek return FPGA_FAIL; 233d5dae85fSMichal Simek } 234d5dae85fSMichal Simek } 235d5dae85fSMichal Simek } 236d5dae85fSMichal Simek 237d5dae85fSMichal Simek isr_status = readl(&devcfg_base->int_sts); 238d5dae85fSMichal Simek 239d5dae85fSMichal Simek /* Clear it all, so if Boot ROM comes back, it can proceed */ 240d5dae85fSMichal Simek writel(0xFFFFFFFF, &devcfg_base->int_sts); 241d5dae85fSMichal Simek 242d5dae85fSMichal Simek if (isr_status & DEVCFG_ISR_FATAL_ERROR_MASK) { 243d5dae85fSMichal Simek debug("%s: Fatal errors in PCAP 0x%X\n", __func__, isr_status); 244d5dae85fSMichal Simek 245d5dae85fSMichal Simek /* If RX FIFO overflow, need to flush RX FIFO first */ 246d5dae85fSMichal Simek if (isr_status & DEVCFG_ISR_RX_FIFO_OV) { 247d5dae85fSMichal Simek writel(DEVCFG_MCTRL_RFIFO_FLUSH, &devcfg_base->mctrl); 248d5dae85fSMichal Simek writel(0xFFFFFFFF, &devcfg_base->int_sts); 249d5dae85fSMichal Simek } 250d5dae85fSMichal Simek return FPGA_FAIL; 251d5dae85fSMichal Simek } 252d5dae85fSMichal Simek 253d5dae85fSMichal Simek status = readl(&devcfg_base->status); 254d5dae85fSMichal Simek 255d5dae85fSMichal Simek debug("%s: Status = 0x%08X\n", __func__, status); 256d5dae85fSMichal Simek 257d5dae85fSMichal Simek if (status & DEVCFG_STATUS_DMA_CMD_Q_F) { 258d5dae85fSMichal Simek debug("%s: Error: device busy\n", __func__); 259d5dae85fSMichal Simek return FPGA_FAIL; 260d5dae85fSMichal Simek } 261d5dae85fSMichal Simek 262d5dae85fSMichal Simek debug("%s: Device ready\n", __func__); 263d5dae85fSMichal Simek 264d5dae85fSMichal Simek if (!(status & DEVCFG_STATUS_DMA_CMD_Q_E)) { 265d5dae85fSMichal Simek if (!(readl(&devcfg_base->int_sts) & DEVCFG_ISR_DMA_DONE)) { 266d5dae85fSMichal Simek /* Error state, transfer cannot occur */ 267d5dae85fSMichal Simek debug("%s: ISR indicates error\n", __func__); 268d5dae85fSMichal Simek return FPGA_FAIL; 269d5dae85fSMichal Simek } else { 270d5dae85fSMichal Simek /* Clear out the status */ 271d5dae85fSMichal Simek writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts); 272d5dae85fSMichal Simek } 273d5dae85fSMichal Simek } 274d5dae85fSMichal Simek 275d5dae85fSMichal Simek if (status & DEVCFG_STATUS_DMA_DONE_CNT_MASK) { 276d5dae85fSMichal Simek /* Clear the count of completed DMA transfers */ 277d5dae85fSMichal Simek writel(DEVCFG_STATUS_DMA_DONE_CNT_MASK, &devcfg_base->status); 278d5dae85fSMichal Simek } 279d5dae85fSMichal Simek 280d5dae85fSMichal Simek debug("%s: Source = 0x%08X\n", __func__, (u32)buf); 281d5dae85fSMichal Simek debug("%s: Size = %zu\n", __func__, bsize); 282d5dae85fSMichal Simek 283d5dae85fSMichal Simek /* Set up the transfer */ 284d5dae85fSMichal Simek writel((u32)buf | 1, &devcfg_base->dma_src_addr); 285d5dae85fSMichal Simek writel(0xFFFFFFFF, &devcfg_base->dma_dst_addr); 286d5dae85fSMichal Simek writel(bsize >> 2, &devcfg_base->dma_src_len); 287d5dae85fSMichal Simek writel(0, &devcfg_base->dma_dst_len); 288d5dae85fSMichal Simek 289d5dae85fSMichal Simek isr_status = readl(&devcfg_base->int_sts); 290d5dae85fSMichal Simek 291d5dae85fSMichal Simek /* Polling the PCAP_INIT status for Set */ 292d5dae85fSMichal Simek ts = get_timer(0); 293d5dae85fSMichal Simek while (!(isr_status & DEVCFG_ISR_DMA_DONE)) { 294d5dae85fSMichal Simek if (isr_status & DEVCFG_ISR_ERROR_FLAGS_MASK) { 295d5dae85fSMichal Simek debug("%s: Error: isr = 0x%08X\n", __func__, 296d5dae85fSMichal Simek isr_status); 297d5dae85fSMichal Simek debug("%s: Write count = 0x%08X\n", __func__, 298d5dae85fSMichal Simek readl(&devcfg_base->write_count)); 299d5dae85fSMichal Simek debug("%s: Read count = 0x%08X\n", __func__, 300d5dae85fSMichal Simek readl(&devcfg_base->read_count)); 301d5dae85fSMichal Simek 302d5dae85fSMichal Simek return FPGA_FAIL; 303d5dae85fSMichal Simek } 304d5dae85fSMichal Simek if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) { 305d5dae85fSMichal Simek printf("%s: Timeout wait for DMA to complete\n", 306d5dae85fSMichal Simek __func__); 307d5dae85fSMichal Simek return FPGA_FAIL; 308d5dae85fSMichal Simek } 309d5dae85fSMichal Simek isr_status = readl(&devcfg_base->int_sts); 310d5dae85fSMichal Simek } 311d5dae85fSMichal Simek 312d5dae85fSMichal Simek debug("%s: DMA transfer is done\n", __func__); 313d5dae85fSMichal Simek 314d5dae85fSMichal Simek /* Check FPGA configuration completion */ 315d5dae85fSMichal Simek ts = get_timer(0); 316d5dae85fSMichal Simek while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) { 317d5dae85fSMichal Simek if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { 318d5dae85fSMichal Simek printf("%s: Timeout wait for FPGA to config\n", 319d5dae85fSMichal Simek __func__); 320d5dae85fSMichal Simek return FPGA_FAIL; 321d5dae85fSMichal Simek } 322d5dae85fSMichal Simek isr_status = readl(&devcfg_base->int_sts); 323d5dae85fSMichal Simek } 324d5dae85fSMichal Simek 325d5dae85fSMichal Simek debug("%s: FPGA config done\n", __func__); 326d5dae85fSMichal Simek 327d5dae85fSMichal Simek /* Clear out the DMA status */ 328d5dae85fSMichal Simek writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts); 329d5dae85fSMichal Simek 330d5dae85fSMichal Simek if (!partialbit) 331d5dae85fSMichal Simek zynq_slcr_devcfg_enable(); 332d5dae85fSMichal Simek 333d5dae85fSMichal Simek return FPGA_SUCCESS; 334d5dae85fSMichal Simek } 335d5dae85fSMichal Simek 336d5dae85fSMichal Simek int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize) 337d5dae85fSMichal Simek { 338d5dae85fSMichal Simek return FPGA_FAIL; 339d5dae85fSMichal Simek } 340