summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-08-13 16:56:05 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2018-08-13 16:56:05 +0200
commit1ec421f533610f7af4544748300296fe7728ed70 (patch)
treed70b6e63ff3d087ac30ed68a87c5199b1f568715
parent64842a68070318c4c78e99bd69de2401e65de7a5 (diff)
parent2b8466c26a911bed1ac5aa25c463f67b3bdbf1eb (diff)
downloadbarebox-1ec421f533610f7af4544748300296fe7728ed70.tar.gz
barebox-1ec421f533610f7af4544748300296fe7728ed70.tar.xz
Merge branch 'for-next/socfpga'
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/boards/reflex-achilles/Makefile4
-rw-r--r--arch/arm/boards/reflex-achilles/board.c19
-rw-r--r--arch/arm/boards/reflex-achilles/lowlevel.c87
-rw-r--r--arch/arm/boards/reflex-achilles/pinmux-config-arria10.c2
-rw-r--r--arch/arm/boards/reflex-achilles/pll-config-arria10.c16
-rw-r--r--arch/arm/configs/socfpga-arria10_defconfig7
-rw-r--r--arch/arm/dts/socfpga_arria10_achilles.dts14
-rw-r--r--arch/arm/lib32/bootm.c7
-rw-r--r--arch/arm/mach-socfpga/Kconfig9
-rw-r--r--arch/arm/mach-socfpga/Makefile12
-rw-r--r--arch/arm/mach-socfpga/arria10-bootsource.c16
-rw-r--r--arch/arm/mach-socfpga/arria10-generic.c2
-rw-r--r--arch/arm/mach-socfpga/arria10-init.c47
-rw-r--r--arch/arm/mach-socfpga/arria10-reset-manager.c33
-rw-r--r--arch/arm/mach-socfpga/arria10-sdram.c2
-rw-r--r--arch/arm/mach-socfpga/arria10-xload-emmc.c222
-rw-r--r--arch/arm/mach-socfpga/arria10-xload.c457
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-fpga.h86
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-regs.h2
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-system-manager.h6
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-xload.h13
-rw-r--r--arch/arm/mach-socfpga/include/mach/debug_ll.h2
-rw-r--r--arch/arm/mach-socfpga/include/mach/generic.h41
-rw-r--r--drivers/mci/dw_mmc.c152
-rw-r--r--drivers/mci/dw_mmc.h140
-rw-r--r--images/Makefile.socfpga17
-rw-r--r--scripts/socfpga_mkimage.c25
28 files changed, 1236 insertions, 208 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 00c893bd0..3b486f7b8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -179,10 +179,6 @@ config ARCH_SOCFPGA
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 6b4214115..092c31d6b 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 000000000..29011ba57
--- /dev/null
+++ b/arch/arm/boards/reflex-achilles/board.c
@@ -0,0 +1,19 @@
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <bbu.h>
+
+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 25e7ad0f1..2265aa882 100644
--- a/arch/arm/boards/reflex-achilles/lowlevel.c
+++ b/arch/arm/boards/reflex-achilles/lowlevel.c
@@ -1,24 +1,39 @@
#include <common.h>
#include <linux/sizes.h>
#include <io.h>
-#include <asm/barebox-arm-head.h>
+#include <memory.h>
#include <asm/barebox-arm.h>
#include <asm/cache.h>
+#include <asm/sections.h>
+#include <asm/unaligned.h>
#include <debug_ll.h>
+#include <pbl.h>
#include <mach/arria10-sdram.h>
#include <mach/arria10-regs.h>
#include <mach/arria10-reset-manager.h>
#include <mach/arria10-clock-manager.h>
#include <mach/arria10-pinmux.h>
+#include <mach/arria10-fpga.h>
#include "pll-config-arria10.c"
#include "pinmux-config-arria10.c"
#include <mach/generic.h>
+#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 @@ static noinline void achilles_entry(void)
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);
+
+ arm_early_mmu_cache_invalidate();
+
+ relocate_to_current_adr();
+ setup_c();
+
+ arria10_init(&mainpll_cfg, &perpll_cfg, pinmux);
- achilles_entry();
+ /* 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 246838a22..b6a72304b 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 @@ static uint32_t pinmux[] = {
[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 94d596606..9da41ecdf 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 @@ static struct arria10_mainpll_cfg mainpll_cfg = {
.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 @@ static struct arria10_mainpll_cfg mainpll_cfg = {
.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 @@ static struct arria10_perpll_cfg perpll_cfg = {
.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 e661895d6..53e932d64 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_SHOW_TYPE=y
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_MM=y
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_DRIVERS=y
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 059a92c41..c03982ef5 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 63713acf5..4cf570e57 100644
--- a/arch/arm/lib32/bootm.c
+++ b/arch/arm/lib32/bootm.c
@@ -434,6 +434,12 @@ static struct image_handler barebox_handler = {
.filetype = filetype_arm_barebox,
};
+static struct image_handler socfpga_xload_handler = {
+ .name = "SoCFPGA prebootloader image",
+ .bootm = do_bootm_linux,
+ .filetype = filetype_socfpga_xload,
+};
+
#include <aimage.h>
static int aimage_load_resource(int fd, struct resource *r, void* buf, int ps)
@@ -628,6 +634,7 @@ static int armlinux_register_image_handler(void)
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 58e4876f5..65097b676 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -11,17 +11,24 @@ config ARCH_SOCFPGA_XLOAD
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 cbb47fa20..3a3a2fc57 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -2,7 +2,15 @@ pbl-$(CONFIG_ARCH_SOCFPGA_CYCLONE5) += cyclone5-init.o cyclone5-freeze-controlle
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 26af64a1a..3319dc4bf 100644
--- a/arch/arm/mach-socfpga/arria10-bootsource.c
+++ b/arch/arm/mach-socfpga/arria10-bootsource.c
@@ -15,16 +15,17 @@
#include <bootsource.h>
#include <init.h>
#include <io.h>
+#include <mach/generic.h>
#include <mach/arria10-system-manager.h>
-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 @@ static int arria10_boot_save_loc(void)
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 6a10c19d1..53ec27873 100644
--- a/arch/arm/mach-socfpga/arria10-generic.c
+++ b/arch/arm/mach-socfpga/arria10-generic.c
@@ -63,7 +63,7 @@ static int arria10_generic_init(void)
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 f016b84bb..2fa44c21c 100644
--- a/arch/arm/mach-socfpga/arria10-init.c
+++ b/arch/arm/mach-socfpga/arria10-init.c
@@ -127,6 +127,32 @@ static void arria10_mask_ecc_errors(void)
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 @@ void arria10_init(struct arria10_mainpll_cfg *mainpll,
/* 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 a7e4bd603..76adc1702 100644
--- a/arch/arm/mach-socfpga/arria10-reset-manager.c
+++ b/arch/arm/mach-socfpga/arria10-reset-manager.c
@@ -5,8 +5,10 @@
*/
#include <common.h>
+#include <bootsource.h>
#include <errno.h>
#include <io.h>
+#include <mach/generic.h>
#include <mach/arria10-pinmux.h>
#include <mach/arria10-regs.h>
#include <mach/arria10-reset-manager.h>
@@ -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;
+
+ src = arria10_get_bootsource();
+ if (src == BOOTSOURCE_MMC) {
+ mask |= ARRIA10_RSTMGR_PER0MODRST_SDMMC;
+ mask |= ARRIA10_RSTMGR_PER0MODRST_SDMMCOCP;
+ }
- /* disable all components except ECC_OCP, L4 Timer0 and L4 WD0 */
+ /* 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 @@ void arria10_reset_deassert_dedicated_peripherals(void)
/* 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 08de0e32c..35c355df7 100644
--- a/arch/arm/mach-socfpga/arria10-sdram.c
+++ b/arch/arm/mach-socfpga/arria10-sdram.c
@@ -531,5 +531,7 @@ int arria10_ddr_calibration_sequence(void)
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 000000000..dcc38cf4a
--- /dev/null
+++ b/arch/arm/mach-socfpga/arria10-xload-emmc.c
@@ -0,0 +1,222 @@
+#include <common.h>
+#include <init.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <mach/arria10-regs.h>
+#include <mach/arria10-system-manager.h>
+#include <mach/arria10-xload.h>
+#include <mci.h>
+#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 000000000..f665ba474
--- /dev/null
+++ b/arch/arm/mach-socfpga/arria10-xload.c
@@ -0,0 +1,457 @@
+#include <common.h>
+#include <asm/sections.h>
+#include <debug_ll.h>
+#include <disks.h>
+#include <init.h>
+#include <filetype.h>
+#include <io.h>
+#include <asm/unaligned.h>
+#include <mach/arria10-pinmux.h>
+#include <mach/arria10-regs.h>
+#include <mach/arria10-system-manager.h>
+#include <mach/arria10-fpga.h>
+#include <mach/arria10-xload.h>
+#include <mach/generic.h>
+#include <linux/sizes.h>
+
+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 000000000..0d957dedc
--- /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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __A10_FPGAMGR_H__
+#define __A10_FPGAMGR_H__
+
+#include <linux/bitops.h>
+#include <mach/arria10-regs.h>
+
+#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 5569574e1..4464f0623 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 f98cc36c7..9117a93b1 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 000000000..71f839736
--- /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 f41258c50..3264934e6 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 @@ static inline void INIT_LL(void)
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 9d6dd1f26..72391f355 100644
--- a/arch/arm/mach-socfpga/include/mach/generic.h
+++ b/arch/arm/mach-socfpga/include/mach/generic.h
@@ -13,6 +13,8 @@ struct arria10_pinmux_cfg;
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 @@ static inline void socfpga_cyclone5_qspi_init(void)
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 27c36a637..e4c550c3e 100644
--- a/drivers/mci/dw_mmc.c
+++ b/drivers/mci/dw_mmc.c
@@ -26,128 +26,15 @@
#include <mci.h>
#include <io.h>
#include <platform_data/dw_mmc.h>
+#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm-generic/errno.h>
+#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 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host,
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 @@ static int dwmci_read_data_pio(struct dwmci_host *host, struct mci_data *data)
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 @@ static int dwmci_write_data_pio(struct dwmci_host *host, struct mci_data *data)
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 @@ static int dwmci_write_data_pio(struct dwmci_host *host, struct mci_data *data)
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 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
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 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
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 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
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 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
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 @@ static int dwmci_send_cmd(struct dwmci_host *host, u32 cmd, u32 arg)
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 @@ static void dwmci_set_ios(struct mci_host *mci, struct mci_ios *ios)
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 @@ static int dwmci_init(struct mci_host *mci, struct device_d *dev)
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 @@ static int dwmci_init(struct mci_host *mci, struct device_d *dev)
/*
* 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 @@ static int dw_mmc_probe(struct device_d *dev)
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 000000000..23b0f0fe2
--- /dev/null
+++ b/drivers/mci/dw_mmc.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 Altera Corporation <www.altera.com>
+ *
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ * Rajeshawari Shinde <rajeshwari.s@samsung.com>
+ *
+ * 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 <linux/bitops.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 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 60b98d1ef..a075b3670 100644
--- a/images/Makefile.socfpga
+++ b/images/Makefile.socfpga
@@ -13,6 +13,17 @@ quiet_cmd_socfpga_image = SOCFPGA-IMG $@
$(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 @@ FILE_barebox-socfpga-de0_nano_soc.img = start_socfpga_de0_nano_soc.pblx
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 d7fe1b1b6..fedcfb5b6 100644
--- a/scripts/socfpga_mkimage.c
+++ b/scripts/socfpga_mkimage.c
@@ -256,7 +256,7 @@ static int add_socfpga_header(void *buf, size_t size, unsigned start_addr, unsig
static void usage(const char *prgname)
{
- fprintf(stderr, "usage: %s [-hb] [-v version] <infile> -o <outfile>\n", prgname);
+ fprintf(stderr, "usage: %s [-hbs] [-v version] <infile> -o <outfile>\n", prgname);
}
int main(int argc, char *argv[])
@@ -268,9 +268,11 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
min_image_size = 0;
addsize = 512;
break;
+ case 's':
+ fixup_size = 1;
+ break;
case 'h':
usage(argv[0]);
exit(0);
@@ -349,10 +354,26 @@ int main(int argc, char *argv[])
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,