All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 00/16] rk3188 uboot support
@ 2017-02-03 16:09 Heiko Stuebner
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl Heiko Stuebner
                   ` (17 more replies)
  0 siblings, 18 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Hi,

this is meant as a status update and possible discussion for
the core parts if needed.

After talking with Simon and Tom the order is now also correct
with tpl -> spl -> uboot.


Status right now is:
- the full uboot still works
- the tpl/spl does start and is able to configure the ddr
  into a working state
- The jump spl -> bootrom -> uboot doesn't work though

On the other hand, Kever was able to make this work, booting
from nand when building the image with a very ancient tool.

All newer tools (including boot_merger.c from Rockchip's uboot)
do not produce working images. But it is possible to produce
a working sd-boot image using the proprietary 1st-stage loader.

See the temporary mkuboot script in the last patch, which can
create both types of images now (especially wrt. the needed
rc4 encryption of everything).

Combining this (it does work using some special tool), it looks
like there is still some minor glitch in the way we build the
spl image somewhere.


Heiko Stuebner (16):
  dm: allow limiting pre-reloc markings to spl or tpl
  rockchip: move bootrom helper compilation to a hidden option
  rockchip: mkimage: Allow encoding of loader code in spl images
  rockchip: mkimage: Add support rk3188 serial
  rockchip: serial: Adapt rockchip of-platdata driver for rk3188
  rockchip: rk3188: Add header files for PMU and GRF
  rockchip: rk3188: Add pinctrl driver
  rockchip: rk3188: Add sysreset driver
  rockchip: rk3188: Add rk3066/rk3188 clock bindings
  rockchip: rk3188: Add clock driver
  rockchip: rk3188: Add core devicetree files
  rockchip: rk3188: Add core support
  rockchip: rk3188: Add sdram driver
  rockchip: rk3188: Add main, spl and tpl boards
  rockchip: rk3188: Add Radxa Rock board
  Add a temporary script that can create a bootimage for rk3188

 arch/arm/dts/Makefile                           |   1 +
 arch/arm/dts/rk3188-radxarock.dts               | 382 +++++++++
 arch/arm/dts/rk3188.dtsi                        | 601 +++++++++++++++
 arch/arm/dts/rk3xxx.dtsi                        | 417 ++++++++++
 arch/arm/include/asm/arch-rockchip/cru_rk3188.h | 191 +++++
 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h |  22 +
 arch/arm/include/asm/arch-rockchip/grf_rk3188.h | 589 ++++++++++++++
 arch/arm/include/asm/arch-rockchip/pmu_rk3188.h |  36 +
 arch/arm/mach-rockchip/Kconfig                  |  20 +
 arch/arm/mach-rockchip/Makefile                 |  14 +-
 arch/arm/mach-rockchip/rk3188-board-spl.c       | 220 ++++++
 arch/arm/mach-rockchip/rk3188-board-tpl.c       |  87 +++
 arch/arm/mach-rockchip/rk3188-board.c           |  71 ++
 arch/arm/mach-rockchip/rk3188/Kconfig           |  35 +
 arch/arm/mach-rockchip/rk3188/Makefile          |  11 +
 arch/arm/mach-rockchip/rk3188/clk_rk3188.c      |  33 +
 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c    | 985 ++++++++++++++++++++++++
 arch/arm/mach-rockchip/rk3188/syscon_rk3188.c   |  55 ++
 board/radxa/rock/Kconfig                        |  15 +
 board/radxa/rock/MAINTAINERS                    |   6 +
 board/radxa/rock/Makefile                       |   7 +
 board/radxa/rock/rock.c                         |   7 +
 configs/rock_defconfig                          |  56 ++
 doc/driver-model/README.txt                     |   4 +
 drivers/clk/at91/pmc.c                          |   3 +-
 drivers/clk/rockchip/Makefile                   |   1 +
 drivers/clk/rockchip/clk_rk3188.c               | 523 +++++++++++++
 drivers/core/root.c                             |   2 +-
 drivers/core/util.c                             |  29 +
 drivers/pinctrl/Kconfig                         |   9 +
 drivers/pinctrl/pinctrl-uclass.c                |   3 +-
 drivers/pinctrl/rockchip/Makefile               |   1 +
 drivers/pinctrl/rockchip/pinctrl_rk3188.c       | 611 +++++++++++++++
 drivers/serial/serial_rockchip.c                |  19 +-
 drivers/sysreset/Makefile                       |   1 +
 drivers/sysreset/sysreset_rk3188.c              |  47 ++
 include/configs/rk3188_common.h                 | 125 +++
 include/configs/rock.h                          |  30 +
 include/dm/util.h                               |   2 +
 include/dt-bindings/clock/rk3066a-cru.h         |  32 +
 include/dt-bindings/clock/rk3188-cru-common.h   | 256 ++++++
 include/dt-bindings/clock/rk3188-cru.h          |  48 ++
 mkuboot                                         |  35 +
 scripts/Makefile.spl                            |   7 +-
 tools/dtoc/dtoc.py                              |   2 +
 tools/rkcommon.c                                |  34 +-
 tools/rkcommon.h                                |  22 +
 tools/rkimage.c                                 |   3 +
 tools/rksd.c                                    |   4 +
 tools/rkspi.c                                   |   4 +
 50 files changed, 5707 insertions(+), 11 deletions(-)
 create mode 100644 arch/arm/dts/rk3188-radxarock.dts
 create mode 100644 arch/arm/dts/rk3188.dtsi
 create mode 100644 arch/arm/dts/rk3xxx.dtsi
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3188.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rk3188.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/pmu_rk3188.h
 create mode 100644 arch/arm/mach-rockchip/rk3188-board-spl.c
 create mode 100644 arch/arm/mach-rockchip/rk3188-board-tpl.c
 create mode 100644 arch/arm/mach-rockchip/rk3188-board.c
 create mode 100644 arch/arm/mach-rockchip/rk3188/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rk3188/Makefile
 create mode 100644 arch/arm/mach-rockchip/rk3188/clk_rk3188.c
 create mode 100644 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
 create mode 100644 arch/arm/mach-rockchip/rk3188/syscon_rk3188.c
 create mode 100644 board/radxa/rock/Kconfig
 create mode 100644 board/radxa/rock/MAINTAINERS
 create mode 100644 board/radxa/rock/Makefile
 create mode 100644 board/radxa/rock/rock.c
 create mode 100644 configs/rock_defconfig
 create mode 100644 drivers/clk/rockchip/clk_rk3188.c
 create mode 100644 drivers/pinctrl/rockchip/pinctrl_rk3188.c
 create mode 100644 drivers/sysreset/sysreset_rk3188.c
 create mode 100644 include/configs/rk3188_common.h
 create mode 100644 include/configs/rock.h
 create mode 100644 include/dt-bindings/clock/rk3066a-cru.h
 create mode 100644 include/dt-bindings/clock/rk3188-cru-common.h
 create mode 100644 include/dt-bindings/clock/rk3188-cru.h
 create mode 100755 mkuboot

-- 
2.11.0

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:34   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 02/16] rockchip: move bootrom helper compilation to a hidden option Heiko Stuebner
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Right now the u-boot,dm-pre-reloc flag will make each marked node
always appear in both spl and tpl. But systems needing an additional
tpl might have special constraints for each, like the spl needing to
be very tiny.

So introduce two additional flags to mark nodes for only spl or tpl
environments and introduce a function dm_fdt_pre_reloc to automate
the necessary checks in code instances checking for pre-relocation
flags.

The behaviour of the original flag stays untouched and still marks
a node for both spl and tpl.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 doc/driver-model/README.txt      |  4 ++++
 drivers/clk/at91/pmc.c           |  3 ++-
 drivers/core/root.c              |  2 +-
 drivers/core/util.c              | 29 +++++++++++++++++++++++++++++
 drivers/pinctrl/pinctrl-uclass.c |  3 ++-
 include/dm/util.h                |  2 ++
 scripts/Makefile.spl             |  7 ++++++-
 tools/dtoc/dtoc.py               |  2 ++
 8 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index 1b5ccec4b2..af28b43c7b 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -825,6 +825,10 @@ drivers marked with DM_FLAG_PRE_RELOC or the device tree
 'u-boot,dm-pre-reloc' flag are initialised prior to relocation. This helps
 to reduce the driver model overhead.
 
+It is possible to limit this to specific relocation steps, by using
+the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags
+in the devicetree.
+
 Then post relocation we throw that away and re-init driver model again.
 For drivers which require some sort of continuity between pre- and
 post-relocation devices, we can provide access to the pre-relocation
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 76ba91af81..c098efc9f7 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -10,6 +10,7 @@
 #include <dm/device.h>
 #include <dm/lists.h>
 #include <dm/root.h>
+#include <dm/util.h>
 #include "pmc.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -56,7 +57,7 @@ int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
 	     offset > 0;
 	     offset = fdt_next_subnode(fdt, offset)) {
 		if (pre_reloc_only &&
-		    !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
+		    !dm_fdt_pre_reloc(fdt, offset))
 			continue;
 		/*
 		 * If this node has "compatible" property, this is not
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 9edfc1efb6..45f990ba9e 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -205,7 +205,7 @@ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
 	     offset > 0;
 	     offset = fdt_next_subnode(blob, offset)) {
 		if (pre_reloc_only &&
-		    !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
+		    !dm_fdt_pre_reloc(blob, offset))
 			continue;
 		if (!fdtdec_get_is_enabled(blob, offset)) {
 			dm_dbg("   - ignoring disabled device\n");
diff --git a/drivers/core/util.c b/drivers/core/util.c
index e01dd06d28..a67434b80d 100644
--- a/drivers/core/util.c
+++ b/drivers/core/util.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <libfdt.h>
 #include <vsprintf.h>
 
 void dm_warn(const char *fmt, ...)
@@ -35,3 +36,31 @@ int list_count_items(struct list_head *head)
 
 	return count;
 }
+
+int dm_fdt_pre_reloc(const void *blob, int offset)
+{
+	bool dm_spl, dm_tpl;
+
+	if (fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
+		return 1;
+
+	dm_spl = fdt_getprop(blob, offset, "u-boot,dm-spl", NULL);
+	dm_tpl = fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL);
+
+#ifdef CONFIG_TPL_BUILD
+	if (dm_tpl)
+		return 1;
+#elif defined(CONFIG_SPL_BUILD)
+	if (dm_spl)
+		return 1;
+#else
+	/*
+	 * In regular builds individual spl and tpl handling both
+	 * count as handled pre-relocation for later second init.
+	 */
+	if (dm_spl || dm_tpl)
+		return 1;
+#endif
+
+	return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 02ab9b4afd..9e0122906c 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -12,6 +12,7 @@
 #include <dm/lists.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass.h>
+#include <dm/util.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -131,7 +132,7 @@ static int pinconfig_post_bind(struct udevice *dev)
 	     offset > 0;
 	     offset = fdt_next_subnode(fdt, offset)) {
 		if (pre_reloc_only &&
-		    !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
+		    !dm_fdt_pre_reloc(fdt, offset))
 			continue;
 		/*
 		 * If this node has "compatible" property, this is not
diff --git a/include/dm/util.h b/include/dm/util.h
index 15daa3d19f..38c023ce66 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -48,4 +48,6 @@ static inline void dm_dump_devres(void)
 }
 #endif
 
+int dm_fdt_pre_reloc(const void *blob, int offset);
+
 #endif
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index c962bbca2c..60bd844e48 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -206,8 +206,13 @@ $(obj)/$(SPL_BIN)-pad.bin: $(obj)/$(SPL_BIN)
 # 'u-boot,dm-pre-reloc' property and thus are not needed by SPL. The second
 # pass removes various unused properties from the remaining nodes.
 # The output is typically a much smaller device tree file.
+ifeq ($(CONFIG_TPL_BUILD),y)
+fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-tpl
+else
+fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-spl
+endif
 quiet_cmd_fdtgrep = FDTGREP $@
-      cmd_fdtgrep = $(objtree)/tools/fdtgrep -b u-boot,dm-pre-reloc -RT $< \
+      cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
 		-n /chosen -O dtb | \
 	$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
 		$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py
index 11050b66f7..232f8ff739 100755
--- a/tools/dtoc/dtoc.py
+++ b/tools/dtoc/dtoc.py
@@ -30,6 +30,8 @@ PROP_IGNORE_LIST = [
     "status",
     'phandle',
     'u-boot,dm-pre-reloc',
+    'u-boot,dm-tpl',
+    'u-boot,dm-spl',
 ]
 
 # C type declarations for the tyues we support
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 02/16] rockchip: move bootrom helper compilation to a hidden option
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:34   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images Heiko Stuebner
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Right now the ROCKCHIP_SPL_BACK_TO_BROM option both triggers
compilation of the bootrom hook-code as well as enabling the
behaviour of loading the full uboot via the boot.

New added socs may always need the bootrom code, while still
being able to decide between loading uboot regularly or via
the bootrom separately.

So move the compilation of the bootrom code to a hidden option
that gets selected by ROCKCHIP_SPL_BACK_TO_BROM, but can also
be selected by other parts.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/arm/mach-rockchip/Kconfig  | 4 ++++
 arch/arm/mach-rockchip/Makefile | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 5c4a4c2291..a776df35f4 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -37,11 +37,15 @@ config ROCKCHIP_RK3399
 config ROCKCHIP_SPL_BACK_TO_BROM
 	bool "SPL returns to bootrom"
 	default y if ROCKCHIP_RK3036
+	select ROCKCHIP_BROM_HELPER
 	help
 	  Rockchip SoCs have ability to load SPL & U-Boot binary. If enabled,
           SPL will return to the boot rom, which will then load the U-Boot
           binary to keep going on.
 
+config ROCKCHIP_BROM_HELPER
+	bool
+
 config SPL_MMC_SUPPORT
 	default y if !ROCKCHIP_SPL_BACK_TO_BROM
 
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 6e79fed485..f9ccc9bb2c 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -7,7 +7,7 @@
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
-obj-$(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) += save_boot_param.o
+obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
 else
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl Heiko Stuebner
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 02/16] rockchip: move bootrom helper compilation to a hidden option Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-17  3:23   ` Kever Yang
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial Heiko Stuebner
                   ` (14 subsequent siblings)
  17 siblings, 2 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Rockchip SoCs allow the spl code to be rc4-encoded, not only the
image header, but only newer SoCs allow this encoding to be disabled.

The rk3188 is not part of those and requires its boot code to be
rc4-encoded with the regular key. So add the ability to do this
encoding via a setting on a per-soc basis when building spl images.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 tools/rkcommon.c | 33 +++++++++++++++++++++++++++++----
 tools/rkcommon.h | 22 ++++++++++++++++++++++
 tools/rkimage.c  |  3 +++
 tools/rksd.c     |  4 ++++
 tools/rkspi.c    |  4 ++++
 5 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 0a072aa83c..ed9b24137a 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -46,17 +46,19 @@ struct header0_info {
  * @imagename:		Image name(passed by "mkimage -n")
  * @spl_hdr:		Boot ROM requires a 4-bytes spl header
  * @spl_size:		Spl size(include extra 4-bytes spl header)
+ * @spl_rc4:		RC4 encode the SPL binary (same key as header)
  */
 struct spl_info {
 	const char *imagename;
 	const char *spl_hdr;
 	const uint32_t spl_size;
+	const bool spl_rc4;
 };
 
 static struct spl_info spl_infos[] = {
-	{ "rk3036", "RK30", 0x1000 },
-	{ "rk3288", "RK32", 0x8000 },
-	{ "rk3399", "RK33", 0x20000 },
+	{ "rk3036", "RK30", 0x1000, false },
+	{ "rk3288", "RK32", 0x8000, false },
+	{ "rk3399", "RK33", 0x20000, false },
 };
 
 static unsigned char rc4_key[16] = {
@@ -113,6 +115,16 @@ int rkcommon_get_spl_size(struct image_tool_params *params)
 	return info->spl_size;
 }
 
+bool rkcommon_need_rc4_spl(struct image_tool_params *params)
+{
+	struct spl_info *info = rkcommon_get_spl_info(params->imagename);
+
+	/*
+	 * info would not be NULL, because of we checked params before.
+	 */
+	return info->spl_rc4;
+}
+
 int rkcommon_set_header(void *buf, uint file_size,
 			struct image_tool_params *params)
 {
@@ -124,7 +136,7 @@ int rkcommon_set_header(void *buf, uint file_size,
 	memset(buf,  '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
 	hdr = (struct header0_info *)buf;
 	hdr->signature = RK_SIGNATURE;
-	hdr->disable_rc4 = 1;
+	hdr->disable_rc4 = !rkcommon_need_rc4_spl(params);
 	hdr->init_offset = RK_INIT_OFFSET;
 
 	hdr->init_size = (file_size + RK_BLK_SIZE - 1) / RK_BLK_SIZE;
@@ -135,3 +147,16 @@ int rkcommon_set_header(void *buf, uint file_size,
 
 	return 0;
 }
+
+void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size)
+{
+	unsigned int remaining = size;
+
+	while (remaining > 0) {
+		int step = (remaining > RK_BLK_SIZE) ? RK_BLK_SIZE : remaining;
+
+		rc4_encode(buf + offset, step, rc4_key);
+		offset += RK_BLK_SIZE;
+		remaining -= step;
+	}
+}
diff --git a/tools/rkcommon.h b/tools/rkcommon.h
index c69540f5f3..b4f6f327dc 100644
--- a/tools/rkcommon.h
+++ b/tools/rkcommon.h
@@ -55,4 +55,26 @@ int rkcommon_get_spl_size(struct image_tool_params *params);
 int rkcommon_set_header(void *buf, uint file_size,
 			struct image_tool_params *params);
 
+/**
+ * rkcommon_need_rc4_spl() - check if rc4 encoded spl is required
+ *
+ * Some socs cannot disable the rc4-encryption of the spl binary.
+ * rc4 encryption is disabled normally except on socs that cannot
+ * handle unencrypted binaries.
+ * @return true or false depending on rc4 being required.
+ */
+bool rkcommon_need_rc4_spl(struct image_tool_params *params);
+
+/**
+ * rkcommon_rc4_encode_spl() - encode the spl binary
+ *
+ * Encrypts the SPL binary using the generic rc4 key as required
+ * by some socs.
+ *
+ * @buf:	Pointer to the SPL data (header and SPL binary)
+ * @offset:	offset inside buf to start at
+ * @size:	number of bytes to encode
+ */
+void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size);
+
 #endif
diff --git a/tools/rkimage.c b/tools/rkimage.c
index ef31cb6944..44d098c775 100644
--- a/tools/rkimage.c
+++ b/tools/rkimage.c
@@ -28,6 +28,9 @@ static void rkimage_set_header(void *buf, struct stat *sbuf, int ifd,
 {
 	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
 	       RK_SPL_HDR_SIZE);
+
+	if (rkcommon_need_rc4_spl(params))
+		rkcommon_rc4_encode_spl(buf, 4, params->file_size);
 }
 
 static int rkimage_extract_subimage(void *buf, struct image_tool_params *params)
diff --git a/tools/rksd.c b/tools/rksd.c
index a2baa74d31..ff2233ff2d 100644
--- a/tools/rksd.c
+++ b/tools/rksd.c
@@ -41,6 +41,10 @@ static void rksd_set_header(void *buf,  struct stat *sbuf,  int ifd,
 
 	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
 	       RK_SPL_HDR_SIZE);
+
+	if (rkcommon_need_rc4_spl(params))
+		rkcommon_rc4_encode_spl(buf, RK_SPL_START - 4,
+					params->file_size - RK_SPL_START + 4);
 }
 
 static int rksd_extract_subimage(void *buf,  struct image_tool_params *params)
diff --git a/tools/rkspi.c b/tools/rkspi.c
index a0b0051d38..0271d2e817 100644
--- a/tools/rkspi.c
+++ b/tools/rkspi.c
@@ -48,6 +48,10 @@ static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd,
 	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
 	       RK_SPL_HDR_SIZE);
 
+	if (rkcommon_need_rc4_spl(params))
+		rkcommon_rc4_encode_spl(buf, RK_SPL_START - 4,
+					params->file_size - RK_SPL_START + 4);
+
 	/*
 	 * Spread the image out so we only use the first 2KB of each 4KB
 	 * region. This is a feature of the SPI format required by the Rockchip
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (2 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-17  3:29   ` Kever Yang
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 05/16] rockchip: serial: Adapt rockchip of-platdata driver for rk3188 Heiko Stuebner
                   ` (13 subsequent siblings)
  17 siblings, 2 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Add the entry for the rk3188 requiring rc4-encryption of the SPL.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 tools/rkcommon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index ed9b24137a..6595e02c1c 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -57,6 +57,7 @@ struct spl_info {
 
 static struct spl_info spl_infos[] = {
 	{ "rk3036", "RK30", 0x1000, false },
+	{ "rk3188", "RK31", 0x8000 - 0x800, true },
 	{ "rk3288", "RK32", 0x8000, false },
 	{ "rk3399", "RK33", 0x20000, false },
 };
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 05/16] rockchip: serial: Adapt rockchip of-platdata driver for rk3188
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (3 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 06/16] rockchip: rk3188: Add header files for PMU and GRF Heiko Stuebner
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Add necessary structs to have the driver also work for the serial
on the rk3188.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/serial/serial_rockchip.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/serial/serial_rockchip.c b/drivers/serial/serial_rockchip.c
index 6bac95a414..7e030a6aed 100644
--- a/drivers/serial/serial_rockchip.c
+++ b/drivers/serial/serial_rockchip.c
@@ -12,12 +12,19 @@
 #include <serial.h>
 #include <asm/arch/clock.h>
 
+#if defined(CONFIG_ROCKCHIP_RK3188)
+struct rockchip_uart_platdata {
+	struct dtd_rockchip_rk3188_uart dtplat;
+	struct ns16550_platdata plat;
+};
+struct dtd_rockchip_rk3188_uart *dtplat, s_dtplat;
+#elif defined(CONFIG_ROCKCHIP_RK3288)
 struct rockchip_uart_platdata {
 	struct dtd_rockchip_rk3288_uart dtplat;
 	struct ns16550_platdata plat;
 };
-
 struct dtd_rockchip_rk3288_uart *dtplat, s_dtplat;
+#endif
 
 static int rockchip_serial_probe(struct udevice *dev)
 {
@@ -32,6 +39,16 @@ static int rockchip_serial_probe(struct udevice *dev)
 	return ns16550_serial_probe(dev);
 }
 
+U_BOOT_DRIVER(rockchip_rk3188_uart) = {
+	.name	= "rockchip_rk3188_uart",
+	.id	= UCLASS_SERIAL,
+	.priv_auto_alloc_size = sizeof(struct NS16550),
+	.platdata_auto_alloc_size = sizeof(struct rockchip_uart_platdata),
+	.probe	= rockchip_serial_probe,
+	.ops	= &ns16550_serial_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
 U_BOOT_DRIVER(rockchip_rk3288_uart) = {
 	.name	= "rockchip_rk3288_uart",
 	.id	= UCLASS_SERIAL,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 06/16] rockchip: rk3188: Add header files for PMU and GRF
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (4 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 05/16] rockchip: serial: Adapt rockchip of-platdata driver for rk3188 Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 07/16] rockchip: rk3188: Add pinctrl driver Heiko Stuebner
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

PMU is the power management unit and GRF is the general register file. Both
are heavily used in U-Boot. Add header files with register definitions.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Simon Glass <sjg@chromium.org>
---
 arch/arm/include/asm/arch-rockchip/grf_rk3188.h | 589 ++++++++++++++++++++++++
 arch/arm/include/asm/arch-rockchip/pmu_rk3188.h |  36 ++
 2 files changed, 625 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rk3188.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/pmu_rk3188.h

diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3188.h b/arch/arm/include/asm/arch-rockchip/grf_rk3188.h
new file mode 100644
index 0000000000..ce7bac5338
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3188.h
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_GRF_RK3188_H
+#define _ASM_ARCH_GRF_RK3188_H
+
+struct rk3188_grf_gpio_lh {
+	u32 l;
+	u32 h;
+};
+
+struct rk3188_grf {
+	struct rk3188_grf_gpio_lh gpio_dir[4];
+	struct rk3188_grf_gpio_lh gpio_do[4];
+	struct rk3188_grf_gpio_lh gpio_en[4];
+
+	u32 reserved[2];
+	u32 gpio0c_iomux;
+	u32 gpio0d_iomux;
+
+	u32 gpio1a_iomux;
+	u32 gpio1b_iomux;
+	u32 gpio1c_iomux;
+	u32 gpio1d_iomux;
+
+	u32 gpio2a_iomux;
+	u32 gpio2b_iomux;
+	u32 gpio2c_iomux;
+	u32 gpio2d_iomux;
+
+	u32 gpio3a_iomux;
+	u32 gpio3b_iomux;
+	u32 gpio3c_iomux;
+	u32 gpio3d_iomux;
+
+	u32 soc_con0;
+	u32 soc_con1;
+	u32 soc_con2;
+	u32 soc_status0;
+
+	u32 busdmac_con[3];
+	u32 peridmac_con[4];
+
+	u32 cpu_con[6];
+	u32 reserved0[2];
+
+	u32 ddrc_con0;
+	u32 ddrc_stat;
+
+	u32 io_con[5];
+	u32 soc_status1;
+
+	u32 uoc0_con[4];
+	u32 uoc1_con[4];
+	u32 uoc2_con[2];
+	u32 reserved1;
+	u32 uoc3_con[2];
+	u32 hsic_stat;
+	u32 os_reg[8];
+
+	u32 gpio0_p[3];
+	u32 gpio1_p[3][4];
+
+	u32 flash_data_p;
+	u32 flash_cmd_p;
+};
+check_member(rk3188_grf, flash_cmd_p, 0x01a4);
+
+/* GRF_GPIO0D_IOMUX */
+enum {
+	GPIO0D7_SHIFT		= 14,
+	GPIO0D7_MASK		= 1,
+	GPIO0D7_GPIO		= 0,
+	GPIO0D7_SPI1_CSN0,
+
+	GPIO0D6_SHIFT		= 12,
+	GPIO0D6_MASK		= 1,
+	GPIO0D6_GPIO		= 0,
+	GPIO0D6_SPI1_CLK,
+
+	GPIO0D5_SHIFT		= 10,
+	GPIO0D5_MASK		= 1,
+	GPIO0D5_GPIO		= 0,
+	GPIO0D5_SPI1_TXD,
+
+	GPIO0D4_SHIFT		= 8,
+	GPIO0D4_MASK		= 1,
+	GPIO0D4_GPIO		= 0,
+	GPIO0D4_SPI0_RXD,
+
+	GPIO0D3_SHIFT		= 6,
+	GPIO0D3_MASK		= 3,
+	GPIO0D3_GPIO		= 0,
+	GPIO0D3_FLASH_CSN3,
+	GPIO0D3_EMMC_RSTN_OUT,
+
+	GPIO0D2_SHIFT		= 4,
+	GPIO0D2_MASK		= 3,
+	GPIO0D2_GPIO		= 0,
+	GPIO0D2_FLASH_CSN2,
+	GPIO0D2_EMMC_CMD,
+
+	GPIO0D1_SHIFT		= 2,
+	GPIO0D1_MASK		= 1,
+	GPIO0D1_GPIO		= 0,
+	GPIO0D1_FLASH_CSN1,
+
+	GPIO0D0_SHIFT		= 0,
+	GPIO0D0_MASK		= 3,
+	GPIO0D0_GPIO		= 0,
+	GPIO0D0_FLASH_DQS,
+	GPIO0D0_EMMC_CLKOUT
+};
+
+/* GRF_GPIO1A_IOMUX */
+enum {
+	GPIO1A7_SHIFT		= 14,
+	GPIO1A7_MASK		= 3,
+	GPIO1A7_GPIO		= 0,
+	GPIO1A7_UART1_RTS_N,
+	GPIO1A7_SPI0_CSN0,
+
+	GPIO1A6_SHIFT		= 12,
+	GPIO1A6_MASK		= 3,
+	GPIO1A6_GPIO		= 0,
+	GPIO1A6_UART1_CTS_N,
+	GPIO1A6_SPI0_CLK,
+
+	GPIO1A5_SHIFT		= 10,
+	GPIO1A5_MASK		= 3,
+	GPIO1A5_GPIO		= 0,
+	GPIO1A5_UART1_SOUT,
+	GPIO1A5_SPI0_TXD,
+
+	GPIO1A4_SHIFT		= 8,
+	GPIO1A4_MASK		= 3,
+	GPIO1A4_GPIO		= 0,
+	GPIO1A4_UART1_SIN,
+	GPIO1A4_SPI0_RXD,
+
+	GPIO1A3_SHIFT		= 6,
+	GPIO1A3_MASK		= 1,
+	GPIO1A3_GPIO		= 0,
+	GPIO1A3_UART0_RTS_N,
+
+	GPIO1A2_SHIFT		= 4,
+	GPIO1A2_MASK		= 1,
+	GPIO1A2_GPIO		= 0,
+	GPIO1A2_UART0_CTS_N,
+
+	GPIO1A1_SHIFT		= 2,
+	GPIO1A1_MASK		= 1,
+	GPIO1A1_GPIO		= 0,
+	GPIO1A1_UART0_SOUT,
+
+	GPIO1A0_SHIFT		= 0,
+	GPIO1A0_MASK		= 1,
+	GPIO1A0_GPIO		= 0,
+	GPIO1A0_UART0_SIN,
+};
+
+/* GRF_GPIO1B_IOMUX */
+enum {
+	GPIO1B7_SHIFT		= 14,
+	GPIO1B7_MASK		= 1,
+	GPIO1B7_GPIO		= 0,
+	GPIO1B7_SPI0_CSN1,
+
+	GPIO1B6_SHIFT		= 12,
+	GPIO1B6_MASK		= 3,
+	GPIO1B6_GPIO		= 0,
+	GPIO1B6_SPDIF_TX,
+	GPIO1B6_SPI1_CSN1,
+
+	GPIO1B5_SHIFT		= 10,
+	GPIO1B5_MASK		= 3,
+	GPIO1B5_GPIO		= 0,
+	GPIO1B5_UART3_RTS_N,
+	GPIO1B5_RESERVED,
+
+	GPIO1B4_SHIFT		= 8,
+	GPIO1B4_MASK		= 3,
+	GPIO1B4_GPIO		= 0,
+	GPIO1B4_UART3_CTS_N,
+	GPIO1B4_GPS_RFCLK,
+
+	GPIO1B3_SHIFT		= 6,
+	GPIO1B3_MASK		= 3,
+	GPIO1B3_GPIO		= 0,
+	GPIO1B3_UART3_SOUT,
+	GPIO1B3_GPS_SIG,
+
+	GPIO1B2_SHIFT		= 4,
+	GPIO1B2_MASK		= 3,
+	GPIO1B2_GPIO		= 0,
+	GPIO1B2_UART3_SIN,
+	GPIO1B2_GPS_MAG,
+
+	GPIO1B1_SHIFT		= 2,
+	GPIO1B1_MASK		= 3,
+	GPIO1B1_GPIO		= 0,
+	GPIO1B1_UART2_SOUT,
+	GPIO1B1_JTAG_TDO,
+
+	GPIO1B0_SHIFT		= 0,
+	GPIO1B0_MASK		= 3,
+	GPIO1B0_GPIO		= 0,
+	GPIO1B0_UART2_SIN,
+	GPIO1B0_JTAG_TDI,
+};
+
+/* GRF_GPIO1D_IOMUX */
+enum {
+	GPIO1D7_SHIFT		= 14,
+	GPIO1D7_MASK		= 1,
+	GPIO1D7_GPIO		= 0,
+	GPIO1D7_I2C4_SCL,
+
+	GPIO1D6_SHIFT		= 12,
+	GPIO1D6_MASK		= 1,
+	GPIO1D6_GPIO		= 0,
+	GPIO1D6_I2C4_SDA,
+
+	GPIO1D5_SHIFT		= 10,
+	GPIO1D5_MASK		= 1,
+	GPIO1D5_GPIO		= 0,
+	GPIO1D5_I2C2_SCL,
+
+	GPIO1D4_SHIFT		= 8,
+	GPIO1D4_MASK		= 1,
+	GPIO1D4_GPIO		= 0,
+	GPIO1D4_I2C2_SDA,
+
+	GPIO1D3_SHIFT		= 6,
+	GPIO1D3_MASK		= 1,
+	GPIO1D3_GPIO		= 0,
+	GPIO1D3_I2C1_SCL,
+
+	GPIO1D2_SHIFT		= 4,
+	GPIO1D2_MASK		= 1,
+	GPIO1D2_GPIO		= 0,
+	GPIO1D2_I2C1_SDA,
+
+	GPIO1D1_SHIFT		= 2,
+	GPIO1D1_MASK		= 1,
+	GPIO1D1_GPIO		= 0,
+	GPIO1D1_I2C0_SCL,
+
+	GPIO1D0_SHIFT		= 0,
+	GPIO1D0_MASK		= 1,
+	GPIO1D0_GPIO		= 0,
+	GPIO1D0_I2C0_SDA,
+};
+
+/* GRF_GPIO3A_IOMUX */
+enum {
+	GPIO3A7_SHIFT		= 14,
+	GPIO3A7_MASK		= 1,
+	GPIO3A7_GPIO		= 0,
+	GPIO3A7_SDMMC0_DATA3,
+
+	GPIO3A6_SHIFT		= 12,
+	GPIO3A6_MASK		= 1,
+	GPIO3A6_GPIO		= 0,
+	GPIO3A6_SDMMC0_DATA2,
+
+	GPIO3A5_SHIFT		= 10,
+	GPIO3A5_MASK		= 1,
+	GPIO3A5_GPIO		= 0,
+	GPIO3A5_SDMMC0_DATA1,
+
+	GPIO3A4_SHIFT		= 8,
+	GPIO3A4_MASK		= 1,
+	GPIO3A4_GPIO		= 0,
+	GPIO3A4_SDMMC0_DATA0,
+
+	GPIO3A3_SHIFT		= 6,
+	GPIO3A3_MASK		= 1,
+	GPIO3A3_GPIO		= 0,
+	GPIO3A3_SDMMC0_CMD,
+
+	GPIO3A2_SHIFT		= 4,
+	GPIO3A2_MASK		= 1,
+	GPIO3A2_GPIO		= 0,
+	GPIO3A2_SDMMC0_CLKOUT,
+
+	GPIO3A1_SHIFT		= 2,
+	GPIO3A1_MASK		= 1,
+	GPIO3A1_GPIO		= 0,
+	GPIO3A1_SDMMC0_PWREN,
+
+	GPIO3A0_SHIFT		= 0,
+	GPIO3A0_MASK		= 1,
+	GPIO3A0_GPIO		= 0,
+	GPIO3A0_SDMMC0_RSTN,
+};
+
+/* GRF_GPIO3B_IOMUX */
+enum {
+	GPIO3B7_SHIFT		= 14,
+	GPIO3B7_MASK		= 3,
+	GPIO3B7_GPIO		= 0,
+	GPIO3B7_CIF_DATA11,
+	GPIO3B7_I2C3_SCL,
+
+	GPIO3B6_SHIFT		= 12,
+	GPIO3B6_MASK		= 3,
+	GPIO3B6_GPIO		= 0,
+	GPIO3B6_CIF_DATA10,
+	GPIO3B6_I2C3_SDA,
+
+	GPIO3B5_SHIFT		= 10,
+	GPIO3B5_MASK		= 3,
+	GPIO3B5_GPIO		= 0,
+	GPIO3B5_CIF_DATA1,
+	GPIO3B5_HSADC_DATA9,
+
+	GPIO3B4_SHIFT		= 8,
+	GPIO3B4_MASK		= 3,
+	GPIO3B4_GPIO		= 0,
+	GPIO3B4_CIF_DATA0,
+	GPIO3B4_HSADC_DATA8,
+
+	GPIO3B3_SHIFT		= 6,
+	GPIO3B3_MASK		= 1,
+	GPIO3B3_GPIO		= 0,
+	GPIO3B3_CIF_CLKOUT,
+
+	GPIO3B2_SHIFT		= 4,
+	GPIO3B2_MASK		= 1,
+	GPIO3B2_GPIO		= 0,
+	/* no muxes */
+
+	GPIO3B1_SHIFT		= 2,
+	GPIO3B1_MASK		= 1,
+	GPIO3B1_GPIO		= 0,
+	GPIO3B1_SDMMC0_WRITE_PRT,
+
+	GPIO3B0_SHIFT		= 0,
+	GPIO3B0_MASK		= 1,
+	GPIO3B0_GPIO		= 0,
+	GPIO3B0_SDMMC_DETECT_N,
+};
+
+/* GRF_GPIO3C_IOMUX */
+enum {
+	GPIO3C7_SHIFT		= 14,
+	GPIO3C7_MASK		= 3,
+	GPIO3C7_GPIO		= 0,
+	GPIO3C7_SDMMC1_WRITE_PRT,
+	GPIO3C7_RMII_CRS_DVALID,
+	GPIO3C7_RESERVED,
+
+	GPIO3C6_SHIFT		= 12,
+	GPIO3C6_MASK		= 3,
+	GPIO3C6_GPIO		= 0,
+	GPIO3C6_SDMMC1_DECTN,
+	GPIO3C6_RMII_RX_ERR,
+	GPIO3C6_RESERVED,
+
+	GPIO3C5_SHIFT		= 10,
+	GPIO3C5_MASK		= 3,
+	GPIO3C5_GPIO		= 0,
+	GPIO3C5_SDMMC1_CLKOUT,
+	GPIO3C5_RMII_CLKOUT,
+	GPIO3C5_RMII_CLKIN,
+
+	GPIO3C4_SHIFT		= 8,
+	GPIO3C4_MASK		= 3,
+	GPIO3C4_GPIO		= 0,
+	GPIO3C4_SDMMC1_DATA3,
+	GPIO3C4_RMII_RXD1,
+	GPIO3C4_RESERVED,
+
+	GPIO3C3_SHIFT		= 6,
+	GPIO3C3_MASK		= 3,
+	GPIO3C3_GPIO		= 0,
+	GPIO3C3_SDMMC1_DATA2,
+	GPIO3C3_RMII_RXD0,
+	GPIO3C3_RESERVED,
+
+	GPIO3C2_SHIFT		= 4,
+	GPIO3C2_MASK		= 3,
+	GPIO3C2_GPIO		= 0,
+	GPIO3C2_SDMMC1_DATA1,
+	GPIO3C2_RMII_TXD0,
+	GPIO3C2_RESERVED,
+
+	GPIO3C1_SHIFT		= 2,
+	GPIO3C1_MASK		= 3,
+	GPIO3C1_GPIO		= 0,
+	GPIO3C1_SDMMC1_DATA0,
+	GPIO3C1_RMII_TXD1,
+	GPIO3C1_RESERVED,
+
+	GPIO3C0_SHIFT		= 0,
+	GPIO3C0_MASK		= 3,
+	GPIO3C0_GPIO		= 0,
+	GPIO3C0_SDMMC1_CMD,
+	GPIO3C0_RMII_TX_EN,
+	GPIO3C0_RESERVED,
+};
+
+/* GRF_GPIO3D_IOMUX */
+enum {
+	GPIO3D6_SHIFT		= 12,
+	GPIO3D6_MASK		= 3,
+	GPIO3D6_GPIO		= 0,
+	GPIO3D6_PWM_3,
+	GPIO3D6_JTAG_TMS,
+	GPIO3D6_HOST_DRV_VBUS,
+
+	GPIO3D5_SHIFT		= 10,
+	GPIO3D5_MASK		= 3,
+	GPIO3D5_GPIO		= 0,
+	GPIO3D5_PWM_2,
+	GPIO3D5_JTAG_TCK,
+	GPIO3D5_OTG_DRV_VBUS,
+
+	GPIO3D4_SHIFT		= 8,
+	GPIO3D4_MASK		= 3,
+	GPIO3D4_GPIO		= 0,
+	GPIO3D4_PWM_1,
+	GPIO3D4_JTAG_TRSTN,
+
+	GPIO3D3_SHIFT		= 6,
+	GPIO3D3_MASK		= 3,
+	GPIO3D3_GPIO		= 0,
+	GPIO3D3_PWM_0,
+
+	GPIO3D2_SHIFT		= 4,
+	GPIO3D2_MASK		= 3,
+	GPIO3D2_GPIO		= 0,
+	GPIO3D2_SDMMC1_INT_N,
+
+	GPIO3D1_SHIFT		= 2,
+	GPIO3D1_MASK		= 3,
+	GPIO3D1_GPIO		= 0,
+	GPIO3D1_SDMMC1_BACKEND_PWR,
+	GPIO3D1_MII_MDCLK,
+
+	GPIO3D0_SHIFT		= 0,
+	GPIO3D0_MASK		= 3,
+	GPIO3D0_GPIO		= 0,
+	GPIO3D0_SDMMC1_PWR_EN,
+	GPIO3D0_MII_MD,
+};
+
+/* GRF_SOC_CON0 */
+enum {
+	HSADC_CLK_DIR_SHIFT	= 15,
+	HSADC_CLK_DIR_MASK	= 1,
+
+	HSADC_SEL_SHIFT		= 14,
+	HSADC_SEL_MASK		= 1,
+
+	NOC_REMAP_SHIFT		= 12,
+	NOC_REMAP_MASK		= 1,
+
+	EMMC_FLASH_SEL_SHIFT	= 11,
+	EMMC_FLASH_SEL_MASK	= 1,
+
+	TZPC_REVISION_SHIFT	= 7,
+	TZPC_REVISION_MASK	= 0xf,
+
+	L2CACHE_ACC_SHIFT	= 5,
+	L2CACHE_ACC_MASK	= 3,
+
+	L2RD_WAIT_SHIFT		= 3,
+	L2RD_WAIT_MASK		= 3,
+
+	IMEMRD_WAIT_SHIFT	= 1,
+	IMEMRD_WAIT_MASK	= 3,
+};
+
+/* GRF_SOC_CON1 */
+enum {
+	RKI2C4_SEL_SHIFT	= 15,
+	RKI2C4_SEL_MASK		= 1,
+
+	RKI2C3_SEL_SHIFT	= 14,
+	RKI2C3_SEL_MASK		= 1,
+
+	RKI2C2_SEL_SHIFT	= 13,
+	RKI2C2_SEL_MASK		= 1,
+
+	RKI2C1_SEL_SHIFT	= 12,
+	RKI2C1_SEL_MASK		= 1,
+
+	RKI2C0_SEL_SHIFT	= 11,
+	RKI2C0_SEL_MASK		= 1,
+
+	VCODEC_SEL_SHIFT	= 10,
+	VCODEC_SEL_MASK		= 1,
+
+	PERI_EMEM_PAUSE_SHIFT	= 9,
+	PERI_EMEM_PAUSE_MASK	= 1,
+
+	PERI_USB_PAUSE_SHIFT	= 8,
+	PERI_USB_PAUSE_MASK	= 1,
+
+	SMC_MUX_MODE_0_SHIFT	= 6,
+	SMC_MUX_MODE_0_MASK	= 1,
+
+	SMC_SRAM_MW_0_SHIFT	= 4,
+	SMC_SRAM_MW_0_MASK	= 3,
+
+	SMC_REMAP_0_SHIFT	= 3,
+	SMC_REMAP_0_MASK	= 1,
+
+	SMC_A_GT_M0_SYNC_SHIFT	= 2,
+	SMC_A_GT_M0_SYNC_MASK	= 1,
+
+	EMAC_SPEED_SHIFT	= 1,
+	EMAC_SPEEC_MASK		= 1,
+
+	EMAC_MODE_SHIFT		= 0,
+	EMAC_MODE_MASK		= 1,
+};
+
+/* GRF_SOC_CON2 */
+enum {
+	SDIO_CLK_OUT_SR_SHIFT	= 15,
+	SDIO_CLK_OUT_SR_MASK	= 1,
+
+	MEM_EMA_L2C_SHIFT	= 11,
+	MEM_EMA_L2C_MASK	= 7,
+
+	MEM_EMA_A9_SHIFT	= 8,
+	MEM_EMA_A9_MASK		= 7,
+
+	MSCH4_MAINDDR3_SHIFT	= 7,
+	MSCH4_MAINDDR3_MASK	= 1,
+	MSCH4_MAINDDR3_DDR3	= 1,
+
+	EMAC_NEWRCV_EN_SHIFT	= 6,
+	EMAC_NEWRCV_EN_MASK	= 1,
+
+	SW_ADDR15_EN_SHIFT	= 5,
+	SW_ADDR15_EN_MASK	= 1,
+
+	SW_ADDR16_EN_SHIFT	= 4,
+	SW_ADDR16_EN_MASK	= 1,
+
+	SW_ADDR17_EN_SHIFT	= 3,
+	SW_ADDR17_EN_MASK	= 1,
+
+	BANK2_TO_RANK_EN_SHIFT	= 2,
+	BANK2_TO_RANK_EN_MASK	= 1,
+
+	RANK_TO_ROW15_EN_SHIFT	= 1,
+	RANK_TO_ROW15_EN_MASK	= 1,
+
+	UPCTL_C_ACTIVE_IN_SHIFT = 0,
+	UPCTL_C_ACTIVE_IN_MASK	= 1,
+	UPCTL_C_ACTIVE_IN_MAY	= 0,
+	UPCTL_C_ACTIVE_IN_WILL,
+};
+
+/* GRF_DDRC_CON0 */
+enum {
+	DDR_16BIT_EN_SHIFT	= 15,
+	DDR_16BIT_EN_MASK	= 1,
+
+	DTO_LB_SHIFT		= 11,
+	DTO_LB_MASK		= 3,
+
+	DTO_TE_SHIFT		= 9,
+	DTO_TE_MASK		= 3,
+
+	DTO_PDR_SHIFT		= 7,
+	DTO_PDR_MASK		= 3,
+
+	DTO_PDD_SHIFT		= 5,
+	DTO_PDD_MASK		= 3,
+
+	DTO_IOM_SHIFT		= 3,
+	DTO_IOM_MASK		= 3,
+
+	DTO_OE_SHIFT		= 1,
+	DTO_OE_MASK		= 3,
+
+	ATO_AE_SHIFT		= 0,
+	ATO_AE_MASK		= 1,
+};
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/pmu_rk3188.h b/arch/arm/include/asm/arch-rockchip/pmu_rk3188.h
new file mode 100644
index 0000000000..d3feac3832
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/pmu_rk3188.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_PMU_RK3188_H
+#define _ASM_ARCH_PMU_RK3188_H
+
+struct rk3188_pmu {
+	u32 wakeup_cfg[2];
+	u32 pwrdn_con;
+	u32 pwrdn_st;
+
+	u32 int_con;
+	u32 int_st;
+	u32 misc_con;
+
+	u32 osc_cnt;
+	u32 pll_cnt;
+	u32 pmu_cnt;
+	u32 ddrio_pwron_cnt;
+	u32 wakeup_rst_clr_cnt;
+	u32 scu_pwrdwn_cnt;
+	u32 scu_pwrup_cnt;
+	u32 misc_con1;
+	u32 gpio0_con;
+
+	u32 sys_reg[4];
+	u32 reserved0[4];
+	u32 stop_int_dly;
+	u32 gpio0_p[2];
+};
+check_member(rk3188_pmu, gpio0_p[1], 0x0068);
+
+#endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 07/16] rockchip: rk3188: Add pinctrl driver
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (5 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 06/16] rockchip: rk3188: Add header files for PMU and GRF Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 08/16] rockchip: rk3188: Add sysreset driver Heiko Stuebner
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Add a driver which supports pin multiplexing setup for the most commonly
used peripherals.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Simon Glass <sjg@chromium.org>
---
 drivers/pinctrl/Kconfig                   |   9 +
 drivers/pinctrl/rockchip/Makefile         |   1 +
 drivers/pinctrl/rockchip/pinctrl_rk3188.c | 611 ++++++++++++++++++++++++++++++
 3 files changed, 621 insertions(+)
 create mode 100644 drivers/pinctrl/rockchip/pinctrl_rk3188.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index efcb4c0003..c68860c092 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -132,6 +132,15 @@ config ROCKCHIP_RK3036_PINCTRL
 	  definitions and pin control functions for each available multiplex
 	  function.
 
+config ROCKCHIP_RK3188_PINCTRL
+	bool "Rockchip pin control driver"
+	depends on DM
+	help
+	  Support pin multiplexing control on Rockchip rk3188 SoCs. The driver
+	  is controlled by a device tree node which contains both the GPIO
+	  definitions and pin control functions for each available multiplex
+	  function.
+
 config ROCKCHIP_RK3288_PINCTRL
 	bool "Rockchip pin control driver"
 	depends on DM
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 805c833ec9..cc99aeebb5 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -6,5 +6,6 @@
 #
 
 obj-$(CONFIG_ROCKCHIP_RK3036_PINCTRL) += pinctrl_rk3036.o
+obj-$(CONFIG_ROCKCHIP_RK3188_PINCTRL) += pinctrl_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK3288_PINCTRL) += pinctrl_rk3288.o
 obj-$(CONFIG_ROCKCHIP_RK3399_PINCTRL) += pinctrl_rk3399.o
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3188.c b/drivers/pinctrl/rockchip/pinctrl_rk3188.c
new file mode 100644
index 0000000000..ef94dab210
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3188.c
@@ -0,0 +1,611 @@
+/*
+ * Pinctrl driver for Rockchip RK3188 SoCs
+ * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3188.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3188.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rk3188_pinctrl_priv {
+	struct rk3188_grf *grf;
+	struct rk3188_pmu *pmu;
+	int num_banks;
+};
+
+/**
+ * Encode variants of iomux registers into a type variable
+ */
+#define IOMUX_GPIO_ONLY		BIT(0)
+
+/**
+ * @type: iomux variant using IOMUX_* constants
+ * @offset: if initialized to -1 it will be autocalculated, by specifying
+ *	    an initial offset value the relevant source offset can be reset
+ *	    to a new value for autocalculating the following iomux registers.
+ */
+struct rockchip_iomux {
+	u8 type;
+	s16 offset;
+};
+
+/**
+ * @reg: register offset of the gpio bank
+ * @nr_pins: number of pins in this bank
+ * @bank_num: number of the bank, to account for holes
+ * @name: name of the bank
+ * @iomux: array describing the 4 iomux sources of the bank
+ */
+struct rockchip_pin_bank {
+	u16 reg;
+	u8 nr_pins;
+	u8 bank_num;
+	char *name;
+	struct rockchip_iomux iomux[4];
+};
+
+#define PIN_BANK(id, pins, label)			\
+	{						\
+		.bank_num	= id,			\
+		.nr_pins	= pins,			\
+		.name		= label,		\
+		.iomux		= {			\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+			{ .offset = -1 },		\
+		},					\
+	}
+
+#define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+	}
+
+#ifndef CONFIG_SPL_BUILD
+static struct rockchip_pin_bank rk3188_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0),
+	PIN_BANK(1, 32, "gpio1"),
+	PIN_BANK(2, 32, "gpio2"),
+	PIN_BANK(3, 32, "gpio3"),
+};
+#endif
+
+static void pinctrl_rk3188_pwm_config(struct rk3188_grf *grf, int pwm_id)
+{
+	switch (pwm_id) {
+	case PERIPH_ID_PWM0:
+		rk_clrsetreg(&grf->gpio3d_iomux, GPIO3D3_MASK << GPIO3D3_SHIFT,
+			     GPIO3D3_PWM_0 << GPIO3D3_SHIFT);
+		break;
+	case PERIPH_ID_PWM1:
+		rk_clrsetreg(&grf->gpio3d_iomux, GPIO3D4_MASK << GPIO3D4_SHIFT,
+			     GPIO3D4_PWM_1 << GPIO3D4_SHIFT);
+		break;
+	case PERIPH_ID_PWM2:
+		rk_clrsetreg(&grf->gpio3d_iomux, GPIO3D5_MASK << GPIO3D5_SHIFT,
+			     GPIO3D5_PWM_2 << GPIO3D5_SHIFT);
+		break;
+	case PERIPH_ID_PWM3:
+		rk_clrsetreg(&grf->gpio3d_iomux, GPIO3D6_MASK << GPIO3D6_SHIFT,
+			     GPIO3D6_PWM_3 << GPIO3D6_SHIFT);
+		break;
+	default:
+		debug("pwm id = %d iomux error!\n", pwm_id);
+		break;
+	}
+}
+
+static void pinctrl_rk3188_i2c_config(struct rk3188_grf *grf,
+				      struct rk3188_pmu *pmu, int i2c_id)
+{
+	switch (i2c_id) {
+	case PERIPH_ID_I2C0:
+		rk_clrsetreg(&grf->gpio1d_iomux,
+				GPIO1D1_MASK << GPIO1D1_SHIFT |
+				GPIO1D0_MASK << GPIO1D0_SHIFT,
+				GPIO1D1_I2C0_SCL << GPIO1D1_SHIFT |
+				GPIO1D0_I2C0_SDA << GPIO1D0_SHIFT);
+		/* enable new i2c controller */
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C0_SEL_SHIFT,
+					     1 << RKI2C0_SEL_SHIFT);
+		break;
+	case PERIPH_ID_I2C1:
+		rk_clrsetreg(&grf->gpio1d_iomux,
+				GPIO1D3_MASK << GPIO1D3_SHIFT |
+				GPIO1D2_MASK << GPIO1D2_SHIFT,
+				GPIO1D3_I2C1_SCL << GPIO1D2_SHIFT |
+				GPIO1D2_I2C1_SDA << GPIO1D2_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C1_SEL_SHIFT,
+					     1 << RKI2C1_SEL_SHIFT);
+		break;
+	case PERIPH_ID_I2C2:
+		rk_clrsetreg(&grf->gpio1d_iomux,
+				GPIO1D5_MASK << GPIO1D5_SHIFT |
+				GPIO1D4_MASK << GPIO1D4_SHIFT,
+				GPIO1D5_I2C2_SCL << GPIO1D5_SHIFT |
+				GPIO1D4_I2C2_SDA << GPIO1D4_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C2_SEL_SHIFT,
+					     1 << RKI2C2_SEL_SHIFT);
+		break;
+	case PERIPH_ID_I2C3:
+		rk_clrsetreg(&grf->gpio3b_iomux,
+				GPIO3B7_MASK << GPIO3B7_SHIFT |
+				GPIO3B6_MASK << GPIO3B6_SHIFT,
+				GPIO3B7_I2C3_SCL << GPIO3B7_SHIFT |
+				GPIO3B6_I2C3_SDA << GPIO3B6_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C3_SEL_SHIFT,
+					     1 << RKI2C3_SEL_SHIFT);
+		break;
+	case PERIPH_ID_I2C4:
+		rk_clrsetreg(&grf->gpio1d_iomux,
+				GPIO1D7_MASK << GPIO1D7_SHIFT |
+				GPIO1D6_MASK << GPIO1D6_SHIFT,
+				GPIO1D7_I2C4_SCL << GPIO1D7_SHIFT |
+				GPIO1D6_I2C4_SDA << GPIO1D6_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C4_SEL_SHIFT,
+					     1 << RKI2C4_SEL_SHIFT);
+		break;
+	default:
+		debug("i2c id = %d iomux error!\n", i2c_id);
+		break;
+	}
+}
+
+static int pinctrl_rk3188_spi_config(struct rk3188_grf *grf,
+				     enum periph_id spi_id, int cs)
+{
+	switch (spi_id) {
+	case PERIPH_ID_SPI0:
+		switch (cs) {
+		case 0:
+			rk_clrsetreg(&grf->gpio1a_iomux,
+				     GPIO1A7_MASK << GPIO1A7_SHIFT,
+				     GPIO1A7_SPI0_CSN0 << GPIO1A7_SHIFT);
+			break;
+		case 1:
+			rk_clrsetreg(&grf->gpio1b_iomux,
+				     GPIO1B7_MASK << GPIO1B7_SHIFT,
+				     GPIO1B7_SPI0_CSN1 << GPIO1B7_SHIFT);
+			break;
+		default:
+			goto err;
+		}
+		rk_clrsetreg(&grf->gpio1a_iomux,
+			     GPIO1A4_MASK << GPIO1A4_SHIFT |
+			     GPIO1A5_MASK << GPIO1A5_SHIFT |
+			     GPIO1A6_MASK << GPIO1A6_SHIFT,
+			     GPIO1A4_SPI0_RXD << GPIO1A4_SHIFT |
+			     GPIO1A5_SPI0_TXD << GPIO1A5_SHIFT |
+			     GPIO1A6_SPI0_CLK << GPIO1A6_SHIFT);
+		break;
+	case PERIPH_ID_SPI1:
+		switch (cs) {
+		case 0:
+			rk_clrsetreg(&grf->gpio0d_iomux,
+				     GPIO0D7_MASK << GPIO0D7_SHIFT,
+				     GPIO0D7_SPI1_CSN0 << GPIO0D7_SHIFT);
+			break;
+		case 1:
+			rk_clrsetreg(&grf->gpio1b_iomux,
+				     GPIO1B6_MASK << GPIO1B6_SHIFT,
+				     GPIO1B6_SPI1_CSN1 << GPIO1B6_SHIFT);
+			break;
+		default:
+			goto err;
+		}
+		rk_clrsetreg(&grf->gpio0d_iomux,
+			     GPIO0D4_MASK << GPIO0D4_SHIFT |
+			     GPIO0D5_MASK << GPIO0D5_SHIFT |
+			     GPIO0D6_MASK << GPIO0D6_SHIFT,
+			     GPIO0D4_SPI0_RXD << GPIO0D4_SHIFT |
+			     GPIO0D5_SPI1_TXD << GPIO0D5_SHIFT |
+			     GPIO0D6_SPI1_CLK << GPIO0D6_SHIFT);
+		break;
+	default:
+		goto err;
+	}
+
+	return 0;
+err:
+	debug("rkspi: periph%d cs=%d not supported", spi_id, cs);
+	return -ENOENT;
+}
+
+static void pinctrl_rk3188_uart_config(struct rk3188_grf *grf, int uart_id)
+{
+	switch (uart_id) {
+	case PERIPH_ID_UART0:
+		rk_clrsetreg(&grf->gpio1a_iomux,
+			     GPIO1A3_MASK << GPIO1A3_SHIFT |
+			     GPIO1A2_MASK << GPIO1A2_SHIFT |
+			     GPIO1A1_MASK << GPIO1A1_SHIFT |
+			     GPIO1A0_MASK << GPIO1A0_SHIFT,
+			     GPIO1A3_UART0_RTS_N << GPIO1A3_SHIFT |
+			     GPIO1A2_UART0_CTS_N << GPIO1A2_SHIFT |
+			     GPIO1A1_UART0_SOUT << GPIO1A1_SHIFT |
+			     GPIO1A0_UART0_SIN << GPIO1A0_SHIFT);
+		break;
+	case PERIPH_ID_UART1:
+		rk_clrsetreg(&grf->gpio1a_iomux,
+			     GPIO1A7_MASK << GPIO1A7_SHIFT |
+			     GPIO1A6_MASK << GPIO1A6_SHIFT |
+			     GPIO1A5_MASK << GPIO1A5_SHIFT |
+			     GPIO1A4_MASK << GPIO1A4_SHIFT,
+			     GPIO1A7_UART1_RTS_N << GPIO1A7_SHIFT |
+			     GPIO1A6_UART1_CTS_N << GPIO1A6_SHIFT |
+			     GPIO1A5_UART1_SOUT << GPIO1A5_SHIFT |
+			     GPIO1A4_UART1_SIN << GPIO1A4_SHIFT);
+		break;
+	case PERIPH_ID_UART2:
+		rk_clrsetreg(&grf->gpio1b_iomux,
+			     GPIO1B1_MASK << GPIO1B1_SHIFT |
+			     GPIO1B0_MASK << GPIO1B0_SHIFT,
+			     GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
+			     GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
+		break;
+	case PERIPH_ID_UART3:
+		rk_clrsetreg(&grf->gpio1b_iomux,
+			     GPIO1B5_MASK << GPIO1B5_SHIFT |
+			     GPIO1B4_MASK << GPIO1B4_SHIFT |
+			     GPIO1B3_MASK << GPIO1B3_SHIFT |
+			     GPIO1B2_MASK << GPIO1B2_SHIFT,
+			     GPIO1B5_UART3_RTS_N << GPIO1B5_SHIFT |
+			     GPIO1B4_UART3_CTS_N << GPIO1B4_SHIFT |
+			     GPIO1B3_UART3_SOUT << GPIO1B3_SHIFT |
+			     GPIO1B2_UART3_SIN << GPIO1B2_SHIFT);
+		break;
+	default:
+		debug("uart id = %d iomux error!\n", uart_id);
+		break;
+	}
+}
+
+static void pinctrl_rk3188_sdmmc_config(struct rk3188_grf *grf, int mmc_id)
+{
+	switch (mmc_id) {
+	case PERIPH_ID_EMMC:
+		rk_clrsetreg(&grf->soc_con0, 1 << EMMC_FLASH_SEL_SHIFT,
+					     1 << EMMC_FLASH_SEL_SHIFT);
+		rk_clrsetreg(&grf->gpio0d_iomux,
+			     GPIO0D2_MASK << GPIO0D2_SHIFT |
+			     GPIO0D0_MASK << GPIO0D0_SHIFT,
+			     GPIO0D2_EMMC_CMD << GPIO0D2_SHIFT |
+			     GPIO0D0_EMMC_CLKOUT << GPIO0D0_SHIFT);
+		break;
+	case PERIPH_ID_SDCARD:
+		rk_clrsetreg(&grf->gpio3b_iomux,
+			     GPIO3B0_MASK << GPIO3B0_SHIFT,
+			     GPIO3B0_SDMMC_DETECT_N << GPIO3B0_SHIFT);
+		rk_clrsetreg(&grf->gpio3a_iomux,
+			     GPIO3A7_MASK << GPIO3A7_SHIFT |
+			     GPIO3A6_MASK << GPIO3A6_SHIFT |
+			     GPIO3A5_MASK << GPIO3A5_SHIFT |
+			     GPIO3A4_MASK << GPIO3A4_SHIFT |
+			     GPIO3A3_MASK << GPIO3A3_SHIFT |
+			     GPIO3A3_MASK << GPIO3A2_SHIFT,
+			     GPIO3A7_SDMMC0_DATA3 << GPIO3A7_SHIFT |
+			     GPIO3A6_SDMMC0_DATA2 << GPIO3A6_SHIFT |
+			     GPIO3A5_SDMMC0_DATA1 << GPIO3A5_SHIFT |
+			     GPIO3A4_SDMMC0_DATA0 << GPIO3A4_SHIFT |
+			     GPIO3A3_SDMMC0_CMD << GPIO3A3_SHIFT |
+			     GPIO3A2_SDMMC0_CLKOUT << GPIO3A2_SHIFT);
+		break;
+	default:
+		debug("mmc id = %d iomux error!\n", mmc_id);
+		break;
+	}
+}
+
+static int rk3188_pinctrl_request(struct udevice *dev, int func, int flags)
+{
+	struct rk3188_pinctrl_priv *priv = dev_get_priv(dev);
+
+	debug("%s: func=%x, flags=%x\n", __func__, func, flags);
+	switch (func) {
+	case PERIPH_ID_PWM0:
+	case PERIPH_ID_PWM1:
+	case PERIPH_ID_PWM2:
+	case PERIPH_ID_PWM3:
+	case PERIPH_ID_PWM4:
+		pinctrl_rk3188_pwm_config(priv->grf, func);
+		break;
+	case PERIPH_ID_I2C0:
+	case PERIPH_ID_I2C1:
+	case PERIPH_ID_I2C2:
+	case PERIPH_ID_I2C3:
+	case PERIPH_ID_I2C4:
+	case PERIPH_ID_I2C5:
+		pinctrl_rk3188_i2c_config(priv->grf, priv->pmu, func);
+		break;
+	case PERIPH_ID_SPI0:
+	case PERIPH_ID_SPI1:
+	case PERIPH_ID_SPI2:
+		pinctrl_rk3188_spi_config(priv->grf, func, flags);
+		break;
+	case PERIPH_ID_UART0:
+	case PERIPH_ID_UART1:
+	case PERIPH_ID_UART2:
+	case PERIPH_ID_UART3:
+	case PERIPH_ID_UART4:
+		pinctrl_rk3188_uart_config(priv->grf, func);
+		break;
+		break;
+	case PERIPH_ID_SDMMC0:
+	case PERIPH_ID_SDMMC1:
+		pinctrl_rk3188_sdmmc_config(priv->grf, func);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rk3188_pinctrl_get_periph_id(struct udevice *dev,
+					struct udevice *periph)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	u32 cell[3];
+	int ret;
+
+	ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
+				   "interrupts", cell, ARRAY_SIZE(cell));
+	if (ret < 0)
+		return -EINVAL;
+
+	switch (cell[1]) {
+	case 44:
+		return PERIPH_ID_SPI0;
+	case 45:
+		return PERIPH_ID_SPI1;
+	case 46:
+		return PERIPH_ID_SPI2;
+	case 60:
+		return PERIPH_ID_I2C0;
+	case 62: /* Note strange order */
+		return PERIPH_ID_I2C1;
+	case 61:
+		return PERIPH_ID_I2C2;
+	case 63:
+		return PERIPH_ID_I2C3;
+	case 64:
+		return PERIPH_ID_I2C4;
+	case 65:
+		return PERIPH_ID_I2C5;
+	}
+#endif
+
+	return -ENOENT;
+}
+
+static int rk3188_pinctrl_set_state_simple(struct udevice *dev,
+					   struct udevice *periph)
+{
+	int func;
+
+	func = rk3188_pinctrl_get_periph_id(dev, periph);
+	if (func < 0)
+		return func;
+	return rk3188_pinctrl_request(dev, func, 0);
+}
+
+#ifndef CONFIG_SPL_BUILD
+int rk3188_pinctrl_get_pin_info(struct rk3188_pinctrl_priv *priv,
+				int banknum, int ind, u32 **addrp, uint *shiftp,
+				uint *maskp)
+{
+	struct rockchip_pin_bank *bank = &rk3188_pin_banks[banknum];
+	uint muxnum;
+	u32 *addr;
+
+	for (muxnum = 0; muxnum < 4; muxnum++) {
+		struct rockchip_iomux *mux = &bank->iomux[muxnum];
+
+		if (ind >= 8) {
+			ind -= 8;
+			continue;
+		}
+
+		addr = &priv->grf->gpio0c_iomux - 2;
+		addr += mux->offset;
+		*shiftp = ind & 7;
+		*maskp = 3;
+		*shiftp *= 2;
+
+		debug("%s: addr=%p, mask=%x, shift=%x\n", __func__, addr,
+		      *maskp, *shiftp);
+		*addrp = addr;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int rk3188_pinctrl_get_gpio_mux(struct udevice *dev, int banknum,
+				       int index)
+{
+	struct rk3188_pinctrl_priv *priv = dev_get_priv(dev);
+	uint shift;
+	uint mask;
+	u32 *addr;
+	int ret;
+
+	ret = rk3188_pinctrl_get_pin_info(priv, banknum, index, &addr, &shift,
+					  &mask);
+	if (ret)
+		return ret;
+	return (readl(addr) & mask) >> shift;
+}
+
+static int rk3188_pinctrl_set_pins(struct udevice *dev, int banknum, int index,
+				   int muxval, int flags)
+{
+	struct rk3188_pinctrl_priv *priv = dev_get_priv(dev);
+	uint shift, ind = index;
+	uint mask;
+	u32 *addr;
+	int ret;
+
+	debug("%s: %x %x %x %x\n", __func__, banknum, index, muxval, flags);
+	ret = rk3188_pinctrl_get_pin_info(priv, banknum, index, &addr, &shift,
+					  &mask);
+	if (ret)
+		return ret;
+	rk_clrsetreg(addr, mask << shift, muxval << shift);
+
+	/* Handle pullup/pulldown */
+	if (flags) {
+		uint val = 0;
+
+		if (flags & (1 << PIN_CONFIG_BIAS_PULL_UP))
+			val = 1;
+		else if (flags & (1 << PIN_CONFIG_BIAS_PULL_DOWN))
+			val = 2;
+
+		ind = index >> 3;
+
+		if (banknum == 0 && index < 12) {
+			addr = &priv->pmu->gpio0_p[ind];
+			shift = (index & 7) * 2;
+		} else if (banknum == 0 && index >= 12) {
+			addr = &priv->grf->gpio0_p[ind - 1];
+			/*
+			 * The bits in the grf-registers have an inverse
+			 * ordering with the lowest pin being in bits 15:14
+			 * and the highest pin in bits 1:0 .
+			 */
+			shift = (7 - (index & 7)) * 2;
+		} else {
+			addr = &priv->grf->gpio1_p[banknum - 1][ind];
+			shift = (7 - (index & 7)) * 2;
+		}
+		debug("%s: addr=%p, val=%x, shift=%x\n", __func__, addr, val,
+		      shift);
+		rk_clrsetreg(addr, 3 << shift, val << shift);
+	}
+
+	return 0;
+}
+
+static int rk3188_pinctrl_set_state(struct udevice *dev, struct udevice *config)
+{
+	const void *blob = gd->fdt_blob;
+	int pcfg_node, ret, flags, count, i;
+	u32 cell[60], *ptr;
+
+	debug("%s: %s %s\n", __func__, dev->name, config->name);
+	ret = fdtdec_get_int_array_count(blob, config->of_offset,
+					 "rockchip,pins", cell,
+					 ARRAY_SIZE(cell));
+	if (ret < 0) {
+		debug("%s: bad array %d\n", __func__, ret);
+		return -EINVAL;
+	}
+	count = ret;
+	for (i = 0, ptr = cell; i < count; i += 4, ptr += 4) {
+		pcfg_node = fdt_node_offset_by_phandle(blob, ptr[3]);
+		if (pcfg_node < 0)
+			return -EINVAL;
+		flags = pinctrl_decode_pin_config(blob, pcfg_node);
+		if (flags < 0)
+			return flags;
+
+		ret = rk3188_pinctrl_set_pins(dev, ptr[0], ptr[1], ptr[2],
+					      flags);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+#endif
+
+static struct pinctrl_ops rk3188_pinctrl_ops = {
+#ifndef CONFIG_SPL_BUILD
+	.set_state	= rk3188_pinctrl_set_state,
+	.get_gpio_mux	= rk3188_pinctrl_get_gpio_mux,
+#endif
+	.set_state_simple	= rk3188_pinctrl_set_state_simple,
+	.request	= rk3188_pinctrl_request,
+	.get_periph_id	= rk3188_pinctrl_get_periph_id,
+};
+
+#ifndef CONFIG_SPL_BUILD
+static int rk3188_pinctrl_parse_tables(struct rk3188_pinctrl_priv *priv,
+				       struct rockchip_pin_bank *banks,
+				       int count)
+{
+	struct rockchip_pin_bank *bank;
+	uint reg, muxnum, banknum;
+
+	reg = 0;
+	for (banknum = 0; banknum < count; banknum++) {
+		bank = &banks[banknum];
+		bank->reg = reg;
+		debug("%s: bank %d, reg %x\n", __func__, banknum, reg * 4);
+		for (muxnum = 0; muxnum < 4; muxnum++) {
+			struct rockchip_iomux *mux = &bank->iomux[muxnum];
+
+			mux->offset = reg;
+			reg += 1;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+static int rk3188_pinctrl_probe(struct udevice *dev)
+{
+	struct rk3188_pinctrl_priv *priv = dev_get_priv(dev);
+	int ret = 0;
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
+	debug("%s: grf=%p, pmu=%p\n", __func__, priv->grf, priv->pmu);
+#ifndef CONFIG_SPL_BUILD
+	ret = rk3188_pinctrl_parse_tables(priv, rk3188_pin_banks,
+					  ARRAY_SIZE(rk3188_pin_banks));
+#endif
+
+	return ret;
+}
+
+static const struct udevice_id rk3188_pinctrl_ids[] = {
+	{ .compatible = "rockchip,rk3188-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_rk3188) = {
+	.name		= "rockchip_rk3188_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= rk3188_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct rk3188_pinctrl_priv),
+	.ops		= &rk3188_pinctrl_ops,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind		= dm_scan_fdt_dev,
+#endif
+	.probe		= rk3188_pinctrl_probe,
+};
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 08/16] rockchip: rk3188: Add sysreset driver
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (6 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 07/16] rockchip: rk3188: Add pinctrl driver Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 09/16] rockchip: rk3188: Add rk3066/rk3188 clock bindings Heiko Stuebner
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Driver for the sysreset of Rockchip rk3188 socs.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/sysreset/Makefile          |  1 +
 drivers/sysreset/sysreset_rk3188.c | 47 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)
 create mode 100644 drivers/sysreset/sysreset_rk3188.c

diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index fa75cc52de..30f1bce390 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3036) += sysreset_rk3036.o
 endif
+obj-$(CONFIG_ROCKCHIP_RK3188) += sysreset_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += sysreset_rk3288.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += sysreset_rk3399.o
 obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
diff --git a/drivers/sysreset/sysreset_rk3188.c b/drivers/sysreset/sysreset_rk3188.c
new file mode 100644
index 0000000000..36ae47600a
--- /dev/null
+++ b/drivers/sysreset/sysreset_rk3188.c
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <sysreset.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3188.h>
+#include <asm/arch/hardware.h>
+#include <linux/err.h>
+
+int rk3188_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	struct rk3188_cru *cru = rockchip_get_cru();
+
+	if (IS_ERR(cru))
+		return PTR_ERR(cru);
+	switch (type) {
+	case SYSRESET_WARM:
+		rk_clrreg(&cru->cru_mode_con, 0xffff);
+		writel(0xeca8, &cru->cru_glb_srst_snd_value);
+		break;
+	case SYSRESET_COLD:
+		rk_clrreg(&cru->cru_mode_con, 0xffff);
+		writel(0xfdb9, &cru->cru_glb_srst_fst_value);
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	return -EINPROGRESS;
+}
+
+static struct sysreset_ops rk3188_sysreset = {
+	.request	= rk3188_sysreset_request,
+};
+
+U_BOOT_DRIVER(sysreset_rk3188) = {
+	.name	= "rk3188_sysreset",
+	.id	= UCLASS_SYSRESET,
+	.ops	= &rk3188_sysreset,
+};
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 09/16] rockchip: rk3188: Add rk3066/rk3188 clock bindings
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (7 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 08/16] rockchip: rk3188: Add sysreset driver Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver Heiko Stuebner
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Bring in required device clock binding files from Linux.
The clock trees for rk3066 and rk3188 are largely similar, which makes
them share the common parts in a shared header. While we focus on rk3188
for now, bring in both headers already for completeness sake.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Simon Glass <sjg@chromium.org>
---
 include/dt-bindings/clock/rk3066a-cru.h       |  32 ++++
 include/dt-bindings/clock/rk3188-cru-common.h | 256 ++++++++++++++++++++++++++
 include/dt-bindings/clock/rk3188-cru.h        |  48 +++++
 3 files changed, 336 insertions(+)
 create mode 100644 include/dt-bindings/clock/rk3066a-cru.h
 create mode 100644 include/dt-bindings/clock/rk3188-cru-common.h
 create mode 100644 include/dt-bindings/clock/rk3188-cru.h

diff --git a/include/dt-bindings/clock/rk3066a-cru.h b/include/dt-bindings/clock/rk3066a-cru.h
new file mode 100644
index 0000000000..549ae6a3f3
--- /dev/null
+++ b/include/dt-bindings/clock/rk3066a-cru.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3066A_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3066A_H
+
+#include <dt-bindings/clock/rk3188-cru-common.h>
+
+/* soft-reset indices */
+#define SRST_SRST1		0
+#define SRST_SRST2		1
+
+#define SRST_L2MEM		18
+#define SRST_I2S0		23
+#define SRST_I2S1		24
+#define SRST_I2S2		25
+#define SRST_TIMER2		29
+
+#define SRST_GPIO4		36
+#define SRST_GPIO6		38
+
+#define SRST_TSADC		92
+
+#define SRST_HDMI		96
+#define SRST_HDMI_APB		97
+#define SRST_CIF1		111
+
+#endif
diff --git a/include/dt-bindings/clock/rk3188-cru-common.h b/include/dt-bindings/clock/rk3188-cru-common.h
new file mode 100644
index 0000000000..8fc818b1d9
--- /dev/null
+++ b/include/dt-bindings/clock/rk3188-cru-common.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3188_COMMON_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3188_COMMON_H
+
+/* core clocks from */
+#define PLL_APLL		1
+#define PLL_DPLL		2
+#define PLL_CPLL		3
+#define PLL_GPLL		4
+#define CORE_PERI		5
+#define CORE_L2C		6
+#define ARMCLK			7
+
+/* sclk gates (special clocks) */
+#define SCLK_UART0		64
+#define SCLK_UART1		65
+#define SCLK_UART2		66
+#define SCLK_UART3		67
+#define SCLK_MAC		68
+#define SCLK_SPI0		69
+#define SCLK_SPI1		70
+#define SCLK_SARADC		71
+#define SCLK_SDMMC		72
+#define SCLK_SDIO		73
+#define SCLK_EMMC		74
+#define SCLK_I2S0		75
+#define SCLK_I2S1		76
+#define SCLK_I2S2		77
+#define SCLK_SPDIF		78
+#define SCLK_CIF0		79
+#define SCLK_CIF1		80
+#define SCLK_OTGPHY0		81
+#define SCLK_OTGPHY1		82
+#define SCLK_HSADC		83
+#define SCLK_TIMER0		84
+#define SCLK_TIMER1		85
+#define SCLK_TIMER2		86
+#define SCLK_TIMER3		87
+#define SCLK_TIMER4		88
+#define SCLK_TIMER5		89
+#define SCLK_TIMER6		90
+#define SCLK_JTAG		91
+#define SCLK_SMC		92
+#define SCLK_TSADC		93
+
+#define DCLK_LCDC0		190
+#define DCLK_LCDC1		191
+
+/* aclk gates */
+#define ACLK_DMA1		192
+#define ACLK_DMA2		193
+#define ACLK_GPS		194
+#define ACLK_LCDC0		195
+#define ACLK_LCDC1		196
+#define ACLK_GPU		197
+#define ACLK_SMC		198
+#define ACLK_CIF		199
+#define ACLK_IPP		200
+#define ACLK_RGA		201
+#define ACLK_CIF0		202
+#define ACLK_CPU		203
+#define ACLK_PERI		204
+
+/* pclk gates */
+#define PCLK_GRF		320
+#define PCLK_PMU		321
+#define PCLK_TIMER0		322
+#define PCLK_TIMER1		323
+#define PCLK_TIMER2		324
+#define PCLK_TIMER3		325
+#define PCLK_PWM01		326
+#define PCLK_PWM23		327
+#define PCLK_SPI0		328
+#define PCLK_SPI1		329
+#define PCLK_SARADC		330
+#define PCLK_WDT		331
+#define PCLK_UART0		332
+#define PCLK_UART1		333
+#define PCLK_UART2		334
+#define PCLK_UART3		335
+#define PCLK_I2C0		336
+#define PCLK_I2C1		337
+#define PCLK_I2C2		338
+#define PCLK_I2C3		339
+#define PCLK_I2C4		340
+#define PCLK_GPIO0		341
+#define PCLK_GPIO1		342
+#define PCLK_GPIO2		343
+#define PCLK_GPIO3		344
+#define PCLK_GPIO4		345
+#define PCLK_GPIO6		346
+#define PCLK_EFUSE		347
+#define PCLK_TZPC		348
+#define PCLK_TSADC		349
+#define PCLK_CPU		350
+#define PCLK_PERI		351
+#define PCLK_DDRUPCTL		352
+#define PCLK_PUBL		353
+
+/* hclk gates */
+#define HCLK_SDMMC		448
+#define HCLK_SDIO		449
+#define HCLK_EMMC		450
+#define HCLK_OTG0		451
+#define HCLK_EMAC		452
+#define HCLK_SPDIF		453
+#define HCLK_I2S0		454
+#define HCLK_I2S1		455
+#define HCLK_I2S2		456
+#define HCLK_OTG1		457
+#define HCLK_HSIC		458
+#define HCLK_HSADC		459
+#define HCLK_PIDF		460
+#define HCLK_LCDC0		461
+#define HCLK_LCDC1		462
+#define HCLK_ROM		463
+#define HCLK_CIF0		464
+#define HCLK_IPP		465
+#define HCLK_RGA		466
+#define HCLK_NANDC0		467
+#define HCLK_CPU		468
+#define HCLK_PERI		469
+
+#define CLK_NR_CLKS		(HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_MCORE		2
+#define SRST_CORE0		3
+#define SRST_CORE1		4
+#define SRST_MCORE_DBG		7
+#define SRST_CORE0_DBG		8
+#define SRST_CORE1_DBG		9
+#define SRST_CORE0_WDT		12
+#define SRST_CORE1_WDT		13
+#define SRST_STRC_SYS		14
+#define SRST_L2C		15
+
+#define SRST_CPU_AHB		17
+#define SRST_AHB2APB		19
+#define SRST_DMA1		20
+#define SRST_INTMEM		21
+#define SRST_ROM		22
+#define SRST_SPDIF		26
+#define SRST_TIMER0		27
+#define SRST_TIMER1		28
+#define SRST_EFUSE		30
+
+#define SRST_GPIO0		32
+#define SRST_GPIO1		33
+#define SRST_GPIO2		34
+#define SRST_GPIO3		35
+
+#define SRST_UART0		39
+#define SRST_UART1		40
+#define SRST_UART2		41
+#define SRST_UART3		42
+#define SRST_I2C0		43
+#define SRST_I2C1		44
+#define SRST_I2C2		45
+#define SRST_I2C3		46
+#define SRST_I2C4		47
+
+#define SRST_PWM0		48
+#define SRST_PWM1		49
+#define SRST_DAP_PO		50
+#define SRST_DAP		51
+#define SRST_DAP_SYS		52
+#define SRST_TPIU_ATB		53
+#define SRST_PMU_APB		54
+#define SRST_GRF		55
+#define SRST_PMU		56
+#define SRST_PERI_AXI		57
+#define SRST_PERI_AHB		58
+#define SRST_PERI_APB		59
+#define SRST_PERI_NIU		60
+#define SRST_CPU_PERI		61
+#define SRST_EMEM_PERI		62
+#define SRST_USB_PERI		63
+
+#define SRST_DMA2		64
+#define SRST_SMC		65
+#define SRST_MAC		66
+#define SRST_NANC0		68
+#define SRST_USBOTG0		69
+#define SRST_USBPHY0		70
+#define SRST_OTGC0		71
+#define SRST_USBOTG1		72
+#define SRST_USBPHY1		73
+#define SRST_OTGC1		74
+#define SRST_HSADC		76
+#define SRST_PIDFILTER		77
+#define SRST_DDR_MSCH		79
+
+#define SRST_TZPC		80
+#define SRST_SDMMC		81
+#define SRST_SDIO		82
+#define SRST_EMMC		83
+#define SRST_SPI0		84
+#define SRST_SPI1		85
+#define SRST_WDT		86
+#define SRST_SARADC		87
+#define SRST_DDRPHY		88
+#define SRST_DDRPHY_APB		89
+#define SRST_DDRCTL		90
+#define SRST_DDRCTL_APB		91
+#define SRST_DDRPUB		93
+
+#define SRST_VIO0_AXI		98
+#define SRST_VIO0_AHB		99
+#define SRST_LCDC0_AXI		100
+#define SRST_LCDC0_AHB		101
+#define SRST_LCDC0_DCLK		102
+#define SRST_LCDC1_AXI		103
+#define SRST_LCDC1_AHB		104
+#define SRST_LCDC1_DCLK		105
+#define SRST_IPP_AXI		106
+#define SRST_IPP_AHB		107
+#define SRST_RGA_AXI		108
+#define SRST_RGA_AHB		109
+#define SRST_CIF0		110
+
+#define SRST_VCODEC_AXI		112
+#define SRST_VCODEC_AHB		113
+#define SRST_VIO1_AXI		114
+#define SRST_VCODEC_CPU		115
+#define SRST_VCODEC_NIU		116
+#define SRST_GPU		120
+#define SRST_GPU_NIU		122
+#define SRST_TFUN_ATB		125
+#define SRST_TFUN_APB		126
+#define SRST_CTI4_APB		127
+
+#define SRST_TPIU_APB		128
+#define SRST_TRACE		129
+#define SRST_CORE_DBG		130
+#define SRST_DBG_APB		131
+#define SRST_CTI0		132
+#define SRST_CTI0_APB		133
+#define SRST_CTI1		134
+#define SRST_CTI1_APB		135
+#define SRST_PTM_CORE0		136
+#define SRST_PTM_CORE1		137
+#define SRST_PTM0		138
+#define SRST_PTM0_ATB		139
+#define SRST_PTM1		140
+#define SRST_PTM1_ATB		141
+#define SRST_CTM		142
+#define SRST_TS			143
+
+#endif
diff --git a/include/dt-bindings/clock/rk3188-cru.h b/include/dt-bindings/clock/rk3188-cru.h
new file mode 100644
index 0000000000..b6960b07bc
--- /dev/null
+++ b/include/dt-bindings/clock/rk3188-cru.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3188_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3188_H
+
+#include <dt-bindings/clock/rk3188-cru-common.h>
+
+/* soft-reset indices */
+#define SRST_PTM_CORE2		0
+#define SRST_PTM_CORE3		1
+#define SRST_CORE2		5
+#define SRST_CORE3		6
+#define SRST_CORE2_DBG		10
+#define SRST_CORE3_DBG		11
+
+#define SRST_TIMER2		16
+#define SRST_TIMER4		23
+#define SRST_I2S0		24
+#define SRST_TIMER5		25
+#define SRST_TIMER3		29
+#define SRST_TIMER6		31
+
+#define SRST_PTM3		36
+#define SRST_PTM3_ATB		37
+
+#define SRST_GPS		67
+#define SRST_HSICPHY		75
+#define SRST_TIMER		78
+
+#define SRST_PTM2		92
+#define SRST_CORE2_WDT		94
+#define SRST_CORE3_WDT		95
+
+#define SRST_PTM2_ATB		111
+
+#define SRST_HSIC		117
+#define SRST_CTI2		118
+#define SRST_CTI2_APB		119
+#define SRST_GPU_BRIDGE		121
+#define SRST_CTI3		123
+#define SRST_CTI3_APB		124
+
+#endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (8 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 09/16] rockchip: rk3188: Add rk3066/rk3188 clock bindings Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files Heiko Stuebner
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Add a driver for setting up and modifying the various PLLs and peripheral
clocks on the RK3188.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/arm/include/asm/arch-rockchip/cru_rk3188.h | 191 +++++++++
 drivers/clk/rockchip/Makefile                   |   1 +
 drivers/clk/rockchip/clk_rk3188.c               | 523 ++++++++++++++++++++++++
 3 files changed, 715 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3188.h
 create mode 100644 drivers/clk/rockchip/clk_rk3188.c

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3188.h b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
new file mode 100644
index 0000000000..74f0fedcc6
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#ifndef _ASM_ARCH_CRU_RK3188_H
+#define _ASM_ARCH_CRU_RK3188_H
+
+#define OSC_HZ		(24 * 1000 * 1000)
+
+#define APLL_HZ		(1608 * 1000000)
+#define GPLL_HZ		(594 * 1000000)
+#define CPLL_HZ		(384 * 1000000)
+
+/* The SRAM is clocked off aclk_cpu, so we want to max it out for boot speed */
+#define CPU_ACLK_HZ	297000000
+#define CPU_HCLK_HZ	148500000
+#define CPU_PCLK_HZ	74250000
+#define CPU_H2P_HZ	74250000
+
+#define PERI_ACLK_HZ	148500000
+#define PERI_HCLK_HZ	148500000
+#define PERI_PCLK_HZ	74250000
+
+/* Private data for the clock driver - used by rockchip_get_cru() */
+struct rk3188_clk_priv {
+	struct rk3188_grf *grf;
+	struct rk3188_cru *cru;
+	ulong rate;
+	bool has_bwadj;
+};
+
+struct rk3188_cru {
+	struct rk3188_pll {
+		u32 con0;
+		u32 con1;
+		u32 con2;
+		u32 con3;
+	} pll[4];
+	u32 cru_mode_con;
+	u32 cru_clksel_con[35];
+	u32 cru_clkgate_con[10];
+	u32 reserved1[2];
+	u32 cru_glb_srst_fst_value;
+	u32 cru_glb_srst_snd_value;
+	u32 reserved2[2];
+	u32 cru_softrst_con[9];
+	u32 cru_misc_con;
+	u32 reserved3[2];
+	u32 cru_glb_cnt_th;
+};
+check_member(rk3188_cru, cru_glb_cnt_th, 0x0140);
+
+/* CRU_CLKSEL0_CON */
+enum {
+	/* a9_core_div: core = core_src / (a9_core_div + 1) */
+	A9_CORE_DIV_SHIFT	= 9,
+	A9_CORE_DIV_MASK	= 0x1f,
+	CORE_PLL_SHIFT		= 8,
+	CORE_PLL_MASK		= 1,
+	CORE_PLL_SELECT_APLL	= 0,
+	CORE_PLL_SELECT_GPLL,
+
+	/* core peri div: core:core_peri = 2:1, 4:1, 8:1 or 16:1 */
+	CORE_PERI_DIV_SHIFT	= 6,
+	CORE_PERI_DIV_MASK	= 3,
+
+	/* aclk_cpu pll selection */
+	CPU_ACLK_PLL_SHIFT	= 5,
+	CPU_ACLK_PLL_MASK	= 1,
+	CPU_ACLK_PLL_SELECT_APLL	= 0,
+	CPU_ACLK_PLL_SELECT_GPLL,
+
+	/* a9_cpu_div: aclk_cpu = cpu_src / (a9_cpu_div + 1) */
+	A9_CPU_DIV_SHIFT	= 0,
+	A9_CPU_DIV_MASK		= 0x1f,
+};
+
+/* CRU_CLKSEL1_CON */
+enum {
+	/* ahb2apb_pclk_div: hclk_cpu:pclk_cpu = 1:1, 2:1 or 4:1 */
+	AHB2APB_DIV_SHIFT	= 14,
+	AHB2APB_DIV_MASK	= 3,
+
+	/* cpu_pclk_div: aclk_cpu:pclk_cpu = 1:1, 2:1, 4:1 or 8:1 */
+	CPU_PCLK_DIV_SHIFT	= 12,
+	CPU_PCLK_DIV_MASK	= 3,
+
+	/* cpu_hclk_div: aclk_cpu:hclk_cpu = 1:1, 2:1 or 4:1 */
+	CPU_HCLK_DIV_SHIFT	= 8,
+	CPU_HCLK_DIV_MASK	= 3,
+
+	/* core_aclk_div: cire:aclk_core = 1:1, 2:1, 3:1, 4:1 or 8:1 */
+	CORE_ACLK_DIV_SHIFT	= 3,
+	CORE_ACLK_DIV_MASK	= 7,
+};
+
+/* CRU_CLKSEL10_CON */
+enum {
+	PERI_SEL_PLL_MASK	= 1,
+	PERI_SEL_PLL_SHIFT	= 15,
+	PERI_SEL_CPLL		= 0,
+	PERI_SEL_GPLL,
+
+	/* peri pclk div: aclk_bus:pclk_bus = 1:1, 2:1, 4:1 or 8:1 */
+	PERI_PCLK_DIV_SHIFT	= 12,
+	PERI_PCLK_DIV_MASK	= 3,
+
+	/* peripheral bus hclk div:aclk_bus: hclk_bus = 1:1, 2:1 or 4:1 */
+	PERI_HCLK_DIV_SHIFT	= 8,
+	PERI_HCLK_DIV_MASK	= 3,
+
+	/* peri aclk div: aclk_peri = periph_src / (peri_aclk_div + 1) */
+	PERI_ACLK_DIV_SHIFT	= 0,
+	PERI_ACLK_DIV_MASK	= 0x1f,
+};
+/* CRU_CLKSEL11_CON */
+enum {
+	HSICPHY_DIV_SHIFT	= 8,
+	HSICPHY_DIV_MASK	= 0x3f,
+
+	MMC0_DIV_SHIFT		= 0,
+	MMC0_DIV_MASK		= 0x3f,
+};
+
+/* CRU_CLKSEL12_CON */
+enum {
+	UART_PLL_SHIFT		= 15,
+	UART_PLL_MASK		= 1,
+	UART_PLL_SELECT_GENERAL	= 0,
+	UART_PLL_SELECT_CODEC,
+
+	EMMC_DIV_SHIFT		= 8,
+	EMMC_DIV_MASK		= 0x3f,
+
+	SDIO_DIV_SHIFT		= 0,
+	SDIO_DIV_MASK		= 0x3f,
+};
+
+/* CRU_CLKSEL25_CON */
+enum {
+	SPI1_DIV_SHIFT		= 8,
+	SPI1_DIV_MASK		= 0x7f,
+
+	SPI0_DIV_SHIFT		= 0,
+	SPI0_DIV_MASK		= 0x7f,
+};
+
+/* CRU_MODE_CON */
+enum {
+	GPLL_MODE_SHIFT		= 12,
+	GPLL_MODE_MASK		= 3,
+	GPLL_MODE_SLOW		= 0,
+	GPLL_MODE_NORMAL,
+	GPLL_MODE_DEEP,
+
+	CPLL_MODE_SHIFT		= 8,
+	CPLL_MODE_MASK		= 3,
+	CPLL_MODE_SLOW		= 0,
+	CPLL_MODE_NORMAL,
+	CPLL_MODE_DEEP,
+
+	DPLL_MODE_SHIFT		= 4,
+	DPLL_MODE_MASK		= 3,
+	DPLL_MODE_SLOW		= 0,
+	DPLL_MODE_NORMAL,
+	DPLL_MODE_DEEP,
+
+	APLL_MODE_SHIFT		= 0,
+	APLL_MODE_MASK		= 3,
+	APLL_MODE_SLOW		= 0,
+	APLL_MODE_NORMAL,
+	APLL_MODE_DEEP,
+};
+
+/* CRU_APLL_CON0 */
+enum {
+	CLKR_SHIFT		= 8,
+	CLKR_MASK		= 0x3f,
+
+	CLKOD_SHIFT		= 0,
+	CLKOD_MASK		= 0x3f,
+};
+
+/* CRU_APLL_CON1 */
+enum {
+	CLKF_SHIFT		= 0,
+	CLKF_MASK		= 0x1fff,
+};
+
+#endif
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 1f8e41739d..b66e81e810 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -5,5 +5,6 @@
 #
 
 obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
+obj-$(CONFIG_ROCKCHIP_RK3188) += clk_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o
diff --git a/drivers/clk/rockchip/clk_rk3188.c b/drivers/clk/rockchip/clk_rk3188.c
new file mode 100644
index 0000000000..c276772136
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rk3188.c
@@ -0,0 +1,523 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <errno.h>
+#include <mapmem.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3188.h>
+#include <asm/arch/grf_rk3188.h>
+#include <asm/arch/hardware.h>
+#include <dt-bindings/clock/rk3188-cru.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass-internal.h>
+#include <linux/log2.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum rk3188_clk_type {
+	RK3188_CRU,
+	RK3188A_CRU,
+};
+
+struct rk3188_clk_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3188_cru dtd;
+#endif
+};
+
+struct pll_div {
+	u32 nr;
+	u32 nf;
+	u32 no;
+};
+
+enum {
+	VCO_MAX_HZ	= 2200U * 1000000,
+	VCO_MIN_HZ	= 440 * 1000000,
+	OUTPUT_MAX_HZ	= 2200U * 1000000,
+	OUTPUT_MIN_HZ	= 30 * 1000000,
+	FREF_MAX_HZ	= 2200U * 1000000,
+	FREF_MIN_HZ	= 30 * 1000,
+};
+
+enum {
+	/* PLL CON0 */
+	PLL_OD_MASK		= 0x0f,
+
+	/* PLL CON1 */
+	PLL_NF_MASK		= 0x1fff,
+
+	/* PLL CON2 */
+	PLL_BWADJ_MASK		= 0x0fff,
+
+	/* PLL CON3 */
+	PLL_RESET_SHIFT		= 5,
+
+	/* GRF_SOC_STATUS0 */
+	SOCSTS_DPLL_LOCK	= 1 << 5,
+	SOCSTS_APLL_LOCK	= 1 << 6,
+	SOCSTS_CPLL_LOCK	= 1 << 7,
+	SOCSTS_GPLL_LOCK	= 1 << 8,
+};
+
+#define RATE_TO_DIV(input_rate, output_rate) \
+	((input_rate) / (output_rate) - 1);
+
+#define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
+
+#define PLL_DIVISORS(hz, _nr, _no) {\
+	.nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\
+	_Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
+		       (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\
+		       "divisors on line " __stringify(__LINE__));
+
+/* Keep divisors as low as possible to reduce jitter and power usage */
+static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
+static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
+
+static int rkclk_set_pll(struct rk3188_cru *cru, enum rk_clk_id clk_id,
+			 const struct pll_div *div, bool has_bwadj)
+{
+	int pll_id = rk_pll_id(clk_id);
+	struct rk3188_pll *pll = &cru->pll[pll_id];
+	/* All PLLs have same VCO and output frequency range restrictions. */
+	uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
+	uint output_hz = vco_hz / div->no;
+
+	debug("PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
+	      (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz);
+	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
+	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
+	       (div->no == 1 || !(div->no % 2)));
+
+	/* enter reset */
+	rk_setreg(&pll->con3, 1 << PLL_RESET_SHIFT);
+
+	rk_clrsetreg(&pll->con0,
+		     CLKR_MASK << CLKR_SHIFT | PLL_OD_MASK,
+		     ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1));
+	rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1);
+
+	if (has_bwadj)
+		rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
+
+	udelay(10);
+
+	/* return from reset */
+	rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT);
+
+	return 0;
+}
+
+static int rkclk_configure_ddr(struct rk3188_cru *cru, struct rk3188_grf *grf,
+			       unsigned int hz, bool has_bwadj)
+{
+	static const struct pll_div dpll_cfg[] = {
+		{.nf = 25, .nr = 2, .no = 1},
+		{.nf = 400, .nr = 9, .no = 2},
+		{.nf = 500, .nr = 9, .no = 2},
+		{.nf = 100, .nr = 3, .no = 1},
+	};
+	int cfg;
+
+	switch (hz) {
+	case 300000000:
+		cfg = 0;
+		break;
+	case 533000000:	/* actually 533.3P MHz */
+		cfg = 1;
+		break;
+	case 666000000:	/* actually 666.6P MHz */
+		cfg = 2;
+		break;
+	case 800000000:
+		cfg = 3;
+		break;
+	default:
+		debug("Unsupported SDRAM frequency");
+		return -EINVAL;
+	}
+
+	/* pll enter slow-mode */
+	rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
+		     DPLL_MODE_SLOW << DPLL_MODE_SHIFT);
+
+	rkclk_set_pll(cru, CLK_DDR, &dpll_cfg[cfg], has_bwadj);
+
+	/* wait for pll lock */
+	while (!(readl(&grf->soc_status0) & SOCSTS_DPLL_LOCK))
+		udelay(1);
+
+	/* PLL enter normal-mode */
+	rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
+		     DPLL_MODE_NORMAL << DPLL_MODE_SHIFT);
+
+	return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+static void rkclk_init(struct rk3188_cru *cru, struct rk3188_grf *grf,
+		       bool has_bwadj)
+{
+	u32 aclk_div, hclk_div, pclk_div, h2p_div;
+
+	/* pll enter slow-mode */
+	rk_clrsetreg(&cru->cru_mode_con,
+		     GPLL_MODE_MASK << GPLL_MODE_SHIFT |
+		     CPLL_MODE_MASK << CPLL_MODE_SHIFT,
+		     GPLL_MODE_SLOW << GPLL_MODE_SHIFT |
+		     CPLL_MODE_SLOW << CPLL_MODE_SHIFT);
+
+	/* init pll */
+	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg, has_bwadj);
+	rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg, has_bwadj);
+
+	/* waiting for pll lock */
+	while ((readl(&grf->soc_status0) &
+			(SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) !=
+			(SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK))
+		udelay(1);
+
+	/*
+	 * cpu clock pll source selection and
+	 * reparent aclk_cpu_pre from apll to gpll
+	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+	 */
+	aclk_div = RATE_TO_DIV(GPLL_HZ, CPU_ACLK_HZ);
+	assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+	rk_clrsetreg(&cru->cru_clksel_con[0],
+		     CPU_ACLK_PLL_MASK << CPU_ACLK_PLL_SHIFT |
+		     A9_CPU_DIV_MASK << A9_CPU_DIV_SHIFT,
+		     CPU_ACLK_PLL_SELECT_GPLL << CPU_ACLK_PLL_SHIFT |
+		     aclk_div << A9_CPU_DIV_SHIFT);
+
+	hclk_div = ilog2(CPU_ACLK_HZ / CPU_HCLK_HZ);
+	assert((1 << hclk_div) * CPU_HCLK_HZ == CPU_ACLK_HZ && hclk_div < 0x3);
+	pclk_div = ilog2(CPU_ACLK_HZ / CPU_PCLK_HZ);
+	assert((1 << pclk_div) * CPU_PCLK_HZ == CPU_ACLK_HZ && pclk_div < 0x4);
+	h2p_div = ilog2(CPU_HCLK_HZ / CPU_H2P_HZ);
+	assert((1 << h2p_div) * CPU_H2P_HZ == CPU_HCLK_HZ && pclk_div < 0x3);
+
+	rk_clrsetreg(&cru->cru_clksel_con[1],
+		     AHB2APB_DIV_MASK << AHB2APB_DIV_SHIFT |
+		     CPU_PCLK_DIV_MASK << CPU_PCLK_DIV_SHIFT |
+		     CPU_HCLK_DIV_MASK << CPU_HCLK_DIV_SHIFT,
+		     h2p_div << AHB2APB_DIV_SHIFT |
+		     pclk_div << CPU_PCLK_DIV_SHIFT |
+		     hclk_div << CPU_HCLK_DIV_SHIFT);
+
+	/*
+	 * peri clock pll source selection and
+	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+	 */
+	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
+	assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+	hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ);
+	assert((1 << hclk_div) * PERI_HCLK_HZ ==
+		PERI_ACLK_HZ && (hclk_div < 0x4));
+
+	pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ);
+	assert((1 << pclk_div) * PERI_PCLK_HZ ==
+		PERI_ACLK_HZ && (pclk_div < 0x4));
+
+	rk_clrsetreg(&cru->cru_clksel_con[10],
+		     PERI_PCLK_DIV_MASK << PERI_PCLK_DIV_SHIFT |
+		     PERI_HCLK_DIV_MASK << PERI_HCLK_DIV_SHIFT |
+		     PERI_ACLK_DIV_MASK << PERI_ACLK_DIV_SHIFT,
+		     PERI_SEL_GPLL << PERI_SEL_PLL_SHIFT |
+		     pclk_div << PERI_PCLK_DIV_SHIFT |
+		     hclk_div << PERI_HCLK_DIV_SHIFT |
+		     aclk_div << PERI_ACLK_DIV_SHIFT);
+
+	/* PLL enter normal-mode */
+	rk_clrsetreg(&cru->cru_mode_con,
+		     GPLL_MODE_MASK << GPLL_MODE_SHIFT |
+		     CPLL_MODE_MASK << CPLL_MODE_SHIFT,
+		     GPLL_MODE_NORMAL << GPLL_MODE_SHIFT |
+		     CPLL_MODE_NORMAL << CPLL_MODE_SHIFT);
+}
+#endif
+
+/* Get pll rate by id */
+static uint32_t rkclk_pll_get_rate(struct rk3188_cru *cru,
+				   enum rk_clk_id clk_id)
+{
+	uint32_t nr, no, nf;
+	uint32_t con;
+	int pll_id = rk_pll_id(clk_id);
+	struct rk3188_pll *pll = &cru->pll[pll_id];
+	static u8 clk_shift[CLK_COUNT] = {
+		0xff, APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
+		GPLL_MODE_SHIFT
+	};
+	uint shift;
+
+	con = readl(&cru->cru_mode_con);
+	shift = clk_shift[clk_id];
+	switch ((con >> shift) & APLL_MODE_MASK) {
+	case APLL_MODE_SLOW:
+		return OSC_HZ;
+	case APLL_MODE_NORMAL:
+		/* normal mode */
+		con = readl(&pll->con0);
+		no = ((con >> CLKOD_SHIFT) & CLKOD_MASK) + 1;
+		nr = ((con >> CLKR_SHIFT) & CLKR_MASK) + 1;
+		con = readl(&pll->con1);
+		nf = ((con >> CLKF_SHIFT) & CLKF_MASK) + 1;
+
+		return (24 * nf / (nr * no)) * 1000000;
+	case APLL_MODE_DEEP:
+	default:
+		return 32768;
+	}
+}
+
+static ulong rockchip_mmc_get_clk(struct rk3188_cru *cru, uint gclk_rate,
+				  int periph)
+{
+	uint div;
+	u32 con;
+
+	switch (periph) {
+	case HCLK_EMMC:
+		con = readl(&cru->cru_clksel_con[12]);
+		div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
+		break;
+	case HCLK_SDMMC:
+		con = readl(&cru->cru_clksel_con[11]);
+		div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
+		break;
+	case HCLK_SDIO:
+		con = readl(&cru->cru_clksel_con[12]);
+		div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(gclk_rate, div);
+}
+
+static ulong rockchip_mmc_set_clk(struct rk3188_cru *cru, uint gclk_rate,
+				  int  periph, uint freq)
+{
+	int src_clk_div;
+
+	debug("%s: gclk_rate=%u\n", __func__, gclk_rate);
+	src_clk_div = RATE_TO_DIV(gclk_rate, freq);
+	assert(src_clk_div <= 0x3f);
+
+	switch (periph) {
+	case HCLK_EMMC:
+		rk_clrsetreg(&cru->cru_clksel_con[12],
+			     EMMC_DIV_MASK << EMMC_DIV_SHIFT,
+			     src_clk_div << EMMC_DIV_SHIFT);
+		break;
+	case HCLK_SDMMC:
+		rk_clrsetreg(&cru->cru_clksel_con[11],
+			     MMC0_DIV_MASK << MMC0_DIV_SHIFT,
+			     src_clk_div << MMC0_DIV_SHIFT);
+		break;
+	case HCLK_SDIO:
+		rk_clrsetreg(&cru->cru_clksel_con[12],
+			     SDIO_DIV_MASK << SDIO_DIV_SHIFT,
+			     src_clk_div << SDIO_DIV_SHIFT);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return rockchip_mmc_get_clk(cru, gclk_rate, periph);
+}
+
+static ulong rockchip_spi_get_clk(struct rk3188_cru *cru, uint gclk_rate,
+				  int periph)
+{
+	uint div;
+	u32 con;
+
+	switch (periph) {
+	case SCLK_SPI0:
+		con = readl(&cru->cru_clksel_con[25]);
+		div = (con >> SPI0_DIV_SHIFT) & SPI0_DIV_MASK;
+		break;
+	case SCLK_SPI1:
+		con = readl(&cru->cru_clksel_con[25]);
+		div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(gclk_rate, div);
+}
+
+static ulong rockchip_spi_set_clk(struct rk3188_cru *cru, uint gclk_rate,
+				  int periph, uint freq)
+{
+	int src_clk_div = RATE_TO_DIV(gclk_rate, freq);
+
+	switch (periph) {
+	case SCLK_SPI0:
+		assert(src_clk_div <= SPI0_DIV_MASK);
+		rk_clrsetreg(&cru->cru_clksel_con[25],
+			     SPI0_DIV_MASK << SPI0_DIV_SHIFT,
+			     src_clk_div << SPI0_DIV_SHIFT);
+		break;
+	case SCLK_SPI1:
+		assert(src_clk_div <= SPI1_DIV_MASK);
+		rk_clrsetreg(&cru->cru_clksel_con[25],
+			     SPI1_DIV_MASK << SPI1_DIV_SHIFT,
+			     src_clk_div << SPI1_DIV_SHIFT);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return rockchip_spi_get_clk(cru, gclk_rate, periph);
+}
+
+static ulong rk3188_clk_get_rate(struct clk *clk)
+{
+	struct rk3188_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong new_rate, gclk_rate;
+
+	gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
+	switch (clk->id) {
+	case 1 ... 4:
+		new_rate = rkclk_pll_get_rate(priv->cru, clk->id);
+		break;
+	case HCLK_EMMC:
+	case HCLK_SDMMC:
+	case HCLK_SDIO:
+		new_rate = rockchip_mmc_get_clk(priv->cru, PERI_HCLK_HZ,
+						clk->id);
+		break;
+	case SCLK_SPI0:
+	case SCLK_SPI1:
+		new_rate = rockchip_spi_get_clk(priv->cru, PERI_PCLK_HZ,
+						clk->id);
+		break;
+	case PCLK_I2C0:
+	case PCLK_I2C1:
+	case PCLK_I2C2:
+	case PCLK_I2C3:
+	case PCLK_I2C4:
+		return gclk_rate;
+	default:
+		return -ENOENT;
+	}
+
+	return new_rate;
+}
+
+static ulong rk3188_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct rk3188_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3188_cru *cru = priv->cru;
+	ulong new_rate;
+
+	switch (clk->id) {
+	case CLK_DDR:
+		new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate,
+					       priv->has_bwadj);
+		break;
+	case HCLK_EMMC:
+	case HCLK_SDMMC:
+	case HCLK_SDIO:
+		new_rate = rockchip_mmc_set_clk(cru, PERI_HCLK_HZ,
+						clk->id, rate);
+		break;
+	case SCLK_SPI0:
+	case SCLK_SPI1:
+		new_rate = rockchip_spi_set_clk(cru, PERI_PCLK_HZ,
+						clk->id, rate);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return new_rate;
+}
+
+static struct clk_ops rk3188_clk_ops = {
+	.get_rate	= rk3188_clk_get_rate,
+	.set_rate	= rk3188_clk_set_rate,
+};
+
+static int rk3188_clk_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3188_clk_priv *priv = dev_get_priv(dev);
+
+	priv->cru = (struct rk3188_cru *)dev_get_addr(dev);
+#endif
+
+	return 0;
+}
+
+static int rk3188_clk_probe(struct udevice *dev)
+{
+	struct rk3188_clk_priv *priv = dev_get_priv(dev);
+	enum rk3188_clk_type type = dev_get_driver_data(dev);
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	if (IS_ERR(priv->grf))
+		return PTR_ERR(priv->grf);
+	priv->has_bwadj = (type == RK3188A_CRU) ? 1 : 0;
+
+#ifdef CONFIG_SPL_BUILD
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3188_clk_plat *plat = dev_get_platdata(dev);
+
+	priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
+#endif
+
+	rkclk_init(priv->cru, priv->grf, priv->has_bwadj);
+#endif
+
+	return 0;
+}
+
+static int rk3188_clk_bind(struct udevice *dev)
+{
+	int ret;
+
+	/* The reset driver does not have a device node, so bind it here */
+	ret = device_bind_driver(gd->dm_root, "rk3188_sysreset", "reset", &dev);
+	if (ret)
+		debug("Warning: No rk3188 reset driver: ret=%d\n", ret);
+
+	return 0;
+}
+
+static const struct udevice_id rk3188_clk_ids[] = {
+	{ .compatible = "rockchip,rk3188-cru", .data = RK3188_CRU },
+	{ .compatible = "rockchip,rk3188a-cru", .data = RK3188A_CRU },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_rk3188_cru) = {
+	.name			= "rockchip_rk3188_cru",
+	.id			= UCLASS_CLK,
+	.of_match		= rk3188_clk_ids,
+	.priv_auto_alloc_size	= sizeof(struct rk3188_clk_priv),
+	.platdata_auto_alloc_size = sizeof(struct rk3188_clk_plat),
+	.ops			= &rk3188_clk_ops,
+	.bind			= rk3188_clk_bind,
+	.ofdata_to_platdata	= rk3188_clk_ofdata_to_platdata,
+	.probe			= rk3188_clk_probe,
+};
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (9 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 12/16] rockchip: rk3188: Add core support Heiko Stuebner
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

The rk3188 shares a lot of peripherals with the rk3066 and thus
has a common include called rk3xxx.dtsi. Add both this one and
the specialized rk3188 on top of it.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/arm/dts/rk3188.dtsi | 601 +++++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/dts/rk3xxx.dtsi | 417 ++++++++++++++++++++++++++++++++
 2 files changed, 1018 insertions(+)
 create mode 100644 arch/arm/dts/rk3188.dtsi
 create mode 100644 arch/arm/dts/rk3xxx.dtsi

diff --git a/arch/arm/dts/rk3188.dtsi b/arch/arm/dts/rk3188.dtsi
new file mode 100644
index 0000000000..f4d438eb66
--- /dev/null
+++ b/arch/arm/dts/rk3188.dtsi
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ or X11
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3188-cru.h>
+#include "rk3xxx.dtsi"
+
+/ {
+	compatible = "rockchip,rk3188";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "rockchip,rk3066-smp";
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x0>;
+			operating-points = <
+				/* kHz    uV */
+				1608000 1350000
+				1416000 1250000
+				1200000 1150000
+				1008000 1075000
+				 816000  975000
+				 600000  950000
+				 504000  925000
+				 312000  875000
+			>;
+			clock-latency = <40000>;
+			clocks = <&cru ARMCLK>;
+		};
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x1>;
+		};
+		cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x2>;
+		};
+		cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x3>;
+		};
+	};
+
+	sram: sram at 10080000 {
+		compatible = "mmio-sram";
+		reg = <0x10080000 0x8000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x10080000 0x8000>;
+
+		smp-sram at 0 {
+			compatible = "rockchip,rk3066-smp-sram";
+			reg = <0x0 0x50>;
+		};
+	};
+
+	i2s0: i2s at 1011a000 {
+		compatible = "rockchip,rk3188-i2s", "rockchip,rk3066-i2s";
+		reg = <0x1011a000 0x2000>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s0_bus>;
+		dmas = <&dmac1_s 6>, <&dmac1_s 7>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_hclk", "i2s_clk";
+		clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+		rockchip,playback-channels = <2>;
+		rockchip,capture-channels = <2>;
+		status = "disabled";
+	};
+
+	spdif: sound at 1011e000 {
+		compatible = "rockchip,rk3188-spdif", "rockchip,rk3066-spdif";
+		reg = <0x1011e000 0x2000>;
+		#sound-dai-cells = <0>;
+		clock-names = "hclk", "mclk";
+		clocks = <&cru HCLK_SPDIF>, <&cru SCLK_SPDIF>;
+		dmas = <&dmac1_s 8>;
+		dma-names = "tx";
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spdif_tx>;
+		status = "disabled";
+	};
+
+	cru: clock-controller at 20000000 {
+		compatible = "rockchip,rk3188-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+		u-boot,dm-spl;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	efuse: efuse at 20010000 {
+		compatible = "rockchip,rockchip-efuse";
+		reg = <0x20010000 0x4000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		clocks = <&cru PCLK_EFUSE>;
+		clock-names = "pclk_efuse";
+
+		cpu_leakage: cpu_leakage at 17 {
+			reg = <0x17 0x1>;
+		};
+	};
+
+	usbphy: phy {
+		compatible = "rockchip,rk3188-usb-phy", "rockchip,rk3288-usb-phy";
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+
+		usbphy0: usb-phy at 10c {
+			#phy-cells = <0>;
+			reg = <0x10c>;
+			clocks = <&cru SCLK_OTGPHY0>;
+			clock-names = "phyclk";
+			#clock-cells = <0>;
+		};
+
+		usbphy1: usb-phy at 11c {
+			#phy-cells = <0>;
+			reg = <0x11c>;
+			clocks = <&cru SCLK_OTGPHY1>;
+			clock-names = "phyclk";
+			#clock-cells = <0>;
+		};
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3188-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmu>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		u-boot,dm-spl;
+
+		gpio0: gpio0 at 2000a000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2000a000 0x100>;
+			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO0>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio1 at 2003c000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2003c000 0x100>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio2 at 2003e000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2003e000 0x100>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio3 at 20080000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20080000 0x100>;
+			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO3>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		pcfg_pull_up: pcfg_pull_up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg_pull_down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg_pull_none {
+			bias-disable;
+		};
+
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins = <RK_GPIO0 24 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins = <RK_GPIO0 26 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_rst: emmc-rst {
+				rockchip,pins = <RK_GPIO0 27 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			/*
+			 * The data pins are shared between nandc and emmc and
+			 * not accessible through pinctrl. Also they should've
+			 * been already set correctly by firmware, as
+			 * flash/emmc is the boot-device.
+			 */
+		};
+
+		emac {
+			emac_xfer: emac-xfer {
+				rockchip,pins = <RK_GPIO3 16 RK_FUNC_2 &pcfg_pull_none>, /* tx_en */
+						<RK_GPIO3 17 RK_FUNC_2 &pcfg_pull_none>, /* txd1 */
+						<RK_GPIO3 18 RK_FUNC_2 &pcfg_pull_none>, /* txd0 */
+						<RK_GPIO3 19 RK_FUNC_2 &pcfg_pull_none>, /* rxd0 */
+						<RK_GPIO3 20 RK_FUNC_2 &pcfg_pull_none>, /* rxd1 */
+						<RK_GPIO3 21 RK_FUNC_2 &pcfg_pull_none>, /* mac_clk */
+						<RK_GPIO3 22 RK_FUNC_2 &pcfg_pull_none>, /* rx_err */
+						<RK_GPIO3 23 RK_FUNC_2 &pcfg_pull_none>; /* crs_dvalid */
+			};
+
+			emac_mdio: emac-mdio {
+				rockchip,pins = <RK_GPIO3 24 RK_FUNC_2 &pcfg_pull_none>,
+						<RK_GPIO3 25 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <RK_GPIO1 24 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 25 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <RK_GPIO1 26 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 27 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <RK_GPIO1 28 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 29 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <RK_GPIO3 14 RK_FUNC_2 &pcfg_pull_none>,
+						<RK_GPIO3 15 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins = <RK_GPIO1 30 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 31 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm0 {
+			pwm0_out: pwm0-out {
+				rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_out: pwm1-out {
+				rockchip,pins = <RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_out: pwm2-out {
+				rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3 {
+			pwm3_out: pwm3-out {
+				rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins = <RK_GPIO1 6 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs0: spi0-cs0 {
+				rockchip,pins = <RK_GPIO1 7 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_tx: spi0-tx {
+				rockchip,pins = <RK_GPIO1 5 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_rx: spi0-rx {
+				rockchip,pins = <RK_GPIO1 4 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs1: spi0-cs1 {
+				rockchip,pins = <RK_GPIO1 15 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins = <RK_GPIO0 30 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi1_cs0: spi1-cs0 {
+				rockchip,pins = <RK_GPIO0 31 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi1_rx: spi1-rx {
+				rockchip,pins = <RK_GPIO0 28 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi1_tx: spi1-tx {
+				rockchip,pins = <RK_GPIO0 29 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi1_cs1: spi1-cs1 {
+				rockchip,pins = <RK_GPIO1 14 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart2 {
+			uart2_xfer: uart2-xfer {
+				rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
+			/* no rts / cts for uart2 */
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>,
+						<RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart3_cts: uart3-cts {
+				rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart3_rts: uart3-rts {
+				rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		sd0 {
+			sd0_clk: sd0-clk {
+				rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd0_cmd: sd0-cmd {
+				rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd0_cd: sd0-cd {
+				rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd0_wp: sd0-wp {
+				rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd0_pwr: sd0-pwr {
+				rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd0_bus1: sd0-bus-width1 {
+				rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd0_bus4: sd0-bus-width4 {
+				rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		sd1 {
+			sd1_clk: sd1-clk {
+				rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd1_cmd: sd1-cmd {
+				rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd1_cd: sd1-cd {
+				rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd1_wp: sd1-wp {
+				rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd1_bus1: sd1-bus-width1 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sd1_bus4: sd1-bus-width4 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s0 {
+			i2s0_bus: i2s0-bus {
+				rockchip,pins = <RK_GPIO1 16 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 17 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 18 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 19 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 20 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO1 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		spdif {
+			spdif_tx: spdif-tx {
+				rockchip,pins = <RK_GPIO1 14 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+	};
+};
+
+&emac {
+	compatible = "rockchip,rk3188-emac";
+};
+
+&global_timer {
+	interrupts = <GIC_PPI 11 0xf04>;
+};
+
+&grf {
+	compatible = "rockchip,rk3188-grf", "syscon";
+};
+
+&local_timer {
+	interrupts = <GIC_PPI 13 0xf04>;
+};
+
+&i2c0 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_xfer>;
+};
+
+&i2c1 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_xfer>;
+};
+
+&i2c2 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_xfer>;
+};
+
+&i2c3 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_xfer>;
+};
+
+&i2c4 {
+	compatible = "rockchip,rk3188-i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_xfer>;
+};
+
+&pmu {
+	compatible = "rockchip,rk3188-pmu", "syscon";
+};
+
+&pwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_out>;
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm1_out>;
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm2_out>;
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm3_out>;
+};
+
+&spi0 {
+	compatible = "rockchip,rk3188-spi", "rockchip,rk3066-spi";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
+};
+
+&spi1 {
+	compatible = "rockchip,rk3188-spi", "rockchip,rk3066-spi";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
+};
+
+&uart0 {
+	compatible = "rockchip,rk3188-uart", "snps,dw-apb-uart";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer>;
+};
+
+&uart1 {
+	compatible = "rockchip,rk3188-uart", "snps,dw-apb-uart";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_xfer>;
+};
+
+&uart2 {
+	compatible = "rockchip,rk3188-uart", "snps,dw-apb-uart";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_xfer>;
+};
+
+&uart3 {
+	compatible = "rockchip,rk3188-uart", "snps,dw-apb-uart";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_xfer>;
+};
+
+&wdt {
+	compatible = "rockchip,rk3188-wdt", "snps,dw-wdt";
+};
diff --git a/arch/arm/dts/rk3xxx.dtsi b/arch/arm/dts/rk3xxx.dtsi
new file mode 100644
index 0000000000..6d9e36d235
--- /dev/null
+++ b/arch/arm/dts/rk3xxx.dtsi
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ or X11
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&gic>;
+
+	aliases {
+		ethernet0 = &emac;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		mshc0 = &emmc;
+		mshc1 = &mmc0;
+		mshc2 = &mmc1;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		spi0 = &spi0;
+		spi1 = &spi1;
+	};
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		dmac1_s: dma-controller at 20018000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x20018000 0x4000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			arm,pl330-broken-no-flushp;
+			clocks = <&cru ACLK_DMA1>;
+			clock-names = "apb_pclk";
+		};
+
+		dmac1_ns: dma-controller at 2001c000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x2001c000 0x4000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			arm,pl330-broken-no-flushp;
+			clocks = <&cru ACLK_DMA1>;
+			clock-names = "apb_pclk";
+			status = "disabled";
+		};
+
+		dmac2: dma-controller at 20078000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x20078000 0x4000>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			arm,pl330-broken-no-flushp;
+			clocks = <&cru ACLK_DMA2>;
+			clock-names = "apb_pclk";
+		};
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		#clock-cells = <0>;
+		clock-output-names = "xin24m";
+	};
+
+	L2: l2-cache-controller at 10138000 {
+		compatible = "arm,pl310-cache";
+		reg = <0x10138000 0x1000>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	scu at 1013c000 {
+		compatible = "arm,cortex-a9-scu";
+		reg = <0x1013c000 0x100>;
+	};
+
+	global_timer: global-timer at 1013c200 {
+		compatible = "arm,cortex-a9-global-timer";
+		reg = <0x1013c200 0x20>;
+		interrupts = <GIC_PPI 11 0x304>;
+		clocks = <&cru CORE_PERI>;
+	};
+
+	local_timer: local-timer at 1013c600 {
+		compatible = "arm,cortex-a9-twd-timer";
+		reg = <0x1013c600 0x20>;
+		interrupts = <GIC_PPI 13 0x304>;
+		clocks = <&cru CORE_PERI>;
+	};
+
+	gic: interrupt-controller at 1013d000 {
+		compatible = "arm,cortex-a9-gic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x1013d000 0x1000>,
+		      <0x1013c100 0x0100>;
+	};
+
+	uart0: serial at 10124000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10124000 0x400>;
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		status = "disabled";
+	};
+
+	uart1: serial at 10126000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10126000 0x400>;
+		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		status = "disabled";
+	};
+
+	noc: syscon at 10128000 {
+		u-boot,dm-spl;
+		compatible = "rockchip,rk3188-noc", "syscon";
+		reg = <0x10128000 0x2000>;
+	};
+
+	usb_otg: usb at 10180000 {
+		compatible = "rockchip,rk3066-usb", "snps,dwc2";
+		reg = <0x10180000 0x40000>;
+		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_OTG0>;
+		clock-names = "otg";
+		dr_mode = "otg";
+		g-np-tx-fifo-size = <16>;
+		g-rx-fifo-size = <275>;
+		g-tx-fifo-size = <256 128 128 64 64 32>;
+		g-use-dma;
+		phys = <&usbphy0>;
+		phy-names = "usb2-phy";
+		status = "disabled";
+	};
+
+	usb_host: usb at 101c0000 {
+		compatible = "snps,dwc2";
+		reg = <0x101c0000 0x40000>;
+		interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_OTG1>;
+		clock-names = "otg";
+		dr_mode = "host";
+		phys = <&usbphy1>;
+		phy-names = "usb2-phy";
+		status = "disabled";
+	};
+
+	emac: ethernet at 10204000 {
+		compatible = "snps,arc-emac";
+		reg = <0x10204000 0x3c>;
+		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru HCLK_EMAC>, <&cru SCLK_MAC>;
+		clock-names = "hclk", "macref";
+		max-speed = <100>;
+		phy-mode = "rmii";
+
+		status = "disabled";
+	};
+
+	mmc0: dwmmc at 10214000 {
+		compatible = "rockchip,rk2928-dw-mshc";
+		reg = <0x10214000 0x1000>;
+		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <256>;
+		status = "disabled";
+	};
+
+	mmc1: dwmmc at 10218000 {
+		compatible = "rockchip,rk2928-dw-mshc";
+		reg = <0x10218000 0x1000>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <256>;
+		status = "disabled";
+	};
+
+	emmc: dwmmc at 1021c000 {
+		compatible = "rockchip,rk2928-dw-mshc";
+		reg = <0x1021c000 0x1000>;
+		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <256>;
+		status = "disabled";
+	};
+
+	pmu: pmu at 20004000 {
+		compatible = "rockchip,rk3066-pmu", "syscon";
+		reg = <0x20004000 0x100>;
+		u-boot,dm-spl;
+	};
+
+	grf: grf at 20008000 {
+		compatible = "syscon";
+		reg = <0x20008000 0x200>;
+		u-boot,dm-spl;
+	};
+
+	dmc: dmc at 20020000 {
+		/* unreviewed u-boot-specific binding */
+		compatible = "rockchip,rk3188-dmc", "syscon";
+		rockchip,cru = <&cru>;
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmu>;
+		rockchip,noc = <&noc>;
+		reg = <0x20020000 0x3fc
+		       0x20040000 0x294>;
+		clocks = <&cru PCLK_DDRUPCTL>, <&cru PCLK_PUBL>;
+		clock-names = "pclk_ddrupctl", "pclk_publ";
+		u-boot,dm-spl;
+	};
+
+	i2c0: i2c at 2002d000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2002d000 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C0>;
+
+		status = "disabled";
+	};
+
+	i2c1: i2c at 2002f000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2002f000 0x1000>;
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru PCLK_I2C1>;
+		clock-names = "i2c";
+
+		status = "disabled";
+	};
+
+	pwm0: pwm at 20030000 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20030000 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM01>;
+		status = "disabled";
+	};
+
+	pwm1: pwm at 20030010 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20030010 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM01>;
+		status = "disabled";
+	};
+
+	wdt: watchdog at 2004c000 {
+		compatible = "snps,dw-wdt";
+		reg = <0x2004c000 0x100>;
+		clocks = <&cru PCLK_WDT>;
+		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	pwm2: pwm at 20050020 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050020 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM23>;
+		status = "disabled";
+	};
+
+	pwm3: pwm at 20050030 {
+		compatible = "rockchip,rk2928-pwm";
+		reg = <0x20050030 0x10>;
+		#pwm-cells = <2>;
+		clocks = <&cru PCLK_PWM23>;
+		status = "disabled";
+	};
+
+	i2c2: i2c at 20056000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x20056000 0x1000>;
+		interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru PCLK_I2C2>;
+		clock-names = "i2c";
+
+		status = "disabled";
+	};
+
+	i2c3: i2c at 2005a000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2005a000 0x1000>;
+		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru PCLK_I2C3>;
+		clock-names = "i2c";
+
+		status = "disabled";
+	};
+
+	i2c4: i2c at 2005e000 {
+		compatible = "rockchip,rk3066-i2c";
+		reg = <0x2005e000 0x1000>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rockchip,grf = <&grf>;
+
+		clocks = <&cru PCLK_I2C4>;
+		clock-names = "i2c";
+
+		status = "disabled";
+	};
+
+	uart2: serial at 20064000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x20064000 0x400>;
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-frequency = <24000000>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		status = "disabled";
+	};
+
+	uart3: serial at 20068000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x20068000 0x400>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clock-names = "baudclk", "apb_pclk";
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		status = "disabled";
+	};
+
+	saradc: saradc at 2006c000 {
+		compatible = "rockchip,saradc";
+		reg = <0x2006c000 0x100>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		status = "disabled";
+	};
+
+	spi0: spi at 20070000 {
+		compatible = "rockchip,rk3066-spi";
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+		reg = <0x20070000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		dmas = <&dmac2 10>, <&dmac2 11>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+	};
+
+	spi1: spi at 20074000 {
+		compatible = "rockchip,rk3066-spi";
+		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		reg = <0x20074000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		dmas = <&dmac2 12>, <&dmac2 13>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+	};
+};
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 12/16] rockchip: rk3188: Add core support
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (10 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver Heiko Stuebner
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Add the core architecture code for the rk3188.
It doesn't support the SPL yet, as because of some
unknown error it doesn't start yet.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/arm/mach-rockchip/Kconfig                |  16 ++++
 arch/arm/mach-rockchip/Makefile               |   5 ++
 arch/arm/mach-rockchip/rk3188/Kconfig         |  24 +++++
 arch/arm/mach-rockchip/rk3188/Makefile        |  10 +++
 arch/arm/mach-rockchip/rk3188/clk_rk3188.c    |  33 +++++++
 arch/arm/mach-rockchip/rk3188/syscon_rk3188.c |  55 ++++++++++++
 include/configs/rk3188_common.h               | 125 ++++++++++++++++++++++++++
 7 files changed, 268 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/rk3188/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rk3188/Makefile
 create mode 100644 arch/arm/mach-rockchip/rk3188/clk_rk3188.c
 create mode 100644 arch/arm/mach-rockchip/rk3188/syscon_rk3188.c
 create mode 100644 include/configs/rk3188_common.h

diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index a776df35f4..ba9fbbbd33 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -11,6 +11,21 @@ config ROCKCHIP_RK3036
 	  and video codec support. Peripherals include Gigabit Ethernet,
 	  USB2 host and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
 
+config ROCKCHIP_RK3188
+	bool "Support Rockchip RK3188"
+	select CPU_V7
+	select SUPPORT_SPL
+	select SUPPORT_TPL
+	select SPL
+	select TPL
+	select ROCKCHIP_BROM_HELPER
+	help
+	  The Rockchip RK3188 is a ARM-based SoC with a quad-core Cortex-A9
+	  including NEON and GPU, 512KB L2 cache, Mali-400 graphics, two
+	  video interfaces, several memory options and video codec support.
+	  Peripherals include Fast Ethernet, USB2 host and OTG, SDIO, I2S,
+	  UART, SPI, I2C and PWMs.
+
 config ROCKCHIP_RK3288
 	bool "Support Rockchip RK3288"
 	select CPU_V7
@@ -50,6 +65,7 @@ config SPL_MMC_SUPPORT
 	default y if !ROCKCHIP_SPL_BACK_TO_BROM
 
 source "arch/arm/mach-rockchip/rk3036/Kconfig"
+source "arch/arm/mach-rockchip/rk3188/Kconfig"
 source "arch/arm/mach-rockchip/rk3288/Kconfig"
 source "arch/arm/mach-rockchip/rk3399/Kconfig"
 endif
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index f9ccc9bb2c..2be7e14e3e 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -16,5 +16,10 @@ ifndef CONFIG_ARM64
 obj-y += rk_timer.o
 endif
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
+
+ifndef CONFIG_TPL_BUILD
+obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188/
+endif
+
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/
 obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399/
diff --git a/arch/arm/mach-rockchip/rk3188/Kconfig b/arch/arm/mach-rockchip/rk3188/Kconfig
new file mode 100644
index 0000000000..f8e1d0316b
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188/Kconfig
@@ -0,0 +1,24 @@
+if ROCKCHIP_RK3188
+
+config SYS_SOC
+	default "rockchip"
+
+config SYS_MALLOC_F_LEN
+	default 0x0800
+
+config SPL_LIBCOMMON_SUPPORT
+	default y
+
+config SPL_LIBGENERIC_SUPPORT
+	default y
+
+config SPL_SERIAL_SUPPORT
+	default y
+
+config TPL_LIBCOMMON_SUPPORT
+	default y
+
+config TPL_SERIAL_SUPPORT
+	default y
+
+endif
diff --git a/arch/arm/mach-rockchip/rk3188/Makefile b/arch/arm/mach-rockchip/rk3188/Makefile
new file mode 100644
index 0000000000..7fa010405b
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2015 Google, Inc
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+ifndef CONFIG_TPL_BUILD
+obj-y += clk_rk3188.o
+obj-y += syscon_rk3188.o
+endif
diff --git a/arch/arm/mach-rockchip/rk3188/clk_rk3188.c b/arch/arm/mach-rockchip/rk3188/clk_rk3188.c
new file mode 100644
index 0000000000..1ec9e1cb75
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188/clk_rk3188.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3188.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_rk3188_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct rk3188_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rk3188/syscon_rk3188.c b/arch/arm/mach-rockchip/rk3188/syscon_rk3188.c
new file mode 100644
index 0000000000..aeee6bfcad
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188/syscon_rk3188.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+
+static const struct udevice_id rk3188_syscon_ids[] = {
+	{ .compatible = "rockchip,rk3188-noc", .data = ROCKCHIP_SYSCON_NOC },
+	{ .compatible = "rockchip,rk3188-grf", .data = ROCKCHIP_SYSCON_GRF },
+	{ .compatible = "rockchip,rk3188-pmu", .data = ROCKCHIP_SYSCON_PMU },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_rk3188) = {
+	.name = "rk3188_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3188_syscon_ids,
+};
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int rk3188_syscon_bind_of_platdata(struct udevice *dev)
+{
+	dev->driver_data = dev->driver->of_match->data;
+	debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(rockchip_rk3188_noc) = {
+	.name = "rockchip_rk3188_noc",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3188_syscon_ids,
+	.bind = rk3188_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3188_grf) = {
+	.name = "rockchip_rk3188_grf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3188_syscon_ids + 1,
+	.bind = rk3188_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3188_pmu) = {
+	.name = "rockchip_rk3188_pmu",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3188_syscon_ids + 2,
+	.bind = rk3188_syscon_bind_of_platdata,
+};
+#endif
diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h
new file mode 100644
index 0000000000..3bd04214ec
--- /dev/null
+++ b/include/configs/rk3188_common.h
@@ -0,0 +1,125 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_RK3188_COMMON_H
+#define __CONFIG_RK3188_COMMON_H
+
+#define CONFIG_SYS_CACHELINE_SIZE	64
+
+#include <asm/arch/hardware.h>
+#include "rockchip-common.h"
+
+#define CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_ENV_SIZE			0x2000
+#define CONFIG_SYS_MAXARGS		16
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_MALLOC_LEN		(32 << 20)
+#define CONFIG_SYS_CBSIZE		1024
+#define CONFIG_SYS_THUMB_BUILD
+
+#define CONFIG_SYS_TIMER_RATE		(24 * 1000 * 1000)
+#define CONFIG_SYS_TIMER_BASE		0x2000e000 /* TIMER3 */
+#define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 8)
+#define CONFIG_SYS_TIMER_COUNTS_DOWN
+
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_SPL_BOARD_INIT
+
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+/* Bootrom will load u-boot binary to 0x60000000 once return from SPL */
+#define CONFIG_SYS_TEXT_BASE		0x60000000
+#else
+#define CONFIG_SYS_TEXT_BASE		0x60100000
+#endif
+#define CONFIG_SYS_INIT_SP_ADDR		0x60100000
+#define CONFIG_SYS_LOAD_ADDR		0x60800800
+
+#define CONFIG_ROCKCHIP_MAX_INIT_SIZE	(0x8000 - 0x800)
+#define CONFIG_ROCKCHIP_CHIP_TAG	"RK31"
+
+#ifdef CONFIG_TPL_BUILD
+#define CONFIG_SPL_TEXT_BASE		0x10080804
+/* tpl size 1kb - 4byte RK31 header */
+#define CONFIG_SPL_MAX_SIZE		(0x400 - 0x4)
+#elif defined(CONFIG_SPL_BUILD)
+/* spl size 32kb sram - 2kb bootrom - 1kb spl */
+#define CONFIG_SPL_MAX_SIZE		(0x8000 - 0xC00)
+#define CONFIG_SPL_TEXT_BASE		0x10080C00
+#define CONFIG_SPL_FRAMEWORK		1
+#define CONFIG_SPL_CLK			1
+#define CONFIG_SPL_PINCTRL		1
+#define CONFIG_SPL_REGMAP		1
+#define CONFIG_SPL_SYSCON		1
+#define CONFIG_SPL_RAM			1
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT	1
+#define CONFIG_ROCKCHIP_SERIAL		1
+#endif
+
+#define CONFIG_SPL_STACK		0x10087fff
+
+/* MMC/SD IP block */
+#define CONFIG_GENERIC_MMC
+#define CONFIG_BOUNCE_BUFFER
+
+#define CONFIG_DOS_PARTITION
+#define CONFIG_FAT_WRITE
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+
+#define CONFIG_SYS_SDRAM_BASE		0x60000000
+#define CONFIG_NR_DRAM_BANKS		1
+#define SDRAM_BANK_SIZE			(2UL << 30)
+
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI
+#define CONFIG_SF_DEFAULT_SPEED 20000000
+
+#ifndef CONFIG_SPL_BUILD
+/* usb otg */
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_DWC2_OTG
+#define CONFIG_ROCKCHIP_USB2_PHY
+#define CONFIG_USB_GADGET_VBUS_DRAW	0
+
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_G_DNL_MANUFACTURER	"Rockchip"
+#define CONFIG_G_DNL_VENDOR_NUM		0x2207
+#define CONFIG_G_DNL_PRODUCT_NUM	0x310a
+
+/* usb host support */
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_DWC2
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_USB_ETHER_ASIX
+#endif
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"scriptaddr=0x60000000\0" \
+	"pxefile_addr_r=0x60100000\0" \
+	"fdt_addr_r=0x61f00000\0" \
+	"kernel_addr_r=0x62000000\0" \
+	"ramdisk_addr_r=0x64000000\0"
+
+#include <config_distro_bootcmd.h>
+
+/* Linux fails to load the fdt if it's loaded above 256M on a Rock board,
+ * so limit the fdt reallocation to that */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"fdt_high=0x6fffffff\0" \
+	"initrd_high=0x6fffffff\0" \
+	"partitions=" PARTS_DEFAULT \
+	ENV_MEM_LAYOUT_SETTINGS \
+	ROCKCHIP_DEVICE_SETTINGS \
+	BOOTENV
+
+#endif /* CONFIG_SPL_BUILD */
+
+#define CONFIG_PREBOOT
+
+#endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (11 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 12/16] rockchip: rk3188: Add core support Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards Heiko Stuebner
                   ` (4 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

The sdram controller blocks are very similar to the rk3288 in utilizing
memory scheduler, Designware uPCTL and Designware PUBL blocks, only
limited to one bank instead of two.

There are some minimal differences when setting up the ram, so it gets
a separate driver for the rk3188 but reuses the driver structs, as there
is no need to define the same again.

More optimization can happen when the modelling of the controller parts
in the dts actually follow the hardware layout hopefully at some point
in the future.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h |  22 +
 arch/arm/mach-rockchip/rk3188/Makefile          |   1 +
 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c    | 985 ++++++++++++++++++++++++
 3 files changed, 1008 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
 create mode 100644 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c

diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
new file mode 100644
index 0000000000..993c58d1a8
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
@@ -0,0 +1,22 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_DDR_RK3188_H
+#define _ASM_ARCH_DDR_RK3188_H
+
+#include <asm/arch/ddr_rk3288.h>
+
+struct rk3188_msch {
+	u32 coreid;
+	u32 revisionid;
+	u32 ddrconf;
+	u32 ddrtiming;
+	u32 ddrmode;
+	u32 readlatency;
+};
+check_member(rk3188_msch, readlatency, 0x0014);
+
+#endif
diff --git a/arch/arm/mach-rockchip/rk3188/Makefile b/arch/arm/mach-rockchip/rk3188/Makefile
index 7fa010405b..2dc9511de7 100644
--- a/arch/arm/mach-rockchip/rk3188/Makefile
+++ b/arch/arm/mach-rockchip/rk3188/Makefile
@@ -6,5 +6,6 @@
 
 ifndef CONFIG_TPL_BUILD
 obj-y += clk_rk3188.o
+obj-y += sdram_rk3188.o
 obj-y += syscon_rk3188.o
 endif
diff --git a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c b/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
new file mode 100644
index 0000000000..9e41723c9f
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
@@ -0,0 +1,985 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ *
+ * Adapted from coreboot.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <errno.h>
+#include <ram.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3188.h>
+#include <asm/arch/ddr_rk3188.h>
+#include <asm/arch/grf_rk3188.h>
+#include <asm/arch/pmu_rk3188.h>
+#include <asm/arch/sdram.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct chan_info {
+	struct rk3288_ddr_pctl *pctl;
+	struct rk3288_ddr_publ *publ;
+	struct rk3188_msch *msch;
+};
+
+struct dram_info {
+	struct chan_info chan[1];
+	struct ram_info info;
+	struct clk ddr_clk;
+	struct rk3188_cru *cru;
+	struct rk3188_grf *grf;
+	struct rk3188_sgrf *sgrf;
+	struct rk3188_pmu *pmu;
+};
+
+struct rk3188_sdram_params {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3188_dmc of_plat;
+#endif
+	struct rk3288_sdram_channel ch[2];
+	struct rk3288_sdram_pctl_timing pctl_timing;
+	struct rk3288_sdram_phy_timing phy_timing;
+	struct rk3288_base_params base;
+	int num_channels;
+	struct regmap *map;
+};
+
+#define TEST_PATTEN	0x5aa5f00f
+#define DQS_GATE_TRAINING_ERROR_RANK0	(1 << 4)
+#define DQS_GATE_TRAINING_ERROR_RANK1	(2 << 4)
+
+#ifdef CONFIG_SPL_BUILD
+static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
+{
+	int i;
+
+	for (i = 0; i < n / sizeof(u32); i++) {
+		writel(*src, dest);
+		src++;
+		dest++;
+	}
+}
+
+static void ddr_reset(struct rk3188_cru *cru, u32 ch, u32 ctl, u32 phy)
+{
+	u32 phy_ctl_srstn_shift = 5 + 8 * ch;
+	u32 ctl_psrstn_shift = 3 + 8 * ch;
+	u32 ctl_srstn_shift = 2 + 8 * ch;
+	u32 phy_psrstn_shift = 1 + 8 * ch;
+	u32 phy_srstn_shift = 8 * ch;
+
+	rk_clrsetreg(&cru->cru_softrst_con[5],
+		     1 << phy_ctl_srstn_shift | 1 << ctl_psrstn_shift |
+		     1 << ctl_srstn_shift | 1 << phy_psrstn_shift |
+		     1 << phy_srstn_shift,
+		     phy << phy_ctl_srstn_shift | ctl << ctl_psrstn_shift |
+		     ctl << ctl_srstn_shift | phy << phy_psrstn_shift |
+		     phy << phy_srstn_shift);
+}
+
+static void ddr_phy_ctl_reset(struct rk3188_cru *cru, u32 ch, u32 n)
+{
+	u32 phy_ctl_srstn_shift = 5 + 8 * ch;
+
+	rk_clrsetreg(&cru->cru_softrst_con[5],
+		     1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift);
+}
+
+static void phy_pctrl_reset(struct rk3188_cru *cru,
+			    struct rk3288_ddr_publ *publ,
+			    u32 channel)
+{
+	int i;
+
+	ddr_reset(cru, channel, 1, 1);
+	udelay(1);
+	clrbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST);
+	for (i = 0; i < 4; i++)
+		clrbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST);
+
+	udelay(10);
+	setbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST);
+	for (i = 0; i < 4; i++)
+		setbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST);
+
+	udelay(10);
+	ddr_reset(cru, channel, 1, 0);
+	udelay(10);
+	ddr_reset(cru, channel, 0, 0);
+	udelay(10);
+}
+
+static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ,
+	u32 freq)
+{
+	int i;
+	if (freq <= 250000000) {
+		if (freq <= 150000000)
+			clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
+		else
+			setbits_le32(&publ->dllgcr, SBIAS_BYPASS);
+		setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
+		for (i = 0; i < 4; i++)
+			setbits_le32(&publ->datx8[i].dxdllcr,
+				     DXDLLCR_DLLDIS);
+
+		setbits_le32(&publ->pir, PIR_DLLBYP);
+	} else {
+		clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
+		clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
+		for (i = 0; i < 4; i++) {
+			clrbits_le32(&publ->datx8[i].dxdllcr,
+				     DXDLLCR_DLLDIS);
+		}
+
+		clrbits_le32(&publ->pir, PIR_DLLBYP);
+	}
+}
+
+static void dfi_cfg(struct rk3288_ddr_pctl *pctl, u32 dramtype)
+{
+	writel(DFI_INIT_START, &pctl->dfistcfg0);
+	writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN,
+	       &pctl->dfistcfg1);
+	writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2);
+	writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN,
+	       &pctl->dfilpcfg0);
+
+	writel(2 << TCTRL_DELAY_TIME_SHIFT, &pctl->dfitctrldelay);
+	writel(1 << TPHY_WRDATA_TIME_SHIFT, &pctl->dfitphywrdata);
+	writel(0xf << TPHY_RDLAT_TIME_SHIFT, &pctl->dfitphyrdlat);
+	writel(2 << TDRAM_CLK_DIS_TIME_SHIFT, &pctl->dfitdramclkdis);
+	writel(2 << TDRAM_CLK_EN_TIME_SHIFT, &pctl->dfitdramclken);
+	writel(1, &pctl->dfitphyupdtype0);
+
+	/* cs0 and cs1 write odt enable */
+	writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL),
+	       &pctl->dfiodtcfg);
+	/* odt write length */
+	writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1);
+	/* phyupd and ctrlupd disabled */
+	writel(0, &pctl->dfiupdcfg);
+}
+
+static void ddr_set_enable(struct rk3188_grf *grf, uint channel, bool enable)
+{
+	uint val = 0;
+
+	if (enable)
+		val = 1 << DDR_16BIT_EN_SHIFT;
+
+	rk_clrsetreg(&grf->ddrc_con0, 1 << DDR_16BIT_EN_SHIFT, val);
+}
+
+static void ddr_set_ddr3_mode(struct rk3188_grf *grf, uint channel,
+			      bool ddr3_mode)
+{
+	uint mask, val;
+
+	mask = 1 << MSCH4_MAINDDR3_SHIFT;
+	val = ddr3_mode << MSCH4_MAINDDR3_SHIFT;
+	rk_clrsetreg(&grf->soc_con2, mask, val);
+}
+
+#define RANK_2_ROW15_EN 1
+static void ddr_rank_2_row15en(struct rk3188_grf *grf, bool enable)
+{
+	uint mask, val;
+
+	mask = 1 << RANK_2_ROW15_EN;
+	val = enable << RANK_2_ROW15_EN;
+	rk_clrsetreg(&grf->soc_con2, mask, val);
+}
+
+static void pctl_cfg(u32 channel, struct rk3288_ddr_pctl *pctl,
+		     struct rk3188_sdram_params *sdram_params,
+		     struct rk3188_grf *grf)
+{
+	copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u,
+		    sizeof(sdram_params->pctl_timing));
+	switch (sdram_params->base.dramtype) {
+	case DDR3:
+		if (sdram_params->phy_timing.mr[1] & DDR3_DLL_DISABLE) {
+			writel(sdram_params->pctl_timing.tcl - 3,
+			       &pctl->dfitrddataen);
+		} else {
+			writel(sdram_params->pctl_timing.tcl - 2,
+			       &pctl->dfitrddataen);
+		}
+		writel(sdram_params->pctl_timing.tcwl - 1,
+		       &pctl->dfitphywrlat);
+		writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN |
+		       DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW |
+		       1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+		       &pctl->mcfg);
+		ddr_set_ddr3_mode(grf, channel, true);
+		ddr_set_enable(grf, channel, true);
+		break;
+	}
+
+	setbits_le32(&pctl->scfg, 1);
+}
+
+static void phy_cfg(const struct chan_info *chan, u32 channel,
+		    struct rk3188_sdram_params *sdram_params)
+{
+	struct rk3288_ddr_publ *publ = chan->publ;
+	struct rk3188_msch *msch = chan->msch;
+	uint ddr_freq_mhz = sdram_params->base.ddr_freq / 1000000;
+	u32 dinit2;
+	int i;
+
+	dinit2 = DIV_ROUND_UP(ddr_freq_mhz * 200000, 1000);
+	/* DDR PHY Timing */
+	copy_to_reg(&publ->dtpr[0], &sdram_params->phy_timing.dtpr0,
+		    sizeof(sdram_params->phy_timing));
+	writel(sdram_params->base.noc_timing, &msch->ddrtiming);
+	writel(0x3f, &msch->readlatency);
+	writel(DIV_ROUND_UP(ddr_freq_mhz * 5120, 1000) << PRT_DLLLOCK_SHIFT |
+	       DIV_ROUND_UP(ddr_freq_mhz * 50, 1000) << PRT_DLLSRST_SHIFT |
+	       8 << PRT_ITMSRST_SHIFT, &publ->ptr[0]);
+	writel(DIV_ROUND_UP(ddr_freq_mhz * 500000, 1000) << PRT_DINIT0_SHIFT |
+	       DIV_ROUND_UP(ddr_freq_mhz * 400, 1000) << PRT_DINIT1_SHIFT,
+	       &publ->ptr[1]);
+	writel(min(dinit2, 0x1ffffU) << PRT_DINIT2_SHIFT |
+	       DIV_ROUND_UP(ddr_freq_mhz * 1000, 1000) << PRT_DINIT3_SHIFT,
+	       &publ->ptr[2]);
+
+	switch (sdram_params->base.dramtype) {
+	case DDR3:
+		clrbits_le32(&publ->pgcr, 0x1f);
+		clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT,
+				DDRMD_DDR3 << DDRMD_SHIFT);
+		break;
+	}
+	if (sdram_params->base.odt) {
+		/*dynamic RTT enable */
+		for (i = 0; i < 4; i++)
+			setbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT);
+	} else {
+		/*dynamic RTT disable */
+		for (i = 0; i < 4; i++)
+			clrbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT);
+	}
+}
+
+static void phy_init(struct rk3288_ddr_publ *publ)
+{
+	setbits_le32(&publ->pir, PIR_INIT | PIR_DLLSRST
+		| PIR_DLLLOCK | PIR_ZCAL | PIR_ITMSRST | PIR_CLRSR);
+	udelay(1);
+	while ((readl(&publ->pgsr) &
+		(PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) !=
+		(PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE))
+		;
+}
+
+static void send_command(struct rk3288_ddr_pctl *pctl, u32 rank,
+			 u32 cmd, u32 arg)
+{
+	writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
+	udelay(1);
+	while (readl(&pctl->mcmd) & START_CMD)
+		;
+}
+
+static inline void send_command_op(struct rk3288_ddr_pctl *pctl,
+				   u32 rank, u32 cmd, u32 ma, u32 op)
+{
+	send_command(pctl, rank, cmd, (ma & LPDDR2_MA_MASK) << LPDDR2_MA_SHIFT |
+		     (op & LPDDR2_OP_MASK) << LPDDR2_OP_SHIFT);
+}
+
+static void memory_init(struct rk3288_ddr_publ *publ,
+			u32 dramtype)
+{
+	setbits_le32(&publ->pir,
+		     (PIR_INIT | PIR_DRAMINIT | PIR_LOCKBYP
+		      | PIR_ZCALBYP | PIR_CLRSR | PIR_ICPC
+		      | (dramtype == DDR3 ? PIR_DRAMRST : 0)));
+	udelay(1);
+	while ((readl(&publ->pgsr) & (PGSR_IDONE | PGSR_DLDONE))
+		!= (PGSR_IDONE | PGSR_DLDONE))
+		;
+}
+
+static void move_to_config_state(struct rk3288_ddr_publ *publ,
+				 struct rk3288_ddr_pctl *pctl)
+{
+	unsigned int state;
+
+	while (1) {
+		state = readl(&pctl->stat) & PCTL_STAT_MSK;
+
+		switch (state) {
+		case LOW_POWER:
+			writel(WAKEUP_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MSK)
+				!= ACCESS)
+				;
+			/* wait DLL lock */
+			while ((readl(&publ->pgsr) & PGSR_DLDONE)
+				!= PGSR_DLDONE)
+				;
+			/* if at low power state,need wakeup first,
+			 * and then enter the config, so
+			 * fallthrough
+			 */
+		case ACCESS:
+			/* fallthrough */
+		case INIT_MEM:
+			writel(CFG_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
+				;
+			break;
+		case CONFIG:
+			return;
+		default:
+			break;
+		}
+	}
+}
+
+static void set_bandwidth_ratio(const struct chan_info *chan, u32 channel,
+				u32 n, struct rk3188_grf *grf)
+{
+	struct rk3288_ddr_pctl *pctl = chan->pctl;
+	struct rk3288_ddr_publ *publ = chan->publ;
+	struct rk3188_msch *msch = chan->msch;
+
+	if (n == 1) {
+		setbits_le32(&pctl->ppcfg, 1);
+		ddr_set_enable(grf, channel, 1);
+		setbits_le32(&msch->ddrtiming, 1 << 31);
+		/* Data Byte disable*/
+		clrbits_le32(&publ->datx8[2].dxgcr, 1);
+		clrbits_le32(&publ->datx8[3].dxgcr, 1);
+		/* disable DLL */
+		setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
+		setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
+	} else {
+		clrbits_le32(&pctl->ppcfg, 1);
+		ddr_set_enable(grf, channel, 0);
+		clrbits_le32(&msch->ddrtiming, 1 << 31);
+		/* Data Byte enable*/
+		setbits_le32(&publ->datx8[2].dxgcr, 1);
+		setbits_le32(&publ->datx8[3].dxgcr, 1);
+
+		/* enable DLL */
+		clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
+		clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
+		/* reset DLL */
+		clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST);
+		clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST);
+		udelay(10);
+		setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST);
+		setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST);
+	}
+	setbits_le32(&pctl->dfistcfg0, 1 << 2);
+}
+
+static int data_training(const struct chan_info *chan, u32 channel,
+			 struct rk3188_sdram_params *sdram_params)
+{
+	unsigned int j;
+	int ret = 0;
+	u32 rank;
+	int i;
+	u32 step[2] = { PIR_QSTRN, PIR_RVTRN };
+	struct rk3288_ddr_publ *publ = chan->publ;
+	struct rk3288_ddr_pctl *pctl = chan->pctl;
+
+	/* disable auto refresh */
+	writel(0, &pctl->trefi);
+
+	if (sdram_params->base.dramtype != LPDDR3)
+		setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
+	rank = sdram_params->ch[channel].rank | 1;
+	for (j = 0; j < ARRAY_SIZE(step); j++) {
+		/*
+		 * trigger QSTRN and RVTRN
+		 * clear DTDONE status
+		 */
+		setbits_le32(&publ->pir, PIR_CLRSR);
+
+		/* trigger DTT */
+		setbits_le32(&publ->pir,
+			     PIR_INIT | step[j] | PIR_LOCKBYP | PIR_ZCALBYP |
+			     PIR_CLRSR);
+		udelay(1);
+		/* wait echo byte DTDONE */
+		while ((readl(&publ->datx8[0].dxgsr[0]) & rank)
+			!= rank)
+			;
+		while ((readl(&publ->datx8[1].dxgsr[0]) & rank)
+			!= rank)
+			;
+		if (!(readl(&pctl->ppcfg) & 1)) {
+			while ((readl(&publ->datx8[2].dxgsr[0])
+				& rank) != rank)
+				;
+			while ((readl(&publ->datx8[3].dxgsr[0])
+				& rank) != rank)
+				;
+		}
+		if (readl(&publ->pgsr) &
+		    (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) {
+			ret = -1;
+			break;
+		}
+	}
+	/* send some auto refresh to complement the lost while DTT */
+	for (i = 0; i < (rank > 1 ? 8 : 4); i++)
+		send_command(pctl, rank, REF_CMD, 0);
+
+	if (sdram_params->base.dramtype != LPDDR3)
+		clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
+
+	/* resume auto refresh */
+	writel(sdram_params->pctl_timing.trefi, &pctl->trefi);
+
+	return ret;
+}
+
+static void move_to_access_state(const struct chan_info *chan)
+{
+	struct rk3288_ddr_publ *publ = chan->publ;
+	struct rk3288_ddr_pctl *pctl = chan->pctl;
+	unsigned int state;
+
+	while (1) {
+		state = readl(&pctl->stat) & PCTL_STAT_MSK;
+
+		switch (state) {
+		case LOW_POWER:
+			if (((readl(&pctl->stat) >> LP_TRIG_SHIFT) &
+					LP_TRIG_MASK) == 1)
+				return;
+
+			writel(WAKEUP_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS)
+				;
+			/* wait DLL lock */
+			while ((readl(&publ->pgsr) & PGSR_DLDONE)
+				!= PGSR_DLDONE)
+				;
+			break;
+		case INIT_MEM:
+			writel(CFG_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
+				;
+			/* fallthrough */
+		case CONFIG:
+			writel(GO_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MSK) == CONFIG)
+				;
+			break;
+		case ACCESS:
+			return;
+		default:
+			break;
+		}
+	}
+}
+
+static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum,
+			 struct rk3188_sdram_params *sdram_params)
+{
+	struct rk3288_ddr_publ *publ = chan->publ;
+
+	if (sdram_params->ch[chnum].bk == 3)
+		clrsetbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT,
+				1 << PDQ_SHIFT);
+	else
+		clrbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT);
+
+	writel(sdram_params->base.ddrconfig, &chan->msch->ddrconf);
+}
+
+static void dram_all_config(const struct dram_info *dram,
+			    struct rk3188_sdram_params *sdram_params)
+{
+	unsigned int chan;
+	u32 sys_reg = 0;
+
+	sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT;
+	sys_reg |= (sdram_params->num_channels - 1) << SYS_REG_NUM_CH_SHIFT;
+	for (chan = 0; chan < sdram_params->num_channels; chan++) {
+		const struct rk3288_sdram_channel *info =
+			&sdram_params->ch[chan];
+
+		sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan);
+		sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(chan);
+		sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan);
+		sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan);
+		sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(chan);
+		sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan);
+		sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan);
+		sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(chan);
+		sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(chan);
+
+		dram_cfg_rbc(&dram->chan[chan], chan, sdram_params);
+	}
+	if (sdram_params->ch[0].rank == 2)
+		ddr_rank_2_row15en(dram->grf, 0);
+	else
+		ddr_rank_2_row15en(dram->grf, 1);
+	writel(sys_reg, &dram->pmu->sys_reg[2]);
+}
+const int ddrconf_table[] = {
+	/*
+	 * [5:4] row(13+n)
+	 * [1:0] col(9+n), assume bw=2
+	 * row	    col,bw */
+	0,
+	((2 << 4) | 1),
+	((1 << 4) | 1),
+	((0 << 4) | 1),
+	((2 << 4) | 2),
+	((1 << 4) | 2),
+	((0 << 4) | 2),
+	((1 << 4) | 0),
+	((0 << 4) | 0),
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+};
+
+static int sdram_rank_bw_detect(struct dram_info *dram, int channel,
+		struct rk3188_sdram_params *sdram_params)
+{
+	int reg;
+	int need_trainig = 0;
+	const struct chan_info *chan = &dram->chan[channel];
+	struct rk3288_ddr_publ *publ = chan->publ;
+
+	ddr_rank_2_row15en(dram->grf, 0);
+
+	if (-1 == data_training(chan, channel, sdram_params)) {
+		printf("first data training fail!\n");
+		reg = readl(&publ->datx8[0].dxgsr[0]);
+		/* Check the result for rank 0 */
+		if ((channel == 0) && (reg & DQS_GATE_TRAINING_ERROR_RANK0)) {
+			printf("data training fail!\n");
+				return -EIO;
+		}
+
+		/* Check the result for rank 1 */
+		if (reg & DQS_GATE_TRAINING_ERROR_RANK1) {
+			sdram_params->ch[channel].rank = 1;
+			clrsetbits_le32(&publ->pgcr, 0xF << 18,
+					sdram_params->ch[channel].rank << 18);
+			need_trainig = 1;
+		}
+		reg = readl(&publ->datx8[2].dxgsr[0]);
+		if (reg & (1 << 4)) {
+			sdram_params->ch[channel].bw = 1;
+			set_bandwidth_ratio(chan, channel,
+					    sdram_params->ch[channel].bw,
+					    dram->grf);
+			need_trainig = 1;
+		}
+	}
+	/* Assume the Die bit width are the same with the chip bit width */
+	sdram_params->ch[channel].dbw = sdram_params->ch[channel].bw;
+
+	if (need_trainig &&
+	    (-1 == data_training(chan, channel, sdram_params))) {
+		if (sdram_params->base.dramtype == LPDDR3) {
+			ddr_phy_ctl_reset(dram->cru, channel, 1);
+			udelay(10);
+			ddr_phy_ctl_reset(dram->cru, channel, 0);
+			udelay(10);
+		}
+		printf("2nd data training failed!");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int sdram_col_row_detect(struct dram_info *dram, int channel,
+		struct rk3188_sdram_params *sdram_params)
+{
+	int row, col;
+	unsigned int addr;
+	const struct chan_info *chan = &dram->chan[channel];
+	struct rk3288_ddr_pctl *pctl = chan->pctl;
+	struct rk3288_ddr_publ *publ = chan->publ;
+	int ret = 0;
+
+	/* Detect col */
+	for (col = 11; col >= 9; col--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		addr = CONFIG_SYS_SDRAM_BASE +
+			(1 << (col + sdram_params->ch[channel].bw - 1));
+		writel(TEST_PATTEN, addr);
+		if ((readl(addr) == TEST_PATTEN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (col == 8) {
+		printf("Col detect error\n");
+		ret = -EINVAL;
+		goto out;
+	} else {
+		sdram_params->ch[channel].col = col;
+	}
+
+	ddr_rank_2_row15en(dram->grf, 1);
+	move_to_config_state(publ, pctl);
+	writel(1, &chan->msch->ddrconf);
+	move_to_access_state(chan);
+	/* Detect row, max 15,min13 in rk3188*/
+	for (row = 16; row >= 13; row--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		addr = CONFIG_SYS_SDRAM_BASE + (1 << (row + 15 - 1));
+		writel(TEST_PATTEN, addr);
+		if ((readl(addr) == TEST_PATTEN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (row == 12) {
+		printf("Row detect error\n");
+		ret = -EINVAL;
+	} else {
+		sdram_params->ch[channel].cs1_row = row;
+		sdram_params->ch[channel].row_3_4 = 0;
+		printf("chn %d col %d, row %d\n", channel, col, row);
+		sdram_params->ch[channel].cs0_row = row;
+	}
+
+out:
+	return ret;
+}
+
+static int sdram_get_niu_config(struct rk3188_sdram_params *sdram_params)
+{
+	int i, tmp, size, ret = 0;
+
+	tmp = sdram_params->ch[0].col - 9;
+	tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1;
+	tmp |= ((sdram_params->ch[0].cs0_row - 13) << 4);
+	size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]);
+	for (i = 0; i < size; i++)
+		if (tmp == ddrconf_table[i])
+			break;
+	if (i >= size) {
+		printf("niu config not found\n");
+		ret = -EINVAL;
+	} else {
+		printf("niu config %d\n", i);
+		sdram_params->base.ddrconfig = i;
+	}
+
+	return ret;
+}
+
+static int sdram_init(struct dram_info *dram,
+		      struct rk3188_sdram_params *sdram_params)
+{
+	int channel;
+	int zqcr;
+	int ret;
+
+	printf("%s start 001\n", __func__);
+	if ((sdram_params->base.dramtype == DDR3 &&
+	     sdram_params->base.ddr_freq > 800000000)) {
+		printf("SDRAM frequency is too high!");
+		return -E2BIG;
+	}
+
+	ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq);
+	printf("ret=%d\n", ret);
+	if (ret) {
+		printf("Could not set DDR clock\n");
+		return ret;
+	}
+
+	for (channel = 0; channel < 1; channel++) {
+		const struct chan_info *chan = &dram->chan[channel];
+		struct rk3288_ddr_pctl *pctl = chan->pctl;
+		struct rk3288_ddr_publ *publ = chan->publ;
+
+		phy_pctrl_reset(dram->cru, publ, channel);
+		phy_dll_bypass_set(publ, sdram_params->base.ddr_freq);
+
+		dfi_cfg(pctl, sdram_params->base.dramtype);
+
+		pctl_cfg(channel, pctl, sdram_params, dram->grf);
+
+		phy_cfg(chan, channel, sdram_params);
+
+		phy_init(publ);
+
+		writel(POWER_UP_START, &pctl->powctl);
+		while (!(readl(&pctl->powstat) & POWER_UP_DONE))
+			;
+
+		memory_init(publ, sdram_params->base.dramtype);
+		move_to_config_state(publ, pctl);
+
+		/* Using 32bit bus width for detect */
+		sdram_params->ch[channel].bw = 2;
+		set_bandwidth_ratio(chan, channel,
+				    sdram_params->ch[channel].bw, dram->grf);
+		/*
+		 * set cs, using n=3 for detect
+		 * CS0, n=1
+		 * CS1, n=2
+		 * CS0 & CS1, n = 3
+		 */
+		sdram_params->ch[channel].rank = 2,
+		clrsetbits_le32(&publ->pgcr, 0xF << 18,
+				(sdram_params->ch[channel].rank | 1) << 18);
+
+		/* DS=40ohm,ODT=155ohm */
+		zqcr = 1 << ZDEN_SHIFT | 2 << PU_ONDIE_SHIFT |
+			2 << PD_ONDIE_SHIFT | 0x19 << PU_OUTPUT_SHIFT |
+			0x19 << PD_OUTPUT_SHIFT;
+		writel(zqcr, &publ->zq1cr[0]);
+		writel(zqcr, &publ->zq0cr[0]);
+
+		/* Detect the rank and bit-width with data-training */
+		writel(1, &chan->msch->ddrconf);
+		sdram_rank_bw_detect(dram, channel, sdram_params);
+
+		if (sdram_params->base.dramtype == LPDDR3) {
+			u32 i;
+			writel(0, &pctl->mrrcfg0);
+			for (i = 0; i < 17; i++)
+				send_command_op(pctl, 1, MRR_CMD, i, 0);
+		}
+		writel(4, &chan->msch->ddrconf);
+		move_to_access_state(chan);
+		/* DDR3 and LPDDR3 are always 8 bank, no need detect */
+		sdram_params->ch[channel].bk = 3;
+		/* Detect Col and Row number*/
+		ret = sdram_col_row_detect(dram, channel, sdram_params);
+		if (ret)
+			goto error;
+	}
+	/* Find NIU DDR configuration */
+	ret = sdram_get_niu_config(sdram_params);
+	if (ret)
+		goto error;
+
+	dram_all_config(dram, sdram_params);
+	printf("%s done\n", __func__);
+
+	return 0;
+error:
+	printf("DRAM init failed!\n");
+	hang();
+}
+#endif /* CONFIG_SPL_BUILD */
+
+size_t sdram_size_mb(struct rk3188_pmu *pmu)
+{
+	u32 rank, col, bk, cs0_row, cs1_row, bw, row_3_4;
+	size_t chipsize_mb = 0;
+	size_t size_mb = 0;
+	u32 ch;
+	u32 sys_reg = readl(&pmu->sys_reg[2]);
+	u32 chans;
+
+	chans = 1 + ((sys_reg >> SYS_REG_NUM_CH_SHIFT) & SYS_REG_NUM_CH_MASK);
+
+	for (ch = 0; ch < chans; ch++) {
+		rank = 1 + (sys_reg >> SYS_REG_RANK_SHIFT(ch) &
+			SYS_REG_RANK_MASK);
+		col = 9 + (sys_reg >> SYS_REG_COL_SHIFT(ch) & SYS_REG_COL_MASK);
+		bk = 3 - ((sys_reg >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK);
+		cs0_row = 13 + (sys_reg >> SYS_REG_CS0_ROW_SHIFT(ch) &
+				SYS_REG_CS0_ROW_MASK);
+		cs1_row = 13 + (sys_reg >> SYS_REG_CS1_ROW_SHIFT(ch) &
+				SYS_REG_CS1_ROW_MASK);
+		bw = (2 >> ((sys_reg >> SYS_REG_BW_SHIFT(ch)) &
+			SYS_REG_BW_MASK));
+		row_3_4 = sys_reg >> SYS_REG_ROW_3_4_SHIFT(ch) &
+			SYS_REG_ROW_3_4_MASK;
+		chipsize_mb = (1 << (cs0_row + col + bk + bw - 20));
+
+		if (rank > 1)
+			chipsize_mb += chipsize_mb >>
+				(cs0_row - cs1_row);
+		if (row_3_4)
+			chipsize_mb = chipsize_mb * 3 / 4;
+		size_mb += chipsize_mb;
+	}
+
+	/* there can be no more than 2gb of memory */
+	size_mb = min(size_mb, 0x80000000 >> 20);
+
+	return size_mb;
+}
+
+#ifdef CONFIG_SPL_BUILD
+static int setup_sdram(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct rk3188_sdram_params *params = dev_get_platdata(dev);
+
+	return sdram_init(priv, params);
+}
+
+static int rk3188_dmc_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3188_sdram_params *params = dev_get_platdata(dev);
+	const void *blob = gd->fdt_blob;
+	int node = dev->of_offset;
+	int ret;
+
+	/* rk3188 supports only one-channel */
+	params->num_channels = 1;
+	ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
+				   (u32 *)&params->pctl_timing,
+				   sizeof(params->pctl_timing) / sizeof(u32));
+	if (ret) {
+		printf("%s: Cannot read rockchip,pctl-timing\n", __func__);
+		return -EINVAL;
+	}
+	ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
+				   (u32 *)&params->phy_timing,
+				   sizeof(params->phy_timing) / sizeof(u32));
+	if (ret) {
+		printf("%s: Cannot read rockchip,phy-timing\n", __func__);
+		return -EINVAL;
+	}
+	ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
+				   (u32 *)&params->base,
+				   sizeof(params->base) / sizeof(u32));
+	if (ret) {
+		printf("%s: Cannot read rockchip,sdram-params\n", __func__);
+		return -EINVAL;
+	}
+	ret = regmap_init_mem(dev, &params->map);
+	if (ret)
+		return ret;
+#endif
+
+	return 0;
+}
+#endif /* CONFIG_SPL_BUILD */
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+	struct rk3188_sdram_params *plat = dev_get_platdata(dev);
+	struct dtd_rockchip_rk3188_dmc *of_plat = &plat->of_plat;
+	int ret;
+
+	memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing,
+	       sizeof(plat->pctl_timing));
+	memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing,
+	       sizeof(plat->phy_timing));
+	memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
+	/* rk3188 supports dual-channel, set default channel num to 2 */
+	plat->num_channels = 1;
+	ret = regmap_init_mem_platdata(dev, of_plat->reg,
+				       ARRAY_SIZE(of_plat->reg) / 2,
+				       &plat->map);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+#endif
+
+static int rk3188_dmc_probe(struct udevice *dev)
+{
+#ifdef CONFIG_SPL_BUILD
+	struct rk3188_sdram_params *plat = dev_get_platdata(dev);
+#endif
+	struct dram_info *priv = dev_get_priv(dev);
+	struct regmap *map;
+	int ret;
+	struct udevice *dev_clk;
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	ret = conv_of_platdata(dev);
+	if (ret)
+		return ret;
+#endif
+	map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+	priv->chan[0].msch = regmap_get_range(map, 0);
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
+
+#ifdef CONFIG_SPL_BUILD
+	priv->chan[0].pctl = regmap_get_range(plat->map, 0);
+	priv->chan[0].publ = regmap_get_range(plat->map, 1);
+#endif
+
+	ret = rockchip_get_clk(&dev_clk);
+	if (ret)
+		return ret;
+	priv->ddr_clk.id = CLK_DDR;
+	ret = clk_request(dev_clk, &priv->ddr_clk);
+	if (ret)
+		return ret;
+
+	priv->cru = rockchip_get_cru();
+	if (IS_ERR(priv->cru))
+		return PTR_ERR(priv->cru);
+#ifdef CONFIG_SPL_BUILD
+	ret = setup_sdram(dev);
+	if (ret)
+		return ret;
+#endif
+	priv->info.base = 0;
+	priv->info.size = sdram_size_mb(priv->pmu) << 20;
+
+	return 0;
+}
+
+static int rk3188_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	*info = priv->info;
+
+	return 0;
+}
+
+static struct ram_ops rk3188_dmc_ops = {
+	.get_info = rk3188_dmc_get_info,
+};
+
+static const struct udevice_id rk3188_dmc_ids[] = {
+	{ .compatible = "rockchip,rk3188-dmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(dmc_rk3188) = {
+	.name = "rockchip_rk3188_dmc",
+	.id = UCLASS_RAM,
+	.of_match = rk3188_dmc_ids,
+	.ops = &rk3188_dmc_ops,
+#ifdef CONFIG_SPL_BUILD
+	.ofdata_to_platdata = rk3188_dmc_ofdata_to_platdata,
+#endif
+	.probe = rk3188_dmc_probe,
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+#ifdef CONFIG_SPL_BUILD
+	.platdata_auto_alloc_size = sizeof(struct rk3188_sdram_params),
+#endif
+};
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (12 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 15/16] rockchip: rk3188: Add Radxa Rock board Heiko Stuebner
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

The rk3188 needs 3 uboot stages: a tpl living in 1KB of sram, a spl
the resides in the rest of the sram and loads the regular uboot living
in regular ram.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/arm/mach-rockchip/Makefile           |   7 +-
 arch/arm/mach-rockchip/rk3188-board-spl.c | 220 ++++++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rk3188-board-tpl.c |  87 ++++++++++++
 arch/arm/mach-rockchip/rk3188-board.c     |  71 ++++++++++
 4 files changed, 384 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-rockchip/rk3188-board-spl.c
 create mode 100644 arch/arm/mach-rockchip/rk3188-board-tpl.c
 create mode 100644 arch/arm/mach-rockchip/rk3188-board.c

diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 2be7e14e3e..7b8abc2266 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -4,11 +4,16 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_TPL_BUILD
+obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
+obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
+else ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
+obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
 obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
 else
+obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
 endif
diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c
new file mode 100644
index 0000000000..b528a2f73d
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188-board-spl.c
@@ -0,0 +1,220 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <led.h>
+#include <malloc.h>
+#include <ram.h>
+#include <spl.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3188.h>
+#include <asm/arch/sdram.h>
+#include <asm/arch/timer.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/util.h>
+#include <power/regulator.h>
+#include <syscon.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	const void *blob = gd->fdt_blob;
+	struct udevice *dev;
+	const char *bootdev;
+	int node;
+	int ret;
+
+	bootdev = fdtdec_get_config_string(blob, "u-boot,boot0");
+	debug("Boot device %s\n", bootdev);
+	if (!bootdev)
+		goto fallback;
+
+	node = fdt_path_offset(blob, bootdev);
+	if (node < 0) {
+		debug("node=%d\n", node);
+		goto fallback;
+	}
+	ret = device_get_global_by_of_offset(node, &dev);
+	if (ret) {
+		debug("device@node %s/%d not found: %d\n", bootdev, node,
+		      ret);
+		goto fallback;
+	}
+	debug("Found device %s\n", dev->name);
+	switch (device_get_uclass_id(dev)) {
+	case UCLASS_SPI_FLASH:
+		return BOOT_DEVICE_SPI;
+	case UCLASS_MMC:
+		return BOOT_DEVICE_MMC1;
+	default:
+		debug("Booting from device uclass '%s' not supported\n",
+		      dev_get_uclass_name(dev));
+	}
+
+fallback:
+#endif
+	return BOOT_DEVICE_MMC1;
+}
+
+u32 spl_boot_mode(const u32 boot_device)
+{
+	return MMCSD_MODE_RAW;
+}
+
+extern u32 SAVE_SP_ADDR;
+extern void back_to_bootrom(void);
+void board_init_f(ulong dummy)
+{
+	struct udevice *pinctrl, *dev;
+	struct rk3188_pmu *pmu;
+	int ret;
+
+#define EARLY_UART
+	/* Example code showing how to enable the debug UART on RK3188 */
+#ifdef EARLY_UART
+#include <asm/arch/grf_rk3188.h>
+	/* Enable early UART on the RK3188 */
+#define GRF_BASE	0x20008000
+	struct rk3188_grf * const grf = (void *)GRF_BASE;
+
+	rk_clrsetreg(&grf->gpio1b_iomux,
+		     GPIO1B1_MASK << GPIO1B1_SHIFT |
+		     GPIO1B0_MASK << GPIO1B0_SHIFT,
+		     GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
+		     GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+	debug_uart_init();
+	printch('s');
+	printch('p');
+	printch('l');
+	printch('\n');
+#endif
+
+	ret = spl_init();
+	if (ret) {
+		debug("spl_init() failed: %d\n", ret);
+		hang();
+	}
+
+	rockchip_timer_init();
+
+	ret = rockchip_get_clk(&dev);
+	if (ret) {
+		debug("CLK init failed: %d\n", ret);
+		return;
+	}
+
+	/*
+	 * Recover the bootrom's stackpointer.
+	 * For whatever reason needs to run after rockchip_get_clk.
+	 */
+	pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
+	if (IS_ERR(pmu))
+		error("pmu syscon returned %ld\n", PTR_ERR(pmu));
+	SAVE_SP_ADDR = readl(&pmu->sys_reg[2]);
+
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("Pinctrl init failed: %d\n", ret);
+		return;
+	}
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return;
+	}
+
+#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
+	back_to_bootrom();
+#endif
+}
+
+static int setup_led(void)
+{
+#ifdef CONFIG_SPL_LED
+	struct udevice *dev;
+	char *led_name;
+	int ret;
+
+	led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led");
+	if (!led_name)
+		return 0;
+	ret = led_get_by_label(led_name, &dev);
+	if (ret) {
+		debug("%s: get=%d\n", __func__, ret);
+		return ret;
+	}
+	ret = led_set_on(dev, 1);
+	if (ret)
+		return ret;
+#endif
+
+	return 0;
+}
+
+void spl_board_init(void)
+{
+	struct udevice *pinctrl;
+	int ret;
+
+	ret = setup_led();
+	if (ret) {
+		debug("LED ret=%d\n", ret);
+		hang();
+	}
+
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("%s: Cannot find pinctrl device\n", __func__);
+		goto err;
+	}
+
+#ifdef CONFIG_SPL_MMC_SUPPORT
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
+	if (ret) {
+		debug("%s: Failed to set up SD card\n", __func__);
+		goto err;
+	}
+#endif
+
+	/* Enable debug UART */
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
+	if (ret) {
+		debug("%s: Failed to set up console UART\n", __func__);
+		goto err;
+	}
+
+	preloader_console_init();
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+	back_to_bootrom();
+#endif
+	return;
+
+err:
+	printf("spl_board_init: Error %d\n", ret);
+
+	/* No way to report error here */
+	hang();
+}
diff --git a/arch/arm/mach-rockchip/rk3188-board-tpl.c b/arch/arm/mach-rockchip/rk3188-board-tpl.c
new file mode 100644
index 0000000000..62cdb8976a
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188-board-tpl.c
@@ -0,0 +1,87 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/pmu_rk3188.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* track how often we were entered */
+static int rk3188_num_entries;
+extern void back_to_bootrom(void);
+
+#define PMU_BASE	0x20004000
+#define TPL_ENTRY	0x10080C00
+extern u32 SAVE_SP_ADDR;
+static void jump_to_tpl(void)
+{
+	typedef void __noreturn (*image_entry_noargs_t)(void);
+
+	struct rk3188_pmu * const pmu = (void *)PMU_BASE;
+	image_entry_noargs_t tpl_entry =
+		(image_entry_noargs_t)(unsigned long)TPL_ENTRY;
+
+	/* Store the SAVE_SP_ADDR in a location shared with TPL. */
+	writel(SAVE_SP_ADDR, &pmu->sys_reg[2]);
+	tpl_entry();
+}
+
+void board_init_f(ulong dummy)
+{
+#define EARLY_UART
+	/* Example code showing how to enable the debug UART on RK3188 */
+#ifdef EARLY_UART
+#include <asm/arch/grf_rk3188.h>
+	/* Enable early UART on the RK3188 */
+#define GRF_BASE	0x20008000
+	struct rk3188_grf * const grf = (void *)GRF_BASE;
+
+	rk_clrsetreg(&grf->gpio1b_iomux,
+		     GPIO1B1_MASK << GPIO1B1_SHIFT |
+		     GPIO1B0_MASK << GPIO1B0_SHIFT,
+		     GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
+		     GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+	debug_uart_init();
+
+	printch('t');
+	printch('p');
+	printch('l');
+	printch('-');
+	printch(rk3188_num_entries + 1 + '0');
+	printch('\n');
+#endif
+
+	rk3188_num_entries++;
+
+	if (rk3188_num_entries == 1) {
+		/*
+		 * The original loader did some very basic integrity
+		 * checking at this point, but the remaining few bytes
+		 * could be used for any improvement making sense
+		 * really early on.
+		 */
+
+		back_to_bootrom();
+	} else {
+		/*
+		 * TPL part of the loader should now wait for us
+		 *@offset 0xC00 in the sram. Should never return
+		 * from there.
+		 */
+		jump_to_tpl();
+	}
+}
diff --git a/arch/arm/mach-rockchip/rk3188-board.c b/arch/arm/mach-rockchip/rk3188-board.c
new file mode 100644
index 0000000000..16f38559af
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3188-board.c
@@ -0,0 +1,71 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3288.h>
+#include <asm/arch/boot_mode.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM)
+	struct udevice *pinctrl;
+	int ret;
+
+	/*
+	 * We need to implement sdcard iomux here for the further
+	 * initialization, otherwise, it'll hit sdcard command sending
+	 * timeout exception.
+	 */
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("%s: Cannot find pinctrl device\n", __func__);
+		goto err;
+	}
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
+	if (ret) {
+		debug("%s: Failed to set up SD card\n", __func__);
+		goto err;
+	}
+
+	return 0;
+err:
+	printf("board_init: Error %d\n", ret);
+
+	/* No way to report error here */
+	hang();
+
+	return -1;
+#else
+	return 0;
+#endif
+}
+
+int dram_init(void)
+{
+	/* FIXME: read back ram size from sys_reg2 */
+	gd->ram_size = 0x40000000;
+
+	return 0;
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 15/16] rockchip: rk3188: Add Radxa Rock board
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (13 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-03 16:09 ` [U-Boot] [TEST-ONLY 16/16] Add a temporary script that can create a bootimage for rk3188 Heiko Stuebner
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

The Rock is a RK3188 based single board computer by Radxa.
Currently it still relies on the proprietary DDR init and
cannot use the generic SPL, but at least is able to boot
a linux kernel and system up to a regular login prompt.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/arm/dts/Makefile                 |   1 +
 arch/arm/dts/rk3188-radxarock.dts     | 382 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rk3188/Kconfig |  11 +
 board/radxa/rock/Kconfig              |  15 ++
 board/radxa/rock/MAINTAINERS          |   6 +
 board/radxa/rock/Makefile             |   7 +
 board/radxa/rock/rock.c               |   7 +
 configs/rock_defconfig                |  56 +++++
 include/configs/rock.h                |  30 +++
 9 files changed, 515 insertions(+)
 create mode 100644 arch/arm/dts/rk3188-radxarock.dts
 create mode 100644 board/radxa/rock/Kconfig
 create mode 100644 board/radxa/rock/MAINTAINERS
 create mode 100644 board/radxa/rock/Makefile
 create mode 100644 board/radxa/rock/rock.c
 create mode 100644 configs/rock_defconfig
 create mode 100644 include/configs/rock.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 3ee608b5b4..647285253e 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -29,6 +29,7 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \
 dtb-$(CONFIG_EXYNOS7420) += exynos7420-espresso7420.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
 	rk3036-sdk.dtb \
+	rk3188-radxarock.dtb \
 	rk3288-firefly.dtb \
 	rk3288-veyron-jerry.dtb \
 	rk3288-veyron-mickey.dtb \
diff --git a/arch/arm/dts/rk3188-radxarock.dts b/arch/arm/dts/rk3188-radxarock.dts
new file mode 100644
index 0000000000..5f5b5e9a1f
--- /dev/null
+++ b/arch/arm/dts/rk3188-radxarock.dts
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ or X11
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "rk3188.dtsi"
+
+/ {
+	model = "Radxa Rock";
+	compatible = "radxa,rock", "rockchip,rk3188";
+
+	chosen {
+/*		stdout-path = &uart2; */
+		stdout-path = "serial2:115200n8";
+	};
+
+	config {
+		u-boot,dm-pre-reloc;
+		u-boot,boot-led = "rock:red:power";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x80000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		power {
+			gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			label = "GPIO Key Power";
+			linux,input-type = <1>;
+			wakeup-source;
+			debounce-interval = <100>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			label = "rock:green:user1";
+			gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		blue {
+			label = "rock:blue:user2";
+			gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		sleep {
+			label = "rock:red:power";
+			gpios = <&gpio0 15 0>;
+			default-state = "off";
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "SPDIF";
+
+		simple-audio-card,dai-link at 1 {  /* S/PDIF - S/PDIF */
+			cpu { sound-dai = <&spdif>; };
+			codec { sound-dai = <&spdif_out>; };
+		};
+	};
+
+	spdif_out: spdif-out {
+		compatible = "linux,spdif-dit";
+		#sound-dai-cells = <0>;
+	};
+
+	ir_recv: gpio-ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio0 10 1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_recv_pin>;
+	};
+
+	vcc_otg: usb-otg-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&otg_vbus_drv>;
+		regulator-name = "otg-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vcc_sd0: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "sdmmc-supply";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio3 1 GPIO_ACTIVE_LOW>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_host: usb-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		regulator-name = "host-pwr";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+};
+
+&dmc {
+	rockchip,pctl-timing = <0x12c 0xc8 0x1f4 0x1e 0x4e 0x4 0x69 0x6
+		0x3 0x0 0x6 0x5 0xc 0x10 0x6 0x4
+		0x4 0x5 0x4 0x200 0x3 0xa 0x40 0x0
+		0x1 0x5 0x5 0x3 0xc 0x1e 0x100 0x0
+		0x4 0x0>;
+	rockchip,phy-timing = <0x208c6690 0x690878 0x10022a00
+		0x220 0x40 0x0 0x0>;
+	rockchip,sdram-params = <0x24716310 0 2 300000000 3 9 0>;
+};
+
+&emac {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&emac_xfer>, <&emac_mdio>, <&phy_int>;
+
+	phy = <&phy0>;
+	phy-supply = <&vcc_rmii>;
+
+	phy0: ethernet-phy at 0 {
+		reg = <0>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_arm>;
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	rtc at 51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&rtc_int>;
+		#clock-cells = <0>;
+		clock-output-names = "xin32k";
+	};
+
+	act8846: act8846 at 5a {
+		compatible = "active-semi,act8846";
+		reg = <0x5a>;
+		status = "okay";
+		system-power-controller;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&act8846_dvs0_ctl>;
+
+		vp1-supply = <&vsys>;
+		vp2-supply = <&vsys>;
+		vp3-supply = <&vsys>;
+		vp4-supply = <&vsys>;
+		inl1-supply = <&vcc_io>;
+		inl2-supply = <&vsys>;
+		inl3-supply = <&vsys>;
+
+		regulators {
+			vcc_ddr: REG1 {
+				regulator-name = "VCC_DDR";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			vdd_log: REG2 {
+				regulator-name = "VDD_LOG";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vdd_arm: REG3 {
+				regulator-name = "VDD_ARM";
+				regulator-min-microvolt = <875000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+
+			vcc_io: REG4 {
+				regulator-name = "VCC_IO";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_10: REG5 {
+				regulator-name = "VDD_10";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vdd_hdmi: REG6 {
+				regulator-name = "VDD_HDMI";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-always-on;
+			};
+
+			vcc18: REG7 {
+				regulator-name = "VCC_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vcca_33: REG8 {
+				regulator-name = "VCCA_33";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vcc_rmii: REG9 {
+				regulator-name = "VCC_RMII";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vccio_wl: REG10 {
+				regulator-name = "VCCIO_WL";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vcc_18: REG11 {
+				regulator-name = "VCC18_IO";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vcc28: REG12 {
+				regulator-name = "VCC_28";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&mmc0 {
+	num-slots = <1>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+	vmmc-supply = <&vcc_sd0>;
+
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	disable-wp;
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&pwm3 {
+	status = "okay";
+};
+
+&pinctrl {
+	pcfg_output_low: pcfg-output-low {
+		output-low;
+	};
+
+	act8846 {
+		act8846_dvs0_ctl: act8846-dvs0-ctl {
+			rockchip,pins = <RK_GPIO3 27 RK_FUNC_GPIO &pcfg_output_low>;
+		};
+	};
+
+	hym8563 {
+		rtc_int: rtc-int {
+			rockchip,pins = <RK_GPIO0 0 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	lan8720a  {
+		phy_int: phy-int {
+			rockchip,pins = <RK_GPIO3 26 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	ir-receiver {
+		ir_recv_pin: ir-recv-pin {
+			rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+		otg_vbus_drv: otg-vbus-drv {
+			rockchip,pins = <2 31 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&spdif {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+	u-boot,dm-spl;
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&usb_host {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/arch/arm/mach-rockchip/rk3188/Kconfig b/arch/arm/mach-rockchip/rk3188/Kconfig
index f8e1d0316b..5afc23ad2f 100644
--- a/arch/arm/mach-rockchip/rk3188/Kconfig
+++ b/arch/arm/mach-rockchip/rk3188/Kconfig
@@ -1,5 +1,14 @@
 if ROCKCHIP_RK3188
 
+config TARGET_ROCK
+	bool "Radxa Rock"
+	help
+	  Rock is a RK3188-based development board with 2 USB and 1 otg
+	  ports, HDMI, TV-out, micro-SD card, audio, WiFi  and 100MBit
+	  Ethernet, It also includes on-board nand and 1GB of SDRAM.
+	  Expansion connectors provide access to display pins, I2C, SPI,
+	  UART and GPIOs.
+
 config SYS_SOC
 	default "rockchip"
 
@@ -21,4 +30,6 @@ config TPL_LIBCOMMON_SUPPORT
 config TPL_SERIAL_SUPPORT
 	default y
 
+source "board/radxa/rock/Kconfig"
+
 endif
diff --git a/board/radxa/rock/Kconfig b/board/radxa/rock/Kconfig
new file mode 100644
index 0000000000..855b9b6954
--- /dev/null
+++ b/board/radxa/rock/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_ROCK
+
+config SYS_BOARD
+	default "rock"
+
+config SYS_VENDOR
+	default "radxa"
+
+config SYS_CONFIG_NAME
+	default "rock"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/radxa/rock/MAINTAINERS b/board/radxa/rock/MAINTAINERS
new file mode 100644
index 0000000000..c5f59c0a6f
--- /dev/null
+++ b/board/radxa/rock/MAINTAINERS
@@ -0,0 +1,6 @@
+RADXA_ROCK
+M:	Heiko Stuebner <heiko@sntech.de>
+S:	Maintained
+F:	board/radxa/rock
+F:	include/configs/rock.h
+F:	configs/rock_defconfig
diff --git a/board/radxa/rock/Makefile b/board/radxa/rock/Makefile
new file mode 100644
index 0000000000..fe94b60c35
--- /dev/null
+++ b/board/radxa/rock/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015 Heiko Stuebner
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y	+= rock.o
diff --git a/board/radxa/rock/rock.c b/board/radxa/rock/rock.c
new file mode 100644
index 0000000000..5119e95455
--- /dev/null
+++ b/board/radxa/rock/rock.c
@@ -0,0 +1,7 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
diff --git a/configs/rock_defconfig b/configs/rock_defconfig
new file mode 100644
index 0000000000..2705909e6c
--- /dev/null
+++ b/configs/rock_defconfig
@@ -0,0 +1,56 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3188=y
+CONFIG_ROCKCHIP_SPL_BACK_TO_BROM=y
+CONFIG_TARGET_ROCK=y
+CONFIG_SPL_STACK_R_ADDR=0x60080000
+CONFIG_DEFAULT_DEVICE_TREE="rk3188-radxarock"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_SPL_OF_PLATDATA=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+# CONFIG_SPL_SIMPLE_BUS is not set
+# CONFIG_SPL_MMC_SUPPORT is not set
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_LED=y
+CONFIG_SYSRESET=y
+CONFIG_PINCTRL=y
+# CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_ROCKCHIP_RK3188_PINCTRL=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_RAM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0x20064000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_NS16550=y
+CONFIG_SYS_NS16550=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
diff --git a/include/configs/rock.h b/include/configs/rock.h
new file mode 100644
index 0000000000..de5291cd05
--- /dev/null
+++ b/include/configs/rock.h
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define ROCKCHIP_DEVICE_SETTINGS
+#include <configs/rk3188_common.h>
+
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV 0
+
+#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
+/* SPL @ 32k for 34k
+ * u-boot directly after @ 68k for 400k or so
+ * ENV @ 992k
+ */
+#define CONFIG_ENV_OFFSET ((1024-32) * 1024)
+#else
+/* SPL @ 32k for ~36k
+ * ENV @ 96k
+ * u-boot @ 128K
+ */
+#define CONFIG_ENV_OFFSET (96 * 1024)
+#endif
+
+#endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [TEST-ONLY 16/16] Add a temporary script that can create a bootimage for rk3188
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (14 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 15/16] rockchip: rk3188: Add Radxa Rock board Heiko Stuebner
@ 2017-02-03 16:09 ` Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
  2017-02-16 20:43 ` [U-Boot] [PATCH v3 00/16] rk3188 uboot support Simon Glass
  2017-02-17  3:21 ` Kever Yang
  17 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-03 16:09 UTC (permalink / raw)
  To: u-boot

Combines tpl, spl and uboot image in one flashable image.
---
 mkuboot | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100755 mkuboot

diff --git a/mkuboot b/mkuboot
new file mode 100755
index 0000000000..42109b2b87
--- /dev/null
+++ b/mkuboot
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+LOCALPATH=$(pwd)
+ROOTDIR=$(dirname $(dirname $(readlink -f $0)))
+OUT=${ROOTDIR}/out
+IMAGE=${ROOTDIR}/image
+BOARD=$1
+DEFCONFIG=""
+
+if [ $# != 1 ] ; then
+BOARD=rock
+fi
+OUTBIN=${BOARD}-uboot.bin
+
+
+# copy tpl and pad to 1020 byte
+cat tpl/u-boot-tpl.bin > tpl/u-boot-tplspl.bin
+truncate -s 1020 tpl/u-boot-tplspl.bin
+
+#append spl and encode the result using mkimage
+truncate -s %2048 spl/u-boot-spl.bin
+cat spl/u-boot-spl.bin >> tpl/u-boot-tplspl.bin
+tools/mkimage  -n rk3188 -T rksd -d tpl/u-boot-tplspl.bin ${OUTBIN}
+
+########
+# Need to remove the RK31 from the FlashBoot binary to create FlashSpl
+# This can be used instead of the open spl as first stage
+#tools/mkimage  -n rk3188 -T rksd -d FlashSpl ${OUTBIN}
+
+# bootrom reads and decodes 2kb blocks, so bring u-boot.bin in line
+truncate -s %2048 u-boot.bin
+
+# rk3188 needs an rc4-encoded uboot as well
+cat u-boot.bin | split -b 512 --filter='openssl rc4 -K 7C4E0304550509072D2C7B38170D1711' >> ${OUTBIN}
+echo U-boot image:${OUTBIN}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl Heiko Stuebner
@ 2017-02-06 15:34   ` Simon Glass
  2017-02-17  0:36     ` Heiko Stübner
  0 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:34 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Right now the u-boot,dm-pre-reloc flag will make each marked node
> always appear in both spl and tpl. But systems needing an additional
> tpl might have special constraints for each, like the spl needing to
> be very tiny.
>
> So introduce two additional flags to mark nodes for only spl or tpl
> environments and introduce a function dm_fdt_pre_reloc to automate
> the necessary checks in code instances checking for pre-relocation
> flags.
>
> The behaviour of the original flag stays untouched and still marks
> a node for both spl and tpl.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  doc/driver-model/README.txt      |  4 ++++
>  drivers/clk/at91/pmc.c           |  3 ++-
>  drivers/core/root.c              |  2 +-
>  drivers/core/util.c              | 29 +++++++++++++++++++++++++++++
>  drivers/pinctrl/pinctrl-uclass.c |  3 ++-
>  include/dm/util.h                |  2 ++
>  scripts/Makefile.spl             |  7 ++++++-
>  tools/dtoc/dtoc.py               |  2 ++
>  8 files changed, 48 insertions(+), 4 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

s/u-boot/U-Boot

Please add a comment for dm_fdt_pre_reloc() in the header file.

Two things to consider:

- Should we drop the use of u-boot,dm-pre-reloc in Makefile.spl, and
convert all users to your version? This would mean having both
u-boot,dm-pre-reloc and u-boot,dm-spl in some cases, I suspect.

- Can you use #ifdef in SPL/TPL to reduce code size fractionally in
dm_fdt_pre_reloc()?

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 02/16] rockchip: move bootrom helper compilation to a hidden option
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 02/16] rockchip: move bootrom helper compilation to a hidden option Heiko Stuebner
@ 2017-02-06 15:34   ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:34 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Right now the ROCKCHIP_SPL_BACK_TO_BROM option both triggers
> compilation of the bootrom hook-code as well as enabling the
> behaviour of loading the full uboot via the boot.
>
> New added socs may always need the bootrom code, while still
> being able to decide between loading uboot regularly or via
> the bootrom separately.
>
> So move the compilation of the bootrom code to a hidden option
> that gets selected by ROCKCHIP_SPL_BACK_TO_BROM, but can also
> be selected by other parts.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/arm/mach-rockchip/Kconfig  | 4 ++++
>  arch/arm/mach-rockchip/Makefile | 2 +-
>  2 files changed, 5 insertions(+), 1 deletion(-)

s/uboot/U-Boot/

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  2017-02-17  3:23   ` Kever Yang
  1 sibling, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Rockchip SoCs allow the spl code to be rc4-encoded, not only the
> image header, but only newer SoCs allow this encoding to be disabled.
>
> The rk3188 is not part of those and requires its boot code to be
> rc4-encoded with the regular key. So add the ability to do this
> encoding via a setting on a per-soc basis when building spl images.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  tools/rkcommon.c | 33 +++++++++++++++++++++++++++++----
>  tools/rkcommon.h | 22 ++++++++++++++++++++++
>  tools/rkimage.c  |  3 +++
>  tools/rksd.c     |  4 ++++
>  tools/rkspi.c    |  4 ++++
>  5 files changed, 62 insertions(+), 4 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  2017-02-17  3:29   ` Kever Yang
  1 sibling, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Add the entry for the rk3188 requiring rc4-encryption of the SPL.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  tools/rkcommon.c | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 05/16] rockchip: serial: Adapt rockchip of-platdata driver for rk3188
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 05/16] rockchip: serial: Adapt rockchip of-platdata driver for rk3188 Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Add necessary structs to have the driver also work for the serial
> on the rk3188.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/serial/serial_rockchip.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 08/16] rockchip: rk3188: Add sysreset driver
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 08/16] rockchip: rk3188: Add sysreset driver Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Driver for the sysreset of Rockchip rk3188 socs.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/sysreset/Makefile          |  1 +
>  drivers/sysreset/sysreset_rk3188.c | 47 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 48 insertions(+)
>  create mode 100644 drivers/sysreset/sysreset_rk3188.c

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  2017-02-18 14:19     ` Heiko Stuebner
  0 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

Hi Heiko.

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Add a driver for setting up and modifying the various PLLs and peripheral
> clocks on the RK3188.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/arm/include/asm/arch-rockchip/cru_rk3188.h | 191 +++++++++
>  drivers/clk/rockchip/Makefile                   |   1 +
>  drivers/clk/rockchip/clk_rk3188.c               | 523 ++++++++++++++++++++++++
>  3 files changed, 715 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>  create mode 100644 drivers/clk/rockchip/clk_rk3188.c

Reviewed-by: Simon Glass <sjg@chromium.org>

With one comment below.

>
> diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3188.h b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
> new file mode 100644
> index 0000000000..74f0fedcc6
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
> @@ -0,0 +1,191 @@
> +/*
> + * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +#ifndef _ASM_ARCH_CRU_RK3188_H
> +#define _ASM_ARCH_CRU_RK3188_H
> +
> +#define OSC_HZ         (24 * 1000 * 1000)
> +
> +#define APLL_HZ                (1608 * 1000000)
> +#define GPLL_HZ                (594 * 1000000)
> +#define CPLL_HZ                (384 * 1000000)
> +
> +/* The SRAM is clocked off aclk_cpu, so we want to max it out for boot speed */
> +#define CPU_ACLK_HZ    297000000
> +#define CPU_HCLK_HZ    148500000
> +#define CPU_PCLK_HZ    74250000
> +#define CPU_H2P_HZ     74250000
> +
> +#define PERI_ACLK_HZ   148500000
> +#define PERI_HCLK_HZ   148500000
> +#define PERI_PCLK_HZ   74250000
> +
> +/* Private data for the clock driver - used by rockchip_get_cru() */
> +struct rk3188_clk_priv {
> +       struct rk3188_grf *grf;
> +       struct rk3188_cru *cru;
> +       ulong rate;
> +       bool has_bwadj;
> +};
> +
> +struct rk3188_cru {
> +       struct rk3188_pll {
> +               u32 con0;
> +               u32 con1;
> +               u32 con2;
> +               u32 con3;
> +       } pll[4];
> +       u32 cru_mode_con;
> +       u32 cru_clksel_con[35];
> +       u32 cru_clkgate_con[10];
> +       u32 reserved1[2];
> +       u32 cru_glb_srst_fst_value;
> +       u32 cru_glb_srst_snd_value;
> +       u32 reserved2[2];
> +       u32 cru_softrst_con[9];
> +       u32 cru_misc_con;
> +       u32 reserved3[2];
> +       u32 cru_glb_cnt_th;
> +};
> +check_member(rk3188_cru, cru_glb_cnt_th, 0x0140);
> +
> +/* CRU_CLKSEL0_CON */
> +enum {
> +       /* a9_core_div: core = core_src / (a9_core_div + 1) */
> +       A9_CORE_DIV_SHIFT       = 9,
> +       A9_CORE_DIV_MASK        = 0x1f,

Can you define

A9_CORE_DIV_MASK = 0x1f << A9_CORE_DIV_SHIFT

and similarly for other masks. I got this wrong with rk3288, and I
think shifting the mask makes the code easier in places.

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  2017-02-10 23:17     ` Heiko Stuebner
  0 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> The rk3188 shares a lot of peripherals with the rk3066 and thus
> has a common include called rk3xxx.dtsi. Add both this one and
> the specialized rk3188 on top of it.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/arm/dts/rk3188.dtsi | 601 +++++++++++++++++++++++++++++++++++++++++++++++
>  arch/arm/dts/rk3xxx.dtsi | 417 ++++++++++++++++++++++++++++++++
>  2 files changed, 1018 insertions(+)
>  create mode 100644 arch/arm/dts/rk3188.dtsi
>  create mode 100644 arch/arm/dts/rk3xxx.dtsi

Reviewed-by: Simon Glass <sjg@chromium.org>

Does this mirror the Linux kernel setup?

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 12/16] rockchip: rk3188: Add core support
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 12/16] rockchip: rk3188: Add core support Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Add the core architecture code for the rk3188.
> It doesn't support the SPL yet, as because of some
> unknown error it doesn't start yet.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/arm/mach-rockchip/Kconfig                |  16 ++++
>  arch/arm/mach-rockchip/Makefile               |   5 ++
>  arch/arm/mach-rockchip/rk3188/Kconfig         |  24 +++++
>  arch/arm/mach-rockchip/rk3188/Makefile        |  10 +++
>  arch/arm/mach-rockchip/rk3188/clk_rk3188.c    |  33 +++++++
>  arch/arm/mach-rockchip/rk3188/syscon_rk3188.c |  55 ++++++++++++
>  include/configs/rk3188_common.h               | 125 ++++++++++++++++++++++++++
>  7 files changed, 268 insertions(+)
>  create mode 100644 arch/arm/mach-rockchip/rk3188/Kconfig
>  create mode 100644 arch/arm/mach-rockchip/rk3188/Makefile
>  create mode 100644 arch/arm/mach-rockchip/rk3188/clk_rk3188.c
>  create mode 100644 arch/arm/mach-rockchip/rk3188/syscon_rk3188.c
>  create mode 100644 include/configs/rk3188_common.h

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  2017-02-17 20:39     ` Heiko Stuebner
  0 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> The sdram controller blocks are very similar to the rk3288 in utilizing
> memory scheduler, Designware uPCTL and Designware PUBL blocks, only
> limited to one bank instead of two.
>
> There are some minimal differences when setting up the ram, so it gets
> a separate driver for the rk3188 but reuses the driver structs, as there
> is no need to define the same again.
>
> More optimization can happen when the modelling of the controller parts
> in the dts actually follow the hardware layout hopefully at some point
> in the future.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/arm/include/asm/arch-rockchip/ddr_rk3188.h |  22 +
>  arch/arm/mach-rockchip/rk3188/Makefile          |   1 +
>  arch/arm/mach-rockchip/rk3188/sdram_rk3188.c    | 985 ++++++++++++++++++++++++
>  3 files changed, 1008 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
>  create mode 100644 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c

Reviewed-by: Simon Glass <sjg@chromium.org>

Nits below.

>
> diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> new file mode 100644
> index 0000000000..993c58d1a8
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> @@ -0,0 +1,22 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + */
> +
> +#ifndef _ASM_ARCH_DDR_RK3188_H
> +#define _ASM_ARCH_DDR_RK3188_H
> +
> +#include <asm/arch/ddr_rk3288.h>
> +
> +struct rk3188_msch {
> +       u32 coreid;
> +       u32 revisionid;
> +       u32 ddrconf;
> +       u32 ddrtiming;
> +       u32 ddrmode;
> +       u32 readlatency;

Can you comment this struct? What is it for?

> +};
> +check_member(rk3188_msch, readlatency, 0x0014);
> +
> +#endif
> diff --git a/arch/arm/mach-rockchip/rk3188/Makefile b/arch/arm/mach-rockchip/rk3188/Makefile
> index 7fa010405b..2dc9511de7 100644
> --- a/arch/arm/mach-rockchip/rk3188/Makefile
> +++ b/arch/arm/mach-rockchip/rk3188/Makefile
> @@ -6,5 +6,6 @@
>
>  ifndef CONFIG_TPL_BUILD
>  obj-y += clk_rk3188.o
> +obj-y += sdram_rk3188.o
>  obj-y += syscon_rk3188.o
>  endif
> diff --git a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c b/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
> new file mode 100644
> index 0000000000..9e41723c9f
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
> @@ -0,0 +1,985 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + * Copyright 2014 Rockchip Inc.
> + *
> + * SPDX-License-Identifier:     GPL-2.0
> + *
> + * Adapted from coreboot.

Does coreboot support the rk3188?

> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dt-structs.h>
> +#include <errno.h>
> +#include <ram.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/cru_rk3188.h>
> +#include <asm/arch/ddr_rk3188.h>
> +#include <asm/arch/grf_rk3188.h>
> +#include <asm/arch/pmu_rk3188.h>
> +#include <asm/arch/sdram.h>
> +#include <linux/err.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct chan_info {
> +       struct rk3288_ddr_pctl *pctl;
> +       struct rk3288_ddr_publ *publ;
> +       struct rk3188_msch *msch;
> +};
> +
> +struct dram_info {
> +       struct chan_info chan[1];
> +       struct ram_info info;
> +       struct clk ddr_clk;
> +       struct rk3188_cru *cru;
> +       struct rk3188_grf *grf;
> +       struct rk3188_sgrf *sgrf;
> +       struct rk3188_pmu *pmu;
> +};
> +
> +struct rk3188_sdram_params {
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +       struct dtd_rockchip_rk3188_dmc of_plat;
> +#endif
> +       struct rk3288_sdram_channel ch[2];
> +       struct rk3288_sdram_pctl_timing pctl_timing;
> +       struct rk3288_sdram_phy_timing phy_timing;
> +       struct rk3288_base_params base;
> +       int num_channels;
> +       struct regmap *map;
> +};
> +
> +#define TEST_PATTEN    0x5aa5f00f
> +#define DQS_GATE_TRAINING_ERROR_RANK0  (1 << 4)
> +#define DQS_GATE_TRAINING_ERROR_RANK1  (2 << 4)
> +
> +#ifdef CONFIG_SPL_BUILD
> +static void copy_to_reg(u32 *dest, const u32 *src, u32 n)

Seems like this should go in a common file as there are several users
- rk_copy_to_reg() ?

> +{
> +       int i;
> +
> +       for (i = 0; i < n / sizeof(u32); i++) {
> +               writel(*src, dest);
> +               src++;
> +               dest++;
> +       }
> +}
> +
> +static void ddr_reset(struct rk3188_cru *cru, u32 ch, u32 ctl, u32 phy)
> +{
> +       u32 phy_ctl_srstn_shift = 5 + 8 * ch;
> +       u32 ctl_psrstn_shift = 3 + 8 * ch;
> +       u32 ctl_srstn_shift = 2 + 8 * ch;
> +       u32 phy_psrstn_shift = 1 + 8 * ch;
> +       u32 phy_srstn_shift = 8 * ch;
> +
> +       rk_clrsetreg(&cru->cru_softrst_con[5],
> +                    1 << phy_ctl_srstn_shift | 1 << ctl_psrstn_shift |
> +                    1 << ctl_srstn_shift | 1 << phy_psrstn_shift |
> +                    1 << phy_srstn_shift,
> +                    phy << phy_ctl_srstn_shift | ctl << ctl_psrstn_shift |
> +                    ctl << ctl_srstn_shift | phy << phy_psrstn_shift |
> +                    phy << phy_srstn_shift);
> +}
> +
> +static void ddr_phy_ctl_reset(struct rk3188_cru *cru, u32 ch, u32 n)
> +{
> +       u32 phy_ctl_srstn_shift = 5 + 8 * ch;
> +
> +       rk_clrsetreg(&cru->cru_softrst_con[5],
> +                    1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift);
> +}
> +
> +static void phy_pctrl_reset(struct rk3188_cru *cru,
> +                           struct rk3288_ddr_publ *publ,
> +                           u32 channel)
> +{
> +       int i;
> +
> +       ddr_reset(cru, channel, 1, 1);
> +       udelay(1);
> +       clrbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST);
> +       for (i = 0; i < 4; i++)
> +               clrbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST);
> +
> +       udelay(10);
> +       setbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST);
> +       for (i = 0; i < 4; i++)
> +               setbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST);
> +
> +       udelay(10);
> +       ddr_reset(cru, channel, 1, 0);
> +       udelay(10);
> +       ddr_reset(cru, channel, 0, 0);
> +       udelay(10);
> +}
> +
> +static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ,
> +       u32 freq)
> +{
> +       int i;

blank line here

Do you have a comment for this logic, and why it is how it is?

> +       if (freq <= 250000000) {
> +               if (freq <= 150000000)
> +                       clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> +               else
> +                       setbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> +               setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
> +               for (i = 0; i < 4; i++)
> +                       setbits_le32(&publ->datx8[i].dxdllcr,
> +                                    DXDLLCR_DLLDIS);
> +
> +               setbits_le32(&publ->pir, PIR_DLLBYP);
> +       } else {
> +               clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> +               clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
> +               for (i = 0; i < 4; i++) {
> +                       clrbits_le32(&publ->datx8[i].dxdllcr,
> +                                    DXDLLCR_DLLDIS);
> +               }
> +
> +               clrbits_le32(&publ->pir, PIR_DLLBYP);
> +       }
> +}
> +
> +static void dfi_cfg(struct rk3288_ddr_pctl *pctl, u32 dramtype)
> +{
> +       writel(DFI_INIT_START, &pctl->dfistcfg0);
> +       writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN,
> +              &pctl->dfistcfg1);
> +       writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2);
> +       writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN,
> +              &pctl->dfilpcfg0);
> +
> +       writel(2 << TCTRL_DELAY_TIME_SHIFT, &pctl->dfitctrldelay);
> +       writel(1 << TPHY_WRDATA_TIME_SHIFT, &pctl->dfitphywrdata);
> +       writel(0xf << TPHY_RDLAT_TIME_SHIFT, &pctl->dfitphyrdlat);
> +       writel(2 << TDRAM_CLK_DIS_TIME_SHIFT, &pctl->dfitdramclkdis);
> +       writel(2 << TDRAM_CLK_EN_TIME_SHIFT, &pctl->dfitdramclken);
> +       writel(1, &pctl->dfitphyupdtype0);
> +
> +       /* cs0 and cs1 write odt enable */
> +       writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL),
> +              &pctl->dfiodtcfg);
> +       /* odt write length */
> +       writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1);
> +       /* phyupd and ctrlupd disabled */
> +       writel(0, &pctl->dfiupdcfg);
> +}
> +
> +static void ddr_set_enable(struct rk3188_grf *grf, uint channel, bool enable)
> +{
> +       uint val = 0;
> +
> +       if (enable)
> +               val = 1 << DDR_16BIT_EN_SHIFT;
> +
> +       rk_clrsetreg(&grf->ddrc_con0, 1 << DDR_16BIT_EN_SHIFT, val);
> +}
> +
> +static void ddr_set_ddr3_mode(struct rk3188_grf *grf, uint channel,
> +                             bool ddr3_mode)
> +{
> +       uint mask, val;
> +
> +       mask = 1 << MSCH4_MAINDDR3_SHIFT;
> +       val = ddr3_mode << MSCH4_MAINDDR3_SHIFT;
> +       rk_clrsetreg(&grf->soc_con2, mask, val);
> +}
> +
> +#define RANK_2_ROW15_EN 1

Can this go at the top of the file?

> +static void ddr_rank_2_row15en(struct rk3188_grf *grf, bool enable)
> +{
> +       uint mask, val;
> +
> +       mask = 1 << RANK_2_ROW15_EN;
> +       val = enable << RANK_2_ROW15_EN;
> +       rk_clrsetreg(&grf->soc_con2, mask, val);
> +}
> +
> +static void pctl_cfg(u32 channel, struct rk3288_ddr_pctl *pctl,
> +                    struct rk3188_sdram_params *sdram_params,
> +                    struct rk3188_grf *grf)
> +{
> +       copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u,
> +                   sizeof(sdram_params->pctl_timing));
> +       switch (sdram_params->base.dramtype) {
> +       case DDR3:
> +               if (sdram_params->phy_timing.mr[1] & DDR3_DLL_DISABLE) {
> +                       writel(sdram_params->pctl_timing.tcl - 3,
> +                              &pctl->dfitrddataen);
> +               } else {
> +                       writel(sdram_params->pctl_timing.tcl - 2,
> +                              &pctl->dfitrddataen);
> +               }
> +               writel(sdram_params->pctl_timing.tcwl - 1,
> +                      &pctl->dfitphywrlat);
> +               writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN |
> +                      DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW |
> +                      1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
> +                      &pctl->mcfg);
> +               ddr_set_ddr3_mode(grf, channel, true);
> +               ddr_set_enable(grf, channel, true);
> +               break;
> +       }
> +
> +       setbits_le32(&pctl->scfg, 1);
> +}
> +
> +static void phy_cfg(const struct chan_info *chan, u32 channel,
> +                   struct rk3188_sdram_params *sdram_params)
> +{
> +       struct rk3288_ddr_publ *publ = chan->publ;
> +       struct rk3188_msch *msch = chan->msch;
> +       uint ddr_freq_mhz = sdram_params->base.ddr_freq / 1000000;
> +       u32 dinit2;
> +       int i;
> +
> +       dinit2 = DIV_ROUND_UP(ddr_freq_mhz * 200000, 1000);
> +       /* DDR PHY Timing */
> +       copy_to_reg(&publ->dtpr[0], &sdram_params->phy_timing.dtpr0,
> +                   sizeof(sdram_params->phy_timing));
> +       writel(sdram_params->base.noc_timing, &msch->ddrtiming);
> +       writel(0x3f, &msch->readlatency);
> +       writel(DIV_ROUND_UP(ddr_freq_mhz * 5120, 1000) << PRT_DLLLOCK_SHIFT |
> +              DIV_ROUND_UP(ddr_freq_mhz * 50, 1000) << PRT_DLLSRST_SHIFT |
> +              8 << PRT_ITMSRST_SHIFT, &publ->ptr[0]);
> +       writel(DIV_ROUND_UP(ddr_freq_mhz * 500000, 1000) << PRT_DINIT0_SHIFT |
> +              DIV_ROUND_UP(ddr_freq_mhz * 400, 1000) << PRT_DINIT1_SHIFT,
> +              &publ->ptr[1]);
> +       writel(min(dinit2, 0x1ffffU) << PRT_DINIT2_SHIFT |
> +              DIV_ROUND_UP(ddr_freq_mhz * 1000, 1000) << PRT_DINIT3_SHIFT,
> +              &publ->ptr[2]);
> +
> +       switch (sdram_params->base.dramtype) {
> +       case DDR3:
> +               clrbits_le32(&publ->pgcr, 0x1f);
> +               clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT,
> +                               DDRMD_DDR3 << DDRMD_SHIFT);
> +               break;
> +       }
> +       if (sdram_params->base.odt) {
> +               /*dynamic RTT enable */
> +               for (i = 0; i < 4; i++)
> +                       setbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT);
> +       } else {
> +               /*dynamic RTT disable */
> +               for (i = 0; i < 4; i++)
> +                       clrbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT);
> +       }
> +}
> +
> +static void phy_init(struct rk3288_ddr_publ *publ)
> +{
> +       setbits_le32(&publ->pir, PIR_INIT | PIR_DLLSRST
> +               | PIR_DLLLOCK | PIR_ZCAL | PIR_ITMSRST | PIR_CLRSR);
> +       udelay(1);
> +       while ((readl(&publ->pgsr) &
> +               (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) !=
> +               (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE))
> +               ;
> +}
> +
> +static void send_command(struct rk3288_ddr_pctl *pctl, u32 rank,
> +                        u32 cmd, u32 arg)
> +{
> +       writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
> +       udelay(1);
> +       while (readl(&pctl->mcmd) & START_CMD)
> +               ;
> +}
> +
> +static inline void send_command_op(struct rk3288_ddr_pctl *pctl,
> +                                  u32 rank, u32 cmd, u32 ma, u32 op)
> +{
> +       send_command(pctl, rank, cmd, (ma & LPDDR2_MA_MASK) << LPDDR2_MA_SHIFT |
> +                    (op & LPDDR2_OP_MASK) << LPDDR2_OP_SHIFT);
> +}
> +
> +static void memory_init(struct rk3288_ddr_publ *publ,
> +                       u32 dramtype)
> +{
> +       setbits_le32(&publ->pir,
> +                    (PIR_INIT | PIR_DRAMINIT | PIR_LOCKBYP
> +                     | PIR_ZCALBYP | PIR_CLRSR | PIR_ICPC
> +                     | (dramtype == DDR3 ? PIR_DRAMRST : 0)));
> +       udelay(1);
> +       while ((readl(&publ->pgsr) & (PGSR_IDONE | PGSR_DLDONE))
> +               != (PGSR_IDONE | PGSR_DLDONE))
> +               ;
> +}
> +
> +static void move_to_config_state(struct rk3288_ddr_publ *publ,
> +                                struct rk3288_ddr_pctl *pctl)
> +{
> +       unsigned int state;
> +
> +       while (1) {
> +               state = readl(&pctl->stat) & PCTL_STAT_MSK;
> +
> +               switch (state) {
> +               case LOW_POWER:
> +                       writel(WAKEUP_STATE, &pctl->sctl);
> +                       while ((readl(&pctl->stat) & PCTL_STAT_MSK)
> +                               != ACCESS)
> +                               ;
> +                       /* wait DLL lock */
> +                       while ((readl(&publ->pgsr) & PGSR_DLDONE)
> +                               != PGSR_DLDONE)
> +                               ;
> +                       /* if at low power state,need wakeup first,

Check multi-line comment style:

/*
 * If at low-power state ...
 * ...
 */

> +                        * and then enter the config, so
> +                        * fallthrough
> +                        */
> +               case ACCESS:
> +                       /* fallthrough */
> +               case INIT_MEM:
> +                       writel(CFG_STATE, &pctl->sctl);
> +                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
> +                               ;
> +                       break;
> +               case CONFIG:
> +                       return;
> +               default:
> +                       break;
> +               }
> +       }
> +}
> +
> +static void set_bandwidth_ratio(const struct chan_info *chan, u32 channel,
> +                               u32 n, struct rk3188_grf *grf)
> +{
> +       struct rk3288_ddr_pctl *pctl = chan->pctl;
> +       struct rk3288_ddr_publ *publ = chan->publ;
> +       struct rk3188_msch *msch = chan->msch;
> +
> +       if (n == 1) {
> +               setbits_le32(&pctl->ppcfg, 1);
> +               ddr_set_enable(grf, channel, 1);
> +               setbits_le32(&msch->ddrtiming, 1 << 31);
> +               /* Data Byte disable*/
> +               clrbits_le32(&publ->datx8[2].dxgcr, 1);
> +               clrbits_le32(&publ->datx8[3].dxgcr, 1);
> +               /* disable DLL */
> +               setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
> +               setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
> +       } else {
> +               clrbits_le32(&pctl->ppcfg, 1);
> +               ddr_set_enable(grf, channel, 0);
> +               clrbits_le32(&msch->ddrtiming, 1 << 31);
> +               /* Data Byte enable*/
> +               setbits_le32(&publ->datx8[2].dxgcr, 1);
> +               setbits_le32(&publ->datx8[3].dxgcr, 1);
> +
> +               /* enable DLL */
> +               clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
> +               clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
> +               /* reset DLL */
> +               clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST);
> +               clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST);
> +               udelay(10);
> +               setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST);
> +               setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST);
> +       }
> +       setbits_le32(&pctl->dfistcfg0, 1 << 2);
> +}
> +
> +static int data_training(const struct chan_info *chan, u32 channel,
> +                        struct rk3188_sdram_params *sdram_params)

Function comment? What does it return? channel could just be int, right?

> +{
> +       unsigned int j;
> +       int ret = 0;
> +       u32 rank;
> +       int i;
> +       u32 step[2] = { PIR_QSTRN, PIR_RVTRN };
> +       struct rk3288_ddr_publ *publ = chan->publ;
> +       struct rk3288_ddr_pctl *pctl = chan->pctl;
> +
> +       /* disable auto refresh */
> +       writel(0, &pctl->trefi);
> +
> +       if (sdram_params->base.dramtype != LPDDR3)
> +               setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
> +       rank = sdram_params->ch[channel].rank | 1;
> +       for (j = 0; j < ARRAY_SIZE(step); j++) {
> +               /*
> +                * trigger QSTRN and RVTRN
> +                * clear DTDONE status
> +                */
> +               setbits_le32(&publ->pir, PIR_CLRSR);
> +
> +               /* trigger DTT */
> +               setbits_le32(&publ->pir,
> +                            PIR_INIT | step[j] | PIR_LOCKBYP | PIR_ZCALBYP |
> +                            PIR_CLRSR);
> +               udelay(1);
> +               /* wait echo byte DTDONE */
> +               while ((readl(&publ->datx8[0].dxgsr[0]) & rank)
> +                       != rank)
> +                       ;
> +               while ((readl(&publ->datx8[1].dxgsr[0]) & rank)
> +                       != rank)
> +                       ;
> +               if (!(readl(&pctl->ppcfg) & 1)) {
> +                       while ((readl(&publ->datx8[2].dxgsr[0])
> +                               & rank) != rank)
> +                               ;
> +                       while ((readl(&publ->datx8[3].dxgsr[0])
> +                               & rank) != rank)
> +                               ;
> +               }
> +               if (readl(&publ->pgsr) &
> +                   (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) {
> +                       ret = -1;
> +                       break;
> +               }
> +       }
> +       /* send some auto refresh to complement the lost while DTT */
> +       for (i = 0; i < (rank > 1 ? 8 : 4); i++)
> +               send_command(pctl, rank, REF_CMD, 0);
> +
> +       if (sdram_params->base.dramtype != LPDDR3)
> +               clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
> +
> +       /* resume auto refresh */
> +       writel(sdram_params->pctl_timing.trefi, &pctl->trefi);
> +
> +       return ret;
> +}
> +
> +static void move_to_access_state(const struct chan_info *chan)
> +{
> +       struct rk3288_ddr_publ *publ = chan->publ;
> +       struct rk3288_ddr_pctl *pctl = chan->pctl;
> +       unsigned int state;
> +
> +       while (1) {
> +               state = readl(&pctl->stat) & PCTL_STAT_MSK;
> +
> +               switch (state) {
> +               case LOW_POWER:
> +                       if (((readl(&pctl->stat) >> LP_TRIG_SHIFT) &
> +                                       LP_TRIG_MASK) == 1)
> +                               return;
> +
> +                       writel(WAKEUP_STATE, &pctl->sctl);
> +                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS)
> +                               ;
> +                       /* wait DLL lock */
> +                       while ((readl(&publ->pgsr) & PGSR_DLDONE)
> +                               != PGSR_DLDONE)
> +                               ;
> +                       break;
> +               case INIT_MEM:
> +                       writel(CFG_STATE, &pctl->sctl);
> +                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
> +                               ;
> +                       /* fallthrough */
> +               case CONFIG:
> +                       writel(GO_STATE, &pctl->sctl);
> +                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) == CONFIG)
> +                               ;
> +                       break;
> +               case ACCESS:
> +                       return;
> +               default:
> +                       break;
> +               }
> +       }
> +}
> +
> +static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum,
> +                        struct rk3188_sdram_params *sdram_params)
> +{
> +       struct rk3288_ddr_publ *publ = chan->publ;
> +
> +       if (sdram_params->ch[chnum].bk == 3)
> +               clrsetbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT,
> +                               1 << PDQ_SHIFT);
> +       else
> +               clrbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT);
> +
> +       writel(sdram_params->base.ddrconfig, &chan->msch->ddrconf);
> +}
> +
> +static void dram_all_config(const struct dram_info *dram,
> +                           struct rk3188_sdram_params *sdram_params)
> +{
> +       unsigned int chan;
> +       u32 sys_reg = 0;
> +
> +       sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT;
> +       sys_reg |= (sdram_params->num_channels - 1) << SYS_REG_NUM_CH_SHIFT;
> +       for (chan = 0; chan < sdram_params->num_channels; chan++) {
> +               const struct rk3288_sdram_channel *info =
> +                       &sdram_params->ch[chan];
> +
> +               sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan);
> +               sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(chan);
> +               sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan);
> +               sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan);
> +               sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(chan);
> +               sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan);
> +               sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan);
> +               sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(chan);
> +               sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(chan);
> +
> +               dram_cfg_rbc(&dram->chan[chan], chan, sdram_params);
> +       }
> +       if (sdram_params->ch[0].rank == 2)
> +               ddr_rank_2_row15en(dram->grf, 0);
> +       else
> +               ddr_rank_2_row15en(dram->grf, 1);
> +       writel(sys_reg, &dram->pmu->sys_reg[2]);
> +}

blank line

> +const int ddrconf_table[] = {
> +       /*
> +        * [5:4] row(13+n)
> +        * [1:0] col(9+n), assume bw=2
> +        * row      col,bw */
> +       0,
> +       ((2 << 4) | 1),
> +       ((1 << 4) | 1),
> +       ((0 << 4) | 1),
> +       ((2 << 4) | 2),
> +       ((1 << 4) | 2),
> +       ((0 << 4) | 2),
> +       ((1 << 4) | 0),
> +       ((0 << 4) | 0),
> +       0,
> +       0,
> +       0,
> +       0,
> +       0,
> +       0,
> +       0,
> +};

Can this go at the top of the file? What are the <<4 for ? Can we have
a #define?

> +
> +static int sdram_rank_bw_detect(struct dram_info *dram, int channel,
> +               struct rk3188_sdram_params *sdram_params)
> +{
> +       int reg;
> +       int need_trainig = 0;
> +       const struct chan_info *chan = &dram->chan[channel];
> +       struct rk3288_ddr_publ *publ = chan->publ;
> +
> +       ddr_rank_2_row15en(dram->grf, 0);
> +
> +       if (-1 == data_training(chan, channel, sdram_params)) {

Can you check for <0 rather than == -1? That is the normal error check.

> +               printf("first data training fail!\n");
> +               reg = readl(&publ->datx8[0].dxgsr[0]);
> +               /* Check the result for rank 0 */
> +               if ((channel == 0) && (reg & DQS_GATE_TRAINING_ERROR_RANK0)) {
> +                       printf("data training fail!\n");
> +                               return -EIO;

funny indent here

> +               }
> +
> +               /* Check the result for rank 1 */
> +               if (reg & DQS_GATE_TRAINING_ERROR_RANK1) {
> +                       sdram_params->ch[channel].rank = 1;
> +                       clrsetbits_le32(&publ->pgcr, 0xF << 18,
> +                                       sdram_params->ch[channel].rank << 18);
> +                       need_trainig = 1;
> +               }
> +               reg = readl(&publ->datx8[2].dxgsr[0]);
> +               if (reg & (1 << 4)) {
> +                       sdram_params->ch[channel].bw = 1;
> +                       set_bandwidth_ratio(chan, channel,
> +                                           sdram_params->ch[channel].bw,
> +                                           dram->grf);
> +                       need_trainig = 1;
> +               }
> +       }
> +       /* Assume the Die bit width are the same with the chip bit width */
> +       sdram_params->ch[channel].dbw = sdram_params->ch[channel].bw;
> +
> +       if (need_trainig &&
> +           (-1 == data_training(chan, channel, sdram_params))) {

same as above

> +               if (sdram_params->base.dramtype == LPDDR3) {
> +                       ddr_phy_ctl_reset(dram->cru, channel, 1);
> +                       udelay(10);
> +                       ddr_phy_ctl_reset(dram->cru, channel, 0);
> +                       udelay(10);
> +               }
> +               printf("2nd data training failed!");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int sdram_col_row_detect(struct dram_info *dram, int channel,
> +               struct rk3188_sdram_params *sdram_params)

Function comment

> +{
> +       int row, col;
> +       unsigned int addr;
> +       const struct chan_info *chan = &dram->chan[channel];
> +       struct rk3288_ddr_pctl *pctl = chan->pctl;
> +       struct rk3288_ddr_publ *publ = chan->publ;
> +       int ret = 0;
> +
> +       /* Detect col */
> +       for (col = 11; col >= 9; col--) {
> +               writel(0, CONFIG_SYS_SDRAM_BASE);
> +               addr = CONFIG_SYS_SDRAM_BASE +
> +                       (1 << (col + sdram_params->ch[channel].bw - 1));
> +               writel(TEST_PATTEN, addr);
> +               if ((readl(addr) == TEST_PATTEN) &&
> +                   (readl(CONFIG_SYS_SDRAM_BASE) == 0))
> +                       break;
> +       }
> +       if (col == 8) {
> +               printf("Col detect error\n");
> +               ret = -EINVAL;
> +               goto out;
> +       } else {
> +               sdram_params->ch[channel].col = col;
> +       }
> +
> +       ddr_rank_2_row15en(dram->grf, 1);
> +       move_to_config_state(publ, pctl);
> +       writel(1, &chan->msch->ddrconf);
> +       move_to_access_state(chan);
> +       /* Detect row, max 15,min13 in rk3188*/
> +       for (row = 16; row >= 13; row--) {
> +               writel(0, CONFIG_SYS_SDRAM_BASE);
> +               addr = CONFIG_SYS_SDRAM_BASE + (1 << (row + 15 - 1));
> +               writel(TEST_PATTEN, addr);
> +               if ((readl(addr) == TEST_PATTEN) &&
> +                   (readl(CONFIG_SYS_SDRAM_BASE) == 0))
> +                       break;
> +       }
> +       if (row == 12) {
> +               printf("Row detect error\n");
> +               ret = -EINVAL;
> +       } else {
> +               sdram_params->ch[channel].cs1_row = row;
> +               sdram_params->ch[channel].row_3_4 = 0;
> +               printf("chn %d col %d, row %d\n", channel, col, row);
> +               sdram_params->ch[channel].cs0_row = row;
> +       }
> +
> +out:
> +       return ret;
> +}
> +
> +static int sdram_get_niu_config(struct rk3188_sdram_params *sdram_params)
> +{
> +       int i, tmp, size, ret = 0;
> +
> +       tmp = sdram_params->ch[0].col - 9;
> +       tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1;
> +       tmp |= ((sdram_params->ch[0].cs0_row - 13) << 4);
> +       size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]);
> +       for (i = 0; i < size; i++)
> +               if (tmp == ddrconf_table[i])
> +                       break;
> +       if (i >= size) {
> +               printf("niu config not found\n");
> +               ret = -EINVAL;
> +       } else {
> +               printf("niu config %d\n", i);
> +               sdram_params->base.ddrconfig = i;
> +       }
> +
> +       return ret;
> +}
> +
> +static int sdram_init(struct dram_info *dram,
> +                     struct rk3188_sdram_params *sdram_params)
> +{
> +       int channel;
> +       int zqcr;
> +       int ret;
> +
> +       printf("%s start 001\n", __func__);

debug()

> +       if ((sdram_params->base.dramtype == DDR3 &&
> +            sdram_params->base.ddr_freq > 800000000)) {
> +               printf("SDRAM frequency is too high!");
> +               return -E2BIG;
> +       }
> +
> +       ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq);
> +       printf("ret=%d\n", ret);

debug()

> +       if (ret) {
> +               printf("Could not set DDR clock\n");
> +               return ret;
> +       }
> +
> +       for (channel = 0; channel < 1; channel++) {
> +               const struct chan_info *chan = &dram->chan[channel];
> +               struct rk3288_ddr_pctl *pctl = chan->pctl;
> +               struct rk3288_ddr_publ *publ = chan->publ;
> +
> +               phy_pctrl_reset(dram->cru, publ, channel);
> +               phy_dll_bypass_set(publ, sdram_params->base.ddr_freq);
> +
> +               dfi_cfg(pctl, sdram_params->base.dramtype);
> +
> +               pctl_cfg(channel, pctl, sdram_params, dram->grf);
> +
> +               phy_cfg(chan, channel, sdram_params);
> +
> +               phy_init(publ);
> +
> +               writel(POWER_UP_START, &pctl->powctl);
> +               while (!(readl(&pctl->powstat) & POWER_UP_DONE))
> +                       ;
> +
> +               memory_init(publ, sdram_params->base.dramtype);
> +               move_to_config_state(publ, pctl);
> +
> +               /* Using 32bit bus width for detect */
> +               sdram_params->ch[channel].bw = 2;
> +               set_bandwidth_ratio(chan, channel,
> +                                   sdram_params->ch[channel].bw, dram->grf);
> +               /*
> +                * set cs, using n=3 for detect
> +                * CS0, n=1
> +                * CS1, n=2
> +                * CS0 & CS1, n = 3
> +                */
> +               sdram_params->ch[channel].rank = 2,
> +               clrsetbits_le32(&publ->pgcr, 0xF << 18,
> +                               (sdram_params->ch[channel].rank | 1) << 18);
> +
> +               /* DS=40ohm,ODT=155ohm */
> +               zqcr = 1 << ZDEN_SHIFT | 2 << PU_ONDIE_SHIFT |
> +                       2 << PD_ONDIE_SHIFT | 0x19 << PU_OUTPUT_SHIFT |
> +                       0x19 << PD_OUTPUT_SHIFT;
> +               writel(zqcr, &publ->zq1cr[0]);
> +               writel(zqcr, &publ->zq0cr[0]);
> +
> +               /* Detect the rank and bit-width with data-training */
> +               writel(1, &chan->msch->ddrconf);
> +               sdram_rank_bw_detect(dram, channel, sdram_params);
> +
> +               if (sdram_params->base.dramtype == LPDDR3) {
> +                       u32 i;
> +                       writel(0, &pctl->mrrcfg0);
> +                       for (i = 0; i < 17; i++)
> +                               send_command_op(pctl, 1, MRR_CMD, i, 0);
> +               }
> +               writel(4, &chan->msch->ddrconf);
> +               move_to_access_state(chan);
> +               /* DDR3 and LPDDR3 are always 8 bank, no need detect */
> +               sdram_params->ch[channel].bk = 3;
> +               /* Detect Col and Row number*/
> +               ret = sdram_col_row_detect(dram, channel, sdram_params);
> +               if (ret)
> +                       goto error;
> +       }
> +       /* Find NIU DDR configuration */
> +       ret = sdram_get_niu_config(sdram_params);
> +       if (ret)
> +               goto error;
> +
> +       dram_all_config(dram, sdram_params);
> +       printf("%s done\n", __func__);
> +
> +       return 0;
> +error:
> +       printf("DRAM init failed!\n");
> +       hang();
> +}
> +#endif /* CONFIG_SPL_BUILD */
> +
> +size_t sdram_size_mb(struct rk3188_pmu *pmu)
> +{
> +       u32 rank, col, bk, cs0_row, cs1_row, bw, row_3_4;
> +       size_t chipsize_mb = 0;
> +       size_t size_mb = 0;
> +       u32 ch;
> +       u32 sys_reg = readl(&pmu->sys_reg[2]);
> +       u32 chans;
> +
> +       chans = 1 + ((sys_reg >> SYS_REG_NUM_CH_SHIFT) & SYS_REG_NUM_CH_MASK);
> +
> +       for (ch = 0; ch < chans; ch++) {
> +               rank = 1 + (sys_reg >> SYS_REG_RANK_SHIFT(ch) &
> +                       SYS_REG_RANK_MASK);
> +               col = 9 + (sys_reg >> SYS_REG_COL_SHIFT(ch) & SYS_REG_COL_MASK);
> +               bk = 3 - ((sys_reg >> SYS_REG_BK_SHIFT(ch)) & SYS_REG_BK_MASK);
> +               cs0_row = 13 + (sys_reg >> SYS_REG_CS0_ROW_SHIFT(ch) &
> +                               SYS_REG_CS0_ROW_MASK);
> +               cs1_row = 13 + (sys_reg >> SYS_REG_CS1_ROW_SHIFT(ch) &
> +                               SYS_REG_CS1_ROW_MASK);
> +               bw = (2 >> ((sys_reg >> SYS_REG_BW_SHIFT(ch)) &
> +                       SYS_REG_BW_MASK));
> +               row_3_4 = sys_reg >> SYS_REG_ROW_3_4_SHIFT(ch) &
> +                       SYS_REG_ROW_3_4_MASK;
> +               chipsize_mb = (1 << (cs0_row + col + bk + bw - 20));
> +
> +               if (rank > 1)
> +                       chipsize_mb += chipsize_mb >>
> +                               (cs0_row - cs1_row);
> +               if (row_3_4)
> +                       chipsize_mb = chipsize_mb * 3 / 4;
> +               size_mb += chipsize_mb;
> +       }
> +
> +       /* there can be no more than 2gb of memory */
> +       size_mb = min(size_mb, 0x80000000 >> 20);
> +
> +       return size_mb;
> +}
> +
> +#ifdef CONFIG_SPL_BUILD
> +static int setup_sdram(struct udevice *dev)
> +{
> +       struct dram_info *priv = dev_get_priv(dev);
> +       struct rk3188_sdram_params *params = dev_get_platdata(dev);
> +
> +       return sdram_init(priv, params);
> +}
> +
> +static int rk3188_dmc_ofdata_to_platdata(struct udevice *dev)
> +{
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> +       struct rk3188_sdram_params *params = dev_get_platdata(dev);
> +       const void *blob = gd->fdt_blob;
> +       int node = dev->of_offset;
> +       int ret;
> +
> +       /* rk3188 supports only one-channel */
> +       params->num_channels = 1;
> +       ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
> +                                  (u32 *)&params->pctl_timing,
> +                                  sizeof(params->pctl_timing) / sizeof(u32));
> +       if (ret) {
> +               printf("%s: Cannot read rockchip,pctl-timing\n", __func__);
> +               return -EINVAL;
> +       }
> +       ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
> +                                  (u32 *)&params->phy_timing,
> +                                  sizeof(params->phy_timing) / sizeof(u32));
> +       if (ret) {
> +               printf("%s: Cannot read rockchip,phy-timing\n", __func__);
> +               return -EINVAL;
> +       }
> +       ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
> +                                  (u32 *)&params->base,
> +                                  sizeof(params->base) / sizeof(u32));
> +       if (ret) {
> +               printf("%s: Cannot read rockchip,sdram-params\n", __func__);
> +               return -EINVAL;
> +       }
> +       ret = regmap_init_mem(dev, &params->map);
> +       if (ret)
> +               return ret;
> +#endif
> +
> +       return 0;
> +}
> +#endif /* CONFIG_SPL_BUILD */
> +
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +static int conv_of_platdata(struct udevice *dev)
> +{
> +       struct rk3188_sdram_params *plat = dev_get_platdata(dev);
> +       struct dtd_rockchip_rk3188_dmc *of_plat = &plat->of_plat;
> +       int ret;
> +
> +       memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing,
> +              sizeof(plat->pctl_timing));
> +       memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing,
> +              sizeof(plat->phy_timing));
> +       memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
> +       /* rk3188 supports dual-channel, set default channel num to 2 */
> +       plat->num_channels = 1;
> +       ret = regmap_init_mem_platdata(dev, of_plat->reg,
> +                                      ARRAY_SIZE(of_plat->reg) / 2,
> +                                      &plat->map);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +#endif
> +
> +static int rk3188_dmc_probe(struct udevice *dev)
> +{
> +#ifdef CONFIG_SPL_BUILD
> +       struct rk3188_sdram_params *plat = dev_get_platdata(dev);
> +#endif
> +       struct dram_info *priv = dev_get_priv(dev);
> +       struct regmap *map;
> +       int ret;
> +       struct udevice *dev_clk;
> +
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +       ret = conv_of_platdata(dev);
> +       if (ret)
> +               return ret;
> +#endif
> +       map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
> +       if (IS_ERR(map))
> +               return PTR_ERR(map);
> +       priv->chan[0].msch = regmap_get_range(map, 0);
> +
> +       priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> +       priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
> +
> +#ifdef CONFIG_SPL_BUILD
> +       priv->chan[0].pctl = regmap_get_range(plat->map, 0);
> +       priv->chan[0].publ = regmap_get_range(plat->map, 1);
> +#endif
> +
> +       ret = rockchip_get_clk(&dev_clk);
> +       if (ret)
> +               return ret;
> +       priv->ddr_clk.id = CLK_DDR;
> +       ret = clk_request(dev_clk, &priv->ddr_clk);
> +       if (ret)
> +               return ret;
> +
> +       priv->cru = rockchip_get_cru();
> +       if (IS_ERR(priv->cru))
> +               return PTR_ERR(priv->cru);
> +#ifdef CONFIG_SPL_BUILD
> +       ret = setup_sdram(dev);
> +       if (ret)
> +               return ret;
> +#endif
> +       priv->info.base = 0;
> +       priv->info.size = sdram_size_mb(priv->pmu) << 20;
> +
> +       return 0;
> +}
> +
> +static int rk3188_dmc_get_info(struct udevice *dev, struct ram_info *info)
> +{
> +       struct dram_info *priv = dev_get_priv(dev);
> +
> +       *info = priv->info;
> +
> +       return 0;
> +}
> +
> +static struct ram_ops rk3188_dmc_ops = {
> +       .get_info = rk3188_dmc_get_info,
> +};
> +
> +static const struct udevice_id rk3188_dmc_ids[] = {
> +       { .compatible = "rockchip,rk3188-dmc" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(dmc_rk3188) = {
> +       .name = "rockchip_rk3188_dmc",
> +       .id = UCLASS_RAM,
> +       .of_match = rk3188_dmc_ids,
> +       .ops = &rk3188_dmc_ops,
> +#ifdef CONFIG_SPL_BUILD
> +       .ofdata_to_platdata = rk3188_dmc_ofdata_to_platdata,
> +#endif
> +       .probe = rk3188_dmc_probe,
> +       .priv_auto_alloc_size = sizeof(struct dram_info),
> +#ifdef CONFIG_SPL_BUILD
> +       .platdata_auto_alloc_size = sizeof(struct rk3188_sdram_params),
> +#endif
> +};
> --
> 2.11.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  2017-02-11  0:47     ` Heiko Stuebner
  0 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> The rk3188 needs 3 uboot stages: a tpl living in 1KB of sram, a spl
> the resides in the rest of the sram and loads the regular uboot living
> in regular ram.

s/uboot/U-Boot/

>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/arm/mach-rockchip/Makefile           |   7 +-
>  arch/arm/mach-rockchip/rk3188-board-spl.c | 220 ++++++++++++++++++++++++++++++

There is a lot of common code here with rk3288 - can we unify it a
bit, or is that not feasible?

>  arch/arm/mach-rockchip/rk3188-board-tpl.c |  87 ++++++++++++
>  arch/arm/mach-rockchip/rk3188-board.c     |  71 ++++++++++
>  4 files changed, 384 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/mach-rockchip/rk3188-board-spl.c
>  create mode 100644 arch/arm/mach-rockchip/rk3188-board-tpl.c
>  create mode 100644 arch/arm/mach-rockchip/rk3188-board.c
>
> diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
> index 2be7e14e3e..7b8abc2266 100644
> --- a/arch/arm/mach-rockchip/Makefile
> +++ b/arch/arm/mach-rockchip/Makefile
> @@ -4,11 +4,16 @@
>  # SPDX-License-Identifier:     GPL-2.0+
>  #
>
> -ifdef CONFIG_SPL_BUILD
> +ifdef CONFIG_TPL_BUILD
> +obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
> +obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
> +else ifdef CONFIG_SPL_BUILD
>  obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
> +obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
>  obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
>  obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
>  else
> +obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
>  obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
>  obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
>  endif
> diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c
> new file mode 100644
> index 0000000000..b528a2f73d
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3188-board-spl.c
> @@ -0,0 +1,220 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <debug_uart.h>
> +#include <dm.h>
> +#include <fdtdec.h>
> +#include <led.h>
> +#include <malloc.h>
> +#include <ram.h>
> +#include <spl.h>
> +#include <asm/gpio.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/hardware.h>
> +#include <asm/arch/periph.h>
> +#include <asm/arch/pmu_rk3188.h>
> +#include <asm/arch/sdram.h>
> +#include <asm/arch/timer.h>
> +#include <dm/pinctrl.h>
> +#include <dm/root.h>
> +#include <dm/test.h>
> +#include <dm/util.h>
> +#include <power/regulator.h>
> +#include <syscon.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +u32 spl_boot_device(void)
> +{
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> +       const void *blob = gd->fdt_blob;
> +       struct udevice *dev;
> +       const char *bootdev;
> +       int node;
> +       int ret;
> +
> +       bootdev = fdtdec_get_config_string(blob, "u-boot,boot0");
> +       debug("Boot device %s\n", bootdev);
> +       if (!bootdev)
> +               goto fallback;
> +
> +       node = fdt_path_offset(blob, bootdev);
> +       if (node < 0) {
> +               debug("node=%d\n", node);
> +               goto fallback;
> +       }
> +       ret = device_get_global_by_of_offset(node, &dev);
> +       if (ret) {
> +               debug("device at node %s/%d not found: %d\n", bootdev, node,
> +                     ret);
> +               goto fallback;
> +       }
> +       debug("Found device %s\n", dev->name);
> +       switch (device_get_uclass_id(dev)) {
> +       case UCLASS_SPI_FLASH:
> +               return BOOT_DEVICE_SPI;
> +       case UCLASS_MMC:
> +               return BOOT_DEVICE_MMC1;
> +       default:
> +               debug("Booting from device uclass '%s' not supported\n",
> +                     dev_get_uclass_name(dev));
> +       }
> +
> +fallback:
> +#endif
> +       return BOOT_DEVICE_MMC1;
> +}
> +
> +u32 spl_boot_mode(const u32 boot_device)
> +{
> +       return MMCSD_MODE_RAW;
> +}
> +
> +extern u32 SAVE_SP_ADDR;
> +extern void back_to_bootrom(void);
> +void board_init_f(ulong dummy)
> +{
> +       struct udevice *pinctrl, *dev;
> +       struct rk3188_pmu *pmu;
> +       int ret;
> +
> +#define EARLY_UART
> +       /* Example code showing how to enable the debug UART on RK3188 */
> +#ifdef EARLY_UART
> +#include <asm/arch/grf_rk3188.h>
> +       /* Enable early UART on the RK3188 */
> +#define GRF_BASE       0x20008000
> +       struct rk3188_grf * const grf = (void *)GRF_BASE;
> +
> +       rk_clrsetreg(&grf->gpio1b_iomux,
> +                    GPIO1B1_MASK << GPIO1B1_SHIFT |
> +                    GPIO1B0_MASK << GPIO1B0_SHIFT,
> +                    GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
> +                    GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
> +       /*
> +        * Debug UART can be used from here if required:
> +        *
> +        * debug_uart_init();
> +        * printch('a');
> +        * printhex8(0x1234);
> +        * printascii("string");
> +        */
> +       debug_uart_init();
> +       printch('s');
> +       printch('p');
> +       printch('l');
> +       printch('\n');

printascii("spl\n");

> +#endif
> +
> +       ret = spl_init();
> +       if (ret) {
> +               debug("spl_init() failed: %d\n", ret);
> +               hang();
> +       }
> +
> +       rockchip_timer_init();
> +
> +       ret = rockchip_get_clk(&dev);
> +       if (ret) {
> +               debug("CLK init failed: %d\n", ret);
> +               return;
> +       }
> +
> +       /*
> +        * Recover the bootrom's stackpointer.
> +        * For whatever reason needs to run after rockchip_get_clk.
> +        */
> +       pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
> +       if (IS_ERR(pmu))
> +               error("pmu syscon returned %ld\n", PTR_ERR(pmu));
> +       SAVE_SP_ADDR = readl(&pmu->sys_reg[2]);
> +
> +       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> +       if (ret) {
> +               debug("Pinctrl init failed: %d\n", ret);
> +               return;
> +       }
> +
> +       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> +       if (ret) {
> +               debug("DRAM init failed: %d\n", ret);
> +               return;
> +       }
> +
> +#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
> +       back_to_bootrom();
> +#endif
> +}
> +
> +static int setup_led(void)
> +{
> +#ifdef CONFIG_SPL_LED
> +       struct udevice *dev;
> +       char *led_name;
> +       int ret;
> +
> +       led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led");
> +       if (!led_name)
> +               return 0;
> +       ret = led_get_by_label(led_name, &dev);
> +       if (ret) {
> +               debug("%s: get=%d\n", __func__, ret);
> +               return ret;
> +       }
> +       ret = led_set_on(dev, 1);
> +       if (ret)
> +               return ret;
> +#endif
> +
> +       return 0;
> +}
> +
> +void spl_board_init(void)
> +{
> +       struct udevice *pinctrl;
> +       int ret;
> +
> +       ret = setup_led();
> +       if (ret) {
> +               debug("LED ret=%d\n", ret);
> +               hang();
> +       }
> +
> +       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> +       if (ret) {
> +               debug("%s: Cannot find pinctrl device\n", __func__);
> +               goto err;
> +       }
> +
> +#ifdef CONFIG_SPL_MMC_SUPPORT
> +       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
> +       if (ret) {
> +               debug("%s: Failed to set up SD card\n", __func__);
> +               goto err;
> +       }
> +#endif
> +
> +       /* Enable debug UART */
> +       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
> +       if (ret) {
> +               debug("%s: Failed to set up console UART\n", __func__);
> +               goto err;
> +       }
> +
> +       preloader_console_init();
> +#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
> +       back_to_bootrom();
> +#endif
> +       return;
> +
> +err:
> +       printf("spl_board_init: Error %d\n", ret);
> +
> +       /* No way to report error here */
> +       hang();
> +}
> diff --git a/arch/arm/mach-rockchip/rk3188-board-tpl.c b/arch/arm/mach-rockchip/rk3188-board-tpl.c
> new file mode 100644
> index 0000000000..62cdb8976a
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3188-board-tpl.c
> @@ -0,0 +1,87 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <debug_uart.h>
> +#include <spl.h>
> +#include <asm/io.h>
> +#include <asm/arch/pmu_rk3188.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* track how often we were entered */
> +static int rk3188_num_entries;

Is this in BSS? I suspect it might cause problems. Perhaps put it in
the data section?

> +extern void back_to_bootrom(void);

Should be in a header file somewhere

> +
> +#define PMU_BASE       0x20004000
> +#define TPL_ENTRY      0x10080C00
> +extern u32 SAVE_SP_ADDR;

Blank line

> +static void jump_to_tpl(void)
> +{
> +       typedef void __noreturn (*image_entry_noargs_t)(void);
> +
> +       struct rk3188_pmu * const pmu = (void *)PMU_BASE;
> +       image_entry_noargs_t tpl_entry =
> +               (image_entry_noargs_t)(unsigned long)TPL_ENTRY;
> +
> +       /* Store the SAVE_SP_ADDR in a location shared with TPL. */
> +       writel(SAVE_SP_ADDR, &pmu->sys_reg[2]);
> +       tpl_entry();
> +}
> +
> +void board_init_f(ulong dummy)
> +{
> +#define EARLY_UART
> +       /* Example code showing how to enable the debug UART on RK3188 */
> +#ifdef EARLY_UART
> +#include <asm/arch/grf_rk3188.h>
> +       /* Enable early UART on the RK3188 */
> +#define GRF_BASE       0x20008000
> +       struct rk3188_grf * const grf = (void *)GRF_BASE;
> +
> +       rk_clrsetreg(&grf->gpio1b_iomux,
> +                    GPIO1B1_MASK << GPIO1B1_SHIFT |
> +                    GPIO1B0_MASK << GPIO1B0_SHIFT,
> +                    GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
> +                    GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
> +       /*
> +        * Debug UART can be used from here if required:
> +        *
> +        * debug_uart_init();
> +        * printch('a');
> +        * printhex8(0x1234);
> +        * printascii("string");
> +        */
> +       debug_uart_init();
> +
> +       printch('t');
> +       printch('p');
> +       printch('l');
> +       printch('-');

printascii()

> +       printch(rk3188_num_entries + 1 + '0');
> +       printch('\n');
> +#endif
> +
> +       rk3188_num_entries++;
> +
> +       if (rk3188_num_entries == 1) {
> +               /*
> +                * The original loader did some very basic integrity
> +                * checking at this point, but the remaining few bytes
> +                * could be used for any improvement making sense
> +                * really early on.
> +                */
> +
> +               back_to_bootrom();
> +       } else {
> +               /*
> +                * TPL part of the loader should now wait for us
> +                * at offset 0xC00 in the sram. Should never return
> +                * from there.
> +                */
> +               jump_to_tpl();
> +       }
> +}
> diff --git a/arch/arm/mach-rockchip/rk3188-board.c b/arch/arm/mach-rockchip/rk3188-board.c
> new file mode 100644
> index 0000000000..16f38559af
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3188-board.c
> @@ -0,0 +1,71 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <ram.h>
> +#include <syscon.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/periph.h>
> +#include <asm/arch/pmu_rk3288.h>
> +#include <asm/arch/boot_mode.h>
> +#include <asm/gpio.h>
> +#include <dm/pinctrl.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int board_init(void)
> +{
> +#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM)
> +       struct udevice *pinctrl;
> +       int ret;
> +
> +       /*
> +        * We need to implement sdcard iomux here for the further
> +        * initialization, otherwise, it'll hit sdcard command sending
> +        * timeout exception.
> +        */
> +       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> +       if (ret) {
> +               debug("%s: Cannot find pinctrl device\n", __func__);
> +               goto err;
> +       }
> +       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
> +       if (ret) {
> +               debug("%s: Failed to set up SD card\n", __func__);
> +               goto err;
> +       }
> +
> +       return 0;
> +err:
> +       printf("board_init: Error %d\n", ret);
> +
> +       /* No way to report error here */
> +       hang();
> +
> +       return -1;
> +#else
> +       return 0;
> +#endif
> +}
> +
> +int dram_init(void)
> +{
> +       /* FIXME: read back ram size from sys_reg2 */

TODO(email):

> +       gd->ram_size = 0x40000000;
> +
> +       return 0;
> +}
> +
> +#ifndef CONFIG_SYS_DCACHE_OFF
> +void enable_caches(void)
> +{
> +       /* Enable D-cache. I-cache is already enabled in start.S */
> +       dcache_enable();
> +}
> +#endif
> --
> 2.11.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 15/16] rockchip: rk3188: Add Radxa Rock board
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 15/16] rockchip: rk3188: Add Radxa Rock board Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> The Rock is a RK3188 based single board computer by Radxa.
> Currently it still relies on the proprietary DDR init and
> cannot use the generic SPL, but at least is able to boot
> a linux kernel and system up to a regular login prompt.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/arm/dts/Makefile                 |   1 +
>  arch/arm/dts/rk3188-radxarock.dts     | 382 ++++++++++++++++++++++++++++++++++
>  arch/arm/mach-rockchip/rk3188/Kconfig |  11 +
>  board/radxa/rock/Kconfig              |  15 ++
>  board/radxa/rock/MAINTAINERS          |   6 +
>  board/radxa/rock/Makefile             |   7 +
>  board/radxa/rock/rock.c               |   7 +
>  configs/rock_defconfig                |  56 +++++
>  include/configs/rock.h                |  30 +++
>  9 files changed, 515 insertions(+)
>  create mode 100644 arch/arm/dts/rk3188-radxarock.dts
>  create mode 100644 board/radxa/rock/Kconfig
>  create mode 100644 board/radxa/rock/MAINTAINERS
>  create mode 100644 board/radxa/rock/Makefile
>  create mode 100644 board/radxa/rock/rock.c
>  create mode 100644 configs/rock_defconfig
>  create mode 100644 include/configs/rock.h

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [TEST-ONLY 16/16] Add a temporary script that can create a bootimage for rk3188
  2017-02-03 16:09 ` [U-Boot] [TEST-ONLY 16/16] Add a temporary script that can create a bootimage for rk3188 Heiko Stuebner
@ 2017-02-06 15:35   ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-06 15:35 UTC (permalink / raw)
  To: u-boot

On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Combines tpl, spl and uboot image in one flashable image.
> ---
>  mkuboot | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100755 mkuboot

Could use binman?

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files
  2017-02-06 15:35   ` Simon Glass
@ 2017-02-10 23:17     ` Heiko Stuebner
  0 siblings, 0 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-10 23:17 UTC (permalink / raw)
  To: u-boot

Am Montag, 6. Februar 2017, 07:35:16 CET schrieb Simon Glass:
> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > The rk3188 shares a lot of peripherals with the rk3066 and thus
> > has a common include called rk3xxx.dtsi. Add both this one and
> > the specialized rk3188 on top of it.
> > 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> > 
> >  arch/arm/dts/rk3188.dtsi | 601
> >  +++++++++++++++++++++++++++++++++++++++++++++++ arch/arm/dts/rk3xxx.dtsi
> >  | 417 ++++++++++++++++++++++++++++++++
> >  2 files changed, 1018 insertions(+)
> >  create mode 100644 arch/arm/dts/rk3188.dtsi
> >  create mode 100644 arch/arm/dts/rk3xxx.dtsi
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> Does this mirror the Linux kernel setup?

yep, the split on the file level is the same in kernel. rk3066 and rk3188 share 
nearly every core component. The only change compared to the kernel are the 
added u-boot,* properties.


Heiko

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards
  2017-02-06 15:35   ` Simon Glass
@ 2017-02-11  0:47     ` Heiko Stuebner
  0 siblings, 0 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-11  0:47 UTC (permalink / raw)
  To: u-boot

Am Montag, 6. Februar 2017, 07:35:25 CET schrieb Simon Glass:
> Hi Heiko,
> 
> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > The rk3188 needs 3 uboot stages: a tpl living in 1KB of sram, a spl
> > the resides in the rest of the sram and loads the regular uboot living
> > in regular ram.
> 
> s/uboot/U-Boot/
> 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> > 
> >  arch/arm/mach-rockchip/Makefile           |   7 +-
> >  arch/arm/mach-rockchip/rk3188-board-spl.c | 220
> >  ++++++++++++++++++++++++++++++
> There is a lot of common code here with rk3288 - can we unify it a
> bit, or is that not feasible?

not sure about that. In the end the amount of code is not that much - 
essentially the setup_led() and spl_board_init() could be unified a bit, but 
then spl_board_init() would probably require empty functions for not 
implemented stuff  - configure_emmc on rk3188 for example.

So I'm not sure if this would help or just makes everything more complicated.


> 
> >  arch/arm/mach-rockchip/rk3188-board-tpl.c |  87 ++++++++++++
> >  arch/arm/mach-rockchip/rk3188-board.c     |  71 ++++++++++
> >  4 files changed, 384 insertions(+), 1 deletion(-)
> >  create mode 100644 arch/arm/mach-rockchip/rk3188-board-spl.c
> >  create mode 100644 arch/arm/mach-rockchip/rk3188-board-tpl.c
> >  create mode 100644 arch/arm/mach-rockchip/rk3188-board.c
> > 
> > diff --git a/arch/arm/mach-rockchip/Makefile
> > b/arch/arm/mach-rockchip/Makefile index 2be7e14e3e..7b8abc2266 100644
> > --- a/arch/arm/mach-rockchip/Makefile
> > +++ b/arch/arm/mach-rockchip/Makefile
> > @@ -4,11 +4,16 @@
> > 
> >  # SPDX-License-Identifier:     GPL-2.0+
> >  #
> > 
> > -ifdef CONFIG_SPL_BUILD
> > +ifdef CONFIG_TPL_BUILD
> > +obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
> > +obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
> > +else ifdef CONFIG_SPL_BUILD
> > 
> >  obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
> > 
> > +obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
> > 
> >  obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
> >  obj-$(CONFIG_ROCKCHIP_BROM_HELPER) += save_boot_param.o
> >  else
> > 
> > +obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
> > 
> >  obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
> >  obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
> >  endif
> > 
> > diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c
> > b/arch/arm/mach-rockchip/rk3188-board-spl.c new file mode 100644
> > index 0000000000..b528a2f73d
> > --- /dev/null
> > +++ b/arch/arm/mach-rockchip/rk3188-board-spl.c
> > @@ -0,0 +1,220 @@
> > +/*
> > + * (C) Copyright 2015 Google, Inc
> > + *
> > + * SPDX-License-Identifier:     GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <debug_uart.h>
> > +#include <dm.h>
> > +#include <fdtdec.h>
> > +#include <led.h>
> > +#include <malloc.h>
> > +#include <ram.h>
> > +#include <spl.h>
> > +#include <asm/gpio.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/clock.h>
> > +#include <asm/arch/hardware.h>
> > +#include <asm/arch/periph.h>
> > +#include <asm/arch/pmu_rk3188.h>
> > +#include <asm/arch/sdram.h>
> > +#include <asm/arch/timer.h>
> > +#include <dm/pinctrl.h>
> > +#include <dm/root.h>
> > +#include <dm/test.h>
> > +#include <dm/util.h>
> > +#include <power/regulator.h>
> > +#include <syscon.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +u32 spl_boot_device(void)
> > +{
> > +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> > +       const void *blob = gd->fdt_blob;
> > +       struct udevice *dev;
> > +       const char *bootdev;
> > +       int node;
> > +       int ret;
> > +
> > +       bootdev = fdtdec_get_config_string(blob, "u-boot,boot0");
> > +       debug("Boot device %s\n", bootdev);
> > +       if (!bootdev)
> > +               goto fallback;
> > +
> > +       node = fdt_path_offset(blob, bootdev);
> > +       if (node < 0) {
> > +               debug("node=%d\n", node);
> > +               goto fallback;
> > +       }
> > +       ret = device_get_global_by_of_offset(node, &dev);
> > +       if (ret) {
> > +               debug("device at node %s/%d not found: %d\n", bootdev,
> > node, +                     ret);
> > +               goto fallback;
> > +       }
> > +       debug("Found device %s\n", dev->name);
> > +       switch (device_get_uclass_id(dev)) {
> > +       case UCLASS_SPI_FLASH:
> > +               return BOOT_DEVICE_SPI;
> > +       case UCLASS_MMC:
> > +               return BOOT_DEVICE_MMC1;
> > +       default:
> > +               debug("Booting from device uclass '%s' not supported\n",
> > +                     dev_get_uclass_name(dev));
> > +       }
> > +
> > +fallback:
> > +#endif
> > +       return BOOT_DEVICE_MMC1;
> > +}
> > +
> > +u32 spl_boot_mode(const u32 boot_device)
> > +{
> > +       return MMCSD_MODE_RAW;
> > +}
> > +
> > +extern u32 SAVE_SP_ADDR;
> > +extern void back_to_bootrom(void);
> > +void board_init_f(ulong dummy)
> > +{
> > +       struct udevice *pinctrl, *dev;
> > +       struct rk3188_pmu *pmu;
> > +       int ret;
> > +
> > +#define EARLY_UART
> > +       /* Example code showing how to enable the debug UART on RK3188 */
> > +#ifdef EARLY_UART
> > +#include <asm/arch/grf_rk3188.h>
> > +       /* Enable early UART on the RK3188 */
> > +#define GRF_BASE       0x20008000
> > +       struct rk3188_grf * const grf = (void *)GRF_BASE;
> > +
> > +       rk_clrsetreg(&grf->gpio1b_iomux,
> > +                    GPIO1B1_MASK << GPIO1B1_SHIFT |
> > +                    GPIO1B0_MASK << GPIO1B0_SHIFT,
> > +                    GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
> > +                    GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
> > +       /*
> > +        * Debug UART can be used from here if required:
> > +        *
> > +        * debug_uart_init();
> > +        * printch('a');
> > +        * printhex8(0x1234);
> > +        * printascii("string");
> > +        */
> > +       debug_uart_init();
> > +       printch('s');
> > +       printch('p');
> > +       printch('l');
> > +       printch('\n');
> 
> printascii("spl\n");

actually using printascii at this point make the board hang in the past. So 
far I haven't figured out why printch works but printascii does not.

I'll try again, maybe it magically fixed itself


> > +#endif
> > +
> > +       ret = spl_init();
> > +       if (ret) {
> > +               debug("spl_init() failed: %d\n", ret);
> > +               hang();
> > +       }
> > +
> > +       rockchip_timer_init();
> > +
> > +       ret = rockchip_get_clk(&dev);
> > +       if (ret) {
> > +               debug("CLK init failed: %d\n", ret);
> > +               return;
> > +       }
> > +
> > +       /*
> > +        * Recover the bootrom's stackpointer.
> > +        * For whatever reason needs to run after rockchip_get_clk.
> > +        */
> > +       pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
> > +       if (IS_ERR(pmu))
> > +               error("pmu syscon returned %ld\n", PTR_ERR(pmu));
> > +       SAVE_SP_ADDR = readl(&pmu->sys_reg[2]);
> > +
> > +       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> > +       if (ret) {
> > +               debug("Pinctrl init failed: %d\n", ret);
> > +               return;
> > +       }
> > +
> > +       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> > +       if (ret) {
> > +               debug("DRAM init failed: %d\n", ret);
> > +               return;
> > +       }
> > +
> > +#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) &&
> > !defined(CONFIG_SPL_BOARD_INIT) +       back_to_bootrom();
> > +#endif
> > +}
> > +
> > +static int setup_led(void)
> > +{
> > +#ifdef CONFIG_SPL_LED
> > +       struct udevice *dev;
> > +       char *led_name;
> > +       int ret;
> > +
> > +       led_name = fdtdec_get_config_string(gd->fdt_blob,
> > "u-boot,boot-led"); +       if (!led_name)
> > +               return 0;
> > +       ret = led_get_by_label(led_name, &dev);
> > +       if (ret) {
> > +               debug("%s: get=%d\n", __func__, ret);
> > +               return ret;
> > +       }
> > +       ret = led_set_on(dev, 1);
> > +       if (ret)
> > +               return ret;
> > +#endif
> > +
> > +       return 0;
> > +}
> > +
> > +void spl_board_init(void)
> > +{
> > +       struct udevice *pinctrl;
> > +       int ret;
> > +
> > +       ret = setup_led();
> > +       if (ret) {
> > +               debug("LED ret=%d\n", ret);
> > +               hang();
> > +       }
> > +
> > +       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> > +       if (ret) {
> > +               debug("%s: Cannot find pinctrl device\n", __func__);
> > +               goto err;
> > +       }
> > +
> > +#ifdef CONFIG_SPL_MMC_SUPPORT
> > +       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
> > +       if (ret) {
> > +               debug("%s: Failed to set up SD card\n", __func__);
> > +               goto err;
> > +       }
> > +#endif
> > +
> > +       /* Enable debug UART */
> > +       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
> > +       if (ret) {
> > +               debug("%s: Failed to set up console UART\n", __func__);
> > +               goto err;
> > +       }
> > +
> > +       preloader_console_init();
> > +#ifdef CONFIG_ROCKCHIP_SPL_BACK_TO_BROM
> > +       back_to_bootrom();
> > +#endif
> > +       return;
> > +
> > +err:
> > +       printf("spl_board_init: Error %d\n", ret);
> > +
> > +       /* No way to report error here */
> > +       hang();
> > +}
> > diff --git a/arch/arm/mach-rockchip/rk3188-board-tpl.c
> > b/arch/arm/mach-rockchip/rk3188-board-tpl.c new file mode 100644
> > index 0000000000..62cdb8976a
> > --- /dev/null
> > +++ b/arch/arm/mach-rockchip/rk3188-board-tpl.c
> > @@ -0,0 +1,87 @@
> > +/*
> > + * (C) Copyright 2015 Google, Inc
> > + *
> > + * SPDX-License-Identifier:     GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <debug_uart.h>
> > +#include <spl.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/pmu_rk3188.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/* track how often we were entered */
> > +static int rk3188_num_entries;
> 
> Is this in BSS? I suspect it might cause problems. Perhaps put it in
> the data section?

ok, I'll give that a try. So far I've never reached linker stuff, but judging 
from other uboot code a " __attribute__ ((section(".data")))" should be 
sufficient?


> 
> > +extern void back_to_bootrom(void);
> 
> Should be in a header file somewhere

So far each board has declared this itself, but I've moved it to a header now
for all of them.


> > +
> > +#define PMU_BASE       0x20004000
> > +#define TPL_ENTRY      0x10080C00
> > +extern u32 SAVE_SP_ADDR;

I've also moved this to my new bootrom.h


> 
> Blank line

ok

> > +static void jump_to_tpl(void)
> > +{
> > +       typedef void __noreturn (*image_entry_noargs_t)(void);
> > +
> > +       struct rk3188_pmu * const pmu = (void *)PMU_BASE;
> > +       image_entry_noargs_t tpl_entry =
> > +               (image_entry_noargs_t)(unsigned long)TPL_ENTRY;
> > +
> > +       /* Store the SAVE_SP_ADDR in a location shared with TPL. */
> > +       writel(SAVE_SP_ADDR, &pmu->sys_reg[2]);
> > +       tpl_entry();
> > +}
> > +
> > +void board_init_f(ulong dummy)
> > +{
> > +#define EARLY_UART
> > +       /* Example code showing how to enable the debug UART on RK3188 */
> > +#ifdef EARLY_UART
> > +#include <asm/arch/grf_rk3188.h>
> > +       /* Enable early UART on the RK3188 */
> > +#define GRF_BASE       0x20008000
> > +       struct rk3188_grf * const grf = (void *)GRF_BASE;
> > +
> > +       rk_clrsetreg(&grf->gpio1b_iomux,
> > +                    GPIO1B1_MASK << GPIO1B1_SHIFT |
> > +                    GPIO1B0_MASK << GPIO1B0_SHIFT,
> > +                    GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
> > +                    GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
> > +       /*
> > +        * Debug UART can be used from here if required:
> > +        *
> > +        * debug_uart_init();
> > +        * printch('a');
> > +        * printhex8(0x1234);
> > +        * printascii("string");
> > +        */
> > +       debug_uart_init();
> > +
> > +       printch('t');
> > +       printch('p');
> > +       printch('l');
> > +       printch('-');
> 
> printascii()

see spl printascii comment :-)

> 
> > +       printch(rk3188_num_entries + 1 + '0');
> > +       printch('\n');
> > +#endif
> > +
> > +       rk3188_num_entries++;
> > +
> > +       if (rk3188_num_entries == 1) {
> > +               /*
> > +                * The original loader did some very basic integrity
> > +                * checking at this point, but the remaining few bytes
> > +                * could be used for any improvement making sense
> > +                * really early on.
> > +                */
> > +
> > +               back_to_bootrom();
> > +       } else {
> > +               /*
> > +                * TPL part of the loader should now wait for us
> > +                * at offset 0xC00 in the sram. Should never return
> > +                * from there.
> > +                */
> > +               jump_to_tpl();
> > +       }
> > +}
> > diff --git a/arch/arm/mach-rockchip/rk3188-board.c
> > b/arch/arm/mach-rockchip/rk3188-board.c new file mode 100644
> > index 0000000000..16f38559af
> > --- /dev/null
> > +++ b/arch/arm/mach-rockchip/rk3188-board.c
> > @@ -0,0 +1,71 @@
> > +/*
> > + * (C) Copyright 2015 Google, Inc
> > + *
> > + * SPDX-License-Identifier:     GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <clk.h>
> > +#include <dm.h>
> > +#include <ram.h>
> > +#include <syscon.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/clock.h>
> > +#include <asm/arch/periph.h>
> > +#include <asm/arch/pmu_rk3288.h>
> > +#include <asm/arch/boot_mode.h>
> > +#include <asm/gpio.h>
> > +#include <dm/pinctrl.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +int board_init(void)
> > +{
> > +#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM)
> > +       struct udevice *pinctrl;
> > +       int ret;
> > +
> > +       /*
> > +        * We need to implement sdcard iomux here for the further
> > +        * initialization, otherwise, it'll hit sdcard command sending
> > +        * timeout exception.
> > +        */
> > +       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> > +       if (ret) {
> > +               debug("%s: Cannot find pinctrl device\n", __func__);
> > +               goto err;
> > +       }
> > +       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
> > +       if (ret) {
> > +               debug("%s: Failed to set up SD card\n", __func__);
> > +               goto err;
> > +       }
> > +
> > +       return 0;
> > +err:
> > +       printf("board_init: Error %d\n", ret);
> > +
> > +       /* No way to report error here */
> > +       hang();
> > +
> > +       return -1;
> > +#else
> > +       return 0;
> > +#endif
> > +}
> > +
> > +int dram_init(void)
> > +{
> > +       /* FIXME: read back ram size from sys_reg2 */
> 
> TODO(email):
> > +       gd->ram_size = 0x40000000;

yep, I plan on doing this once the jump from spl to uboot actually works :-)


> > +
> > +       return 0;
> > +}
> > +
> > +#ifndef CONFIG_SYS_DCACHE_OFF
> > +void enable_caches(void)
> > +{
> > +       /* Enable D-cache. I-cache is already enabled in start.S */
> > +       dcache_enable();
> > +}
> > +#endif
> > --
> > 2.11.0
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 00/16] rk3188 uboot support
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (15 preceding siblings ...)
  2017-02-03 16:09 ` [U-Boot] [TEST-ONLY 16/16] Add a temporary script that can create a bootimage for rk3188 Heiko Stuebner
@ 2017-02-16 20:43 ` Simon Glass
  2017-02-17  0:41   ` Heiko Stübner
  2017-02-17  3:21 ` Kever Yang
  17 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2017-02-16 20:43 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 3 February 2017 at 09:09, Heiko Stuebner <heiko@sntech.de> wrote:
> Hi,
>
> this is meant as a status update and possible discussion for
> the core parts if needed.
>
> After talking with Simon and Tom the order is now also correct
> with tpl -> spl -> uboot.
>
>
> Status right now is:
> - the full uboot still works
> - the tpl/spl does start and is able to configure the ddr
>   into a working state
> - The jump spl -> bootrom -> uboot doesn't work though
>
> On the other hand, Kever was able to make this work, booting
> from nand when building the image with a very ancient tool.
>
> All newer tools (including boot_merger.c from Rockchip's uboot)
> do not produce working images. But it is possible to produce
> a working sd-boot image using the proprietary 1st-stage loader.
>
> See the temporary mkuboot script in the last patch, which can
> create both types of images now (especially wrt. the needed
> rc4 encryption of everything).
>
> Combining this (it does work using some special tool), it looks
> like there is still some minor glitch in the way we build the
> spl image somewhere.

What should we do with this series? There are a few minor things to
resolve but other than that, do you think it is ready to apply?

The above problem could perhaps be resolved later if there is a
suitable README describing it?

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl
  2017-02-06 15:34   ` Simon Glass
@ 2017-02-17  0:36     ` Heiko Stübner
  2017-02-22  3:59       ` Simon Glass
  0 siblings, 1 reply; 45+ messages in thread
From: Heiko Stübner @ 2017-02-17  0:36 UTC (permalink / raw)
  To: u-boot

Hi Simon,

Am Montag, 6. Februar 2017, 07:34:54 CET schrieb Simon Glass:
> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > Right now the u-boot,dm-pre-reloc flag will make each marked node
> > always appear in both spl and tpl. But systems needing an additional
> > tpl might have special constraints for each, like the spl needing to
> > be very tiny.
> > 
> > So introduce two additional flags to mark nodes for only spl or tpl
> > environments and introduce a function dm_fdt_pre_reloc to automate
> > the necessary checks in code instances checking for pre-relocation
> > flags.
> > 
> > The behaviour of the original flag stays untouched and still marks
> > a node for both spl and tpl.
> > 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> > 
> >  doc/driver-model/README.txt      |  4 ++++
> >  drivers/clk/at91/pmc.c           |  3 ++-
> >  drivers/core/root.c              |  2 +-
> >  drivers/core/util.c              | 29 +++++++++++++++++++++++++++++
> >  drivers/pinctrl/pinctrl-uclass.c |  3 ++-
> >  include/dm/util.h                |  2 ++
> >  scripts/Makefile.spl             |  7 ++++++-
> >  tools/dtoc/dtoc.py               |  2 ++
> >  8 files changed, 48 insertions(+), 4 deletions(-)
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> s/u-boot/U-Boot
> 
> Please add a comment for dm_fdt_pre_reloc() in the header file.
> 
> Two things to consider:
> 
> - Should we drop the use of u-boot,dm-pre-reloc in Makefile.spl, and
> convert all users to your version? This would mean having both
> u-boot,dm-pre-reloc and u-boot,dm-spl in some cases, I suspect.
	^^ u-boot,dm-spl and u-boot,dm-tpl I guess

Dropping u-boot,dm-pre-reloc is for you to decide, as you wrote the original 
implementation ;-) . It will save one fdt-query but might need several 
iterations as I guess new boards will add new ones after we remove the old 
ones.

> - Can you use #ifdef in SPL/TPL to reduce code size fractionally in
> dm_fdt_pre_reloc()?

Do you mean moving the
+       dm_spl = fdt_getprop(blob, offset, "u-boot,dm-spl", NULL);
+       dm_tpl = fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL);

into the existing #ifdef CONFIG_TPL_BUILD / SPL_BUILD blocks or something 
else?


Thanks
Heiko

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 00/16] rk3188 uboot support
  2017-02-16 20:43 ` [U-Boot] [PATCH v3 00/16] rk3188 uboot support Simon Glass
@ 2017-02-17  0:41   ` Heiko Stübner
  2017-02-17 20:11     ` Heiko Stuebner
  0 siblings, 1 reply; 45+ messages in thread
From: Heiko Stübner @ 2017-02-17  0:41 UTC (permalink / raw)
  To: u-boot

Hi Simon,

Am Donnerstag, 16. Februar 2017, 13:43:45 CET schrieb Simon Glass:
> On 3 February 2017 at 09:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > this is meant as a status update and possible discussion for
> > the core parts if needed.
> > 
> > After talking with Simon and Tom the order is now also correct
> > with tpl -> spl -> uboot.
> > 
> > 
> > Status right now is:
> > - the full uboot still works
> > - the tpl/spl does start and is able to configure the ddr
> > 
> >   into a working state
> > 
> > - The jump spl -> bootrom -> uboot doesn't work though
> > 
> > On the other hand, Kever was able to make this work, booting
> > from nand when building the image with a very ancient tool.
> > 
> > All newer tools (including boot_merger.c from Rockchip's uboot)
> > do not produce working images. But it is possible to produce
> > a working sd-boot image using the proprietary 1st-stage loader.
> > 
> > See the temporary mkuboot script in the last patch, which can
> > create both types of images now (especially wrt. the needed
> > rc4 encryption of everything).
> > 
> > Combining this (it does work using some special tool), it looks
> > like there is still some minor glitch in the way we build the
> > spl image somewhere.
> 
> What should we do with this series? There are a few minor things to
> resolve but other than that, do you think it is ready to apply?

It's somehow always on the backburner, but I already started fixing the things 
you pointed out. Though I'll be in Portland, Mountain View and San Francisco 
for the next two weeks, so will only be able to resend the fixes after that.


> The above problem could perhaps be resolved later if there is a
> suitable README describing it?

Kever  already found out, that the sd read the bootrom does fails when trying 
to load the uboot from the spl. I'm still trying to investigate this [same 
Portland remark applies], but if you're ok with stuff going in in this state, 
that is definitly fine by me, as it spares me from sending the full series all 
the time ;-)


Heiko

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 00/16] rk3188 uboot support
  2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
                   ` (16 preceding siblings ...)
  2017-02-16 20:43 ` [U-Boot] [PATCH v3 00/16] rk3188 uboot support Simon Glass
@ 2017-02-17  3:21 ` Kever Yang
  17 siblings, 0 replies; 45+ messages in thread
From: Kever Yang @ 2017-02-17  3:21 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

For this patch series, I have test and works on my NAND based rodxa board.

For the sd-card, you will need one patch to fix the problem which I have 
send
to you offline.

Tested-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
On 02/04/2017 12:09 AM, Heiko Stuebner wrote:
> Hi,
>
> this is meant as a status update and possible discussion for
> the core parts if needed.
>
> After talking with Simon and Tom the order is now also correct
> with tpl -> spl -> uboot.
>
>
> Status right now is:
> - the full uboot still works
> - the tpl/spl does start and is able to configure the ddr
>    into a working state
> - The jump spl -> bootrom -> uboot doesn't work though
>
> On the other hand, Kever was able to make this work, booting
> from nand when building the image with a very ancient tool.
>
> All newer tools (including boot_merger.c from Rockchip's uboot)
> do not produce working images. But it is possible to produce
> a working sd-boot image using the proprietary 1st-stage loader.
>
> See the temporary mkuboot script in the last patch, which can
> create both types of images now (especially wrt. the needed
> rc4 encryption of everything).
>
> Combining this (it does work using some special tool), it looks
> like there is still some minor glitch in the way we build the
> spl image somewhere.
>
>
> Heiko Stuebner (16):
>    dm: allow limiting pre-reloc markings to spl or tpl
>    rockchip: move bootrom helper compilation to a hidden option
>    rockchip: mkimage: Allow encoding of loader code in spl images
>    rockchip: mkimage: Add support rk3188 serial
>    rockchip: serial: Adapt rockchip of-platdata driver for rk3188
>    rockchip: rk3188: Add header files for PMU and GRF
>    rockchip: rk3188: Add pinctrl driver
>    rockchip: rk3188: Add sysreset driver
>    rockchip: rk3188: Add rk3066/rk3188 clock bindings
>    rockchip: rk3188: Add clock driver
>    rockchip: rk3188: Add core devicetree files
>    rockchip: rk3188: Add core support
>    rockchip: rk3188: Add sdram driver
>    rockchip: rk3188: Add main, spl and tpl boards
>    rockchip: rk3188: Add Radxa Rock board
>    Add a temporary script that can create a bootimage for rk3188
>
>   arch/arm/dts/Makefile                           |   1 +
>   arch/arm/dts/rk3188-radxarock.dts               | 382 +++++++++
>   arch/arm/dts/rk3188.dtsi                        | 601 +++++++++++++++
>   arch/arm/dts/rk3xxx.dtsi                        | 417 ++++++++++
>   arch/arm/include/asm/arch-rockchip/cru_rk3188.h | 191 +++++
>   arch/arm/include/asm/arch-rockchip/ddr_rk3188.h |  22 +
>   arch/arm/include/asm/arch-rockchip/grf_rk3188.h | 589 ++++++++++++++
>   arch/arm/include/asm/arch-rockchip/pmu_rk3188.h |  36 +
>   arch/arm/mach-rockchip/Kconfig                  |  20 +
>   arch/arm/mach-rockchip/Makefile                 |  14 +-
>   arch/arm/mach-rockchip/rk3188-board-spl.c       | 220 ++++++
>   arch/arm/mach-rockchip/rk3188-board-tpl.c       |  87 +++
>   arch/arm/mach-rockchip/rk3188-board.c           |  71 ++
>   arch/arm/mach-rockchip/rk3188/Kconfig           |  35 +
>   arch/arm/mach-rockchip/rk3188/Makefile          |  11 +
>   arch/arm/mach-rockchip/rk3188/clk_rk3188.c      |  33 +
>   arch/arm/mach-rockchip/rk3188/sdram_rk3188.c    | 985 ++++++++++++++++++++++++
>   arch/arm/mach-rockchip/rk3188/syscon_rk3188.c   |  55 ++
>   board/radxa/rock/Kconfig                        |  15 +
>   board/radxa/rock/MAINTAINERS                    |   6 +
>   board/radxa/rock/Makefile                       |   7 +
>   board/radxa/rock/rock.c                         |   7 +
>   configs/rock_defconfig                          |  56 ++
>   doc/driver-model/README.txt                     |   4 +
>   drivers/clk/at91/pmc.c                          |   3 +-
>   drivers/clk/rockchip/Makefile                   |   1 +
>   drivers/clk/rockchip/clk_rk3188.c               | 523 +++++++++++++
>   drivers/core/root.c                             |   2 +-
>   drivers/core/util.c                             |  29 +
>   drivers/pinctrl/Kconfig                         |   9 +
>   drivers/pinctrl/pinctrl-uclass.c                |   3 +-
>   drivers/pinctrl/rockchip/Makefile               |   1 +
>   drivers/pinctrl/rockchip/pinctrl_rk3188.c       | 611 +++++++++++++++
>   drivers/serial/serial_rockchip.c                |  19 +-
>   drivers/sysreset/Makefile                       |   1 +
>   drivers/sysreset/sysreset_rk3188.c              |  47 ++
>   include/configs/rk3188_common.h                 | 125 +++
>   include/configs/rock.h                          |  30 +
>   include/dm/util.h                               |   2 +
>   include/dt-bindings/clock/rk3066a-cru.h         |  32 +
>   include/dt-bindings/clock/rk3188-cru-common.h   | 256 ++++++
>   include/dt-bindings/clock/rk3188-cru.h          |  48 ++
>   mkuboot                                         |  35 +
>   scripts/Makefile.spl                            |   7 +-
>   tools/dtoc/dtoc.py                              |   2 +
>   tools/rkcommon.c                                |  34 +-
>   tools/rkcommon.h                                |  22 +
>   tools/rkimage.c                                 |   3 +
>   tools/rksd.c                                    |   4 +
>   tools/rkspi.c                                   |   4 +
>   50 files changed, 5707 insertions(+), 11 deletions(-)
>   create mode 100644 arch/arm/dts/rk3188-radxarock.dts
>   create mode 100644 arch/arm/dts/rk3188.dtsi
>   create mode 100644 arch/arm/dts/rk3xxx.dtsi
>   create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>   create mode 100644 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
>   create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rk3188.h
>   create mode 100644 arch/arm/include/asm/arch-rockchip/pmu_rk3188.h
>   create mode 100644 arch/arm/mach-rockchip/rk3188-board-spl.c
>   create mode 100644 arch/arm/mach-rockchip/rk3188-board-tpl.c
>   create mode 100644 arch/arm/mach-rockchip/rk3188-board.c
>   create mode 100644 arch/arm/mach-rockchip/rk3188/Kconfig
>   create mode 100644 arch/arm/mach-rockchip/rk3188/Makefile
>   create mode 100644 arch/arm/mach-rockchip/rk3188/clk_rk3188.c
>   create mode 100644 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
>   create mode 100644 arch/arm/mach-rockchip/rk3188/syscon_rk3188.c
>   create mode 100644 board/radxa/rock/Kconfig
>   create mode 100644 board/radxa/rock/MAINTAINERS
>   create mode 100644 board/radxa/rock/Makefile
>   create mode 100644 board/radxa/rock/rock.c
>   create mode 100644 configs/rock_defconfig
>   create mode 100644 drivers/clk/rockchip/clk_rk3188.c
>   create mode 100644 drivers/pinctrl/rockchip/pinctrl_rk3188.c
>   create mode 100644 drivers/sysreset/sysreset_rk3188.c
>   create mode 100644 include/configs/rk3188_common.h
>   create mode 100644 include/configs/rock.h
>   create mode 100644 include/dt-bindings/clock/rk3066a-cru.h
>   create mode 100644 include/dt-bindings/clock/rk3188-cru-common.h
>   create mode 100644 include/dt-bindings/clock/rk3188-cru.h
>   create mode 100755 mkuboot
>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
@ 2017-02-17  3:23   ` Kever Yang
  1 sibling, 0 replies; 45+ messages in thread
From: Kever Yang @ 2017-02-17  3:23 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 02/04/2017 12:09 AM, Heiko Stuebner wrote:
> Rockchip SoCs allow the spl code to be rc4-encoded, not only the
> image header, but only newer SoCs allow this encoding to be disabled.
>
> The rk3188 is not part of those and requires its boot code to be
> rc4-encoded with the regular key. So add the ability to do this
> encoding via a setting on a per-soc basis when building spl images.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>   tools/rkcommon.c | 33 +++++++++++++++++++++++++++++----
>   tools/rkcommon.h | 22 ++++++++++++++++++++++
>   tools/rkimage.c  |  3 +++
>   tools/rksd.c     |  4 ++++
>   tools/rkspi.c    |  4 ++++
>   5 files changed, 62 insertions(+), 4 deletions(-)
>
> diff --git a/tools/rkcommon.c b/tools/rkcommon.c
> index 0a072aa83c..ed9b24137a 100644
> --- a/tools/rkcommon.c
> +++ b/tools/rkcommon.c
> @@ -46,17 +46,19 @@ struct header0_info {
>    * @imagename:		Image name(passed by "mkimage -n")
>    * @spl_hdr:		Boot ROM requires a 4-bytes spl header
>    * @spl_size:		Spl size(include extra 4-bytes spl header)
> + * @spl_rc4:		RC4 encode the SPL binary (same key as header)
>    */
>   struct spl_info {
>   	const char *imagename;
>   	const char *spl_hdr;
>   	const uint32_t spl_size;
> +	const bool spl_rc4;
>   };
>   
>   static struct spl_info spl_infos[] = {
> -	{ "rk3036", "RK30", 0x1000 },
> -	{ "rk3288", "RK32", 0x8000 },
> -	{ "rk3399", "RK33", 0x20000 },
> +	{ "rk3036", "RK30", 0x1000, false },
> +	{ "rk3288", "RK32", 0x8000, false },
> +	{ "rk3399", "RK33", 0x20000, false },
>   };
>   
>   static unsigned char rc4_key[16] = {
> @@ -113,6 +115,16 @@ int rkcommon_get_spl_size(struct image_tool_params *params)
>   	return info->spl_size;
>   }
>   
> +bool rkcommon_need_rc4_spl(struct image_tool_params *params)
> +{
> +	struct spl_info *info = rkcommon_get_spl_info(params->imagename);
> +
> +	/*
> +	 * info would not be NULL, because of we checked params before.
> +	 */
> +	return info->spl_rc4;
> +}
> +
>   int rkcommon_set_header(void *buf, uint file_size,
>   			struct image_tool_params *params)
>   {
> @@ -124,7 +136,7 @@ int rkcommon_set_header(void *buf, uint file_size,
>   	memset(buf,  '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
>   	hdr = (struct header0_info *)buf;
>   	hdr->signature = RK_SIGNATURE;
> -	hdr->disable_rc4 = 1;
> +	hdr->disable_rc4 = !rkcommon_need_rc4_spl(params);
>   	hdr->init_offset = RK_INIT_OFFSET;
>   
>   	hdr->init_size = (file_size + RK_BLK_SIZE - 1) / RK_BLK_SIZE;
> @@ -135,3 +147,16 @@ int rkcommon_set_header(void *buf, uint file_size,
>   
>   	return 0;
>   }
> +
> +void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size)
> +{
> +	unsigned int remaining = size;
> +
> +	while (remaining > 0) {
> +		int step = (remaining > RK_BLK_SIZE) ? RK_BLK_SIZE : remaining;
> +
> +		rc4_encode(buf + offset, step, rc4_key);
> +		offset += RK_BLK_SIZE;
> +		remaining -= step;
> +	}
> +}
> diff --git a/tools/rkcommon.h b/tools/rkcommon.h
> index c69540f5f3..b4f6f327dc 100644
> --- a/tools/rkcommon.h
> +++ b/tools/rkcommon.h
> @@ -55,4 +55,26 @@ int rkcommon_get_spl_size(struct image_tool_params *params);
>   int rkcommon_set_header(void *buf, uint file_size,
>   			struct image_tool_params *params);
>   
> +/**
> + * rkcommon_need_rc4_spl() - check if rc4 encoded spl is required
> + *
> + * Some socs cannot disable the rc4-encryption of the spl binary.
> + * rc4 encryption is disabled normally except on socs that cannot
> + * handle unencrypted binaries.
> + * @return true or false depending on rc4 being required.
> + */
> +bool rkcommon_need_rc4_spl(struct image_tool_params *params);
> +
> +/**
> + * rkcommon_rc4_encode_spl() - encode the spl binary
> + *
> + * Encrypts the SPL binary using the generic rc4 key as required
> + * by some socs.
> + *
> + * @buf:	Pointer to the SPL data (header and SPL binary)
> + * @offset:	offset inside buf to start at
> + * @size:	number of bytes to encode
> + */
> +void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size);
> +
>   #endif
> diff --git a/tools/rkimage.c b/tools/rkimage.c
> index ef31cb6944..44d098c775 100644
> --- a/tools/rkimage.c
> +++ b/tools/rkimage.c
> @@ -28,6 +28,9 @@ static void rkimage_set_header(void *buf, struct stat *sbuf, int ifd,
>   {
>   	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
>   	       RK_SPL_HDR_SIZE);
> +
> +	if (rkcommon_need_rc4_spl(params))
> +		rkcommon_rc4_encode_spl(buf, 4, params->file_size);
>   }
>   
>   static int rkimage_extract_subimage(void *buf, struct image_tool_params *params)
> diff --git a/tools/rksd.c b/tools/rksd.c
> index a2baa74d31..ff2233ff2d 100644
> --- a/tools/rksd.c
> +++ b/tools/rksd.c
> @@ -41,6 +41,10 @@ static void rksd_set_header(void *buf,  struct stat *sbuf,  int ifd,
>   
>   	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
>   	       RK_SPL_HDR_SIZE);
> +
> +	if (rkcommon_need_rc4_spl(params))
> +		rkcommon_rc4_encode_spl(buf, RK_SPL_START - 4,
> +					params->file_size - RK_SPL_START + 4);
>   }
>   
>   static int rksd_extract_subimage(void *buf,  struct image_tool_params *params)
> diff --git a/tools/rkspi.c b/tools/rkspi.c
> index a0b0051d38..0271d2e817 100644
> --- a/tools/rkspi.c
> +++ b/tools/rkspi.c
> @@ -48,6 +48,10 @@ static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd,
>   	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
>   	       RK_SPL_HDR_SIZE);
>   
> +	if (rkcommon_need_rc4_spl(params))
> +		rkcommon_rc4_encode_spl(buf, RK_SPL_START - 4,
> +					params->file_size - RK_SPL_START + 4);
> +
>   	/*
>   	 * Spread the image out so we only use the first 2KB of each 4KB
>   	 * region. This is a feature of the SPI format required by the Rockchip

Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
Tested-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial
  2017-02-03 16:09 ` [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial Heiko Stuebner
  2017-02-06 15:35   ` Simon Glass
@ 2017-02-17  3:29   ` Kever Yang
  1 sibling, 0 replies; 45+ messages in thread
From: Kever Yang @ 2017-02-17  3:29 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 02/04/2017 12:09 AM, Heiko Stuebner wrote:
> Add the entry for the rk3188 requiring rc4-encryption of the SPL.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>   tools/rkcommon.c | 1 +
>   1 file changed, 1 insertion(+)
>
> diff --git a/tools/rkcommon.c b/tools/rkcommon.c
> index ed9b24137a..6595e02c1c 100644
> --- a/tools/rkcommon.c
> +++ b/tools/rkcommon.c
> @@ -57,6 +57,7 @@ struct spl_info {
>   
>   static struct spl_info spl_infos[] = {
>   	{ "rk3036", "RK30", 0x1000, false },
> +	{ "rk3188", "RK31", 0x8000 - 0x800, true },
>   	{ "rk3288", "RK32", 0x8000, false },
>   	{ "rk3399", "RK33", 0x20000, false },
>   };

Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 00/16] rk3188 uboot support
  2017-02-17  0:41   ` Heiko Stübner
@ 2017-02-17 20:11     ` Heiko Stuebner
  0 siblings, 0 replies; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-17 20:11 UTC (permalink / raw)
  To: u-boot

Am Freitag, 17. Februar 2017, 01:41:27 CET schrieb Heiko St?bner:
> Hi Simon,
> 
> Am Donnerstag, 16. Februar 2017, 13:43:45 CET schrieb Simon Glass:
> > On 3 February 2017 at 09:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > > this is meant as a status update and possible discussion for
> > > the core parts if needed.
> > > 
> > > After talking with Simon and Tom the order is now also correct
> > > with tpl -> spl -> uboot.
> > > 
> > > 
> > > Status right now is:
> > > - the full uboot still works
> > > - the tpl/spl does start and is able to configure the ddr
> > > 
> > >   into a working state
> > > 
> > > - The jump spl -> bootrom -> uboot doesn't work though
> > > 
> > > On the other hand, Kever was able to make this work, booting
> > > from nand when building the image with a very ancient tool.
> > > 
> > > All newer tools (including boot_merger.c from Rockchip's uboot)
> > > do not produce working images. But it is possible to produce
> > > a working sd-boot image using the proprietary 1st-stage loader.
> > > 
> > > See the temporary mkuboot script in the last patch, which can
> > > create both types of images now (especially wrt. the needed
> > > rc4 encryption of everything).
> > > 
> > > Combining this (it does work using some special tool), it looks
> > > like there is still some minor glitch in the way we build the
> > > spl image somewhere.
> > 
> > What should we do with this series? There are a few minor things to
> > resolve but other than that, do you think it is ready to apply?
> 
> It's somehow always on the backburner, but I already started fixing the
> things you pointed out. Though I'll be in Portland, Mountain View and San
> Francisco for the next two weeks, so will only be able to resend the fixes
> after that.
> > The above problem could perhaps be resolved later if there is a
> > suitable README describing it?
> 
> Kever  already found out, that the sd read the bootrom does fails when
> trying to load the uboot from the spl. I'm still trying to investigate this
> [same Portland remark applies], but if you're ok with stuff going in in
> this state, that is definitly fine by me, as it spares me from sending the
> full series all the time ;-)

schedule update :-)

Kever is the hero of the day, as he found out what was causing the load 
failure (reset in sdram driver did actually reset the sdmmc controller). So 
now the real uboot does load finally from spl.

So with the technical issues solved, I'm hoping to just get the review commens 
finalized tomorrow on my flight over the atlantic and plane-wifi permitting may 
even resend from there ;-) .


Heiko

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver
  2017-02-06 15:35   ` Simon Glass
@ 2017-02-17 20:39     ` Heiko Stuebner
  2017-02-17 20:44       ` Simon Glass
  0 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-17 20:39 UTC (permalink / raw)
  To: u-boot

Hi Simon,

Am Montag, 6. Februar 2017, 07:35:23 CET schrieb Simon Glass:
> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > The sdram controller blocks are very similar to the rk3288 in utilizing
> > memory scheduler, Designware uPCTL and Designware PUBL blocks, only
> > limited to one bank instead of two.
> > 
> > There are some minimal differences when setting up the ram, so it gets
> > a separate driver for the rk3188 but reuses the driver structs, as there
> > is no need to define the same again.
> > 
> > More optimization can happen when the modelling of the controller parts
> > in the dts actually follow the hardware layout hopefully at some point
> > in the future.
> > 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> > 
> >  arch/arm/include/asm/arch-rockchip/ddr_rk3188.h |  22 +
> >  arch/arm/mach-rockchip/rk3188/Makefile          |   1 +
> >  arch/arm/mach-rockchip/rk3188/sdram_rk3188.c    | 985
> >  ++++++++++++++++++++++++ 3 files changed, 1008 insertions(+)
> >  create mode 100644 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> >  create mode 100644 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> Nits below.
> 
> > diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> > b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h new file mode 100644
> > index 0000000000..993c58d1a8
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * (C) Copyright 2015 Google, Inc
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0
> > + */
> > +
> > +#ifndef _ASM_ARCH_DDR_RK3188_H
> > +#define _ASM_ARCH_DDR_RK3188_H
> > +
> > +#include <asm/arch/ddr_rk3288.h>
> > +
> > +struct rk3188_msch {
> > +       u32 coreid;
> > +       u32 revisionid;
> > +       u32 ddrconf;
> > +       u32 ddrtiming;
> > +       u32 ddrmode;
> > +       u32 readlatency;
> 
> Can you comment this struct? What is it for?

Added a comment that this the memory scheduler register map, but that is all I 
can say for it, as it is sparsely documented in the chip manuals.


> > +#ifdef CONFIG_SPL_BUILD
> > +static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
> 
> Seems like this should go in a common file as there are several users
> - rk_copy_to_reg() ?

Right now we don't have a common file with shared code and as that function is 
specific to the SPL build I'm not sure if it wouldn't cause issues if we have a 
big bunch of common code that gets included in all SPLs.

Looking at my compilation result, it looks like the compiler inlined the 
function anyway, so maybe just define it as inline in the hardware.h ?


> 
> > +{
> > +       int i;
> > +
> > +       for (i = 0; i < n / sizeof(u32); i++) {
> > +               writel(*src, dest);
> > +               src++;
> > +               dest++;
> > +       }
> > +}

[...]

> > +static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ,
> > +       u32 freq)
> > +{
> > +       int i;
> 
> blank line here
> 
> Do you have a comment for this logic, and why it is how it is?

Not really ... the memory controllers of the rk3066,rk3188 are very much 
similar to the rk3288, so this simply mirrors your own sdram code from rk3288 
;-) .

Speaking of duplicate code, you might already realize that this sdram driver 
is very much similar to the rk3288.
My current plan is to submit the rk3188 separately at first and after 
everything lands try to make the common code shared.

rk3066, rk3188 and rk3288 all use a dw-upctl + dw-publ + phy, with some 
minimal differences, while the rk3036 uses a dw-upctl with a different phy 
block, so it might get a bit tricky on where to share and how to name stuff.

Also another developer seems to be working on rk3066 uboot support already, so 
it might be interesting to see if this will also require additional 
adaptations.


> > +       if (freq <= 250000000) {
> > +               if (freq <= 150000000)
> > +                       clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> > +               else
> > +                       setbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> > +               setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
> > +               for (i = 0; i < 4; i++)
> > +                       setbits_le32(&publ->datx8[i].dxdllcr,
> > +                                    DXDLLCR_DLLDIS);
> > +
> > +               setbits_le32(&publ->pir, PIR_DLLBYP);
> > +       } else {
> > +               clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> > +               clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
> > +               for (i = 0; i < 4; i++) {
> > +                       clrbits_le32(&publ->datx8[i].dxdllcr,
> > +                                    DXDLLCR_DLLDIS);
> > +               }
> > +
> > +               clrbits_le32(&publ->pir, PIR_DLLBYP);
> > +       }
> > +}

[...]

> > +static void ddr_set_ddr3_mode(struct rk3188_grf *grf, uint channel,
> > +                             bool ddr3_mode)
> > +{
> > +       uint mask, val;
> > +
> > +       mask = 1 << MSCH4_MAINDDR3_SHIFT;
> > +       val = ddr3_mode << MSCH4_MAINDDR3_SHIFT;
> > +       rk_clrsetreg(&grf->soc_con2, mask, val);
> > +}
> > +
> > +#define RANK_2_ROW15_EN 1
> 
> Can this go at the top of the file?

actually already contained in the grf header, so can be simply used from there


> > +static void ddr_rank_2_row15en(struct rk3188_grf *grf, bool enable)
> > +{
> > +       uint mask, val;
> > +
> > +       mask = 1 << RANK_2_ROW15_EN;
> > +       val = enable << RANK_2_ROW15_EN;
> > +       rk_clrsetreg(&grf->soc_con2, mask, val);
> > +}




> > +static int data_training(const struct chan_info *chan, u32 channel,
> > +                        struct rk3188_sdram_params *sdram_params)
> 
> Function comment? What does it return? channel could just be int, right?

I'm not particular insighted on what this code actually does, except what the 
function name implies ;-) ... but I did swap the channel to int.


> 
> > +{
> > +       unsigned int j;
> > +       int ret = 0;
> > +       u32 rank;
> > +       int i;
> > +       u32 step[2] = { PIR_QSTRN, PIR_RVTRN };
> > +       struct rk3288_ddr_publ *publ = chan->publ;
> > +       struct rk3288_ddr_pctl *pctl = chan->pctl;
> > +
> > +       /* disable auto refresh */
> > +       writel(0, &pctl->trefi);
> > +
> > +       if (sdram_params->base.dramtype != LPDDR3)
> > +               setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
> > +       rank = sdram_params->ch[channel].rank | 1;
> > +       for (j = 0; j < ARRAY_SIZE(step); j++) {
> > +               /*
> > +                * trigger QSTRN and RVTRN
> > +                * clear DTDONE status
> > +                */
> > +               setbits_le32(&publ->pir, PIR_CLRSR);
> > +
> > +               /* trigger DTT */
> > +               setbits_le32(&publ->pir,
> > +                            PIR_INIT | step[j] | PIR_LOCKBYP |
> > PIR_ZCALBYP | +                            PIR_CLRSR);
> > +               udelay(1);
> > +               /* wait echo byte DTDONE */
> > +               while ((readl(&publ->datx8[0].dxgsr[0]) & rank)
> > +                       != rank)
> > +                       ;
> > +               while ((readl(&publ->datx8[1].dxgsr[0]) & rank)
> > +                       != rank)
> > +                       ;
> > +               if (!(readl(&pctl->ppcfg) & 1)) {
> > +                       while ((readl(&publ->datx8[2].dxgsr[0])
> > +                               & rank) != rank)
> > +                               ;
> > +                       while ((readl(&publ->datx8[3].dxgsr[0])
> > +                               & rank) != rank)
> > +                               ;
> > +               }
> > +               if (readl(&publ->pgsr) &
> > +                   (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) {
> > +                       ret = -1;
> > +                       break;
> > +               }
> > +       }
> > +       /* send some auto refresh to complement the lost while DTT */
> > +       for (i = 0; i < (rank > 1 ? 8 : 4); i++)
> > +               send_command(pctl, rank, REF_CMD, 0);
> > +
> > +       if (sdram_params->base.dramtype != LPDDR3)
> > +               clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
> > +
> > +       /* resume auto refresh */
> > +       writel(sdram_params->pctl_timing.trefi, &pctl->trefi);
> > +
> > +       return ret;
> > +}
> > +



> > +const int ddrconf_table[] = {
> > +       /*
> > +        * [5:4] row(13+n)
> > +        * [1:0] col(9+n), assume bw=2
> > +        * row      col,bw */
> > +       0,
> > +       ((2 << 4) | 1),
> > +       ((1 << 4) | 1),
> > +       ((0 << 4) | 1),
> > +       ((2 << 4) | 2),
> > +       ((1 << 4) | 2),
> > +       ((0 << 4) | 2),
> > +       ((1 << 4) | 0),
> > +       ((0 << 4) | 0),
> > +       0,
> > +       0,
> > +       0,
> > +       0,
> > +       0,
> > +       0,
> > +       0,
> > +};
> 
> Can this go at the top of the file? What are the <<4 for ? Can we have
> a #define?

Having that shift as define might get difficult. As you can see this is the value 
that gets written into the ddrconf register of the memory scheduler and the 
contents of this registers aren't documented in any TRM (rk3288, rk3188, 
rk3066).

So I'd like to refrain from introducting possible wrong defines right now :-) .


Heiko

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver
  2017-02-17 20:39     ` Heiko Stuebner
@ 2017-02-17 20:44       ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-17 20:44 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 17 February 2017 at 13:39, Heiko Stuebner <heiko@sntech.de> wrote:
> Hi Simon,
>
> Am Montag, 6. Februar 2017, 07:35:23 CET schrieb Simon Glass:
>> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
>> > The sdram controller blocks are very similar to the rk3288 in utilizing
>> > memory scheduler, Designware uPCTL and Designware PUBL blocks, only
>> > limited to one bank instead of two.
>> >
>> > There are some minimal differences when setting up the ram, so it gets
>> > a separate driver for the rk3188 but reuses the driver structs, as there
>> > is no need to define the same again.
>> >
>> > More optimization can happen when the modelling of the controller parts
>> > in the dts actually follow the hardware layout hopefully at some point
>> > in the future.
>> >
>> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> > ---
>> >
>> >  arch/arm/include/asm/arch-rockchip/ddr_rk3188.h |  22 +
>> >  arch/arm/mach-rockchip/rk3188/Makefile          |   1 +
>> >  arch/arm/mach-rockchip/rk3188/sdram_rk3188.c    | 985
>> >  ++++++++++++++++++++++++ 3 files changed, 1008 insertions(+)
>> >  create mode 100644 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
>> >  create mode 100644 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> Nits below.
>>
>> > diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
>> > b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h new file mode 100644
>> > index 0000000000..993c58d1a8
>> > --- /dev/null
>> > +++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
>> > @@ -0,0 +1,22 @@
>> > +/*
>> > + * (C) Copyright 2015 Google, Inc
>> > + *
>> > + * SPDX-License-Identifier:    GPL-2.0
>> > + */
>> > +
>> > +#ifndef _ASM_ARCH_DDR_RK3188_H
>> > +#define _ASM_ARCH_DDR_RK3188_H
>> > +
>> > +#include <asm/arch/ddr_rk3288.h>
>> > +
>> > +struct rk3188_msch {
>> > +       u32 coreid;
>> > +       u32 revisionid;
>> > +       u32 ddrconf;
>> > +       u32 ddrtiming;
>> > +       u32 ddrmode;
>> > +       u32 readlatency;
>>
>> Can you comment this struct? What is it for?
>
> Added a comment that this the memory scheduler register map, but that is all I
> can say for it, as it is sparsely documented in the chip manuals.
>
>
>> > +#ifdef CONFIG_SPL_BUILD
>> > +static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
>>
>> Seems like this should go in a common file as there are several users
>> - rk_copy_to_reg() ?
>
> Right now we don't have a common file with shared code and as that function is
> specific to the SPL build I'm not sure if it wouldn't cause issues if we have a
> big bunch of common code that gets included in all SPLs.
>
> Looking at my compilation result, it looks like the compiler inlined the
> function anyway, so maybe just define it as inline in the hardware.h ?

I'd rather not do that - how about cleaning it up in a separate patch later.

>
>
>>
>> > +{
>> > +       int i;
>> > +
>> > +       for (i = 0; i < n / sizeof(u32); i++) {
>> > +               writel(*src, dest);
>> > +               src++;
>> > +               dest++;
>> > +       }
>> > +}
>
> [...]
>
>> > +static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ,
>> > +       u32 freq)
>> > +{
>> > +       int i;
>>
>> blank line here
>>
>> Do you have a comment for this logic, and why it is how it is?
>
> Not really ... the memory controllers of the rk3066,rk3188 are very much
> similar to the rk3288, so this simply mirrors your own sdram code from rk3288
> ;-) .
>
> Speaking of duplicate code, you might already realize that this sdram driver
> is very much similar to the rk3288.
> My current plan is to submit the rk3188 separately at first and after
> everything lands try to make the common code shared.
>
> rk3066, rk3188 and rk3288 all use a dw-upctl + dw-publ + phy, with some
> minimal differences, while the rk3036 uses a dw-upctl with a different phy
> block, so it might get a bit tricky on where to share and how to name stuff.
>
> Also another developer seems to be working on rk3066 uboot support already, so
> it might be interesting to see if this will also require additional
> adaptations.

OK

>
>
>> > +       if (freq <= 250000000) {
>> > +               if (freq <= 150000000)
>> > +                       clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
>> > +               else
>> > +                       setbits_le32(&publ->dllgcr, SBIAS_BYPASS);
>> > +               setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
>> > +               for (i = 0; i < 4; i++)
>> > +                       setbits_le32(&publ->datx8[i].dxdllcr,
>> > +                                    DXDLLCR_DLLDIS);
>> > +
>> > +               setbits_le32(&publ->pir, PIR_DLLBYP);
>> > +       } else {
>> > +               clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
>> > +               clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
>> > +               for (i = 0; i < 4; i++) {
>> > +                       clrbits_le32(&publ->datx8[i].dxdllcr,
>> > +                                    DXDLLCR_DLLDIS);
>> > +               }
>> > +
>> > +               clrbits_le32(&publ->pir, PIR_DLLBYP);
>> > +       }
>> > +}
>
> [...]
>
>> > +static void ddr_set_ddr3_mode(struct rk3188_grf *grf, uint channel,
>> > +                             bool ddr3_mode)
>> > +{
>> > +       uint mask, val;
>> > +
>> > +       mask = 1 << MSCH4_MAINDDR3_SHIFT;
>> > +       val = ddr3_mode << MSCH4_MAINDDR3_SHIFT;
>> > +       rk_clrsetreg(&grf->soc_con2, mask, val);
>> > +}
>> > +
>> > +#define RANK_2_ROW15_EN 1
>>
>> Can this go at the top of the file?
>
> actually already contained in the grf header, so can be simply used from there
>
>
>> > +static void ddr_rank_2_row15en(struct rk3188_grf *grf, bool enable)
>> > +{
>> > +       uint mask, val;
>> > +
>> > +       mask = 1 << RANK_2_ROW15_EN;
>> > +       val = enable << RANK_2_ROW15_EN;
>> > +       rk_clrsetreg(&grf->soc_con2, mask, val);
>> > +}
>
>
>
>
>> > +static int data_training(const struct chan_info *chan, u32 channel,
>> > +                        struct rk3188_sdram_params *sdram_params)
>>
>> Function comment? What does it return? channel could just be int, right?
>
> I'm not particular insighted on what this code actually does, except what the
> function name implies ;-) ... but I did swap the channel to int.
>
>
>>
>> > +{
>> > +       unsigned int j;
>> > +       int ret = 0;
>> > +       u32 rank;
>> > +       int i;
>> > +       u32 step[2] = { PIR_QSTRN, PIR_RVTRN };
>> > +       struct rk3288_ddr_publ *publ = chan->publ;
>> > +       struct rk3288_ddr_pctl *pctl = chan->pctl;
>> > +
>> > +       /* disable auto refresh */
>> > +       writel(0, &pctl->trefi);
>> > +
>> > +       if (sdram_params->base.dramtype != LPDDR3)
>> > +               setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
>> > +       rank = sdram_params->ch[channel].rank | 1;
>> > +       for (j = 0; j < ARRAY_SIZE(step); j++) {
>> > +               /*
>> > +                * trigger QSTRN and RVTRN
>> > +                * clear DTDONE status
>> > +                */
>> > +               setbits_le32(&publ->pir, PIR_CLRSR);
>> > +
>> > +               /* trigger DTT */
>> > +               setbits_le32(&publ->pir,
>> > +                            PIR_INIT | step[j] | PIR_LOCKBYP |
>> > PIR_ZCALBYP | +                            PIR_CLRSR);
>> > +               udelay(1);
>> > +               /* wait echo byte DTDONE */
>> > +               while ((readl(&publ->datx8[0].dxgsr[0]) & rank)
>> > +                       != rank)
>> > +                       ;
>> > +               while ((readl(&publ->datx8[1].dxgsr[0]) & rank)
>> > +                       != rank)
>> > +                       ;
>> > +               if (!(readl(&pctl->ppcfg) & 1)) {
>> > +                       while ((readl(&publ->datx8[2].dxgsr[0])
>> > +                               & rank) != rank)
>> > +                               ;
>> > +                       while ((readl(&publ->datx8[3].dxgsr[0])
>> > +                               & rank) != rank)
>> > +                               ;
>> > +               }
>> > +               if (readl(&publ->pgsr) &
>> > +                   (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) {
>> > +                       ret = -1;
>> > +                       break;
>> > +               }
>> > +       }
>> > +       /* send some auto refresh to complement the lost while DTT */
>> > +       for (i = 0; i < (rank > 1 ? 8 : 4); i++)
>> > +               send_command(pctl, rank, REF_CMD, 0);
>> > +
>> > +       if (sdram_params->base.dramtype != LPDDR3)
>> > +               clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
>> > +
>> > +       /* resume auto refresh */
>> > +       writel(sdram_params->pctl_timing.trefi, &pctl->trefi);
>> > +
>> > +       return ret;
>> > +}
>> > +
>
>
>
>> > +const int ddrconf_table[] = {
>> > +       /*
>> > +        * [5:4] row(13+n)
>> > +        * [1:0] col(9+n), assume bw=2
>> > +        * row      col,bw */
>> > +       0,
>> > +       ((2 << 4) | 1),
>> > +       ((1 << 4) | 1),
>> > +       ((0 << 4) | 1),
>> > +       ((2 << 4) | 2),
>> > +       ((1 << 4) | 2),
>> > +       ((0 << 4) | 2),
>> > +       ((1 << 4) | 0),
>> > +       ((0 << 4) | 0),
>> > +       0,
>> > +       0,
>> > +       0,
>> > +       0,
>> > +       0,
>> > +       0,
>> > +       0,
>> > +};
>>
>> Can this go at the top of the file? What are the <<4 for ? Can we have
>> a #define?
>
> Having that shift as define might get difficult. As you can see this is the value
> that gets written into the ddrconf register of the memory scheduler and the
> contents of this registers aren't documented in any TRM (rk3288, rk3188,
> rk3066).
>
> So I'd like to refrain from introducting possible wrong defines right now :-) .

OK. The memory init code is a pain point for many SoCs, let's just do
our best and hopefully docs and meaning can improve with time.

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver
  2017-02-06 15:35   ` Simon Glass
@ 2017-02-18 14:19     ` Heiko Stuebner
  2017-02-21 18:07       ` Simon Glass
  0 siblings, 1 reply; 45+ messages in thread
From: Heiko Stuebner @ 2017-02-18 14:19 UTC (permalink / raw)
  To: u-boot

Hi Simon,

Am Montag, 6. Februar 2017, 07:35:12 CET schrieb Simon Glass:
> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > Add a driver for setting up and modifying the various PLLs and peripheral
> > clocks on the RK3188.
> > 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> > 
> >  arch/arm/include/asm/arch-rockchip/cru_rk3188.h | 191 +++++++++
> >  drivers/clk/rockchip/Makefile                   |   1 +
> >  drivers/clk/rockchip/clk_rk3188.c               | 523
> >  ++++++++++++++++++++++++ 3 files changed, 715 insertions(+)
> >  create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3188.h
> >  create mode 100644 drivers/clk/rockchip/clk_rk3188.c
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> With one comment below.
> 
> > diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
> > b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h new file mode 100644
> > index 0000000000..74f0fedcc6
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
> > @@ -0,0 +1,191 @@
> > +/*
> > + * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
> > + *
> > + * SPDX-License-Identifier:     GPL-2.0+
> > + */
> > +#ifndef _ASM_ARCH_CRU_RK3188_H
> > +#define _ASM_ARCH_CRU_RK3188_H
> > +
> > +#define OSC_HZ         (24 * 1000 * 1000)
> > +
> > +#define APLL_HZ                (1608 * 1000000)
> > +#define GPLL_HZ                (594 * 1000000)
> > +#define CPLL_HZ                (384 * 1000000)
> > +
> > +/* The SRAM is clocked off aclk_cpu, so we want to max it out for boot
> > speed */ +#define CPU_ACLK_HZ    297000000
> > +#define CPU_HCLK_HZ    148500000
> > +#define CPU_PCLK_HZ    74250000
> > +#define CPU_H2P_HZ     74250000
> > +
> > +#define PERI_ACLK_HZ   148500000
> > +#define PERI_HCLK_HZ   148500000
> > +#define PERI_PCLK_HZ   74250000
> > +
> > +/* Private data for the clock driver - used by rockchip_get_cru() */
> > +struct rk3188_clk_priv {
> > +       struct rk3188_grf *grf;
> > +       struct rk3188_cru *cru;
> > +       ulong rate;
> > +       bool has_bwadj;
> > +};
> > +
> > +struct rk3188_cru {
> > +       struct rk3188_pll {
> > +               u32 con0;
> > +               u32 con1;
> > +               u32 con2;
> > +               u32 con3;
> > +       } pll[4];
> > +       u32 cru_mode_con;
> > +       u32 cru_clksel_con[35];
> > +       u32 cru_clkgate_con[10];
> > +       u32 reserved1[2];
> > +       u32 cru_glb_srst_fst_value;
> > +       u32 cru_glb_srst_snd_value;
> > +       u32 reserved2[2];
> > +       u32 cru_softrst_con[9];
> > +       u32 cru_misc_con;
> > +       u32 reserved3[2];
> > +       u32 cru_glb_cnt_th;
> > +};
> > +check_member(rk3188_cru, cru_glb_cnt_th, 0x0140);
> > +
> > +/* CRU_CLKSEL0_CON */
> > +enum {
> > +       /* a9_core_div: core = core_src / (a9_core_div + 1) */
> > +       A9_CORE_DIV_SHIFT       = 9,
> > +       A9_CORE_DIV_MASK        = 0x1f,
> 
> Can you define
> 
> A9_CORE_DIV_MASK = 0x1f << A9_CORE_DIV_SHIFT
> 
> and similarly for other masks. I got this wrong with rk3288, and I
> think shifting the mask makes the code easier in places.

I'd disagree here. We're using this scheme everywhere on Rockchip platforms.
For example please look at all the pinmux defines
	GPIO3C1_SHIFT		= 2,
	GPIO3C1_MASK		= 3,
	GPIO3C1_GPIO		= 0,
	GPIO3C1_SDMMC1_DATA0,
	GPIO3C1_RMII_TXD1,
	GPIO3C1_RESERVED,

and numerous other places and I'd think mixing paradigms in one soc and 
between all Rockchip socs would be somewhat unwise.

Heiko

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver
  2017-02-18 14:19     ` Heiko Stuebner
@ 2017-02-21 18:07       ` Simon Glass
  2017-02-21 20:35         ` Simon Glass
  0 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2017-02-21 18:07 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 18 February 2017 at 07:19, Heiko Stuebner <heiko@sntech.de> wrote:
> Hi Simon,
>
> Am Montag, 6. Februar 2017, 07:35:12 CET schrieb Simon Glass:
>> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
>> > Add a driver for setting up and modifying the various PLLs and peripheral
>> > clocks on the RK3188.
>> >
>> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>> > ---
>> >
>> >  arch/arm/include/asm/arch-rockchip/cru_rk3188.h | 191 +++++++++
>> >  drivers/clk/rockchip/Makefile                   |   1 +
>> >  drivers/clk/rockchip/clk_rk3188.c               | 523
>> >  ++++++++++++++++++++++++ 3 files changed, 715 insertions(+)
>> >  create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>> >  create mode 100644 drivers/clk/rockchip/clk_rk3188.c
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> With one comment below.
>>
>> > diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>> > b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h new file mode 100644
>> > index 0000000000..74f0fedcc6
>> > --- /dev/null
>> > +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>> > @@ -0,0 +1,191 @@
>> > +/*
>> > + * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
>> > + *
>> > + * SPDX-License-Identifier:     GPL-2.0+
>> > + */
>> > +#ifndef _ASM_ARCH_CRU_RK3188_H
>> > +#define _ASM_ARCH_CRU_RK3188_H
>> > +
>> > +#define OSC_HZ         (24 * 1000 * 1000)
>> > +
>> > +#define APLL_HZ                (1608 * 1000000)
>> > +#define GPLL_HZ                (594 * 1000000)
>> > +#define CPLL_HZ                (384 * 1000000)
>> > +
>> > +/* The SRAM is clocked off aclk_cpu, so we want to max it out for boot
>> > speed */ +#define CPU_ACLK_HZ    297000000
>> > +#define CPU_HCLK_HZ    148500000
>> > +#define CPU_PCLK_HZ    74250000
>> > +#define CPU_H2P_HZ     74250000
>> > +
>> > +#define PERI_ACLK_HZ   148500000
>> > +#define PERI_HCLK_HZ   148500000
>> > +#define PERI_PCLK_HZ   74250000
>> > +
>> > +/* Private data for the clock driver - used by rockchip_get_cru() */
>> > +struct rk3188_clk_priv {
>> > +       struct rk3188_grf *grf;
>> > +       struct rk3188_cru *cru;
>> > +       ulong rate;
>> > +       bool has_bwadj;
>> > +};
>> > +
>> > +struct rk3188_cru {
>> > +       struct rk3188_pll {
>> > +               u32 con0;
>> > +               u32 con1;
>> > +               u32 con2;
>> > +               u32 con3;
>> > +       } pll[4];
>> > +       u32 cru_mode_con;
>> > +       u32 cru_clksel_con[35];
>> > +       u32 cru_clkgate_con[10];
>> > +       u32 reserved1[2];
>> > +       u32 cru_glb_srst_fst_value;
>> > +       u32 cru_glb_srst_snd_value;
>> > +       u32 reserved2[2];
>> > +       u32 cru_softrst_con[9];
>> > +       u32 cru_misc_con;
>> > +       u32 reserved3[2];
>> > +       u32 cru_glb_cnt_th;
>> > +};
>> > +check_member(rk3188_cru, cru_glb_cnt_th, 0x0140);
>> > +
>> > +/* CRU_CLKSEL0_CON */
>> > +enum {
>> > +       /* a9_core_div: core = core_src / (a9_core_div + 1) */
>> > +       A9_CORE_DIV_SHIFT       = 9,
>> > +       A9_CORE_DIV_MASK        = 0x1f,
>>
>> Can you define
>>
>> A9_CORE_DIV_MASK = 0x1f << A9_CORE_DIV_SHIFT
>>
>> and similarly for other masks. I got this wrong with rk3288, and I
>> think shifting the mask makes the code easier in places.
>
> I'd disagree here. We're using this scheme everywhere on Rockchip platforms.
> For example please look at all the pinmux defines
>         GPIO3C1_SHIFT           = 2,
>         GPIO3C1_MASK            = 3,
>         GPIO3C1_GPIO            = 0,
>         GPIO3C1_SDMMC1_DATA0,
>         GPIO3C1_RMII_TXD1,
>         GPIO3C1_RESERVED,
>
> and numerous other places and I'd think mixing paradigms in one soc and
> between all Rockchip socs would be somewhat unwise.

The new ones are going to use this approach and I will get around to
converting them at some point. I do think I did it wrong in the first
place.

Anyway let's not hold this up for this as we have the same issue with rk3399.

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver
  2017-02-21 18:07       ` Simon Glass
@ 2017-02-21 20:35         ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-21 20:35 UTC (permalink / raw)
  To: u-boot

On 21 February 2017 at 11:07, Simon Glass <sjg@chromium.org> wrote:
> Hi Heiko,
>
> On 18 February 2017 at 07:19, Heiko Stuebner <heiko@sntech.de> wrote:
>> Hi Simon,
>>
>> Am Montag, 6. Februar 2017, 07:35:12 CET schrieb Simon Glass:
>>> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
>>> > Add a driver for setting up and modifying the various PLLs and peripheral
>>> > clocks on the RK3188.
>>> >
>>> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>>> > ---
>>> >
>>> >  arch/arm/include/asm/arch-rockchip/cru_rk3188.h | 191 +++++++++
>>> >  drivers/clk/rockchip/Makefile                   |   1 +
>>> >  drivers/clk/rockchip/clk_rk3188.c               | 523
>>> >  ++++++++++++++++++++++++ 3 files changed, 715 insertions(+)
>>> >  create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>>> >  create mode 100644 drivers/clk/rockchip/clk_rk3188.c
>>>
>>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>>
>>> With one comment below.
>>>
>>> > diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>>> > b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h new file mode 100644
>>> > index 0000000000..74f0fedcc6
>>> > --- /dev/null
>>> > +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3188.h
>>> > @@ -0,0 +1,191 @@
>>> > +/*
>>> > + * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
>>> > + *
>>> > + * SPDX-License-Identifier:     GPL-2.0+
>>> > + */
>>> > +#ifndef _ASM_ARCH_CRU_RK3188_H
>>> > +#define _ASM_ARCH_CRU_RK3188_H
>>> > +
>>> > +#define OSC_HZ         (24 * 1000 * 1000)
>>> > +
>>> > +#define APLL_HZ                (1608 * 1000000)
>>> > +#define GPLL_HZ                (594 * 1000000)
>>> > +#define CPLL_HZ                (384 * 1000000)
>>> > +
>>> > +/* The SRAM is clocked off aclk_cpu, so we want to max it out for boot
>>> > speed */ +#define CPU_ACLK_HZ    297000000
>>> > +#define CPU_HCLK_HZ    148500000
>>> > +#define CPU_PCLK_HZ    74250000
>>> > +#define CPU_H2P_HZ     74250000
>>> > +
>>> > +#define PERI_ACLK_HZ   148500000
>>> > +#define PERI_HCLK_HZ   148500000
>>> > +#define PERI_PCLK_HZ   74250000
>>> > +
>>> > +/* Private data for the clock driver - used by rockchip_get_cru() */
>>> > +struct rk3188_clk_priv {
>>> > +       struct rk3188_grf *grf;
>>> > +       struct rk3188_cru *cru;
>>> > +       ulong rate;
>>> > +       bool has_bwadj;
>>> > +};
>>> > +
>>> > +struct rk3188_cru {
>>> > +       struct rk3188_pll {
>>> > +               u32 con0;
>>> > +               u32 con1;
>>> > +               u32 con2;
>>> > +               u32 con3;
>>> > +       } pll[4];
>>> > +       u32 cru_mode_con;
>>> > +       u32 cru_clksel_con[35];
>>> > +       u32 cru_clkgate_con[10];
>>> > +       u32 reserved1[2];
>>> > +       u32 cru_glb_srst_fst_value;
>>> > +       u32 cru_glb_srst_snd_value;
>>> > +       u32 reserved2[2];
>>> > +       u32 cru_softrst_con[9];
>>> > +       u32 cru_misc_con;
>>> > +       u32 reserved3[2];
>>> > +       u32 cru_glb_cnt_th;
>>> > +};
>>> > +check_member(rk3188_cru, cru_glb_cnt_th, 0x0140);
>>> > +
>>> > +/* CRU_CLKSEL0_CON */
>>> > +enum {
>>> > +       /* a9_core_div: core = core_src / (a9_core_div + 1) */
>>> > +       A9_CORE_DIV_SHIFT       = 9,
>>> > +       A9_CORE_DIV_MASK        = 0x1f,
>>>
>>> Can you define
>>>
>>> A9_CORE_DIV_MASK = 0x1f << A9_CORE_DIV_SHIFT
>>>
>>> and similarly for other masks. I got this wrong with rk3288, and I
>>> think shifting the mask makes the code easier in places.
>>
>> I'd disagree here. We're using this scheme everywhere on Rockchip platforms.
>> For example please look at all the pinmux defines
>>         GPIO3C1_SHIFT           = 2,
>>         GPIO3C1_MASK            = 3,
>>         GPIO3C1_GPIO            = 0,
>>         GPIO3C1_SDMMC1_DATA0,
>>         GPIO3C1_RMII_TXD1,
>>         GPIO3C1_RESERVED,
>>
>> and numerous other places and I'd think mixing paradigms in one soc and
>> between all Rockchip socs would be somewhat unwise.
>
> The new ones are going to use this approach and I will get around to
> converting them at some point. I do think I did it wrong in the first
> place.
>
> Anyway let's not hold this up for this as we have the same issue with rk3399.
>
> Regards,
> Simon

Applied to u-boot-rockchip, thanks!

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl
  2017-02-17  0:36     ` Heiko Stübner
@ 2017-02-22  3:59       ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2017-02-22  3:59 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 16 February 2017 at 17:36, Heiko St?bner <heiko@sntech.de> wrote:
>
> Hi Simon,
>
> Am Montag, 6. Februar 2017, 07:34:54 CET schrieb Simon Glass:
> > On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > > Right now the u-boot,dm-pre-reloc flag will make each marked node
> > > always appear in both spl and tpl. But systems needing an additional
> > > tpl might have special constraints for each, like the spl needing to
> > > be very tiny.
> > >
> > > So introduce two additional flags to mark nodes for only spl or tpl
> > > environments and introduce a function dm_fdt_pre_reloc to automate
> > > the necessary checks in code instances checking for pre-relocation
> > > flags.
> > >
> > > The behaviour of the original flag stays untouched and still marks
> > > a node for both spl and tpl.
> > >
> > > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > > ---
> > >
> > >  doc/driver-model/README.txt      |  4 ++++
> > >  drivers/clk/at91/pmc.c           |  3 ++-
> > >  drivers/core/root.c              |  2 +-
> > >  drivers/core/util.c              | 29 +++++++++++++++++++++++++++++
> > >  drivers/pinctrl/pinctrl-uclass.c |  3 ++-
> > >  include/dm/util.h                |  2 ++
> > >  scripts/Makefile.spl             |  7 ++++++-
> > >  tools/dtoc/dtoc.py               |  2 ++
> > >  8 files changed, 48 insertions(+), 4 deletions(-)
> >
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> >
> > s/u-boot/U-Boot
> >
> > Please add a comment for dm_fdt_pre_reloc() in the header file.
> >
> > Two things to consider:
> >
> > - Should we drop the use of u-boot,dm-pre-reloc in Makefile.spl, and
> > convert all users to your version? This would mean having both
> > u-boot,dm-pre-reloc and u-boot,dm-spl in some cases, I suspect.
>         ^^ u-boot,dm-spl and u-boot,dm-tpl I guess
>
> Dropping u-boot,dm-pre-reloc is for you to decide, as you wrote the original
> implementation ;-) . It will save one fdt-query but might need several
> iterations as I guess new boards will add new ones after we remove the old
> ones.

Let's do it. It is more efficient and I don't expect it to cause many
problems if we get it in at the start of the merge window.

>
> > - Can you use #ifdef in SPL/TPL to reduce code size fractionally in
> > dm_fdt_pre_reloc()?
>
> Do you mean moving the
> +       dm_spl = fdt_getprop(blob, offset, "u-boot,dm-spl", NULL);
> +       dm_tpl = fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL);
>
> into the existing #ifdef CONFIG_TPL_BUILD / SPL_BUILD blocks or something
> else?

Well I don't think it matters, but the idea is that there would then
be no point in checking u-boot,dm-tpl except when CONFIG_TPL_BUILD is
defined.

Regards,
Simon

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2017-02-22  3:59 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl Heiko Stuebner
2017-02-06 15:34   ` Simon Glass
2017-02-17  0:36     ` Heiko Stübner
2017-02-22  3:59       ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 02/16] rockchip: move bootrom helper compilation to a hidden option Heiko Stuebner
2017-02-06 15:34   ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-17  3:23   ` Kever Yang
2017-02-03 16:09 ` [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-17  3:29   ` Kever Yang
2017-02-03 16:09 ` [U-Boot] [PATCH v3 05/16] rockchip: serial: Adapt rockchip of-platdata driver for rk3188 Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 06/16] rockchip: rk3188: Add header files for PMU and GRF Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 07/16] rockchip: rk3188: Add pinctrl driver Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 08/16] rockchip: rk3188: Add sysreset driver Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 09/16] rockchip: rk3188: Add rk3066/rk3188 clock bindings Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-18 14:19     ` Heiko Stuebner
2017-02-21 18:07       ` Simon Glass
2017-02-21 20:35         ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-10 23:17     ` Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 12/16] rockchip: rk3188: Add core support Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-17 20:39     ` Heiko Stuebner
2017-02-17 20:44       ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-11  0:47     ` Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 15/16] rockchip: rk3188: Add Radxa Rock board Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [TEST-ONLY 16/16] Add a temporary script that can create a bootimage for rk3188 Heiko Stuebner
2017-02-06 15:35   ` Simon Glass
2017-02-16 20:43 ` [U-Boot] [PATCH v3 00/16] rk3188 uboot support Simon Glass
2017-02-17  0:41   ` Heiko Stübner
2017-02-17 20:11     ` Heiko Stuebner
2017-02-17  3:21 ` Kever Yang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.