Browse Source

Merge branch 'master' of git://git.denx.de/u-boot-sh

- Gen3 PCIe driver + enablement on Salvator-X platforms.
- Gen3 recovery SPL used to reload ATF/OpTee/U-Boot instead of minimon.
- SDHI HS400 fixes ported from latest BSP and datasheet.
Tom Rini 5 years ago
parent
commit
c18b103657

+ 1 - 0
Kconfig

@@ -155,6 +155,7 @@ config SYS_MALLOC_LEN
 config SPL_SYS_MALLOC_F_LEN
 	hex "Size of malloc() pool in SPL before relocation"
 	depends on SYS_MALLOC_F
+	default 0x2800 if RCAR_GEN3
 	default SYS_MALLOC_F_LEN
 	help
 	  Before relocation, memory is very limited on many platforms. Still,

+ 3 - 0
Makefile

@@ -1117,6 +1117,9 @@ OBJCOPYFLAGS_u-boot-spl.srec = $(OBJCOPYFLAGS_u-boot.srec)
 spl/u-boot-spl.srec: spl/u-boot-spl FORCE
 	$(call if_changed,objcopy)
 
+%.scif: %.srec
+	$(Q)$(MAKE) $(build)=arch/arm/mach-rmobile $@
+
 OBJCOPYFLAGS_u-boot-nodtb.bin := -O binary \
 		$(if $(CONFIG_X86_16BIT_INIT),-R .start16 -R .resetvec) \
 		$(if $(CONFIG_MPC85XX_HAVE_RESET_VECTOR),-R .bootpg -R .resetvec)

+ 11 - 0
arch/arm/mach-rmobile/Kconfig

@@ -16,11 +16,22 @@ config RCAR_GEN3
 	select PINCTRL
 	select PINCONF
 	select PINCTRL_PFC
+	select SUPPORT_SPL
 	imply CMD_FS_UUID
 	imply CMD_GPT
 	imply CMD_UUID
 	imply CMD_MMC_SWRITE if MMC
 	imply SUPPORT_EMMC_RPMB if MMC
+	imply SPL
+	imply SPL_BOARD_INIT
+	imply SPL_GZIP
+	imply SPL_LIBCOMMON_SUPPORT
+	imply SPL_LIBGENERIC_SUPPORT
+	imply SPL_SERIAL_SUPPORT
+	imply SPL_SYS_MALLOC_SIMPLE
+	imply SPL_TINY_MEMSET
+	imply SPL_YMODEM_SUPPORT
+	imply USE_TINY_PRINTF
 
 config RZA1
 	prompt "Renesas ARM SoCs RZ/A1 (32bit)"

+ 73 - 0
arch/arm/mach-rmobile/Makefile

@@ -13,3 +13,76 @@ obj-$(CONFIG_SH73A0) += lowlevel_init.o cpu_info-sh73a0.o pfc-sh73a0.o
 obj-$(CONFIG_R8A7740) += lowlevel_init.o cpu_info-r8a7740.o pfc-r8a7740.o
 obj-$(CONFIG_RCAR_GEN2) += lowlevel_init_ca15.o cpu_info-rcar.o
 obj-$(CONFIG_RCAR_GEN3) += lowlevel_init_gen3.o cpu_info-rcar.o memmap-gen3.o
+
+OBJCOPYFLAGS_u-boot-spl.srec := -O srec
+quiet_cmd_objcopy = OBJCOPY $@
+cmd_objcopy = $(OBJCOPY) --gap-fill=0x00 $(OBJCOPYFLAGS) \
+	$(OBJCOPYFLAGS_$(@F)) $< $@
+
+spl/u-boot-spl.srec: spl/u-boot-spl FORCE
+	$(call if_changed,objcopy)
+
+ifneq ($(CONFIG_R8A77990)$(CONFIG_R8A77995),)
+#
+# The first 6 generate statements generate the R-Car Gen3 SCIF loader header.
+# The subsequent generate statements represent the following chunk of assembler
+# code, which copies the loaded data from 0xe6304030 to 0xe6318000. This is to
+# work around a limitation of the D3/E3 BootROM, which does not permit loading
+# to 0xe6318000 directly.
+#
+#	mov	x0,	#0xe6000000
+#	orr	x0, x0,	#0x00300000
+#	orr	x1, x0,	#0x00004000
+#	orr	x1, x1,	#0x00000030
+#
+#	orr	x2, x0,	#0x00018000
+#	mov	x0, x2
+#	mov	x3,	#0x7000
+#1:	ldp	x4, x5, [x1], #16
+#
+#	stp	x4, x5, [x2], #16
+#	subs	x3, x3, #16
+#	b.ge	1b
+#	br	x0
+#
+quiet_cmd_srec_cat = SRECCAT $@
+      cmd_srec_cat = srec_cat -output $@ -M 8 $< -M 8 \
+			-offset -0x13fd0 \
+			-Output_Block_Size 16 \
+			-generate 0xe6300400 0xe6300404 -l-e-constant 0x0 4 \
+			-generate 0xe630048c 0xe6300490 -l-e-constant 0x0 4 \
+			-generate 0xe63005d4 0xe63005d8 -l-e-constant 0xe6304000 4 \
+			-generate 0xe63006e4 0xe63006e8 -l-e-constant $2 4 \
+			-generate 0xe6301154 0xe6301158 -l-e-constant 0xe6304000 4 \
+			-generate 0xe6301264 0xe6301268 -l-e-constant $2 4 \
+			-generate 0xe6304000 0xe6304004 -l-e-constant 0xd2bcc000 4 \
+			-generate 0xe6304004 0xe6304008 -l-e-constant 0xb26c0400 4 \
+			-generate 0xe6304008 0xe630400c -l-e-constant 0xb2720001 4 \
+			-generate 0xe630400c 0xe6304010 -l-e-constant 0xb27c0421 4 \
+			-generate 0xe6304010 0xe6304014 -l-e-constant 0xb2710402 4 \
+			-generate 0xe6304014 0xe6304018 -l-e-constant 0xaa0203e0 4 \
+			-generate 0xe6304018 0xe630401c -l-e-constant 0xd28e0003 4 \
+			-generate 0xe630401c 0xe6304020 -l-e-constant 0xa8c11424 4 \
+			-generate 0xe6304020 0xe6304024 -l-e-constant 0xa8811444 4 \
+			-generate 0xe6304024 0xe6304028 -l-e-constant 0xf1004063 4 \
+			-generate 0xe6304028 0xe630402c -l-e-constant 0x54ffffaa 4 \
+			-generate 0xe630402c 0xe6304030 -l-e-constant 0xd61f0000 4
+else
+quiet_cmd_srec_cat = SRECCAT $@
+      cmd_srec_cat = srec_cat -output $@ -M 8 $< -M 8 \
+			-Output_Block_Size 16 \
+			-generate 0xe6300400 0xe6300404 -l-e-constant 0x0 4 \
+			-generate 0xe630048c 0xe6300490 -l-e-constant 0x0 4 \
+			-generate 0xe63005d4 0xe63005d8 -l-e-constant $(CONFIG_SPL_TEXT_BASE) 4 \
+			-generate 0xe63006e4 0xe63006e8 -l-e-constant $2 4 \
+			-generate 0xe6301154 0xe6301158 -l-e-constant $(CONFIG_SPL_TEXT_BASE) 4 \
+			-generate 0xe6301264 0xe6301268 -l-e-constant $2 4
+endif
+
+spl/u-boot-spl.scif: spl/u-boot-spl.srec spl/u-boot-spl.bin
+	$(call cmd,srec_cat,$(shell wc -c spl/u-boot-spl.bin | awk '{printf("0x%08x\n",$$1)}'))
+
+# if srec_cat is present build u-boot-spl.scif by default
+has_srec_cat = $(call try-run,srec_cat -VERSion,y,n)
+ALL-$(has_srec_cat) += u-boot-spl.scif
+CLEAN_FILES += u-boot-spl.scif

+ 5 - 1
board/renesas/draak/Makefile

@@ -6,4 +6,8 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 
-obj-y	:= draak.o
+ifdef CONFIG_SPL_BUILD
+obj-y	:= ../rcar-common/gen3-spl.o
+else
+obj-y	:= draak.o ../rcar-common/common.o
+endif

+ 0 - 15
board/renesas/draak/draak.c

@@ -70,21 +70,6 @@ int board_init(void)
 	return 0;
 }
 
-int dram_init(void)
-{
-	if (fdtdec_setup_mem_size_base() != 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-int dram_init_banksize(void)
-{
-	fdtdec_setup_memory_banksize();
-
-	return 0;
-}
-
 #define RST_BASE	0xE6160000
 #define RST_CA57RESCNT	(RST_BASE + 0x40)
 #define RST_CA53RESCNT	(RST_BASE + 0x44)

+ 5 - 1
board/renesas/eagle/Makefile

@@ -6,4 +6,8 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 
-obj-y	:= eagle.o
+ifdef CONFIG_SPL_BUILD
+obj-y	:= ../rcar-common/gen3-spl.o
+else
+obj-y	:= eagle.o ../rcar-common/common.o
+endif

+ 0 - 15
board/renesas/eagle/eagle.c

@@ -67,21 +67,6 @@ int board_init(void)
 	return 0;
 }
 
-int dram_init(void)
-{
-	if (fdtdec_setup_mem_size_base() != 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-int dram_init_banksize(void)
-{
-	fdtdec_setup_memory_banksize();
-
-	return 0;
-}
-
 #define RST_BASE	0xE6160000
 #define RST_CA57RESCNT	(RST_BASE + 0x40)
 #define RST_CA53RESCNT	(RST_BASE + 0x44)

+ 5 - 1
board/renesas/ebisu/Makefile

@@ -6,4 +6,8 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 
-obj-y	:= ebisu.o
+ifdef CONFIG_SPL_BUILD
+obj-y	:= ../rcar-common/gen3-spl.o
+else
+obj-y	:= ebisu.o ../rcar-common/common.o
+endif

+ 0 - 35
board/renesas/ebisu/ebisu.c

@@ -43,41 +43,6 @@ int board_init(void)
 	return 0;
 }
 
-/*
- * If the firmware passed a device tree use it for U-Boot DRAM setup.
- */
-extern u64 rcar_atf_boot_args[];
-
-int dram_init(void)
-{
-	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
-	const void *blob;
-
-	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
-	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
-		blob = atf_fdt_blob;
-	else
-		blob = gd->fdt_blob;
-
-	return fdtdec_setup_mem_size_base_fdt(blob);
-}
-
-int dram_init_banksize(void)
-{
-	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
-	const void *blob;
-
-	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
-	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
-		blob = atf_fdt_blob;
-	else
-		blob = gd->fdt_blob;
-
-	fdtdec_setup_memory_banksize_fdt(blob);
-
-	return 0;
-}
-
 #define RST_BASE	0xE6160000
 #define RST_CA57RESCNT	(RST_BASE + 0x40)
 #define RST_CA53RESCNT	(RST_BASE + 0x44)

+ 38 - 0
board/renesas/rcar-common/common.c

@@ -9,3 +9,41 @@
 
 #include <common.h>
 #include <asm/arch/rmobile.h>
+
+#ifdef CONFIG_RCAR_GEN3
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* If the firmware passed a device tree use it for U-Boot DRAM setup. */
+extern u64 rcar_atf_boot_args[];
+
+int dram_init(void)
+{
+	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
+	const void *blob;
+
+	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
+	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
+		blob = atf_fdt_blob;
+	else
+		blob = gd->fdt_blob;
+
+	return fdtdec_setup_mem_size_base_fdt(blob);
+}
+
+int dram_init_banksize(void)
+{
+	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
+	const void *blob;
+
+	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
+	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
+		blob = atf_fdt_blob;
+	else
+		blob = gd->fdt_blob;
+
+	fdtdec_setup_memory_banksize_fdt(blob);
+
+	return 0;
+}
+#endif

+ 55 - 0
board/renesas/rcar-common/gen3-spl.c

@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Car Gen3 recovery SPL
+ *
+ * Copyright (C) 2019 Marek Vasut <marek.vasut@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <spl.h>
+
+#define RCAR_CNTC_BASE	0xE6080000
+#define CNTCR_EN	BIT(0)
+
+void board_init_f(ulong dummy)
+{
+	writel(CNTCR_EN, RCAR_CNTC_BASE);
+	timer_init();
+}
+
+void spl_board_init(void)
+{
+	/* UART clocks enabled and gd valid - init serial console */
+	preloader_console_init();
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_UART;
+}
+
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
+{
+	debug("image entry point: 0x%lx\n", spl_image->entry_point);
+	if (spl_image->os == IH_OS_ARM_TRUSTED_FIRMWARE) {
+		typedef void (*image_entry_arg_t)(int, int, int, int)
+			__attribute__ ((noreturn));
+		image_entry_arg_t image_entry =
+			(image_entry_arg_t)(uintptr_t) spl_image->entry_point;
+		image_entry(IH_MAGIC, CONFIG_SPL_TEXT_BASE, 0, 0);
+	} else {
+		typedef void __noreturn (*image_entry_noargs_t)(void);
+		image_entry_noargs_t image_entry =
+			(image_entry_noargs_t)spl_image->entry_point;
+		image_entry();
+	}
+}
+
+void s_init(void)
+{
+}
+
+void reset_cpu(ulong addr)
+{
+}

+ 5 - 1
board/renesas/salvator-x/Makefile

@@ -6,4 +6,8 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 
-obj-y	:= salvator-x.o
+ifdef CONFIG_SPL_BUILD
+obj-y	:= ../rcar-common/gen3-spl.o
+else
+obj-y	:= salvator-x.o ../rcar-common/common.o
+endif

+ 0 - 35
board/renesas/salvator-x/salvator-x.c

@@ -69,41 +69,6 @@ int board_init(void)
 	return 0;
 }
 
-/*
- * If the firmware passed a device tree use it for U-Boot DRAM setup.
- */
-extern u64 rcar_atf_boot_args[];
-
-int dram_init(void)
-{
-	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
-	const void *blob;
-
-	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
-	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
-		blob = atf_fdt_blob;
-	else
-		blob = gd->fdt_blob;
-
-	return fdtdec_setup_mem_size_base_fdt(blob);
-}
-
-int dram_init_banksize(void)
-{
-	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
-	const void *blob;
-
-	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
-	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
-		blob = atf_fdt_blob;
-	else
-		blob = gd->fdt_blob;
-
-	fdtdec_setup_memory_banksize_fdt(blob);
-
-	return 0;
-}
-
 #define RST_BASE	0xE6160000
 #define RST_CA57RESCNT	(RST_BASE + 0x40)
 #define RST_CA53RESCNT	(RST_BASE + 0x44)

+ 5 - 1
board/renesas/ulcb/Makefile

@@ -6,4 +6,8 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 
-obj-y	:= ulcb.o cpld.o
+ifdef CONFIG_SPL_BUILD
+obj-y	:= ../rcar-common/gen3-spl.o
+else
+obj-y	:= ulcb.o cpld.o ../rcar-common/common.o
+endif

+ 0 - 35
board/renesas/ulcb/ulcb.c

@@ -68,41 +68,6 @@ int board_init(void)
 	return 0;
 }
 
-/*
- * If the firmware passed a device tree use it for U-Boot DRAM setup.
- */
-extern u64 rcar_atf_boot_args[];
-
-int dram_init(void)
-{
-	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
-	const void *blob;
-
-	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
-	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
-		blob = atf_fdt_blob;
-	else
-		blob = gd->fdt_blob;
-
-	return fdtdec_setup_mem_size_base_fdt(blob);
-}
-
-int dram_init_banksize(void)
-{
-	const void *atf_fdt_blob = (const void *)(rcar_atf_boot_args[1]);
-	const void *blob;
-
-	/* Check if ATF passed us DTB. If not, fall back to builtin DTB. */
-	if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
-		blob = atf_fdt_blob;
-	else
-		blob = gd->fdt_blob;
-
-	fdtdec_setup_memory_banksize_fdt(blob);
-
-	return 0;
-}
-
 #ifdef CONFIG_MULTI_DTB_FIT
 int board_fit_config_name_match(const char *name)
 {

+ 5 - 0
configs/r8a7795_salvator-x_defconfig

@@ -11,11 +11,13 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a7795-salvator-x.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6338000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
@@ -48,6 +50,9 @@ CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_DM_ETH=y
 CONFIG_RENESAS_RAVB=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_RCAR_GEN3=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y

+ 1 - 0
configs/r8a7795_ulcb_defconfig

@@ -12,6 +12,7 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a7795-h3ulcb.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6338000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y

+ 5 - 0
configs/r8a77965_salvator-x_defconfig

@@ -12,11 +12,13 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a77965-salvator-x.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6338000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
@@ -49,6 +51,9 @@ CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_DM_ETH=y
 CONFIG_RENESAS_RAVB=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_RCAR_GEN3=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y

+ 1 - 0
configs/r8a77965_ulcb_defconfig

@@ -12,6 +12,7 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a77965-m3nulcb.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6338000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y

+ 5 - 0
configs/r8a7796_salvator-x_defconfig

@@ -12,11 +12,13 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a7796-salvator-x.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6338000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
@@ -49,6 +51,9 @@ CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_DM_ETH=y
 CONFIG_RENESAS_RAVB=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_RCAR_GEN3=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y

+ 1 - 0
configs/r8a7796_ulcb_defconfig

@@ -12,6 +12,7 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a7796-m3ulcb.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6338000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y

+ 1 - 0
configs/r8a77970_eagle_defconfig

@@ -12,6 +12,7 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a77970-eagle.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6318000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y

+ 1 - 0
configs/r8a77990_ebisu_defconfig

@@ -12,6 +12,7 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a77990-ebisu.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6318000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y

+ 1 - 0
configs/r8a77995_draak_defconfig

@@ -12,6 +12,7 @@ CONFIG_BOOTARGS="root=/dev/nfs rw nfsroot=192.168.0.1:/export/rfs ip=192.168.0.2
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_DEFAULT_FDT_FILE="r8a77995-draak.dtb"
 CONFIG_VERSION_VARIABLE=y
+CONFIG_SPL_TEXT_BASE=0xe6318000
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPIO=y

+ 172 - 13
drivers/mmc/renesas-sdhi.c

@@ -23,24 +23,126 @@
 
 /* SCC registers */
 #define RENESAS_SDHI_SCC_DTCNTL			0x800
-#define   RENESAS_SDHI_SCC_DTCNTL_TAPEN		BIT(0)
-#define   RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT	16
-#define   RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK		0xff
+#define RENESAS_SDHI_SCC_DTCNTL_TAPEN		BIT(0)
+#define RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT	16
+#define RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK	0xff
 #define RENESAS_SDHI_SCC_TAPSET			0x804
 #define RENESAS_SDHI_SCC_DT2FF			0x808
 #define RENESAS_SDHI_SCC_CKSEL			0x80c
-#define   RENESAS_SDHI_SCC_CKSEL_DTSEL		BIT(0)
-#define RENESAS_SDHI_SCC_RVSCNTL			0x810
-#define   RENESAS_SDHI_SCC_RVSCNTL_RVSEN		BIT(0)
+#define RENESAS_SDHI_SCC_CKSEL_DTSEL		BIT(0)
+#define RENESAS_SDHI_SCC_RVSCNTL		0x810
+#define RENESAS_SDHI_SCC_RVSCNTL_RVSEN		BIT(0)
 #define RENESAS_SDHI_SCC_RVSREQ			0x814
-#define   RENESAS_SDHI_SCC_RVSREQ_RVSERR		BIT(2)
+#define RENESAS_SDHI_SCC_RVSREQ_RVSERR		BIT(2)
 #define RENESAS_SDHI_SCC_SMPCMP			0x818
-#define RENESAS_SDHI_SCC_TMPPORT2			0x81c
-#define   RENESAS_SDHI_SCC_TMPPORT2_HS400EN		BIT(31)
-#define   RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL		BIT(4)
+#define RENESAS_SDHI_SCC_TMPPORT2		0x81c
+#define RENESAS_SDHI_SCC_TMPPORT2_HS400EN	BIT(31)
+#define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL	BIT(4)
+#define RENESAS_SDHI_SCC_TMPPORT3		0x828
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_0	3
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_1	2
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_2	1
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_3	0
+#define RENESAS_SDHI_SCC_TMPPORT3_OFFSET_MASK	0x3
+#define RENESAS_SDHI_SCC_TMPPORT4		0x82c
+#define RENESAS_SDHI_SCC_TMPPORT4_DLL_ACC_START	BIT(0)
+#define RENESAS_SDHI_SCC_TMPPORT5		0x830
+#define RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_R	BIT(8)
+#define RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_W	(0 << 8)
+#define RENESAS_SDHI_SCC_TMPPORT5_DLL_ADR_MASK	0x3F
+#define RENESAS_SDHI_SCC_TMPPORT6		0x834
+#define RENESAS_SDHI_SCC_TMPPORT7		0x838
+#define RENESAS_SDHI_SCC_TMPPORT_DISABLE_WP_CODE	0xa5000000
+#define RENESAS_SDHI_SCC_TMPPORT_CALIB_CODE_MASK	0x1f
+#define RENESAS_SDHI_SCC_TMPPORT_MANUAL_MODE		BIT(7)
 
 #define RENESAS_SDHI_MAX_TAP 3
 
+static u32 sd_scc_tmpport_read32(struct tmio_sd_priv *priv, u32 addr)
+{
+	/* read mode */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_R |
+		       (RENESAS_SDHI_SCC_TMPPORT5_DLL_ADR_MASK & addr),
+		       RENESAS_SDHI_SCC_TMPPORT5);
+
+	/* access start and stop */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT4_DLL_ACC_START,
+		       RENESAS_SDHI_SCC_TMPPORT4);
+	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_TMPPORT4);
+
+	return tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT7);
+}
+
+static void sd_scc_tmpport_write32(struct tmio_sd_priv *priv, u32 addr, u32 val)
+{
+	/* write mode */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT5_DLL_RW_SEL_W |
+		       (RENESAS_SDHI_SCC_TMPPORT5_DLL_ADR_MASK & addr),
+		       RENESAS_SDHI_SCC_TMPPORT5);
+	tmio_sd_writel(priv, val, RENESAS_SDHI_SCC_TMPPORT6);
+
+	/* access start and stop */
+	tmio_sd_writel(priv, RENESAS_SDHI_SCC_TMPPORT4_DLL_ACC_START,
+		       RENESAS_SDHI_SCC_TMPPORT4);
+	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_TMPPORT4);
+}
+
+static void renesas_sdhi_adjust_hs400_mode_enable(struct tmio_sd_priv *priv)
+{
+	u32 calib_code;
+
+	if (!priv->adjust_hs400_enable)
+		return;
+
+	if (!priv->needs_adjust_hs400)
+		return;
+
+	/*
+	 * Enabled Manual adjust HS400 mode
+	 *
+	 * 1) Disabled Write Protect
+	 *    W(addr=0x00, WP_DISABLE_CODE)
+	 * 2) Read Calibration code and adjust
+	 *    R(addr=0x26) - adjust value
+	 * 3) Enabled Manual Calibration
+	 *    W(addr=0x22, manual mode | Calibration code)
+	 * 4) Set Offset value to TMPPORT3 Reg
+	 */
+	sd_scc_tmpport_write32(priv, 0x00,
+			       RENESAS_SDHI_SCC_TMPPORT_DISABLE_WP_CODE);
+	calib_code = sd_scc_tmpport_read32(priv, 0x26);
+	calib_code &= RENESAS_SDHI_SCC_TMPPORT_CALIB_CODE_MASK;
+	if (calib_code > priv->adjust_hs400_calibrate)
+		calib_code -= priv->adjust_hs400_calibrate;
+	else
+		calib_code = 0;
+	sd_scc_tmpport_write32(priv, 0x22,
+			       RENESAS_SDHI_SCC_TMPPORT_MANUAL_MODE |
+			       calib_code);
+	tmio_sd_writel(priv, priv->adjust_hs400_offset,
+		       RENESAS_SDHI_SCC_TMPPORT3);
+
+	/* Clear flag */
+	priv->needs_adjust_hs400 = false;
+}
+
+static void renesas_sdhi_adjust_hs400_mode_disable(struct tmio_sd_priv *priv)
+{
+
+	/* Disabled Manual adjust HS400 mode
+	 *
+	 * 1) Disabled Write Protect
+	 *    W(addr=0x00, WP_DISABLE_CODE)
+	 * 2) Disabled Manual Calibration
+	 *    W(addr=0x22, 0)
+	 * 3) Clear offset value to TMPPORT3 Reg
+	 */
+	sd_scc_tmpport_write32(priv, 0x00,
+			       RENESAS_SDHI_SCC_TMPPORT_DISABLE_WP_CODE);
+	sd_scc_tmpport_write32(priv, 0x22, 0);
+	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_TMPPORT3);
+}
+
 static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv)
 {
 	u32 reg;
@@ -96,6 +198,9 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv)
 		 RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL);
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
 
+	/* Disable HS400 mode adjustment */
+	renesas_sdhi_adjust_hs400_mode_disable(priv);
+
 	reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
 	reg |= TMIO_SD_CLKCTL_SCLKEN;
 	tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
@@ -137,6 +242,10 @@ static int renesas_sdhi_hs400(struct udevice *dev)
 
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
 
+	/* Disable HS400 mode adjustment */
+	if (!hs400)
+		renesas_sdhi_adjust_hs400_mode_disable(priv);
+
 	tmio_sd_writel(priv, (0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) |
 			     RENESAS_SDHI_SCC_DTCNTL_TAPEN,
 			     RENESAS_SDHI_SCC_DTCNTL);
@@ -159,6 +268,10 @@ static int renesas_sdhi_hs400(struct udevice *dev)
 	reg |= RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
 
+	/* Execute adjust hs400 offset after setting to HS400 mode */
+	if (hs400)
+		priv->needs_adjust_hs400 = true;
+
 	return 0;
 }
 
@@ -188,6 +301,8 @@ static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv,
 	bool select = false;
 	u32 reg;
 
+	priv->needs_adjust_hs400 = false;
+
 	/* Clear SCC_RVSREQ */
 	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
 
@@ -405,8 +520,29 @@ static int renesas_sdhi_wait_dat0(struct udevice *dev, int state, int timeout)
 }
 #endif
 
+static int renesas_sdhi_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+				 struct mmc_data *data)
+{
+	int ret;
+
+	ret = tmio_sd_send_cmd(dev, cmd, data);
+	if (ret)
+		return ret;
+
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+	if (cmd->cmdidx == MMC_CMD_SEND_STATUS)
+		renesas_sdhi_adjust_hs400_mode_enable(priv);
+#endif
+
+	return 0;
+}
+
 static const struct dm_mmc_ops renesas_sdhi_ops = {
-	.send_cmd = tmio_sd_send_cmd,
+	.send_cmd = renesas_sdhi_send_cmd,
 	.set_ios = renesas_sdhi_set_ios,
 	.get_cd = tmio_sd_get_cd,
 #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
@@ -451,14 +587,37 @@ static void renesas_sdhi_filter_caps(struct udevice *dev)
 	if (!(priv->caps & TMIO_SD_CAP_RCAR_GEN3))
 		return;
 
-	/* HS400 is not supported on H3 ES1.x and M3W ES1.0,ES1.1 */
+	/* HS400 is not supported on H3 ES1.x and M3W ES1.0,ES1.1,ES1.2 */
 	if (((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
 	    (rmobile_get_cpu_rev_integer() <= 1)) ||
 	    ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
 	    (rmobile_get_cpu_rev_integer() == 1) &&
-	    (rmobile_get_cpu_rev_fraction() <= 1)))
+	    (rmobile_get_cpu_rev_fraction() <= 2)))
 		plat->cfg.host_caps &= ~MMC_MODE_HS400;
 
+	/* M3W ES1.x for x>2 can use HS400 with manual adjustment */
+	if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
+	    (rmobile_get_cpu_rev_integer() == 1) &&
+	    (rmobile_get_cpu_rev_fraction() > 2)) {
+		priv->adjust_hs400_enable = true;
+		priv->adjust_hs400_offset = 0;
+		priv->adjust_hs400_calibrate = 0x9;
+	}
+
+	/* M3N can use HS400 with manual adjustment */
+	if (rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A77965) {
+		priv->adjust_hs400_enable = true;
+		priv->adjust_hs400_offset = 0;
+		priv->adjust_hs400_calibrate = 0x0;
+	}
+
+	/* E3 can use HS400 with manual adjustment */
+	if (rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A77990) {
+		priv->adjust_hs400_enable = true;
+		priv->adjust_hs400_offset = 0;
+		priv->adjust_hs400_calibrate = 0x2;
+	}
+
 	/* H3 ES2.0 uses 4 tuning taps */
 	if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
 	    (rmobile_get_cpu_rev_integer() == 2))

+ 4 - 0
drivers/mmc/tmio-common.h

@@ -139,6 +139,10 @@ struct tmio_sd_priv {
 #if CONFIG_IS_ENABLED(RENESAS_SDHI)
 	u8				tap_set;
 	u8				nrtaps;
+	bool				needs_adjust_hs400;
+	bool				adjust_hs400_enable;
+	u8				adjust_hs400_offset;
+	u8				adjust_hs400_calibrate;
 #endif
 	ulong (*clk_get_rate)(struct tmio_sd_priv *);
 };

+ 8 - 0
drivers/pci/Kconfig

@@ -69,6 +69,14 @@ config PCI_RCAR_GEN2
 	  Renesas RCar Gen2 SoCs. The PCIe controller on RCar Gen2 is
 	  also used to access EHCI USB controller on the SoC.
 
+config PCI_RCAR_GEN3
+	bool "Renesas RCar Gen3 PCIe driver"
+	depends on DM_PCI
+	depends on RCAR_GEN3
+	help
+	  Say Y here if you want to enable PCIe controller support on
+	  Renesas RCar Gen3 SoCs.
+
 config PCI_SANDBOX
 	bool "Sandbox PCI support"
 	depends on SANDBOX && DM_PCI

+ 1 - 0
drivers/pci/Makefile

@@ -24,6 +24,7 @@ obj-$(CONFIG_PCIE_IMX) += pcie_imx.o
 obj-$(CONFIG_FTPCI100) += pci_ftpci100.o
 obj-$(CONFIG_PCI_MVEBU) += pci_mvebu.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
+obj-$(CONFIG_PCI_RCAR_GEN3) += pci-rcar-gen3.o
 obj-$(CONFIG_SH4_PCI) += pci_sh4.o
 obj-$(CONFIG_SH7751_PCI) +=pci_sh7751.o
 obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o

+ 411 - 0
drivers/pci/pci-rcar-gen3.c

@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RCar Gen3 PCIEC driver
+ *
+ * Copyright (C) 2018-2019 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on Linux PCIe driver for Renesas R-Car SoCs
+ *  Copyright (C) 2014 Renesas Electronics Europe Ltd
+ *
+ * Based on:
+ *  arch/sh/drivers/pci/pcie-sh7786.c
+ *  arch/sh/drivers/pci/ops-sh7786.c
+ *  Copyright (C) 2009 - 2011  Paul Mundt
+ *
+ * Author: Phil Edworthy <phil.edworthy@renesas.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <pci.h>
+#include <wait_bit.h>
+
+#define PCIECAR			0x000010
+#define PCIECCTLR		0x000018
+#define  CONFIG_SEND_ENABLE	BIT(31)
+#define  TYPE0			(0 << 8)
+#define  TYPE1			BIT(8)
+#define PCIECDR			0x000020
+#define PCIEMSR			0x000028
+#define PCIEINTXR		0x000400
+#define PCIEPHYSR		0x0007f0
+#define  PHYRDY			BIT(0)
+#define PCIEMSITXR		0x000840
+
+/* Transfer control */
+#define PCIETCTLR		0x02000
+#define  CFINIT			1
+#define PCIETSTR		0x02004
+#define  DATA_LINK_ACTIVE	1
+#define PCIEERRFR		0x02020
+#define  UNSUPPORTED_REQUEST	BIT(4)
+#define PCIEMSIFR		0x02044
+#define PCIEMSIALR		0x02048
+#define  MSIFE			1
+#define PCIEMSIAUR		0x0204c
+#define PCIEMSIIER		0x02050
+
+/* root port address */
+#define PCIEPRAR(x)		(0x02080 + ((x) * 0x4))
+
+/* local address reg & mask */
+#define PCIELAR(x)		(0x02200 + ((x) * 0x20))
+#define PCIELAMR(x)		(0x02208 + ((x) * 0x20))
+#define  LAM_PREFETCH		BIT(3)
+#define  LAM_64BIT		BIT(2)
+#define  LAR_ENABLE		BIT(1)
+
+/* PCIe address reg & mask */
+#define PCIEPALR(x)		(0x03400 + ((x) * 0x20))
+#define PCIEPAUR(x)		(0x03404 + ((x) * 0x20))
+#define PCIEPAMR(x)		(0x03408 + ((x) * 0x20))
+#define PCIEPTCTLR(x)		(0x0340c + ((x) * 0x20))
+#define  PAR_ENABLE		BIT(31)
+#define  IO_SPACE		BIT(8)
+
+/* Configuration */
+#define PCICONF(x)		(0x010000 + ((x) * 0x4))
+#define PMCAP(x)		(0x010040 + ((x) * 0x4))
+#define EXPCAP(x)		(0x010070 + ((x) * 0x4))
+#define VCCAP(x)		(0x010100 + ((x) * 0x4))
+
+/* link layer */
+#define IDSETR1			0x011004
+#define TLCTLR			0x011048
+#define MACSR			0x011054
+#define  SPCHGFIN		BIT(4)
+#define  SPCHGFAIL		BIT(6)
+#define  SPCHGSUC		BIT(7)
+#define  LINK_SPEED		(0xf << 16)
+#define  LINK_SPEED_2_5GTS	(1 << 16)
+#define  LINK_SPEED_5_0GTS	(2 << 16)
+#define MACCTLR			0x011058
+#define  SPEED_CHANGE		BIT(24)
+#define  SCRAMBLE_DISABLE	BIT(27)
+#define MACS2R			0x011078
+#define MACCGSPSETR		0x011084
+#define  SPCNGRSN		BIT(31)
+
+/* R-Car H1 PHY */
+#define H1_PCIEPHYADRR		0x04000c
+#define  WRITE_CMD		BIT(16)
+#define  PHY_ACK		BIT(24)
+#define  RATE_POS		12
+#define  LANE_POS		8
+#define  ADR_POS		0
+#define H1_PCIEPHYDOUTR		0x040014
+
+/* R-Car Gen2 PHY */
+#define GEN2_PCIEPHYADDR	0x780
+#define GEN2_PCIEPHYDATA	0x784
+#define GEN2_PCIEPHYCTRL	0x78c
+
+#define INT_PCI_MSI_NR		32
+
+#define RCONF(x)		(PCICONF(0) + (x))
+#define RPMCAP(x)		(PMCAP(0) + (x))
+#define REXPCAP(x)		(EXPCAP(0) + (x))
+#define RVCCAP(x)		(VCCAP(0) + (x))
+
+#define PCIE_CONF_BUS(b)	(((b) & 0xff) << 24)
+#define PCIE_CONF_DEV(d)	(((d) & 0x1f) << 19)
+#define PCIE_CONF_FUNC(f)	(((f) & 0x7) << 16)
+
+#define RCAR_PCI_MAX_RESOURCES	4
+#define MAX_NR_INBOUND_MAPS	6
+
+#define PCI_EXP_FLAGS		2		/* Capabilities register */
+#define PCI_EXP_FLAGS_TYPE	0x00f0		/* Device/Port type */
+#define PCI_EXP_TYPE_ROOT_PORT	0x4		/* Root Port */
+#define PCI_EXP_LNKCAP		12		/* Link Capabilities */
+#define PCI_EXP_LNKCAP_DLLLARC	0x00100000	/* Data Link Layer Link Active Reporting Capable */
+#define PCI_EXP_SLTCAP		20		/* Slot Capabilities */
+#define PCI_EXP_SLTCAP_PSN	0xfff80000	/* Physical Slot Number */
+
+enum {
+	RCAR_PCI_ACCESS_READ,
+	RCAR_PCI_ACCESS_WRITE,
+};
+
+struct rcar_gen3_pcie_priv {
+	fdt_addr_t		regs;
+};
+
+static void rcar_rmw32(struct udevice *dev, int where, u32 mask, u32 data)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(dev);
+	int shift = 8 * (where & 3);
+
+	clrsetbits_le32(priv->regs + (where & ~3),
+			mask << shift, data << shift);
+}
+
+static u32 rcar_read_conf(struct udevice *dev, int where)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(dev);
+	int shift = 8 * (where & 3);
+
+	return readl(priv->regs + (where & ~3)) >> shift;
+}
+
+static int rcar_pcie_config_access(struct udevice *udev,
+				   unsigned char access_type,
+				   pci_dev_t bdf, int where, ulong *data)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(udev);
+	u32 reg = where & ~3;
+
+	/* Clear errors */
+	clrbits_le32(priv->regs + PCIEERRFR, 0);
+
+	/* Set the PIO address */
+	writel((bdf << 8) | reg, priv->regs + PCIECAR);
+
+	/* Enable the configuration access */
+	if (!PCI_BUS(bdf))
+		writel(CONFIG_SEND_ENABLE | TYPE0, priv->regs + PCIECCTLR);
+	else
+		writel(CONFIG_SEND_ENABLE | TYPE1, priv->regs + PCIECCTLR);
+
+	/* Check for errors */
+	if (readl(priv->regs + PCIEERRFR) & UNSUPPORTED_REQUEST)
+		return -ENODEV;
+
+	/* Check for master and target aborts */
+	if (rcar_read_conf(udev, RCONF(PCI_STATUS)) &
+		(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
+		return -ENODEV;
+
+	if (access_type == RCAR_PCI_ACCESS_READ)
+		*data = readl(priv->regs + PCIECDR);
+	else
+		writel(*data, priv->regs + PCIECDR);
+
+	/* Disable the configuration access */
+	writel(0, priv->regs + PCIECCTLR);
+
+	return 0;
+}
+
+static int rcar_gen3_pcie_addr_valid(pci_dev_t d, uint where)
+{
+	u32 slot;
+
+	if (PCI_FUNC(d))
+		return -EINVAL;
+
+	slot = PCI_DEV(d);
+	if (slot != 1)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rcar_gen3_pcie_read_config(struct udevice *dev, pci_dev_t bdf,
+				      uint where, ulong *val,
+				      enum pci_size_t size)
+{
+	ulong reg;
+	int ret;
+
+	ret = rcar_gen3_pcie_addr_valid(bdf, where);
+	if (ret) {
+		*val = pci_get_ff(size);
+		return 0;
+	}
+
+	ret = rcar_pcie_config_access(dev, RCAR_PCI_ACCESS_READ,
+				      bdf, where, &reg);
+	if (ret != 0)
+		reg = 0xffffffffUL;
+
+	*val = pci_conv_32_to_size(reg, where, size);
+
+	return ret;
+}
+
+static int rcar_gen3_pcie_write_config(struct udevice *dev, pci_dev_t bdf,
+				       uint where, ulong val,
+				       enum pci_size_t size)
+{
+	ulong data;
+	int ret;
+
+	ret = rcar_gen3_pcie_addr_valid(bdf, where);
+	if (ret)
+		return ret;
+
+	data = pci_conv_32_to_size(val, where, size);
+
+	ret = rcar_pcie_config_access(dev, RCAR_PCI_ACCESS_WRITE,
+				      bdf, where, &data);
+
+	return ret;
+}
+
+static int rcar_gen3_pcie_wait_for_phyrdy(struct udevice *dev)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(dev);
+
+	return wait_for_bit_le32((void *)priv->regs + PCIEPHYSR, PHYRDY,
+				 true, 50, false);
+}
+
+static int rcar_gen3_pcie_wait_for_dl(struct udevice *dev)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(dev);
+
+	return wait_for_bit_le32((void *)priv->regs + PCIETSTR,
+				 DATA_LINK_ACTIVE, true, 50, false);
+}
+
+static int rcar_gen3_pcie_hw_init(struct udevice *dev)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(dev);
+	int ret;
+
+	/* Begin initialization */
+	writel(0, priv->regs + PCIETCTLR);
+
+	/* Set mode */
+	writel(1, priv->regs + PCIEMSR);
+
+	ret = rcar_gen3_pcie_wait_for_phyrdy(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Initial header for port config space is type 1, set the device
+	 * class to match. Hardware takes care of propagating the IDSETR
+	 * settings, so there is no need to bother with a quirk.
+	 */
+	writel(PCI_CLASS_BRIDGE_PCI << 16, priv->regs + IDSETR1);
+
+	/*
+	 * Setup Secondary Bus Number & Subordinate Bus Number, even though
+	 * they aren't used, to avoid bridge being detected as broken.
+	 */
+	rcar_rmw32(dev, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
+	rcar_rmw32(dev, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
+
+	/* Initialize default capabilities. */
+	rcar_rmw32(dev, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
+	rcar_rmw32(dev, REXPCAP(PCI_EXP_FLAGS),
+		   PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
+	rcar_rmw32(dev, RCONF(PCI_HEADER_TYPE), 0x7f,
+		   PCI_HEADER_TYPE_BRIDGE);
+
+	/* Enable data link layer active state reporting */
+	rcar_rmw32(dev, REXPCAP(PCI_EXP_LNKCAP),
+		   PCI_EXP_LNKCAP_DLLLARC, PCI_EXP_LNKCAP_DLLLARC);
+
+	/* Write out the physical slot number = 0 */
+	rcar_rmw32(dev, REXPCAP(PCI_EXP_SLTCAP),
+		   PCI_EXP_SLTCAP_PSN, 0);
+
+	/* Set the completion timer timeout to the maximum 50ms. */
+	rcar_rmw32(dev, TLCTLR + 1, 0x3f, 50);
+
+	/* Terminate list of capabilities (Next Capability Offset=0) */
+	rcar_rmw32(dev, RVCCAP(0), 0xfff00000, 0);
+
+	/* Finish initialization - establish a PCI Express link */
+	writel(CFINIT, priv->regs + PCIETCTLR);
+
+	return rcar_gen3_pcie_wait_for_dl(dev);
+}
+
+static int rcar_gen3_pcie_probe(struct udevice *dev)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(dev);
+	struct pci_controller *hose = dev_get_uclass_priv(dev);
+	struct clk pci_clk;
+	u32 mask;
+	int i, cnt, ret;
+
+	ret = clk_get_by_index(dev, 0, &pci_clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&pci_clk);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < hose->region_count; i++) {
+		if (hose->regions[i].flags != PCI_REGION_SYS_MEMORY)
+			continue;
+
+		if (hose->regions[i].phys_start == 0)
+			continue;
+
+		mask = (hose->regions[i].size - 1) & ~0xf;
+		mask |= LAR_ENABLE;
+		writel(hose->regions[i].phys_start, priv->regs + PCIEPRAR(0));
+		writel(hose->regions[i].phys_start, priv->regs + PCIELAR(0));
+		writel(mask, priv->regs + PCIELAMR(0));
+		break;
+	}
+
+	writel(0, priv->regs + PCIEPRAR(4));
+	writel(0, priv->regs + PCIELAR(4));
+	writel(0, priv->regs + PCIELAMR(4));
+
+	ret = rcar_gen3_pcie_hw_init(dev);
+	if (ret)
+		return ret;
+
+	for (i = 0, cnt = 0; i < hose->region_count; i++) {
+		if (hose->regions[i].flags == PCI_REGION_SYS_MEMORY)
+			continue;
+
+		writel(0, priv->regs + PCIEPTCTLR(cnt));
+		writel((hose->regions[i].size - 1) & ~0x7f,
+		       priv->regs + PCIEPAMR(cnt));
+		writel(upper_32_bits(hose->regions[i].phys_start),
+		       priv->regs + PCIEPAUR(cnt));
+		writel(lower_32_bits(hose->regions[i].phys_start),
+		       priv->regs + PCIEPALR(cnt));
+		mask = PAR_ENABLE;
+		if (hose->regions[i].flags == PCI_REGION_IO)
+			mask |= IO_SPACE;
+		writel(mask, priv->regs + PCIEPTCTLR(cnt));
+
+		cnt++;
+	}
+
+	return 0;
+}
+
+static int rcar_gen3_pcie_ofdata_to_platdata(struct udevice *dev)
+{
+	struct rcar_gen3_pcie_priv *priv = dev_get_platdata(dev);
+
+	priv->regs = devfdt_get_addr_index(dev, 0);
+	if (!priv->regs)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct dm_pci_ops rcar_gen3_pcie_ops = {
+	.read_config	= rcar_gen3_pcie_read_config,
+	.write_config	= rcar_gen3_pcie_write_config,
+};
+
+static const struct udevice_id rcar_gen3_pcie_ids[] = {
+	{ .compatible = "renesas,pcie-rcar-gen3" },
+	{ }
+};
+
+U_BOOT_DRIVER(rcar_gen3_pcie) = {
+	.name			= "rcar_gen3_pcie",
+	.id			= UCLASS_PCI,
+	.of_match		= rcar_gen3_pcie_ids,
+	.ops			= &rcar_gen3_pcie_ops,
+	.probe			= rcar_gen3_pcie_probe,
+	.ofdata_to_platdata	= rcar_gen3_pcie_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct rcar_gen3_pcie_priv),
+};

+ 19 - 0
include/configs/rcar-gen3-common.h

@@ -13,6 +13,10 @@
 
 #define CONFIG_REMAKE_ELF
 
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_TARGET	"spl/u-boot-spl.scif"
+#endif
+
 /* boot option */
 
 #define CONFIG_CMDLINE_TAG
@@ -64,4 +68,19 @@
 	"tftp 0x48000000 Image-"CONFIG_DEFAULT_FDT_FILE"; " \
 	"booti 0x48080000 - 0x48000000"
 
+/* SPL support */
+#if defined(CONFIG_R8A7795) || defined(CONFIG_R8A7796) || defined(CONFIG_R8A77965)
+#define CONFIG_SPL_BSS_START_ADDR	0xe633f000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x1000
+#else
+#define CONFIG_SPL_BSS_START_ADDR	0xe631f000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x1000
+#endif
+#define CONFIG_SPL_STACK		0xe6304000
+#define CONFIG_SPL_MAX_SIZE		0x7000
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_CONS_SCIF2
+#define CONFIG_SH_SCIF_CLK_FREQ		65000000
+#endif
+
 #endif	/* __RCAR_GEN3_COMMON_H */