diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 00c893b..3b486f7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -179,10 +179,6 @@ select CPU_V7 select COMMON_CLK select CLKDEV_LOOKUP - select GPIOLIB - select HAVE_PBL_MULTI_IMAGES - select OFDEVICE if !(ARCH_SOCFPGA_XLOAD && ARCH_SOCFPGA_CYCLONE5) - select OFTREE if !(ARCH_SOCFPGA_XLOAD && ARCH_SOCFPGA_CYCLONE5) config ARCH_S3C24xx bool "Samsung S3C2410, S3C2440" diff --git a/arch/arm/boards/reflex-achilles/Makefile b/arch/arm/boards/reflex-achilles/Makefile index 6b42141..092c31d 100644 --- a/arch/arm/boards/reflex-achilles/Makefile +++ b/arch/arm/boards/reflex-achilles/Makefile @@ -1,2 +1,2 @@ -obj-y += lowlevel.o -pbl-y += lowlevel.o +lwl-y += lowlevel.o +obj-y += board.o diff --git a/arch/arm/boards/reflex-achilles/board.c b/arch/arm/boards/reflex-achilles/board.c new file mode 100644 index 0000000..29011ba --- /dev/null +++ b/arch/arm/boards/reflex-achilles/board.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +static int achilles_init(void) +{ + int pbl_index = 0; + + if (!of_machine_is_compatible("reflex,achilles")) + return 0; + + pbl_index = readl(0xFFD06210); + + pr_debug("Current barebox instance %d\n", pbl_index); + + return 0; +} +postcore_initcall(achilles_init); diff --git a/arch/arm/boards/reflex-achilles/lowlevel.c b/arch/arm/boards/reflex-achilles/lowlevel.c index 25e7ad0..2265aa8 100644 --- a/arch/arm/boards/reflex-achilles/lowlevel.c +++ b/arch/arm/boards/reflex-achilles/lowlevel.c @@ -1,24 +1,39 @@ #include #include #include -#include +#include #include #include +#include +#include #include +#include #include #include #include #include #include +#include #include "pll-config-arria10.c" #include "pinmux-config-arria10.c" #include +#define BAREBOX_PART 0 +#define BITSTREAM_PART 1 +#define BAREBOX1_OFFSET SZ_1M +#define BAREBOX2_OFFSET BAREBOX1_OFFSET + SZ_512K +#define BAREBOX3_OFFSET BAREBOX2_OFFSET + SZ_512K +#define BAREBOX4_OFFSET BAREBOX3_OFFSET + SZ_512K +#define BITSTREAM1_OFFSET 0x0 +#define BITSTREAM2_OFFSET BITSTREAM1_OFFSET + SZ_64M + extern char __dtb_socfpga_arria10_achilles_start[]; -static noinline void achilles_entry(void) +static noinline void achilles_start(void) { - void *fdt; + int pbl_index = 0; + int barebox = 0; + int bitstream = 0; arm_early_mmu_cache_invalidate(); @@ -27,22 +42,78 @@ arria10_init(&mainpll_cfg, &perpll_cfg, pinmux); - puts_ll("lowlevel init done\n"); + arria10_prepare_mmc(BAREBOX_PART, BITSTREAM_PART); + + pbl_index = readl(ARRIA10_SYSMGR_ROM_INITSWLASTLD); + + switch (pbl_index) { + case 0: + barebox = BAREBOX1_OFFSET; + bitstream = BITSTREAM1_OFFSET; + break; + case 1: + barebox = BAREBOX2_OFFSET; + bitstream = BITSTREAM1_OFFSET; + break; + case 2: + barebox = BAREBOX3_OFFSET; + bitstream = BITSTREAM2_OFFSET; + break; + case 3: + barebox = BAREBOX4_OFFSET; + bitstream = BITSTREAM2_OFFSET; + break; + } + + arria10_load_fpga(bitstream, SZ_64M); + + arria10_finish_io(&mainpll_cfg, &perpll_cfg, pinmux); arria10_ddr_calibration_sequence(); - puts_ll("SDRAM setup done\n"); + arria10_start_image(barebox); +} + +ENTRY_FUNCTION(start_socfpga_achilles, r0, r1, r2) +{ + void *fdt; + + if (get_pc() > ARRIA10_OCRAM_ADDR) { + arm_cpu_lowlevel_init(); + + arm_setup_stack(ARRIA10_OCRAM_ADDR + SZ_256K - 32); + + achilles_start(); + } fdt = __dtb_socfpga_arria10_achilles_start + get_runtime_offset(); barebox_arm_entry(0x0, SZ_2G + SZ_1G, fdt); } -ENTRY_FUNCTION(start_socfpga_achilles, r0, r1, r2) +ENTRY_FUNCTION(start_socfpga_achilles_bringup, r0, r1, r2) { + void *fdt; + arm_cpu_lowlevel_init(); - arm_setup_stack(0xffe00000 + SZ_256K - SZ_32K - SZ_4K - 16); + arm_setup_stack(ARRIA10_OCRAM_ADDR + SZ_256K - 16); - achilles_entry(); + arm_early_mmu_cache_invalidate(); + + relocate_to_current_adr(); + setup_c(); + + arria10_init(&mainpll_cfg, &perpll_cfg, pinmux); + + /* wait for fpga_usermode */ + a10_wait_for_usermode(0x1000000); + + arria10_finish_io(&mainpll_cfg, &perpll_cfg, pinmux); + + arria10_ddr_calibration_sequence(); + + fdt = __dtb_socfpga_arria10_achilles_start + get_runtime_offset(); + + barebox_arm_entry(0x0, SZ_2G + SZ_1G, fdt); } diff --git a/arch/arm/boards/reflex-achilles/pinmux-config-arria10.c b/arch/arm/boards/reflex-achilles/pinmux-config-arria10.c index 246838a..b6a7230 100644 --- a/arch/arm/boards/reflex-achilles/pinmux-config-arria10.c +++ b/arch/arm/boards/reflex-achilles/pinmux-config-arria10.c @@ -69,7 +69,7 @@ [arria10_pincfg_dedicated_io_3] = 0xb080a, [arria10_pincfg_dedicated_io_4] = 0xa282a, [arria10_pincfg_dedicated_io_5] = 0xa282a, -[arria10_pincfg_dedicated_io_6] = 0xa282a, +[arria10_pincfg_dedicated_io_6] = 0x8282a, [arria10_pincfg_dedicated_io_7] = 0xa282a, [arria10_pincfg_dedicated_io_8] = 0xa282a, [arria10_pincfg_dedicated_io_9] = 0xa282a, diff --git a/arch/arm/boards/reflex-achilles/pll-config-arria10.c b/arch/arm/boards/reflex-achilles/pll-config-arria10.c index 94d5966..9da41ec 100644 --- a/arch/arm/boards/reflex-achilles/pll-config-arria10.c +++ b/arch/arm/boards/reflex-achilles/pll-config-arria10.c @@ -6,8 +6,8 @@ .cntr3clk_cnt = 900, .cntr4clk_cnt = 900, .cntr5clk_cnt = 900, - .cntr6clk_cnt = 7, - .cntr7clk_cnt = 900, + .cntr6clk_cnt = 9, + .cntr7clk_cnt = 19, .cntr7clk_src = 0, .cntr8clk_cnt = 900, .cntr9clk_cnt = 900, @@ -24,19 +24,19 @@ .nocdiv_l4spclk = 2, .vco0_psrc = 0, .vco1_denom = 1, - .vco1_numer = 127, + .vco1_numer = 159, .mpuclk = 0x3840001, - .nocclk = 0x3840003, + .nocclk = 0x3840004, }; static struct arria10_perpll_cfg perpll_cfg = { - .cntr2clk_cnt = 5, + .cntr2clk_cnt = 7, .cntr2clk_src = 1, .cntr3clk_cnt = 900, .cntr3clk_src = 1, - .cntr4clk_cnt = 14, + .cntr4clk_cnt = 19, .cntr4clk_src = 1, - .cntr5clk_cnt = 374, + .cntr5clk_cnt = 499, .cntr5clk_src = 1, .cntr6clk_cnt = 900, .cntr6clk_src = 0, @@ -50,5 +50,5 @@ .gpiodiv_gpiodbclk = 32000, .vco0_psrc = 0, .vco1_denom = 1, - .vco1_numer = 119, + .vco1_numer = 159, }; diff --git a/arch/arm/configs/socfpga-arria10_defconfig b/arch/arm/configs/socfpga-arria10_defconfig index e661895..53e932d 100644 --- a/arch/arm/configs/socfpga-arria10_defconfig +++ b/arch/arm/configs/socfpga-arria10_defconfig @@ -1,9 +1,9 @@ CONFIG_ARCH_SOCFPGA=y CONFIG_MACH_SOCFPGA_REFLEX_ACHILLES=y -CONFIG_THUMB2_BAREBOX=y +CONFIG_AEABI=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_ARM_UNWIND=y -CONFIG_MMU=y +CONFIG_TEXT_BASE=0xffe00000 CONFIG_MALLOC_SIZE=0x0 CONFIG_MALLOC_TLSF=y CONFIG_KALLSYMS=y @@ -17,7 +17,6 @@ CONFIG_BOOTM_VERBOSE=y CONFIG_BOOTM_INITRD=y CONFIG_BOOTM_OFTREE=y -CONFIG_PBL_CONSOLE=y CONFIG_DEFAULT_COMPRESSION_LZO=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_POLLER=y @@ -57,7 +56,6 @@ CONFIG_CMD_CLK=y CONFIG_CMD_DETECT=y CONFIG_CMD_FLASH=y -CONFIG_CMD_GPIO=y CONFIG_CMD_BAREBOX_UPDATE=y CONFIG_CMD_FIRMWARELOAD=y CONFIG_CMD_OF_NODE=y @@ -72,6 +70,7 @@ CONFIG_OF_BAREBOX_ENV_IN_FS=y CONFIG_DRIVER_SERIAL_NS16550=y CONFIG_DRIVER_NET_DESIGNWARE=y +CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA=y CONFIG_MICREL_PHY=y # CONFIG_SPI is not set CONFIG_MCI=y diff --git a/arch/arm/dts/socfpga_arria10_achilles.dts b/arch/arm/dts/socfpga_arria10_achilles.dts index 059a92c..c03982e 100644 --- a/arch/arm/dts/socfpga_arria10_achilles.dts +++ b/arch/arm/dts/socfpga_arria10_achilles.dts @@ -30,8 +30,7 @@ environment { compatible = "barebox,environment"; - device-path = &mmc, "partname:1"; - file-path = "barebox.env"; + device-path = &environment_mmc; }; }; @@ -93,17 +92,17 @@ &i2c0 { status = "okay"; - tempsensor: ti,tmp102@0x48 { + tempsensor: ti,tmp102@48 { compatible = "ti,tmp102"; reg = <0x48>; }; - rtc: nxp,pcf8563@0x51 { + rtc: nxp,pcf8563@51 { compatible = "nxp,pcf8563"; reg = <0x51>; }; - eeprom: at24@0x54 { + eeprom: at24@54 { compatible = "at24"; reg = <0x54>; bytelen = <256>; @@ -116,6 +115,11 @@ broken-cd; bus-width = <1>; status = "okay"; + + environment_mmc: partition@178000 { + label = "environment"; + reg = <0x178000 0x8000>; + }; }; &uart0 { diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c index 63713ac..4cf570e 100644 --- a/arch/arm/lib32/bootm.c +++ b/arch/arm/lib32/bootm.c @@ -434,6 +434,12 @@ .filetype = filetype_arm_barebox, }; +static struct image_handler socfpga_xload_handler = { + .name = "SoCFPGA prebootloader image", + .bootm = do_bootm_linux, + .filetype = filetype_socfpga_xload, +}; + #include static int aimage_load_resource(int fd, struct resource *r, void* buf, int ps) @@ -628,6 +634,7 @@ globalvar_add_simple_bool("bootm.boot_atag", &bootm_boot_atag); register_image_handler(&barebox_handler); + register_image_handler(&socfpga_xload_handler); register_image_handler(&uimage_handler); register_image_handler(&rawimage_handler); register_image_handler(&zimage_handler); diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 58e4876..65097b6 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -11,17 +11,24 @@ config ARCH_TEXT_BASE hex default 0x00100000 if MACH_SOCFPGA_CYCLONE5 + default 0xffe00000 if MACH_SOCFPGA_ARRIA10 comment "Altera SoCFPGA System-on-Chip" config ARCH_SOCFPGA_CYCLONE5 bool select CPU_V7 + select HAVE_PBL_MULTI_IMAGES + select OFDEVICE if !ARCH_SOCFPGA_XLOAD + select OFTREE if !ARCH_SOCFPGA_XLOAD config ARCH_SOCFPGA_ARRIA10 bool select CPU_V7 - select HAVE_MACH_ARM_HEAD + select RESET_CONTROLLER + select HAVE_PBL_MULTI_IMAGES + select OFDEVICE + select OFTREE config MACH_SOCFPGA_ALTERA_SOCDK select ARCH_SOCFPGA_CYCLONE5 diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index cbb47fa..3a3a2fc 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -2,7 +2,15 @@ pbl-$(CONFIG_ARCH_SOCFPGA_CYCLONE5) += cyclone5-clock-manager.o obj-$(CONFIG_ARCH_SOCFPGA_CYCLONE5) += cyclone5-generic.o nic301.o cyclone5-bootsource.o cyclone5-reset-manager.o -pbl-$(CONFIG_ARCH_SOCFPGA_ARRIA10) += arria10-init.o arria10-clock-manager.o arria10-sdram.o arria10-reset-manager.o arria10-bootsource.o -obj-$(CONFIG_ARCH_SOCFPGA_ARRIA10) += arria10-bootsource.o arria10-generic.o arria10-reset-manager.o +pbl-$(CONFIG_ARCH_SOCFPGA_ARRIA10) += arria10-xload.o \ + arria10-xload-emmc.o +obj-pbl-$(CONFIG_ARCH_SOCFPGA_ARRIA10) += arria10-bootsource.o \ + arria10-clock-manager.o \ + arria10-generic.o \ + arria10-reset-manager.o \ + arria10-init.o \ + arria10-sdram.o +ifdef CONFIG_ARCH_SOCFPGA_CYCLONE5 obj-$(CONFIG_ARCH_SOCFPGA_XLOAD) += xload.o +endif diff --git a/arch/arm/mach-socfpga/arria10-bootsource.c b/arch/arm/mach-socfpga/arria10-bootsource.c index 26af64a..3319dc4 100644 --- a/arch/arm/mach-socfpga/arria10-bootsource.c +++ b/arch/arm/mach-socfpga/arria10-bootsource.c @@ -15,16 +15,17 @@ #include #include #include +#include #include -static int arria10_boot_save_loc(void) -{ +enum bootsource arria10_get_bootsource(void) { enum bootsource src = BOOTSOURCE_UNKNOWN; uint32_t val; + uint32_t mask = ARRIA10_SYSMGR_BOOTINFO_BSEL_MASK; val = readl(ARRIA10_SYSMGR_BOOTINFO); - switch ((val & 0x7000) >> 12) { + switch ((val & mask) >> ARRIA10_SYSMGR_BOOTINFO_BSEL_SHIFT) { case 0: /* reserved */ break; @@ -45,6 +46,15 @@ break; } + return src; +} + +static int arria10_boot_save_loc(void) +{ + enum bootsource src; + + src = arria10_get_bootsource(); + bootsource_set(src); bootsource_set_instance(0); diff --git a/arch/arm/mach-socfpga/arria10-generic.c b/arch/arm/mach-socfpga/arria10-generic.c index 6a10c19..53ec278 100644 --- a/arch/arm/mach-socfpga/arria10-generic.c +++ b/arch/arm/mach-socfpga/arria10-generic.c @@ -63,7 +63,7 @@ pr_debug("Setting SDMMC phase shifts for Arria10\n"); writel(ARRIA10_SYSMGR_SDMMC_DRVSEL(3) | - ARRIA10_SYSMGR_SDMMC_SMPLSEL(0), + ARRIA10_SYSMGR_SDMMC_SMPLSEL(2), ARRIA10_SYSMGR_SDMMC); pr_debug("Initialize EMACs\n"); diff --git a/arch/arm/mach-socfpga/arria10-init.c b/arch/arm/mach-socfpga/arria10-init.c index f016b84..2fa44c2 100644 --- a/arch/arm/mach-socfpga/arria10-init.c +++ b/arch/arm/mach-socfpga/arria10-init.c @@ -127,6 +127,32 @@ writel(0x0007FFFF, ARRIA10_SYSMGR_ADDR + 0x94); } +void arria10_finish_io(struct arria10_mainpll_cfg *mainpll, + struct arria10_perpll_cfg *perpll, + uint32_t *pinmux) +{ + int i; + + /* shared pins */ + for (i = arria10_pinmux_shared_io_q1_1; + i <= arria10_pinmux_shared_io_q4_12; i++) + writel(pinmux[i], ARRIA10_PINMUX_SHARED_3V_IO_GRP_ADDR + + (i - arria10_pinmux_shared_io_q1_1) * sizeof(uint32_t)); + + /* usefpga: select source for signals: hps or fpga */ + for (i = arria10_pinmux_rgmii0_usefpga; + i < arria10_pinmux_max; i++) + writel(pinmux[i], ARRIA10_PINMUX_FPGA_INTERFACE_ADDR + + (i - arria10_pinmux_rgmii0_usefpga) * sizeof(uint32_t)); + + arria10_reset_deassert_shared_peripherals(); + + arria10_reset_deassert_fpga_peripherals(); + + INIT_LL(); + + puts_ll("lowlevel init done\n"); +} /* * First C function to initialize the critical hardware early */ @@ -173,25 +199,4 @@ /* deassert peripheral resets */ arria10_reset_deassert_dedicated_peripherals(); - - /* wait for fpga_usermode */ - while ((readl(0xffd03080) & 0x6) == 0); - - /* shared pins */ - for (i = arria10_pinmux_shared_io_q1_1; - i <= arria10_pinmux_shared_io_q4_12; i++) - writel(pinmux[i], ARRIA10_PINMUX_SHARED_3V_IO_GRP_ADDR + - (i - arria10_pinmux_shared_io_q1_1) * sizeof(uint32_t)); - - arria10_reset_deassert_shared_peripherals(); - - /* usefpga: select source for signals: hps or fpga */ - for (i = arria10_pinmux_rgmii0_usefpga; - i < arria10_pinmux_max; i++) - writel(pinmux[i], ARRIA10_PINMUX_FPGA_INTERFACE_ADDR + - (i - arria10_pinmux_rgmii0_usefpga) * sizeof(uint32_t)); - - arria10_reset_deassert_fpga_peripherals(); - - INIT_LL(); } diff --git a/arch/arm/mach-socfpga/arria10-reset-manager.c b/arch/arm/mach-socfpga/arria10-reset-manager.c index a7e4bd6..76adc17 100644 --- a/arch/arm/mach-socfpga/arria10-reset-manager.c +++ b/arch/arm/mach-socfpga/arria10-reset-manager.c @@ -5,8 +5,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -14,23 +16,35 @@ void arria10_reset_peripherals(void) { - unsigned mask_ecc_ocp = ARRIA10_RSTMGR_PER0MODRST_EMAC0OCP | + enum bootsource src; + + uint32_t mask = ARRIA10_RSTMGR_PER0MODRST_EMAC0OCP | ARRIA10_RSTMGR_PER0MODRST_EMAC1OCP | ARRIA10_RSTMGR_PER0MODRST_EMAC2OCP | ARRIA10_RSTMGR_PER0MODRST_USB0OCP | ARRIA10_RSTMGR_PER0MODRST_USB1OCP | ARRIA10_RSTMGR_PER0MODRST_NANDOCP | - ARRIA10_RSTMGR_PER0MODRST_QSPIOCP | - ARRIA10_RSTMGR_PER0MODRST_SDMMCOCP; + ARRIA10_RSTMGR_PER0MODRST_QSPIOCP; - /* disable all components except ECC_OCP, L4 Timer0 and L4 WD0 */ + src = arria10_get_bootsource(); + if (src == BOOTSOURCE_MMC) { + mask |= ARRIA10_RSTMGR_PER0MODRST_SDMMC; + mask |= ARRIA10_RSTMGR_PER0MODRST_SDMMCOCP; + } + + /* disable all components except the ECC_OCP and bootsource */ writel(0xffffffff, ARRIA10_RSTMGR_ADDR + ARRIA10_RSTMGR_PER1MODRST); - setbits_le32(ARRIA10_RSTMGR_ADDR + ARRIA10_RSTMGR_PER0MODRST, - ~mask_ecc_ocp); + writel(~mask, ARRIA10_RSTMGR_ADDR + ARRIA10_RSTMGR_PER0MODRST); + + mask = 0xffffffff; + + if (src == BOOTSOURCE_MMC) { + mask &= ~ARRIA10_RSTMGR_PER0MODRST_SDMMC; + mask &= ~ARRIA10_RSTMGR_PER0MODRST_SDMMCOCP; + } /* Finally disable the ECC_OCP */ - setbits_le32(ARRIA10_RSTMGR_ADDR + ARRIA10_RSTMGR_PER0MODRST, - mask_ecc_ocp); + writel(mask, ARRIA10_RSTMGR_ADDR + ARRIA10_RSTMGR_PER0MODRST); } void arria10_reset_deassert_dedicated_peripherals(void) @@ -45,8 +59,7 @@ /* enable ECC OCP first */ clrbits_le32(ARRIA10_RSTMGR_ADDR + ARRIA10_RSTMGR_PER0MODRST, mask); - mask = ARRIA10_RSTMGR_PER0MODRST_SDMMC | - ARRIA10_RSTMGR_PER0MODRST_QSPI | + mask = ARRIA10_RSTMGR_PER0MODRST_QSPI | ARRIA10_RSTMGR_PER0MODRST_NAND | ARRIA10_RSTMGR_PER0MODRST_DMA; diff --git a/arch/arm/mach-socfpga/arria10-sdram.c b/arch/arm/mach-socfpga/arria10-sdram.c index 08de0e3..35c355d 100644 --- a/arch/arm/mach-socfpga/arria10-sdram.c +++ b/arch/arm/mach-socfpga/arria10-sdram.c @@ -531,5 +531,7 @@ if (arria10_sdram_firewall_setup()) puts_ll("FW: Error Configuring Firewall\n"); + puts_ll("SDRAM setup done\n"); + return 0; } diff --git a/arch/arm/mach-socfpga/arria10-xload-emmc.c b/arch/arm/mach-socfpga/arria10-xload-emmc.c new file mode 100644 index 0000000..dcc38cf --- /dev/null +++ b/arch/arm/mach-socfpga/arria10-xload-emmc.c @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../drivers/mci/sdhci.h" +#include "../../../drivers/mci/dw_mmc.h" + +#define SECTOR_SIZE 512 + +static int dwmci_wait_reset(uint32_t value) +{ + uint32_t ctrl; + int32_t timeout; + + timeout = 10000; + + writel(value, ARRIA10_SDMMC_ADDR + DWMCI_CTRL); + + while (timeout-- > 0) { + ctrl = readl(ARRIA10_SDMMC_ADDR + DWMCI_CTRL); + if (!(ctrl & DWMCI_RESET_ALL)) + return 0; + } + + return -EIO; +} + +static int dwmci_prepare_data(struct mci_data *data) +{ + unsigned long ctrl; + + dwmci_wait_reset(DWMCI_CTRL_FIFO_RESET); + + writel(DWMCI_INTMSK_TXDR | DWMCI_INTMSK_RXDR, + ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + + ctrl = readl(ARRIA10_SDMMC_ADDR + DWMCI_INTMASK); + ctrl |= DWMCI_INTMSK_TXDR | DWMCI_INTMSK_RXDR; + writel(ctrl, ARRIA10_SDMMC_ADDR + DWMCI_INTMASK); + + ctrl = readl(ARRIA10_SDMMC_ADDR + DWMCI_CTRL); + ctrl &= ~(DWMCI_IDMAC_EN | DWMCI_DMA_EN); + writel(ctrl, ARRIA10_SDMMC_ADDR + DWMCI_CTRL); + + writel(0x1, ARRIA10_SDMMC_ADDR + DWMCI_FIFOTH); + writel(0xffffffff, ARRIA10_SDMMC_ADDR + DWMCI_TMOUT); + writel(0x0, ARRIA10_SDMMC_ADDR + DWMCI_IDINTEN); + + return 0; +} + +static int dwmci_read_data_pio(struct mci_data *data) +{ + u32 *pdata = (u32 *)data->dest; + u32 val, status, timeout; + u32 rcnt, rlen = 0; + + for (rcnt = (data->blocksize * data->blocks)>>2; rcnt; rcnt--) { + timeout = 20000; + status = readl(ARRIA10_SDMMC_ADDR + DWMCI_STATUS); + while (--timeout > 0 + && (status & DWMCI_STATUS_FIFO_EMPTY)) { + __udelay(200); + status = readl(ARRIA10_SDMMC_ADDR + DWMCI_STATUS); + } + if (!timeout) + break; + + val = readl(ARRIA10_SDMMC_ADDR + DWMCI_DATA); + *pdata++ = val; + rlen += 4; + } + writel(DWMCI_INTMSK_RXDR, ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + + return rlen; +} + +static int dwmci_cmd(struct mci_cmd *cmd, struct mci_data *data) +{ + int flags = 0; + uint32_t mask; + int timeout; + + timeout = 100000; + while (readl(ARRIA10_SDMMC_ADDR + DWMCI_STATUS) & DWMCI_STATUS_BUSY) { + if (timeout-- <= 0) + return -ETIMEDOUT; + + } + + writel(DWMCI_INTMSK_ALL, ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + + if (data) { + writel(data->blocksize, ARRIA10_SDMMC_ADDR + DWMCI_BLKSIZ); + writel(data->blocksize * data->blocks, ARRIA10_SDMMC_ADDR + + DWMCI_BYTCNT); + + dwmci_prepare_data(data); + } + + writel(cmd->cmdarg, ARRIA10_SDMMC_ADDR + DWMCI_CMDARG); + + if (data) + flags = DWMCI_CMD_DATA_EXP; + + if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) + return -EINVAL; + + if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) + flags |= DWMCI_CMD_ABORT_STOP; + else + flags |= DWMCI_CMD_PRV_DAT_WAIT; + + if (cmd->resp_type & MMC_RSP_PRESENT) { + flags |= DWMCI_CMD_RESP_EXP; + if (cmd->resp_type & MMC_RSP_136) + flags |= DWMCI_CMD_RESP_LENGTH; + } + + if (cmd->resp_type & MMC_RSP_CRC) + flags |= DWMCI_CMD_CHECK_CRC; + + flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG); + + writel(flags, ARRIA10_SDMMC_ADDR + DWMCI_CMD); + + for (timeout = 10000; timeout > 0; timeout--) { + mask = readl(ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + if (mask & DWMCI_INTMSK_CDONE) { + if (!data) + writel(mask, ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + break; + } + } + + if (timeout <= 0) + return -ETIMEDOUT; + + if (mask & DWMCI_INTMSK_RTO) + return -ETIMEDOUT; + else if (mask & DWMCI_INTMSK_RE) + return -EIO; + + if (cmd->resp_type & MMC_RSP_PRESENT) { + if (cmd->resp_type & MMC_RSP_136) { + cmd->response[0] = readl(ARRIA10_SDMMC_ADDR + DWMCI_RESP3); + cmd->response[1] = readl(ARRIA10_SDMMC_ADDR + DWMCI_RESP2); + cmd->response[2] = readl(ARRIA10_SDMMC_ADDR + DWMCI_RESP1); + cmd->response[3] = readl(ARRIA10_SDMMC_ADDR + DWMCI_RESP0); + } else { + cmd->response[0] = readl(ARRIA10_SDMMC_ADDR + DWMCI_RESP0); + } + } + + if (data) { + do { + mask = readl(ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + if (mask & (DWMCI_DATA_ERR)) + return -EIO; + + if (mask & DWMCI_INTMSK_RXDR) { + dwmci_read_data_pio(data); + mask = readl(ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + } + } while (!(mask & DWMCI_INTMSK_DTO)); + + writel(mask, ARRIA10_SDMMC_ADDR + DWMCI_RINTSTS); + } + + return 0; +} + +int arria10_read_blocks(void *dst, int blocknum, size_t len) +{ + struct mci_cmd cmd; + struct mci_data data; + int ret; + int blocks; + + blocks = len / SECTOR_SIZE; + + if (blocks > 1) + cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; + else + cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK; + + cmd.cmdarg = blocknum; + cmd.resp_type = MMC_RSP_R1; + + data.dest = dst; + data.blocks = blocks; + data.blocksize = SECTOR_SIZE; + data.flags = MMC_DATA_READ; + + ret = dwmci_cmd(&cmd, &data); + + if (ret || blocks > 1) { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + + dwmci_cmd(&cmd, NULL); + } + + return ret; +} + +void arria10_init_mmc(void) +{ + writel(ARRIA10_SYSMGR_SDMMC_DRVSEL(3) | + ARRIA10_SYSMGR_SDMMC_SMPLSEL(2), + ARRIA10_SYSMGR_SDMMC); + + /* enable power to card */ + writel(0x1, ARRIA10_SDMMC_ADDR + DWMCI_PWREN); + + writel(DWMCI_CTYPE_1BIT, ARRIA10_SDMMC_ADDR + DWMCI_CTYPE); +} diff --git a/arch/arm/mach-socfpga/arria10-xload.c b/arch/arm/mach-socfpga/arria10-xload.c new file mode 100644 index 0000000..f665ba4 --- /dev/null +++ b/arch/arm/mach-socfpga/arria10-xload.c @@ -0,0 +1,457 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int a10_update_bits(unsigned int reg, unsigned int mask, + unsigned int val) +{ + unsigned int tmp, orig; + int ret = 0; + + orig = readl(ARRIA10_FPGAMGRREGS_ADDR + reg); + tmp = orig & ~mask; + tmp |= val & mask; + + if (tmp != orig) + ret = writel(tmp, ARRIA10_FPGAMGRREGS_ADDR + reg); + + return ret; +} + +static uint32_t socfpga_a10_fpga_read_stat(void) +{ + return readl(ARRIA10_FPGAMGRREGS_ADDR + A10_FPGAMGR_IMGCFG_STAT_OFST); +} + +static int a10_fpga_wait_for_condone(void) +{ + u32 reg, i; + + for (i = 0; i < 0x1000000 ; i++) { + reg = socfpga_a10_fpga_read_stat(); + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) + return 0; + + if ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0) + return -EIO; + } + + return -ETIMEDOUT; +} + +static void a10_fpga_generate_dclks(uint32_t count) +{ + int32_t timeout; + + /* Clear any existing DONE status. */ + writel(A10_FPGAMGR_DCLKSTAT_DCLKDONE, ARRIA10_FPGAMGRREGS_ADDR + + A10_FPGAMGR_DCLKSTAT_OFST); + + /* Issue the DCLK regmap. */ + writel(count, ARRIA10_FPGAMGRREGS_ADDR + A10_FPGAMGR_DCLKCNT_OFST); + + /* wait till the dclkcnt done */ + timeout = 10000000; + + while (!readl(ARRIA10_FPGAMGRREGS_ADDR + A10_FPGAMGR_DCLKSTAT_OFST)) { + if (timeout-- < 0) + return; + } + + /* Clear DONE status. */ + writel(A10_FPGAMGR_DCLKSTAT_DCLKDONE, ARRIA10_FPGAMGRREGS_ADDR + + A10_FPGAMGR_DCLKSTAT_OFST); +} + +static unsigned int a10_fpga_get_cd_ratio(unsigned int cfg_width, + bool encrypt, bool compress) +{ + unsigned int cd_ratio; + + /* + * cd ratio is dependent on cfg width and whether the bitstream + * is encrypted and/or compressed. + * + * | width | encr. | compr. | cd ratio | value | + * | 16 | 0 | 0 | 1 | 0 | + * | 16 | 0 | 1 | 4 | 2 | + * | 16 | 1 | 0 | 2 | 1 | + * | 16 | 1 | 1 | 4 | 2 | + * | 32 | 0 | 0 | 1 | 0 | + * | 32 | 0 | 1 | 8 | 3 | + * | 32 | 1 | 0 | 4 | 2 | + * | 32 | 1 | 1 | 8 | 3 | + */ + if (!compress && !encrypt) + return CDRATIO_x1; + + if (compress) + cd_ratio = CDRATIO_x4; + else + cd_ratio = CDRATIO_x2; + + /* If 32 bit, double the cd ratio by incrementing the field */ + if (cfg_width == CFGWDTH_32) + cd_ratio += 1; + + return cd_ratio; +} + +static int a10_fpga_set_cdratio(unsigned int cfg_width, + const void *buf) +{ + unsigned int cd_ratio; + int encrypt, compress; + u32 *rbf_data = (u32 *)buf; + + encrypt = (rbf_data[69] >> 2) & 3; + encrypt = encrypt != 0; + + compress = (rbf_data[229] >> 1) & 1; + compress = !compress; + + cd_ratio = a10_fpga_get_cd_ratio(cfg_width, encrypt, compress); + + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK, + cd_ratio << A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT); + + return 0; +} + +static int a10_fpga_init(void *buf) +{ + uint32_t stat, mask; + uint32_t val; + uint32_t timeout; + + val = CFGWDTH_32 << A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT; + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH, val); + + a10_fpga_set_cdratio(CFGWDTH_32, buf); + + mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN | + A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN; + /* Make sure no external devices are interfering */ + timeout = 10000; + while ((socfpga_a10_fpga_read_stat() & mask) != mask) { + if (timeout-- < 0) + return -ETIMEDOUT; + } + + /* S2F_NCE = 1 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE); + /* S2F_PR_REQUEST = 0 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST, 0); + /* EN_CFG_CTRL = 0 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, 0); + /* S2F_NCONFIG = 1 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_00_OFST, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG); + /* S2F_NSTATUS_OE = 0 and S2f_CONDONE_OE = 0 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_00_OFST, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE | + A10_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE, + 0); + /* Enable overrides: S2F_NENABLE_CONFIG = 0 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, 0); + /* Enable overrides: S2F_NENABLE_NCONFIG = 0 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_00_OFST, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG, 0); + /* Disable unused overrides: S2F_NENABLE_NSTATUS = 1 and S2F_NENABLE_CONDONE = 1 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_00_OFST, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS | + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS | + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE); + /* Drive chip select S2F_NCE = 0 */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE, 0); + + mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN | + A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN; + + timeout = 100000; + while ((socfpga_a10_fpga_read_stat() & mask) != mask) { + if (timeout-- < 0) + return -ETIMEDOUT; + } + + /* reset the configuration */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_00_OFST, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG, 0); + + timeout = 1000000; + while ((socfpga_a10_fpga_read_stat() & + A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) != 0) { + if (timeout-- < 0) + return -ETIMEDOUT; + } + + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_00_OFST, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG); + + mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN; + /* wait for nstatus == 1 */ + timeout = 1000000; + while ((socfpga_a10_fpga_read_stat() & mask) != mask) { + if (timeout-- < 0) { + writel(socfpga_a10_fpga_read_stat(), 0xFFD06238); + return -ETIMEDOUT; + } + } + + stat = socfpga_a10_fpga_read_stat(); + if ((stat & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) != 0) + return -EINVAL; + if ((stat & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_OE) == 0) + return -EINVAL; + + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL | + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA, + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA | + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL); + + /* Check fpga_usermode */ + if ((socfpga_a10_fpga_read_stat() & 0x6) == 0x6) + return -EIO; + + return 0; +} + +static int a10_fpga_write(void *buf, size_t count) +{ + const uint32_t *buf32 = buf; + uint32_t reg; + + /* Stop if FPGA is configured */ + reg = socfpga_a10_fpga_read_stat(); + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) + return -ENOSPC; + + /* Write out the complete 32-bit chunks */ + while (count >= sizeof(uint32_t)) { + writel(*buf32, ARRIA10_FPGAMGRDATA_ADDR); + buf32++; + count -= sizeof(u32); + } + + /* Write out remaining non 32-bit chunks */ + if (count) { + const uint8_t *buf8 = (const uint8_t *)buf32; + uint32_t word = 0; + + while (count--) { + word |= *buf8; + word <<= 8; + buf8++; + } + + writel(word, ARRIA10_FPGAMGRDATA_ADDR); + } + + return 0; +} + +static int a10_fpga_write_complete(void) +{ + u32 reg; + int ret; + + /* Wait for condone */ + ret = a10_fpga_wait_for_condone(); + + /* Send some clocks to clear out any errors */ + a10_fpga_generate_dclks(256); + + /* Disable s2f dclk and data */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, 0); + + /* Deassert chip select */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE); + + /* Disable data, dclk, nce, and pr_request override to CSS */ + a10_update_bits(A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG); + + /* Return any errors regarding pr_done or pr_error */ + if (ret) + return ret; + + /* wait for fpga_usermode */ + a10_wait_for_usermode(0x1000000); + + /* Final check */ + reg = socfpga_a10_fpga_read_stat(); + + if (((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE) == 0) || + ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) == 0) || + ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)) + return -ETIMEDOUT; + + return 0; +} + +static struct partition bitstream; +static struct partition bootloader; + +int arria10_prepare_mmc(int barebox_part, int rbf_part) +{ + void *buf = (void *)0xffe00000 + SZ_256K - 128 - SECTOR_SIZE; + struct partition_entry *table; + uint32_t i; + int ret; + + arria10_init_mmc(); + + /* read partition table */ + ret = arria10_read_blocks(buf, 0x0, SECTOR_SIZE); + if (ret) + return ret; + + table = (struct partition_entry *)&buf[446]; + + for (i = 0; i < 4; i++) { + bootloader.type = get_unaligned_le32(&table[i].type); + if (bootloader.type == 0xa2) { + bootloader.first_sec = get_unaligned_le32(&table[i].partition_start); + break; + } + } + + bitstream.first_sec = get_unaligned_le32(&table[rbf_part].partition_start); + + return 0; +} + +int arria10_load_fpga(int offset, int bitstream_size) +{ + void *buf = (void *)0xffe00000 + SZ_256K - 256 - SZ_16K; + int ret; + uint32_t count; + uint32_t size = bitstream_size / SECTOR_SIZE; + + if (offset) + offset = offset / SECTOR_SIZE; + + count = offset; + + arria10_read_blocks(buf, count + bitstream.first_sec, SZ_16K); + + count += SZ_16K / SECTOR_SIZE; + + ret = a10_fpga_init(buf); + if (ret) + hang(); + + while (count <= size) { + ret = a10_fpga_write(buf, SZ_16K); + if (ret == -ENOSPC) + break; + count += SZ_16K / SECTOR_SIZE; + ret = arria10_read_blocks(buf, count, SZ_16K); + } + + ret = a10_fpga_write_complete(); + if (ret) + hang(); + + return 0; +} + +static int image_size(void) +{ + uint32_t *image_end = (void *)__image_end; + uint32_t payload_len; + uint32_t pbl_len; + uint32_t arria10_header_len; + uint32_t sizep; + uint32_t arria10_crc; + + /* arria10 header is 512 byte */ + arria10_header_len = 512; + /* pbl is appended with 4 byte CRC for boot rom */ + arria10_crc = 4; + + /* The length of the PBL image */ + pbl_len = __image_end - _text; + + sizep = 4; + + /* The length of the payload is appended directly behind the PBL */ + payload_len = *(image_end); + + return pbl_len + arria10_header_len + sizep + arria10_crc + payload_len; +} + +void arria10_start_image(int offset) +{ + void *buf = (void *)0x0; + void *in_buf = (void *)SZ_1M; + uint32_t start; + int size = 0; + int ret; + void __noreturn (*bb)(void); + uint32_t pbl_len = __image_end - _text; + uint32_t *image_end = (void *)__image_end; + uint32_t arria10_header_len; + uint32_t sizep; + uint32_t arria10_crc; + + size = image_size(); + + start = bootloader.first_sec + offset / SECTOR_SIZE; + + ret = arria10_read_blocks(buf, start, ALIGN(size, SECTOR_SIZE)); + if (ret) { + puts_ll("Loading image failed\n"); + hang(); + } + + /* arria10 header is 512 byte */ + arria10_header_len = 512; + sizep = 4; + + /* copy PBL */ + memcpy(in_buf, buf, pbl_len + sizep + arria10_header_len); + + /* pbl is appended with 4 byte CRC for boot rom */ + arria10_crc = 4; + + /* copy payload, skip the Arria10 CRC */ + memcpy(in_buf + pbl_len + sizep + arria10_header_len, + buf + pbl_len + sizep + arria10_header_len + arria10_crc, *(image_end)); + + bb = in_buf; + + bb(); + + hang(); +} diff --git a/arch/arm/mach-socfpga/include/mach/arria10-fpga.h b/arch/arm/mach-socfpga/include/mach/arria10-fpga.h new file mode 100644 index 0000000..0d957de --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/arria10-fpga.h @@ -0,0 +1,86 @@ +/* + * FPGA Manager Driver for Altera Arria10 SoCFPGA + * + * Copyright (C) 2015-2016 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + */ + +#ifndef __A10_FPGAMGR_H__ +#define __A10_FPGAMGR_H__ + +#include +#include + +#define A10_FPGAMGR_DCLKCNT_OFST 0x08 +#define A10_FPGAMGR_DCLKSTAT_OFST 0x0c +#define A10_FPGAMGR_IMGCFG_CTL_00_OFST 0x70 +#define A10_FPGAMGR_IMGCFG_CTL_01_OFST 0x74 +#define A10_FPGAMGR_IMGCFG_CTL_02_OFST 0x78 +#define A10_FPGAMGR_IMGCFG_STAT_OFST 0x80 + +#define A10_FPGAMGR_DCLKSTAT_DCLKDONE BIT(0) + +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG BIT(0) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS BIT(1) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE BIT(2) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG BIT(8) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE BIT(16) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE BIT(24) + +#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG BIT(0) +#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST BIT(16) +#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE BIT(24) + +#define A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL BIT(0) +#define A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_DATA BIT(8) +#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK (BIT(16) | BIT(17)) +#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT 16 +#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH BIT(24) +#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT 24 + +#define A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR BIT(0) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE BIT(1) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE BIT(2) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN BIT(4) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN BIT(6) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_OE BIT(7) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY BIT(9) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE BIT(10) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR BIT(11) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN BIT(12) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK (BIT(16) | BIT(17) | BIT(18)) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT 16 + +/* FPGA CD Ratio Value */ +#define CDRATIO_x1 0x0 +#define CDRATIO_x2 0x1 +#define CDRATIO_x4 0x2 +#define CDRATIO_x8 0x3 + +/* Configuration width 16/32 bit */ +#define CFGWDTH_32 1 +#define CFGWDTH_16 0 + +int inline a10_wait_for_usermode(int timeout) { + while ((readl(ARRIA10_FPGAMGRREGS_ADDR + + A10_FPGAMGR_IMGCFG_STAT_OFST) & + (A10_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE | + A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE)) == 0) + if (timeout-- <= 0) + return -ETIMEDOUT; + + return 0; +} + +#endif diff --git a/arch/arm/mach-socfpga/include/mach/arria10-regs.h b/arch/arm/mach-socfpga/include/mach/arria10-regs.h index 5569574..4464f06 100644 --- a/arch/arm/mach-socfpga/include/mach/arria10-regs.h +++ b/arch/arm/mach-socfpga/include/mach/arria10-regs.h @@ -43,7 +43,9 @@ #define ARRIA10_NOC_FW_SOC2FPGA_SOC2FPGA_SCR_ADDR (0xffd13500) #define ARRIA10_DMANONSECURE_ADDR (0xffda0000) #define ARRIA10_DMASECURE_ADDR (0xffda1000) +#define ARRIA10_OCRAM_ADDR (0xffe00000) #define ARRIA10_MPUSCU_ADDR (0xffffc000) +#define ARRIA10_SMP_TWD_ADDR (0xffffc600) #define ARRIA10_MPUL2_ADDR (0xfffff000) /* L2 cache controller */ diff --git a/arch/arm/mach-socfpga/include/mach/arria10-system-manager.h b/arch/arm/mach-socfpga/include/mach/arria10-system-manager.h index f98cc36..9117a93 100644 --- a/arch/arm/mach-socfpga/include/mach/arria10-system-manager.h +++ b/arch/arm/mach-socfpga/include/mach/arria10-system-manager.h @@ -52,6 +52,12 @@ #define ARRIA10_SYSMGR_NOC_IDLESTATUS (ARRIA10_SYSMGR_ADDR + 0xd4) #define ARRIA10_SYSMGR_FPGA2SOC_CTRL (ARRIA10_SYSMGR_ADDR + 0xd8) +#define ARRIA10_SYSMGR_ROM_INITSWLASTLD (ARRIA10_SYSMGR_ADDR + 0x10) + + +#define ARRIA10_SYSMGR_BOOTINFO_BSEL_MASK 0x00007000 +#define ARRIA10_SYSMGR_BOOTINFO_BSEL_SHIFT 12 + /* pin mux */ #define ARRIA10_SYSMGR_PINMUXGRP (ARRIA10_SYSMGR_ADDR + 0x400) #define ARRIA10_SYSMGR_PINMUXGRP_NANDUSEFPGA (ARRIA10_SYSMGR_PINMUXGRP + 0x2F0) diff --git a/arch/arm/mach-socfpga/include/mach/arria10-xload.h b/arch/arm/mach-socfpga/include/mach/arria10-xload.h new file mode 100644 index 0000000..71f8397 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/arria10-xload.h @@ -0,0 +1,13 @@ +#ifndef __MACH_ARRIA10_XLOAD_H +#define __MACH_ARRIA10_XLOAD_H + +void arria10_init_mmc(void); +int arria10_prepare_mmc(int barebox_part, int rbf_part); +int arria10_read_blocks(void *dst, int blocknum, size_t len); + +struct partition { + uint64_t first_sec; + uint8_t type; +}; + +#endif /* __MACH_ARRIA10_XLOAD_H */ diff --git a/arch/arm/mach-socfpga/include/mach/debug_ll.h b/arch/arm/mach-socfpga/include/mach/debug_ll.h index f41258c..3264934 100644 --- a/arch/arm/mach-socfpga/include/mach/debug_ll.h +++ b/arch/arm/mach-socfpga/include/mach/debug_ll.h @@ -40,8 +40,6 @@ unsigned int div = ns16550_calc_divisor(CONFIG_DEBUG_SOCFPGA_UART_CLOCK, 115200); - while ((readl(UART_BASE + LSR) & LSR_TEMT) == 0); - writel(0x00, UART_BASE + IER); writel(LCR_BKSE, UART_BASE + LCR); diff --git a/arch/arm/mach-socfpga/include/mach/generic.h b/arch/arm/mach-socfpga/include/mach/generic.h index 9d6dd1f..72391f3 100644 --- a/arch/arm/mach-socfpga/include/mach/generic.h +++ b/arch/arm/mach-socfpga/include/mach/generic.h @@ -13,6 +13,8 @@ void arria10_init(struct arria10_mainpll_cfg *mainpll, struct arria10_perpll_cfg *perpll, uint32_t *pinmux); +void arria10_finish_io(struct arria10_mainpll_cfg *mainpll, + struct arria10_perpll_cfg *perpll, uint32_t *pinmux); void socfpga_lowlevel_init(struct socfpga_cm_config *cm_config, struct socfpga_io_config *io_config); @@ -43,6 +45,45 @@ return; } #endif +#if defined(CONFIG_ARCH_SOCFPGA_ARRIA10) +void socfpga_arria10_mmc_init(void); +void socfpga_arria10_timer_init(void); +int arria10_prepare_mmc(int barebox, int bitstream); +void arria10_start_image(int offset); +int arria10_load_fpga(int offset, int size); +int arria10_device_init(struct arria10_mainpll_cfg *mainpll, + struct arria10_perpll_cfg *perpll, + uint32_t *pinmux); +enum bootsource arria10_get_bootsource(void); +#else +static inline void socfpga_arria10_mmc_init(void) +{ + return; +} + +static inline void socfpga_arria10_timer_init(void) +{ + return; +} +static void arria10_prepare_mmc(int barebox, int bitstream) +{ + return; +} +static void arria10_start_image(int offset) +{ + return; +} +static int arria10_load_fpga(int offset, int size) +{ + return; +} +static int arria10_device_init(struct arria10_mainpll_cfg *mainpll, + struct arria10_perpll_cfg *perpll, + uint32_t *pinmux) +{ + return 0; +} +#endif static inline void __udelay(unsigned us) { diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c index 27c36a6..e4c550c 100644 --- a/drivers/mci/dw_mmc.c +++ b/drivers/mci/dw_mmc.c @@ -26,128 +26,15 @@ #include #include #include +#include #include #include #include +#include "dw_mmc.h" -#define DWMCI_CTRL 0x000 -#define DWMCI_PWREN 0x004 -#define DWMCI_CLKDIV 0x008 -#define DWMCI_CLKSRC 0x00C -#define DWMCI_CLKENA 0x010 -#define DWMCI_TMOUT 0x014 -#define DWMCI_CTYPE 0x018 -#define DWMCI_BLKSIZ 0x01C -#define DWMCI_BYTCNT 0x020 -#define DWMCI_INTMASK 0x024 -#define DWMCI_CMDARG 0x028 -#define DWMCI_CMD 0x02C -#define DWMCI_RESP0 0x030 -#define DWMCI_RESP1 0x034 -#define DWMCI_RESP2 0x038 -#define DWMCI_RESP3 0x03C -#define DWMCI_MINTSTS 0x040 -#define DWMCI_RINTSTS 0x044 -#define DWMCI_STATUS 0x048 -#define DWMCI_FIFOTH 0x04C -#define DWMCI_CDETECT 0x050 -#define DWMCI_WRTPRT 0x054 -#define DWMCI_GPIO 0x058 -#define DWMCI_TCMCNT 0x05C -#define DWMCI_TBBCNT 0x060 -#define DWMCI_DEBNCE 0x064 -#define DWMCI_USRID 0x068 -#define DWMCI_VERID 0x06C -#define DWMCI_HCON 0x070 -#define DWMCI_UHS_REG 0x074 -#define DWMCI_BMOD 0x080 -#define DWMCI_PLDMND 0x084 -#define DWMCI_DBADDR 0x088 -#define DWMCI_IDSTS 0x08C -#define DWMCI_IDINTEN 0x090 -#define DWMCI_DSCADDR 0x094 -#define DWMCI_BUFADDR 0x098 -#define DWMCI_DATA 0x200 - -/* Interrupt Mask register */ -#define DWMCI_INTMSK_ALL 0xffffffff -#define DWMCI_INTMSK_RE (1 << 1) -#define DWMCI_INTMSK_CDONE (1 << 2) -#define DWMCI_INTMSK_DTO (1 << 3) -#define DWMCI_INTMSK_TXDR (1 << 4) -#define DWMCI_INTMSK_RXDR (1 << 5) -#define DWMCI_INTMSK_RCRC (1 << 6) -#define DWMCI_INTMSK_DCRC (1 << 7) -#define DWMCI_INTMSK_RTO (1 << 8) -#define DWMCI_INTMSK_DRTO (1 << 9) -#define DWMCI_INTMSK_HTO (1 << 10) -#define DWMCI_INTMSK_FRUN (1 << 11) -#define DWMCI_INTMSK_HLE (1 << 12) -#define DWMCI_INTMSK_SBE (1 << 13) -#define DWMCI_INTMSK_ACD (1 << 14) -#define DWMCI_INTMSK_EBE (1 << 15) - -/* Raw interrupt Register */ -#define DWMCI_DATA_ERR (DWMCI_INTMSK_EBE | DWMCI_INTMSK_SBE | DWMCI_INTMSK_HLE |\ - DWMCI_INTMSK_FRUN | DWMCI_INTMSK_DCRC) -#define DWMCI_DATA_TOUT (DWMCI_INTMSK_HTO | DWMCI_INTMSK_DRTO) - -/* CTRL register */ -#define DWMCI_CTRL_RESET (1 << 0) -#define DWMCI_CTRL_FIFO_RESET (1 << 1) -#define DWMCI_CTRL_DMA_RESET (1 << 2) -#define DWMCI_DMA_EN (1 << 5) -#define DWMCI_CTRL_SEND_AS_CCSD (1 << 10) -#define DWMCI_IDMAC_EN (1 << 25) -#define DWMCI_RESET_ALL (DWMCI_CTRL_RESET | DWMCI_CTRL_FIFO_RESET |\ - DWMCI_CTRL_DMA_RESET) - -/* CMD register */ -#define DWMCI_CMD_RESP_EXP (1 << 6) -#define DWMCI_CMD_RESP_LENGTH (1 << 7) -#define DWMCI_CMD_CHECK_CRC (1 << 8) -#define DWMCI_CMD_DATA_EXP (1 << 9) -#define DWMCI_CMD_RW (1 << 10) -#define DWMCI_CMD_SEND_STOP (1 << 12) -#define DWMCI_CMD_ABORT_STOP (1 << 14) -#define DWMCI_CMD_PRV_DAT_WAIT (1 << 13) -#define DWMCI_CMD_UPD_CLK (1 << 21) -#define DWMCI_CMD_USE_HOLD_REG (1 << 29) -#define DWMCI_CMD_START (1 << 31) - -/* CLKENA register */ -#define DWMCI_CLKEN_ENABLE (1 << 0) -#define DWMCI_CLKEN_LOW_PWR (1 << 16) - -/* Card-type register */ -#define DWMCI_CTYPE_1BIT 0 -#define DWMCI_CTYPE_4BIT (1 << 0) -#define DWMCI_CTYPE_8BIT (1 << 16) - -/* Status Register */ -#define DWMCI_STATUS_FIFO_EMPTY (1 << 2) -#define DWMCI_STATUS_FIFO_FULL (1 << 3) -#define DWMCI_STATUS_BUSY (1 << 9) - -/* FIFOTH Register */ -#define DWMCI_FIFOTH_MSIZE(x) ((x) << 28) -#define DWMCI_FIFOTH_RX_WMARK(x) ((x) << 16) -#define DWMCI_FIFOTH_TX_WMARK(x) (x) -#define DWMCI_FIFOTH_FIFO_DEPTH(x) ((((x) >> 16) & 0x3ff) + 1) - -#define DWMCI_IDMAC_OWN (1 << 31) -#define DWMCI_IDMAC_CH (1 << 4) -#define DWMCI_IDMAC_FS (1 << 3) -#define DWMCI_IDMAC_LD (1 << 2) - -/* Bus Mode Register */ -#define DWMCI_BMOD_IDMAC_RESET (1 << 0) -#define DWMCI_BMOD_IDMAC_FB (1 << 1) -#define DWMCI_BMOD_IDMAC_EN (1 << 7) struct dwmci_host { struct mci_host mci; - struct device_d *dev; struct clk *clk_biu, *clk_ciu; void *ioaddr; unsigned int fifo_size_bytes; @@ -271,7 +158,7 @@ desc->addr = start_addr + (i * PAGE_SIZE); desc->next_addr = (uint32_t)(desc + 1); - dev_dbg(host->dev, "desc@ 0x%p 0x%08x 0x%08x 0x%08x 0x%08x\n", + dev_dbg(host->mci.hw_dev, "desc@ 0x%p 0x%08x 0x%08x 0x%08x 0x%08x\n", desc, flags, cnt, desc->addr, desc->next_addr); if (blk_cnt < 8) break; @@ -331,7 +218,7 @@ status = dwmci_readl(host, DWMCI_STATUS); } if (!timeout) { - dev_err(host->dev, "%s: FIFO underflow timeout\n", + dev_err(host->mci.hw_dev, "%s: FIFO underflow timeout\n", __func__); break; } @@ -360,7 +247,7 @@ status = dwmci_readl(host, DWMCI_STATUS); } if (!timeout) { - dev_err(host->dev, "%s: FIFO overflow timeout\n", + dev_err(host->mci.hw_dev, "%s: FIFO overflow timeout\n", __func__); break; } @@ -378,7 +265,7 @@ status = dwmci_readl(host, DWMCI_STATUS); } if (!timeout) { - dev_err(host->dev, "%s: FIFO flush timeout\n", + dev_err(host->mci.hw_dev, "%s: FIFO flush timeout\n", __func__); return -EIO; } @@ -403,7 +290,7 @@ break; if (is_timeout(start, 100 * MSECOND)) { - dev_dbg(host->dev, "Timeout on data busy\n"); + dev_dbg(host->mci.hw_dev, "Timeout on data busy\n"); return -ETIMEDOUT; } } @@ -449,7 +336,7 @@ flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG); - dev_dbg(host->dev, "Sending CMD%d\n", cmd->cmdidx); + dev_dbg(host->mci.hw_dev, "Sending CMD%d\n", cmd->cmdidx); dwmci_writel(host, DWMCI_CMD, flags); @@ -462,16 +349,16 @@ break; } if (is_timeout(start, 100 * MSECOND)) { - dev_dbg(host->dev, "Send command timeout..\n"); + dev_dbg(host->mci.hw_dev, "Send command timeout..\n"); return -ETIMEDOUT; } } if (mask & DWMCI_INTMSK_RTO) { - dev_dbg(host->dev, "Response Timeout..\n"); + dev_dbg(host->mci.hw_dev, "Response Timeout..\n"); return -ETIMEDOUT; } else if (mask & DWMCI_INTMSK_RE) { - dev_dbg(host->dev, "Response Error..\n"); + dev_dbg(host->mci.hw_dev, "Response Error..\n"); return -EIO; } @@ -492,17 +379,17 @@ mask = dwmci_readl(host, DWMCI_RINTSTS); if (mask & (DWMCI_DATA_ERR)) { - dev_dbg(host->dev, "DATA ERROR!\n"); + dev_dbg(host->mci.hw_dev, "DATA ERROR!\n"); return -EIO; } if (!dwmci_use_pio(host) && (mask & DWMCI_DATA_TOUT)) { - dev_dbg(host->dev, "DATA TIMEOUT!\n"); + dev_dbg(host->mci.hw_dev, "DATA TIMEOUT!\n"); return -EIO; } if (is_timeout(start, SECOND * 10)) { - dev_dbg(host->dev, "Data timeout\n"); + dev_dbg(host->mci.hw_dev, "Data timeout\n"); return -ETIMEDOUT; } @@ -552,7 +439,7 @@ return 0; if (is_timeout(start, 100 * MSECOND)) { - dev_err(host->dev, "TIMEOUT error!!\n"); + dev_err(host->mci.hw_dev, "TIMEOUT error!!\n"); return -ETIMEDOUT; } } @@ -590,7 +477,7 @@ struct dwmci_host *host = to_dwmci_host(mci); uint32_t ctype; - dev_dbg(host->dev, "Buswidth = %d, clock: %d\n", ios->bus_width, ios->clock); + dev_dbg(host->mci.hw_dev, "Buswidth = %d, clock: %d\n", ios->bus_width, ios->clock); if (ios->clock) dwmci_setup_bus(host, ios->clock); @@ -623,7 +510,7 @@ dwmci_writel(host, DWMCI_PWREN, host->pwren_value); if (dwmci_wait_reset(host, DWMCI_RESET_ALL)) { - dev_err(host->dev, "reset failed\n"); + dev_err(host->mci.hw_dev, "reset failed\n"); return -EIO; } @@ -647,10 +534,10 @@ /* * If fifo-depth property is set, use this value */ - if (!of_property_read_u32(host->dev->device_node, + if (!of_property_read_u32(host->mci.hw_dev->device_node, "fifo-depth", &fifo_size)) { host->fifo_size_bytes = fifo_size; - dev_dbg(host->dev, "Using fifo-depth=%u\n", + dev_dbg(host->mci.hw_dev, "Using fifo-depth=%u\n", host->fifo_size_bytes); } @@ -692,7 +579,6 @@ clk_enable(host->clk_biu); clk_enable(host->clk_ciu); - host->dev = dev; iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); diff --git a/drivers/mci/dw_mmc.h b/drivers/mci/dw_mmc.h new file mode 100644 index 0000000..23b0f0f --- /dev/null +++ b/drivers/mci/dw_mmc.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2013 Altera Corporation + * + * (C) Copyright 2012 SAMSUNG Electronics + * Jaehoon Chung + * Rajeshawari Shinde + * + * 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. + * + */ + +#ifndef __DW_MMC_H__ +#define __DW_MMC_H__ + +#include + +#define DWMCI_CTRL 0x000 +#define DWMCI_PWREN 0x004 +#define DWMCI_CLKDIV 0x008 +#define DWMCI_CLKSRC 0x00C +#define DWMCI_CLKENA 0x010 +#define DWMCI_TMOUT 0x014 +#define DWMCI_CTYPE 0x018 +#define DWMCI_BLKSIZ 0x01C +#define DWMCI_BYTCNT 0x020 +#define DWMCI_INTMASK 0x024 +#define DWMCI_CMDARG 0x028 +#define DWMCI_CMD 0x02C +#define DWMCI_RESP0 0x030 +#define DWMCI_RESP1 0x034 +#define DWMCI_RESP2 0x038 +#define DWMCI_RESP3 0x03C +#define DWMCI_MINTSTS 0x040 +#define DWMCI_RINTSTS 0x044 +#define DWMCI_STATUS 0x048 +#define DWMCI_FIFOTH 0x04C +#define DWMCI_CDETECT 0x050 +#define DWMCI_WRTPRT 0x054 +#define DWMCI_GPIO 0x058 +#define DWMCI_TCMCNT 0x05C +#define DWMCI_TBBCNT 0x060 +#define DWMCI_DEBNCE 0x064 +#define DWMCI_USRID 0x068 +#define DWMCI_VERID 0x06C +#define DWMCI_HCON 0x070 +#define DWMCI_UHS_REG 0x074 +#define DWMCI_BMOD 0x080 +#define DWMCI_PLDMND 0x084 +#define DWMCI_DBADDR 0x088 +#define DWMCI_IDSTS 0x08C +#define DWMCI_IDINTEN 0x090 +#define DWMCI_DSCADDR 0x094 +#define DWMCI_BUFADDR 0x098 +#define DWMCI_DATA 0x200 + +/* Interrupt Mask register */ +#define DWMCI_INTMSK_ALL 0xffffffff +#define DWMCI_INTMSK_RE BIT(1) +#define DWMCI_INTMSK_CDONE BIT(2) +#define DWMCI_INTMSK_DTO BIT(3) +#define DWMCI_INTMSK_TXDR BIT(4) +#define DWMCI_INTMSK_RXDR BIT(5) +#define DWMCI_INTMSK_RCRC BIT(6) +#define DWMCI_INTMSK_DCRC BIT(7) +#define DWMCI_INTMSK_RTO BIT(8) +#define DWMCI_INTMSK_DRTO BIT(9) +#define DWMCI_INTMSK_HTO BIT(10) +#define DWMCI_INTMSK_FRUN BIT(11) +#define DWMCI_INTMSK_HLE BIT(12) +#define DWMCI_INTMSK_SBE BIT(13) +#define DWMCI_INTMSK_ACD BIT(14) +#define DWMCI_INTMSK_EBE BIT(15) + +/* Raw interrupt Register */ +#define DWMCI_DATA_ERR (DWMCI_INTMSK_EBE | DWMCI_INTMSK_SBE | DWMCI_INTMSK_HLE |\ + DWMCI_INTMSK_FRUN | DWMCI_INTMSK_DCRC) +#define DWMCI_DATA_TOUT (DWMCI_INTMSK_HTO | DWMCI_INTMSK_DRTO) + +/* CTRL register */ +#define DWMCI_CTRL_RESET BIT(0) +#define DWMCI_CTRL_FIFO_RESET BIT(1) +#define DWMCI_CTRL_DMA_RESET BIT(2) +#define DWMCI_DMA_EN BIT(5) +#define DWMCI_CTRL_SEND_AS_CCSD BIT(10) +#define DWMCI_IDMAC_EN BIT(25) +#define DWMCI_RESET_ALL (DWMCI_CTRL_RESET | DWMCI_CTRL_FIFO_RESET | \ + DWMCI_CTRL_DMA_RESET) + +/* CMD register */ +#define DWMCI_CMD_RESP_EXP BIT(6) +#define DWMCI_CMD_RESP_LENGTH BIT(7) +#define DWMCI_CMD_CHECK_CRC BIT(8) +#define DWMCI_CMD_DATA_EXP BIT(9) +#define DWMCI_CMD_RW BIT(10) +#define DWMCI_CMD_SEND_STOP BIT(12) +#define DWMCI_CMD_ABORT_STOP BIT(14) +#define DWMCI_CMD_PRV_DAT_WAIT BIT(13) +#define DWMCI_CMD_UPD_CLK BIT(21) +#define DWMCI_CMD_USE_HOLD_REG BIT(29) +#define DWMCI_CMD_START BIT(31) + +/* CLKENA register */ +#define DWMCI_CLKEN_ENABLE BIT(0) +#define DWMCI_CLKEN_LOW_PWR BIT(16) + +/* Card-type register */ +#define DWMCI_CTYPE_1BIT 0 +#define DWMCI_CTYPE_4BIT BIT(0) +#define DWMCI_CTYPE_8BIT BIT(16) + +/* Status Register */ +#define DWMCI_STATUS_FIFO_EMPTY BIT(2) +#define DWMCI_STATUS_FIFO_FULL BIT(3) +#define DWMCI_STATUS_BUSY BIT(9) + +/* FIFOTH Register */ +#define DWMCI_FIFOTH_MSIZE(x) ((x) << 28) +#define DWMCI_FIFOTH_RX_WMARK(x) ((x) << 16) +#define DWMCI_FIFOTH_TX_WMARK(x) (x) +#define DWMCI_FIFOTH_FIFO_DEPTH(x) ((((x) >> 16) & 0x3ff) + 1) + +#define DWMCI_IDMAC_OWN BIT(31) +#define DWMCI_IDMAC_CH BIT(4) +#define DWMCI_IDMAC_FS BIT(3) +#define DWMCI_IDMAC_LD BIT(2) + +/* Bus Mode Register */ +#define DWMCI_BMOD_IDMAC_RESET BIT(0) +#define DWMCI_BMOD_IDMAC_FB BIT(1) +#define DWMCI_BMOD_IDMAC_EN BIT(7) + +#endif diff --git a/images/Makefile.socfpga b/images/Makefile.socfpga index 60b98d1..a075b36 100644 --- a/images/Makefile.socfpga +++ b/images/Makefile.socfpga @@ -13,6 +13,17 @@ $(obj)/%.socfpgaimg: $(obj)/% FORCE $(call if_changed,socfpga_image) +ocram-tmp = $(subst $(comma),_,$(dot-target).ocram.tmp) + +quiet_cmd_socfpga_ocram_img ?= SOCFPGA-OCRAM-IMG $@ + cmd_socfpga_ocram_img ?= cat $(obj)/$(patsubst %.socfpga-ocram-img,%.pblb,$(2)) > $(ocram-tmp); \ + $(call size_append, $(obj)/barebox.z) >> $(ocram-tmp); \ + $(objtree)/scripts/socfpga_mkimage -v1 -b -s -o $@ $(ocram-tmp); \ + cat $(obj)/barebox.z >> $@ + +$(obj)/%.socfpga-ocram-img: $(obj)/%.pblb $(obj)/barebox.z FORCE + $(call if_changed,socfpga_ocram_img,$(@F)) + # ----------------------- Cyclone5 based boards --------------------------- pblx-$(CONFIG_MACH_SOCFPGA_ALTERA_SOCDK) += start_socfpga_socdk_xload FILE_barebox-socfpga-socdk-xload.img = start_socfpga_socdk_xload.pblx.socfpgaimg @@ -31,9 +42,13 @@ socfpga-barebox-$(CONFIG_MACH_SOCFPGA_TERASIC_DE0_NANO_SOC) += barebox-socfpga-de0_nano_soc.img pblx-$(CONFIG_MACH_SOCFPGA_REFLEX_ACHILLES) += start_socfpga_achilles -FILE_barebox-socfpga-achilles.img = start_socfpga_achilles.pblx.socfpgaimg +FILE_barebox-socfpga-achilles.img = start_socfpga_achilles.socfpga-ocram-img socfpga-barebox-$(CONFIG_MACH_SOCFPGA_REFLEX_ACHILLES) += barebox-socfpga-achilles.img +pblx-$(CONFIG_MACH_SOCFPGA_REFLEX_ACHILLES) += start_socfpga_achilles_bringup +FILE_barebox-socfpga-achilles-bringup.img = start_socfpga_achilles_bringup.pblx +socfpga-barebox-$(CONFIG_MACH_SOCFPGA_REFLEX_ACHILLES) += barebox-socfpga-achilles-bringup.img + pblx-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += start_socfpga_sockit_xload FILE_barebox-socfpga-sockit-xload.img = start_socfpga_sockit_xload.pblx.socfpgaimg socfpga-xload-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += barebox-socfpga-sockit-xload.img diff --git a/scripts/socfpga_mkimage.c b/scripts/socfpga_mkimage.c index d7fe1b1..fedcfb5 100644 --- a/scripts/socfpga_mkimage.c +++ b/scripts/socfpga_mkimage.c @@ -256,7 +256,7 @@ static void usage(const char *prgname) { - fprintf(stderr, "usage: %s [-hb] [-v version] -o \n", prgname); + fprintf(stderr, "usage: %s [-hbs] [-v version] -o \n", prgname); } int main(int argc, char *argv[]) @@ -268,9 +268,11 @@ int fd; int max_image_size, min_image_size = 80; int addsize = 0, pad; + int fixup_size = 0; unsigned int version = 0; + int fixed_size = 0; - while ((opt = getopt(argc, argv, "o:hbv:")) != -1) { + while ((opt = getopt(argc, argv, "o:hbsv:")) != -1) { switch (opt) { case 'v': version = atoi(optarg); @@ -285,6 +287,9 @@ min_image_size = 0; addsize = 512; break; + case 's': + fixup_size = 1; + break; case 'h': usage(argv[0]); exit(0); @@ -349,10 +354,26 @@ exit(1); } + fixed_size = s.st_size; + close(fd); if (add_barebox_header) { + int barebox_size = 0; + int *image_size = buf + 0x2c; + memcpy(buf, bb_header, sizeof(bb_header)); + + if (fixup_size) { + fixed_size = htole32(fixed_size); + + barebox_size = *((uint32_t *)buf + (fixed_size + addsize + pad) / 4 - 1); + + /* size of barebox+pbl, header, size */ + fixed_size += (barebox_size + addsize + 4); + + *image_size = fixed_size; + } } ret = add_socfpga_header(buf, s.st_size + 4 + addsize + pad, addsize,