diff options
29 files changed, 1492 insertions, 436 deletions
diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c index 788a8fd14f..52048c6766 100644 --- a/arch/arm/cpu/armv7/zynq/slcr.c +++ b/arch/arm/cpu/armv7/zynq/slcr.c @@ -28,6 +28,9 @@ #define SLCR_LOCK_MAGIC 0x767B #define SLCR_UNLOCK_MAGIC 0xDF0D +#define SLCR_IDCODE_MASK 0x1F000 +#define SLCR_IDCODE_SHIFT 12 + static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */ void zynq_slcr_lock(void) @@ -61,3 +64,61 @@ void zynq_slcr_cpu_reset(void) writel(1, &slcr_base->pss_rst_ctrl); } + +/* Setup clk for network */ +void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk) +{ + zynq_slcr_unlock(); + + if (gem_id > 1) { + printf("Non existing GEM id %d\n", gem_id); + goto out; + } + + if (gem_id) { + /* Set divisors for appropriate frequency in GEM_CLK_CTRL */ + writel(clk, &slcr_base->gem1_clk_ctrl); + /* Configure GEM_RCLK_CTRL */ + writel(rclk, &slcr_base->gem1_rclk_ctrl); + } else { + /* Set divisors for appropriate frequency in GEM_CLK_CTRL */ + writel(clk, &slcr_base->gem0_clk_ctrl); + /* Configure GEM_RCLK_CTRL */ + writel(rclk, &slcr_base->gem0_rclk_ctrl); + } + +out: + zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_disable(void) +{ + zynq_slcr_unlock(); + + /* Disable AXI interface */ + writel(0xFFFFFFFF, &slcr_base->fpga_rst_ctrl); + + /* Set Level Shifters DT618760 */ + writel(0xA, &slcr_base->lvl_shftr_en); + + zynq_slcr_lock(); +} + +void zynq_slcr_devcfg_enable(void) +{ + zynq_slcr_unlock(); + + /* Set Level Shifters DT618760 */ + writel(0xF, &slcr_base->lvl_shftr_en); + + /* Disable AXI interface */ + writel(0x0, &slcr_base->fpga_rst_ctrl); + + zynq_slcr_lock(); +} + +u32 zynq_slcr_get_idcode(void) +{ + return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >> + SLCR_IDCODE_SHIFT; +} diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c index 45b405a4ba..8c4357de42 100644 --- a/arch/arm/cpu/armv7/zynq/timer.c +++ b/arch/arm/cpu/armv7/zynq/timer.c @@ -44,6 +44,7 @@ #include <common.h> #include <div64.h> #include <asm/io.h> +#include <asm/arch/hardware.h> DECLARE_GLOBAL_DATA_PTR; @@ -54,7 +55,7 @@ struct scu_timer { }; static struct scu_timer *timer_base = - (struct scu_timer *) CONFIG_SCUTIMER_BASEADDR; + (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR; #define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */ #define SCUTIMER_CONTROL_PRESCALER_SHIFT 8 @@ -114,15 +115,43 @@ ulong get_timer_masked(void) void __udelay(unsigned long usec) { - unsigned long long tmp; - ulong tmo; - - tmo = usec / (1000000 / CONFIG_SYS_HZ); - tmp = get_ticks() + tmo; /* Get current timestamp */ - - while (get_ticks() < tmp) { /* Loop till event */ - /* NOP */; - } + u32 countticks; + u32 timeend; + u32 timediff; + u32 timenow; + + if (usec == 0) + return; + + countticks = (u32) (((unsigned long long) TIMER_TICK_HZ * usec) / + 1000000); + + /* decrementing timer */ + timeend = readl(&timer_base->counter) - countticks; + +#if TIMER_LOAD_VAL != 0xFFFFFFFF + /* do not manage multiple overflow */ + if (countticks >= TIMER_LOAD_VAL) + countticks = TIMER_LOAD_VAL - 1; +#endif + + do { + timenow = readl(&timer_base->counter); + + if (timenow >= timeend) { + /* normal case */ + timediff = timenow - timeend; + } else { + if ((TIMER_LOAD_VAL - timeend + timenow) <= + countticks) { + /* overflow */ + timediff = TIMER_LOAD_VAL - timeend + timenow; + } else { + /* missed the exact match */ + break; + } + } + } while (timediff > 0); } /* Timer without interrupts */ diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h index d0c69da971..8b8a91ae65 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/include/asm/arch-zynq/hardware.h @@ -23,16 +23,28 @@ #ifndef _ASM_ARCH_HARDWARE_H #define _ASM_ARCH_HARDWARE_H -#define XPSS_SYS_CTRL_BASEADDR 0xF8000000 -#define XPSS_DEV_CFG_APB_BASEADDR 0xF8007000 -#define XPSS_SCU_BASEADDR 0xF8F00000 +#define ZYNQ_SYS_CTRL_BASEADDR 0xF8000000 +#define ZYNQ_DEV_CFG_APB_BASEADDR 0xF8007000 +#define ZYNQ_SCU_BASEADDR 0xF8F00000 +#define ZYNQ_SCUTIMER_BASEADDR 0xF8F00600 +#define ZYNQ_GEM_BASEADDR0 0xE000B000 +#define ZYNQ_GEM_BASEADDR1 0xE000C000 +#define ZYNQ_SDHCI_BASEADDR0 0xE0100000 +#define ZYNQ_SDHCI_BASEADDR1 0xE0101000 +#define ZYNQ_I2C_BASEADDR0 0xE0004000 +#define ZYNQ_I2C_BASEADDR1 0xE0005000 /* Reflect slcr offsets */ struct slcr_regs { u32 scl; /* 0x0 */ u32 slcr_lock; /* 0x4 */ u32 slcr_unlock; /* 0x8 */ - u32 reserved1[125]; + u32 reserved0[75]; + u32 gem0_rclk_ctrl; /* 0x138 */ + u32 gem1_rclk_ctrl; /* 0x13c */ + u32 gem0_clk_ctrl; /* 0x140 */ + u32 gem1_clk_ctrl; /* 0x144 */ + u32 reserved1[46]; u32 pss_rst_ctrl; /* 0x200 */ u32 reserved2[15]; u32 fpga_rst_ctrl; /* 0x240 */ @@ -41,15 +53,21 @@ struct slcr_regs { u32 boot_mode; /* 0x25c */ u32 reserved4[116]; u32 trust_zone; /* 0x430 */ /* FIXME */ - u32 reserved5[115]; + u32 reserved5_1[63]; + u32 pss_idcode; /* 0x530 */ + u32 reserved5_2[51]; u32 ddr_urgent; /* 0x600 */ u32 reserved6[6]; u32 ddr_urgent_sel; /* 0x61c */ - u32 reserved7[188]; + u32 reserved7[56]; + u32 mio_pin[54]; /* 0x700 - 0x7D4 */ + u32 reserved8[74]; + u32 lvl_shftr_en; /* 0x900 */ + u32 reserved9[3]; u32 ocm_cfg; /* 0x910 */ }; -#define slcr_base ((struct slcr_regs *) XPSS_SYS_CTRL_BASEADDR) +#define slcr_base ((struct slcr_regs *)ZYNQ_SYS_CTRL_BASEADDR) struct devcfg_regs { u32 ctrl; /* 0x0 */ @@ -72,7 +90,7 @@ struct devcfg_regs { u32 read_count; /* 0x8c */ }; -#define devcfg_base ((struct devcfg_regs *) XPSS_DEV_CFG_APB_BASEADDR) +#define devcfg_base ((struct devcfg_regs *)ZYNQ_DEV_CFG_APB_BASEADDR) struct scu_regs { u32 reserved1[16]; @@ -80,6 +98,6 @@ struct scu_regs { u32 filter_end; /* 0x44 */ }; -#define scu_base ((struct scu_regs *) XPSS_SCU_BASEADDR) +#define scu_base ((struct scu_regs *)ZYNQ_SCU_BASEADDR) #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/include/asm/arch-zynq/sys_proto.h index e78890011a..2317121ca6 100644 --- a/arch/arm/include/asm/arch-zynq/sys_proto.h +++ b/arch/arm/include/asm/arch-zynq/sys_proto.h @@ -26,5 +26,12 @@ extern void zynq_slcr_lock(void); extern void zynq_slcr_unlock(void); extern void zynq_slcr_cpu_reset(void); +extern void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk); +extern void zynq_slcr_devcfg_disable(void); +extern void zynq_slcr_devcfg_enable(void); +extern u32 zynq_slcr_get_idcode(void); + +/* Driver extern functions */ +extern int zynq_sdhci_init(u32 regbase); #endif /* _SYS_PROTO_H_ */ diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 8ed75c3d38..b02c364dc9 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -22,13 +22,52 @@ #include <common.h> #include <netdev.h> +#include <zynqpl.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> DECLARE_GLOBAL_DATA_PTR; +#ifdef CONFIG_FPGA +Xilinx_desc fpga; + +/* It can be done differently */ +Xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10); +Xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20); +Xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30); +Xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45); +#endif + int board_init(void) { +#ifdef CONFIG_FPGA + u32 idcode; + + idcode = zynq_slcr_get_idcode(); + + switch (idcode) { + case XILINX_ZYNQ_7010: + fpga = fpga010; + break; + case XILINX_ZYNQ_7020: + fpga = fpga020; + break; + case XILINX_ZYNQ_7030: + fpga = fpga030; + break; + case XILINX_ZYNQ_7045: + fpga = fpga045; + break; + } +#endif + icache_enable(); +#ifdef CONFIG_FPGA + fpga_init(); + fpga_add(fpga_xilinx, &fpga); +#endif + return 0; } @@ -38,10 +77,33 @@ int board_eth_init(bd_t *bis) { u32 ret = 0; -#if defined(CONFIG_ZYNQ_GEM) && defined(CONFIG_ZYNQ_GEM_BASEADDR0) - ret = zynq_gem_initialize(bis, CONFIG_ZYNQ_GEM_BASEADDR0); +#if defined(CONFIG_ZYNQ_GEM) +# if defined(CONFIG_ZYNQ_GEM0) + ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR0, + CONFIG_ZYNQ_GEM_PHY_ADDR0, 0); +# endif +# if defined(CONFIG_ZYNQ_GEM1) + ret |= zynq_gem_initialize(bis, ZYNQ_GEM_BASEADDR1, + CONFIG_ZYNQ_GEM_PHY_ADDR1, 0); +# endif +#endif + return ret; +} #endif +#ifdef CONFIG_CMD_MMC +int board_mmc_init(bd_t *bd) +{ + int ret = 0; + +#if defined(CONFIG_ZYNQ_SDHCI) +# if defined(CONFIG_ZYNQ_SDHCI0) + ret = zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR0); +# endif +# if defined(CONFIG_ZYNQ_SDHCI1) + ret |= zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR1); +# endif +#endif return ret; } #endif diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index 1834246f30..5e1d037853 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -27,14 +27,11 @@ */ #include <common.h> #include <command.h> -#if defined(CONFIG_CMD_NET) -#include <net.h> -#endif #include <fpga.h> #include <malloc.h> /* Local functions */ -static int fpga_get_op (char *opstr); +static int fpga_get_op(char *opstr); /* Local defines */ #define FPGA_NONE -1 @@ -44,102 +41,6 @@ static int fpga_get_op (char *opstr); #define FPGA_DUMP 3 #define FPGA_LOADMK 4 -/* Convert bitstream data and load into the fpga */ -int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size) -{ -#if defined(CONFIG_FPGA_XILINX) - unsigned int length; - unsigned int swapsize; - char buffer[80]; - unsigned char *dataptr; - unsigned int i; - int rc; - - dataptr = (unsigned char *)fpgadata; - - /* skip the first bytes of the bitsteam, their meaning is unknown */ - length = (*dataptr << 8) + *(dataptr+1); - dataptr+=2; - dataptr+=length; - - /* get design name (identifier, length, string) */ - length = (*dataptr << 8) + *(dataptr+1); - dataptr+=2; - if (*dataptr++ != 0x61) { - debug("%s: Design name identifier not recognized " - "in bitstream\n", - __func__); - return FPGA_FAIL; - } - - length = (*dataptr << 8) + *(dataptr+1); - dataptr+=2; - for(i=0;i<length;i++) - buffer[i] = *dataptr++; - - printf(" design filename = \"%s\"\n", buffer); - - /* get part number (identifier, length, string) */ - if (*dataptr++ != 0x62) { - printf("%s: Part number identifier not recognized " - "in bitstream\n", - __func__); - return FPGA_FAIL; - } - - length = (*dataptr << 8) + *(dataptr+1); - dataptr+=2; - for(i=0;i<length;i++) - buffer[i] = *dataptr++; - printf(" part number = \"%s\"\n", buffer); - - /* get date (identifier, length, string) */ - if (*dataptr++ != 0x63) { - printf("%s: Date identifier not recognized in bitstream\n", - __func__); - return FPGA_FAIL; - } - - length = (*dataptr << 8) + *(dataptr+1); - dataptr+=2; - for(i=0;i<length;i++) - buffer[i] = *dataptr++; - printf(" date = \"%s\"\n", buffer); - - /* get time (identifier, length, string) */ - if (*dataptr++ != 0x64) { - printf("%s: Time identifier not recognized in bitstream\n", - __func__); - return FPGA_FAIL; - } - - length = (*dataptr << 8) + *(dataptr+1); - dataptr+=2; - for(i=0;i<length;i++) - buffer[i] = *dataptr++; - printf(" time = \"%s\"\n", buffer); - - /* get fpga data length (identifier, length) */ - if (*dataptr++ != 0x65) { - printf("%s: Data length identifier not recognized in bitstream\n", - __func__); - return FPGA_FAIL; - } - swapsize = ((unsigned int) *dataptr <<24) + - ((unsigned int) *(dataptr+1) <<16) + - ((unsigned int) *(dataptr+2) <<8 ) + - ((unsigned int) *(dataptr+3) ) ; - dataptr+=4; - printf(" bytes in bitstream = %d\n", swapsize); - - rc = fpga_load(dev, dataptr, swapsize); - return rc; -#else - printf("Bitstream support only for Xilinx devices\n"); - return FPGA_FAIL; -#endif -} - /* ------------------------------------------------------------------------- */ /* command form: * fpga <op> <device number> <data addr> <datasize> @@ -148,81 +49,81 @@ int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size) * If there is no data addr field, the fpgadata environment variable is used. * The info command requires no data address field. */ -int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int op, dev = FPGA_INVALID_DEVICE; size_t data_size = 0; void *fpga_data = NULL; - char *devstr = getenv ("fpga"); - char *datastr = getenv ("fpgadata"); + char *devstr = getenv("fpga"); + char *datastr = getenv("fpgadata"); int rc = FPGA_FAIL; int wrong_parms = 0; -#if defined (CONFIG_FIT) +#if defined(CONFIG_FIT) const char *fit_uname = NULL; ulong fit_addr; #endif if (devstr) - dev = (int) simple_strtoul (devstr, NULL, 16); + dev = (int) simple_strtoul(devstr, NULL, 16); if (datastr) - fpga_data = (void *) simple_strtoul (datastr, NULL, 16); + fpga_data = (void *)simple_strtoul(datastr, NULL, 16); switch (argc) { case 5: /* fpga <op> <dev> <data> <datasize> */ - data_size = simple_strtoul (argv[4], NULL, 16); + data_size = simple_strtoul(argv[4], NULL, 16); case 4: /* fpga <op> <dev> <data> */ #if defined(CONFIG_FIT) - if (fit_parse_subimage (argv[3], (ulong)fpga_data, - &fit_addr, &fit_uname)) { + if (fit_parse_subimage(argv[3], (ulong)fpga_data, + &fit_addr, &fit_uname)) { fpga_data = (void *)fit_addr; - debug("* fpga: subimage '%s' from FIT image " - "at 0x%08lx\n", - fit_uname, fit_addr); + debug("* fpga: subimage '%s' from FIT image ", + fit_uname); + debug("at 0x%08lx\n", fit_addr); } else #endif { - fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); + fpga_data = (void *)simple_strtoul(argv[3], NULL, 16); debug("* fpga: cmdline image address = 0x%08lx\n", - (ulong)fpga_data); + (ulong)fpga_data); } - debug("%s: fpga_data = 0x%x\n", __func__, (uint) fpga_data); + debug("%s: fpga_data = 0x%x\n", __func__, (uint)fpga_data); case 3: /* fpga <op> <dev | data addr> */ - dev = (int) simple_strtoul (argv[2], NULL, 16); + dev = (int)simple_strtoul(argv[2], NULL, 16); debug("%s: device = %d\n", __func__, dev); /* FIXME - this is a really weak test */ - if ((argc == 3) && (dev > fpga_count ())) { /* must be buffer ptr */ + if ((argc == 3) && (dev > fpga_count())) { + /* must be buffer ptr */ debug("%s: Assuming buffer pointer in arg 3\n", - __func__); + __func__); #if defined(CONFIG_FIT) - if (fit_parse_subimage (argv[2], (ulong)fpga_data, - &fit_addr, &fit_uname)) { + if (fit_parse_subimage(argv[2], (ulong)fpga_data, + &fit_addr, &fit_uname)) { fpga_data = (void *)fit_addr; - debug("* fpga: subimage '%s' from FIT image " - "at 0x%08lx\n", - fit_uname, fit_addr); + debug("* fpga: subimage '%s' from FIT image ", + fit_uname); + debug("at 0x%08lx\n", fit_addr); } else #endif { - fpga_data = (void *) dev; - debug("* fpga: cmdline image address = " - "0x%08lx\n", (ulong)fpga_data); + fpga_data = (void *)dev; + debug("* fpga: cmdline image addr = 0x%08lx\n", + (ulong)fpga_data); } debug("%s: fpga_data = 0x%x\n", - __func__, (uint) fpga_data); + __func__, (uint)fpga_data); dev = FPGA_INVALID_DEVICE; /* reset device num */ } case 2: /* fpga <op> */ - op = (int) fpga_get_op (argv[1]); + op = (int)fpga_get_op(argv[1]); break; default: - debug("%s: Too many or too few args (%d)\n", - __func__, argc); + debug("%s: Too many or too few args (%d)\n", __func__, argc); op = FPGA_NONE; /* force usage display */ break; } @@ -258,11 +159,11 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; case FPGA_INFO: - rc = fpga_info (dev); + rc = fpga_info(dev); break; case FPGA_LOAD: - rc = fpga_load (dev, fpga_data, data_size); + rc = fpga_load(dev, fpga_data, data_size); break; case FPGA_LOADB: @@ -270,15 +171,16 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) break; case FPGA_LOADMK: - switch (genimg_get_format (fpga_data)) { + switch (genimg_get_format(fpga_data)) { case IMAGE_FORMAT_LEGACY: { - image_header_t *hdr = (image_header_t *)fpga_data; - ulong data; + image_header_t *hdr = + (image_header_t *)fpga_data; + ulong data; - data = (ulong)image_get_data (hdr); - data_size = image_get_data_size (hdr); - rc = fpga_load (dev, (void *)data, data_size); + data = (ulong)image_get_data(hdr); + data_size = image_get_data_size(hdr); + rc = fpga_load(dev, (void *)data, data_size); } break; #if defined(CONFIG_FIT) @@ -289,95 +191,97 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) const void *fit_data; if (fit_uname == NULL) { - puts ("No FIT subimage unit name\n"); + puts("No FIT subimage unit name\n"); return 1; } - if (!fit_check_format (fit_hdr)) { - puts ("Bad FIT image format\n"); + if (!fit_check_format(fit_hdr)) { + puts("Bad FIT image format\n"); return 1; } /* get fpga component image node offset */ - noffset = fit_image_get_node (fit_hdr, fit_uname); + noffset = fit_image_get_node(fit_hdr, + fit_uname); if (noffset < 0) { - printf ("Can't find '%s' FIT subimage\n", fit_uname); + printf("Can't find '%s' FIT subimage\n", + fit_uname); return 1; } /* verify integrity */ - if (!fit_image_check_hashes (fit_hdr, noffset)) { - puts ("Bad Data Hash\n"); + if (!fit_image_check_hashes(fit_hdr, noffset)) { + puts("Bad Data Hash\n"); return 1; } /* get fpga subimage data address and length */ - if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) { - puts ("Could not find fpga subimage data\n"); + if (fit_image_get_data(fit_hdr, noffset, + &fit_data, &data_size)) { + puts("Fpga subimage data not found\n"); return 1; } - rc = fpga_load (dev, fit_data, data_size); + rc = fpga_load(dev, fit_data, data_size); } break; #endif default: - puts ("** Unknown image type\n"); + puts("** Unknown image type\n"); rc = FPGA_FAIL; break; } break; case FPGA_DUMP: - rc = fpga_dump (dev, fpga_data, data_size); + rc = fpga_dump(dev, fpga_data, data_size); break; default: - printf ("Unknown operation\n"); + printf("Unknown operation\n"); return CMD_RET_USAGE; } - return (rc); + return rc; } /* * Map op to supported operations. We don't use a table since we * would just have to relocate it from flash anyway. */ -static int fpga_get_op (char *opstr) +static int fpga_get_op(char *opstr) { int op = FPGA_NONE; - if (!strcmp ("info", opstr)) { + if (!strcmp("info", opstr)) op = FPGA_INFO; - } else if (!strcmp ("loadb", opstr)) { + else if (!strcmp("loadb", opstr)) op = FPGA_LOADB; - } else if (!strcmp ("load", opstr)) { + else if (!strcmp("load", opstr)) op = FPGA_LOAD; - } else if (!strcmp ("loadmk", opstr)) { + else if (!strcmp("loadmk", opstr)) op = FPGA_LOADMK; - } else if (!strcmp ("dump", opstr)) { + else if (!strcmp("dump", opstr)) op = FPGA_DUMP; - } - if (op == FPGA_NONE) { - printf ("Unknown fpga operation \"%s\"\n", opstr); - } + if (op == FPGA_NONE) + printf("Unknown fpga operation \"%s\"\n", opstr); + return op; } -U_BOOT_CMD (fpga, 6, 1, do_fpga, - "loadable FPGA image support", - "[operation type] [device number] [image address] [image size]\n" - "fpga operations:\n" - " dump\t[dev]\t\t\tLoad device to memory buffer\n" - " info\t[dev]\t\t\tlist known device information\n" - " load\t[dev] [address] [size]\tLoad device from memory buffer\n" - " loadb\t[dev] [address] [size]\t" - "Load device from bitstream buffer (Xilinx only)\n" - " loadmk [dev] [address]\tLoad device generated with mkimage" +U_BOOT_CMD(fpga, 6, 1, do_fpga, + "loadable FPGA image support", + "[operation type] [device number] [image address] [image size]\n" + "fpga operations:\n" + " dump\t[dev]\t\t\tLoad device to memory buffer\n" + " info\t[dev]\t\t\tlist known device information\n" + " load\t[dev] [address] [size]\tLoad device from memory buffer\n" + " loadb\t[dev] [address] [size]\t" + "Load device from bitstream buffer (Xilinx only)\n" + " loadmk [dev] [address]\tLoad device generated with mkimage" #if defined(CONFIG_FIT) - "\n" - "\tFor loadmk operating on FIT format uImage address must include\n" - "\tsubimage unit name in the form of addr:<subimg_uname>" + "\n" + "\tFor loadmk operating on FIT format uImage address must include\n" + "\tsubimage unit name in the form of addr:<subimg_uname>" #endif ); diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index b48f623c18..0b51dcdef3 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -30,6 +30,7 @@ COBJS-y += fpga.o COBJS-$(CONFIG_FPGA_SPARTAN2) += spartan2.o COBJS-$(CONFIG_FPGA_SPARTAN3) += spartan3.o COBJS-$(CONFIG_FPGA_VIRTEX2) += virtex2.o +COBJS-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o COBJS-$(CONFIG_FPGA_XILINX) += xilinx.o COBJS-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o ifdef CONFIG_FPGA_ALTERA diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 26d244354c..f70bff6ed1 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -22,122 +22,99 @@ * */ -/* - * Generic FPGA support - */ +/* Generic FPGA support */ #include <common.h> /* core U-Boot definitions */ #include <xilinx.h> /* xilinx specific definitions */ #include <altera.h> /* altera specific definitions */ #include <lattice.h> -#if 0 -#define FPGA_DEBUG /* define FPGA_DEBUG to get debug messages */ -#endif - /* Local definitions */ #ifndef CONFIG_MAX_FPGA_DEVICES #define CONFIG_MAX_FPGA_DEVICES 5 #endif -/* Enable/Disable debug console messages */ -#ifdef FPGA_DEBUG -#define PRINTF(fmt,args...) printf (fmt ,##args) -#else -#define PRINTF(fmt,args...) -#endif - /* Local static data */ static int next_desc = FPGA_INVALID_DEVICE; static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES]; -/* Local static functions */ -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum ); -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate(int devnum, const void *buf, - size_t bsize, char *fn ); -static int fpga_dev_info( int devnum ); - - -/* ------------------------------------------------------------------------- */ - -/* fpga_no_sup +/* + * fpga_no_sup * 'no support' message function */ -static void fpga_no_sup( char *fn, char *msg ) +static void fpga_no_sup(char *fn, char *msg) { - if ( fn && msg ) { - printf( "%s: No support for %s.\n", fn, msg); - } else if ( msg ) { - printf( "No support for %s.\n", msg); - } else { - printf( "No FPGA suport!\n"); - } + if (fn && msg) + printf("%s: No support for %s.\n", fn, msg); + else if (msg) + printf("No support for %s.\n", msg); + else + printf("No FPGA suport!\n"); } /* fpga_get_desc * map a device number to a descriptor */ -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum ) +static const fpga_desc *const fpga_get_desc(int devnum) { - fpga_desc *desc = (fpga_desc * )NULL; + fpga_desc *desc = (fpga_desc *)NULL; - if (( devnum >= 0 ) && (devnum < next_desc )) { + if ((devnum >= 0) && (devnum < next_desc)) { desc = &desc_table[devnum]; - PRINTF( "%s: found fpga descriptor #%d @ 0x%p\n", - __FUNCTION__, devnum, desc ); + debug("%s: found fpga descriptor #%d @ 0x%p\n", + __func__, devnum, desc); } return desc; } - -/* fpga_validate +/* + * fpga_validate * generic parameter checking code */ -static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate(int devnum, const void *buf, - size_t bsize, char *fn ) +const fpga_desc *const fpga_validate(int devnum, const void *buf, + size_t bsize, char *fn) { - fpga_desc * desc = fpga_get_desc( devnum ); + const fpga_desc *desc = fpga_get_desc(devnum); - if ( !desc ) { - printf( "%s: Invalid device number %d\n", fn, devnum ); - } + if (!desc) + printf("%s: Invalid device number %d\n", fn, devnum); - if ( !buf ) { - printf( "%s: Null buffer.\n", fn ); + if (!buf) { + printf("%s: Null buffer.\n", fn); return (fpga_desc * const)NULL; } return desc; } - -/* fpga_dev_info +/* + * fpga_dev_info * generic multiplexing code */ -static int fpga_dev_info( int devnum ) +static int fpga_dev_info(int devnum) { - int ret_val = FPGA_FAIL; /* assume failure */ - const fpga_desc * const desc = fpga_get_desc( devnum ); + int ret_val = FPGA_FAIL; /* assume failure */ + const fpga_desc * const desc = fpga_get_desc(devnum); - if ( desc ) { - PRINTF( "%s: Device Descriptor @ 0x%p\n", - __FUNCTION__, desc->devdesc ); + if (desc) { + debug("%s: Device Descriptor @ 0x%p\n", + __func__, desc->devdesc); - switch ( desc->devtype ) { + switch (desc->devtype) { case fpga_xilinx: #if defined(CONFIG_FPGA_XILINX) - printf( "Xilinx Device\nDescriptor @ 0x%p\n", desc ); - ret_val = xilinx_info( desc->devdesc ); + printf("Xilinx Device\nDescriptor @ 0x%p\n", desc); + ret_val = xilinx_info(desc->devdesc); #else - fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" ); + fpga_no_sup((char *)__func__, "Xilinx devices"); #endif break; case fpga_altera: #if defined(CONFIG_FPGA_ALTERA) - printf( "Altera Device\nDescriptor @ 0x%p\n", desc ); - ret_val = altera_info( desc->devdesc ); + printf("Altera Device\nDescriptor @ 0x%p\n", desc); + ret_val = altera_info(desc->devdesc); #else - fpga_no_sup( (char *)__FUNCTION__, "Altera devices" ); + fpga_no_sup((char *)__func__, "Altera devices"); #endif break; case fpga_lattice: @@ -145,171 +122,183 @@ static int fpga_dev_info( int devnum ) printf("Lattice Device\nDescriptor @ 0x%p\n", desc); ret_val = lattice_info(desc->devdesc); #else - fpga_no_sup( (char *)__FUNCTION__, "Lattice devices" ); + fpga_no_sup((char *)__func__, "Lattice devices"); #endif break; default: - printf( "%s: Invalid or unsupported device type %d\n", - __FUNCTION__, desc->devtype ); + printf("%s: Invalid or unsupported device type %d\n", + __func__, desc->devtype); } } else { - printf( "%s: Invalid device number %d\n", - __FUNCTION__, devnum ); + printf("%s: Invalid device number %d\n", __func__, devnum); } return ret_val; } - -/* ------------------------------------------------------------------------- */ -/* fgpa_init is usually called from misc_init_r() and MUST be called +/* + * fgpa_init is usually called from misc_init_r() and MUST be called * before any of the other fpga functions are used. */ void fpga_init(void) { next_desc = 0; - memset( desc_table, 0, sizeof(desc_table)); + memset(desc_table, 0, sizeof(desc_table)); - PRINTF( "%s: CONFIG_FPGA = 0x%x\n", __FUNCTION__, CONFIG_FPGA ); + debug("%s\n", __func__); } -/* fpga_count +/* + * fpga_count * Basic interface function to get the current number of devices available. */ -int fpga_count( void ) +int fpga_count(void) { return next_desc; } -/* fpga_add +/* + * fpga_add * Add the device descriptor to the device table. */ -int fpga_add( fpga_type devtype, void *desc ) +int fpga_add(fpga_type devtype, void *desc) { int devnum = FPGA_INVALID_DEVICE; - if ( next_desc < 0 ) { - printf( "%s: FPGA support not initialized!\n", __FUNCTION__ ); - } else if (( devtype > fpga_min_type ) && ( devtype < fpga_undefined )) { - if ( desc ) { - if ( next_desc < CONFIG_MAX_FPGA_DEVICES ) { + if (next_desc < 0) { + printf("%s: FPGA support not initialized!\n", __func__); + } else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) { + if (desc) { + if (next_desc < CONFIG_MAX_FPGA_DEVICES) { devnum = next_desc; desc_table[next_desc].devtype = devtype; desc_table[next_desc++].devdesc = desc; } else { - printf( "%s: Exceeded Max FPGA device count\n", __FUNCTION__ ); + printf("%s: Exceeded Max FPGA device count\n", + __func__); } } else { - printf( "%s: NULL device descriptor\n", __FUNCTION__ ); + printf("%s: NULL device descriptor\n", __func__); } } else { - printf( "%s: Unsupported FPGA type %d\n", __FUNCTION__, devtype ); + printf("%s: Unsupported FPGA type %d\n", __func__, devtype); } return devnum; } /* - * Generic multiplexing code + * Convert bitstream data and load into the fpga + */ +int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size) +{ + printf("Bitstream support not implemented for this FPGA device\n"); + return FPGA_FAIL; +} + +/* + * Generic multiplexing code */ int fpga_load(int devnum, const void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume failure */ - fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ ); + const fpga_desc *desc = fpga_validate(devnum, buf, bsize, + (char *)__func__); - if ( desc ) { - switch ( desc->devtype ) { + if (desc) { + switch (desc->devtype) { case fpga_xilinx: #if defined(CONFIG_FPGA_XILINX) - ret_val = xilinx_load( desc->devdesc, buf, bsize ); + ret_val = xilinx_load(desc->devdesc, buf, bsize); #else - fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" ); + fpga_no_sup((char *)__func__, "Xilinx devices"); #endif break; case fpga_altera: #if defined(CONFIG_FPGA_ALTERA) - ret_val = altera_load( desc->devdesc, buf, bsize ); + ret_val = altera_load(desc->devdesc, buf, bsize); #else - fpga_no_sup( (char *)__FUNCTION__, "Altera devices" ); + fpga_no_sup((char *)__func__, "Altera devices"); #endif break; case fpga_lattice: #if defined(CONFIG_FPGA_LATTICE) ret_val = lattice_load(desc->devdesc, buf, bsize); #else - fpga_no_sup( (char *)__FUNCTION__, "Lattice devices" ); + fpga_no_sup((char *)__func__, "Lattice devices"); #endif break; default: - printf( "%s: Invalid or unsupported device type %d\n", - __FUNCTION__, desc->devtype ); + printf("%s: Invalid or unsupported device type %d\n", + __func__, desc->devtype); } } return ret_val; } -/* fpga_dump +/* + * fpga_dump * generic multiplexing code */ int fpga_dump(int devnum, const void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume failure */ - fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ ); + const fpga_desc *desc = fpga_validate(devnum, buf, bsize, + (char *)__func__); - if ( desc ) { - switch ( desc->devtype ) { + if (desc) { + switch (desc->devtype) { case fpga_xilinx: #if defined(CONFIG_FPGA_XILINX) - ret_val = xilinx_dump( desc->devdesc, buf, bsize ); + ret_val = xilinx_dump(desc->devdesc, buf, bsize); #else - fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" ); + fpga_no_sup((char *)__func__, "Xilinx devices"); #endif break; case fpga_altera: #if defined(CONFIG_FPGA_ALTERA) - ret_val = altera_dump( desc->devdesc, buf, bsize ); + ret_val = altera_dump(desc->devdesc, buf, bsize); #else - fpga_no_sup( (char *)__FUNCTION__, "Altera devices" ); + fpga_no_sup((char *)__func__, "Altera devices"); #endif break; case fpga_lattice: #if defined(CONFIG_FPGA_LATTICE) ret_val = lattice_dump(desc->devdesc, buf, bsize); #else - fpga_no_sup( (char *)__FUNCTION__, "Lattice devices" ); + fpga_no_sup((char *)__func__, "Lattice devices"); #endif break; default: - printf( "%s: Invalid or unsupported device type %d\n", - __FUNCTION__, desc->devtype ); + printf("%s: Invalid or unsupported device type %d\n", + __func__, desc->devtype); } } return ret_val; } - -/* fpga_info +/* + * fpga_info * front end to fpga_dev_info. If devnum is invalid, report on all * available devices. */ -int fpga_info( int devnum ) +int fpga_info(int devnum) { - if ( devnum == FPGA_INVALID_DEVICE ) { - if ( next_desc > 0 ) { + if (devnum == FPGA_INVALID_DEVICE) { + if (next_desc > 0) { int dev; - for ( dev = 0; dev < next_desc; dev++ ) { - fpga_dev_info( dev ); - } + for (dev = 0; dev < next_desc; dev++) + fpga_dev_info(dev); + return FPGA_SUCCESS; } else { - printf( "%s: No FPGA devices available.\n", __FUNCTION__ ); + printf("%s: No FPGA devices available.\n", __func__); return FPGA_FAIL; } } - else return fpga_dev_info( devnum ); -} -/* ------------------------------------------------------------------------- */ + return fpga_dev_info(devnum); +} diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index 32787b2366..49e943718e 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -1,4 +1,6 @@ /* + * (C) Copyright 2012-2013, Xilinx, Michal Simek + * * (C) Copyright 2002 * Rich Ireland, Enterasys Networks, rireland@enterasys.com. * Keith Outwater, keith_outwater@mvis.com @@ -28,9 +30,11 @@ */ #include <common.h> +#include <fpga.h> #include <virtex2.h> #include <spartan2.h> #include <spartan3.h> +#include <zynqpl.h> #if 0 #define FPGA_DEBUG @@ -48,6 +52,112 @@ static int xilinx_validate (Xilinx_desc * desc, char *fn); /* ------------------------------------------------------------------------- */ +int fpga_loadbitstream(int devnum, char *fpgadata, size_t size) +{ + unsigned int length; + unsigned int swapsize; + char buffer[80]; + unsigned char *dataptr; + unsigned int i; + const fpga_desc *desc; + Xilinx_desc *xdesc; + + dataptr = (unsigned char *)fpgadata; + /* Find out fpga_description */ + desc = fpga_validate(devnum, dataptr, 0, (char *)__func__); + /* Assign xilinx device description */ + xdesc = desc->devdesc; + + /* skip the first bytes of the bitsteam, their meaning is unknown */ + length = (*dataptr << 8) + *(dataptr + 1); + dataptr += 2; + dataptr += length; + + /* get design name (identifier, length, string) */ + length = (*dataptr << 8) + *(dataptr + 1); + dataptr += 2; + if (*dataptr++ != 0x61) { + debug("%s: Design name id not recognized in bitstream\n", + __func__); + return FPGA_FAIL; + } + + length = (*dataptr << 8) + *(dataptr + 1); + dataptr += 2; + for (i = 0; i < length; i++) + buffer[i] = *dataptr++; + + printf(" design filename = \"%s\"\n", buffer); + + /* get part number (identifier, length, string) */ + if (*dataptr++ != 0x62) { + printf("%s: Part number id not recognized in bitstream\n", + __func__); + return FPGA_FAIL; + } + + length = (*dataptr << 8) + *(dataptr + 1); + dataptr += 2; + for (i = 0; i < length; i++) + buffer[i] = *dataptr++; + + if (xdesc->name) { + i = strncmp(buffer, xdesc->name, strlen(xdesc->name)); + if (i) { + printf("%s: Wrong bitstream ID for this device\n", + __func__); + printf("%s: Bitstream ID %s, current device ID %d/%s\n", + __func__, buffer, devnum, xdesc->name); + return FPGA_FAIL; + } + } else { + printf("%s: Please fill correct device ID to Xilinx_desc\n", + __func__); + } + printf(" part number = \"%s\"\n", buffer); + + /* get date (identifier, length, string) */ + if (*dataptr++ != 0x63) { + printf("%s: Date identifier not recognized in bitstream\n", + __func__); + return FPGA_FAIL; + } + + length = (*dataptr << 8) + *(dataptr+1); + dataptr += 2; + for (i = 0; i < length; i++) + buffer[i] = *dataptr++; + printf(" date = \"%s\"\n", buffer); + + /* get time (identifier, length, string) */ + if (*dataptr++ != 0x64) { + printf("%s: Time identifier not recognized in bitstream\n", + __func__); + return FPGA_FAIL; + } + + length = (*dataptr << 8) + *(dataptr+1); + dataptr += 2; + for (i = 0; i < length; i++) + buffer[i] = *dataptr++; + printf(" time = \"%s\"\n", buffer); + + /* get fpga data length (identifier, length) */ + if (*dataptr++ != 0x65) { + printf("%s: Data length id not recognized in bitstream\n", + __func__); + return FPGA_FAIL; + } + swapsize = ((unsigned int) *dataptr << 24) + + ((unsigned int) *(dataptr + 1) << 16) + + ((unsigned int) *(dataptr + 2) << 8) + + ((unsigned int) *(dataptr + 3)); + dataptr += 4; + printf(" bytes in bitstream = %d\n", swapsize); + + return fpga_load(devnum, dataptr, swapsize); +} + int xilinx_load(Xilinx_desc *desc, const void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume a failure */ @@ -86,6 +196,16 @@ int xilinx_load(Xilinx_desc *desc, const void *buf, size_t bsize) __FUNCTION__); #endif break; + case xilinx_zynq: +#if defined(CONFIG_FPGA_ZYNQPL) + PRINTF("%s: Launching the Zynq PL Loader...\n", + __func__); + ret_val = zynq_load(desc, buf, bsize); +#else + printf("%s: No support for Zynq devices.\n", + __func__); +#endif + break; default: printf ("%s: Unsupported family type, %d\n", @@ -133,6 +253,16 @@ int xilinx_dump(Xilinx_desc *desc, const void *buf, size_t bsize) __FUNCTION__); #endif break; + case xilinx_zynq: +#if defined(CONFIG_FPGA_ZYNQPL) + PRINTF("%s: Launching the Zynq PL Reader...\n", + __func__); + ret_val = zynq_dump(desc, buf, bsize); +#else + printf("%s: No support for Zynq devices.\n", + __func__); +#endif + break; default: printf ("%s: Unsupported family type, %d\n", @@ -158,6 +288,9 @@ int xilinx_info (Xilinx_desc * desc) case Xilinx_Virtex2: printf ("Virtex-II\n"); break; + case xilinx_zynq: + printf("Zynq PL\n"); + break; /* Add new family types here */ default: printf ("Unknown family type, %d\n", desc->family); @@ -183,6 +316,9 @@ int xilinx_info (Xilinx_desc * desc) case master_selectmap: printf ("Master SelectMap Mode\n"); break; + case devcfg: + printf("Device configuration interface (Zynq)\n"); + break; /* Add new interface types here */ default: printf ("Unsupported interface type, %d\n", desc->iface); @@ -191,6 +327,8 @@ int xilinx_info (Xilinx_desc * desc) printf ("Device Size: \t%d bytes\n" "Cookie: \t0x%x (%d)\n", desc->size, desc->cookie, desc->cookie); + if (desc->name) + printf("Device name: \t%s\n", desc->name); if (desc->iface_fns) { printf ("Device Function Table @ 0x%p\n", desc->iface_fns); @@ -222,6 +360,14 @@ int xilinx_info (Xilinx_desc * desc) __FUNCTION__); #endif break; + case xilinx_zynq: +#if defined(CONFIG_FPGA_ZYNQPL) + zynq_info(desc); +#else + /* just in case */ + printf("%s: No support for Zynq devices.\n", + __func__); +#endif /* Add new family types here */ default: /* we don't need a message here - we give one up above */ diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c new file mode 100644 index 0000000000..8feccdea48 --- /dev/null +++ b/drivers/fpga/zynqpl.c @@ -0,0 +1,355 @@ +/* + * (C) Copyright 2012-2013, Xilinx, Michal Simek + * + * (C) Copyright 2012 + * Joe Hershberger <joe.hershberger@ni.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <zynqpl.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> + +#define DEVCFG_CTRL_PCFG_PROG_B 0x40000000 +#define DEVCFG_ISR_FATAL_ERROR_MASK 0x00740040 +#define DEVCFG_ISR_ERROR_FLAGS_MASK 0x00340840 +#define DEVCFG_ISR_RX_FIFO_OV 0x00040000 +#define DEVCFG_ISR_DMA_DONE 0x00002000 +#define DEVCFG_ISR_PCFG_DONE 0x00000004 +#define DEVCFG_STATUS_DMA_CMD_Q_F 0x80000000 +#define DEVCFG_STATUS_DMA_CMD_Q_E 0x40000000 +#define DEVCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000 +#define DEVCFG_STATUS_PCFG_INIT 0x00000010 +#define DEVCFG_MCTRL_RFIFO_FLUSH 0x00000002 +#define DEVCFG_MCTRL_WFIFO_FLUSH 0x00000001 + +#ifndef CONFIG_SYS_FPGA_WAIT +#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */ +#endif + +#ifndef CONFIG_SYS_FPGA_PROG_TIME +#define CONFIG_SYS_FPGA_PROG_TIME CONFIG_SYS_HZ /* 1 s */ +#endif + +int zynq_info(Xilinx_desc *desc) +{ + return FPGA_SUCCESS; +} + +#define DUMMY_WORD 0xffffffff + +/* Xilinx binary format header */ +static const u32 bin_format[] = { + DUMMY_WORD, /* Dummy words */ + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + 0x000000bb, /* Sync word */ + 0x11220044, /* Sync word */ + DUMMY_WORD, + DUMMY_WORD, + 0xaa995566, /* Sync word */ +}; + +#define SWAP_NO 1 +#define SWAP_DONE 2 + +/* + * Load the whole word from unaligned buffer + * Keep in your mind that it is byte loading on little-endian system + */ +static u32 load_word(const void *buf, u32 swap) +{ + u32 word = 0; + u8 *bitc = (u8 *)buf; + int p; + + if (swap == SWAP_NO) { + for (p = 0; p < 4; p++) { + word <<= 8; + word |= bitc[p]; + } + } else { + for (p = 3; p >= 0; p--) { + word <<= 8; + word |= bitc[p]; + } + } + + return word; +} + +static u32 check_header(const void *buf) +{ + u32 i, pattern; + int swap = SWAP_NO; + u32 *test = (u32 *)buf; + + debug("%s: Let's check bitstream header\n", __func__); + + /* Checking that passing bin is not a bitstream */ + for (i = 0; i < ARRAY_SIZE(bin_format); i++) { + pattern = load_word(&test[i], swap); + + /* + * Bitstreams in binary format are swapped + * compare to regular bistream. + * Do not swap dummy word but if swap is done assume + * that parsing buffer is binary format + */ + if ((__swab32(pattern) != DUMMY_WORD) && + (__swab32(pattern) == bin_format[i])) { + pattern = __swab32(pattern); + swap = SWAP_DONE; + debug("%s: data swapped - let's swap\n", __func__); + } + + debug("%s: %d/%x: pattern %x/%x bin_format\n", __func__, i, + (u32)&test[i], pattern, bin_format[i]); + if (pattern != bin_format[i]) { + debug("%s: Bitstream is not recognized\n", __func__); + return 0; + } + } + debug("%s: Found bitstream header at %x %s swapinng\n", __func__, + (u32)buf, swap == SWAP_NO ? "without" : "with"); + + return swap; +} + +static void *check_data(u8 *buf, size_t bsize, u32 *swap) +{ + u32 word, p = 0; /* possition */ + + /* Because buf doesn't need to be aligned let's read it by chars */ + for (p = 0; p < bsize; p++) { + word = load_word(&buf[p], SWAP_NO); + debug("%s: word %x %x/%x\n", __func__, word, p, (u32)&buf[p]); + + /* Find the first bitstream dummy word */ + if (word == DUMMY_WORD) { + debug("%s: Found dummy word at position %x/%x\n", + __func__, p, (u32)&buf[p]); + *swap = check_header(&buf[p]); + if (*swap) { + /* FIXME add full bitstream checking here */ + return &buf[p]; + } + } + /* Loop can be huge - support CTRL + C */ + if (ctrlc()) + return 0; + } + return 0; +} + + +int zynq_load(Xilinx_desc *desc, const void *buf, size_t bsize) +{ + unsigned long ts; /* Timestamp */ + u32 partialbit = 0; + u32 i, control, isr_status, status, swap, diff; + u32 *buf_start; + + /* Detect if we are going working with partial or full bitstream */ + if (bsize != desc->size) { + printf("%s: Working with partial bitstream\n", __func__); + partialbit = 1; + } + + buf_start = check_data((u8 *)buf, bsize, &swap); + if (!buf_start) + return FPGA_FAIL; + + /* Check if data is postpone from start */ + diff = (u32)buf_start - (u32)buf; + if (diff) { + printf("%s: Bitstream is not validated yet (diff %x)\n", + __func__, diff); + return FPGA_FAIL; + } + + if ((u32)buf_start & 0x3) { + u32 *new_buf = (u32 *)((u32)buf & ~0x3); + + printf("%s: Align buffer at %x to %x(swap %d)\n", __func__, + (u32)buf_start, (u32)new_buf, swap); + + for (i = 0; i < (bsize/4); i++) + new_buf[i] = load_word(&buf_start[i], swap); + + swap = SWAP_DONE; + buf = new_buf; + } else if (swap != SWAP_DONE) { + /* For bitstream which are aligned */ + u32 *new_buf = (u32 *)buf; + + printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__, + swap); + + for (i = 0; i < (bsize/4); i++) + new_buf[i] = load_word(&buf_start[i], swap); + + swap = SWAP_DONE; + } + + if (!partialbit) { + zynq_slcr_devcfg_disable(); + + /* Setting PCFG_PROG_B signal to high */ + control = readl(&devcfg_base->ctrl); + writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); + /* Setting PCFG_PROG_B signal to low */ + writel(control & ~DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); + + /* Polling the PCAP_INIT status for Reset */ + ts = get_timer(0); + while (readl(&devcfg_base->status) & DEVCFG_STATUS_PCFG_INIT) { + if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { + printf("%s: Timeout wait for INIT to clear\n", + __func__); + return FPGA_FAIL; + } + } + + /* Setting PCFG_PROG_B signal to high */ + writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl); + + /* Polling the PCAP_INIT status for Set */ + ts = get_timer(0); + while (!(readl(&devcfg_base->status) & + DEVCFG_STATUS_PCFG_INIT)) { + if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { + printf("%s: Timeout wait for INIT to set\n", + __func__); + return FPGA_FAIL; + } + } + } + + isr_status = readl(&devcfg_base->int_sts); + + /* Clear it all, so if Boot ROM comes back, it can proceed */ + writel(0xFFFFFFFF, &devcfg_base->int_sts); + + if (isr_status & DEVCFG_ISR_FATAL_ERROR_MASK) { + debug("%s: Fatal errors in PCAP 0x%X\n", __func__, isr_status); + + /* If RX FIFO overflow, need to flush RX FIFO first */ + if (isr_status & DEVCFG_ISR_RX_FIFO_OV) { + writel(DEVCFG_MCTRL_RFIFO_FLUSH, &devcfg_base->mctrl); + writel(0xFFFFFFFF, &devcfg_base->int_sts); + } + return FPGA_FAIL; + } + + status = readl(&devcfg_base->status); + + debug("%s: Status = 0x%08X\n", __func__, status); + + if (status & DEVCFG_STATUS_DMA_CMD_Q_F) { + debug("%s: Error: device busy\n", __func__); + return FPGA_FAIL; + } + + debug("%s: Device ready\n", __func__); + + if (!(status & DEVCFG_STATUS_DMA_CMD_Q_E)) { + if (!(readl(&devcfg_base->int_sts) & DEVCFG_ISR_DMA_DONE)) { + /* Error state, transfer cannot occur */ + debug("%s: ISR indicates error\n", __func__); + return FPGA_FAIL; + } else { + /* Clear out the status */ + writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts); + } + } + + if (status & DEVCFG_STATUS_DMA_DONE_CNT_MASK) { + /* Clear the count of completed DMA transfers */ + writel(DEVCFG_STATUS_DMA_DONE_CNT_MASK, &devcfg_base->status); + } + + debug("%s: Source = 0x%08X\n", __func__, (u32)buf); + debug("%s: Size = %zu\n", __func__, bsize); + + /* Set up the transfer */ + writel((u32)buf | 1, &devcfg_base->dma_src_addr); + writel(0xFFFFFFFF, &devcfg_base->dma_dst_addr); + writel(bsize >> 2, &devcfg_base->dma_src_len); + writel(0, &devcfg_base->dma_dst_len); + + isr_status = readl(&devcfg_base->int_sts); + + /* Polling the PCAP_INIT status for Set */ + ts = get_timer(0); + while (!(isr_status & DEVCFG_ISR_DMA_DONE)) { + if (isr_status & DEVCFG_ISR_ERROR_FLAGS_MASK) { + debug("%s: Error: isr = 0x%08X\n", __func__, + isr_status); + debug("%s: Write count = 0x%08X\n", __func__, + readl(&devcfg_base->write_count)); + debug("%s: Read count = 0x%08X\n", __func__, + readl(&devcfg_base->read_count)); + + return FPGA_FAIL; + } + if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) { + printf("%s: Timeout wait for DMA to complete\n", + __func__); + return FPGA_FAIL; + } + isr_status = readl(&devcfg_base->int_sts); + } + + debug("%s: DMA transfer is done\n", __func__); + + /* Check FPGA configuration completion */ + ts = get_timer(0); + while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) { + if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { + printf("%s: Timeout wait for FPGA to config\n", + __func__); + return FPGA_FAIL; + } + isr_status = readl(&devcfg_base->int_sts); + } + + debug("%s: FPGA config done\n", __func__); + + /* Clear out the DMA status */ + writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts); + + if (!partialbit) + zynq_slcr_devcfg_enable(); + + return FPGA_SUCCESS; +} + +int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize) +{ + return FPGA_FAIL; +} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 5dbdbe3672..72e85a349a 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -46,6 +46,7 @@ COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o COBJS-$(CONFIG_SH_I2C) += sh_i2c.o COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o +COBJS-$(CONFIG_ZYNQ_I2C) += zynq_i2c.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/i2c/zynq_i2c.c b/drivers/i2c/zynq_i2c.c new file mode 100644 index 0000000000..ec49660cf7 --- /dev/null +++ b/drivers/i2c/zynq_i2c.c @@ -0,0 +1,306 @@ +/* + * Driver for the Zynq-7000 PS I2C controller + * IP from Cadence (ID T-CS-PE-0007-100, Version R1p10f2) + * + * Author: Joe Hershberger <joe.hershberger@ni.com> + * Copyright (c) 2012 Joe Hershberger. + * + * Copyright (c) 2012-2013 Xilinx, Michal Simek + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <i2c.h> +#include <asm/errno.h> +#include <asm/arch/hardware.h> + +/* i2c register set */ +struct zynq_i2c_registers { + u32 control; + u32 status; + u32 address; + u32 data; + u32 interrupt_status; + u32 transfer_size; + u32 slave_mon_pause; + u32 time_out; + u32 interrupt_mask; + u32 interrupt_enable; + u32 interrupt_disable; +}; + +/* Control register fields */ +#define ZYNQ_I2C_CONTROL_RW 0x00000001 +#define ZYNQ_I2C_CONTROL_MS 0x00000002 +#define ZYNQ_I2C_CONTROL_NEA 0x00000004 +#define ZYNQ_I2C_CONTROL_ACKEN 0x00000008 +#define ZYNQ_I2C_CONTROL_HOLD 0x00000010 +#define ZYNQ_I2C_CONTROL_SLVMON 0x00000020 +#define ZYNQ_I2C_CONTROL_CLR_FIFO 0x00000040 +#define ZYNQ_I2C_CONTROL_DIV_B_SHIFT 8 +#define ZYNQ_I2C_CONTROL_DIV_B_MASK 0x00003F00 +#define ZYNQ_I2C_CONTROL_DIV_A_SHIFT 14 +#define ZYNQ_I2C_CONTROL_DIV_A_MASK 0x0000C000 + +/* Status register values */ +#define ZYNQ_I2C_STATUS_RXDV 0x00000020 +#define ZYNQ_I2C_STATUS_TXDV 0x00000040 +#define ZYNQ_I2C_STATUS_RXOVF 0x00000080 +#define ZYNQ_I2C_STATUS_BA 0x00000100 + +/* Interrupt register fields */ +#define ZYNQ_I2C_INTERRUPT_COMP 0x00000001 +#define ZYNQ_I2C_INTERRUPT_DATA 0x00000002 +#define ZYNQ_I2C_INTERRUPT_NACK 0x00000004 +#define ZYNQ_I2C_INTERRUPT_TO 0x00000008 +#define ZYNQ_I2C_INTERRUPT_SLVRDY 0x00000010 +#define ZYNQ_I2C_INTERRUPT_RXOVF 0x00000020 +#define ZYNQ_I2C_INTERRUPT_TXOVF 0x00000040 +#define ZYNQ_I2C_INTERRUPT_RXUNF 0x00000080 +#define ZYNQ_I2C_INTERRUPT_ARBLOST 0x00000200 + +#define ZYNQ_I2C_FIFO_DEPTH 16 +#define ZYNQ_I2C_TRANSFERT_SIZE_MAX 255 /* Controller transfer limit */ + +#if defined(CONFIG_ZYNQ_I2C0) +# define ZYNQ_I2C_BASE ZYNQ_I2C_BASEADDR0 +#else +# define ZYNQ_I2C_BASE ZYNQ_I2C_BASEADDR1 +#endif + +static struct zynq_i2c_registers *zynq_i2c = + (struct zynq_i2c_registers *)ZYNQ_I2C_BASE; + +/* I2C init called by cmd_i2c when doing 'i2c reset'. */ +void i2c_init(int requested_speed, int slaveadd) +{ + /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ + writel((16 << ZYNQ_I2C_CONTROL_DIV_B_SHIFT) | + (2 << ZYNQ_I2C_CONTROL_DIV_A_SHIFT), &zynq_i2c->control); + + /* Enable master mode, ack, and 7-bit addressing */ + setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_MS | + ZYNQ_I2C_CONTROL_ACKEN | ZYNQ_I2C_CONTROL_NEA); +} + +#ifdef DEBUG +static void zynq_i2c_debug_status(void) +{ + int int_status; + int status; + int_status = readl(&zynq_i2c->interrupt_status); + + status = readl(&zynq_i2c->status); + if (int_status || status) { + debug("Status: "); + if (int_status & ZYNQ_I2C_INTERRUPT_COMP) + debug("COMP "); + if (int_status & ZYNQ_I2C_INTERRUPT_DATA) + debug("DATA "); + if (int_status & ZYNQ_I2C_INTERRUPT_NACK) + debug("NACK "); + if (int_status & ZYNQ_I2C_INTERRUPT_TO) + debug("TO "); + if (int_status & ZYNQ_I2C_INTERRUPT_SLVRDY) + debug("SLVRDY "); + if (int_status & ZYNQ_I2C_INTERRUPT_RXOVF) + debug("RXOVF "); + if (int_status & ZYNQ_I2C_INTERRUPT_TXOVF) + debug("TXOVF "); + if (int_status & ZYNQ_I2C_INTERRUPT_RXUNF) + debug("RXUNF "); + if (int_status & ZYNQ_I2C_INTERRUPT_ARBLOST) + debug("ARBLOST "); + if (status & ZYNQ_I2C_STATUS_RXDV) + debug("RXDV "); + if (status & ZYNQ_I2C_STATUS_TXDV) + debug("TXDV "); + if (status & ZYNQ_I2C_STATUS_RXOVF) + debug("RXOVF "); + if (status & ZYNQ_I2C_STATUS_BA) + debug("BA "); + debug("TS%d ", readl(&zynq_i2c->transfer_size)); + debug("\n"); + } +} +#endif + +/* Wait for an interrupt */ +static u32 zynq_i2c_wait(u32 mask) +{ + int timeout, int_status; + + for (timeout = 0; timeout < 100; timeout++) { + udelay(100); + int_status = readl(&zynq_i2c->interrupt_status); + if (int_status & mask) + break; + } +#ifdef DEBUG + zynq_i2c_debug_status(); +#endif + /* Clear interrupt status flags */ + writel(int_status & mask, &zynq_i2c->interrupt_status); + + return int_status & mask; +} + +/* + * I2C probe called by cmd_i2c when doing 'i2c probe'. + * Begin read, nak data byte, end. + */ +int i2c_probe(u8 dev) +{ + /* Attempt to read a byte */ + setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | + ZYNQ_I2C_CONTROL_RW); + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); + writel(0xFF, &zynq_i2c->interrupt_status); + writel(dev, &zynq_i2c->address); + writel(1, &zynq_i2c->transfer_size); + + return (zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP | + ZYNQ_I2C_INTERRUPT_NACK) & + ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT; +} + +/* + * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c + * Begin write, send address byte(s), begin read, receive data bytes, end. + */ +int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) +{ + u32 status; + u32 i = 0; + u8 *cur_data = data; + + /* Check the hardware can handle the requested bytes */ + if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX)) + return -EINVAL; + + /* Write the register address */ + setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | + ZYNQ_I2C_CONTROL_HOLD); + /* + * Temporarily disable restart (by clearing hold) + * It doesn't seem to work. + */ + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW | + ZYNQ_I2C_CONTROL_HOLD); + writel(0xFF, &zynq_i2c->interrupt_status); + while (alen--) + writel(addr >> (8*alen), &zynq_i2c->data); + writel(dev, &zynq_i2c->address); + + /* Wait for the address to be sent */ + if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { + /* Release the bus */ + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); + return -ETIMEDOUT; + } + debug("Device acked address\n"); + + setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | + ZYNQ_I2C_CONTROL_RW); + /* Start reading data */ + writel(dev, &zynq_i2c->address); + writel(length, &zynq_i2c->transfer_size); + + /* Wait for data */ + do { + status = zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP | + ZYNQ_I2C_INTERRUPT_DATA); + if (!status) { + /* Release the bus */ + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); + return -ETIMEDOUT; + } + debug("Read %d bytes\n", + length - readl(&zynq_i2c->transfer_size)); + for (; i < length - readl(&zynq_i2c->transfer_size); i++) + *(cur_data++) = readl(&zynq_i2c->data); + } while (readl(&zynq_i2c->transfer_size) != 0); + /* All done... release the bus */ + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); + +#ifdef DEBUG + zynq_i2c_debug_status(); +#endif + return 0; +} + +/* + * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c + * Begin write, send address byte(s), send data bytes, end. + */ +int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) +{ + u8 *cur_data = data; + + /* Write the register address */ + setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | + ZYNQ_I2C_CONTROL_HOLD); + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW); + writel(0xFF, &zynq_i2c->interrupt_status); + while (alen--) + writel(addr >> (8*alen), &zynq_i2c->data); + /* Start the tranfer */ + writel(dev, &zynq_i2c->address); + if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { + /* Release the bus */ + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); + return -ETIMEDOUT; + } + + debug("Device acked address\n"); + while (length--) { + writel(*(cur_data++), &zynq_i2c->data); + if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) { + if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { + /* Release the bus */ + clrbits_le32(&zynq_i2c->control, + ZYNQ_I2C_CONTROL_HOLD); + return -ETIMEDOUT; + } + } + } + + /* All done... release the bus */ + clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); + /* Wait for the address and data to be sent */ + if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) + return -ETIMEDOUT; + return 0; +} + +int i2c_set_bus_num(unsigned int bus) +{ + /* Only support bus 0 */ + if (bus > 0) + return -1; + return 0; +} + +unsigned int i2c_get_bus_num(void) +{ + /* Only support bus 0 */ + return 0; +} diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 1d6faa2a92..7cd4281733 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -49,6 +49,7 @@ COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o COBJS-$(CONFIG_DWMMC) += dw_mmc.o COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o +COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c new file mode 100644 index 0000000000..9e37af45fc --- /dev/null +++ b/drivers/mmc/zynq_sdhci.c @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2013 Inc. + * + * Xilinx Zynq SD Host Controller Interface + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <sdhci.h> +#include <asm/arch/sys_proto.h> + +int zynq_sdhci_init(u32 regbase) +{ + struct sdhci_host *host = NULL; + + host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); + if (!host) { + printf("zynq_sdhci_init: sdhci_host malloc fail\n"); + return 1; + } + + host->name = "zynq_sdhci"; + host->ioaddr = (void *)regbase; + host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD; + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + + host->host_caps = MMC_MODE_HC; + + add_sdhci(host, 52000000, 52000000 >> 9); + return 0; +} diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4b271989ac..46801c7919 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -465,6 +465,16 @@ static struct phy_driver M88E1149S_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver M88E1518_driver = { + .name = "Marvell 88E1518", + .uid = 0x1410dd1, + .mask = 0xffffff0, + .features = PHY_GBIT_FEATURES, + .config = &m88e1111s_config, + .startup = &m88e1011s_startup, + .shutdown = &genphy_shutdown, +}; + int phy_marvell_init(void) { phy_register(&M88E1149S_driver); @@ -474,6 +484,7 @@ int phy_marvell_init(void) phy_register(&M88E1118R_driver); phy_register(&M88E1111S_driver); phy_register(&M88E1011S_driver); + phy_register(&M88E1518_driver); return 0; } diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 3596065694..eac9b6f458 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -33,6 +33,8 @@ #include <phy.h> #include <miiphy.h> #include <watchdog.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> #if !defined(CONFIG_PHYLIB) # error XILINX_GEM_ETHERNET requires PHYLIB @@ -67,13 +69,14 @@ #define ZYNQ_GEM_NWCTRL_MDEN_MASK 0x00000010 /* Enable MDIO port */ #define ZYNQ_GEM_NWCTRL_STARTTX_MASK 0x00000200 /* Start tx (tx_go) */ -#define ZYNQ_GEM_NWCFG_SPEED 0x00000001 /* 100 Mbps operation */ -#define ZYNQ_GEM_NWCFG_FDEN 0x00000002 /* Full Duplex mode */ -#define ZYNQ_GEM_NWCFG_FSREM 0x00020000 /* FCS removal */ +#define ZYNQ_GEM_NWCFG_SPEED100 0x000000001 /* 100 Mbps operation */ +#define ZYNQ_GEM_NWCFG_SPEED1000 0x000000400 /* 1Gbps operation */ +#define ZYNQ_GEM_NWCFG_FDEN 0x000000002 /* Full Duplex mode */ +#define ZYNQ_GEM_NWCFG_FSREM 0x000020000 /* FCS removal */ #define ZYNQ_GEM_NWCFG_MDCCLKDIV 0x000080000 /* Div pclk by 32, 80MHz */ +#define ZYNQ_GEM_NWCFG_MDCCLKDIV2 0x0000c0000 /* Div pclk by 48, 120MHz */ -#define ZYNQ_GEM_NWCFG_INIT (ZYNQ_GEM_NWCFG_SPEED | \ - ZYNQ_GEM_NWCFG_FDEN | \ +#define ZYNQ_GEM_NWCFG_INIT (ZYNQ_GEM_NWCFG_FDEN | \ ZYNQ_GEM_NWCFG_FSREM | \ ZYNQ_GEM_NWCFG_MDCCLKDIV) @@ -92,6 +95,17 @@ ZYNQ_GEM_DMACR_TXSIZE | \ ZYNQ_GEM_DMACR_RXBUF) +/* Use MII register 1 (MII status register) to detect PHY */ +#define PHY_DETECT_REG 1 + +/* Mask used to verify certain PHY features (or register contents) + * in the register above: + * 0x1000: 10Mbps full duplex support + * 0x0800: 10Mbps half duplex support + * 0x0008: Auto-negotiation support + */ +#define PHY_DETECT_MASK 0x1808 + /* Device registers */ struct zynq_gem_regs { u32 nwctrl; /* Network Control reg */ @@ -134,6 +148,8 @@ struct zynq_gem_priv { u32 rxbd_current; u32 rx_first_buf; int phyaddr; + u32 emio; + int init; struct phy_device *phydev; struct mii_dev *bus; }; @@ -196,6 +212,44 @@ static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data) ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data); } +static void phy_detection(struct eth_device *dev) +{ + int i; + u16 phyreg; + struct zynq_gem_priv *priv = dev->priv; + + if (priv->phyaddr != -1) { + phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg); + if ((phyreg != 0xFFFF) && + ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + debug("Default phy address %d is valid\n", + priv->phyaddr); + return; + } else { + debug("PHY address is not setup correctly %d\n", + priv->phyaddr); + priv->phyaddr = -1; + } + } + + debug("detecting phy address\n"); + if (priv->phyaddr == -1) { + /* detect the PHY address */ + for (i = 31; i >= 0; i--) { + phyread(dev, i, PHY_DETECT_REG, &phyreg); + if ((phyreg != 0xFFFF) && + ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + priv->phyaddr = i; + debug("Found valid phy address, %d\n", i); + return; + } + } + } + printf("PHY is not detected\n"); +} + static int zynq_gem_setup_mac(struct eth_device *dev) { u32 i, macaddrlow, macaddrhigh; @@ -226,7 +280,7 @@ static int zynq_gem_setup_mac(struct eth_device *dev) static int zynq_gem_init(struct eth_device *dev, bd_t * bis) { - u32 i; + u32 i, rclk, clk = 0; struct phy_device *phydev; const u32 stat_size = (sizeof(struct zynq_gem_regs) - offsetof(struct zynq_gem_regs, stat)) / 4; @@ -239,59 +293,92 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; - /* Disable all interrupts */ - writel(0xFFFFFFFF, ®s->idr); - - /* Disable the receiver & transmitter */ - writel(0, ®s->nwctrl); - writel(0, ®s->txsr); - writel(0, ®s->rxsr); - writel(0, ®s->phymntnc); - - /* Clear the Hash registers for the mac address pointed by AddressPtr */ - writel(0x0, ®s->hashl); - /* Write bits [63:32] in TOP */ - writel(0x0, ®s->hashh); + if (!priv->init) { + /* Disable all interrupts */ + writel(0xFFFFFFFF, ®s->idr); + + /* Disable the receiver & transmitter */ + writel(0, ®s->nwctrl); + writel(0, ®s->txsr); + writel(0, ®s->rxsr); + writel(0, ®s->phymntnc); + + /* Clear the Hash registers for the mac address + * pointed by AddressPtr + */ + writel(0x0, ®s->hashl); + /* Write bits [63:32] in TOP */ + writel(0x0, ®s->hashh); + + /* Clear all counters */ + for (i = 0; i <= stat_size; i++) + readl(®s->stat[i]); + + /* Setup RxBD space */ + memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd)); + /* Create the RxBD ring */ + memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers)); + + for (i = 0; i < RX_BUF; i++) { + priv->rx_bd[i].status = 0xF0000000; + priv->rx_bd[i].addr = + (u32)((char *)&(priv->rxbuffers) + + (i * PKTSIZE_ALIGN)); + } + /* WRAP bit to last BD */ + priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; + /* Write RxBDs to IP */ + writel((u32)&(priv->rx_bd), ®s->rxqbase); - /* Clear all counters */ - for (i = 0; i <= stat_size; i++) - readl(®s->stat[i]); + /* Setup for DMA Configuration register */ + writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); - /* Setup RxBD space */ - memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd)); - /* Create the RxBD ring */ - memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers)); + /* Setup for Network Control register, MDIO, Rx and Tx enable */ + setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK); - for (i = 0; i < RX_BUF; i++) { - priv->rx_bd[i].status = 0xF0000000; - priv->rx_bd[i].addr = (u32)((char *) &(priv->rxbuffers) + - (i * PKTSIZE_ALIGN)); + priv->init++; } - /* WRAP bit to last BD */ - priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; - /* Write RxBDs to IP */ - writel((u32) &(priv->rx_bd), ®s->rxqbase); - /* MAC Setup */ - /* Setup Network Configuration register */ - writel(ZYNQ_GEM_NWCFG_INIT, ®s->nwcfg); - - /* Setup for DMA Configuration register */ - writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); - - /* Setup for Network Control register, MDIO, Rx and Tx enable */ - setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK | - ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK); + phy_detection(dev); /* interface - look at tsec */ phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0); - phydev->supported &= supported; + phydev->supported = supported | ADVERTISED_Pause | + ADVERTISED_Asym_Pause; phydev->advertising = phydev->supported; priv->phydev = phydev; phy_config(phydev); phy_startup(phydev); + switch (phydev->speed) { + case SPEED_1000: + writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, + ®s->nwcfg); + rclk = (0 << 4) | (1 << 0); + clk = (1 << 20) | (8 << 8) | (0 << 4) | (1 << 0); + break; + case SPEED_100: + clrsetbits_le32(®s->nwcfg, ZYNQ_GEM_NWCFG_SPEED1000, + ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100); + rclk = 1 << 0; + clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0); + break; + case SPEED_10: + rclk = 1 << 0; + /* FIXME untested */ + clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0); + break; + } + + /* Change the rclk and clk only not using EMIO interface */ + if (!priv->emio) + zynq_slcr_gem_clk_setup(dev->iobase != + ZYNQ_GEM_BASEADDR0, rclk, clk); + + setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | + ZYNQ_GEM_NWCTRL_TXEN_MASK); + return 0; } @@ -307,11 +394,10 @@ static int zynq_gem_send(struct eth_device *dev, void *ptr, int len) writel((u32)&(priv->tx_bd), ®s->txqbase); /* Setup Tx BD */ - memset((void *) &(priv->tx_bd), 0, sizeof(struct emac_bd)); + memset((void *)&(priv->tx_bd), 0, sizeof(struct emac_bd)); priv->tx_bd.addr = (u32)ptr; - priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK | - ZYNQ_GEM_TXBUF_WRAP_MASK; + priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK; /* Start transmit */ setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_STARTTX_MASK); @@ -364,19 +450,17 @@ static int zynq_gem_recv(struct eth_device *dev) if ((++priv->rxbd_current) >= RX_BUF) priv->rxbd_current = 0; - - return frame_len; } - return 0; + return frame_len; } static void zynq_gem_halt(struct eth_device *dev) { struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; - /* Disable the receiver & transmitter */ - writel(0, ®s->nwctrl); + clrsetbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | + ZYNQ_GEM_NWCTRL_TXEN_MASK, 0); } static int zynq_gem_miiphyread(const char *devname, uchar addr, @@ -399,7 +483,7 @@ static int zynq_gem_miiphy_write(const char *devname, uchar addr, return phywrite(dev, addr, reg, val); } -int zynq_gem_initialize(bd_t *bis, int base_addr) +int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio) { struct eth_device *dev; struct zynq_gem_priv *priv; @@ -415,11 +499,8 @@ int zynq_gem_initialize(bd_t *bis, int base_addr) } priv = dev->priv; -#ifdef CONFIG_PHY_ADDR - priv->phyaddr = CONFIG_PHY_ADDR; -#else - priv->phyaddr = -1; -#endif + priv->phyaddr = phy_addr; + priv->emio = emio; sprintf(dev->name, "Gem.%x", base_addr); diff --git a/include/altera.h b/include/altera.h index 7a2bece032..6aad5ee868 100644 --- a/include/altera.h +++ b/include/altera.h @@ -27,23 +27,6 @@ #ifndef _ALTERA_H_ #define _ALTERA_H_ -/* Altera Model definitions - *********************************************************************/ -#define CONFIG_SYS_ACEX1K CONFIG_SYS_FPGA_DEV( 0x1 ) -#define CONFIG_SYS_CYCLON2 CONFIG_SYS_FPGA_DEV( 0x2 ) -#define CONFIG_SYS_STRATIX_II CONFIG_SYS_FPGA_DEV( 0x4 ) - -#define CONFIG_SYS_ALTERA_ACEX1K (CONFIG_SYS_FPGA_ALTERA | CONFIG_SYS_ACEX1K) -#define CONFIG_SYS_ALTERA_CYCLON2 (CONFIG_SYS_FPGA_ALTERA | CONFIG_SYS_CYCLON2) -#define CONFIG_SYS_ALTERA_STRATIX_II (CONFIG_SYS_FPGA_ALTERA | CONFIG_SYS_STRATIX_II) -/* Add new models here */ - -/* Altera Interface definitions - *********************************************************************/ -#define CONFIG_SYS_ALTERA_IF_PS CONFIG_SYS_FPGA_IF( 0x1 ) /* passive serial */ -#define CONFIG_SYS_ALTERA_IF_FPP CONFIG_SYS_FPGA_IF( 0x2 ) /* fast passive parallel */ -/* Add new interfaces here */ - typedef enum { /* typedef Altera_iface */ min_altera_iface_type, /* insert all new types after this */ passive_serial, /* serial data and external clock */ diff --git a/include/configs/M54455EVB.h b/include/configs/M54455EVB.h index 1bc2c5a0a4..536b7556fa 100644 --- a/include/configs/M54455EVB.h +++ b/include/configs/M54455EVB.h @@ -238,7 +238,7 @@ /* FPGA - Spartan 2 */ /* experiment -#define CONFIG_FPGA CONFIG_SYS_SPARTAN3 +#define CONFIG_FPGA #define CONFIG_FPGA_COUNT 1 #define CONFIG_SYS_FPGA_PROG_FEEDBACK #define CONFIG_SYS_FPGA_CHECK_CTRLC diff --git a/include/configs/MERGERBOX.h b/include/configs/MERGERBOX.h index c296e3cf06..30fb6c2ffd 100644 --- a/include/configs/MERGERBOX.h +++ b/include/configs/MERGERBOX.h @@ -606,7 +606,7 @@ * FPGA */ #define CONFIG_FPGA_COUNT 1 -#define CONFIG_FPGA CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA #define CONFIG_FPGA_ALTERA #define CONFIG_FPGA_CYCLON2 diff --git a/include/configs/MVBC_P.h b/include/configs/MVBC_P.h index 6850965fb3..72714688eb 100644 --- a/include/configs/MVBC_P.h +++ b/include/configs/MVBC_P.h @@ -310,7 +310,7 @@ #undef FPGA_DEBUG #undef CONFIG_SYS_FPGA_PROG_FEEDBACK -#define CONFIG_FPGA CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA #define CONFIG_FPGA_ALTERA 1 #define CONFIG_FPGA_CYCLON2 1 #define CONFIG_FPGA_COUNT 1 diff --git a/include/configs/MVBLM7.h b/include/configs/MVBLM7.h index a99ad3c44b..a9c00acc9a 100644 --- a/include/configs/MVBLM7.h +++ b/include/configs/MVBLM7.h @@ -499,7 +499,7 @@ "" #define CONFIG_FPGA_COUNT 1 -#define CONFIG_FPGA CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA #define CONFIG_FPGA_ALTERA #define CONFIG_FPGA_CYCLON2 diff --git a/include/configs/MVSMR.h b/include/configs/MVSMR.h index bf2f44ec6e..5d2ff14805 100644 --- a/include/configs/MVSMR.h +++ b/include/configs/MVSMR.h @@ -280,7 +280,7 @@ #undef FPGA_DEBUG #undef CONFIG_SYS_FPGA_PROG_FEEDBACK -#define CONFIG_FPGA CONFIG_SYS_XILINX_SPARTAN2 +#define CONFIG_FPGA #define CONFIG_FPGA_XILINX 1 #define CONFIG_FPGA_SPARTAN2 1 #define CONFIG_FPGA_COUNT 1 diff --git a/include/configs/omap3_mvblx.h b/include/configs/omap3_mvblx.h index 376a3d031e..f9adc01700 100644 --- a/include/configs/omap3_mvblx.h +++ b/include/configs/omap3_mvblx.h @@ -273,7 +273,7 @@ #endif /* (CONFIG_CMD_NET) */ #define CONFIG_FPGA_COUNT 1 -#define CONFIG_FPGA CONFIG_SYS_ALTERA_CYCLON2 +#define CONFIG_FPGA #define CONFIG_FPGA_ALTERA #define CONFIG_FPGA_CYCLON2 #define CONFIG_SYS_FPGA_PROG_FEEDBACK diff --git a/include/configs/zynq.h b/include/configs/zynq.h index 2989e723e0..38f04f642b 100644 --- a/include/configs/zynq.h +++ b/include/configs/zynq.h @@ -50,19 +50,50 @@ #define CONFIG_ZYNQ_SERIAL_BAUDRATE0 CONFIG_BAUDRATE #define CONFIG_ZYNQ_SERIAL_CLOCK0 50000000 -/* SCU timer address is hardcoded */ -#define CONFIG_SCUTIMER_BASEADDR 0xF8F00600 - /* Ethernet driver */ #define CONFIG_NET_MULTI #define CONFIG_ZYNQ_GEM -#define CONFIG_ZYNQ_GEM_BASEADDR0 0xE000B000 +#define CONFIG_ZYNQ_GEM0 +#define CONFIG_ZYNQ_GEM_PHY_ADDR0 7 + +#define CONFIG_ZYNQ_SDHCI +#define CONFIG_ZYNQ_SDHCI0 + +/* MMC */ +#if defined(CONFIG_ZYNQ_SDHCI0) || defined(CONFIG_ZYNQ_SDHCI1) +# define CONFIG_MMC +# define CONFIG_GENERIC_MMC +# define CONFIG_SDHCI +# define CONFIG_ZYNQ_SDHCI +# define CONFIG_CMD_MMC +# define CONFIG_CMD_FAT +# define CONFIG_SUPPORT_VFAT +# define CONFIG_CMD_EXT2 +# define CONFIG_DOS_PARTITION +#endif + +#define CONFIG_ZYNQ_I2C0 + +/* I2C */ +#if defined(CONFIG_ZYNQ_I2C0) || defined(CONFIG_ZYNQ_I2C1) +# define CONFIG_CMD_I2C +# define CONFIG_ZYNQ_I2C +# define CONFIG_HARD_I2C +# define CONFIG_SYS_I2C_SPEED 100000 +# define CONFIG_SYS_I2C_SLAVE 1 +#endif #if defined(CONFIG_ZYNQ_DCC) # define CONFIG_ARM_DCC # define CONFIG_CPU_V6 /* Required by CONFIG_ARM_DCC */ #endif +/* Enable the PL to be downloaded */ +#define CONFIG_FPGA +#define CONFIG_FPGA_XILINX +#define CONFIG_FPGA_ZYNQPL +#define CONFIG_CMD_FPGA + #define CONFIG_BOOTP_SERVERIP #define CONFIG_BOOTP_BOOTPATH #define CONFIG_BOOTP_GATEWAY diff --git a/include/fpga.h b/include/fpga.h index 30a4e6a2e8..38e9018c93 100644 --- a/include/fpga.h +++ b/include/fpga.h @@ -31,16 +31,6 @@ #define CONFIG_MAX_FPGA_DEVICES 5 #endif -/* CONFIG_FPGA bit assignments */ -#define CONFIG_SYS_FPGA_MAN(x) (x) -#define CONFIG_SYS_FPGA_DEV(x) ((x) << 8 ) -#define CONFIG_SYS_FPGA_IF(x) ((x) << 16 ) - -/* FPGA Manufacturer bits in CONFIG_FPGA */ -#define CONFIG_SYS_FPGA_XILINX CONFIG_SYS_FPGA_MAN( 0x1 ) -#define CONFIG_SYS_FPGA_ALTERA CONFIG_SYS_FPGA_MAN( 0x2 ) - - /* fpga_xxxx function return value definitions */ #define FPGA_SUCCESS 0 #define FPGA_FAIL -1 @@ -68,7 +58,10 @@ extern void fpga_init(void); extern int fpga_add(fpga_type devtype, void *desc); extern int fpga_count(void); extern int fpga_load(int devnum, const void *buf, size_t bsize); +extern int fpga_loadbitstream(int devnum, char *fpgadata, size_t size); extern int fpga_dump(int devnum, const void *buf, size_t bsize); extern int fpga_info(int devnum); +extern const fpga_desc *const fpga_validate(int devnum, const void *buf, + size_t bsize, char *fn); #endif /* _FPGA_H_ */ diff --git a/include/lattice.h b/include/lattice.h index 6a2cf93db1..49871da22d 100644 --- a/include/lattice.h +++ b/include/lattice.h @@ -278,9 +278,6 @@ typedef struct { char *desc; /* description string */ } Lattice_desc; /* end, typedef Altera_desc */ -/* Lattice Model Type */ -#define CONFIG_SYS_XP2 CONFIG_SYS_FPGA_DEV(0x1) - /* Board specific implementation specific function types */ typedef void (*Lattice_jtag_init)(void); typedef void (*Lattice_jtag_set_tdi)(int v); diff --git a/include/netdev.h b/include/netdev.h index fd3e243c71..516b351ebe 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -104,7 +104,7 @@ int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr, int txpp, int rxpp); int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags, unsigned long ctrl_addr); -int zynq_gem_initialize(bd_t *bis, int base_addr); +int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio); /* * As long as the Xilinx xps_ll_temac ethernet driver has not its own interface * exported by a public hader file, we need a global definition at this point. diff --git a/include/xilinx.h b/include/xilinx.h index 5f25b7a8a9..9a64771c60 100644 --- a/include/xilinx.h +++ b/include/xilinx.h @@ -27,28 +27,6 @@ #ifndef _XILINX_H_ #define _XILINX_H_ -/* Xilinx Model definitions - *********************************************************************/ -#define CONFIG_SYS_SPARTAN2 CONFIG_SYS_FPGA_DEV( 0x1 ) -#define CONFIG_SYS_VIRTEX_E CONFIG_SYS_FPGA_DEV( 0x2 ) -#define CONFIG_SYS_VIRTEX2 CONFIG_SYS_FPGA_DEV( 0x4 ) -#define CONFIG_SYS_SPARTAN3 CONFIG_SYS_FPGA_DEV( 0x8 ) -#define CONFIG_SYS_XILINX_SPARTAN2 (CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_SPARTAN2) -#define CONFIG_SYS_XILINX_VIRTEX_E (CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_VIRTEX_E) -#define CONFIG_SYS_XILINX_VIRTEX2 (CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_VIRTEX2) -#define CONFIG_SYS_XILINX_SPARTAN3 (CONFIG_SYS_FPGA_XILINX | CONFIG_SYS_SPARTAN3) -/* XXX - Add new models here */ - - -/* Xilinx Interface definitions - *********************************************************************/ -#define CONFIG_SYS_XILINX_IF_SS CONFIG_SYS_FPGA_IF( 0x1 ) /* slave serial */ -#define CONFIG_SYS_XILINX_IF_MS CONFIG_SYS_FPGA_IF( 0x2 ) /* master serial */ -#define CONFIG_SYS_XILINX_IF_SP CONFIG_SYS_FPGA_IF( 0x4 ) /* slave parallel */ -#define CONFIG_SYS_XILINX_IF_JTAG CONFIG_SYS_FPGA_IF( 0x8 ) /* jtag */ -#define CONFIG_SYS_XILINX_IF_MSM CONFIG_SYS_FPGA_IF( 0x10 ) /* master selectmap */ -#define CONFIG_SYS_XILINX_IF_SSM CONFIG_SYS_FPGA_IF( 0x20 ) /* slave selectmap */ - /* Xilinx types *********************************************************************/ typedef enum { /* typedef Xilinx_iface */ @@ -59,6 +37,7 @@ typedef enum { /* typedef Xilinx_iface */ jtag_mode, /* jtag/tap serial (not used ) */ master_selectmap, /* master SelectMap (virtex2) */ slave_selectmap, /* slave SelectMap (virtex2) */ + devcfg, /* devcfg interface (zynq) */ max_xilinx_iface_type /* insert all new types before this */ } Xilinx_iface; /* end, typedef Xilinx_iface */ @@ -68,6 +47,7 @@ typedef enum { /* typedef Xilinx_Family */ Xilinx_VirtexE, /* Virtex-E Family */ Xilinx_Virtex2, /* Virtex2 Family */ Xilinx_Spartan3, /* Spartan-III Family */ + xilinx_zynq, /* Zynq Family */ max_xilinx_type /* insert all new types before this */ } Xilinx_Family; /* end, typedef Xilinx_Family */ @@ -77,6 +57,7 @@ typedef struct { /* typedef Xilinx_desc */ size_t size; /* bytes of data part can accept */ void *iface_fns; /* interface function table */ int cookie; /* implementation specific cookie */ + char *name; /* device name in bitstream */ } Xilinx_desc; /* end, typedef Xilinx_desc */ /* Generic Xilinx Functions diff --git a/include/zynqpl.h b/include/zynqpl.h new file mode 100644 index 0000000000..0247ef61cc --- /dev/null +++ b/include/zynqpl.h @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2012-2013, Xilinx, Michal Simek + * + * (C) Copyright 2012 + * Joe Hershberger <joe.hershberger@ni.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ZYNQPL_H_ +#define _ZYNQPL_H_ + +#include <xilinx.h> + +extern int zynq_load(Xilinx_desc *desc, const void *image, size_t size); +extern int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize); +extern int zynq_info(Xilinx_desc *desc); + +#define XILINX_ZYNQ_7010 0x2 +#define XILINX_ZYNQ_7020 0x7 +#define XILINX_ZYNQ_7030 0xc +#define XILINX_ZYNQ_7045 0x11 + +/* Device Image Sizes */ +#define XILINX_XC7Z010_SIZE 16669920/8 +#define XILINX_XC7Z020_SIZE 32364512/8 +#define XILINX_XC7Z030_SIZE 47839328/8 +#define XILINX_XC7Z045_SIZE 106571232/8 + +/* Descriptor Macros */ +#define XILINX_XC7Z010_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z010_SIZE, NULL, cookie, "7z010" } + +#define XILINX_XC7Z020_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z020_SIZE, NULL, cookie, "7z020" } + +#define XILINX_XC7Z030_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z030_SIZE, NULL, cookie, "7z030" } + +#define XILINX_XC7Z045_DESC(cookie) \ +{ xilinx_zynq, devcfg, XILINX_XC7Z045_SIZE, NULL, cookie, "7z045" } + +#endif /* _ZYNQPL_H_ */ |