All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v4 00/19] add support for rk3066 platform.
@ 2017-08-17 13:11 =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-17 13:11 ` [U-Boot] [PATCH v4 01/19] rockchip: rk3066: add grf header file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (19 more replies)
  0 siblings, 20 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:11 UTC (permalink / raw)
  To: u-boot

This patch serie adds support for Rockchip RK3066 processor.

Paweł Jarosz (19):
  rockchip: rk3066: add grf header file
  rockchip: rk3066: add rk3066 pinctrl driver
  rockchip: rk3066: add sysreset driver
  rockchip: rk3066: add clock driver for rk3066 soc
  rockchip: rk3066: add rk3066 platform devicetree file
  rockchip: rk3066: add core support
  rockchip: rk3066: add mk808 board files
  rockchip: rk3066: add sdram driver
  mtd: nand: add support for the Sandisk SDTNQGAMA chip
  mtd: nand: add the rockchip nand controller driver
  rockchip: mkimage: add support for rockchip nand boot image
  rockchip: board: rk3066: convert board_usb_init to live tree functions
  ARM: dts: rockchip: prefer u-boot,dm-pre-reloc rather than
    u-boot,dm-spl
  mmc: dw_mmc: support transfer mode autodetection
  mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
  armv7: support rk3066 early back to bootrom in vector.S
  rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers
  dfu: fix spl build
  mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util

 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/rk3066a-mk808.dts                     | 189 +++++
 arch/arm/dts/rk3066a.dtsi                          | 707 +++++++++++++++
 arch/arm/dts/rk3xxx.dtsi                           |   8 +-
 arch/arm/include/asm/arch-rockchip/boot0.h         |  14 +
 arch/arm/include/asm/arch-rockchip/cru_rk3066.h    | 189 +++++
 arch/arm/include/asm/arch-rockchip/grf_rk3066.h    | 621 ++++++++++++++
 arch/arm/include/asm/arch-rockchip/periph.h        |   1 +
 .../include/asm/arch-rockchip/sysreset_common.h    |  20 +
 arch/arm/lib/vectors.S                             |  18 +-
 arch/arm/mach-rockchip/Kconfig                     |  16 +
 arch/arm/mach-rockchip/Makefile                    |   7 +
 arch/arm/mach-rockchip/rk3066-board-spl.c          | 139 +++
 arch/arm/mach-rockchip/rk3066-board-tpl.c          |  90 ++
 arch/arm/mach-rockchip/rk3066-board.c              | 112 +++
 arch/arm/mach-rockchip/rk3066/Kconfig              |  31 +
 arch/arm/mach-rockchip/rk3066/Makefile             |   9 +
 arch/arm/mach-rockchip/rk3066/clk_rk3066.c         |  33 +
 arch/arm/mach-rockchip/rk3066/sdram_rk3066.c       | 943 +++++++++++++++++++++
 arch/arm/mach-rockchip/rk3066/syscon_rk3066.c      |  54 ++
 arch/arm/mach-rockchip/sysreset-common.c           |  39 +
 board/rikomagic/mk808_rk3066/Kconfig               |  15 +
 board/rikomagic/mk808_rk3066/MAINTAINERS           |   6 +
 board/rikomagic/mk808_rk3066/Makefile              |   7 +
 board/rikomagic/mk808_rk3066/mk808_rk3066.c        |  10 +
 common/image.c                                     |   1 +
 configs/mk808_defconfig                            | 115 +++
 drivers/clk/rockchip/Makefile                      |   1 +
 drivers/clk/rockchip/clk_rk3066.c                  | 587 +++++++++++++
 drivers/dfu/dfu_nand.c                             |   5 +-
 drivers/mmc/dw_mmc.c                               |   8 +
 drivers/mmc/rockchip_dw_mmc.c                      |   1 +
 drivers/mtd/nand/Kconfig                           |   6 +
 drivers/mtd/nand/Makefile                          |   4 +
 drivers/mtd/nand/nand_ids.c                        |   3 +
 drivers/mtd/nand/rockchip_nand.c                   | 660 ++++++++++++++
 drivers/pinctrl/Kconfig                            |   9 +
 drivers/pinctrl/rockchip/Makefile                  |   1 +
 drivers/pinctrl/rockchip/pinctrl_rk3066.c          | 340 ++++++++
 drivers/sysreset/Makefile                          |   1 +
 drivers/sysreset/sysreset_rk3066.c                 |  49 ++
 drivers/sysreset/sysreset_rk3188.c                 |  35 +-
 include/configs/mk808_rk3066.h                     |  61 ++
 include/configs/rk3066_common.h                    |  99 +++
 include/dwmmc.h                                    |   4 +
 include/fdtdec.h                                   |   1 +
 include/image.h                                    |   1 +
 lib/fdtdec.c                                       |   1 +
 tools/Makefile                                     |   2 +-
 tools/imagetool.h                                  |   1 +
 tools/mkimage.c                                    |   8 +-
 tools/rkcommon.c                                   |  10 +-
 tools/rkcommon.h                                   |  10 +-
 tools/rknand.c                                     | 156 ++++
 tools/rksd.c                                       |   2 +-
 tools/rkspi.c                                      |   2 +-
 56 files changed, 5415 insertions(+), 48 deletions(-)
 create mode 100644 arch/arm/dts/rk3066a-mk808.dts
 create mode 100644 arch/arm/dts/rk3066a.dtsi
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3066.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rk3066.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/sysreset_common.h
 create mode 100644 arch/arm/mach-rockchip/rk3066-board-spl.c
 create mode 100644 arch/arm/mach-rockchip/rk3066-board-tpl.c
 create mode 100644 arch/arm/mach-rockchip/rk3066-board.c
 create mode 100644 arch/arm/mach-rockchip/rk3066/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rk3066/Makefile
 create mode 100644 arch/arm/mach-rockchip/rk3066/clk_rk3066.c
 create mode 100644 arch/arm/mach-rockchip/rk3066/sdram_rk3066.c
 create mode 100644 arch/arm/mach-rockchip/rk3066/syscon_rk3066.c
 create mode 100644 arch/arm/mach-rockchip/sysreset-common.c
 create mode 100644 board/rikomagic/mk808_rk3066/Kconfig
 create mode 100644 board/rikomagic/mk808_rk3066/MAINTAINERS
 create mode 100644 board/rikomagic/mk808_rk3066/Makefile
 create mode 100644 board/rikomagic/mk808_rk3066/mk808_rk3066.c
 create mode 100644 configs/mk808_defconfig
 create mode 100644 drivers/clk/rockchip/clk_rk3066.c
 create mode 100644 drivers/mtd/nand/rockchip_nand.c
 create mode 100644 drivers/pinctrl/rockchip/pinctrl_rk3066.c
 create mode 100644 drivers/sysreset/sysreset_rk3066.c
 create mode 100644 include/configs/mk808_rk3066.h
 create mode 100644 include/configs/rk3066_common.h
 create mode 100644 tools/rknand.c

-- 
2.7.4

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

* [U-Boot] [PATCH v4 01/19] rockchip: rk3066: add grf header file
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:11 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 02/19] rockchip: rk3066: add rk3066 pinctrl driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:11 UTC (permalink / raw)
  To: u-boot

grf is needed by various drivers for rk3066 soc.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- updated to shifted masks

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/include/asm/arch-rockchip/grf_rk3066.h | 621 ++++++++++++++++++++++++
 1 file changed, 621 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rk3066.h

diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3066.h b/arch/arm/include/asm/arch-rockchip/grf_rk3066.h
new file mode 100644
index 0000000..be40884
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3066.h
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_GRF_RK3066_H
+#define _ASM_ARCH_GRF_RK3066_H
+
+struct rk3066_grf_gpio_lh {
+	u32 l;
+	u32 h;
+};
+
+struct rk3066_grf {
+	struct rk3066_grf_gpio_lh gpio_dir[7];
+	struct rk3066_grf_gpio_lh gpio_do[7];
+	struct rk3066_grf_gpio_lh gpio_en[7];
+
+	u32 gpio0a_iomux;
+	u32 gpio0b_iomux;
+	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 gpio4a_iomux;
+	u32 gpio4b_iomux;
+	u32 gpio4c_iomux;
+	u32 gpio4d_iomux;
+
+	u32 reserved0[5];
+
+	u32 gpio6b_iomux;
+
+	u32 reserved1[2];
+
+	struct rk3066_grf_gpio_lh gpio_pull[7];
+
+	u32 soc_con0;
+	u32 soc_con1;
+	u32 soc_con2;
+
+	u32 soc_status0;
+
+	u32 dmac1_con[3];
+	u32 dmac2_con[4];
+
+	u32 uoc0_con[3];
+	u32 uoc1_con[4];
+	u32 ddrc_con;
+	u32 ddrc_stat;
+
+	u32 reserved2[10];
+
+	u32 os_reg[4];
+};
+check_member(rk3066_grf, os_reg[3], 0x01d4);
+
+/* GRF_GPIO0A_IOMUX */
+enum {
+	GPIO0A6_SHIFT		= 12,
+	GPIO0A6_MASK		= 1 << GPIO0A6_SHIFT,
+	GPIO0A6_GPIO		= 0,
+	GPIO0A6_HOST_DRV_VBUS,
+
+	GPIO0A5_SHIFT		= 10,
+	GPIO0A5_MASK		= 1 << GPIO0A5_SHIFT,
+	GPIO0A5_GPIO		= 0,
+	GPIO0A5_OTG_DRV_VBUS,
+
+	GPIO0A4_SHIFT		= 8,
+	GPIO0A4_MASK		= 1 << GPIO0A4_SHIFT,
+	GPIO0A4_GPIO		= 0,
+	GPIO0A4_PWM1,
+
+	GPIO0A3_SHIFT		= 6,
+	GPIO0A3_MASK		= 1 << GPIO0A3_SHIFT,
+	GPIO0A3_GPIO		= 0,
+	GPIO0A3_PWM0
+};
+
+/* GRF_GPIO0D_IOMUX */
+enum {
+	GPIO0D7_SHIFT		= 14,
+	GPIO0D7_MASK		= 1 << GPIO0D7_SHIFT,
+	GPIO0D7_GPIO		= 0,
+	GPIO0D7_PWM3,
+
+	GPIO0D6_SHIFT		= 12,
+	GPIO0D6_MASK		= 1 << GPIO0D6_SHIFT,
+	GPIO0D6_GPIO		= 0,
+	GPIO0D6_PWM2
+};
+
+/* GRF_GPIO1A_IOMUX */
+enum {
+	GPIO1A7_SHIFT		= 14,
+	GPIO1A7_MASK		= 3 << GPIO1A7_SHIFT,
+	GPIO1A7_GPIO		= 0,
+	GPIO1A7_UART1_RTS_N,
+	GPIO1A7_SPI0_TXD,
+
+	GPIO1A6_SHIFT		= 12,
+	GPIO1A6_MASK		= 3 << GPIO1A6_SHIFT,
+	GPIO1A6_GPIO		= 0,
+	GPIO1A6_UART1_CTS_N,
+	GPIO1A6_SPI0_RXD,
+
+	GPIO1A5_SHIFT		= 10,
+	GPIO1A5_MASK		= 3 << GPIO1A5_SHIFT,
+	GPIO1A5_GPIO		= 0,
+	GPIO1A5_UART1_SOUT,
+	GPIO1A5_SPI0_CLK,
+
+	GPIO1A4_SHIFT		= 8,
+	GPIO1A4_MASK		= 3 << GPIO1A4_SHIFT,
+	GPIO1A4_GPIO		= 0,
+	GPIO1A4_UART1_SIN,
+	GPIO1A4_SPI0_CSN0,
+
+	GPIO1A3_SHIFT		= 6,
+	GPIO1A3_MASK		= 1 << GPIO1A3_SHIFT,
+	GPIO1A3_GPIO		= 0,
+	GPIO1A3_UART0_RTS_N,
+
+	GPIO1A2_SHIFT		= 4,
+	GPIO1A2_MASK		= 1 << GPIO1A2_SHIFT,
+	GPIO1A2_GPIO		= 0,
+	GPIO1A2_UART0_CTS_N,
+
+	GPIO1A1_SHIFT		= 2,
+	GPIO1A1_MASK		= 1 << GPIO1A1_SHIFT,
+	GPIO1A1_GPIO		= 0,
+	GPIO1A1_UART0_SOUT,
+
+	GPIO1A0_SHIFT		= 0,
+	GPIO1A0_MASK		= 1 << GPIO1A0_SHIFT,
+	GPIO1A0_GPIO		= 0,
+	GPIO1A0_UART0_SIN
+};
+
+/* GRF_GPIO1B_IOMUX */
+enum {
+	GPIO1B1_SHIFT		= 2,
+	GPIO1B1_MASK		= 1 << GPIO1B1_SHIFT,
+	GPIO1B1_GPIO		= 0,
+	GPIO1B1_UART2_SOUT,
+
+	GPIO1B0_SHIFT		= 0,
+	GPIO1B0_MASK		= 1 << GPIO1B0_SHIFT,
+	GPIO1B0_GPIO		= 0,
+	GPIO1B0_UART2_SIN
+};
+
+/* GRF_GPIO2C_IOMUX */
+enum {
+	GPIO2C7_SHIFT		= 14,
+	GPIO2C7_MASK		= 3 << GPIO2C7_SHIFT,
+	GPIO2C7_GPIO		= 0,
+	GPIO2C7_LCDC1_DATA23,
+	GPIO2C7_SPI1_CSN1,
+	GPIO2C7_HSADC_DATA4,
+
+	GPIO2C6_SHIFT		= 12,
+	GPIO2C6_MASK		= 3 << GPIO2C6_SHIFT,
+	GPIO2C6_GPIO		= 0,
+	GPIO2C6_LCDC1_DATA22,
+	GPIO2C6_SPI1_RXD,
+	GPIO2C6_HSADC_DATA3,
+
+	GPIO2C5_SHIFT		= 10,
+	GPIO2C5_MASK		= 3 << GPIO2C5_SHIFT,
+	GPIO2C5_GPIO		= 0,
+	GPIO2C5_LCDC1_DATA21,
+	GPIO2C5_SPI1_TXD,
+	GPIO2C5_HSADC_DATA2,
+
+	GPIO2C4_SHIFT		= 8,
+	GPIO2C4_MASK		= 3 << GPIO2C4_SHIFT,
+	GPIO2C4_GPIO		= 0,
+	GPIO2C4_LCDC1_DATA20,
+	GPIO2C4_SPI1_CSN0,
+	GPIO2C4_HSADC_DATA1,
+
+	GPIO2C3_SHIFT		= 6,
+	GPIO2C3_MASK		= 3 << GPIO2C3_SHIFT,
+	GPIO2C3_GPIO		= 0,
+	GPIO2C3_LCDC1_DATA19,
+	GPIO2C3_SPI1_CLK,
+	GPIO2C3_HSADC_DATA0
+};
+
+/* GRF_GPIO2D_IOMUX */
+enum {
+	GPIO2D7_SHIFT		= 14,
+	GPIO2D7_MASK		= 1 << GPIO2D7_SHIFT,
+	GPIO2D7_GPIO		= 0,
+	GPIO2D7_I2C1_SCL,
+
+	GPIO2D6_SHIFT		= 12,
+	GPIO2D6_MASK		= 1 << GPIO2D6_SHIFT,
+	GPIO2D6_GPIO		= 0,
+	GPIO2D6_I2C1_SDA,
+
+	GPIO2D5_SHIFT		= 10,
+	GPIO2D5_MASK		= 1 << GPIO2D5_SHIFT,
+	GPIO2D5_GPIO		= 0,
+	GPIO2D5_I2C0_SCL,
+
+	GPIO2D4_SHIFT		= 8,
+	GPIO2D4_MASK		= 1 << GPIO2D4_SHIFT,
+	GPIO2D4_GPIO		= 0,
+	GPIO2D4_I2C0_SDA
+
+};
+
+/* GRF_GPIO3A_IOMUX */
+enum {
+	GPIO3A7_SHIFT		= 14,
+	GPIO3A7_MASK		= 1 << GPIO3A7_SHIFT,
+	GPIO3A7_GPIO		= 0,
+	GPIO3A7_SDMMC0_WRITE_PRT,
+
+	GPIO3A6_SHIFT		= 12,
+	GPIO3A6_MASK		= 1 << GPIO3A6_SHIFT,
+	GPIO3A6_GPIO		= 0,
+	GPIO3A6_SDMMC0_RSTN_OUT,
+
+	GPIO3A5_SHIFT		= 10,
+	GPIO3A5_MASK		= 1 << GPIO3A5_SHIFT,
+	GPIO3A5_GPIO		= 0,
+	GPIO3A5_I2C4_SCL,
+
+	GPIO3A4_SHIFT		= 8,
+	GPIO3A4_MASK		= 1 << GPIO3A4_SHIFT,
+	GPIO3A4_GPIO		= 0,
+	GPIO3A4_I2C4_SDA,
+
+	GPIO3A3_SHIFT		= 6,
+	GPIO3A3_MASK		= 1 << GPIO3A3_SHIFT,
+	GPIO3A3_GPIO		= 0,
+	GPIO3A3_I2C3_SCL,
+
+	GPIO3A2_SHIFT		= 4,
+	GPIO3A2_MASK		= 1 << GPIO3A2_SHIFT,
+	GPIO3A2_GPIO		= 0,
+	GPIO3A2_I2C3_SDA,
+
+	GPIO3A1_SHIFT		= 2,
+	GPIO3A1_MASK		= 1 << GPIO3A1_SHIFT,
+	GPIO3A1_GPIO		= 0,
+	GPIO3A1_I2C2_SCL,
+
+	GPIO3A0_SHIFT		= 0,
+	GPIO3A0_MASK		= 1 << GPIO3A0_SHIFT,
+	GPIO3A0_GPIO		= 0,
+	GPIO3A0_I2C2_SDA,
+};
+
+/* GRF_GPIO3B_IOMUX */
+enum {
+	GPIO3B7_SHIFT		= 14,
+	GPIO3B7_MASK		= 1 << GPIO3B7_SHIFT,
+	GPIO3B7_GPIO		= 0,
+	GPIO3B7_SDMMC0_WRITE_PRT,
+
+	GPIO3B6_SHIFT		= 12,
+	GPIO3B6_MASK		= 1 << GPIO3B6_SHIFT,
+	GPIO3B6_GPIO		= 0,
+	GPIO3B6_SDMMC0_DETECT_N,
+
+	GPIO3B5_SHIFT		= 10,
+	GPIO3B5_MASK		= 1 << GPIO3B5_SHIFT,
+	GPIO3B5_GPIO		= 0,
+	GPIO3B5_SDMMC0_DATA3,
+
+	GPIO3B4_SHIFT		= 8,
+	GPIO3B4_MASK		= 1 << GPIO3B4_SHIFT,
+	GPIO3B4_GPIO		= 0,
+	GPIO3B4_SDMMC0_DATA2,
+
+	GPIO3B3_SHIFT		= 6,
+	GPIO3B3_MASK		= 1 << GPIO3B3_SHIFT,
+	GPIO3B3_GPIO		= 0,
+	GPIO3B3_SDMMC0_DATA1,
+
+	GPIO3B2_SHIFT		= 4,
+	GPIO3B2_MASK		= 1 << GPIO3B2_SHIFT,
+	GPIO3B2_GPIO		= 0,
+	GPIO3B2_SDMMC0_DATA0,
+
+	GPIO3B1_SHIFT		= 2,
+	GPIO3B1_MASK		= 1 << GPIO3B1_SHIFT,
+	GPIO3B1_GPIO		= 0,
+	GPIO3B1_SDMMC0_CMD,
+
+	GPIO3B0_SHIFT		= 0,
+	GPIO3B0_MASK		= 1 << GPIO3B0_SHIFT,
+	GPIO3B0_GPIO		= 0,
+	GPIO3B0_SDMMC0_CLKOUT
+
+};
+
+/* GRF_GPIO3C_IOMUX */
+enum {
+	GPIO3C7_SHIFT		= 14,
+	GPIO3C7_MASK		= 1 << GPIO3C7_SHIFT,
+	GPIO3C7_GPIO		= 0,
+	GPIO3C7_SDMMC1_WRITE_PRT,
+
+	GPIO3C6_SHIFT		= 12,
+	GPIO3C6_MASK		= 1 << GPIO3C6_SHIFT,
+	GPIO3C6_GPIO		= 0,
+	GPIO3C6_SDMMC1_DETECT_N,
+
+	GPIO3C5_SHIFT		= 10,
+	GPIO3C5_MASK		= 1 << GPIO3C5_SHIFT,
+	GPIO3C5_GPIO		= 0,
+	GPIO3C5_SDMMC1_CLKOUT,
+
+	GPIO3C4_SHIFT		= 8,
+	GPIO3C4_MASK		= 1 << GPIO3C4_SHIFT,
+	GPIO3C4_GPIO		= 0,
+	GPIO3C4_SDMMC1_DATA3,
+
+	GPIO3C3_SHIFT		= 6,
+	GPIO3C3_MASK		= 1 << GPIO3C3_SHIFT,
+	GPIO3C3_GPIO		= 0,
+	GPIO3C3_SDMMC1_DATA2,
+
+	GPIO3C2_SHIFT		= 4,
+	GPIO3C2_MASK		= 1 << GPIO3C2_SHIFT,
+	GPIO3C2_GPIO		= 0,
+	GPIO3C2_SDMMC1_DATA1,
+
+	GPIO3C1_SHIFT		= 2,
+	GPIO3C1_MASK		= 1 << GPIO3C1_SHIFT,
+	GPIO3C1_GPIO		= 0,
+	GPIO3C1_SDMMC1_DATA0,
+
+	GPIO3C0_SHIFT		= 0,
+	GPIO3C0_MASK		= 1 << GPIO3C0_SHIFT,
+	GPIO3C0_GPIO		= 0,
+	GPIO3C0_SMMC1_CMD
+};
+
+/* GRF_GPIO3D_IOMUX */
+enum {
+	GPIO3D7_SHIFT		= 14,
+	GPIO3D7_MASK		= 3 << GPIO3D7_SHIFT,
+	GPIO3D7_GPIO		= 0,
+	GPIO3D7_FLASH_DQS,
+	GPIO3D7_EMMC_CLKOUT,
+
+	GPIO3D6_SHIFT		= 12,
+	GPIO3D6_MASK		= 1 << GPIO3D6_SHIFT,
+	GPIO3D6_GPIO		= 0,
+	GPIO3D6_UART3_RTS_N,
+
+	GPIO3D5_SHIFT		= 10,
+	GPIO3D5_MASK		= 1 << GPIO3D5_SHIFT,
+	GPIO3D5_GPIO		= 0,
+	GPIO3D5_UART3_CTS_N,
+
+	GPIO3D4_SHIFT		= 8,
+	GPIO3D4_MASK		= 1 << GPIO3D4_SHIFT,
+	GPIO3D4_GPIO		= 0,
+	GPIO3D4_UART3_SOUT,
+
+	GPIO3D3_SHIFT		= 6,
+	GPIO3D3_MASK		= 1 << GPIO3D3_SHIFT,
+	GPIO3D3_GPIO		= 0,
+	GPIO3D3_UART3_SIN,
+
+	GPIO3D2_SHIFT		= 4,
+	GPIO3D2_MASK		= 1 << GPIO3D2_SHIFT,
+	GPIO3D2_GPIO		= 0,
+	GPIO3D2_SDMMC1_INT_N,
+
+	GPIO3D1_SHIFT		= 2,
+	GPIO3D1_MASK		= 1 << GPIO3D1_SHIFT,
+	GPIO3D1_GPIO		= 0,
+	GPIO3D1_SDMMC1_BACKEND_PWR,
+
+	GPIO3D0_SHIFT		= 0,
+	GPIO3D0_MASK		= 1 << GPIO3D0_SHIFT,
+	GPIO3D0_GPIO		= 0,
+	GPIO3D0_SDMMC1_PWR_EN
+
+};
+
+/* GRF_GPIO4A_IOMUX */
+enum {
+	GPIO4A7_SHIFT		= 14,
+	GPIO4A7_MASK		= 1 << GPIO4A7_SHIFT,
+	GPIO4A7_GPIO		= 0,
+	GPIO4A7_FLASH_DATA15,
+
+	GPIO4A6_SHIFT		= 12,
+	GPIO4A6_MASK		= 1 << GPIO4A6_SHIFT,
+	GPIO4A6_GPIO		= 0,
+	GPIO4A6_FLASH_DATA14,
+
+	GPIO4A5_SHIFT		= 10,
+	GPIO4A5_MASK		= 1 << GPIO4A5_SHIFT,
+	GPIO4A5_GPIO		= 0,
+	GPIO4A5_FLASH_DATA13,
+
+	GPIO4A4_SHIFT		= 8,
+	GPIO4A4_MASK		= 1 << GPIO4A4_SHIFT,
+	GPIO4A4_GPIO		= 0,
+	GPIO4A4_FLASH_DATA12,
+
+	GPIO4A3_SHIFT		= 6,
+	GPIO4A3_MASK		= 1 << GPIO4A3_SHIFT,
+	GPIO4A3_GPIO		= 0,
+	GPIO4A3_FLASH_DATA11,
+
+	GPIO4A2_SHIFT		= 4,
+	GPIO4A2_MASK		= 1 << GPIO4A2_SHIFT,
+	GPIO4A2_GPIO		= 0,
+	GPIO4A2_FLASH_DATA10,
+
+	GPIO4A1_SHIFT		= 2,
+	GPIO4A1_MASK		= 1 << GPIO4A1_SHIFT,
+	GPIO4A1_GPIO		= 0,
+	GPIO4A1_FLASH_DATA9,
+
+	GPIO4A0_SHIFT		= 0,
+	GPIO4A0_MASK		= 1 << GPIO4A0_SHIFT,
+	GPIO4A0_GPIO		= 0,
+	GPIO4A0_FLASH_DATA8
+
+};
+
+/* GRF_GPIO4B_IOMUX */
+enum {
+	GPIO4B7_SHIFT		= 14,
+	GPIO4B7_MASK		= 1 << GPIO4B7_SHIFT,
+	GPIO4B7_GPIO		= 0,
+	GPIO4B7_SPI0_CSN1,
+
+	GPIO4B6_SHIFT		= 12,
+	GPIO4B6_MASK		= 1 << GPIO4B6_SHIFT,
+	GPIO4B6_GPIO		= 0,
+	GPIO4B6_FLASH_CSN7,
+
+	GPIO4B5_SHIFT		= 10,
+	GPIO4B5_MASK		= 1 << GPIO4B5_SHIFT,
+	GPIO4B5_GPIO		= 0,
+	GPIO4B5_FLASH_CSN6,
+
+	GPIO4B4_SHIFT		= 8,
+	GPIO4B4_MASK		= 1 << GPIO4B4_SHIFT,
+	GPIO4B4_GPIO		= 0,
+	GPIO4B4_FLASH_CSN5,
+
+	GPIO4B3_SHIFT		= 6,
+	GPIO4B3_MASK		= 1 << GPIO4B3_SHIFT,
+	GPIO4B3_GPIO		= 0,
+	GPIO4B3_FLASH_CSN4,
+
+	GPIO4B2_SHIFT		= 4,
+	GPIO4B2_MASK		= 3 << GPIO4B2_SHIFT,
+	GPIO4B2_GPIO		= 0,
+	GPIO4B2_FLASH_CSN3,
+	GPIO4B2_EMMC_RSTN_OUT,
+
+	GPIO4B1_SHIFT		= 2,
+	GPIO4B1_MASK		= 3 << GPIO4B1_SHIFT,
+	GPIO4B1_GPIO		= 0,
+	GPIO4B1_FLASH_CSN2,
+	GPIO4B1_EMMC_CMD,
+
+	GPIO4B0_SHIFT		= 0,
+	GPIO4B0_MASK		= 1 << GPIO4B0_SHIFT,
+	GPIO4B0_GPIO		= 0,
+	GPIO4B0_FLASH_CSN1
+};
+
+/* GRF_SOC_CON0 */
+enum {
+	SMC_MUX_CON_SHIFT	= 13,
+	SMC_MUX_CON_MASK	= 1 << SMC_MUX_CON_SHIFT,
+
+	NOC_REMAP_SHIFT		= 12,
+	NOC_REMAP_MASK		= 1 << NOC_REMAP_SHIFT,
+
+	EMMC_FLASH_SEL_SHIFT	= 11,
+	EMMC_FLASH_SEL_MASK	= 1 << EMMC_FLASH_SEL_SHIFT,
+
+	TZPC_REVISION_SHIFT	= 7,
+	TZPC_REVISION_MASK	= 0xf << TZPC_REVISION_SHIFT,
+
+	L2CACHE_ACC_SHIFT	= 5,
+	L2CACHE_ACC_MASK	= 3 << L2CACHE_ACC_SHIFT,
+
+	L2RD_WAIT_SHIFT		= 3,
+	L2RD_WAIT_MASK		= 3 << L2RD_WAIT_SHIFT,
+
+	IMEMRD_WAIT_SHIFT	= 1,
+	IMEMRD_WAIT_MASK	= 3 << IMEMRD_WAIT_SHIFT,
+	
+	SOC_REMAP_SHIFT		= 0,
+	SOC_REMAP_MASK		= 1 << SOC_REMAP_SHIFT,
+};
+
+/* GRF_SOC_CON1 */
+enum {
+	RKI2C4_SEL_SHIFT	= 15,
+	RKI2C4_SEL_MASK		= 1 << RKI2C4_SEL_SHIFT,
+
+	RKI2C3_SEL_SHIFT	= 14,
+	RKI2C3_SEL_MASK		= 1 << RKI2C3_SEL_SHIFT,
+
+	RKI2C2_SEL_SHIFT	= 13,
+	RKI2C2_SEL_MASK		= 1 << RKI2C2_SEL_SHIFT,
+
+	RKI2C1_SEL_SHIFT	= 12,
+	RKI2C1_SEL_MASK		= 1 << RKI2C1_SEL_SHIFT,
+
+	RKI2C0_SEL_SHIFT	= 11,
+	RKI2C0_SEL_MASK		= 1 << RKI2C0_SEL_SHIFT,
+
+	VCODEC_SEL_SHIFT	= 10,
+	VCODEC_SEL_MASK		= 1 << VCODEC_SEL_SHIFT,
+
+	PERI_EMEM_PAUSE_SHIFT	= 9,
+	PERI_EMEM_PAUSE_MASK	= 1 << PERI_EMEM_PAUSE_SHIFT,
+
+	PERI_USB_PAUSE_SHIFT	= 8,
+	PERI_USB_PAUSE_MASK	= 1 << PERI_USB_PAUSE_SHIFT,
+
+	SMC_MUX_MODE_0_SHIFT	= 6,
+	SMC_MUX_MODE_0_MASK	= 1 << SMC_MUX_MODE_0_SHIFT,
+
+	SMC_SRAM_MW_0_SHIFT	= 4,
+	SMC_SRAM_MW_0_MASK	= 3 << SMC_SRAM_MW_0_SHIFT,
+
+	SMC_REMAP_0_SHIFT	= 3,
+	SMC_REMAP_0_MASK	= 1 << SMC_REMAP_0_SHIFT,
+
+	SMC_A_GT_M0_SYNC_SHIFT	= 2,
+	SMC_A_GT_M0_SYNC_MASK	= 1 << SMC_A_GT_M0_SYNC_SHIFT,
+
+	EMAC_SPEED_SHIFT	= 1,
+	EMAC_SPEEC_MASK		= 1 << EMAC_SPEED_SHIFT,
+
+	EMAC_MODE_SHIFT		= 0,
+	EMAC_MODE_MASK		= 1 << EMAC_MODE_SHIFT,
+};
+
+/* GRF_SOC_CON2 */
+enum {
+
+	MSCH4_MAINDDR3_SHIFT	= 7,
+	MSCH4_MAINDDR3_MASK	= 1 << MSCH4_MAINDDR3_SHIFT,
+	MSCH4_MAINDDR3_DDR3	= 1,
+
+	EMAC_NEWRCV_EN_SHIFT	= 6,
+	EMAC_NEWRCV_EN_MASK	= 1 << EMAC_NEWRCV_EN_SHIFT,
+
+	SW_ADDR15_EN_SHIFT	= 5,
+	SW_ADDR15_EN_MASK	= 1 << SW_ADDR15_EN_SHIFT,
+
+	SW_ADDR16_EN_SHIFT	= 4,
+	SW_ADDR16_EN_MASK	= 1 << SW_ADDR16_EN_SHIFT,
+
+	SW_ADDR17_EN_SHIFT	= 3,
+	SW_ADDR17_EN_MASK	= 1 << SW_ADDR17_EN_SHIFT,
+
+	BANK2_TO_RANK_EN_SHIFT	= 2,
+	BANK2_TO_RANK_EN_MASK	= 1 << BANK2_TO_RANK_EN_SHIFT,
+
+	RANK_TO_ROW15_EN_SHIFT	= 1,
+	RANK_TO_ROW15_EN_MASK	= 1 << RANK_TO_ROW15_EN_SHIFT,
+
+	UPCTL_C_ACTIVE_IN_SHIFT = 0,
+	UPCTL_C_ACTIVE_IN_MASK	= 1 << UPCTL_C_ACTIVE_IN_SHIFT,
+	UPCTL_C_ACTIVE_IN_MAY	= 0,
+	UPCTL_C_ACTIVE_IN_WILL,
+};
+
+/* GRF_DDRC_CON0 */
+enum {
+	DTO_LB_SHIFT		= 11,
+	DTO_LB_MASK		= 3 << DTO_LB_SHIFT,
+
+	DTO_TE_SHIFT		= 9,
+	DTO_TE_MASK		= 3 << DTO_TE_SHIFT,
+
+	DTO_PDR_SHIFT		= 7,
+	DTO_PDR_MASK		= 3 << DTO_PDR_SHIFT,
+
+	DTO_PDD_SHIFT		= 5,
+	DTO_PDD_MASK		= 3 << DTO_PDD_SHIFT,
+
+	DTO_IOM_SHIFT		= 3,
+	DTO_IOM_MASK		= 3 << DTO_IOM_SHIFT,
+
+	DTO_OE_SHIFT		= 1,
+	DTO_OE_MASK		= 3 << DTO_OE_SHIFT,
+
+	ATO_AE_SHIFT		= 0,
+	ATO_AE_MASK		= 1 << ATO_AE_SHIFT,
+};
+#endif
-- 
2.7.4

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

* [U-Boot] [PATCH v4 02/19] rockchip: rk3066: add rk3066 pinctrl driver
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-17 13:11 ` [U-Boot] [PATCH v4 01/19] rockchip: rk3066: add grf header file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:12 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 03/19] rockchip: rk3066: add sysreset driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:12 UTC (permalink / raw)
  To: u-boot

Add driver supporting pin multiplexing on rk3066 platform.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- updated to shifted masks
- added nand support

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/include/asm/arch-rockchip/periph.h |   1 +
 drivers/pinctrl/Kconfig                     |   9 +
 drivers/pinctrl/rockchip/Makefile           |   1 +
 drivers/pinctrl/rockchip/pinctrl_rk3066.c   | 340 ++++++++++++++++++++++++++++
 4 files changed, 351 insertions(+)
 create mode 100644 drivers/pinctrl/rockchip/pinctrl_rk3066.c

diff --git a/arch/arm/include/asm/arch-rockchip/periph.h b/arch/arm/include/asm/arch-rockchip/periph.h
index 9f4bc2e..6c8c77d 100644
--- a/arch/arm/include/asm/arch-rockchip/periph.h
+++ b/arch/arm/include/asm/arch-rockchip/periph.h
@@ -43,6 +43,7 @@ enum periph_id {
 	PERIPH_ID_HDMI,
 	PERIPH_ID_GMAC,
 	PERIPH_ID_SFC,
+	PERIPH_ID_NAND,
 
 	PERIPH_ID_COUNT,
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index bcbe4a1..c9eb49d 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -168,6 +168,15 @@ config PINCTRL_ROCKCHIP_RK3036
 	  the GPIO definitions and pin control functions for each available
 	  multiplex function.
 
+config PINCTRL_ROCKCHIP_RK3066
+        bool "Rockchip rk3066 pin control driver"
+        depends on DM
+        help
+          Support pin multiplexing control on Rockchip rk3066 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 PINCTRL_ROCKCHIP_RK3188
 	bool "Rockchip rk3188 pin control driver"
 	depends on DM
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 5251771..65923f9 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -6,6 +6,7 @@
 #
 
 obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3036) += pinctrl_rk3036.o
+obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3066) += pinctrl_rk3066.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3188) += pinctrl_rk3188.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP_RK322X) += pinctrl_rk322x.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3288) += pinctrl_rk3288.o
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3066.c b/drivers/pinctrl/rockchip/pinctrl_rk3066.c
new file mode 100644
index 0000000..79e0a54
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3066.c
@@ -0,0 +1,340 @@
+/*
+ * Pinctrl driver for Rockchip 3066 SoCs
+ * (C) Copyright 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3066.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rk3066_pinctrl_priv {
+	struct rk3066_grf *grf;
+};
+
+static void pinctrl_rk3066_pwm_config(struct rk3066_grf *grf, int pwm_id)
+{
+	switch (pwm_id) {
+	case PERIPH_ID_PWM0:
+		rk_clrsetreg(&grf->gpio0a_iomux, GPIO0A3_MASK,
+			     GPIO0A3_PWM0 << GPIO0A3_SHIFT);
+		break;
+	case PERIPH_ID_PWM1:
+		rk_clrsetreg(&grf->gpio0a_iomux, GPIO0A4_MASK,
+			     GPIO0A4_PWM1 << GPIO0A4_SHIFT);
+		break;
+	case PERIPH_ID_PWM2:
+		rk_clrsetreg(&grf->gpio0d_iomux, GPIO0D6_MASK,
+			     GPIO0D6_PWM2 << GPIO0D6_SHIFT);
+		break;
+	case PERIPH_ID_PWM3:
+		rk_clrsetreg(&grf->gpio0d_iomux, GPIO0D7_MASK,
+			     GPIO0D7_PWM3 << GPIO0D7_SHIFT);
+		break;
+	default:
+		debug("pwm id = %d iomux error!\n", pwm_id);
+		break;
+	}
+}
+
+static void pinctrl_rk3066_i2c_config(struct rk3066_grf *grf, int i2c_id)
+{
+	switch (i2c_id) {
+	case PERIPH_ID_I2C0:
+		rk_clrsetreg(&grf->gpio2d_iomux,
+			     GPIO2D4_MASK | GPIO2D5_MASK,
+			     GPIO2D4_I2C0_SDA << GPIO2D4_SHIFT |
+			     GPIO2D5_I2C0_SCL << GPIO2D5_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C0_SEL_SHIFT,
+					     1 << RKI2C0_SEL_SHIFT);
+		break;
+	case PERIPH_ID_I2C1:
+		rk_clrsetreg(&grf->gpio2d_iomux,
+			     GPIO2D6_MASK | GPIO2D7_MASK,
+			     GPIO2D6_I2C1_SDA << GPIO2D6_SHIFT |
+			     GPIO2D7_I2C1_SCL << GPIO2D7_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C1_SEL_SHIFT,
+					     1 << RKI2C1_SEL_SHIFT);
+		break;
+	case PERIPH_ID_I2C2:
+		rk_clrsetreg(&grf->gpio3a_iomux,
+			     GPIO3A1_MASK | GPIO3A0_MASK,
+			     GPIO3A1_I2C2_SCL << GPIO3A1_SHIFT |
+			     GPIO3A0_I2C2_SDA << GPIO3A0_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C2_SEL_SHIFT,
+					     1 << RKI2C2_SEL_SHIFT);
+	case PERIPH_ID_I2C3:
+		rk_clrsetreg(&grf->gpio3a_iomux,
+			     GPIO3A3_MASK | GPIO3A2_MASK,
+			     GPIO3A3_I2C3_SCL << GPIO3A3_SHIFT |
+			     GPIO3A2_I2C3_SDA << GPIO3A2_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C3_SEL_SHIFT,
+					     1 << RKI2C3_SEL_SHIFT);
+	case PERIPH_ID_I2C4:
+		rk_clrsetreg(&grf->gpio3a_iomux,
+			     GPIO3A5_MASK | GPIO3A4_MASK,
+			     GPIO3A5_I2C4_SCL << GPIO3A5_SHIFT |
+			     GPIO3A4_I2C4_SDA << GPIO3A4_SHIFT);
+		rk_clrsetreg(&grf->soc_con1, 1 << RKI2C4_SEL_SHIFT,
+					     1 << RKI2C4_SEL_SHIFT);
+		break;
+	}
+}
+
+static void pinctrl_rk3066_spi_config(struct rk3066_grf *grf, int spi_id, int cs)
+{
+	switch (spi_id) {
+	case PERIPH_ID_SPI0:
+		rk_clrsetreg(&grf->gpio1a_iomux,
+			     GPIO1A7_MASK | GPIO1A6_MASK | GPIO1A5_MASK,
+			     GPIO1A7_SPI0_TXD << GPIO1A7_SHIFT |
+			     GPIO1A6_SPI0_RXD << GPIO1A6_SHIFT |
+			     GPIO1A5_SPI0_CLK << GPIO1A5_SHIFT);
+		if(cs == 0)
+			rk_clrsetreg(&grf->gpio1a_iomux,
+				     GPIO1A4_MASK,
+				     GPIO1A4_SPI0_CSN0 << GPIO1A4_SHIFT);
+		else
+			rk_clrsetreg(&grf->gpio4b_iomux,
+				     GPIO4B7_MASK,
+				     GPIO4B7_SPI0_CSN1 << GPIO4B7_SHIFT);
+		break;
+	case PERIPH_ID_SPI1:
+		rk_clrsetreg(&grf->gpio2c_iomux,
+			     GPIO2C5_MASK | GPIO2C6_MASK | GPIO2C3_MASK,
+			     GPIO2C5_SPI1_TXD << GPIO2C5_SHIFT |
+			     GPIO2C6_SPI1_RXD << GPIO2C6_SHIFT |
+			     GPIO2C3_SPI1_CLK << GPIO2C3_SHIFT);
+		if(cs == 0)
+			rk_clrsetreg(&grf->gpio2c_iomux,
+				     GPIO2C4_MASK,
+				     GPIO2C4_SPI1_CSN0 << GPIO2C4_SHIFT);
+		else
+			rk_clrsetreg(&grf->gpio2c_iomux,
+				     GPIO2C7_MASK,
+				     GPIO2C7_SPI1_CSN1 << GPIO2C7_SHIFT);
+		break;
+	}
+}
+
+static void pinctrl_rk3066_uart_config(struct rk3066_grf *grf, int uart_id)
+{
+	switch (uart_id) {
+	case PERIPH_ID_UART0:
+		rk_clrsetreg(&grf->gpio1a_iomux,
+			     GPIO1A2_MASK | GPIO1A3_MASK |
+			     GPIO1A0_MASK | GPIO1A1_MASK,
+			     GPIO1A2_UART0_CTS_N << GPIO1A2_SHIFT |
+			     GPIO1A3_UART0_RTS_N << GPIO1A3_SHIFT |
+			     GPIO1A0_UART0_SIN << GPIO1A0_SHIFT |
+			     GPIO1A1_UART0_SOUT << GPIO1A1_SHIFT);
+		break;
+	case PERIPH_ID_UART1:
+		rk_clrsetreg(&grf->gpio1a_iomux,
+			     GPIO1A7_MASK | GPIO1A6_MASK |
+			     GPIO1A5_MASK | GPIO1A4_MASK,
+			     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 | GPIO1B0_MASK,
+			     GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
+			     GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
+		break;
+	case PERIPH_ID_UART3:
+		rk_clrsetreg(&grf->gpio3d_iomux,
+			     GPIO3D6_MASK | GPIO3D5_MASK |
+			     GPIO3D4_MASK | GPIO3D3_MASK,
+			     GPIO3D6_UART3_RTS_N << GPIO3D6_SHIFT |
+			     GPIO3D5_UART3_CTS_N << GPIO3D5_SHIFT |
+			     GPIO3D4_UART3_SOUT << GPIO3D4_SHIFT |
+			     GPIO3D3_UART3_SIN << GPIO3D3_SHIFT);
+		break;
+	}
+}
+
+static void pinctrl_rk3066_sdmmc_config(struct rk3066_grf *grf, int mmc_id)
+{
+	switch (mmc_id) {
+	case PERIPH_ID_EMMC:
+		rk_clrsetreg(&grf->soc_con0,
+			     EMMC_FLASH_SEL_MASK,
+			     1 << EMMC_FLASH_SEL_SHIFT);
+		rk_clrsetreg(&grf->gpio3d_iomux,
+			     GPIO3D7_MASK,
+			     GPIO3D7_EMMC_CLKOUT << GPIO3D7_SHIFT);
+		rk_clrsetreg(&grf->gpio4b_iomux,
+			     GPIO4B2_MASK | GPIO4B1_MASK,
+			     GPIO4B2_EMMC_RSTN_OUT << GPIO4B2_SHIFT |
+			     GPIO4B1_EMMC_CMD << GPIO4B1_SHIFT);
+		break;
+	case PERIPH_ID_SDCARD:
+		rk_clrsetreg(&grf->gpio3b_iomux, 0xffff,
+			     GPIO3B7_SDMMC0_WRITE_PRT << GPIO3B7_SHIFT |
+			     GPIO3B6_SDMMC0_DETECT_N << GPIO3B6_SHIFT |
+			     GPIO3B5_SDMMC0_DATA3 << GPIO3B5_SHIFT |
+			     GPIO3B4_SDMMC0_DATA2 << GPIO3B4_SHIFT |
+			     GPIO3B3_SDMMC0_DATA1 << GPIO3B3_SHIFT |
+			     GPIO3B2_SDMMC0_DATA0 << GPIO3B2_SHIFT |
+			     GPIO3B1_SDMMC0_CMD << GPIO3B1_SHIFT |
+			     GPIO3B0_SDMMC0_CLKOUT << GPIO3B0_SHIFT);
+		break;
+	}
+}
+
+static void pinctrl_rk3066_nand_config(struct rk3066_grf *grf)
+{
+	rk_clrsetreg(&grf->soc_con0,
+		     EMMC_FLASH_SEL_MASK,
+		     0 << EMMC_FLASH_SEL_SHIFT);
+	rk_clrsetreg(&grf->gpio3d_iomux,
+		     GPIO3D7_MASK,
+		     GPIO3D7_FLASH_DQS << GPIO3D7_SHIFT);
+}
+
+static int rk3066_pinctrl_request(struct udevice *dev, int func, int flags)
+{
+	struct rk3066_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:
+		pinctrl_rk3066_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:
+		pinctrl_rk3066_i2c_config(priv->grf, func);
+		break;
+	case PERIPH_ID_SPI0:
+	case PERIPH_ID_SPI1:
+		pinctrl_rk3066_spi_config(priv->grf, func, flags);
+		break;
+	case PERIPH_ID_UART0:
+	case PERIPH_ID_UART1:
+	case PERIPH_ID_UART2:
+	case PERIPH_ID_UART3:
+		pinctrl_rk3066_uart_config(priv->grf, func);
+		break;
+	case PERIPH_ID_EMMC:
+	case PERIPH_ID_SDCARD:
+		pinctrl_rk3066_sdmmc_config(priv->grf, func);
+		break;
+	case PERIPH_ID_NAND:
+		pinctrl_rk3066_nand_config(priv->grf);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rk3066_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, dev_of_offset(periph),
+				   "interrupts", cell, ARRAY_SIZE(cell));
+	if (ret < 0)
+		return -EINVAL;
+
+	switch (cell[1]) {
+	case 23:
+		return PERIPH_ID_SDCARD;
+	case 25:
+		return PERIPH_ID_EMMC;
+	case 27:
+		return PERIPH_ID_NAND;
+	case 34:
+		return PERIPH_ID_UART0;
+	case 35:
+		return PERIPH_ID_UART1;
+	case 36:
+		return PERIPH_ID_UART2;
+	case 37:
+		return PERIPH_ID_UART3;
+	case 38:
+		return PERIPH_ID_SPI0;
+	case 39:
+		return PERIPH_ID_SPI1;
+	case 40:
+		return PERIPH_ID_I2C0;
+	case 41:
+		return PERIPH_ID_I2C1;
+	case 42:
+		return PERIPH_ID_I2C2;
+	case 43:
+		return PERIPH_ID_I2C3;
+	case 30:
+		return PERIPH_ID_PWM0;
+	}
+#endif
+	return -ENOENT;
+}
+
+static int rk3066_pinctrl_set_state_simple(struct udevice *dev,
+					   struct udevice *periph)
+{
+	int func;
+
+	func = rk3066_pinctrl_get_periph_id(dev, periph);
+	if (func < 0)
+		return func;
+	return rk3066_pinctrl_request(dev, func, 0);
+}
+
+static struct pinctrl_ops rk3066_pinctrl_ops = {
+	.set_state_simple	= rk3066_pinctrl_set_state_simple,
+	.request	= rk3066_pinctrl_request,
+	.get_periph_id	= rk3066_pinctrl_get_periph_id,
+};
+
+static int rk3066_pinctrl_probe(struct udevice *dev)
+{
+	struct rk3066_pinctrl_priv *priv = dev_get_priv(dev);
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	if (IS_ERR(priv->grf))
+		debug("%s: grf=%p\n", __func__, priv->grf);
+	return 0;
+}
+
+static const struct udevice_id rk3066_pinctrl_ids[] = {
+	{ .compatible = "rockchip,rk3066a-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_rk3066a_pinctrl) = {
+	.name		= "rockchip_rk3066a_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= rk3066_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct rk3066_pinctrl_priv),
+	.ops		= &rk3066_pinctrl_ops,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind           = dm_scan_fdt_dev,
+#endif
+	.probe		= rk3066_pinctrl_probe,
+};
-- 
2.7.4

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

* [U-Boot] [PATCH v4 03/19] rockchip: rk3066: add sysreset driver
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-17 13:11 ` [U-Boot] [PATCH v4 01/19] rockchip: rk3066: add grf header file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 02/19] rockchip: rk3066: add rk3066 pinctrl driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:12 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 04/19] rockchip: rk3066: add clock driver for rk3066 soc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:12 UTC (permalink / raw)
  To: u-boot

Add support for system reset for rk3066 socs.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- updated to shifted masks

Changes since v2:
- none

Changes since v3:
- none

 drivers/sysreset/Makefile          |  1 +
 drivers/sysreset/sysreset_rk3066.c | 61 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)
 create mode 100644 drivers/sysreset/sysreset_rk3066.c

diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index a5200d3..7d4d0cd 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3036) += sysreset_rk3036.o
 endif
+obj-$(CONFIG_ROCKCHIP_RK3066) += sysreset_rk3066.o
 obj-$(CONFIG_ROCKCHIP_RK3188) += sysreset_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += sysreset_rk3288.o
 obj-$(CONFIG_ROCKCHIP_RK3328) += sysreset_rk3328.o
diff --git a/drivers/sysreset/sysreset_rk3066.c b/drivers/sysreset/sysreset_rk3066.c
new file mode 100644
index 0000000..b5dcb9a
--- /dev/null
+++ b/drivers/sysreset/sysreset_rk3066.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <sysreset.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3066.h>
+#include <asm/arch/grf_rk3066.h>
+#include <asm/arch/hardware.h>
+#include <linux/err.h>
+
+int rk3066_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	struct rk3066_cru *cru = rockchip_get_cru();
+	struct rk3066_grf *grf;
+
+	if (IS_ERR(cru))
+		return PTR_ERR(cru);
+
+	switch (type) {
+	case SYSRESET_WARM:
+		grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+		if (IS_ERR(grf))
+			return -EPROTONOSUPPORT;
+		/*
+		 * warm-reset keeps the remap value,
+		 * so make sure it's disabled.
+		 */
+		rk_clrsetreg(&grf->soc_con0,
+			NOC_REMAP_MASK, 0 << NOC_REMAP_SHIFT);
+
+		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 rk3066_sysreset = {
+	.request	= rk3066_sysreset_request,
+};
+
+U_BOOT_DRIVER(sysreset_rk3066) = {
+	.name	= "rk3066_sysreset",
+	.id	= UCLASS_SYSRESET,
+	.ops	= &rk3066_sysreset,
+};
-- 
2.7.4

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

* [U-Boot] [PATCH v4 04/19] rockchip: rk3066: add clock driver for rk3066 soc
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (2 preceding siblings ...)
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 03/19] rockchip: rk3066: add sysreset driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:12 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 11:26   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 05/19] rockchip: rk3066: add rk3066 platform devicetree file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:12 UTC (permalink / raw)
  To: u-boot

Add clock driver for rk3066 platform.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- updated to shifted masks
- moved clk init to tpl

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/include/asm/arch-rockchip/cru_rk3066.h | 189 ++++++++
 drivers/clk/rockchip/Makefile                   |   1 +
 drivers/clk/rockchip/clk_rk3066.c               | 587 ++++++++++++++++++++++++
 3 files changed, 777 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3066.h
 create mode 100644 drivers/clk/rockchip/clk_rk3066.c

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3066.h b/arch/arm/include/asm/arch-rockchip/cru_rk3066.h
new file mode 100644
index 0000000..c4a6951
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3066.h
@@ -0,0 +1,189 @@
+/*
+ * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#ifndef _ASM_ARCH_CRU_RK3066_H
+#define _ASM_ARCH_CRU_RK3066_H
+
+#define OSC_HZ		(24 * 1000 * 1000)
+
+#define APLL_HZ		(1416 * 1000000)
+#define APLL_SAFE_HZ	(600 * 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 rk3066_clk_priv {
+	struct rk3066_grf *grf;
+	struct rk3066_cru *cru;
+	ulong rate;
+	bool has_bwadj;
+};
+
+struct rk3066_cru {
+	struct rk3066_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(rk3066_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 << A9_CORE_DIV_SHIFT,
+	CORE_PLL_SHIFT		= 8,
+	CORE_PLL_MASK		= 1 << CORE_PLL_SHIFT,
+	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 << CORE_PERI_DIV_SHIFT,
+
+	/* aclk_cpu pll selection */
+	CPU_ACLK_PLL_SHIFT	= 5,
+	CPU_ACLK_PLL_MASK	= 1 << CPU_ACLK_PLL_SHIFT,
+	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 << A9_CPU_DIV_SHIFT,
+};
+
+/* 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 << AHB2APB_DIV_SHIFT,
+
+	/* 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_PCLK_DIV_SHIFT,
+
+	/* cpu_hclk_div: aclk_cpu:hclk_cpu = 1:1, 2:1 or 4:1 */
+	CPU_HCLK_DIV_SHIFT	= 8,
+	CPU_HCLK_DIV_MASK	= 3 << CPU_HCLK_DIV_SHIFT,
+
+	/* 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 << CORE_ACLK_DIV_SHIFT,
+};
+
+/* CRU_CLKSEL10_CON */
+enum {
+	PERI_SEL_PLL_SHIFT	= 15,
+	PERI_SEL_PLL_MASK	= 1 << PERI_SEL_PLL_SHIFT,
+	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 << PERI_PCLK_DIV_SHIFT,
+
+	/* 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_HCLK_DIV_SHIFT,
+
+	/* peri aclk div: aclk_peri = periph_src / (peri_aclk_div + 1) */
+	PERI_ACLK_DIV_SHIFT	= 0,
+	PERI_ACLK_DIV_MASK	= 0x1f << PERI_ACLK_DIV_SHIFT,
+};
+/* CRU_CLKSEL11_CON */
+enum {
+	MMC0_DIV_SHIFT		= 0,
+	MMC0_DIV_MASK		= 0x3f << MMC0_DIV_SHIFT,
+};
+
+/* CRU_CLKSEL12_CON */
+enum {
+	UART_PLL_SHIFT		= 15,
+	UART_PLL_MASK		= 1 << UART_PLL_SHIFT,
+	UART_PLL_SELECT_GENERAL	= 0,
+	UART_PLL_SELECT_CODEC,
+
+	EMMC_DIV_SHIFT		= 8,
+	EMMC_DIV_MASK		= 0x3f << EMMC_DIV_SHIFT,
+
+	SDIO_DIV_SHIFT		= 0,
+	SDIO_DIV_MASK		= 0x3f << SDIO_DIV_SHIFT,
+};
+
+/* CRU_CLKSEL25_CON */
+enum {
+	SPI1_DIV_SHIFT		= 8,
+	SPI1_DIV_MASK		= 0x7f << SPI1_DIV_SHIFT,
+
+	SPI0_DIV_SHIFT		= 0,
+	SPI0_DIV_MASK		= 0x7f << SPI0_DIV_SHIFT,
+};
+
+/* CRU_MODE_CON */
+enum {
+	GPLL_MODE_SHIFT		= 12,
+	GPLL_MODE_MASK		= 3 << GPLL_MODE_SHIFT,
+	GPLL_MODE_SLOW		= 0,
+	GPLL_MODE_NORMAL,
+	GPLL_MODE_DEEP,
+
+	CPLL_MODE_SHIFT		= 8,
+	CPLL_MODE_MASK		= 3 << CPLL_MODE_SHIFT,
+	CPLL_MODE_SLOW		= 0,
+	CPLL_MODE_NORMAL,
+	CPLL_MODE_DEEP,
+
+	DPLL_MODE_SHIFT		= 4,
+	DPLL_MODE_MASK		= 3 << DPLL_MODE_SHIFT,
+	DPLL_MODE_SLOW		= 0,
+	DPLL_MODE_NORMAL,
+	DPLL_MODE_DEEP,
+
+	APLL_MODE_SHIFT		= 0,
+	APLL_MODE_MASK		= 3 << APLL_MODE_SHIFT,
+	APLL_MODE_SLOW		= 0,
+	APLL_MODE_NORMAL,
+	APLL_MODE_DEEP,
+};
+
+/* CRU_APLL_CON0 */
+enum {
+	CLKR_SHIFT		= 8,
+	CLKR_MASK		= 0x3f << CLKR_SHIFT,
+
+	CLKOD_SHIFT		= 0,
+	CLKOD_MASK		= 0x3f << CLKOD_SHIFT,
+};
+
+/* CRU_APLL_CON1 */
+enum {
+	CLKF_SHIFT		= 0,
+	CLKF_MASK		= 0x1fff << CLKF_SHIFT,
+};
+
+#endif
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index c50aff2..167b08e 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
+obj-$(CONFIG_ROCKCHIP_RK3066) += clk_rk3066.o
 obj-$(CONFIG_ROCKCHIP_RK3188) += clk_rk3188.o
 obj-$(CONFIG_ROCKCHIP_RK322X) += clk_rk322x.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
diff --git a/drivers/clk/rockchip/clk_rk3066.c b/drivers/clk/rockchip/clk_rk3066.c
new file mode 100644
index 0000000..bcf65e0
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rk3066.c
@@ -0,0 +1,587 @@
+/*
+ * (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_rk3066.h>
+#include <asm/arch/grf_rk3066.h>
+#include <asm/arch/hardware.h>
+#include <dt-bindings/clock/rk3066a-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 rk3066_clk_type {
+	RK3066_CRU,
+	RK3066A_CRU,
+};
+
+struct rk3066_clk_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3066a_cru dtd;
+#endif
+};
+
+struct pll_div {
+	u32 nr;
+	u32 nf;
+	u32 no;
+};
+
+enum {
+	VCO_MAX_HZ	= 1416U * 1000000,
+	VCO_MIN_HZ	= 300 * 1000000,
+	OUTPUT_MAX_HZ	= 1416U * 1000000,
+	OUTPUT_MIN_HZ	= 30 * 1000000,
+	FREF_MAX_HZ	= 1416U * 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 << 4,
+	SOCSTS_APLL_LOCK	= 1 << 5,
+	SOCSTS_CPLL_LOCK	= 1 << 6,
+	SOCSTS_GPLL_LOCK	= 1 << 7,
+};
+
+#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 */
+#ifdef CONFIG_TPL_BUILD
+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);
+#endif
+
+static int rkclk_set_pll(struct rk3066_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 rk3066_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 | 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 rk3066_cru *cru, struct rk3066_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_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_NORMAL << DPLL_MODE_SHIFT);
+
+	return 0;
+}
+
+static int rkclk_configure_cpu(struct rk3066_cru *cru, struct rk3066_grf *grf,
+			      unsigned int hz, bool has_bwadj)
+{
+	static const struct pll_div apll_cfg[] = {
+		{.nf = 50, .nr = 1, .no = 2},
+		{.nf = 59, .nr = 1, .no = 1},
+	};
+	int div_core_peri, div_aclk_core, cfg;
+
+	/*
+	 * We support two possible frequencies, the safe 600MHz
+	 * which will work with default pmic settings and will
+	 * be set to get away from the 24MHz default and
+	 * the maximum of 1.416Ghz, which boards can set if they
+	 * were able to get pmic support for it.
+	 */
+	switch (hz) {
+	case APLL_SAFE_HZ:
+		cfg = 0;
+		div_core_peri = 1;
+		div_aclk_core = 3;
+		break;
+	case APLL_HZ:
+		cfg = 1;
+		div_core_peri = 2;
+		div_aclk_core = 3;
+		break;
+	default:
+		debug("Unsupported ARMCLK frequency");
+		return -EINVAL;
+	}
+
+	/* pll enter slow-mode */
+	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
+		     APLL_MODE_SLOW << APLL_MODE_SHIFT);
+
+	rkclk_set_pll(cru, CLK_ARM, &apll_cfg[cfg], has_bwadj);
+
+	/* waiting for pll lock */
+	while (!(readl(&grf->soc_status0) & SOCSTS_APLL_LOCK))
+		udelay(1);
+
+	/* Set divider for peripherals attached to the cpu core. */
+	rk_clrsetreg(&cru->cru_clksel_con[0],
+		CORE_PERI_DIV_MASK,
+		div_core_peri << CORE_PERI_DIV_SHIFT);
+
+	/* set up dependent divisor for aclk_core */
+	rk_clrsetreg(&cru->cru_clksel_con[1],
+		CORE_ACLK_DIV_MASK,
+		div_aclk_core << CORE_ACLK_DIV_SHIFT);
+
+	/* PLL enter normal-mode */
+	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
+		     APLL_MODE_NORMAL << APLL_MODE_SHIFT);
+
+	return hz;
+}
+
+/* Get pll rate by id */
+static uint32_t rkclk_pll_get_rate(struct rk3066_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 rk3066_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 >> APLL_MODE_SHIFT) {
+	case APLL_MODE_SLOW:
+		return OSC_HZ;
+	case APLL_MODE_NORMAL:
+		/* normal mode */
+		con = readl(&pll->con0);
+		no = ((con >> CLKOD_SHIFT) & (CLKOD_MASK >> CLKOD_SHIFT)) + 1;
+		nr = ((con >> CLKR_SHIFT) & (CLKR_MASK >> CLKR_SHIFT)) + 1;
+		con = readl(&pll->con1);
+		nf = ((con >> CLKF_SHIFT) & (CLKF_MASK >> CLKF_SHIFT)) + 1;
+
+		return (24 * nf / (nr * no)) * 1000000;
+	case APLL_MODE_DEEP:
+	default:
+		return 32768;
+	}
+}
+
+static ulong rockchip_mmc_get_clk(struct rk3066_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 >> EMMC_DIV_SHIFT;
+		break;
+	case HCLK_SDMMC:
+		con = readl(&cru->cru_clksel_con[11]);
+		div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK >> MMC0_DIV_SHIFT;
+		break;
+	case HCLK_SDIO:
+		con = readl(&cru->cru_clksel_con[12]);
+		div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK >> SDIO_DIV_SHIFT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(gclk_rate, div);
+}
+
+static ulong rockchip_mmc_set_clk(struct rk3066_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);
+	if (src_clk_div > 0x3f)
+		src_clk_div = 0x3f;
+
+	switch (periph) {
+	case HCLK_EMMC:
+		rk_clrsetreg(&cru->cru_clksel_con[12],
+			     EMMC_DIV_MASK,
+			     src_clk_div << EMMC_DIV_SHIFT);
+		break;
+	case HCLK_SDMMC:
+		rk_clrsetreg(&cru->cru_clksel_con[11],
+			     MMC0_DIV_MASK,
+			     src_clk_div << MMC0_DIV_SHIFT);
+		break;
+	case HCLK_SDIO:
+		rk_clrsetreg(&cru->cru_clksel_con[12],
+			     SDIO_DIV_MASK,
+			     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 rk3066_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 >> SPI0_DIV_SHIFT;
+		break;
+	case SCLK_SPI1:
+		con = readl(&cru->cru_clksel_con[25]);
+		div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK >> SPI1_DIV_SHIFT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return DIV_TO_RATE(gclk_rate, div);
+}
+
+static ulong rockchip_spi_set_clk(struct rk3066_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 >> SPI0_DIV_SHIFT);
+		rk_clrsetreg(&cru->cru_clksel_con[25],
+			     SPI0_DIV_MASK,
+			     src_clk_div << SPI0_DIV_SHIFT);
+		break;
+	case SCLK_SPI1:
+		assert(src_clk_div <= SPI1_DIV_MASK >> SPI1_DIV_SHIFT);
+		rk_clrsetreg(&cru->cru_clksel_con[25],
+			     SPI1_DIV_MASK,
+			     src_clk_div << SPI1_DIV_SHIFT);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return rockchip_spi_get_clk(cru, gclk_rate, periph);
+}
+#ifdef CONFIG_TPL_BUILD
+static void rkclk_init(struct rk3066_cru *cru, struct rk3066_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 |
+		     CPLL_MODE_MASK,
+		     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 |
+		     A9_CPU_DIV_MASK,
+		     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 |
+		     CPU_PCLK_DIV_MASK |
+		     CPU_HCLK_DIV_MASK,
+		     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_HCLK_DIV_MASK |
+		     PERI_ACLK_DIV_MASK,
+		     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 |
+		     CPLL_MODE_MASK,
+		     GPLL_MODE_NORMAL << GPLL_MODE_SHIFT |
+		     CPLL_MODE_NORMAL << CPLL_MODE_SHIFT);
+
+	rockchip_mmc_set_clk(cru, PERI_HCLK_HZ, HCLK_SDMMC, 16000000);
+}
+#endif
+
+static ulong rk3066_clk_get_rate(struct clk *clk)
+{
+	struct rk3066_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 rk3066_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
+	struct rk3066_cru *cru = priv->cru;
+	ulong new_rate;
+
+	switch (clk->id) {
+	case PLL_APLL:
+		new_rate = rkclk_configure_cpu(priv->cru, priv->grf, rate,
+					       priv->has_bwadj);
+		break;
+	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 rk3066_clk_ops = {
+	.get_rate	= rk3066_clk_get_rate,
+	.set_rate	= rk3066_clk_set_rate,
+};
+
+static int rk3066_clk_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3066_clk_priv *priv = dev_get_priv(dev);
+
+	priv->cru = (struct rk3066_cru *)devfdt_get_addr(dev);
+#endif
+
+	return 0;
+}
+
+static int rk3066_clk_probe(struct udevice *dev)
+{
+	struct rk3066_clk_priv *priv = dev_get_priv(dev);
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	if (IS_ERR(priv->grf))
+		return PTR_ERR(priv->grf);
+
+#ifdef CONFIG_TPL_BUILD
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3066_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, 1);
+#endif
+
+	return 0;
+}
+
+static int rk3066_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, "rk3066_sysreset", "reset", &dev);
+	if (ret)
+		debug("Warning: No rk3066 reset driver: ret=%d\n", ret);
+
+	return 0;
+}
+
+static const struct udevice_id rk3066_clk_ids[] = {
+	{ .compatible = "rockchip,rk3066a-cru" },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_rk3066a_cru) = {
+	.name			= "rockchip_rk3066a_cru",
+	.id			= UCLASS_CLK,
+	.of_match		= rk3066_clk_ids,
+	.priv_auto_alloc_size	= sizeof(struct rk3066_clk_priv),
+	.platdata_auto_alloc_size = sizeof(struct rk3066_clk_plat),
+	.ops			= &rk3066_clk_ops,
+	.bind			= rk3066_clk_bind,
+	.ofdata_to_platdata	= rk3066_clk_ofdata_to_platdata,
+	.probe			= rk3066_clk_probe,
+};
-- 
2.7.4

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

* [U-Boot] [PATCH v4 05/19] rockchip: rk3066: add rk3066 platform devicetree file
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (3 preceding siblings ...)
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 04/19] rockchip: rk3066: add clock driver for rk3066 soc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:12 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 06/19] rockchip: rk3066: add core support =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:12 UTC (permalink / raw)
  To: u-boot

rk3066 peripherials include usb, i2c, pwm, gpio, sdio, sdmmc, emmc, spi,
watchdog and uart

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- added nand dts node

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/dts/rk3066a.dtsi | 707 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 707 insertions(+)
 create mode 100644 arch/arm/dts/rk3066a.dtsi

diff --git a/arch/arm/dts/rk3066a.dtsi b/arch/arm/dts/rk3066a.dtsi
new file mode 100644
index 0000000..92ee1c2
--- /dev/null
+++ b/arch/arm/dts/rk3066a.dtsi
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3066a-cru.h>
+#include "rk3xxx.dtsi"
+
+/ {
+	compatible = "rockchip,rk3066a";
+
+	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 */
+				1416000 1300000
+				1200000 1175000
+				1008000 1125000
+				816000  1125000
+				600000  1100000
+				504000  1100000
+				312000  1075000
+			>;
+			clock-latency = <40000>;
+			clocks = <&cru ARMCLK>;
+		};
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x1>;
+		};
+	};
+
+	sram: sram at 10080000 {
+		compatible = "mmio-sram";
+		reg = <0x10080000 0x10000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x10080000 0x10000>;
+
+		smp-sram at 0 {
+			compatible = "rockchip,rk3066-smp-sram";
+			reg = <0x0 0x50>;
+		};
+	};
+
+	i2s0: i2s at 10118000 {
+		compatible = "rockchip,rk3066-i2s";
+		reg = <0x10118000 0x2000>;
+		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s0_bus>;
+		dmas = <&dmac1_s 4>, <&dmac1_s 5>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_hclk", "i2s_clk";
+		clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+		rockchip,playback-channels = <8>;
+		rockchip,capture-channels = <2>;
+		status = "disabled";
+	};
+
+	i2s1: i2s at 1011a000 {
+		compatible = "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 = <&i2s1_bus>;
+		dmas = <&dmac1_s 6>, <&dmac1_s 7>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_hclk", "i2s_clk";
+		clocks = <&cru HCLK_I2S1>, <&cru SCLK_I2S1>;
+		rockchip,playback-channels = <2>;
+		rockchip,capture-channels = <2>;
+		status = "disabled";
+	};
+
+	i2s2: i2s at 1011c000 {
+		compatible = "rockchip,rk3066-i2s";
+		reg = <0x1011c000 0x2000>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s2_bus>;
+		dmas = <&dmac1_s 9>, <&dmac1_s 10>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_hclk", "i2s_clk";
+		clocks = <&cru HCLK_I2S2>, <&cru SCLK_I2S2>;
+		rockchip,playback-channels = <2>;
+		rockchip,capture-channels = <2>;
+		status = "disabled";
+	};
+
+	nandc: nandc at 10500000 {
+		compatible = "rockchip,nandc";
+		reg = <0x10500000 0x2000>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		clock-names = "hclk";
+		clocks = <&cru HCLK_NANDC0>;
+		status = "disabled";
+	};
+
+	cru: clock-controller at 20000000 {
+		compatible = "rockchip,rk3066a-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+		u-boot,dm-pre-reloc;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		assigned-clocks = <&cru PLL_CPLL>, <&cru PLL_GPLL>,
+				  <&cru ACLK_CPU>, <&cru HCLK_CPU>,
+				  <&cru PCLK_CPU>, <&cru ACLK_PERI>,
+				  <&cru HCLK_PERI>, <&cru PCLK_PERI>;
+		assigned-clock-rates = <400000000>, <594000000>,
+				       <300000000>, <150000000>,
+				       <75000000>, <300000000>,
+				       <150000000>, <75000000>;
+	};
+
+	timer at 2000e000 {
+		compatible = "snps,dw-apb-timer-osc";
+		reg = <0x2000e000 0x100>;
+		interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_TIMER2>, <&cru PCLK_TIMER2>;
+		clock-names = "timer", "pclk";
+	};
+
+	efuse: efuse at 20010000 {
+		compatible = "rockchip,rk3066a-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>;
+		};
+	};
+
+	timer at 20038000 {
+		compatible = "snps,dw-apb-timer-osc";
+		reg = <0x20038000 0x100>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_TIMER0>, <&cru PCLK_TIMER0>;
+		clock-names = "timer", "pclk";
+	};
+
+	timer at 2003a000 {
+		compatible = "snps,dw-apb-timer-osc";
+		reg = <0x2003a000 0x100>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_TIMER1>, <&cru PCLK_TIMER1>;
+		clock-names = "timer", "pclk";
+	};
+
+	tsadc: tsadc at 20060000 {
+		compatible = "rockchip,rk3066-tsadc";
+		reg = <0x20060000 0x100>;
+		clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+		clock-names = "saradc", "apb_pclk";
+		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		resets = <&cru SRST_TSADC>;
+		reset-names = "saradc-apb";
+		status = "disabled";
+	};
+
+	usbphy: phy {
+		compatible = "rockchip,rk3066a-usb-phy", "rockchip,rk3288-usb-phy";
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+
+		usbphy0: usb-phy at 17c {
+			#phy-cells = <0>;
+			reg = <0x17c>;
+			clocks = <&cru SCLK_OTGPHY0>;
+			clock-names = "phyclk";
+			#clock-cells = <0>;
+		};
+
+		usbphy1: usb-phy at 188 {
+			#phy-cells = <0>;
+			reg = <0x188>;
+			clocks = <&cru SCLK_OTGPHY1>;
+			clock-names = "phyclk";
+			#clock-cells = <0>;
+		};
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3066a-pinctrl";
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		u-boot,dm-pre-reloc;
+
+		gpio0: gpio0 at 20034000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20034000 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>;
+		};
+
+		gpio4: gpio4 at 20084000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20084000 0x100>;
+			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO4>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio6: gpio6 at 2000a000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2000a000 0x100>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO6>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		pcfg_pull_default: pcfg_pull_default {
+			bias-pull-pin-default;
+		};
+
+		pcfg_pull_none: pcfg_pull_none {
+			bias-disable;
+		};
+
+		emac {
+			emac_xfer: emac-xfer {
+				rockchip,pins = <RK_GPIO1 16 RK_FUNC_2 &pcfg_pull_none>, /* mac_clk */
+						<RK_GPIO1 17 RK_FUNC_2 &pcfg_pull_none>, /* tx_en */
+						<RK_GPIO1 18 RK_FUNC_2 &pcfg_pull_none>, /* txd1 */
+						<RK_GPIO1 19 RK_FUNC_2 &pcfg_pull_none>, /* txd0 */
+						<RK_GPIO1 20 RK_FUNC_2 &pcfg_pull_none>, /* rx_err */
+						<RK_GPIO1 21 RK_FUNC_2 &pcfg_pull_none>, /* crs_dvalid */
+						<RK_GPIO1 22 RK_FUNC_2 &pcfg_pull_none>, /* rxd1 */
+						<RK_GPIO1 23 RK_FUNC_2 &pcfg_pull_none>; /* rxd0 */
+			};
+
+			emac_mdio: emac-mdio {
+				rockchip,pins = <RK_GPIO1 24 RK_FUNC_2 &pcfg_pull_none>, /* mac_md */
+						<RK_GPIO1 25 RK_FUNC_2 &pcfg_pull_none>; /* mac_mdclk */
+			};
+		};
+
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins = <RK_GPIO3 31 RK_FUNC_2 &pcfg_pull_default>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins = <RK_GPIO4 9 RK_FUNC_2 &pcfg_pull_default>;
+			};
+
+			emmc_rst: emmc-rst {
+				rockchip,pins = <RK_GPIO4 10 RK_FUNC_2 &pcfg_pull_default>;
+			};
+
+			/*
+			 * 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.
+			 */
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <RK_GPIO2 28 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO2 29 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <RK_GPIO2 30 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO2 31 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <RK_GPIO3 0 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <RK_GPIO3 2 RK_FUNC_2 &pcfg_pull_none>,
+						<RK_GPIO3 3 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
+						<RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm0 {
+			pwm0_out: pwm0-out {
+				rockchip,pins = <RK_GPIO0 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_out: pwm1-out {
+				rockchip,pins = <RK_GPIO0 4 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_out: pwm2-out {
+				rockchip,pins = <RK_GPIO0 30 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3 {
+			pwm3_out: pwm3-out {
+				rockchip,pins = <RK_GPIO0 31 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins = <RK_GPIO1 5 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi0_cs0: spi0-cs0 {
+				rockchip,pins = <RK_GPIO1 4 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi0_tx: spi0-tx {
+				rockchip,pins = <RK_GPIO1 7 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi0_rx: spi0-rx {
+				rockchip,pins = <RK_GPIO1 6 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi0_cs1: spi0-cs1 {
+				rockchip,pins = <RK_GPIO4 15 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins = <RK_GPIO2 19 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi1_cs0: spi1-cs0 {
+				rockchip,pins = <RK_GPIO2 20 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi1_rx: spi1-rx {
+				rockchip,pins = <RK_GPIO2 22 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi1_tx: spi1-tx {
+				rockchip,pins = <RK_GPIO2 21 RK_FUNC_2 &pcfg_pull_default>;
+			};
+			spi1_cs1: spi1-cs1 {
+				rockchip,pins = <RK_GPIO2 23 RK_FUNC_2 &pcfg_pull_default>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		uart2 {
+			uart2_xfer: uart2-xfer {
+				rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_default>;
+			};
+			/* no rts / cts for uart2 */
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			uart3_cts: uart3-cts {
+				rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			uart3_rts: uart3-rts {
+				rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		sd0 {
+			sd0_clk: sd0-clk {
+				rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd0_cmd: sd0-cmd {
+				rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd0_cd: sd0-cd {
+				rockchip,pins = <RK_GPIO3 14 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd0_wp: sd0-wp {
+				rockchip,pins = <RK_GPIO3 15 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd0_bus1: sd0-bus-width1 {
+				rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd0_bus4: sd0-bus-width4 {
+				rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 11 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 12 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 13 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		sd1 {
+			sd1_clk: sd1-clk {
+				rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd1_cmd: sd1-cmd {
+				rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd1_cd: sd1-cd {
+				rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd1_wp: sd1-wp {
+				rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd1_bus1: sd1-bus-width1 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>;
+			};
+
+			sd1_bus4: sd1-bus-width4 {
+				rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		i2s0 {
+			i2s0_bus: i2s0-bus {
+				rockchip,pins = <RK_GPIO0 7 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 8 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 9 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 10 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 11 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 12 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 13 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 14 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 15 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		i2s1 {
+			i2s1_bus: i2s1-bus {
+				rockchip,pins = <RK_GPIO0 16 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 17 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 18 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 19 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 20 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 21 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+
+		i2s2 {
+			i2s2_bus: i2s2-bus {
+				rockchip,pins = <RK_GPIO0 24 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 25 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 26 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 27 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 28 RK_FUNC_1 &pcfg_pull_default>,
+						<RK_GPIO0 29 RK_FUNC_1 &pcfg_pull_default>;
+			};
+		};
+	};
+};
+
+&grf {
+	compatible = "rockchip,rk3066-grf", "syscon";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_xfer>;
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_xfer>;
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_xfer>;
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_xfer>;
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_xfer>;
+};
+
+&mmc0 {
+	clock-frequency = <50000000>;
+	dmas = <&dmac2 1>;
+	dma-names = "rx-tx";
+	max-frequency = <50000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4>;
+	u-boot,dm-pre-reloc;
+};
+
+&mmc1 {
+	dmas = <&dmac2 3>;
+	dma-names = "rx-tx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus4>;
+};
+
+&emmc {
+	dmas = <&dmac2 4>;
+	dma-names = "rx-tx";
+};
+
+&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 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
+};
+
+&uart0 {
+	compatible = "rockchip,rk3066-uart", "snps,dw-apb-uart";
+	dmas = <&dmac1_s 0>, <&dmac1_s 1>;
+	dma-names = "tx", "rx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_xfer>;
+};
+
+&uart1 {
+	compatible = "rockchip,rk3066-uart", "snps,dw-apb-uart";
+	dmas = <&dmac1_s 2>, <&dmac1_s 3>;
+	dma-names = "tx", "rx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_xfer>;
+};
+
+&uart2 {
+	compatible = "rockchip,rk3066-uart", "snps,dw-apb-uart";
+	dmas = <&dmac2 6>, <&dmac2 7>;
+	dma-names = "tx", "rx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_xfer>;
+};
+
+&uart3 {
+	compatible = "rockchip,rk3066-uart", "snps,dw-apb-uart";
+	dmas = <&dmac2 8>, <&dmac2 9>;
+	dma-names = "tx", "rx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_xfer>;
+};
+
+&wdt {
+	compatible = "rockchip,rk3066-wdt", "snps,dw-wdt";
+};
+
+&emac {
+	compatible = "rockchip,rk3066-emac";
+};
-- 
2.7.4

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

* [U-Boot] [PATCH v4 06/19] rockchip: rk3066: add core support
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (4 preceding siblings ...)
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 05/19] rockchip: rk3066: add rk3066 platform devicetree file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:13 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:26   ` [U-Boot] [U-Boot,v4,06/19] " Philipp Tomsich
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 07/19] rockchip: rk3066: add mk808 board files =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:13 UTC (permalink / raw)
  To: u-boot

Add core skeleton for rk3066

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- updated to shifted masks
- moved syscon.h below spl.h
- changed error to debug and return error reason
- changed Cortex-A7 to Cortex-A9
- added nand support
- added dfu support
- removed dram_init
- reset timer before enable
- moved configs to board config file
- moved arm clk setup to tpl
- moved ddr setup to tpl
- moved to boot device bootrom

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/mach-rockchip/Kconfig                |  16 +++
 arch/arm/mach-rockchip/Makefile               |   4 +
 arch/arm/mach-rockchip/rk3066-board-spl.c     | 139 ++++++++++++++++++++++++
 arch/arm/mach-rockchip/rk3066-board-tpl.c     |  90 ++++++++++++++++
 arch/arm/mach-rockchip/rk3066-board.c         | 150 ++++++++++++++++++++++++++
 arch/arm/mach-rockchip/rk3066/Kconfig         |  31 ++++++
 arch/arm/mach-rockchip/rk3066/Makefile        |   8 ++
 arch/arm/mach-rockchip/rk3066/clk_rk3066.c    |  33 ++++++
 arch/arm/mach-rockchip/rk3066/syscon_rk3066.c |  54 ++++++++++
 include/configs/rk3066_common.h               |  99 +++++++++++++++++
 10 files changed, 624 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/rk3066-board-spl.c
 create mode 100644 arch/arm/mach-rockchip/rk3066-board-tpl.c
 create mode 100644 arch/arm/mach-rockchip/rk3066-board.c
 create mode 100644 arch/arm/mach-rockchip/rk3066/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rk3066/Makefile
 create mode 100644 arch/arm/mach-rockchip/rk3066/clk_rk3066.c
 create mode 100644 arch/arm/mach-rockchip/rk3066/syscon_rk3066.c
 create mode 100644 include/configs/rk3066_common.h

diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index d9b25d5..810353f 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_RK3066
+	bool "Support Rockchip RK3066"
+	select CPU_V7
+	select SUPPORT_SPL
+	select SUPPORT_TPL
+	select SPL
+	select TPL
+	select BOARD_LATE_INIT
+	select ROCKCHIP_BROM_HELPER
+	help
+	  The Rockchip RK3066 is a ARM-based SoC with a dual-core Cortex-A9
+	  including NEON and GPU, Mali-400 graphics, several DDR3 options
+	  and video codec support. Peripherals include ethernet, USB2 host
+	  and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
+
 config ROCKCHIP_RK3188
 	bool "Support Rockchip RK3188"
 	select CPU_V7
@@ -164,6 +179,7 @@ config SPL_MMC_SUPPORT
 	default y if !SPL_ROCKCHIP_BACK_TO_BROM
 
 source "arch/arm/mach-rockchip/rk3036/Kconfig"
+source "arch/arm/mach-rockchip/rk3066/Kconfig"
 source "arch/arm/mach-rockchip/rk3188/Kconfig"
 source "arch/arm/mach-rockchip/rk322x/Kconfig"
 source "arch/arm/mach-rockchip/rk3288/Kconfig"
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 79e9704..ae878ef 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -11,10 +11,12 @@
 obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
 obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
 
+obj-tpl-$(CONFIG_ROCKCHIP_RK3066) += rk3066-board-tpl.o
 obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
 obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o
 
 obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
+obj-spl-$(CONFIG_ROCKCHIP_RK3066) += rk3066-board-spl.o
 obj-spl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
 obj-spl-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board-spl.o
 obj-spl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
@@ -22,6 +24,7 @@ obj-spl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-spl.o spl-boot-order.o
 obj-spl-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o spl-boot-order.o
 
 ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
+obj-$(CONFIG_ROCKCHIP_RK3066) += rk3066-board.o
 obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
 obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
@@ -35,6 +38,7 @@ obj-y += rk_timer.o
 endif
 
 obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
+obj-$(CONFIG_ROCKCHIP_RK3066) += rk3066/
 ifndef CONFIG_TPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188/
 endif
diff --git a/arch/arm/mach-rockchip/rk3066-board-spl.c b/arch/arm/mach-rockchip/rk3066-board-spl.c
new file mode 100644
index 0000000..9acdd83
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066-board-spl.c
@@ -0,0 +1,139 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <clk.h>
+#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 <syscon.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/bootrom.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>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_NAND;
+}
+
+void board_init_f(ulong dummy)
+{
+	struct udevice *pinctrl, *dev;
+	int ret;
+
+	debug_uart_init();
+
+	ret = spl_early_init();
+	if (ret) {
+		debug("spl_early_init() failed: %d\n", ret);
+		hang();
+	}
+
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("Pinctrl init failed: %d\n", ret);
+		return;
+	}
+
+	ret = rockchip_get_clk(&dev);
+	if (ret) {
+		debug("CLK init failed: %d\n", ret);
+		return;
+	}
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return;
+	}
+}
+
+void spl_board_init(void)
+{
+	struct udevice *pinctrl;
+	int ret;
+
+	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();
+
+	return;
+
+err:
+	debug("spl_board_init: Error %d\n", ret);
+
+	/* No way to report error here */
+	hang();
+}
+
+#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+#include <usb.h>
+#include <usb/dwc2_udc.h>
+
+static struct dwc2_plat_otg_data rk3066_otg_data = {
+	.rx_fifo_sz	= 275,
+	.np_tx_fifo_sz	= 16,
+	.tx_fifo_sz	= 256,
+};
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	ofnode otg_node;
+	u32 reg;
+
+	otg_node = ofnode_path("/usb at 10180000");
+	if (!ofnode_valid(otg_node)) {
+		debug("Not found usb otg device\n");
+		return -ENODEV;
+	}
+
+	ofnode_read_u32(otg_node, "reg", &reg);
+	rk3066_otg_data.regs_otg = reg;
+
+	return dwc2_udc_probe(&rk3066_otg_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3066-board-tpl.c b/arch/arm/mach-rockchip/rk3066-board-tpl.c
new file mode 100644
index 0000000..5dcac90
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066-board-tpl.c
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/bootrom.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/ddr_rk3188.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/grf_rk3066.h>
+#include <asm/arch/pmu_rk3188.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define RK3066_TIMER_CONTROL	0x8
+#define GRF_BASE	0x20008000
+
+static int setup_arm_clock(void)
+{
+	struct udevice *dev;
+	struct clk clk;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ret;
+
+	clk.id = CLK_ARM;
+	ret = clk_request(dev, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_set_rate(&clk, 600000000);
+
+	clk_free(&clk);
+	return ret;
+}
+
+void board_init_f(ulong dummy)
+{
+	struct rk3066_grf * const grf = (void *)GRF_BASE;
+	struct udevice *dev;
+	int ret;
+
+	/* Enable early UART on the RK3066 */
+	rk_clrsetreg(&grf->gpio1b_iomux,
+		     GPIO1B1_MASK | GPIO1B0_MASK,
+		     GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
+		     GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
+
+	debug_uart_init();
+
+	printascii("U-Boot TPL board init\n");
+
+	ret = spl_early_init();
+	if (ret) {
+		debug("spl_early_init() failed: %d\n", ret);
+		hang();
+	}
+
+	/* Reset and enable Timer0 */
+	writel(0, CONFIG_SYS_TIMER_BASE);
+	rk_clrsetreg(CONFIG_SYS_TIMER_BASE + RK3066_TIMER_CONTROL, 0x1, 0x1);
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return;
+	}
+
+	setup_arm_clock();
+}
+
+void board_return_to_bootrom(void)
+{
+	back_to_bootrom();
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_BOOTROM;
+}
diff --git a/arch/arm/mach-rockchip/rk3066-board.c b/arch/arm/mach-rockchip/rk3066-board.c
new file mode 100644
index 0000000..8fa06a2
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066-board.c
@@ -0,0 +1,150 @@
+/*
+ * (C) Copyright 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * 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/grf_rk3066.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3188.h>
+#include <asm/arch/boot_mode.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_late_init(void)
+{
+	struct rk3066_grf *grf;
+
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	if (IS_ERR(grf)) {
+		debug("grf syscon returned %ld\n", PTR_ERR(grf));
+		return PTR_ERR(grf);
+	}
+	/* enable noc remap to mimic legacy loaders */
+	rk_clrsetreg(&grf->soc_con0, NOC_REMAP_MASK, NOC_REMAP_MASK);
+
+	return 0;
+}
+
+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:
+	debug("board_init: Error %d\n", ret);
+
+	/* No way to report error here */
+	hang();
+
+	return -1;
+#else
+	return 0;
+#endif
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
+
+#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
+#include <usb.h>
+#include <usb/dwc2_udc.h>
+
+static struct dwc2_plat_otg_data rk3066_otg_data = {
+	.rx_fifo_sz	= 275,
+	.np_tx_fifo_sz	= 16,
+	.tx_fifo_sz	= 256,
+};
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	int node, phy_node;
+	const char *mode;
+	bool matched = false;
+	const void *blob = gd->fdt_blob;
+	u32 grf_phy_offset;
+
+	/* find the usb_otg node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					"rockchip,rk3066-usb");
+
+	while (node > 0) {
+		mode = fdt_getprop(blob, node, "dr_mode", NULL);
+		if (mode && strcmp(mode, "otg") == 0) {
+			matched = true;
+			break;
+		}
+
+		node = fdt_node_offset_by_compatible(blob, node,
+					"rockchip,rk3066-usb");
+	}
+	if (!matched) {
+		debug("Not found usb_otg device\n");
+		return -ENODEV;
+	}
+	rk3066_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+
+	node = fdtdec_lookup_phandle(blob, node, "phys");
+	if (node <= 0) {
+		debug("Not found usb phy device\n");
+		return -ENODEV;
+	}
+
+	phy_node = fdt_parent_offset(blob, node);
+	if (phy_node <= 0) {
+		debug("Not found usb phy device\n");
+		return -ENODEV;
+	}
+
+	rk3066_otg_data.phy_of_node = phy_node;
+	grf_phy_offset = fdtdec_get_addr(blob, node, "reg");
+
+	node = fdt_node_offset_by_compatible(blob, -1,
+					"rockchip,rk3066-grf");
+	if (node <= 0) {
+		debug("Not found grf device\n");
+		return -ENODEV;
+	}
+	rk3066_otg_data.regs_phy = grf_phy_offset +
+				fdtdec_get_addr(blob, node, "reg");
+
+	return dwc2_udc_probe(&rk3066_otg_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3066/Kconfig b/arch/arm/mach-rockchip/rk3066/Kconfig
new file mode 100644
index 0000000..b5277fe
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066/Kconfig
@@ -0,0 +1,31 @@
+if ROCKCHIP_RK3066
+
+config TARGET_MK808_RK3066
+        bool "MK808_RK3066"
+	help
+	  MK808 is a tv stick with usb host and otg, microsd card slot, hdmi and wifi.
+
+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_LIBGENERIC_SUPPORT
+        default y
+
+source "board/rikomagic/mk808_rk3066/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/rk3066/Makefile b/arch/arm/mach-rockchip/rk3066/Makefile
new file mode 100644
index 0000000..61b7fd4
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y += clk_rk3066.o
+obj-y += syscon_rk3066.o
diff --git a/arch/arm/mach-rockchip/rk3066/clk_rk3066.c b/arch/arm/mach-rockchip/rk3066/clk_rk3066.c
new file mode 100644
index 0000000..ae52902
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066/clk_rk3066.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 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_rk3066.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_GET_DRIVER(rockchip_rk3066a_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct rk3066_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/rk3066/syscon_rk3066.c b/arch/arm/mach-rockchip/rk3066/syscon_rk3066.c
new file mode 100644
index 0000000..57b2376
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066/syscon_rk3066.c
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2015 Rockchip Electronics Co., Ltd
+ *
+ * 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 rk3066_syscon_ids[] = {
+	{ .compatible = "rockchip,rk3188-noc", .data = ROCKCHIP_SYSCON_NOC },
+	{ .compatible = "rockchip,rk3066-grf", .data = ROCKCHIP_SYSCON_GRF },
+	{ .compatible = "rockchip,rk3066-pmu", .data = ROCKCHIP_SYSCON_PMU },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_rk3066) = {
+	.name = "rk3066_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3066_syscon_ids,
+};
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int rk3066_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 = rk3066_syscon_ids,
+	.bind = rk3066_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3066_grf) = {
+	.name = "rockchip_rk3066_grf",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3066_syscon_ids + 1,
+	.bind = rk3066_syscon_bind_of_platdata,
+};
+
+U_BOOT_DRIVER(rockchip_rk3066_pmu) = {
+	.name = "rockchip_rk3066_pmu",
+	.id = UCLASS_SYSCON,
+	.of_match = rk3066_syscon_ids + 2,
+	.bind = rk3066_syscon_bind_of_platdata,
+};
+#endif
diff --git a/include/configs/rk3066_common.h b/include/configs/rk3066_common.h
new file mode 100644
index 0000000..3d8c9e8
--- /dev/null
+++ b/include/configs/rk3066_common.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_RK3066_COMMON_H
+#define __CONFIG_RK3066_COMMON_H
+
+#include <asm/arch/hardware.h>
+#include "rockchip-common.h"
+
+#define CONFIG_SKIP_LOWLEVEL_INIT_ONLY
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE			0x2000
+#define CONFIG_SYS_MAXARGS		16
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_MALLOC_LEN		(64 << 20)
+#define CONFIG_SYS_CBSIZE		256
+
+#define CONFIG_SYS_SDRAM_BASE		0x60000000
+#define CONFIG_NR_DRAM_BANKS		1
+#define SDRAM_BANK_SIZE			(1024UL << 20UL)
+#define SDRAM_MAX_SIZE			CONFIG_NR_DRAM_BANKS * SDRAM_BANK_SIZE
+
+#define CONFIG_SYS_TIMER_RATE		24000000
+#define CONFIG_SYS_TIMER_BASE		0x20038000
+#define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 4)
+#define CONFIG_SYS_TIMER_COUNTS_DOWN
+
+#define CONFIG_SYS_TEXT_BASE		0x60408000
+#define CONFIG_SYS_INIT_SP_ADDR		0x78000000
+#define CONFIG_SYS_LOAD_ADDR		0x70800800
+
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_SPL_FRAMEWORK
+
+#define CONFIG_SYS_MAX_NAND_DEVICE	8
+
+#ifdef CONFIG_TPL_BUILD
+#define CONFIG_SPL_TEXT_BASE		0x10080C04
+#define CONFIG_SPL_STACK		0x1008FFFF
+/* tpl size max 32kb - 4byte RK30 header */
+#define CONFIG_SPL_MAX_SIZE		(0x8000 - 0x4)
+#elif defined(CONFIG_SPL_BUILD)
+/* spl size max 200k */
+#define CONFIG_SPL_MAX_SIZE		0x32000
+#define CONFIG_SPL_TEXT_BASE		0x60000000
+#define CONFIG_SPL_STACK		0x1008FFFF
+#define CONFIG_SPL_BOARD_INIT
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_LOAD
+#define CONFIG_SPL_NAND_ECC
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_INIT
+#define CONFIG_SPL_NAND_BBT
+#define CONFIG_SPL_NAND_IDS
+#define CONFIG_SPL_NAND_UTIL
+#define CONFIG_SPL_NAND_RAW_ONLY
+#define CONFIG_SYS_NAND_U_BOOT_START	CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_NAND_U_BOOT_DST	CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	0x80000
+#define CONFIG_EXTRA_ENV_SETTINGS ROCKCHIP_DEVICE_SETTINGS
+#define CONFIG_MTD_DEVICE
+#endif
+
+#include <config_distro_defaults.h>
+
+#ifndef CONFIG_SPL_BUILD
+
+#define CONFIG_USB_FUNCTION_MASS_STORAGE
+
+#define CONFIG_MTD_DEVICE
+#define MTDIDS_DEFAULT			"nand0=rockchip-nand.0"
+
+#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>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"fdt_high=0x6fffffff\0" \
+	"initrd_high=0x6fffffff\0" \
+	"partitions=" PARTS_DEFAULT \
+	"mtdids=" MTDIDS_DEFAULT "\0" \
+	ENV_MEM_LAYOUT_SETTINGS \
+	ROCKCHIP_DEVICE_SETTINGS \
+	BOOTENV
+
+#endif
+
+#define CONFIG_PREBOOT
+
+#endif
-- 
2.7.4

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

* [U-Boot] [PATCH v4 07/19] rockchip: rk3066: add mk808 board files
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (5 preceding siblings ...)
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 06/19] rockchip: rk3066: add core support =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:13 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 08/19] rockchip: rk3066: add sdram driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:13 UTC (permalink / raw)
  To: u-boot

mk808 is a tv stick with two usb ports, micro sd card slot, hdmi and
nand onboard.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- added nand support
- dropped spl of-platdata

Changes since v2:
- fixed dfu ram config

Changes since v3:
- none

 arch/arm/dts/Makefile                       |   1 +
 arch/arm/dts/rk3066a-mk808.dts              | 189 ++++++++++++++++++++++++++++
 board/rikomagic/mk808_rk3066/Kconfig        |  15 +++
 board/rikomagic/mk808_rk3066/MAINTAINERS    |   6 +
 board/rikomagic/mk808_rk3066/Makefile       |   7 ++
 board/rikomagic/mk808_rk3066/mk808_rk3066.c |  10 ++
 configs/mk808_defconfig                     | 114 +++++++++++++++++
 include/configs/mk808_rk3066.h              |  61 +++++++++
 8 files changed, 403 insertions(+)
 create mode 100644 arch/arm/dts/rk3066a-mk808.dts
 create mode 100644 board/rikomagic/mk808_rk3066/Kconfig
 create mode 100644 board/rikomagic/mk808_rk3066/MAINTAINERS
 create mode 100644 board/rikomagic/mk808_rk3066/Makefile
 create mode 100644 board/rikomagic/mk808_rk3066/mk808_rk3066.c
 create mode 100644 configs/mk808_defconfig
 create mode 100644 include/configs/mk808_rk3066.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 2cbdb17..fd4bb4f 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 \
+	rk3066a-mk808.dtb \
 	rk3188-radxarock.dtb \
 	rk3288-evb.dtb \
 	rk3288-fennec.dtb \
diff --git a/arch/arm/dts/rk3066a-mk808.dts b/arch/arm/dts/rk3066a-mk808.dts
new file mode 100644
index 0000000..0a452d7
--- /dev/null
+++ b/arch/arm/dts/rk3066a-mk808.dts
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ or X11
+ */
+
+/dts-v1/;
+#include "rk3066a.dtsi"
+
+/ {
+	model = "Rikomagic MK808";
+	compatible = "rikomagic,mk808", "rockchip,rk3066a";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory at 60000000 {
+		reg = <0x60000000 0x40000000>;
+		device_type = "memory";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		blue {
+			label = "mk808:blue:power";
+			gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "default-on";
+		};
+	};
+
+	vcc_io: vcc-io {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_io";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_host: usb-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&host_drv>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-name = "host-pwr";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_otg: usb-otg-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&otg_drv>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-name = "vcc_otg";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_sd: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
+		pinctrl-0 = <&sdmmc_pwr>;
+		pinctrl-names = "default";
+		regulator-name = "vcc_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_wifi: sdio-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&wifi_pwr>;
+		pinctrl-names = "default";
+		regulator-name = "vcc_wifi";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+};
+
+&dmc {
+	compatible = "rockchip,rk3066-dmc", "syscon";
+	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>;
+};
+
+&mmc0 {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	num-slots = <1>;
+	vmmc-supply = <&vcc_sd>;
+	status = "okay";
+};
+
+&mmc1 {
+	bus-width = <4>;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
+	pinctrl-names = "default";
+	vmmc-supply = <&vcc_wifi>;
+	status = "okay";
+};
+
+&nandc {
+	u-boot,dm-spl;
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	nand at 0 {
+		u-boot,dm-spl;
+		reg = <0>;
+		nand-ecc-mode = "hw_syndrome";
+		nand-ecc-strength = <40>;
+		nand-ecc-step-size = <1024>;
+		rockchip,protect-bootrom-blocks;
+	};
+};
+
+&pinctrl {
+	usb-host {
+		host_drv: host-drv {
+			rockchip,pins = <RK_GPIO0 6 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	usb-otg {
+		otg_drv: otg-drv {
+			rockchip,pins = <RK_GPIO0 5 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <RK_GPIO3 7 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	sdio {
+		wifi_pwr: wifi-pwr {
+			rockchip,pins = <RK_GPIO3 24 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&uart2 {
+	status = "okay";
+	u-boot,dm-pre-reloc;
+};
+
+&usb_host {
+	status = "okay";
+};
+
+&usb_otg {
+	u-boot,dm-spl;
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/board/rikomagic/mk808_rk3066/Kconfig b/board/rikomagic/mk808_rk3066/Kconfig
new file mode 100644
index 0000000..0da0a17
--- /dev/null
+++ b/board/rikomagic/mk808_rk3066/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_MK808_RK3066
+
+config SYS_BOARD
+	default "mk808_rk3066"
+
+config SYS_VENDOR
+	default "rikomagic"
+
+config SYS_CONFIG_NAME
+	default "mk808_rk3066"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+
+endif
diff --git a/board/rikomagic/mk808_rk3066/MAINTAINERS b/board/rikomagic/mk808_rk3066/MAINTAINERS
new file mode 100644
index 0000000..65b5cbd
--- /dev/null
+++ b/board/rikomagic/mk808_rk3066/MAINTAINERS
@@ -0,0 +1,6 @@
+MK808
+M:	Paweł Jarosz <paweljarosz3691@gmail.com>
+S:	Maintained
+F:	include/configs/mk808_rk3066.h
+F:	configs/mk808-rk3066_defconfig
+F:	board/rikomagic/mk808_rk3066
diff --git a/board/rikomagic/mk808_rk3066/Makefile b/board/rikomagic/mk808_rk3066/Makefile
new file mode 100644
index 0000000..ef5ba56
--- /dev/null
+++ b/board/rikomagic/mk808_rk3066/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2017 Paweł‚ Jarosz <paweljarosz3691@gmail.com>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y	+= mk808_rk3066.o
diff --git a/board/rikomagic/mk808_rk3066/mk808_rk3066.c b/board/rikomagic/mk808_rk3066/mk808_rk3066.c
new file mode 100644
index 0000000..e5d66fe
--- /dev/null
+++ b/board/rikomagic/mk808_rk3066/mk808_rk3066.c
@@ -0,0 +1,10 @@
+/*
+ * (C) Copyright 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
diff --git a/configs/mk808_defconfig b/configs/mk808_defconfig
new file mode 100644
index 0000000..ab67e4f
--- /dev/null
+++ b/configs/mk808_defconfig
@@ -0,0 +1,114 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_ROCKCHIP_RK3066=y
+CONFIG_TARGET_MK808_RK3066=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3066a-mk808"
+CONFIG_CMD_REGULATOR=y
+CONFIG_CLK=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_RAM=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
+CONFIG_SYS_NS16550=y
+CONFIG_BOOTDELAY=1
+CONFIG_CONSOLE_MUX=y
+CONFIG_DISPLAY_BOARDINFO=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_CMD_BOOTZ=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_CACHE=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_SYSRESET=y
+CONFIG_CMD_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_DM_MMC=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_EFI_PARTITION is not set
+CONFIG_CMD_BOOTEFI is not set
+CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set
+CONFIG_EFI_LOADER is not set
+CONFIG_CMD_GPIO=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_GENERIC=y
+CONFIG_PINCTRL_ROCKCHIP_RK3066=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0x20064000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_STORAGE=y
+CONFIG_CMD_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DWC2_OTG_PHY=y
+CONFIG_USB_GADGET_VBUS_DRAW=500 
+CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x300a
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_MTD_DEVICE=y
+CONFIG_NAND_ROCKCHIP=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_NAND=y
+CONFIG_DFU_NAND=y
+CONFIG_USB_FUNCTION_DFU=y
+CONFIG_DFU_RAM=y
+CONFIG_CMD_DFU=y
+CONFIG_SPL_BLK=y
+CONFIG_SPL_CLK=y
+CONFIG_SPL_DFU_RAM=y
+CONFIG_SPL_DFU_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_SPL_ENV_SUPPORT=y
+CONFIG_SPL_MTD_SUPPORT=y
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_SPL_RAM=y
+CONFIG_SPL_RAM_SUPPORT=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_ADDR=0x70000000
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x200000
+CONFIG_SPL_SYSCON=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_SPL_USB_GADGET_SUPPORT=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+# CONFIG_SPL_USE_ARCH_MEMCPY is not set
+# CONFIG_SPL_USE_ARCH_MEMSET is not set
+# CONFIG_SPL_SIMPLE_BUS is not set
+# CONFIG_SPL_PINCTRL_FULL is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+# CONFIG_SPL_BOARD_INIT is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EXT_SUPPORT is not set
+# CONFIG_SPL_LIBDISK_SUPPORT is not set
+# CONFIG_SPL_MMC_SUPPORT is not set
+CONFIG_TPL_BOOTROM_SUPPORT=y
+CONFIG_TPL_CLK=y
+CONFIG_TPL_DM=y
+CONFIG_TPL_DM_SERIAL=y
+# CONFIG_TPL_DRIVERS_MISC_SUPPORT is not set
+CONFIG_TPL_OF_CONTROL=y
+CONFIG_TPL_OF_PLATDATA=y
+CONFIG_TPL_RAM=y
+CONFIG_TPL_REGMAP=y
+CONFIG_TPL_ROCKCHIP_BACK_TO_BROM=y
+CONFIG_TPL_SERIAL_SUPPORT=y
+CONFIG_TPL_SYSCON=y
+CONFIG_TPL_TINY_MEMSET=y
diff --git a/include/configs/mk808_rk3066.h b/include/configs/mk808_rk3066.h
new file mode 100644
index 0000000..d6b1fc8
--- /dev/null
+++ b/include/configs/mk808_rk3066.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+/*
+ * Using bootrom layout for rockchip-idb* and spl*. Size is nand erase size.
+ */
+#define MTDPARTS_DEFAULT \
+		"mtdparts=rockchip-nand.0:" \
+			"4M(idb)," \
+			"4M(idb.backup)," \
+			"4M(spl)," \
+			"4M(spl.backup1)," \
+			"4M(spl.backup2)," \
+			"4M(spl.backup3)," \
+			"4M(spl.backup4)," \
+			"4M(u-boot)," \
+			"4M(u-boot.backup)," \
+			"4M(u-boot-env)," \
+			"4M(u-boot-env.backup)," \
+			"16M(kernel)," \
+			"32M(initrd)," \
+			"-(rootfs)"
+
+#define DFU_ALT_INFO_NAND \
+		"idb raw 0x0 0x400000;" \
+		"idb.backup raw 0x400000 0x400000;" \
+		"spl raw 0x800000 0x400000;" \
+		"spl.backup1 raw 0xC00000 0x400000;" \
+		"spl.backup2 raw 0x1000000 0x400000;" \
+		"spl.backup3 raw 0x1400000 0x400000;" \
+		"spl.backup4 raw 0x1800000 0x400000;" \
+		"u-boot raw 0x1C00000 0x400000;" \
+		"u-boot.backup raw 0x2000000 0x400000;" \
+		"u-boot-env raw 0x2400000 0x400000;" \
+		"u-boot-env.backup raw 0x2800000 0x400000;" \
+		"kernel raw 0x2C00000 0x1000000;" \
+		"initrd raw 0x3C00000 0x2000000"
+
+#define DFU_ALT_INFO_RAM \
+	"tpl.bin ram 0x10080C00 0x10000;" \
+	"spl.bin ram 0x60000000 0x40000;" \
+	"u-boot.bin ram 0x60408000 0x80000"
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+	"mtdparts=" MTDPARTS_DEFAULT "\0" \
+	"dfu_alt_info=" DFU_ALT_INFO_NAND "\0" \
+	"dfu_alt_info_ram=" DFU_ALT_INFO_RAM "\0"
+
+#define CONFIG_SYS_DFU_DATA_BUF_SIZE		SZ_4M
+#define CONFIG_SYS_NAND_U_BOOT_OFFS		0x01c00000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND	0x02000000
+
+#include <configs/rk3066_common.h>
+
+#endif
+
-- 
2.7.4

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

* [U-Boot] [PATCH v4 08/19] rockchip: rk3066: add sdram driver
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (6 preceding siblings ...)
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 07/19] rockchip: rk3066: add mk808 board files =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:13 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:34   ` [U-Boot] [U-Boot,v4,08/19] " Philipp Tomsich
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:13 UTC (permalink / raw)
  To: u-boot

Add rockchip rk3066 sdram driver

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- use common rockchip_sdram_size
- moved sdram init from sdram_init.c

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/mach-rockchip/rk3066/Makefile       |   1 +
 arch/arm/mach-rockchip/rk3066/sdram_rk3066.c | 943 +++++++++++++++++++++++++++
 2 files changed, 944 insertions(+)
 create mode 100644 arch/arm/mach-rockchip/rk3066/sdram_rk3066.c

diff --git a/arch/arm/mach-rockchip/rk3066/Makefile b/arch/arm/mach-rockchip/rk3066/Makefile
index 61b7fd4..7663b6a 100644
--- a/arch/arm/mach-rockchip/rk3066/Makefile
+++ b/arch/arm/mach-rockchip/rk3066/Makefile
@@ -5,4 +5,5 @@
 #
 
 obj-y += clk_rk3066.o
+obj-y += sdram_rk3066.o
 obj-y += syscon_rk3066.o
diff --git a/arch/arm/mach-rockchip/rk3066/sdram_rk3066.c b/arch/arm/mach-rockchip/rk3066/sdram_rk3066.c
new file mode 100644
index 0000000..e7475b8
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3066/sdram_rk3066.c
@@ -0,0 +1,943 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ *
+ * Adapted from the very similar rk3188 ddr init.
+ */
+
+#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_rk3066.h>
+#include <asm/arch/ddr_rk3188.h>
+#include <asm/arch/grf_rk3066.h>
+#include <asm/arch/pmu_rk3188.h>
+#include <asm/arch/sdram.h>
+#include <asm/arch/sdram_common.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 rk3066_cru *cru;
+	struct rk3066_grf *grf;
+	struct rk3066_sgrf *sgrf;
+	struct rk3188_pmu *pmu;
+};
+
+struct rk3066_sdram_params {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_rockchip_rk3066_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;
+};
+
+const int ddrconf_table[] = {
+	/*
+	 * [5:4] row(13+n)
+	 * [1:0] col(9+n), assume bw=2
+	 * row	    col,bw
+	 */
+	0,
+	(2 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT,
+	(1 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT,
+	(0 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT,
+	(2 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT,
+	(1 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT,
+	(0 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT,
+	(1 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT,
+	(0 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+};
+
+#define TEST_PATTEN	0x5aa5f00f
+#define DQS_GATE_TRAINING_ERROR_RANK0	(1 << 4)
+#define DQS_GATE_TRAINING_ERROR_RANK1	(2 << 4)
+
+#ifdef CONFIG_TPL_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 rk3066_cru *cru, u32 ch, u32 ctl, u32 phy)
+{
+	u32 phy_ctl_srstn_shift = 13;
+	u32 ctl_psrstn_shift = 11;
+	u32 ctl_srstn_shift = 10;
+	u32 phy_psrstn_shift = 9;
+	u32 phy_srstn_shift = 8;
+
+	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 rk3066_cru *cru, u32 ch, u32 n)
+{
+	u32 phy_ctl_srstn_shift = 13;
+
+	rk_clrsetreg(&cru->cru_softrst_con[5],
+		     1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift);
+}
+
+static void phy_pctrl_reset(struct rk3066_cru *cru,
+			    struct rk3288_ddr_publ *publ,
+			    int 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_ddr3_mode(struct rk3066_grf *grf, uint channel,
+			      bool ddr3_mode)
+{
+	uint mask, val;
+
+	mask = MSCH4_MAINDDR3_MASK << MSCH4_MAINDDR3_SHIFT;
+	val = ddr3_mode << MSCH4_MAINDDR3_SHIFT;
+	rk_clrsetreg(&grf->soc_con2, mask, val);
+}
+
+static void ddr_rank_2_row15en(struct rk3066_grf *grf, bool enable)
+{
+	uint mask, val;
+
+	mask = RANK_TO_ROW15_EN_MASK << RANK_TO_ROW15_EN_SHIFT;
+	val = enable << RANK_TO_ROW15_EN_SHIFT;
+	rk_clrsetreg(&grf->soc_con2, mask, val);
+}
+
+static void pctl_cfg(int channel, struct rk3288_ddr_pctl *pctl,
+		     struct rk3066_sdram_params *sdram_params,
+		     struct rk3066_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);
+		break;
+	}
+
+	setbits_le32(&pctl->scfg, 1);
+}
+
+static void phy_cfg(const struct chan_info *chan, int channel,
+		    struct rk3066_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, int channel,
+				u32 n, struct rk3066_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);
+		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);
+		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, int channel,
+			 struct rk3066_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 rk3066_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 rk3066_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]);
+}
+
+static int sdram_rank_bw_detect(struct dram_info *dram, int channel,
+		struct rk3066_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 (data_training(chan, channel, sdram_params) < 0) {
+		debug("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)) {
+			debug("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 &&
+	    (data_training(chan, channel, sdram_params) < 0)) {
+		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);
+		}
+		debug("2nd data training failed!");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * Detect ram columns and rows.
+ * @dram: dram info struct
+ * @channel: channel number to handle
+ * @sdram_params: sdram parameters, function will fill in col and row values
+ *
+ * Returns 0 or negative on error.
+ */
+static int sdram_col_row_detect(struct dram_info *dram, int channel,
+		struct rk3066_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) {
+		debug("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 rk3066*/
+	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) {
+		debug("Row detect error\n");
+		ret = -EINVAL;
+	} else {
+		sdram_params->ch[channel].cs1_row = row;
+		sdram_params->ch[channel].row_3_4 = 0;
+		debug("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 rk3066_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) {
+		debug("niu config not found\n");
+		ret = -EINVAL;
+	} else {
+		debug("niu config %d\n", i);
+		sdram_params->base.ddrconfig = i;
+	}
+
+	return ret;
+}
+
+static int sdram_init(struct dram_info *dram,
+		      struct rk3066_sdram_params *sdram_params)
+{
+	int channel;
+	int zqcr;
+	int ret;
+
+	if ((sdram_params->base.dramtype == DDR3 &&
+	     sdram_params->base.ddr_freq > 800000000)) {
+		debug("SDRAM frequency is too high!");
+		return -E2BIG;
+	}
+
+	ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq);
+	if (ret) {
+		debug("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);
+	debug("%s done\n", __func__);
+
+	return 0;
+error:
+	debug("DRAM init failed!\n");
+	hang();
+}
+#endif /* CONFIG_TPL_BUILD */
+
+#ifdef CONFIG_TPL_BUILD
+static int setup_sdram(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct rk3066_sdram_params *params = dev_get_platdata(dev);
+
+	return sdram_init(priv, params);
+}
+
+static int rk3066_dmc_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk3066_sdram_params *params = dev_get_platdata(dev);
+	const void *blob = gd->fdt_blob;
+	int node = dev_of_offset(dev);
+	int ret;
+
+	/* rk3066 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) {
+		debug("%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) {
+		debug("%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) {
+		debug("%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_TPL_BUILD */
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+	struct rk3066_sdram_params *plat = dev_get_platdata(dev);
+	struct dtd_rockchip_rk3066_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));
+	/* rk3066 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 rk3066_dmc_probe(struct udevice *dev)
+{
+#ifdef CONFIG_TPL_BUILD
+	struct rk3066_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_TPL_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_TPL_BUILD
+	ret = setup_sdram(dev);
+	if (ret)
+		return ret;
+#endif
+	priv->info.base = CONFIG_SYS_SDRAM_BASE;
+	priv->info.size = rockchip_sdram_size(
+				(phys_addr_t)&priv->pmu->sys_reg[2]);
+
+	return 0;
+}
+
+static int rk3066_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 rk3066_dmc_ops = {
+	.get_info = rk3066_dmc_get_info,
+};
+
+static const struct udevice_id rk3066_dmc_ids[] = {
+	{ .compatible = "rockchip,rk3066-dmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(dmc_rk3066) = {
+	.name = "rockchip_rk3066_dmc",
+	.id = UCLASS_RAM,
+	.of_match = rk3066_dmc_ids,
+	.ops = &rk3066_dmc_ops,
+#ifdef CONFIG_TPL_BUILD
+	.ofdata_to_platdata = rk3066_dmc_ofdata_to_platdata,
+#endif
+	.probe = rk3066_dmc_probe,
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+#ifdef CONFIG_TPL_BUILD
+	.platdata_auto_alloc_size = sizeof(struct rk3066_sdram_params),
+#endif
+};
-- 
2.7.4

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

* [U-Boot] [PATCH v4 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (7 preceding siblings ...)
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 08/19] rockchip: rk3066: add sdram driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:13 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 more replies)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 10/19] mtd: nand: add the rockchip nand controller driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (10 subsequent siblings)
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:13 UTC (permalink / raw)
  To: u-boot

Sandisk SDTNQGAMA is a 8GB size, 3.3V 8 bit chip with 16KB page size, 1KB write size and 40 bit ecc support

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- none

 drivers/mtd/nand/nand_ids.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index d36f900..7bd9f7d 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -58,6 +58,9 @@ struct nand_flash_dev nand_flash_ids[] = {
 	{"TC58NVG6D2 64G 3.3V 8-bit",
 		{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} },
 		  SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) },
+	{"SDTNQGAMA 64G 3.3V 8-bit",
+		{ .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x57} },
+		  SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },
 	{"SDTNRGAMA 64G 3.3V 8-bit",
 		{ .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} },
 		  SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },
-- 
2.7.4

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

* [U-Boot] [PATCH v4 10/19] mtd: nand: add the rockchip nand controller driver
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (8 preceding siblings ...)
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:14 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:45   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 more replies)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 11/19] rockchip: mkimage: add support for rockchip nand boot image =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (9 subsequent siblings)
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:14 UTC (permalink / raw)
  To: u-boot

Add basic Rockchip nand driver.

Driver in current state has 16, 24, 40, 60 per 1024B BCH/ECC ability and 8 bit asynchronous flash interface support. Other features will come later.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- fixed correct ecc checking

Changes since v3:
- none

 drivers/mtd/nand/Kconfig         |   6 +
 drivers/mtd/nand/Makefile        |   1 +
 drivers/mtd/nand/rockchip_nand.c | 660 +++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h                 |   1 +
 lib/fdtdec.c                     |   1 +
 5 files changed, 669 insertions(+)
 create mode 100644 drivers/mtd/nand/rockchip_nand.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 71d678f..c308497 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -69,6 +69,12 @@ config NAND_PXA3XX
 	  This enables the driver for the NAND flash device found on
 	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
 
+config NAND_ROCKCHIP
+	bool "Support for NAND on Rockchip SoCs"
+	select SYS_NAND_SELF_INIT
+	---help---
+	Enable support for Rockchip nand.
+
 config NAND_SUNXI
 	bool "Support for NAND on Allwinner SoCs"
 	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index c3d4a99..0659253 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
 obj-$(CONFIG_NAND_PLAT) += nand_plat.o
 obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
 obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
+obj-$(CONFIG_NAND_ROCKCHIP) += rockchip_nand.o
 
 else  # minimal SPL drivers
 
diff --git a/drivers/mtd/nand/rockchip_nand.c b/drivers/mtd/nand/rockchip_nand.c
new file mode 100644
index 0000000..d8f4439
--- /dev/null
+++ b/drivers/mtd/nand/rockchip_nand.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright (c) 2017 Yifeng Zhao <yifeng.zhao@rock-chips.com>
+ * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <inttypes.h>
+#include <nand.h>
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define NANDC_V6_BOOTROM_ECC	24
+#define	NANDC_V6_NUM_BANKS	8
+#define NANDC_V6_DEF_TIMEOUT	20000
+#define NANDC_V6_READ		0
+#define NANDC_V6_WRITE		1
+
+#define	NANDC_REG_V6_FMCTL	0x00
+#define	NANDC_REG_V6_FMWAIT	0x04
+#define	NANDC_REG_V6_FLCTL	0x08
+#define	NANDC_REG_V6_BCHCTL	0x0c
+#define	NANDC_REG_V6_DMA_CFG	0x10
+#define	NANDC_REG_V6_DMA_BUF0	0x14
+#define	NANDC_REG_V6_DMA_BUF1	0x18
+#define	NANDC_REG_V6_DMA_ST	0x1C
+#define	NANDC_REG_V6_BCHST	0x20
+#define	NANDC_REG_V6_RANDMZ	0x150
+#define	NANDC_REG_V6_VER	0x160
+#define	NANDC_REG_V6_INTEN	0x16C
+#define	NANDC_REG_V6_INTCLR 	0x170
+#define	NANDC_REG_V6_INTST	0x174
+#define	NANDC_REG_V6_SPARE0	0x200
+#define	NANDC_REG_V6_SPARE1	0x230
+#define	NANDC_REG_V6_BANK0	0x800
+#define	NANDC_REG_V6_SRAM0	0x1000
+#define	NANDC_REG_V6_SRAM_SIZE	0x400
+
+#define NANDC_REG_V6_DATA	0x00
+#define NANDC_REG_V6_ADDR	0x04
+#define NANDC_REG_V6_CMD	0x08
+
+/* FMCTL */
+#define NANDC_V6_FM_WP		BIT(8)
+#define NANDC_V6_FM_CE_SEL_M	0xFF
+#define NANDC_V6_FM_CE_SEL(x)	(1 << (x))
+#define NANDC_V6_FM_FREADY	BIT(9)
+
+/* FLCTL */
+#define NANDC_V6_FL_RST		BIT(0)
+#define NANDC_V6_FL_DIR_S	0x1
+#define NANDC_V6_FL_XFER_START	BIT(2)
+#define NANDC_V6_FL_XFER_EN	BIT(3)
+#define NANDC_V6_FL_ST_BUF_S	0x4
+#define NANDC_V6_FL_XFER_COUNT	BIT(5)
+#define NANDC_V6_FL_ACORRECT	BIT(10)
+#define NANDC_V6_FL_XFER_READY	BIT(20)
+
+/* BCHCTL */
+#define NAND_V6_BCH_REGION_S	0x5
+#define NAND_V6_BCH_REGION_M	0x7	
+
+/* BCHST */
+#define NANDC_V6_BCH0_ST_ERR	BIT(2)
+#define NANDC_V6_BCH1_ST_ERR	BIT(15)
+#define NANDC_V6_ECC_ERR_CNT0(x) ((((x & (0x1F << 3)) >> 3) \
+				| ((x & (1 << 27)) >> 22)) & 0x3F)
+#define NANDC_V6_ECC_ERR_CNT1(x) ((((x & (0x1F << 16)) >> 16) \
+				| ((x & (1 << 29)) >> 24)) & 0x3F)
+
+struct rk_nand {
+	uint32_t banks[NANDC_V6_NUM_BANKS];
+	struct nand_hw_control controller;
+	uint32_t ecc_strength;
+	struct mtd_info mtd;
+	bool bootromblocks;
+	void __iomem *regs;
+	int selected_bank;
+};
+
+static struct nand_ecclayout nand_oob_fix = {
+	.eccbytes = 24,
+	.eccpos = {
+		   4, 5, 6, 7, 8, 9, 10},
+	.oobfree = {
+		{.offset = 0,
+		 .length = 4} }
+};
+
+static inline struct rk_nand *to_rknand(struct nand_hw_control *ctrl)
+{
+	return container_of(ctrl, struct rk_nand, controller);
+}
+
+static void rockchip_nand_init(struct rk_nand *rknand)
+{
+	writel(0, rknand->regs + NANDC_REG_V6_RANDMZ);
+	writel(0, rknand->regs + NANDC_REG_V6_DMA_CFG);
+	writel(0, rknand->regs + NANDC_REG_V6_BCHCTL);
+	writel(NANDC_V6_FM_WP, rknand->regs + NANDC_REG_V6_FMCTL);
+	writel(0x1081, rknand->regs + NANDC_REG_V6_FMWAIT);
+}
+
+static void rockchip_nand_select_chip(struct mtd_info *mtd, int chipnr)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	void __iomem *bank_base;
+	uint32_t reg;
+	int banknr;
+
+	reg = readl(rknand->regs + NANDC_REG_V6_FMCTL);
+	reg &= ~NANDC_V6_FM_CE_SEL_M;
+
+	if (chipnr == -1) {
+		banknr = -1;
+	} else {
+		banknr = rknand->banks[chipnr];
+		bank_base = rknand->regs + NANDC_REG_V6_BANK0 + banknr * 0x100;
+
+		chip->IO_ADDR_R = bank_base;
+		chip->IO_ADDR_W = bank_base;
+
+		reg |= 1 << banknr;
+	}
+	writel(reg, rknand->regs + NANDC_REG_V6_FMCTL);
+
+	rknand->selected_bank = banknr;
+}
+
+static void rockchip_nand_cmd_ctrl(struct mtd_info *mtd,
+				   int dat,
+				   unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
+				+ rknand->selected_bank * 0x100;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		if (ctrl & NAND_ALE)
+			bank_base += NANDC_REG_V6_ADDR;
+		else if (ctrl & NAND_CLE)
+			bank_base += NANDC_REG_V6_CMD;
+		chip->IO_ADDR_W = bank_base;
+	}
+
+	if (dat != NAND_CMD_NONE)
+		writeb(dat & 0xFF, chip->IO_ADDR_W);
+}
+
+static void rockchip_nand_read_buf(struct mtd_info *mtd,
+				   uint8_t *buf,
+				   int len)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	int offs = 0;
+	void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
+				+ rknand->selected_bank * 0x100;
+
+	for (offs = 0; offs < len; offs++)
+		buf[offs] = readb(bank_base);
+}
+
+static void rockchip_nand_write_buf(struct mtd_info *mtd,
+				    const uint8_t *buf,
+				    int len)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	int offs = 0;
+	void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
+				+ rknand->selected_bank * 0x100;
+
+	for (offs = 0; offs < len; offs++)
+		writeb(buf[offs], bank_base);
+}
+
+static uint8_t rockchip_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t ret;
+
+	rockchip_nand_read_buf(mtd, &ret, 1);
+
+	return ret;
+}
+
+static int rockchip_nand_dev_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct rk_nand *rknand = to_rknand(chip->controller);
+
+	if (readl(rknand->regs + NANDC_REG_V6_FMCTL) & NANDC_V6_FM_FREADY)
+		return 1;
+
+	return 0;
+}
+
+static int rockchip_nand_hw_ecc_setup(struct mtd_info *mtd,
+				      struct nand_ecc_ctrl *ecc,
+				      uint32_t strength)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	u32 reg;
+
+	ecc->strength = strength;
+	ecc->bytes = DIV_ROUND_UP(ecc->strength * 14, 8);
+	ecc->bytes = ALIGN(ecc->bytes, 2);
+
+	switch (ecc->strength) {
+	case 60:
+		reg = 0x00040010;
+		break;
+	case 40:
+		reg = 0x00040000;
+		break;
+	case 24:
+		reg = 0x00000010;
+		break;
+	case 16:
+		reg = 0x00000000;
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);
+
+	return 0;
+}
+
+static void rockchip_nand_pio_xfer_start(struct rk_nand *rknand,
+					 u8 dir,
+					 u8 st_buf)
+{
+	u32 reg;
+
+	reg = readl(rknand->regs + NANDC_REG_V6_BCHCTL);
+	reg = (reg & (~(NAND_V6_BCH_REGION_M << NAND_V6_BCH_REGION_S))) |
+	      (rknand->selected_bank << NAND_V6_BCH_REGION_S);
+	writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);
+
+	reg = (dir << NANDC_V6_FL_DIR_S) | (st_buf << NANDC_V6_FL_ST_BUF_S) |
+	      NANDC_V6_FL_XFER_EN | NANDC_V6_FL_XFER_COUNT |
+	      NANDC_V6_FL_ACORRECT;
+	writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);
+
+	reg |= NANDC_V6_FL_XFER_START;
+	writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);
+}
+
+static int rockchip_nand_wait_pio_xfer_done(struct rk_nand *rknand)
+{
+	int timeout = NANDC_V6_DEF_TIMEOUT;
+	int reg;
+
+	while (timeout--) {
+		reg = readl(rknand->regs + NANDC_REG_V6_FLCTL);
+
+		if ((reg & NANDC_V6_FL_XFER_READY) != 0)
+			break;
+
+		udelay(1);
+	}
+
+	if (timeout == 0)
+		return -1;
+
+	return 0;
+}
+
+static void rockchip_nand_read_extra_oob(struct mtd_info *mtd, u8 *oob)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
+	int len = mtd->oobsize - offset;
+
+	if (len <= 0)
+		return;
+
+	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1);
+
+	rockchip_nand_read_buf(mtd, oob + offset, len);
+}
+
+static void rockchip_nand_write_extra_oob(struct mtd_info *mtd, u8 *oob)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
+	int len = mtd->oobsize - offset;
+
+	if (len <= 0)
+		return;
+
+	chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1);
+
+	rockchip_nand_write_buf(mtd, oob + offset, len);
+}
+
+
+static int rockchip_nand_hw_syndrome_pio_read_page(struct mtd_info *mtd,
+						   struct nand_chip *chip,
+						   uint8_t *buf,
+						   int oob_required,
+						   int page)
+{
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
+	unsigned int max_bitflips = 0;
+	int ret, step, bch_st;
+	int offset = page * mtd->writesize;
+
+	if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
+		rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
+
+	rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ, 0);
+
+	for (step = 0; step < ecc->steps; step++) {
+		int data_off = step * ecc->size;
+		int oob_off = step * (ecc->bytes + ecc->prepad);
+		u8 *data = buf + data_off;
+		u8 *oob = chip->oob_poi + oob_off;
+
+		ret = rockchip_nand_wait_pio_xfer_done(rknand);
+		if (ret)
+			return ret;
+
+		bch_st = readl(rknand->regs + NANDC_REG_V6_BCHST);
+
+		if (bch_st & NANDC_V6_BCH0_ST_ERR) {
+			mtd->ecc_stats.failed++;
+			max_bitflips = -1;
+		} else {
+			ret = NANDC_V6_ECC_ERR_CNT0(bch_st);
+			mtd->ecc_stats.corrected += ret;
+			max_bitflips = max_t(unsigned int, max_bitflips, ret);
+		}
+
+		if ((step + 1) < ecc->steps)
+			rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ,
+					      		(step + 1) & 0x1);
+
+		memcpy_fromio(data, sram_base + NANDC_REG_V6_SRAM_SIZE *
+			     				(step & 1), ecc->size);
+
+		if (step & 1)
+			memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE1, 4);
+		else
+			memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE0, 4);
+	}
+
+	rockchip_nand_read_extra_oob(mtd, chip->oob_poi);
+
+	if (rknand->bootromblocks)
+		rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
+
+	return max_bitflips;
+}
+
+static uint32_t rockchip_nand_make_bootrom_compat(struct mtd_info *mtd,
+						  int page,
+						  const u8 *oob,
+						  bool bootromblocks)
+{
+	int pages_per_block = mtd->erasesize / mtd->writesize;
+	int offset = page * mtd->writesize;
+
+	if ((offset < (2 * mtd->erasesize)) || !(page % 2) ||
+	    (offset >= (7 * mtd->erasesize)) || !bootromblocks)
+		return oob[3] | (oob[2] << 8) | (oob[1] << 16) | (oob[0] << 24);
+
+	return (page % pages_per_block + 1) * 4;
+}
+
+static int rockchip_nand_hw_syndrome_pio_write_page(struct mtd_info *mtd,
+						    struct nand_chip *chip,
+						    const uint8_t *buf,
+						    int oob_required,
+						    int page)
+{
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
+	int ret, index, step = 0;
+	int offset = page * mtd->writesize;
+	int data_off = step * ecc->size;
+	int oob_off = step * (ecc->bytes + ecc->prepad);
+	const u8 *data = buf + data_off;
+	const u8 *oob = chip->oob_poi + oob_off;
+
+	if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
+		rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
+
+	index = rockchip_nand_make_bootrom_compat(mtd, page, oob,
+					   rknand->bootromblocks);
+
+	memcpy_toio(sram_base, data, ecc->size);
+	memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0, &index, ecc->prepad);
+
+	for (step = 1; step <= ecc->steps; step++) {
+		rockchip_nand_pio_xfer_start(rknand, NANDC_V6_WRITE,
+					     (step - 1) & 0x1);
+
+		data_off = step * ecc->size;
+		oob_off = step * (ecc->bytes + ecc->prepad);
+		data = buf + data_off;
+		oob = chip->oob_poi + oob_off;
+
+		if (step < ecc->steps) {
+			memcpy_toio(sram_base + NANDC_REG_V6_SRAM_SIZE * 
+				    (step & 1), data, ecc->size);
+			if (step & 1)
+				memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE1,
+					    oob, ecc->prepad);
+			else
+				memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0,
+					    oob, ecc->prepad);
+		}
+
+		ret = rockchip_nand_wait_pio_xfer_done(rknand);
+		if (ret)
+			return ret;
+	}
+
+	rockchip_nand_write_extra_oob(mtd, chip->oob_poi);
+
+	rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
+
+	return 0;
+}
+
+static const u8 strengths[] = {60, 40, 24, 16};
+
+static int rockchip_nand_ecc_max_strength(struct mtd_info *mtd,
+					  struct nand_ecc_ctrl *ecc)
+{
+	uint32_t max_strength, index;
+	
+	max_strength = ((mtd->oobsize / ecc->steps) - ecc->prepad) * 8 / 14;
+
+	for (index = 0; index < ARRAY_SIZE(strengths); index++)
+		if (max_strength >= strengths[index])
+			break;
+
+	if (index >= ARRAY_SIZE(strengths))
+		return -ENOTSUPP;
+
+	return strengths[index];
+}
+
+static bool rockchip_nand_strength_is_valid(int strength)
+{
+	uint32_t index;
+
+	for (index = 0; index < ARRAY_SIZE(strengths); index++)
+		if (strength == strengths[index])
+			break;
+
+	if (index == ARRAY_SIZE(strengths))
+		return false;
+
+	return true;
+}
+
+static int rockchip_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
+					  struct nand_ecc_ctrl *ecc)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct rk_nand *rknand = to_rknand(chip->controller);
+	uint32_t strength;
+	int index;
+
+	ecc->prepad = 4;
+	ecc->steps = mtd->writesize / ecc->size;
+
+	if (fdtdec_get_bool(gd->fdt_blob, chip->flash_node,
+			    "rockchip,protect-bootrom-blocks"))
+                rknand->bootromblocks = true;
+	else
+		rknand->bootromblocks = false;
+
+	if (rockchip_nand_strength_is_valid(ecc->strength))
+		strength = ecc->strength;
+	else
+		strength = rockchip_nand_ecc_max_strength(mtd, ecc);
+
+	rockchip_nand_hw_ecc_setup(mtd, ecc, strength);
+
+	rknand->ecc_strength = ecc->strength;
+
+	nand_oob_fix.eccbytes = ecc->bytes * ecc->steps;
+	for (index = 0; index < ecc->bytes; index++)
+		nand_oob_fix.eccpos[index] = index + ecc->prepad;
+	ecc->layout = &nand_oob_fix;
+
+	if (mtd->oobsize < ((ecc->bytes + ecc->prepad) * ecc->steps)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rockchip_nand_ecc_init(struct mtd_info *mtd,
+				  struct nand_ecc_ctrl *ecc)
+{
+	int ret;
+
+	switch (ecc->mode) {
+	case NAND_ECC_HW_SYNDROME:
+		ret = rockchip_nand_hw_ecc_ctrl_init(mtd, ecc);
+		if (ret)
+			return ret;
+		ecc->read_page =  rockchip_nand_hw_syndrome_pio_read_page;
+		ecc->write_page = rockchip_nand_hw_syndrome_pio_write_page;
+		break;
+	case NAND_ECC_SOFT_BCH:
+	case NAND_ECC_NONE:
+	case NAND_ECC_SOFT:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rockchip_nand_chip_init(int node, struct rk_nand *rknand, int devnum)
+{
+	const void *blob = gd->fdt_blob;
+	struct nand_chip *chip;
+	struct mtd_info *mtd;
+	int ret;
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+
+	chip->chip_delay = 50;
+	chip->flash_node = node;
+	chip->select_chip = rockchip_nand_select_chip;
+	chip->cmd_ctrl = rockchip_nand_cmd_ctrl;
+	chip->read_buf = rockchip_nand_read_buf;
+	chip->write_buf = rockchip_nand_write_buf;
+	chip->read_byte = rockchip_nand_read_byte;
+	chip->dev_ready = rockchip_nand_dev_ready;
+	chip->controller = &rknand->controller;
+
+	rknand->banks[devnum] = fdtdec_get_int(blob, node, "reg", -1);
+
+	if (rknand->banks[devnum] < 0)
+		return -EINVAL;
+
+	mtd = nand_to_mtd(chip);
+	mtd->name = "rknand";
+
+	ret = nand_scan_ident(mtd, 1, NULL);
+	if (ret)
+		return ret;
+
+	ret = rockchip_nand_ecc_init(mtd, &chip->ecc);
+	if (ret) {
+		debug("rockchip_nand_ecc_init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = nand_scan_tail(mtd);
+	if (ret) {
+		debug("nand_scan_tail failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = nand_register(devnum, mtd);
+	if (ret) {
+		debug("Failed to register mtd device: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rockchip_nand_chips_init(int node, struct rk_nand *rknand)
+{
+	const void *blob = gd->fdt_blob;
+	int nand_node;
+	int ret, i = 0;
+
+	for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
+	     nand_node = fdt_next_subnode(blob, nand_node)) {
+		ret = rockchip_nand_chip_init(nand_node, rknand, i++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void board_nand_init(void)
+{
+	const void *blob = gd->fdt_blob;
+	struct rk_nand *rknand;
+	fdt_addr_t regs;
+	int node;
+	int ret;
+
+	rknand = kzalloc(sizeof(*rknand), GFP_KERNEL);
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_ROCKCHIP_NANDC);
+
+	if (node < 0) {
+		debug("Nand node not found\n");
+		goto err;
+	}
+
+	if (!fdtdec_get_is_enabled(blob, node)) {
+		debug("Nand disabled in device tree\n");
+		goto err;
+	}
+
+	regs = fdtdec_get_addr(blob, node, "reg");
+	if (regs == FDT_ADDR_T_NONE) {
+		debug("Nand address not found\n");
+		goto err;
+	}
+
+	rknand->regs = (void *)regs;
+
+	spin_lock_init(&rknand->controller.lock);
+	init_waitqueue_head(&rknand->controller.wq);
+
+	rockchip_nand_init(rknand);
+
+	ret = rockchip_nand_chips_init(node, rknand);
+	if (ret) {
+		debug("Failed to init nand chips\n");
+		goto err;
+	}
+
+	return;
+err:
+	kfree(rknand);
+}
+
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
+{
+	struct mtd_info *mtd;
+
+	mtd = get_nand_dev_by_index(0);
+	return nand_read_skip_bad(mtd, offs, &size, NULL, size, (u_char *)dst);
+}
+
+void nand_deselect(void) {}
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 4a0947c..0e68788 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -157,6 +157,7 @@ enum fdt_compat_id {
 	COMPAT_ALTERA_SOCFPGA_F2SDR0,           /* SoCFPGA fpga2SDRAM0 bridge */
 	COMPAT_ALTERA_SOCFPGA_F2SDR1,           /* SoCFPGA fpga2SDRAM1 bridge */
 	COMPAT_ALTERA_SOCFPGA_F2SDR2,           /* SoCFPGA fpga2SDRAM2 bridge */
+	COMPAT_ROCKCHIP_NANDC,			/* Rockchip NAND controller */
 
 	COMPAT_COUNT,
 };
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 107a892..4a8a8d7 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"),
 	COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"),
 	COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"),
+	COMPAT(ROCKCHIP_NANDC, "rockchip,nandc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
-- 
2.7.4

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

* [U-Boot] [PATCH v4 11/19] rockchip: mkimage: add support for rockchip nand boot image
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (9 preceding siblings ...)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 10/19] mtd: nand: add the rockchip nand controller driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:14 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:49   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 more replies)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (8 subsequent siblings)
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:14 UTC (permalink / raw)
  To: u-boot

The Rockchip boot ROM requires a particular file format for booting from NAND:

* It starts with 512-byte, rc4 encoded header and is aligned to nand page size

* Then first 2KB of first stage loader (tpl) aligned to nand page size
* n empty pages

* second 2KB of first stage loader (tpl) aligned to nand page size
* n empty pages

* ...

* first 2KB of second stage loader (spl) aligned to nand page size
* n empty pages

* second 2KB of first stage loader (spl) aligned to nand page size
* n empty pages

* ...

Size of spl and tpl must be aligned to 2KB.

example usage for nand with page size 16384 and one empty page in iteration:

    # mkimage -n rk3066 -T rknand -d ./u-boot/tpl/u-boot-tpl.bin:./u-boot/spl/u-boot-spl.bin -X 16384,1 out

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- none

 common/image.c    |   1 +
 include/image.h   |   1 +
 tools/Makefile    |   2 +-
 tools/imagetool.h |   1 +
 tools/mkimage.c   |   8 ++-
 tools/rkcommon.c  |  10 ++--
 tools/rkcommon.h  |  10 +++-
 tools/rknand.c    | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/rksd.c      |   2 +-
 tools/rkspi.c     |   2 +-
 10 files changed, 183 insertions(+), 10 deletions(-)
 create mode 100644 tools/rknand.c

diff --git a/common/image.c b/common/image.c
index a058eb8..f5f6cd2 100644
--- a/common/image.c
+++ b/common/image.c
@@ -167,6 +167,7 @@ static const table_entry_t uimage_type[] = {
 	{	IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
 	{       IH_TYPE_TEE,        "tee",        "Trusted Execution Environment Image",},
 	{	IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" },
+	{	IH_TYPE_RKNAND,     "rknand",     "Rockchip NAND Boot Image" },
 	{	-1,		    "",		  "",			},
 };
 
diff --git a/include/image.h b/include/image.h
index 1f4bfda..10ff094 100644
--- a/include/image.h
+++ b/include/image.h
@@ -269,6 +269,7 @@ enum {
 	IH_TYPE_VYBRIDIMAGE,	/* VYBRID .vyb Image */
 	IH_TYPE_TEE,            /* Trusted Execution Environment OS Image */
 	IH_TYPE_FIRMWARE_IVT,		/* Firmware Image with HABv4 IVT */
+	IH_TYPE_RKNAND,			/* Rockchip NAND Boot Image	*/
 
 	IH_TYPE_COUNT,			/* Number of image types */
 };
diff --git a/tools/Makefile b/tools/Makefile
index a1790eb..044049c 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -79,7 +79,7 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
 					rsa-sign.o rsa-verify.o rsa-checksum.o \
 					rsa-mod-exp.o)
 
-ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o
+ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rknand.o rksd.o rkspi.o
 
 # common objs for dumpimage and mkimage
 dumpimage-mkimage-objs := aisimage.o \
diff --git a/tools/imagetool.h b/tools/imagetool.h
index a8d5054..0b2a707 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -77,6 +77,7 @@ struct image_tool_params {
 	bool quiet;		/* Don't output text in normal operation */
 	unsigned int external_offset;	/* Add padding to external data */
 	const char *engine_id;	/* Engine to use for signing */
+	char *extraparams;	/* Extra parameters for img creation (-X) */
 };
 
 /*
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 28ff35e..ffc91d2 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -144,7 +144,7 @@ static void process_args(int argc, char **argv)
 	int opt;
 
 	while ((opt = getopt(argc, argv,
-			     "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVx")) != -1) {
+			     "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVxX:")) != -1) {
 		switch (opt) {
 		case 'a':
 			params.addr = strtoull(optarg, &ptr, 16);
@@ -279,6 +279,9 @@ static void process_args(int argc, char **argv)
 		case 'x':
 			params.xflag++;
 			break;
+		case 'X':
+			params.extraparams = optarg;
+			break;
 		default:
 			usage("Invalid option");
 		}
@@ -416,7 +419,8 @@ int main(int argc, char **argv)
 		exit (retval);
 	}
 
-	if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT)) {
+	if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT) &&
+	    (params.type != IH_TYPE_RKNAND)) {
 		dfd = open(params.datafile, O_RDONLY | O_BINARY);
 		if (dfd < 0) {
 			fprintf(stderr, "%s: Can't open %s: %s\n",
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 04e8272..a2f2160 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -73,6 +73,7 @@ struct spl_info {
 
 static struct spl_info spl_infos[] = {
 	{ "rk3036", "RK30", 0x1000, false, false },
+	{ "rk3066", "RK30", 0x8000, true, false },
 	{ "rk3188", "RK31", 0x8000 - 0x800, true, false },
 	{ "rk322x", "RK32", 0x8000 - 0x1000, false, false },
 	{ "rk3288", "RK32", 0x8000, false, false },
@@ -167,7 +168,7 @@ bool rkcommon_spl_is_boot0(struct image_tool_params *params)
 	return info->spl_boot0;
 }
 
-static void rkcommon_set_header0(void *buf, uint file_size,
+static void rkcommon_set_header0(void *buf, uint file_size, uint max_size,
 				 struct image_tool_params *params)
 {
 	struct header0_info *hdr = buf;
@@ -194,12 +195,13 @@ static void rkcommon_set_header0(void *buf, uint file_size,
 	 * see https://lists.denx.de/pipermail/u-boot/2017-May/293267.html
 	 * for a more detailed explanation by Andy Yan
 	 */
-	hdr->init_boot_size = hdr->init_size + RK_MAX_BOOT_SIZE / RK_BLK_SIZE;
+	hdr->init_boot_size = hdr->init_size + DIV_ROUND_UP(max_size, RK_BLK_SIZE);
+	hdr->init_boot_size = ROUND(hdr->init_boot_size, 4);
 
 	rc4_encode(buf, RK_BLK_SIZE, rc4_key);
 }
 
-int rkcommon_set_header(void *buf, uint file_size,
+int rkcommon_set_header(void *buf, uint file_size, uint max_size,
 			struct image_tool_params *params)
 {
 	struct header1_info *hdr = buf + RK_SPL_HDR_START;
@@ -207,7 +209,7 @@ int rkcommon_set_header(void *buf, uint file_size,
 	if (file_size > rkcommon_get_spl_size(params))
 		return -ENOSPC;
 
-	rkcommon_set_header0(buf, file_size, params);
+	rkcommon_set_header0(buf, file_size, max_size, params);
 
 	/* Set up the SPL name (i.e. copy spl_hdr over) */
 	memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE);
diff --git a/tools/rkcommon.h b/tools/rkcommon.h
index 8790f1c..cd357c7 100644
--- a/tools/rkcommon.h
+++ b/tools/rkcommon.h
@@ -45,6 +45,14 @@ const char *rkcommon_get_spl_hdr(struct image_tool_params *params);
 int rkcommon_get_spl_size(struct image_tool_params *params);
 
 /**
+ * rkcommon_spl_is_boot0() - is magic included in spl
+ *
+ * Returns true if magic (for example RK30) is included in spl
+ */
+
+bool rkcommon_spl_is_boot0(struct image_tool_params *params);
+
+/**
  * rkcommon_set_header() - set up the header for a Rockchip boot image
  *
  * This sets up a 2KB header which can be interpreted by the Rockchip boot ROM.
@@ -53,7 +61,7 @@ int rkcommon_get_spl_size(struct image_tool_params *params);
  * @file_size:	Size of the file we want the boot ROM to load, in bytes
  * @return 0 if OK, -ENOSPC if too large
  */
-int rkcommon_set_header(void *buf, uint file_size,
+int rkcommon_set_header(void *buf, uint file_size, uint max_size,
 			struct image_tool_params *params);
 
 /**
diff --git a/tools/rknand.c b/tools/rknand.c
new file mode 100644
index 0000000..690af2d
--- /dev/null
+++ b/tools/rknand.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include "imagetool.h"
+#include <image.h>
+#include <rc4.h>
+#include "mkimage.h"
+#include "rkcommon.h"
+
+enum {
+	RKNAND_SECT_LEN = RK_BLK_SIZE * 4,
+};
+
+struct rknand_info {
+	uint32_t pagesize;
+	uint32_t skippages;
+	uint32_t tplsize;
+	uint32_t splsize;
+	uint32_t tplpaddedsize;
+	uint32_t splpaddedsize;
+	uint32_t itersize;
+	uint32_t tplsplsize;
+	char *tplfile;
+	char *splfile;
+};
+
+struct rknand_info ninfo;
+
+static uint32_t rknand_get_file_size(char *filename)
+{
+	int dfd;
+	struct stat sbuf;
+
+	dfd = open(filename, O_RDONLY | O_BINARY);
+	if (dfd < 0) {
+		fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	if (fstat(dfd, &sbuf) < 0) {
+		fprintf(stderr, "Can't stat %s: %s\n", filename, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	close(dfd);
+
+	return sbuf.st_size;
+}
+
+static void rknand_fill_ninfo(struct image_tool_params *params)
+{
+	sscanf(params->extraparams, "%u,%u", &ninfo.pagesize, &ninfo.skippages);
+
+	ninfo.tplfile = params->datafile;
+	if ((ninfo.splfile = strchr(params->datafile, ':')) != NULL) {
+		*ninfo.splfile = '\0';
+		ninfo.splfile += 1;
+	}
+
+	ninfo.tplsize = rknand_get_file_size(ninfo.tplfile);
+	ninfo.splsize = rknand_get_file_size(ninfo.splfile);
+
+	ninfo.tplpaddedsize = ROUND(ninfo.tplsize + 
+		(rkcommon_spl_is_boot0(params) ? 0 : 4), RKNAND_SECT_LEN);
+
+	ninfo.splpaddedsize = ROUND(ninfo.splsize, RKNAND_SECT_LEN);
+
+	ninfo.itersize = ninfo.pagesize * (ninfo.skippages + 1);
+	ninfo.tplsplsize = ((ninfo.tplpaddedsize + ninfo.splpaddedsize) /
+		     RKNAND_SECT_LEN) * ninfo.itersize;
+}
+
+static void rknand_set_header(void *buf, struct stat *sbuf, int ifd,
+			     struct image_tool_params *params)
+{
+	int sector, sploffset, splfd, ret;
+
+	ret = rkcommon_set_header(buf, ninfo.tplsize, ninfo.splsize, params);
+	if (ret) {
+		printf("Warning: TPL image is too large (size %#x) and will "
+		       "not boot\n", ninfo.tplsize);
+	}
+
+	if ((splfd = open(ninfo.splfile, O_RDONLY | O_BINARY)) < 0) {
+		fprintf (stderr, "%s: Can't open %s: %s\n",
+			params->cmdname, ninfo.splfile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	sploffset = RKNAND_SECT_LEN + ninfo.tplpaddedsize;
+	if (read(splfd, buf + sploffset, ninfo.splsize) != ninfo.splsize) {
+		fprintf (stderr, "%s: Read error on %s: %s\n",
+			params->cmdname, ninfo.splfile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+	close(splfd);
+
+	if (rkcommon_need_rc4_spl(params))
+		rkcommon_rc4_encode_spl(buf, sploffset, ninfo.splpaddedsize);
+
+	/*
+	 * Spread the image out so we only use the first 2KB of each pagesize
+	 * region. This is a feature of the NAND format required by the Rockchip
+	 * boot ROM.
+	 */
+	for (sector = ninfo.tplsplsize / ninfo.itersize - 1; sector >= 0; sector--) {
+		memmove(buf + sector * ninfo.itersize + ninfo.pagesize,
+			buf + (sector + 1) * RKNAND_SECT_LEN, RKNAND_SECT_LEN);
+
+		if (sector < (ninfo.tplsplsize / ninfo.itersize - 1))
+			memset(buf + sector * ninfo.itersize  + ninfo.pagesize +
+			       RKNAND_SECT_LEN, 0xFF, ninfo.itersize -
+			       RKNAND_SECT_LEN);
+	}
+	memset(buf + RKNAND_SECT_LEN, 0xFF, ninfo.pagesize - RKNAND_SECT_LEN);
+	memset(buf + ninfo.tplsplsize - ninfo.pagesize + RKNAND_SECT_LEN, 0xFF,
+	       ninfo.pagesize - RKNAND_SECT_LEN);
+}
+
+static int rknand_check_image_type(uint8_t type)
+{
+	if (type == IH_TYPE_RKNAND)
+		return EXIT_SUCCESS;
+	else
+		return EXIT_FAILURE;
+}
+
+static int rknand_vrec_header(struct image_tool_params *params,
+			     struct image_type_params *tparams)
+{
+	rknand_fill_ninfo(params);
+	rkcommon_vrec_header(params, tparams, RKNAND_SECT_LEN);
+
+	return ninfo.tplsplsize - tparams->header_size - ninfo.tplsize;
+}
+
+/*
+ * rknand parameters
+ */
+U_BOOT_IMAGE_TYPE(
+	rknand,
+	"Rockchip NAND Boot Image support",
+	0,
+	NULL,
+	rkcommon_check_params,
+	rkcommon_verify_header,
+	rkcommon_print_header,
+	rknand_set_header,
+	NULL,
+	rknand_check_image_type,
+	NULL,
+	rknand_vrec_header
+);
diff --git a/tools/rksd.c b/tools/rksd.c
index c56153d..164c1fb 100644
--- a/tools/rksd.c
+++ b/tools/rksd.c
@@ -26,7 +26,7 @@ static void rksd_set_header(void *buf,  struct stat *sbuf,  int ifd,
 	 * header).
 	 */
 	size = params->file_size - RK_SPL_HDR_START;
-	ret = rkcommon_set_header(buf, size, params);
+	ret = rkcommon_set_header(buf, size, RK_MAX_BOOT_SIZE, params);
 	if (ret) {
 		/* TODO(sjg at chromium.org): This method should return an error */
 		printf("Warning: SPL image is too large (size %#x) and will "
diff --git a/tools/rkspi.c b/tools/rkspi.c
index 4332ce1..5005051 100644
--- a/tools/rkspi.c
+++ b/tools/rkspi.c
@@ -25,7 +25,7 @@ static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd,
 	int ret;
 
 	size = params->orig_file_size;
-	ret = rkcommon_set_header(buf, size, params);
+	ret = rkcommon_set_header(buf, size, RK_MAX_BOOT_SIZE, params);
 	debug("size %x\n", size);
 	if (ret) {
 		/* TODO(sjg at chromium.org): This method should return an error */
-- 
2.7.4

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

* [U-Boot] [PATCH v4 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (10 preceding siblings ...)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 11/19] rockchip: mkimage: add support for rockchip nand boot image =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:14 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 more replies)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (7 subsequent siblings)
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:14 UTC (permalink / raw)
  To: u-boot

Use live tree functions to fill dwc2_plat_otg_data structure in board_usb_init.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/mach-rockchip/rk3066-board.c | 52 +++++------------------------------
 1 file changed, 7 insertions(+), 45 deletions(-)

diff --git a/arch/arm/mach-rockchip/rk3066-board.c b/arch/arm/mach-rockchip/rk3066-board.c
index 8fa06a2..2b96eb2 100644
--- a/arch/arm/mach-rockchip/rk3066-board.c
+++ b/arch/arm/mach-rockchip/rk3066-board.c
@@ -90,55 +90,17 @@ static struct dwc2_plat_otg_data rk3066_otg_data = {
 
 int board_usb_init(int index, enum usb_init_type init)
 {
-	int node, phy_node;
-	const char *mode;
-	bool matched = false;
-	const void *blob = gd->fdt_blob;
-	u32 grf_phy_offset;
-
-	/* find the usb_otg node */
-	node = fdt_node_offset_by_compatible(blob, -1,
-					"rockchip,rk3066-usb");
-
-	while (node > 0) {
-		mode = fdt_getprop(blob, node, "dr_mode", NULL);
-		if (mode && strcmp(mode, "otg") == 0) {
-			matched = true;
-			break;
-		}
-
-		node = fdt_node_offset_by_compatible(blob, node,
-					"rockchip,rk3066-usb");
-	}
-	if (!matched) {
-		debug("Not found usb_otg device\n");
-		return -ENODEV;
-	}
-	rk3066_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
+	ofnode otg_node;
+	u32 reg;
 
-	node = fdtdec_lookup_phandle(blob, node, "phys");
-	if (node <= 0) {
-		debug("Not found usb phy device\n");
+	otg_node = ofnode_path("/usb@10180000");
+	if (!ofnode_valid(otg_node)) {
+		debug("Not found usb otg device\n");
 		return -ENODEV;
 	}
 
-	phy_node = fdt_parent_offset(blob, node);
-	if (phy_node <= 0) {
-		debug("Not found usb phy device\n");
-		return -ENODEV;
-	}
-
-	rk3066_otg_data.phy_of_node = phy_node;
-	grf_phy_offset = fdtdec_get_addr(blob, node, "reg");
-
-	node = fdt_node_offset_by_compatible(blob, -1,
-					"rockchip,rk3066-grf");
-	if (node <= 0) {
-		debug("Not found grf device\n");
-		return -ENODEV;
-	}
-	rk3066_otg_data.regs_phy = grf_phy_offset +
-				fdtdec_get_addr(blob, node, "reg");
+	ofnode_read_u32(otg_node, "reg", &reg);
+	rk3066_otg_data.regs_otg = reg;
 
 	return dwc2_udc_probe(&rk3066_otg_data);
 }
-- 
2.7.4

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

* [U-Boot] [PATCH v4 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (11 preceding siblings ...)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:14 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 more replies)
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (6 subsequent siblings)
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:14 UTC (permalink / raw)
  To: u-boot

rk3xxx.dtsi is used by rk3188 and rk3066. rk3188 uses alocated data in spl but rk3066 needs it in tpl.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/dts/rk3xxx.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/dts/rk3xxx.dtsi b/arch/arm/dts/rk3xxx.dtsi
index 6d9e36d..d1c205b 100644
--- a/arch/arm/dts/rk3xxx.dtsi
+++ b/arch/arm/dts/rk3xxx.dtsi
@@ -135,7 +135,7 @@
 	};
 
 	noc: syscon at 10128000 {
-		u-boot,dm-spl;
+		u-boot,dm-pre-reloc;
 		compatible = "rockchip,rk3188-noc", "syscon";
 		reg = <0x10128000 0x2000>;
 	};
@@ -218,13 +218,13 @@
 	pmu: pmu at 20004000 {
 		compatible = "rockchip,rk3066-pmu", "syscon";
 		reg = <0x20004000 0x100>;
-		u-boot,dm-spl;
+		u-boot,dm-pre-reloc;
 	};
 
 	grf: grf at 20008000 {
 		compatible = "syscon";
 		reg = <0x20008000 0x200>;
-		u-boot,dm-spl;
+		u-boot,dm-pre-reloc;
 	};
 
 	dmc: dmc at 20020000 {
@@ -238,7 +238,7 @@
 		       0x20040000 0x294>;
 		clocks = <&cru PCLK_DDRUPCTL>, <&cru PCLK_PUBL>;
 		clock-names = "pclk_ddrupctl", "pclk_publ";
-		u-boot,dm-spl;
+		u-boot,dm-pre-reloc;
 	};
 
 	i2c0: i2c at 2002d000 {
-- 
2.7.4

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

* [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (12 preceding siblings ...)
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:15 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18  7:02   ` Jaehoon Chung
                     ` (3 more replies)
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (5 subsequent siblings)
  19 siblings, 4 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:15 UTC (permalink / raw)
  To: u-boot

dw_mmc supports two transfer modes in u-boot: idma and fifo.
This patch adds autodetection of transfer mode and eliminates setting this in host config struct

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- none

 drivers/mmc/dw_mmc.c | 8 ++++++++
 include/dwmmc.h      | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 700f764..2cc4d67 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -428,6 +428,7 @@ static int dwmci_set_ios(struct mmc *mmc)
 static int dwmci_init(struct mmc *mmc)
 {
 	struct dwmci_host *host = mmc->priv;
+	uint32_t use_dma;
 
 	if (host->board_init)
 		host->board_init(host);
@@ -439,6 +440,13 @@ static int dwmci_init(struct mmc *mmc)
 		return -EIO;
 	}
 
+	use_dma = SDMMC_GET_TRANS_MODE(dwmci_readl(host, DWMCI_HCON));
+	if (use_dma == DMA_INTERFACE_IDMA) {
+		host->fifo_mode = 0;
+	} else {
+		host->fifo_mode = 1;
+	}
+
 	/* Enumerate at 400KHz */
 	dwmci_setup_bus(host, mmc->cfg->f_min);
 
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 4dda009..269536d 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -115,6 +115,10 @@
 #define RX_WMARK_SHIFT		16
 #define RX_WMARK_MASK		(0xfff << RX_WMARK_SHIFT)
 
+/* HCON Register */
+#define DMA_INTERFACE_IDMA		(0x0)
+#define SDMMC_GET_TRANS_MODE(x)		(((x)>>16) & 0x3)
+
 #define DWMCI_IDMAC_OWN		(1 << 31)
 #define DWMCI_IDMAC_CH		(1 << 4)
 #define DWMCI_IDMAC_FS		(1 << 3)
-- 
2.7.4

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

* [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (13 preceding siblings ...)
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:15 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18  7:02   ` Jaehoon Chung
                     ` (3 more replies)
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 16/19] armv7: support rk3066 early back to bootrom in vector.S =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (4 subsequent siblings)
  19 siblings, 4 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:15 UTC (permalink / raw)
  To: u-boot

This patch enables support for the Rockchip RK3066 SD/MMC controller, which is based on Designware IP. The device supports SD, SDIO, MMC and eMMC.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- dropped OF_PLATDATA

Changes since v2:
- none

Changes since v3:
- none

 drivers/mmc/rockchip_dw_mmc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index e7fcf89..a879fcd 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -160,6 +160,7 @@ static int rockchip_dwmmc_bind(struct udevice *dev)
 
 static const struct udevice_id rockchip_dwmmc_ids[] = {
 	{ .compatible = "rockchip,rk3288-dw-mshc" },
+	{ .compatible = "rockchip,rk2928-dw-mshc" },
 	{ }
 };
 
-- 
2.7.4

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

* [U-Boot] [PATCH v4 16/19] armv7: support rk3066 early back to bootrom in vector.S
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (14 preceding siblings ...)
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:16 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:54   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:16 UTC (permalink / raw)
  To: u-boot

Rockchip bootrom first reads 1KB data from nand at offset 0x10080C00 and
executes it. Then waits for back to bootrom and loads another 32KB to sram
which also executes. Sdram initialisation code needs to be in one of these two
steps. Then bootloader loads another ~200KB of data at offset 0x60000000
and jumps to it.

32KB of data is a little low for tpl + spl part and ~200KB data is to low for
u-boot part(for example to boot from mmc you need to disable usb support.

My solution to size problem is to move sdram initialisation code to tpl stage,
move spl part to third stage(reading 200KB data) and add support for loading
u-boot by spl from ext2/4, fat partitions.

But moving sdram initialisation code to tpl increases size of tpl above 1KB
(first boot stage). Solution to this is to add code which will be below 1KB
offset in tpl binary and do back to bootrom at very beginning of the tpl
execution.

Adding this few lines of code here meets these conditions.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
Changes since v1:
- moved to vector.S

Changes since v2:
- none

Changes since v3:
- none

 arch/arm/include/asm/arch-rockchip/boot0.h | 14 ++++++++++++++
 arch/arm/lib/vectors.S                     | 18 +++++++++---------
 configs/mk808_defconfig                    |  1 +
 3 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/boot0.h b/arch/arm/include/asm/arch-rockchip/boot0.h
index 72d264b..4179448 100644
--- a/arch/arm/include/asm/arch-rockchip/boot0.h
+++ b/arch/arm/include/asm/arch-rockchip/boot0.h
@@ -5,6 +5,19 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#if defined(CONFIG_ROCKCHIP_RK3066) && defined(CONFIG_TPL_BUILD)
+	ldr	r3, =0x10080900
+	ldr	r0, [r3]
+	cmp	r0, #1
+	movne	r0, #1
+	strne	r0, [r3]
+	beq	out_of_bootrom
+	bx	lr
+out_of_bootrom:
+	mov	r0, #0
+	str	r0, [r3]
+#endif
+
 /*
  * Execution starts on the instruction following this 4-byte header
  * (containing the magic 'RK33').
@@ -26,6 +39,7 @@
 	 */
 	b reset	 /* may be overwritten --- should be 'nop' or a 'b reset' */
 #endif
+
 	b reset
 
 #if defined(CONFIG_ROCKCHIP_RK3399) && defined(CONFIG_SPL_BUILD)
diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S
index 1019091..e3c18da 100644
--- a/arch/arm/lib/vectors.S
+++ b/arch/arm/lib/vectors.S
@@ -47,6 +47,15 @@
 
 _start:
 
+#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
+/*
+ * Various SoCs need something special and SoC-specific up front in
+ * order to boot, allow them to set that in their boot0.h file and then
+ * use it here.
+ */
+#include <asm/arch/boot0.h>
+#endif
+
 #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
 	.word	CONFIG_SYS_DV_NOR_BOOT_CFG
 #endif
@@ -60,15 +69,6 @@ _start:
 	ldr	pc, _irq
 	ldr	pc, _fiq
 
-#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
-/*
- * Various SoCs need something special and SoC-specific up front in
- * order to boot, allow them to set that in their boot0.h file and then
- * use it here.
- */
-#include <asm/arch/boot0.h>
-#endif
-
 /*
  *************************************************************************
  *
diff --git a/configs/mk808_defconfig b/configs/mk808_defconfig
index ab67e4f..bf4af82 100644
--- a/configs/mk808_defconfig
+++ b/configs/mk808_defconfig
@@ -13,6 +13,7 @@ CONFIG_USE_PRIVATE_LIBGCC=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_SYS_NS16550=y
+CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y
 CONFIG_BOOTDELAY=1
 CONFIG_CONSOLE_MUX=y
 CONFIG_DISPLAY_BOARDINFO=y
-- 
2.7.4

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

* [U-Boot] [PATCH v4 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (15 preceding siblings ...)
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 16/19] armv7: support rk3066 early back to bootrom in vector.S =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:16 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 more replies)
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 18/19] dfu: fix spl build =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (2 subsequent siblings)
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:16 UTC (permalink / raw)
  To: u-boot

Sysreset drivers for rk3066 and rk3188 contain common elements which can be reused.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- none

 .../include/asm/arch-rockchip/sysreset_common.h    | 20 +++++++++++
 arch/arm/mach-rockchip/Makefile                    |  3 ++
 arch/arm/mach-rockchip/sysreset-common.c           | 39 ++++++++++++++++++++++
 drivers/sysreset/sysreset_rk3066.c                 | 34 ++++++-------------
 drivers/sysreset/sysreset_rk3188.c                 | 35 ++++++-------------
 5 files changed, 84 insertions(+), 47 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-rockchip/sysreset_common.h
 create mode 100644 arch/arm/mach-rockchip/sysreset-common.c

diff --git a/arch/arm/include/asm/arch-rockchip/sysreset_common.h b/arch/arm/include/asm/arch-rockchip/sysreset_common.h
new file mode 100644
index 0000000..c7e1fc0
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sysreset_common.h
@@ -0,0 +1,20 @@
+/*
+ * (C) Copyright 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_SYSRESET_COMMON_H
+#define _ASM_ARCH_SYSRESET_COMMON_H
+
+struct rockchip_sysreset_data {
+	void *grf_soc_con0;
+	uint32_t noc_remap_mask;
+	void *cru_mode_con;
+	void *cru_glb_srst_snd_value;
+	void *cru_glb_srst_fst_value;
+};
+
+int rockchip_sysreset_request(struct rockchip_sysreset_data *data,
+			      enum sysreset_t type);
+#endif
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index ae878ef..b58a9c4 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -11,6 +11,9 @@
 obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
 obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
 
+obj-$(CONFIG_ROCKCHIP_RK3066) += sysreset-common.o
+obj-$(CONFIG_ROCKCHIP_RK3188) += sysreset-common.o
+
 obj-tpl-$(CONFIG_ROCKCHIP_RK3066) += rk3066-board-tpl.o
 obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
 obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o
diff --git a/arch/arm/mach-rockchip/sysreset-common.c b/arch/arm/mach-rockchip/sysreset-common.c
new file mode 100644
index 0000000..41e76e3
--- /dev/null
+++ b/arch/arm/mach-rockchip/sysreset-common.c
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <sysreset.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sysreset_common.h>
+#include <linux/err.h>
+
+int rockchip_sysreset_request(struct rockchip_sysreset_data *data,
+			      enum sysreset_t type)
+{
+	switch (type) {
+	case SYSRESET_WARM:
+		/*
+		 * warm-reset keeps the remap value,
+		 * so make sure it's disabled.
+		 */
+		rk_clrsetreg(data->grf_soc_con0,
+			data->noc_remap_mask, 0);
+
+		rk_clrreg(data->cru_mode_con, 0xffff);
+		writel(0xeca8, data->cru_glb_srst_snd_value);
+		break;
+	case SYSRESET_COLD:
+		rk_clrreg(data->cru_mode_con, 0xffff);
+		writel(0xfdb9, data->cru_glb_srst_fst_value);
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	return -EINPROGRESS;
+}
diff --git a/drivers/sysreset/sysreset_rk3066.c b/drivers/sysreset/sysreset_rk3066.c
index b5dcb9a..f82b3dd 100644
--- a/drivers/sysreset/sysreset_rk3066.c
+++ b/drivers/sysreset/sysreset_rk3066.c
@@ -14,40 +14,28 @@
 #include <asm/arch/cru_rk3066.h>
 #include <asm/arch/grf_rk3066.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sysreset_common.h>
 #include <linux/err.h>
 
 int rk3066_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
 	struct rk3066_cru *cru = rockchip_get_cru();
-	struct rk3066_grf *grf;
+	struct rk3066_grf *grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	struct rockchip_sysreset_data data = {
+			.grf_soc_con0 = &grf->soc_con0,
+			.noc_remap_mask = NOC_REMAP_MASK,
+			.cru_mode_con = &cru->cru_mode_con,
+			.cru_glb_srst_snd_value = &cru->cru_glb_srst_snd_value,
+			.cru_glb_srst_fst_value = &cru->cru_glb_srst_fst_value
+	};
 
 	if (IS_ERR(cru))
 		return PTR_ERR(cru);
 
-	switch (type) {
-	case SYSRESET_WARM:
-		grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
-		if (IS_ERR(grf))
-			return -EPROTONOSUPPORT;
-		/*
-		 * warm-reset keeps the remap value,
-		 * so make sure it's disabled.
-		 */
-		rk_clrsetreg(&grf->soc_con0,
-			NOC_REMAP_MASK, 0 << NOC_REMAP_SHIFT);
-
-		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:
+	if (IS_ERR(grf))
 		return -EPROTONOSUPPORT;
-	}
 
-	return -EINPROGRESS;
+	return rockchip_sysreset_request(&data, type);
 }
 
 static struct sysreset_ops rk3066_sysreset = {
diff --git a/drivers/sysreset/sysreset_rk3188.c b/drivers/sysreset/sysreset_rk3188.c
index 053a634..e924a02 100644
--- a/drivers/sysreset/sysreset_rk3188.c
+++ b/drivers/sysreset/sysreset_rk3188.c
@@ -14,41 +14,28 @@
 #include <asm/arch/cru_rk3188.h>
 #include <asm/arch/grf_rk3188.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sysreset_common.h>
 #include <linux/err.h>
 
 int rk3188_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
 	struct rk3188_cru *cru = rockchip_get_cru();
-	struct rk3188_grf *grf;
+	struct rk3188_grf *grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	struct rockchip_sysreset_data data = {
+			.grf_soc_con0 = &grf->soc_con0,
+			.noc_remap_mask = NOC_REMAP_MASK,
+			.cru_mode_con = &cru->cru_mode_con,
+			.cru_glb_srst_snd_value = &cru->cru_glb_srst_snd_value,
+			.cru_glb_srst_fst_value = &cru->cru_glb_srst_fst_value
+	};
 
 	if (IS_ERR(cru))
 		return PTR_ERR(cru);
-	switch (type) {
-	case SYSRESET_WARM:
-		grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
-		if (IS_ERR(grf))
-			return -EPROTONOSUPPORT;
 
-		/*
-		 * warm-reset keeps the remap value,
-		 * so make sure it's disabled.
-		 */
-		rk_clrsetreg(&grf->soc_con0,
-			NOC_REMAP_MASK << NOC_REMAP_SHIFT,
-			0 << NOC_REMAP_SHIFT);
-
-		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:
+	if (IS_ERR(grf))
 		return -EPROTONOSUPPORT;
-	}
 
-	return -EINPROGRESS;
+	return rockchip_sysreset_request(&data, type);
 }
 
 static struct sysreset_ops rk3188_sysreset = {
-- 
2.7.4

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

* [U-Boot] [PATCH v4 18/19] dfu: fix spl build
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (16 preceding siblings ...)
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:16 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot,v4,18/19] " Philipp Tomsich
                     ` (2 more replies)
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-21 15:46 ` [U-Boot] [PATCH v4 00/19] add support for rk3066 platform Bin Meng
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:16 UTC (permalink / raw)
  To: u-boot

In current state dfu depends on cmd/mtdparts.c which isn't build in SPL.
This patch resolves it by cutting out unwanted code in SPL build.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- removed unneded space

 drivers/dfu/dfu_nand.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
index 6dc9ff7..23dfc8e 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -192,8 +192,9 @@ unsigned int dfu_polltimeout_nand(struct dfu_entity *dfu)
 int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s)
 {
 	char *st;
+#ifndef CONFIG_SPL_BUILD
 	int ret, dev, part;
-
+#endif
 	dfu->data.nand.ubi = 0;
 	dfu->dev_type = DFU_DEV_NAND;
 	st = strsep(&s, " ");
@@ -203,6 +204,7 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s)
 		s++;
 		dfu->data.nand.size = simple_strtoul(s, &s, 16);
 	} else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) {
+#ifndef CONFIG_SPL_BUILD
 		char mtd_id[32];
 		struct mtd_device *mtd_dev;
 		u8 part_num;
@@ -229,6 +231,7 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s)
 		dfu->data.nand.size = pi->size;
 		if (!strcmp(st, "partubi"))
 			dfu->data.nand.ubi = 1;
+#endif
 	} else {
 		printf("%s: Memory layout (%s) not supported!\n", __func__, st);
 		return -1;
-- 
2.7.4

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

* [U-Boot] [PATCH v4 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (17 preceding siblings ...)
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 18/19] dfu: fix spl build =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-17 13:16 ` =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 more replies)
  2017-08-21 15:46 ` [U-Boot] [PATCH v4 00/19] add support for rk3066 platform Bin Meng
  19 siblings, 3 replies; 64+ messages in thread
From: =?UTF-8?q?Pawe=C5=82=20Jarosz?= @ 2017-08-17 13:16 UTC (permalink / raw)
  To: u-boot

This patch allows building of nand_bbt, nand_ids, nand_util for nand drivers that need it.

Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
---
Changes since v1:
- none

Changes since v2:
- none

Changes since v3:
- none

 drivers/mtd/nand/Makefile | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 0659253..9062c2e 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -18,6 +18,9 @@ obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
 obj-$(CONFIG_SPL_NAND_BASE) += nand_base.o
 obj-$(CONFIG_SPL_NAND_INIT) += nand.o
+obj-$(CONFIG_SPL_NAND_BBT) += nand_bbt.o
+obj-$(CONFIG_SPL_NAND_IDS) += nand_ids.o
+obj-$(CONFIG_SPL_NAND_UTIL) += nand_util.o
 ifeq ($(CONFIG_SPL_ENV_SUPPORT),y)
 obj-$(CONFIG_ENV_IS_IN_NAND) += nand_util.o
 endif
-- 
2.7.4

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

* [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18  7:02   ` Jaehoon Chung
  2017-08-18  9:36     ` Paweł Jarosz
  2017-08-18 12:51   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 64+ messages in thread
From: Jaehoon Chung @ 2017-08-18  7:02 UTC (permalink / raw)
  To: u-boot

On 08/17/2017 10:15 PM, =?UTF-8?q?Pawe=C5=82=20Jarosz?= wrote:
> dw_mmc supports two transfer modes in u-boot: idma and fifo.
> This patch adds autodetection of transfer mode and eliminates setting this in host config struct
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mmc/dw_mmc.c | 8 ++++++++
>  include/dwmmc.h      | 4 ++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
> index 700f764..2cc4d67 100644
> --- a/drivers/mmc/dw_mmc.c
> +++ b/drivers/mmc/dw_mmc.c
> @@ -428,6 +428,7 @@ static int dwmci_set_ios(struct mmc *mmc)
>  static int dwmci_init(struct mmc *mmc)
>  {
>  	struct dwmci_host *host = mmc->priv;
> +	uint32_t use_dma;

Does it need to use unit32_t for use_dma?

>  
>  	if (host->board_init)
>  		host->board_init(host);
> @@ -439,6 +440,13 @@ static int dwmci_init(struct mmc *mmc)
>  		return -EIO;
>  	}
>  
> +	use_dma = SDMMC_GET_TRANS_MODE(dwmci_readl(host, DWMCI_HCON));
> +	if (use_dma == DMA_INTERFACE_IDMA) {
> +		host->fifo_mode = 0;
> +	} else {
> +		host->fifo_mode = 1;
> +	}

Don't need to use the brackets.

Best Regards,
Jaehoon Chung

> +
>  	/* Enumerate at 400KHz */
>  	dwmci_setup_bus(host, mmc->cfg->f_min);
>  
> diff --git a/include/dwmmc.h b/include/dwmmc.h
> index 4dda009..269536d 100644
> --- a/include/dwmmc.h
> +++ b/include/dwmmc.h
> @@ -115,6 +115,10 @@
>  #define RX_WMARK_SHIFT		16
>  #define RX_WMARK_MASK		(0xfff << RX_WMARK_SHIFT)
>  
> +/* HCON Register */
> +#define DMA_INTERFACE_IDMA		(0x0)
> +#define SDMMC_GET_TRANS_MODE(x)		(((x)>>16) & 0x3)
> +
>  #define DWMCI_IDMAC_OWN		(1 << 31)
>  #define DWMCI_IDMAC_CH		(1 << 4)
>  #define DWMCI_IDMAC_FS		(1 << 3)
> 

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

* [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18  7:02   ` Jaehoon Chung
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 64+ messages in thread
From: Jaehoon Chung @ 2017-08-18  7:02 UTC (permalink / raw)
  To: u-boot

On 08/17/2017 10:15 PM, =?UTF-8?q?Pawe=C5=82=20Jarosz?= wrote:
> This patch enables support for the Rockchip RK3066 SD/MMC controller, which is based on Designware IP. The device supports SD, SDIO, MMC and eMMC.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

> ---
> Changes since v1:
> - dropped OF_PLATDATA
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mmc/rockchip_dw_mmc.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
> index e7fcf89..a879fcd 100644
> --- a/drivers/mmc/rockchip_dw_mmc.c
> +++ b/drivers/mmc/rockchip_dw_mmc.c
> @@ -160,6 +160,7 @@ static int rockchip_dwmmc_bind(struct udevice *dev)
>  
>  static const struct udevice_id rockchip_dwmmc_ids[] = {
>  	{ .compatible = "rockchip,rk3288-dw-mshc" },
> +	{ .compatible = "rockchip,rk2928-dw-mshc" },
>  	{ }
>  };
>  
> 

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

* [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection
  2017-08-18  7:02   ` Jaehoon Chung
@ 2017-08-18  9:36     ` Paweł Jarosz
  0 siblings, 0 replies; 64+ messages in thread
From: Paweł Jarosz @ 2017-08-18  9:36 UTC (permalink / raw)
  To: u-boot

Hi,


W dniu 18.08.2017 o 09:02, Jaehoon Chung pisze:
> On 08/17/2017 10:15 PM, =?UTF-8?q?Pawe=C5=82=20Jarosz?= wrote:
>> dw_mmc supports two transfer modes in u-boot: idma and fifo.
>> This patch adds autodetection of transfer mode and eliminates setting this in host config struct
>>
>> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
>> ---
>> Changes since v1:
>> - none
>>
>> Changes since v2:
>> - none
>>
>> Changes since v3:
>> - none
>>
>>   drivers/mmc/dw_mmc.c | 8 ++++++++
>>   include/dwmmc.h      | 4 ++++
>>   2 files changed, 12 insertions(+)
>>
>> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
>> index 700f764..2cc4d67 100644
>> --- a/drivers/mmc/dw_mmc.c
>> +++ b/drivers/mmc/dw_mmc.c
>> @@ -428,6 +428,7 @@ static int dwmci_set_ios(struct mmc *mmc)
>>   static int dwmci_init(struct mmc *mmc)
>>   {
>>   	struct dwmci_host *host = mmc->priv;
>> +	uint32_t use_dma;
> Does it need to use unit32_t for use_dma?

SDMMC_GET_TRANS_MODE returns 2 bit value so i guess it can be uint8_t.

>>   
>>   	if (host->board_init)
>>   		host->board_init(host);
>> @@ -439,6 +440,13 @@ static int dwmci_init(struct mmc *mmc)
>>   		return -EIO;
>>   	}
>>   
>> +	use_dma = SDMMC_GET_TRANS_MODE(dwmci_readl(host, DWMCI_HCON));
>> +	if (use_dma == DMA_INTERFACE_IDMA) {
>> +		host->fifo_mode = 0;
>> +	} else {
>> +		host->fifo_mode = 1;
>> +	}
> Don't need to use the brackets.

i will do that in the next version.

Thanks for your comments.

Regards,
Paweł

> Best Regards,
> Jaehoon Chung
>
>> +
>>   	/* Enumerate at 400KHz */
>>   	dwmci_setup_bus(host, mmc->cfg->f_min);
>>   
>> diff --git a/include/dwmmc.h b/include/dwmmc.h
>> index 4dda009..269536d 100644
>> --- a/include/dwmmc.h
>> +++ b/include/dwmmc.h
>> @@ -115,6 +115,10 @@
>>   #define RX_WMARK_SHIFT		16
>>   #define RX_WMARK_MASK		(0xfff << RX_WMARK_SHIFT)
>>   
>> +/* HCON Register */
>> +#define DMA_INTERFACE_IDMA		(0x0)
>> +#define SDMMC_GET_TRANS_MODE(x)		(((x)>>16) & 0x3)
>> +
>>   #define DWMCI_IDMAC_OWN		(1 << 31)
>>   #define DWMCI_IDMAC_CH		(1 << 4)
>>   #define DWMCI_IDMAC_FS		(1 << 3)
>>

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

* [U-Boot] [U-Boot, v4, 04/19] rockchip: rk3066: add clock driver for rk3066 soc
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 04/19] rockchip: rk3066: add clock driver for rk3066 soc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 11:26   ` Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 11:26 UTC (permalink / raw)
  To: u-boot



On Thu, 17 Aug 2017, Paweł Jarosz wrote:

> Add clock driver for rk3066 platform.
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
> ---
> Changes since v1:
> - updated to shifted masks
> - moved clk init to tpl
>
> Changes since v2:
> - none
>
> Changes since v3:
> - none
>
> arch/arm/include/asm/arch-rockchip/cru_rk3066.h | 189 ++++++++
> drivers/clk/rockchip/Makefile                   |   1 +
> drivers/clk/rockchip/clk_rk3066.c               | 587 ++++++++++++++++++++++++
> 3 files changed, 777 insertions(+)
> create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rk3066.h
> create mode 100644 drivers/clk/rockchip/clk_rk3066.c
>
> diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3066.h b/arch/arm/include/asm/arch-rockchip/cru_rk3066.h
> new file mode 100644
> index 0000000..c4a6951
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3066.h
> @@ -0,0 +1,189 @@
> +/*
> + * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +#ifndef _ASM_ARCH_CRU_RK3066_H
> +#define _ASM_ARCH_CRU_RK3066_H
> +
> +#define OSC_HZ		(24 * 1000 * 1000)
> +
> +#define APLL_HZ		(1416 * 1000000)
> +#define APLL_SAFE_HZ	(600 * 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 rk3066_clk_priv {
> +	struct rk3066_grf *grf;
> +	struct rk3066_cru *cru;
> +	ulong rate;

I don't see the 'rate' field of the priv-structure ever used.
Did I miss something?

> +	bool has_bwadj;

I can't find any way to set 'has_bwadj' to 'true' in the below code.
If this is not needed, has_bwadj should be removed/codepaths should be 
eliminated.  If it is needed/recommended, it should always be used for
those PLLs that support bandwidth adjustment.

> +};
> +
> +struct rk3066_cru {
> +	struct rk3066_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(rk3066_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 << A9_CORE_DIV_SHIFT,
> +	CORE_PLL_SHIFT		= 8,
> +	CORE_PLL_MASK		= 1 << CORE_PLL_SHIFT,
> +	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 << CORE_PERI_DIV_SHIFT,
> +
> +	/* aclk_cpu pll selection */
> +	CPU_ACLK_PLL_SHIFT	= 5,
> +	CPU_ACLK_PLL_MASK	= 1 << CPU_ACLK_PLL_SHIFT,
> +	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 << A9_CPU_DIV_SHIFT,
> +};
> +
> +/* 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 << AHB2APB_DIV_SHIFT,
> +
> +	/* 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_PCLK_DIV_SHIFT,
> +
> +	/* cpu_hclk_div: aclk_cpu:hclk_cpu = 1:1, 2:1 or 4:1 */
> +	CPU_HCLK_DIV_SHIFT	= 8,
> +	CPU_HCLK_DIV_MASK	= 3 << CPU_HCLK_DIV_SHIFT,
> +
> +	/* 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 << CORE_ACLK_DIV_SHIFT,
> +};
> +
> +/* CRU_CLKSEL10_CON */
> +enum {
> +	PERI_SEL_PLL_SHIFT	= 15,
> +	PERI_SEL_PLL_MASK	= 1 << PERI_SEL_PLL_SHIFT,
> +	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 << PERI_PCLK_DIV_SHIFT,
> +
> +	/* 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_HCLK_DIV_SHIFT,
> +
> +	/* peri aclk div: aclk_peri = periph_src / (peri_aclk_div + 1) */
> +	PERI_ACLK_DIV_SHIFT	= 0,
> +	PERI_ACLK_DIV_MASK	= 0x1f << PERI_ACLK_DIV_SHIFT,
> +};
> +/* CRU_CLKSEL11_CON */
> +enum {
> +	MMC0_DIV_SHIFT		= 0,
> +	MMC0_DIV_MASK		= 0x3f << MMC0_DIV_SHIFT,
> +};
> +
> +/* CRU_CLKSEL12_CON */
> +enum {
> +	UART_PLL_SHIFT		= 15,
> +	UART_PLL_MASK		= 1 << UART_PLL_SHIFT,
> +	UART_PLL_SELECT_GENERAL	= 0,
> +	UART_PLL_SELECT_CODEC,
> +
> +	EMMC_DIV_SHIFT		= 8,
> +	EMMC_DIV_MASK		= 0x3f << EMMC_DIV_SHIFT,
> +
> +	SDIO_DIV_SHIFT		= 0,
> +	SDIO_DIV_MASK		= 0x3f << SDIO_DIV_SHIFT,
> +};
> +
> +/* CRU_CLKSEL25_CON */
> +enum {
> +	SPI1_DIV_SHIFT		= 8,
> +	SPI1_DIV_MASK		= 0x7f << SPI1_DIV_SHIFT,
> +
> +	SPI0_DIV_SHIFT		= 0,
> +	SPI0_DIV_MASK		= 0x7f << SPI0_DIV_SHIFT,
> +};
> +
> +/* CRU_MODE_CON */
> +enum {
> +	GPLL_MODE_SHIFT		= 12,
> +	GPLL_MODE_MASK		= 3 << GPLL_MODE_SHIFT,
> +	GPLL_MODE_SLOW		= 0,
> +	GPLL_MODE_NORMAL,
> +	GPLL_MODE_DEEP,
> +
> +	CPLL_MODE_SHIFT		= 8,
> +	CPLL_MODE_MASK		= 3 << CPLL_MODE_SHIFT,
> +	CPLL_MODE_SLOW		= 0,
> +	CPLL_MODE_NORMAL,
> +	CPLL_MODE_DEEP,
> +
> +	DPLL_MODE_SHIFT		= 4,
> +	DPLL_MODE_MASK		= 3 << DPLL_MODE_SHIFT,
> +	DPLL_MODE_SLOW		= 0,
> +	DPLL_MODE_NORMAL,
> +	DPLL_MODE_DEEP,
> +
> +	APLL_MODE_SHIFT		= 0,
> +	APLL_MODE_MASK		= 3 << APLL_MODE_SHIFT,
> +	APLL_MODE_SLOW		= 0,
> +	APLL_MODE_NORMAL,
> +	APLL_MODE_DEEP,
> +};
> +
> +/* CRU_APLL_CON0 */
> +enum {
> +	CLKR_SHIFT		= 8,
> +	CLKR_MASK		= 0x3f << CLKR_SHIFT,
> +
> +	CLKOD_SHIFT		= 0,
> +	CLKOD_MASK		= 0x3f << CLKOD_SHIFT,
> +};
> +
> +/* CRU_APLL_CON1 */
> +enum {
> +	CLKF_SHIFT		= 0,
> +	CLKF_MASK		= 0x1fff << CLKF_SHIFT,
> +};
> +
> +#endif
> diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
> index c50aff2..167b08e 100644
> --- a/drivers/clk/rockchip/Makefile
> +++ b/drivers/clk/rockchip/Makefile
> @@ -5,6 +5,7 @@
> #
>
> obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
> +obj-$(CONFIG_ROCKCHIP_RK3066) += clk_rk3066.o
> obj-$(CONFIG_ROCKCHIP_RK3188) += clk_rk3188.o
> obj-$(CONFIG_ROCKCHIP_RK322X) += clk_rk322x.o
> obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
> diff --git a/drivers/clk/rockchip/clk_rk3066.c b/drivers/clk/rockchip/clk_rk3066.c
> new file mode 100644
> index 0000000..bcf65e0
> --- /dev/null
> +++ b/drivers/clk/rockchip/clk_rk3066.c
> @@ -0,0 +1,587 @@
> +/*
> + * (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_rk3066.h>
> +#include <asm/arch/grf_rk3066.h>
> +#include <asm/arch/hardware.h>
> +#include <dt-bindings/clock/rk3066a-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 rk3066_clk_type {
> +	RK3066_CRU,
> +	RK3066A_CRU,
> +};
> +
> +struct rk3066_clk_plat {
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +	struct dtd_rockchip_rk3066a_cru dtd;
> +#endif
> +};
> +
> +struct pll_div {
> +	u32 nr;
> +	u32 nf;
> +	u32 no;
> +};
> +
> +enum {
> +	VCO_MAX_HZ	= 1416U * 1000000,
> +	VCO_MIN_HZ	= 300 * 1000000,
> +	OUTPUT_MAX_HZ	= 1416U * 1000000,
> +	OUTPUT_MIN_HZ	= 30 * 1000000,
> +	FREF_MAX_HZ	= 1416U * 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,

Please use GENMASK(..., ...).

> +
> +	/* PLL CON3 */
> +	PLL_RESET_SHIFT		= 5,
> +
> +	/* GRF_SOC_STATUS0 */
> +	SOCSTS_DPLL_LOCK	= 1 << 4,
> +	SOCSTS_APLL_LOCK	= 1 << 5,
> +	SOCSTS_CPLL_LOCK	= 1 << 6,
> +	SOCSTS_GPLL_LOCK	= 1 << 7,

Please use BIT(...).

> +};
> +
> +#define RATE_TO_DIV(input_rate, output_rate) \
> +	((input_rate) / (output_rate) - 1);

Kever just removed this from all other clock-drivers.

Could you track this change in this clock driver (sorry...)?
A separate, additional patch is fine, if you prefer.

> +
> +#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 */
> +#ifdef CONFIG_TPL_BUILD
> +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);
> +#endif
> +
> +static int rkclk_set_pll(struct rk3066_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 rk3066_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);

I'd prefer BIT(PLL_RESET_SHIFT).

> +
> +	rk_clrsetreg(&pll->con0,
> +		     CLKR_MASK | 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);

Why the udelay() and not polling the PLL to signal that it 
locked/is stable?

> +
> +	/* return from reset */
> +	rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT);

Again, I would prefer BIT(PLL_RESET_SHIFT).

> +
> +	return 0;
> +}
> +
> +static int rkclk_configure_ddr(struct rk3066_cru *cru, struct rk3066_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_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_NORMAL << DPLL_MODE_SHIFT);
> +
> +	return 0;
> +}
> +
> +static int rkclk_configure_cpu(struct rk3066_cru *cru, struct rk3066_grf *grf,
> +			      unsigned int hz, bool has_bwadj)
> +{
> +	static const struct pll_div apll_cfg[] = {
> +		{.nf = 50, .nr = 1, .no = 2},
> +		{.nf = 59, .nr = 1, .no = 1},
> +	};
> +	int div_core_peri, div_aclk_core, cfg;
> +
> +	/*
> +	 * We support two possible frequencies, the safe 600MHz
> +	 * which will work with default pmic settings and will
> +	 * be set to get away from the 24MHz default and
> +	 * the maximum of 1.416Ghz, which boards can set if they
> +	 * were able to get pmic support for it.
> +	 */
> +	switch (hz) {
> +	case APLL_SAFE_HZ:
> +		cfg = 0;
> +		div_core_peri = 1;
> +		div_aclk_core = 3;
> +		break;
> +	case APLL_HZ:
> +		cfg = 1;
> +		div_core_peri = 2;
> +		div_aclk_core = 3;
> +		break;
> +	default:
> +		debug("Unsupported ARMCLK frequency");
> +		return -EINVAL;
> +	}
> +
> +	/* pll enter slow-mode */
> +	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
> +		     APLL_MODE_SLOW << APLL_MODE_SHIFT);
> +
> +	rkclk_set_pll(cru, CLK_ARM, &apll_cfg[cfg], has_bwadj);
> +
> +	/* waiting for pll lock */
> +	while (!(readl(&grf->soc_status0) & SOCSTS_APLL_LOCK))
> +		udelay(1);
> +
> +	/* Set divider for peripherals attached to the cpu core. */
> +	rk_clrsetreg(&cru->cru_clksel_con[0],
> +		CORE_PERI_DIV_MASK,
> +		div_core_peri << CORE_PERI_DIV_SHIFT);
> +
> +	/* set up dependent divisor for aclk_core */
> +	rk_clrsetreg(&cru->cru_clksel_con[1],
> +		CORE_ACLK_DIV_MASK,
> +		div_aclk_core << CORE_ACLK_DIV_SHIFT);
> +
> +	/* PLL enter normal-mode */
> +	rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
> +		     APLL_MODE_NORMAL << APLL_MODE_SHIFT);
> +
> +	return hz;
> +}
> +
> +/* Get pll rate by id */
> +static uint32_t rkclk_pll_get_rate(struct rk3066_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 rk3066_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 >> APLL_MODE_SHIFT) {
> +	case APLL_MODE_SLOW:
> +		return OSC_HZ;
> +	case APLL_MODE_NORMAL:
> +		/* normal mode */
> +		con = readl(&pll->con0);
> +		no = ((con >> CLKOD_SHIFT) & (CLKOD_MASK >> CLKOD_SHIFT)) + 1;

Could you use 'bitfield_extract' from include/bitfield.h?

> +		nr = ((con >> CLKR_SHIFT) & (CLKR_MASK >> CLKR_SHIFT)) + 1;
> +		con = readl(&pll->con1);
> +		nf = ((con >> CLKF_SHIFT) & (CLKF_MASK >> CLKF_SHIFT)) + 1;
> +

Same.

> +		return (24 * nf / (nr * no)) * 1000000;

Shouldn't this be (OSZ_HZ * nf) / (nr * no)?

> +	case APLL_MODE_DEEP:
> +	default:
> +		return 32768;
> +	}
> +}
> +
> +static ulong rockchip_mmc_get_clk(struct rk3066_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 >> EMMC_DIV_SHIFT;
> +		break;
> +	case HCLK_SDMMC:
> +		con = readl(&cru->cru_clksel_con[11]);
> +		div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK >> MMC0_DIV_SHIFT;
> +		break;
> +	case HCLK_SDIO:
> +		con = readl(&cru->cru_clksel_con[12]);
> +		div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK >> SDIO_DIV_SHIFT;

Again, can we use bitfield.h?

> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return DIV_TO_RATE(gclk_rate, div);
> +}
> +
> +static ulong rockchip_mmc_set_clk(struct rk3066_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);
> +	if (src_clk_div > 0x3f)
> +		src_clk_div = 0x3f;
> +
> +	switch (periph) {
> +	case HCLK_EMMC:
> +		rk_clrsetreg(&cru->cru_clksel_con[12],
> +			     EMMC_DIV_MASK,
> +			     src_clk_div << EMMC_DIV_SHIFT);
> +		break;
> +	case HCLK_SDMMC:
> +		rk_clrsetreg(&cru->cru_clksel_con[11],
> +			     MMC0_DIV_MASK,
> +			     src_clk_div << MMC0_DIV_SHIFT);
> +		break;
> +	case HCLK_SDIO:
> +		rk_clrsetreg(&cru->cru_clksel_con[12],
> +			     SDIO_DIV_MASK,
> +			     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 rk3066_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 >> SPI0_DIV_SHIFT;
> +		break;
> +	case SCLK_SPI1:
> +		con = readl(&cru->cru_clksel_con[25]);
> +		div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK >> SPI1_DIV_SHIFT;
> +		break;

See above.

> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return DIV_TO_RATE(gclk_rate, div);
> +}
> +
> +static ulong rockchip_spi_set_clk(struct rk3066_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 >> SPI0_DIV_SHIFT);
> +		rk_clrsetreg(&cru->cru_clksel_con[25],
> +			     SPI0_DIV_MASK,
> +			     src_clk_div << SPI0_DIV_SHIFT);
> +		break;
> +	case SCLK_SPI1:
> +		assert(src_clk_div <= SPI1_DIV_MASK >> SPI1_DIV_SHIFT);
> +		rk_clrsetreg(&cru->cru_clksel_con[25],
> +			     SPI1_DIV_MASK,
> +			     src_clk_div << SPI1_DIV_SHIFT);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return rockchip_spi_get_clk(cru, gclk_rate, periph);
> +}
> +#ifdef CONFIG_TPL_BUILD
> +static void rkclk_init(struct rk3066_cru *cru, struct rk3066_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 |
> +		     CPLL_MODE_MASK,
> +		     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 |
> +		     A9_CPU_DIV_MASK,
> +		     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 |
> +		     CPU_PCLK_DIV_MASK |
> +		     CPU_HCLK_DIV_MASK,
> +		     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_HCLK_DIV_MASK |
> +		     PERI_ACLK_DIV_MASK,
> +		     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 |
> +		     CPLL_MODE_MASK,
> +		     GPLL_MODE_NORMAL << GPLL_MODE_SHIFT |
> +		     CPLL_MODE_NORMAL << CPLL_MODE_SHIFT);
> +
> +	rockchip_mmc_set_clk(cru, PERI_HCLK_HZ, HCLK_SDMMC, 16000000);

Why is this 'rockchip_mmc_set_clk' necessary here?
Will this not be requested by the MMC driver?

> +}
> +#endif
> +
> +static ulong rk3066_clk_get_rate(struct clk *clk)
> +{
> +	struct rk3066_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 rk3066_clk_set_rate(struct clk *clk, ulong rate)
> +{
> +	struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
> +	struct rk3066_cru *cru = priv->cru;
> +	ulong new_rate;
> +
> +	switch (clk->id) {
> +	case PLL_APLL:
> +		new_rate = rkclk_configure_cpu(priv->cru, priv->grf, rate,
> +					       priv->has_bwadj);
> +		break;
> +	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 rk3066_clk_ops = {
> +	.get_rate	= rk3066_clk_get_rate,
> +	.set_rate	= rk3066_clk_set_rate,
> +};
> +
> +static int rk3066_clk_ofdata_to_platdata(struct udevice *dev)
> +{
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> +	struct rk3066_clk_priv *priv = dev_get_priv(dev);
> +
> +	priv->cru = (struct rk3066_cru *)devfdt_get_addr(dev);
> +#endif
> +
> +	return 0;
> +}
> +
> +static int rk3066_clk_probe(struct udevice *dev)
> +{
> +	struct rk3066_clk_priv *priv = dev_get_priv(dev);
> +
> +	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> +	if (IS_ERR(priv->grf))
> +		return PTR_ERR(priv->grf);
> +
> +#ifdef CONFIG_TPL_BUILD
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +	struct rk3066_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, 1);
> +#endif
> +
> +	return 0;
> +}
> +
> +static int rk3066_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, "rk3066_sysreset", "reset", &dev);
> +	if (ret)
> +		debug("Warning: No rk3066 reset driver: ret=%d\n", ret);
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id rk3066_clk_ids[] = {
> +	{ .compatible = "rockchip,rk3066a-cru" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(rockchip_rk3066a_cru) = {
> +	.name			= "rockchip_rk3066a_cru",
> +	.id			= UCLASS_CLK,
> +	.of_match		= rk3066_clk_ids,
> +	.priv_auto_alloc_size	= sizeof(struct rk3066_clk_priv),
> +	.platdata_auto_alloc_size = sizeof(struct rk3066_clk_plat),
> +	.ops			= &rk3066_clk_ops,
> +	.bind			= rk3066_clk_bind,
> +	.ofdata_to_platdata	= rk3066_clk_ofdata_to_platdata,
> +	.probe			= rk3066_clk_probe,
> +};
>

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

* [U-Boot] [U-Boot,v4,06/19] rockchip: rk3066: add core support
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 06/19] rockchip: rk3066: add core support =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 12:26   ` Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 12:26 UTC (permalink / raw)
  To: u-boot

On Thu, 17 Aug 2017, Paweł Jarosz wrote:

> Add core skeleton for rk3066
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

See below for a few comments.

> ---
> Changes since v1:
> - updated to shifted masks
> - moved syscon.h below spl.h
> - changed error to debug and return error reason
> - changed Cortex-A7 to Cortex-A9
> - added nand support
> - added dfu support
> - removed dram_init
> - reset timer before enable
> - moved configs to board config file
> - moved arm clk setup to tpl
> - moved ddr setup to tpl
> - moved to boot device bootrom
>
> Changes since v2:
> - none
>
> Changes since v3:
> - none
>
> arch/arm/mach-rockchip/Kconfig                |  16 +++
> arch/arm/mach-rockchip/Makefile               |   4 +
> arch/arm/mach-rockchip/rk3066-board-spl.c     | 139 ++++++++++++++++++++++++
> arch/arm/mach-rockchip/rk3066-board-tpl.c     |  90 ++++++++++++++++
> arch/arm/mach-rockchip/rk3066-board.c         | 150 ++++++++++++++++++++++++++
> arch/arm/mach-rockchip/rk3066/Kconfig         |  31 ++++++
> arch/arm/mach-rockchip/rk3066/Makefile        |   8 ++
> arch/arm/mach-rockchip/rk3066/clk_rk3066.c    |  33 ++++++
> arch/arm/mach-rockchip/rk3066/syscon_rk3066.c |  54 ++++++++++
> include/configs/rk3066_common.h               |  99 +++++++++++++++++
> 10 files changed, 624 insertions(+)
> create mode 100644 arch/arm/mach-rockchip/rk3066-board-spl.c
> create mode 100644 arch/arm/mach-rockchip/rk3066-board-tpl.c
> create mode 100644 arch/arm/mach-rockchip/rk3066-board.c
> create mode 100644 arch/arm/mach-rockchip/rk3066/Kconfig
> create mode 100644 arch/arm/mach-rockchip/rk3066/Makefile
> create mode 100644 arch/arm/mach-rockchip/rk3066/clk_rk3066.c
> create mode 100644 arch/arm/mach-rockchip/rk3066/syscon_rk3066.c
> create mode 100644 include/configs/rk3066_common.h
>
> diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
> index d9b25d5..810353f 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_RK3066
> +	bool "Support Rockchip RK3066"
> +	select CPU_V7
> +	select SUPPORT_SPL
> +	select SUPPORT_TPL
> +	select SPL
> +	select TPL
> +	select BOARD_LATE_INIT
> +	select ROCKCHIP_BROM_HELPER
> +	help
> +	  The Rockchip RK3066 is a ARM-based SoC with a dual-core Cortex-A9
> +	  including NEON and GPU, Mali-400 graphics, several DDR3 options
> +	  and video codec support. Peripherals include ethernet, USB2 host
> +	  and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
> +
> config ROCKCHIP_RK3188
> 	bool "Support Rockchip RK3188"
> 	select CPU_V7
> @@ -164,6 +179,7 @@ config SPL_MMC_SUPPORT
> 	default y if !SPL_ROCKCHIP_BACK_TO_BROM
>
> source "arch/arm/mach-rockchip/rk3036/Kconfig"
> +source "arch/arm/mach-rockchip/rk3066/Kconfig"
> source "arch/arm/mach-rockchip/rk3188/Kconfig"
> source "arch/arm/mach-rockchip/rk322x/Kconfig"
> source "arch/arm/mach-rockchip/rk3288/Kconfig"
> diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
> index 79e9704..ae878ef 100644
> --- a/arch/arm/mach-rockchip/Makefile
> +++ b/arch/arm/mach-rockchip/Makefile
> @@ -11,10 +11,12 @@
> obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
> obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
>
> +obj-tpl-$(CONFIG_ROCKCHIP_RK3066) += rk3066-board-tpl.o
> obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
> obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o
>
> obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
> +obj-spl-$(CONFIG_ROCKCHIP_RK3066) += rk3066-board-spl.o
> obj-spl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-spl.o
> obj-spl-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board-spl.o
> obj-spl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-spl.o
> @@ -22,6 +24,7 @@ obj-spl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-spl.o spl-boot-order.o
> obj-spl-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o spl-boot-order.o
>
> ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
> +obj-$(CONFIG_ROCKCHIP_RK3066) += rk3066-board.o
> obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
> obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board.o
> obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
> @@ -35,6 +38,7 @@ obj-y += rk_timer.o
> endif
>
> obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/
> +obj-$(CONFIG_ROCKCHIP_RK3066) += rk3066/
> ifndef CONFIG_TPL_BUILD
> obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188/
> endif
> diff --git a/arch/arm/mach-rockchip/rk3066-board-spl.c b/arch/arm/mach-rockchip/rk3066-board-spl.c
> new file mode 100644
> index 0000000..9acdd83
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066-board-spl.c
> @@ -0,0 +1,139 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <clk.h>
> +#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 <syscon.h>
> +#include <asm/gpio.h>
> +#include <asm/io.h>
> +#include <asm/arch/bootrom.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>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +u32 spl_boot_device(void)
> +{
> +	return BOOT_DEVICE_NAND;
> +}
> +
> +void board_init_f(ulong dummy)
> +{
> +	struct udevice *pinctrl, *dev;
> +	int ret;
> +
> +	debug_uart_init();
> +
> +	ret = spl_early_init();
> +	if (ret) {
> +		debug("spl_early_init() failed: %d\n", ret);
> +		hang();
> +	}
> +
> +	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
> +	if (ret) {
> +		debug("Pinctrl init failed: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = rockchip_get_clk(&dev);
> +	if (ret) {
> +		debug("CLK init failed: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> +	if (ret) {
> +		debug("DRAM init failed: %d\n", ret);
> +		return;
> +	}
> +}
> +
> +void spl_board_init(void)
> +{
> +	struct udevice *pinctrl;
> +	int ret;
> +
> +	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();
> +
> +	return;
> +
> +err:
> +	debug("spl_board_init: Error %d\n", ret);
> +
> +	/* No way to report error here */
> +	hang();
> +}
> +
> +#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
> +#include <usb.h>
> +#include <usb/dwc2_udc.h>
> +
> +static struct dwc2_plat_otg_data rk3066_otg_data = {
> +	.rx_fifo_sz	= 275,
> +	.np_tx_fifo_sz	= 16,
> +	.tx_fifo_sz	= 256,
> +};
> +
> +int board_usb_init(int index, enum usb_init_type init)
> +{
> +	ofnode otg_node;
> +	u32 reg;
> +
> +	otg_node = ofnode_path("/usb at 10180000");
> +	if (!ofnode_valid(otg_node)) {
> +		debug("Not found usb otg device\n");
> +		return -ENODEV;
> +	}
> +
> +	ofnode_read_u32(otg_node, "reg", &reg);
> +	rk3066_otg_data.regs_otg = reg;
> +
> +	return dwc2_udc_probe(&rk3066_otg_data);
> +}
> +
> +int board_usb_cleanup(int index, enum usb_init_type init)
> +{
> +	return 0;
> +}
> +#endif
> diff --git a/arch/arm/mach-rockchip/rk3066-board-tpl.c b/arch/arm/mach-rockchip/rk3066-board-tpl.c
> new file mode 100644
> index 0000000..5dcac90
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066-board-tpl.c
> @@ -0,0 +1,90 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <clk.h>
> +#include <common.h>
> +#include <debug_uart.h>
> +#include <dm.h>
> +#include <ram.h>
> +#include <spl.h>
> +#include <asm/io.h>
> +#include <asm/arch/bootrom.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/ddr_rk3188.h>
> +#include <asm/arch/hardware.h>
> +#include <asm/arch/grf_rk3066.h>
> +#include <asm/arch/pmu_rk3188.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define RK3066_TIMER_CONTROL	0x8
> +#define GRF_BASE	0x20008000
> +
> +static int setup_arm_clock(void)
> +{
> +	struct udevice *dev;
> +	struct clk clk;
> +	int ret;
> +
> +	ret = rockchip_get_clk(&dev);
> +	if (ret)
> +		return ret;
> +
> +	clk.id = CLK_ARM;
> +	ret = clk_request(dev, &clk);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = clk_set_rate(&clk, 600000000);
> +
> +	clk_free(&clk);
> +	return ret;
> +}
> +
> +void board_init_f(ulong dummy)
> +{
> +	struct rk3066_grf * const grf = (void *)GRF_BASE;
> +	struct udevice *dev;
> +	int ret;
> +
> +	/* Enable early UART on the RK3066 */
> +	rk_clrsetreg(&grf->gpio1b_iomux,
> +		     GPIO1B1_MASK | GPIO1B0_MASK,
> +		     GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
> +		     GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);

You should consider putting the pinmux-setting into board_debug_uart_init
and selecting DEBUG_UART_BOARD_INIT.

I'd prefer this to be changed (especially, as it is done so early that it
needs the GRF_BASE as a constant).

> +
> +	debug_uart_init();
> +
> +	printascii("U-Boot TPL board init\n");
> +
> +	ret = spl_early_init();
> +	if (ret) {
> +		debug("spl_early_init() failed: %d\n", ret);
> +		hang();
> +	}
> +
> +	/* Reset and enable Timer0 */
> +	writel(0, CONFIG_SYS_TIMER_BASE);
> +	rk_clrsetreg(CONFIG_SYS_TIMER_BASE + RK3066_TIMER_CONTROL, 0x1, 0x1);

I recently added timer/rockchip_timer.c (it still needs some upstream
patches to be merged to be useful for 32bit devices, as the OF_PLATDATA
handling is 64bit specific), which should allow you to rely on the DM
to initialise the driver (i.e. no explicit initialisation necessary).

No change needed at this time (I'll merge this as is), but I'd prefer this
to be migrated on the 32/64bit weirdness is resolved.

> +
> +	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
> +	if (ret) {
> +		debug("DRAM init failed: %d\n", ret);
> +		return;
> +	}
> +
> +	setup_arm_clock();
> +}
> +
> +void board_return_to_bootrom(void)
> +{
> +	back_to_bootrom();
> +}
> +
> +u32 spl_boot_device(void)
> +{
> +	return BOOT_DEVICE_BOOTROM;
> +}
> diff --git a/arch/arm/mach-rockchip/rk3066-board.c b/arch/arm/mach-rockchip/rk3066-board.c
> new file mode 100644
> index 0000000..8fa06a2
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066-board.c
> @@ -0,0 +1,150 @@
> +/*
> + * (C) Copyright 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
> + *
> + * 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/grf_rk3066.h>
> +#include <asm/arch/periph.h>
> +#include <asm/arch/pmu_rk3188.h>
> +#include <asm/arch/boot_mode.h>
> +#include <asm/gpio.h>
> +#include <dm/pinctrl.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int board_late_init(void)
> +{
> +	struct rk3066_grf *grf;
> +
> +	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> +	if (IS_ERR(grf)) {
> +		debug("grf syscon returned %ld\n", PTR_ERR(grf));
> +		return PTR_ERR(grf);
> +	}
> +	/* enable noc remap to mimic legacy loaders */
> +	rk_clrsetreg(&grf->soc_con0, NOC_REMAP_MASK, NOC_REMAP_MASK);
> +
> +	return 0;
> +}
> +
> +int board_init(void)
> +{
> +#if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM)

Could this simply be "always on"? Or am I missing something here?

> +	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:
> +	debug("board_init: Error %d\n", ret);
> +
> +	/* No way to report error here */
> +	hang();
> +
> +	return -1;
> +#else
> +	return 0;
> +#endif
> +}
> +
> +#ifndef CONFIG_SYS_DCACHE_OFF
> +void enable_caches(void)
> +{
> +	/* Enable D-cache. I-cache is already enabled in start.S */
> +	dcache_enable();
> +}
> +#endif
> +
> +#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
> +#include <usb.h>
> +#include <usb/dwc2_udc.h>
> +
> +static struct dwc2_plat_otg_data rk3066_otg_data = {
> +	.rx_fifo_sz	= 275,
> +	.np_tx_fifo_sz	= 16,
> +	.tx_fifo_sz	= 256,
> +};
> +
> +int board_usb_init(int index, enum usb_init_type init)
> +{
> +	int node, phy_node;
> +	const char *mode;
> +	bool matched = false;
> +	const void *blob = gd->fdt_blob;
> +	u32 grf_phy_offset;
> +
> +	/* find the usb_otg node */
> +	node = fdt_node_offset_by_compatible(blob, -1,
> +					"rockchip,rk3066-usb");
> +
> +	while (node > 0) {
> +		mode = fdt_getprop(blob, node, "dr_mode", NULL);
> +		if (mode && strcmp(mode, "otg") == 0) {
> +			matched = true;
> +			break;
> +		}
> +
> +		node = fdt_node_offset_by_compatible(blob, node,
> +					"rockchip,rk3066-usb");
> +	}
> +	if (!matched) {
> +		debug("Not found usb_otg device\n");
> +		return -ENODEV;
> +	}
> +	rk3066_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
> +
> +	node = fdtdec_lookup_phandle(blob, node, "phys");
> +	if (node <= 0) {
> +		debug("Not found usb phy device\n");
> +		return -ENODEV;
> +	}
> +
> +	phy_node = fdt_parent_offset(blob, node);
> +	if (phy_node <= 0) {
> +		debug("Not found usb phy device\n");
> +		return -ENODEV;
> +	}
> +
> +	rk3066_otg_data.phy_of_node = phy_node;
> +	grf_phy_offset = fdtdec_get_addr(blob, node, "reg");
> +
> +	node = fdt_node_offset_by_compatible(blob, -1,
> +					"rockchip,rk3066-grf");
> +	if (node <= 0) {
> +		debug("Not found grf device\n");
> +		return -ENODEV;
> +	}
> +	rk3066_otg_data.regs_phy = grf_phy_offset +
> +				fdtdec_get_addr(blob, node, "reg");
> +
> +	return dwc2_udc_probe(&rk3066_otg_data);
> +}
> +
> +int board_usb_cleanup(int index, enum usb_init_type init)
> +{
> +	return 0;
> +}
> +#endif
> diff --git a/arch/arm/mach-rockchip/rk3066/Kconfig b/arch/arm/mach-rockchip/rk3066/Kconfig
> new file mode 100644
> index 0000000..b5277fe
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066/Kconfig
> @@ -0,0 +1,31 @@
> +if ROCKCHIP_RK3066
> +
> +config TARGET_MK808_RK3066
> +        bool "MK808_RK3066"
> +	help
> +	  MK808 is a tv stick with usb host and otg, microsd card slot, hdmi and wifi.
> +
> +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_LIBGENERIC_SUPPORT
> +        default y
> +
> +source "board/rikomagic/mk808_rk3066/Kconfig"
> +
> +endif
> diff --git a/arch/arm/mach-rockchip/rk3066/Makefile b/arch/arm/mach-rockchip/rk3066/Makefile
> new file mode 100644
> index 0000000..61b7fd4
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
> +#
> +# SPDX-License-Identifier:      GPL-2.0+
> +#
> +
> +obj-y += clk_rk3066.o
> +obj-y += syscon_rk3066.o
> diff --git a/arch/arm/mach-rockchip/rk3066/clk_rk3066.c b/arch/arm/mach-rockchip/rk3066/clk_rk3066.c
> new file mode 100644
> index 0000000..ae52902
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066/clk_rk3066.c
> @@ -0,0 +1,33 @@
> +/*
> + * Copyright (C) 2016 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_rk3066.h>
> +
> +int rockchip_get_clk(struct udevice **devp)
> +{
> +	return uclass_get_device_by_driver(UCLASS_CLK,
> +			DM_GET_DRIVER(rockchip_rk3066a_cru), devp);
> +}
> +
> +void *rockchip_get_cru(void)
> +{
> +	struct rk3066_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/rk3066/syscon_rk3066.c b/arch/arm/mach-rockchip/rk3066/syscon_rk3066.c
> new file mode 100644
> index 0000000..57b2376
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066/syscon_rk3066.c
> @@ -0,0 +1,54 @@
> +/*
> + * (C) Copyright 2015 Rockchip Electronics Co., Ltd
> + *
> + * 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 rk3066_syscon_ids[] = {
> +	{ .compatible = "rockchip,rk3188-noc", .data = ROCKCHIP_SYSCON_NOC },
> +	{ .compatible = "rockchip,rk3066-grf", .data = ROCKCHIP_SYSCON_GRF },
> +	{ .compatible = "rockchip,rk3066-pmu", .data = ROCKCHIP_SYSCON_PMU },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(syscon_rk3066) = {
> +	.name = "rk3066_syscon",
> +	.id = UCLASS_SYSCON,
> +	.of_match = rk3066_syscon_ids,
> +};
> +
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +static int rk3066_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 = rk3066_syscon_ids,
> +	.bind = rk3066_syscon_bind_of_platdata,
> +};
> +
> +U_BOOT_DRIVER(rockchip_rk3066_grf) = {
> +	.name = "rockchip_rk3066_grf",
> +	.id = UCLASS_SYSCON,
> +	.of_match = rk3066_syscon_ids + 1,
> +	.bind = rk3066_syscon_bind_of_platdata,
> +};
> +
> +U_BOOT_DRIVER(rockchip_rk3066_pmu) = {
> +	.name = "rockchip_rk3066_pmu",
> +	.id = UCLASS_SYSCON,
> +	.of_match = rk3066_syscon_ids + 2,
> +	.bind = rk3066_syscon_bind_of_platdata,
> +};
> +#endif
> diff --git a/include/configs/rk3066_common.h b/include/configs/rk3066_common.h
> new file mode 100644
> index 0000000..3d8c9e8
> --- /dev/null
> +++ b/include/configs/rk3066_common.h
> @@ -0,0 +1,99 @@
> +/*
> + * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#ifndef __CONFIG_RK3066_COMMON_H
> +#define __CONFIG_RK3066_COMMON_H
> +
> +#include <asm/arch/hardware.h>
> +#include "rockchip-common.h"
> +
> +#define CONFIG_SKIP_LOWLEVEL_INIT_ONLY
> +#define CONFIG_ENV_IS_NOWHERE
> +#define CONFIG_ENV_SIZE			0x2000

With Simon's migration of the various ENV configuration items to Kconfig
merged: this should also be migrated.

> +#define CONFIG_SYS_MAXARGS		16
> +#define CONFIG_BAUDRATE			115200
> +#define CONFIG_SYS_MALLOC_LEN		(64 << 20)
> +#define CONFIG_SYS_CBSIZE		256
> +
> +#define CONFIG_SYS_SDRAM_BASE		0x60000000
> +#define CONFIG_NR_DRAM_BANKS		1
> +#define SDRAM_BANK_SIZE			(1024UL << 20UL)
> +#define SDRAM_MAX_SIZE			CONFIG_NR_DRAM_BANKS * SDRAM_BANK_SIZE
> +
> +#define CONFIG_SYS_TIMER_RATE		24000000
> +#define CONFIG_SYS_TIMER_BASE		0x20038000

Once/if you can move to DM timer, these should become obsolete.

> +#define CONFIG_SYS_TIMER_COUNTER	(CONFIG_SYS_TIMER_BASE + 4)
> +#define CONFIG_SYS_TIMER_COUNTS_DOWN
> +
> +#define CONFIG_SYS_TEXT_BASE		0x60408000
> +#define CONFIG_SYS_INIT_SP_ADDR		0x78000000
> +#define CONFIG_SYS_LOAD_ADDR		0x70800800
> +
> +#define CONFIG_SYS_NS16550_MEM32
> +#define CONFIG_BOUNCE_BUFFER
> +#define CONFIG_SPL_FRAMEWORK
> +
> +#define CONFIG_SYS_MAX_NAND_DEVICE	8
> +
> +#ifdef CONFIG_TPL_BUILD
> +#define CONFIG_SPL_TEXT_BASE		0x10080C04
> +#define CONFIG_SPL_STACK		0x1008FFFF

The TPL variants of these can now be set via Kconfig.
arch/arm/mach-rockchip/Kconfig has an example of this for the RK3368.

> +/* tpl size max 32kb - 4byte RK30 header */
> +#define CONFIG_SPL_MAX_SIZE		(0x8000 - 0x4)
> +#elif defined(CONFIG_SPL_BUILD)
> +/* spl size max 200k */
> +#define CONFIG_SPL_MAX_SIZE		0x32000
> +#define CONFIG_SPL_TEXT_BASE		0x60000000
> +#define CONFIG_SPL_STACK		0x1008FFFF
> +#define CONFIG_SPL_BOARD_INIT
> +#define CONFIG_SPL_NAND_DRIVERS
> +#define CONFIG_SPL_NAND_LOAD
> +#define CONFIG_SPL_NAND_ECC
> +#define CONFIG_SPL_NAND_BASE
> +#define CONFIG_SPL_NAND_INIT
> +#define CONFIG_SPL_NAND_BBT
> +#define CONFIG_SPL_NAND_IDS
> +#define CONFIG_SPL_NAND_UTIL
> +#define CONFIG_SPL_NAND_RAW_ONLY
> +#define CONFIG_SYS_NAND_U_BOOT_START	CONFIG_SYS_TEXT_BASE
> +#define CONFIG_SYS_NAND_U_BOOT_DST	CONFIG_SYS_TEXT_BASE
> +#define CONFIG_SYS_NAND_U_BOOT_SIZE	0x80000
> +#define CONFIG_EXTRA_ENV_SETTINGS ROCKCHIP_DEVICE_SETTINGS
> +#define CONFIG_MTD_DEVICE
> +#endif
> +
> +#include <config_distro_defaults.h>
> +
> +#ifndef CONFIG_SPL_BUILD
> +
> +#define CONFIG_USB_FUNCTION_MASS_STORAGE
> +
> +#define CONFIG_MTD_DEVICE
> +#define MTDIDS_DEFAULT			"nand0=rockchip-nand.0"
> +
> +#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>
> +
> +#define CONFIG_EXTRA_ENV_SETTINGS \
> +	"fdt_high=0x6fffffff\0" \
> +	"initrd_high=0x6fffffff\0" \
> +	"partitions=" PARTS_DEFAULT \
> +	"mtdids=" MTDIDS_DEFAULT "\0" \
> +	ENV_MEM_LAYOUT_SETTINGS \
> +	ROCKCHIP_DEVICE_SETTINGS \
> +	BOOTENV
> +
> +#endif
> +
> +#define CONFIG_PREBOOT
> +
> +#endif
>

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

* [U-Boot] [U-Boot,v4,08/19] rockchip: rk3066: add sdram driver
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 08/19] rockchip: rk3066: add sdram driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 12:34   ` Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 12:34 UTC (permalink / raw)
  To: u-boot



On Thu, 17 Aug 2017, Paweł Jarosz wrote:

> Add rockchip rk3066 sdram driver
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

> ---
> Changes since v1:
> - use common rockchip_sdram_size
> - moved sdram init from sdram_init.c

I am still unhappy about the large amount of code duplication between
this one and other drivers (I've highlightes some extremes below, 
in-line).

>
> Changes since v2:
> - none
>
> Changes since v3:
> - none
>
> arch/arm/mach-rockchip/rk3066/Makefile       |   1 +
> arch/arm/mach-rockchip/rk3066/sdram_rk3066.c | 943 +++++++++++++++++++++++++++

Can you please move this over to drivers/ram/rockchip?
All DM-aware DRAM controllers should live under drivers/ram...

Thanks.

> 2 files changed, 944 insertions(+)
> create mode 100644 arch/arm/mach-rockchip/rk3066/sdram_rk3066.c
>
> diff --git a/arch/arm/mach-rockchip/rk3066/Makefile b/arch/arm/mach-rockchip/rk3066/Makefile
> index 61b7fd4..7663b6a 100644
> --- a/arch/arm/mach-rockchip/rk3066/Makefile
> +++ b/arch/arm/mach-rockchip/rk3066/Makefile
> @@ -5,4 +5,5 @@
> #
>
> obj-y += clk_rk3066.o
> +obj-y += sdram_rk3066.o
> obj-y += syscon_rk3066.o
> diff --git a/arch/arm/mach-rockchip/rk3066/sdram_rk3066.c b/arch/arm/mach-rockchip/rk3066/sdram_rk3066.c
> new file mode 100644
> index 0000000..e7475b8
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066/sdram_rk3066.c
> @@ -0,0 +1,943 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + * Copyright 2014 Rockchip Inc.
> + *
> + * SPDX-License-Identifier:     GPL-2.0
> + *
> + * Adapted from the very similar rk3188 ddr init.
> + */
> +
> +#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_rk3066.h>
> +#include <asm/arch/ddr_rk3188.h>
> +#include <asm/arch/grf_rk3066.h>
> +#include <asm/arch/pmu_rk3188.h>
> +#include <asm/arch/sdram.h>
> +#include <asm/arch/sdram_common.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 rk3066_cru *cru;
> +	struct rk3066_grf *grf;
> +	struct rk3066_sgrf *sgrf;
> +	struct rk3188_pmu *pmu;
> +};
> +
> +struct rk3066_sdram_params {
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +	struct dtd_rockchip_rk3066_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;
> +};
> +
> +const int ddrconf_table[] = {
> +	/*
> +	 * [5:4] row(13+n)
> +	 * [1:0] col(9+n), assume bw=2
> +	 * row	    col,bw
> +	 */
> +	0,
> +	(2 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT,
> +	(1 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT,
> +	(0 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT,
> +	(2 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT,
> +	(1 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT,
> +	(0 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT,
> +	(1 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT,
> +	(0 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT,
> +	0,
> +	0,
> +	0,
> +	0,
> +	0,
> +	0,
> +	0,
> +};
> +
> +#define TEST_PATTEN	0x5aa5f00f
> +#define DQS_GATE_TRAINING_ERROR_RANK0	(1 << 4)
> +#define DQS_GATE_TRAINING_ERROR_RANK1	(2 << 4)
> +
> +#ifdef CONFIG_TPL_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 rk3066_cru *cru, u32 ch, u32 ctl, u32 phy)
> +{
> +	u32 phy_ctl_srstn_shift = 13;
> +	u32 ctl_psrstn_shift = 11;
> +	u32 ctl_srstn_shift = 10;
> +	u32 phy_psrstn_shift = 9;
> +	u32 phy_srstn_shift = 8;
> +
> +	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);
> +}

Identical (except for the layout of CRU) to sdram_rk3188.c

> +
> +static void ddr_phy_ctl_reset(struct rk3066_cru *cru, u32 ch, u32 n)
> +{
> +	u32 phy_ctl_srstn_shift = 13;
> +
> +	rk_clrsetreg(&cru->cru_softrst_con[5],
> +		     1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift);
> +}

Identical (except for the layouy of CRU) to sdram_rk3188.c

> +
> +static void phy_pctrl_reset(struct rk3066_cru *cru,
> +			    struct rk3288_ddr_publ *publ,
> +			    int 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);
> +}

And again.

> +
> +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);
> +	}
> +}

Verbatim copy from sdram_rk3188.c or sdram_rk3288.c
In other words: this is already duplicated and we are now adding the
third copy.

...

> +
> +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_ddr3_mode(struct rk3066_grf *grf, uint channel,
> +			      bool ddr3_mode)
> +{
> +	uint mask, val;
> +
> +	mask = MSCH4_MAINDDR3_MASK << MSCH4_MAINDDR3_SHIFT;
> +	val = ddr3_mode << MSCH4_MAINDDR3_SHIFT;
> +	rk_clrsetreg(&grf->soc_con2, mask, val);
> +}
> +
> +static void ddr_rank_2_row15en(struct rk3066_grf *grf, bool enable)
> +{
> +	uint mask, val;
> +
> +	mask = RANK_TO_ROW15_EN_MASK << RANK_TO_ROW15_EN_SHIFT;
> +	val = enable << RANK_TO_ROW15_EN_SHIFT;
> +	rk_clrsetreg(&grf->soc_con2, mask, val);
> +}
> +
> +static void pctl_cfg(int channel, struct rk3288_ddr_pctl *pctl,
> +		     struct rk3066_sdram_params *sdram_params,
> +		     struct rk3066_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);
> +		break;
> +	}
> +
> +	setbits_le32(&pctl->scfg, 1);
> +}
> +
> +static void phy_cfg(const struct chan_info *chan, int channel,
> +		    struct rk3066_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, int channel,
> +				u32 n, struct rk3066_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);
> +		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);
> +		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, int channel,
> +			 struct rk3066_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 rk3066_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 rk3066_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]);
> +}
> +
> +static int sdram_rank_bw_detect(struct dram_info *dram, int channel,
> +		struct rk3066_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 (data_training(chan, channel, sdram_params) < 0) {
> +		debug("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)) {
> +			debug("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 &&
> +	    (data_training(chan, channel, sdram_params) < 0)) {
> +		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);
> +		}
> +		debug("2nd data training failed!");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Detect ram columns and rows.
> + * @dram: dram info struct
> + * @channel: channel number to handle
> + * @sdram_params: sdram parameters, function will fill in col and row values
> + *
> + * Returns 0 or negative on error.
> + */
> +static int sdram_col_row_detect(struct dram_info *dram, int channel,
> +		struct rk3066_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) {
> +		debug("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 rk3066*/
> +	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) {
> +		debug("Row detect error\n");
> +		ret = -EINVAL;
> +	} else {
> +		sdram_params->ch[channel].cs1_row = row;
> +		sdram_params->ch[channel].row_3_4 = 0;
> +		debug("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 rk3066_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) {
> +		debug("niu config not found\n");
> +		ret = -EINVAL;
> +	} else {
> +		debug("niu config %d\n", i);
> +		sdram_params->base.ddrconfig = i;
> +	}
> +
> +	return ret;
> +}
> +
> +static int sdram_init(struct dram_info *dram,
> +		      struct rk3066_sdram_params *sdram_params)
> +{
> +	int channel;
> +	int zqcr;
> +	int ret;
> +
> +	if ((sdram_params->base.dramtype == DDR3 &&
> +	     sdram_params->base.ddr_freq > 800000000)) {
> +		debug("SDRAM frequency is too high!");
> +		return -E2BIG;
> +	}
> +
> +	ret = clk_set_rate(&dram->ddr_clk, sdram_params->base.ddr_freq);
> +	if (ret) {
> +		debug("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);
> +	debug("%s done\n", __func__);
> +
> +	return 0;
> +error:
> +	debug("DRAM init failed!\n");
> +	hang();
> +}
> +#endif /* CONFIG_TPL_BUILD */
> +
> +#ifdef CONFIG_TPL_BUILD
> +static int setup_sdram(struct udevice *dev)
> +{
> +	struct dram_info *priv = dev_get_priv(dev);
> +	struct rk3066_sdram_params *params = dev_get_platdata(dev);
> +
> +	return sdram_init(priv, params);
> +}
> +
> +static int rk3066_dmc_ofdata_to_platdata(struct udevice *dev)
> +{
> +#if !CONFIG_IS_ENABLED(OF_PLATDATA)
> +	struct rk3066_sdram_params *params = dev_get_platdata(dev);
> +	const void *blob = gd->fdt_blob;
> +	int node = dev_of_offset(dev);
> +	int ret;
> +
> +	/* rk3066 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) {
> +		debug("%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) {
> +		debug("%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) {
> +		debug("%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_TPL_BUILD */
> +
> +#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +static int conv_of_platdata(struct udevice *dev)
> +{
> +	struct rk3066_sdram_params *plat = dev_get_platdata(dev);
> +	struct dtd_rockchip_rk3066_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));
> +	/* rk3066 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 rk3066_dmc_probe(struct udevice *dev)
> +{
> +#ifdef CONFIG_TPL_BUILD
> +	struct rk3066_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_TPL_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_TPL_BUILD
> +	ret = setup_sdram(dev);
> +	if (ret)
> +		return ret;
> +#endif
> +	priv->info.base = CONFIG_SYS_SDRAM_BASE;
> +	priv->info.size = rockchip_sdram_size(
> +				(phys_addr_t)&priv->pmu->sys_reg[2]);
> +
> +	return 0;
> +}
> +
> +static int rk3066_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 rk3066_dmc_ops = {
> +	.get_info = rk3066_dmc_get_info,
> +};
> +
> +static const struct udevice_id rk3066_dmc_ids[] = {
> +	{ .compatible = "rockchip,rk3066-dmc" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(dmc_rk3066) = {
> +	.name = "rockchip_rk3066_dmc",
> +	.id = UCLASS_RAM,
> +	.of_match = rk3066_dmc_ids,
> +	.ops = &rk3066_dmc_ops,
> +#ifdef CONFIG_TPL_BUILD
> +	.ofdata_to_platdata = rk3066_dmc_ofdata_to_platdata,
> +#endif
> +	.probe = rk3066_dmc_probe,
> +	.priv_auto_alloc_size = sizeof(struct dram_info),
> +#ifdef CONFIG_TPL_BUILD
> +	.platdata_auto_alloc_size = sizeof(struct rk3066_sdram_params),
> +#endif
> +};
>

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

* [U-Boot] [U-Boot, v4, 10/19] mtd: nand: add the rockchip nand controller driver
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 10/19] mtd: nand: add the rockchip nand controller driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 12:45   ` Philipp Tomsich
  2017-08-18 18:14     ` Paweł Jarosz
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 1 reply; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 12:45 UTC (permalink / raw)
  To: u-boot



On Thu, 17 Aug 2017, Paweł Jarosz wrote:

> Add basic Rockchip nand driver.
>
> Driver in current state has 16, 24, 40, 60 per 1024B BCH/ECC ability and 8 bit asynchronous flash interface support. Other features will come later.
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
>
> Changes since v2:
> - fixed correct ecc checking
>
> Changes since v3:
> - none
>
> drivers/mtd/nand/Kconfig         |   6 +
> drivers/mtd/nand/Makefile        |   1 +
> drivers/mtd/nand/rockchip_nand.c | 660 +++++++++++++++++++++++++++++++++++++++
> include/fdtdec.h                 |   1 +
> lib/fdtdec.c                     |   1 +
> 5 files changed, 669 insertions(+)
> create mode 100644 drivers/mtd/nand/rockchip_nand.c
>
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 71d678f..c308497 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -69,6 +69,12 @@ config NAND_PXA3XX
> 	  This enables the driver for the NAND flash device found on
> 	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
>
> +config NAND_ROCKCHIP
> +	bool "Support for NAND on Rockchip SoCs"
> +	select SYS_NAND_SELF_INIT
> +	---help---
> +	Enable support for Rockchip nand.
> +
> config NAND_SUNXI
> 	bool "Support for NAND on Allwinner SoCs"
> 	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> index c3d4a99..0659253 100644
> --- a/drivers/mtd/nand/Makefile
> +++ b/drivers/mtd/nand/Makefile
> @@ -65,6 +65,7 @@ obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
> obj-$(CONFIG_NAND_PLAT) += nand_plat.o
> obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
> obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
> +obj-$(CONFIG_NAND_ROCKCHIP) += rockchip_nand.o
>
> else  # minimal SPL drivers
>
> diff --git a/drivers/mtd/nand/rockchip_nand.c b/drivers/mtd/nand/rockchip_nand.c
> new file mode 100644
> index 0000000..d8f4439
> --- /dev/null
> +++ b/drivers/mtd/nand/rockchip_nand.c
> @@ -0,0 +1,660 @@
> +/*
> + * Copyright (c) 2017 Yifeng Zhao <yifeng.zhao@rock-chips.com>
> + * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <inttypes.h>
> +#include <nand.h>
> +#include <linux/kernel.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/nand.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define NANDC_V6_BOOTROM_ECC	24
> +#define	NANDC_V6_NUM_BANKS	8
> +#define NANDC_V6_DEF_TIMEOUT	20000
> +#define NANDC_V6_READ		0
> +#define NANDC_V6_WRITE		1
> +
> +#define	NANDC_REG_V6_FMCTL	0x00
> +#define	NANDC_REG_V6_FMWAIT	0x04
> +#define	NANDC_REG_V6_FLCTL	0x08
> +#define	NANDC_REG_V6_BCHCTL	0x0c
> +#define	NANDC_REG_V6_DMA_CFG	0x10
> +#define	NANDC_REG_V6_DMA_BUF0	0x14
> +#define	NANDC_REG_V6_DMA_BUF1	0x18
> +#define	NANDC_REG_V6_DMA_ST	0x1C
> +#define	NANDC_REG_V6_BCHST	0x20
> +#define	NANDC_REG_V6_RANDMZ	0x150
> +#define	NANDC_REG_V6_VER	0x160
> +#define	NANDC_REG_V6_INTEN	0x16C
> +#define	NANDC_REG_V6_INTCLR 	0x170
> +#define	NANDC_REG_V6_INTST	0x174
> +#define	NANDC_REG_V6_SPARE0	0x200
> +#define	NANDC_REG_V6_SPARE1	0x230
> +#define	NANDC_REG_V6_BANK0	0x800
> +#define	NANDC_REG_V6_SRAM0	0x1000
> +#define	NANDC_REG_V6_SRAM_SIZE	0x400

For the Rockchip drivers we have usually used structures to represent
the layout. I know that this will be very sparse for this particular
case, but it seems to be worth this for consistency.

> +
> +#define NANDC_REG_V6_DATA	0x00
> +#define NANDC_REG_V6_ADDR	0x04
> +#define NANDC_REG_V6_CMD	0x08
> +
> +/* FMCTL */
> +#define NANDC_V6_FM_WP		BIT(8)
> +#define NANDC_V6_FM_CE_SEL_M	0xFF
> +#define NANDC_V6_FM_CE_SEL(x)	(1 << (x))

BIT(x) ?

> +#define NANDC_V6_FM_FREADY	BIT(9)
> +
> +/* FLCTL */
> +#define NANDC_V6_FL_RST		BIT(0)
> +#define NANDC_V6_FL_DIR_S	0x1
> +#define NANDC_V6_FL_XFER_START	BIT(2)
> +#define NANDC_V6_FL_XFER_EN	BIT(3)
> +#define NANDC_V6_FL_ST_BUF_S	0x4
> +#define NANDC_V6_FL_XFER_COUNT	BIT(5)
> +#define NANDC_V6_FL_ACORRECT	BIT(10)
> +#define NANDC_V6_FL_XFER_READY	BIT(20)
> +
> +/* BCHCTL */
> +#define NAND_V6_BCH_REGION_S	0x5
> +#define NAND_V6_BCH_REGION_M	0x7
> +
> +/* BCHST */
> +#define NANDC_V6_BCH0_ST_ERR	BIT(2)
> +#define NANDC_V6_BCH1_ST_ERR	BIT(15)
> +#define NANDC_V6_ECC_ERR_CNT0(x) ((((x & (0x1F << 3)) >> 3) \
> +				| ((x & (1 << 27)) >> 22)) & 0x3F)
> +#define NANDC_V6_ECC_ERR_CNT1(x) ((((x & (0x1F << 16)) >> 16) \
> +				| ((x & (1 << 29)) >> 24)) & 0x3F)

This might benefit from using functions from bitfield.h?

> +
> +struct rk_nand {
> +	uint32_t banks[NANDC_V6_NUM_BANKS];

Is the number of banks fixed or should this be dynamically allocated based
on a device-tree property (or driver-data, if it is dependent on how the 
controller was synthesized)?

> +	struct nand_hw_control controller;
> +	uint32_t ecc_strength;
> +	struct mtd_info mtd;
> +	bool bootromblocks;
> +	void __iomem *regs;
> +	int selected_bank;
> +};
> +
> +static struct nand_ecclayout nand_oob_fix = {
> +	.eccbytes = 24,
> +	.eccpos = {
> +		   4, 5, 6, 7, 8, 9, 10},
> +	.oobfree = {
> +		{.offset = 0,
> +		 .length = 4} }

The indentation looks odd on those.

> +};
> +
> +static inline struct rk_nand *to_rknand(struct nand_hw_control *ctrl)
> +{
> +	return container_of(ctrl, struct rk_nand, controller);
> +}
> +
> +static void rockchip_nand_init(struct rk_nand *rknand)
> +{
> +	writel(0, rknand->regs + NANDC_REG_V6_RANDMZ);
> +	writel(0, rknand->regs + NANDC_REG_V6_DMA_CFG);
> +	writel(0, rknand->regs + NANDC_REG_V6_BCHCTL);
> +	writel(NANDC_V6_FM_WP, rknand->regs + NANDC_REG_V6_FMCTL);
> +	writel(0x1081, rknand->regs + NANDC_REG_V6_FMWAIT);

Why the 0x1081?

> +}
> +
> +static void rockchip_nand_select_chip(struct mtd_info *mtd, int chipnr)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	void __iomem *bank_base;
> +	uint32_t reg;
> +	int banknr;
> +
> +	reg = readl(rknand->regs + NANDC_REG_V6_FMCTL);
> +	reg &= ~NANDC_V6_FM_CE_SEL_M;
> +
> +	if (chipnr == -1) {
> +		banknr = -1;
> +	} else {
> +		banknr = rknand->banks[chipnr];
> +		bank_base = rknand->regs + NANDC_REG_V6_BANK0 + banknr * 0x100;

Once converted to a structure, this could be as simple to read as
 	bank_base = &rknand->bank[banknr];

> +
> +		chip->IO_ADDR_R = bank_base;
> +		chip->IO_ADDR_W = bank_base;
> +
> +		reg |= 1 << banknr;
> +	}
> +	writel(reg, rknand->regs + NANDC_REG_V6_FMCTL);

Why not a clrsetbits?

> +
> +	rknand->selected_bank = banknr;
> +}
> +
> +static void rockchip_nand_cmd_ctrl(struct mtd_info *mtd,
> +				   int dat,
> +				   unsigned int ctrl)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
> +				+ rknand->selected_bank * 0x100;

See above.

> +
> +	if (ctrl & NAND_CTRL_CHANGE) {
> +		if (ctrl & NAND_ALE)
> +			bank_base += NANDC_REG_V6_ADDR;

This is not the bank_base you are modifying.
So this really is
 	if (ctrl & NAND_ALE)
 		chip->IO_ADDR_W = &rknand->bank[i].addr;
 	else if (ctrl & NAND_CLE)
 		chip->IO_ADDR_W = &rknand->bank[i].cmd;
 	else
 		chip->IO_ADDR_W = &rknand->bank[i];

> +		else if (ctrl & NAND_CLE)
> +			bank_base += NANDC_REG_V6_CMD;
> +		chip->IO_ADDR_W = bank_base;
> +	}
> +
> +	if (dat != NAND_CMD_NONE)
> +		writeb(dat & 0xFF, chip->IO_ADDR_W);
> +}
> +
> +static void rockchip_nand_read_buf(struct mtd_info *mtd,
> +				   uint8_t *buf,
> +				   int len)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	int offs = 0;
> +	void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
> +				+ rknand->selected_bank * 0x100;
> +
> +	for (offs = 0; offs < len; offs++)
> +		buf[offs] = readb(bank_base);
> +}
> +
> +static void rockchip_nand_write_buf(struct mtd_info *mtd,
> +				    const uint8_t *buf,
> +				    int len)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	int offs = 0;
> +	void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
> +				+ rknand->selected_bank * 0x100;
> +
> +	for (offs = 0; offs < len; offs++)
> +		writeb(buf[offs], bank_base);
> +}

See above.

> +
> +static uint8_t rockchip_nand_read_byte(struct mtd_info *mtd)
> +{
> +	uint8_t ret;
> +
> +	rockchip_nand_read_buf(mtd, &ret, 1);
> +
> +	return ret;
> +}
> +
> +static int rockchip_nand_dev_ready(struct mtd_info *mtd)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +
> +	if (readl(rknand->regs + NANDC_REG_V6_FMCTL) & NANDC_V6_FM_FREADY)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +static int rockchip_nand_hw_ecc_setup(struct mtd_info *mtd,
> +				      struct nand_ecc_ctrl *ecc,
> +				      uint32_t strength)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	u32 reg;
> +
> +	ecc->strength = strength;
> +	ecc->bytes = DIV_ROUND_UP(ecc->strength * 14, 8);
> +	ecc->bytes = ALIGN(ecc->bytes, 2);
> +
> +	switch (ecc->strength) {
> +	case 60:
> +		reg = 0x00040010;
> +		break;
> +	case 40:
> +		reg = 0x00040000;
> +		break;
> +	case 24:
> +		reg = 0x00000010;
> +		break;
> +	case 16:
> +		reg = 0x00000000;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}

Could you use symbolic constants?

> +	writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);
> +
> +	return 0;
> +}
> +
> +static void rockchip_nand_pio_xfer_start(struct rk_nand *rknand,
> +					 u8 dir,
> +					 u8 st_buf)
> +{
> +	u32 reg;
> +
> +	reg = readl(rknand->regs + NANDC_REG_V6_BCHCTL);
> +	reg = (reg & (~(NAND_V6_BCH_REGION_M << NAND_V6_BCH_REGION_S))) |
> +	      (rknand->selected_bank << NAND_V6_BCH_REGION_S);
> +	writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);

clrsetbits?

> +
> +	reg = (dir << NANDC_V6_FL_DIR_S) | (st_buf << NANDC_V6_FL_ST_BUF_S) |
> +	      NANDC_V6_FL_XFER_EN | NANDC_V6_FL_XFER_COUNT |
> +	      NANDC_V6_FL_ACORRECT;
> +	writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);
> +
> +	reg |= NANDC_V6_FL_XFER_START;
> +	writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);

setbits?

> +}
> +
> +static int rockchip_nand_wait_pio_xfer_done(struct rk_nand *rknand)
> +{
> +	int timeout = NANDC_V6_DEF_TIMEOUT;
> +	int reg;
> +
> +	while (timeout--) {
> +		reg = readl(rknand->regs + NANDC_REG_V6_FLCTL);
> +
> +		if ((reg & NANDC_V6_FL_XFER_READY) != 0)
> +			break;
> +
> +		udelay(1);
> +	}
> +
> +	if (timeout == 0)
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static void rockchip_nand_read_extra_oob(struct mtd_info *mtd, u8 *oob)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_ecc_ctrl *ecc = &chip->ecc;
> +	int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
> +	int len = mtd->oobsize - offset;
> +
> +	if (len <= 0)
> +		return;
> +
> +	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1);
> +
> +	rockchip_nand_read_buf(mtd, oob + offset, len);
> +}
> +
> +static void rockchip_nand_write_extra_oob(struct mtd_info *mtd, u8 *oob)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_ecc_ctrl *ecc = &chip->ecc;
> +	int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
> +	int len = mtd->oobsize - offset;
> +
> +	if (len <= 0)
> +		return;
> +
> +	chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1);
> +
> +	rockchip_nand_write_buf(mtd, oob + offset, len);
> +}
> +
> +
> +static int rockchip_nand_hw_syndrome_pio_read_page(struct mtd_info *mtd,
> +						   struct nand_chip *chip,
> +						   uint8_t *buf,
> +						   int oob_required,
> +						   int page)
> +{
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	struct nand_ecc_ctrl *ecc = &chip->ecc;
> +	void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
> +	unsigned int max_bitflips = 0;
> +	int ret, step, bch_st;
> +	int offset = page * mtd->writesize;
> +
> +	if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
> +		rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
> +
> +	rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ, 0);
> +
> +	for (step = 0; step < ecc->steps; step++) {
> +		int data_off = step * ecc->size;
> +		int oob_off = step * (ecc->bytes + ecc->prepad);
> +		u8 *data = buf + data_off;
> +		u8 *oob = chip->oob_poi + oob_off;
> +
> +		ret = rockchip_nand_wait_pio_xfer_done(rknand);
> +		if (ret)
> +			return ret;
> +
> +		bch_st = readl(rknand->regs + NANDC_REG_V6_BCHST);
> +
> +		if (bch_st & NANDC_V6_BCH0_ST_ERR) {
> +			mtd->ecc_stats.failed++;
> +			max_bitflips = -1;
> +		} else {
> +			ret = NANDC_V6_ECC_ERR_CNT0(bch_st);
> +			mtd->ecc_stats.corrected += ret;
> +			max_bitflips = max_t(unsigned int, max_bitflips, ret);
> +		}
> +
> +		if ((step + 1) < ecc->steps)
> +			rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ,
> +					      		(step + 1) & 0x1);
> +
> +		memcpy_fromio(data, sram_base + NANDC_REG_V6_SRAM_SIZE *
> +			     				(step & 1), ecc->size);
> +
> +		if (step & 1)
> +			memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE1, 4);
> +		else
> +			memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE0, 4);
> +	}
> +
> +	rockchip_nand_read_extra_oob(mtd, chip->oob_poi);
> +
> +	if (rknand->bootromblocks)
> +		rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
> +
> +	return max_bitflips;
> +}
> +
> +static uint32_t rockchip_nand_make_bootrom_compat(struct mtd_info *mtd,
> +						  int page,
> +						  const u8 *oob,
> +						  bool bootromblocks)
> +{
> +	int pages_per_block = mtd->erasesize / mtd->writesize;
> +	int offset = page * mtd->writesize;
> +
> +	if ((offset < (2 * mtd->erasesize)) || !(page % 2) ||
> +	    (offset >= (7 * mtd->erasesize)) || !bootromblocks)
> +		return oob[3] | (oob[2] << 8) | (oob[1] << 16) | (oob[0] << 24);
> +
> +	return (page % pages_per_block + 1) * 4;
> +}
> +
> +static int rockchip_nand_hw_syndrome_pio_write_page(struct mtd_info *mtd,
> +						    struct nand_chip *chip,
> +						    const uint8_t *buf,
> +						    int oob_required,
> +						    int page)
> +{
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	struct nand_ecc_ctrl *ecc = &chip->ecc;
> +	void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
> +	int ret, index, step = 0;
> +	int offset = page * mtd->writesize;
> +	int data_off = step * ecc->size;
> +	int oob_off = step * (ecc->bytes + ecc->prepad);
> +	const u8 *data = buf + data_off;
> +	const u8 *oob = chip->oob_poi + oob_off;
> +
> +	if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
> +		rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
> +
> +	index = rockchip_nand_make_bootrom_compat(mtd, page, oob,
> +					   rknand->bootromblocks);
> +
> +	memcpy_toio(sram_base, data, ecc->size);
> +	memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0, &index, ecc->prepad);
> +
> +	for (step = 1; step <= ecc->steps; step++) {
> +		rockchip_nand_pio_xfer_start(rknand, NANDC_V6_WRITE,
> +					     (step - 1) & 0x1);
> +
> +		data_off = step * ecc->size;
> +		oob_off = step * (ecc->bytes + ecc->prepad);
> +		data = buf + data_off;
> +		oob = chip->oob_poi + oob_off;
> +
> +		if (step < ecc->steps) {
> +			memcpy_toio(sram_base + NANDC_REG_V6_SRAM_SIZE *
> +				    (step & 1), data, ecc->size);
> +			if (step & 1)
> +				memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE1,
> +					    oob, ecc->prepad);
> +			else
> +				memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0,
> +					    oob, ecc->prepad);
> +		}
> +
> +		ret = rockchip_nand_wait_pio_xfer_done(rknand);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	rockchip_nand_write_extra_oob(mtd, chip->oob_poi);
> +
> +	rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
> +
> +	return 0;
> +}
> +
> +static const u8 strengths[] = {60, 40, 24, 16};
> +
> +static int rockchip_nand_ecc_max_strength(struct mtd_info *mtd,
> +					  struct nand_ecc_ctrl *ecc)
> +{
> +	uint32_t max_strength, index;
> +
> +	max_strength = ((mtd->oobsize / ecc->steps) - ecc->prepad) * 8 / 14;
> +
> +	for (index = 0; index < ARRAY_SIZE(strengths); index++)
> +		if (max_strength >= strengths[index])
> +			break;
> +
> +	if (index >= ARRAY_SIZE(strengths))
> +		return -ENOTSUPP;
> +
> +	return strengths[index];
> +}
> +
> +static bool rockchip_nand_strength_is_valid(int strength)
> +{
> +	uint32_t index;
> +
> +	for (index = 0; index < ARRAY_SIZE(strengths); index++)
> +		if (strength == strengths[index])
> +			break;
> +
> +	if (index == ARRAY_SIZE(strengths))
> +		return false;
> +
> +	return true;
> +}
> +
> +static int rockchip_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
> +					  struct nand_ecc_ctrl *ecc)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct rk_nand *rknand = to_rknand(chip->controller);
> +	uint32_t strength;
> +	int index;
> +
> +	ecc->prepad = 4;
> +	ecc->steps = mtd->writesize / ecc->size;
> +
> +	if (fdtdec_get_bool(gd->fdt_blob, chip->flash_node,
> +			    "rockchip,protect-bootrom-blocks"))
> +                rknand->bootromblocks = true;
> +	else
> +		rknand->bootromblocks = false;
> +
> +	if (rockchip_nand_strength_is_valid(ecc->strength))
> +		strength = ecc->strength;
> +	else
> +		strength = rockchip_nand_ecc_max_strength(mtd, ecc);
> +
> +	rockchip_nand_hw_ecc_setup(mtd, ecc, strength);
> +
> +	rknand->ecc_strength = ecc->strength;
> +
> +	nand_oob_fix.eccbytes = ecc->bytes * ecc->steps;
> +	for (index = 0; index < ecc->bytes; index++)
> +		nand_oob_fix.eccpos[index] = index + ecc->prepad;
> +	ecc->layout = &nand_oob_fix;
> +
> +	if (mtd->oobsize < ((ecc->bytes + ecc->prepad) * ecc->steps)) {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rockchip_nand_ecc_init(struct mtd_info *mtd,
> +				  struct nand_ecc_ctrl *ecc)
> +{
> +	int ret;
> +
> +	switch (ecc->mode) {
> +	case NAND_ECC_HW_SYNDROME:
> +		ret = rockchip_nand_hw_ecc_ctrl_init(mtd, ecc);
> +		if (ret)
> +			return ret;
> +		ecc->read_page =  rockchip_nand_hw_syndrome_pio_read_page;
> +		ecc->write_page = rockchip_nand_hw_syndrome_pio_write_page;
> +		break;
> +	case NAND_ECC_SOFT_BCH:
> +	case NAND_ECC_NONE:
> +	case NAND_ECC_SOFT:
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rockchip_nand_chip_init(int node, struct rk_nand *rknand, int devnum)
> +{
> +	const void *blob = gd->fdt_blob;
> +	struct nand_chip *chip;
> +	struct mtd_info *mtd;
> +	int ret;
> +
> +	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
> +
> +	chip->chip_delay = 50;
> +	chip->flash_node = node;
> +	chip->select_chip = rockchip_nand_select_chip;
> +	chip->cmd_ctrl = rockchip_nand_cmd_ctrl;
> +	chip->read_buf = rockchip_nand_read_buf;
> +	chip->write_buf = rockchip_nand_write_buf;
> +	chip->read_byte = rockchip_nand_read_byte;
> +	chip->dev_ready = rockchip_nand_dev_ready;
> +	chip->controller = &rknand->controller;
> +
> +	rknand->banks[devnum] = fdtdec_get_int(blob, node, "reg", -1);
> +
> +	if (rknand->banks[devnum] < 0)
> +		return -EINVAL;
> +
> +	mtd = nand_to_mtd(chip);
> +	mtd->name = "rknand";
> +
> +	ret = nand_scan_ident(mtd, 1, NULL);
> +	if (ret)
> +		return ret;
> +
> +	ret = rockchip_nand_ecc_init(mtd, &chip->ecc);
> +	if (ret) {
> +		debug("rockchip_nand_ecc_init failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = nand_scan_tail(mtd);
> +	if (ret) {
> +		debug("nand_scan_tail failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = nand_register(devnum, mtd);
> +	if (ret) {
> +		debug("Failed to register mtd device: %d\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rockchip_nand_chips_init(int node, struct rk_nand *rknand)
> +{
> +	const void *blob = gd->fdt_blob;
> +	int nand_node;
> +	int ret, i = 0;
> +
> +	for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
> +	     nand_node = fdt_next_subnode(blob, nand_node)) {
> +		ret = rockchip_nand_chip_init(nand_node, rknand, i++);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +void board_nand_init(void)
> +{
> +	const void *blob = gd->fdt_blob;
> +	struct rk_nand *rknand;
> +	fdt_addr_t regs;
> +	int node;
> +	int ret;
> +
> +	rknand = kzalloc(sizeof(*rknand), GFP_KERNEL);
> +
> +	node = fdtdec_next_compatible(blob, 0, COMPAT_ROCKCHIP_NANDC);
> +
> +	if (node < 0) {
> +		debug("Nand node not found\n");
> +		goto err;
> +	}
> +
> +	if (!fdtdec_get_is_enabled(blob, node)) {
> +		debug("Nand disabled in device tree\n");
> +		goto err;
> +	}
> +
> +	regs = fdtdec_get_addr(blob, node, "reg");
> +	if (regs == FDT_ADDR_T_NONE) {
> +		debug("Nand address not found\n");
> +		goto err;
> +	}
> +
> +	rknand->regs = (void *)regs;
> +
> +	spin_lock_init(&rknand->controller.lock);
> +	init_waitqueue_head(&rknand->controller.wq);
> +
> +	rockchip_nand_init(rknand);
> +
> +	ret = rockchip_nand_chips_init(node, rknand);
> +	if (ret) {
> +		debug("Failed to init nand chips\n");
> +		goto err;
> +	}
> +
> +	return;
> +err:
> +	kfree(rknand);
> +}
> +
> +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
> +{
> +	struct mtd_info *mtd;
> +
> +	mtd = get_nand_dev_by_index(0);
> +	return nand_read_skip_bad(mtd, offs, &size, NULL, size, (u_char *)dst);
> +}
> +
> +void nand_deselect(void) {}
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 4a0947c..0e68788 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -157,6 +157,7 @@ enum fdt_compat_id {
> 	COMPAT_ALTERA_SOCFPGA_F2SDR0,           /* SoCFPGA fpga2SDRAM0 bridge */
> 	COMPAT_ALTERA_SOCFPGA_F2SDR1,           /* SoCFPGA fpga2SDRAM1 bridge */
> 	COMPAT_ALTERA_SOCFPGA_F2SDR2,           /* SoCFPGA fpga2SDRAM2 bridge */
> +	COMPAT_ROCKCHIP_NANDC,			/* Rockchip NAND controller */
>
> 	COMPAT_COUNT,
> };
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index 107a892..4a8a8d7 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
> 	COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"),
> 	COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"),
> 	COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"),
> +	COMPAT(ROCKCHIP_NANDC, "rockchip,nandc"),
> };
>
> const char *fdtdec_get_compatible(enum fdt_compat_id id)
>

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

* [U-Boot] [U-Boot, v4, 11/19] rockchip: mkimage: add support for rockchip nand boot image
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 11/19] rockchip: mkimage: add support for rockchip nand boot image =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 12:49   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 12:49 UTC (permalink / raw)
  To: u-boot



On Thu, 17 Aug 2017, Paweł Jarosz wrote:

> The Rockchip boot ROM requires a particular file format for booting from NAND:
>
> * It starts with 512-byte, rc4 encoded header and is aligned to nand page size
>
> * Then first 2KB of first stage loader (tpl) aligned to nand page size
> * n empty pages
>
> * second 2KB of first stage loader (tpl) aligned to nand page size
> * n empty pages
>
> * ...
>
> * first 2KB of second stage loader (spl) aligned to nand page size
> * n empty pages
>
> * second 2KB of first stage loader (spl) aligned to nand page size
> * n empty pages
>
> * ...

Sounds a lot like the 'rkspi' format.
If I correctly understand this, then the only difference is that you added
support for TPL processing by the mkimage tool.

Could you recheck whether this is the same as RKSPI and (if so) merge this
there?

>
> Size of spl and tpl must be aligned to 2KB.
>
> example usage for nand with page size 16384 and one empty page in iteration:
>
>    # mkimage -n rk3066 -T rknand -d ./u-boot/tpl/u-boot-tpl.bin:./u-boot/spl/u-boot-spl.bin -X 16384,1 out
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
>
> Changes since v2:
> - none
>
> Changes since v3:
> - none
>
> common/image.c    |   1 +
> include/image.h   |   1 +
> tools/Makefile    |   2 +-
> tools/imagetool.h |   1 +
> tools/mkimage.c   |   8 ++-
> tools/rkcommon.c  |  10 ++--
> tools/rkcommon.h  |  10 +++-
> tools/rknand.c    | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> tools/rksd.c      |   2 +-
> tools/rkspi.c     |   2 +-
> 10 files changed, 183 insertions(+), 10 deletions(-)
> create mode 100644 tools/rknand.c
>
> diff --git a/common/image.c b/common/image.c
> index a058eb8..f5f6cd2 100644
> --- a/common/image.c
> +++ b/common/image.c
> @@ -167,6 +167,7 @@ static const table_entry_t uimage_type[] = {
> 	{	IH_TYPE_FPGA,       "fpga",       "FPGA Image" },
> 	{       IH_TYPE_TEE,        "tee",        "Trusted Execution Environment Image",},
> 	{	IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" },
> +	{	IH_TYPE_RKNAND,     "rknand",     "Rockchip NAND Boot Image" },
> 	{	-1,		    "",		  "",			},
> };
>
> diff --git a/include/image.h b/include/image.h
> index 1f4bfda..10ff094 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -269,6 +269,7 @@ enum {
> 	IH_TYPE_VYBRIDIMAGE,	/* VYBRID .vyb Image */
> 	IH_TYPE_TEE,            /* Trusted Execution Environment OS Image */
> 	IH_TYPE_FIRMWARE_IVT,		/* Firmware Image with HABv4 IVT */
> +	IH_TYPE_RKNAND,			/* Rockchip NAND Boot Image	*/
>
> 	IH_TYPE_COUNT,			/* Number of image types */
> };
> diff --git a/tools/Makefile b/tools/Makefile
> index a1790eb..044049c 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -79,7 +79,7 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
> 					rsa-sign.o rsa-verify.o rsa-checksum.o \
> 					rsa-mod-exp.o)
>
> -ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o
> +ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rknand.o rksd.o rkspi.o
>
> # common objs for dumpimage and mkimage
> dumpimage-mkimage-objs := aisimage.o \
> diff --git a/tools/imagetool.h b/tools/imagetool.h
> index a8d5054..0b2a707 100644
> --- a/tools/imagetool.h
> +++ b/tools/imagetool.h
> @@ -77,6 +77,7 @@ struct image_tool_params {
> 	bool quiet;		/* Don't output text in normal operation */
> 	unsigned int external_offset;	/* Add padding to external data */
> 	const char *engine_id;	/* Engine to use for signing */
> +	char *extraparams;	/* Extra parameters for img creation (-X) */
> };
>
> /*
> diff --git a/tools/mkimage.c b/tools/mkimage.c
> index 28ff35e..ffc91d2 100644
> --- a/tools/mkimage.c
> +++ b/tools/mkimage.c
> @@ -144,7 +144,7 @@ static void process_args(int argc, char **argv)
> 	int opt;
>
> 	while ((opt = getopt(argc, argv,
> -			     "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVx")) != -1) {
> +			     "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVxX:")) != -1) {
> 		switch (opt) {
> 		case 'a':
> 			params.addr = strtoull(optarg, &ptr, 16);
> @@ -279,6 +279,9 @@ static void process_args(int argc, char **argv)
> 		case 'x':
> 			params.xflag++;
> 			break;
> +		case 'X':
> +			params.extraparams = optarg;
> +			break;
> 		default:
> 			usage("Invalid option");
> 		}
> @@ -416,7 +419,8 @@ int main(int argc, char **argv)
> 		exit (retval);
> 	}
>
> -	if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT)) {
> +	if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT) &&
> +	    (params.type != IH_TYPE_RKNAND)) {
> 		dfd = open(params.datafile, O_RDONLY | O_BINARY);
> 		if (dfd < 0) {
> 			fprintf(stderr, "%s: Can't open %s: %s\n",
> diff --git a/tools/rkcommon.c b/tools/rkcommon.c
> index 04e8272..a2f2160 100644
> --- a/tools/rkcommon.c
> +++ b/tools/rkcommon.c
> @@ -73,6 +73,7 @@ struct spl_info {
>
> static struct spl_info spl_infos[] = {
> 	{ "rk3036", "RK30", 0x1000, false, false },
> +	{ "rk3066", "RK30", 0x8000, true, false },
> 	{ "rk3188", "RK31", 0x8000 - 0x800, true, false },
> 	{ "rk322x", "RK32", 0x8000 - 0x1000, false, false },
> 	{ "rk3288", "RK32", 0x8000, false, false },
> @@ -167,7 +168,7 @@ bool rkcommon_spl_is_boot0(struct image_tool_params *params)
> 	return info->spl_boot0;
> }
>
> -static void rkcommon_set_header0(void *buf, uint file_size,
> +static void rkcommon_set_header0(void *buf, uint file_size, uint max_size,
> 				 struct image_tool_params *params)
> {
> 	struct header0_info *hdr = buf;
> @@ -194,12 +195,13 @@ static void rkcommon_set_header0(void *buf, uint file_size,
> 	 * see https://lists.denx.de/pipermail/u-boot/2017-May/293267.html
> 	 * for a more detailed explanation by Andy Yan
> 	 */
> -	hdr->init_boot_size = hdr->init_size + RK_MAX_BOOT_SIZE / RK_BLK_SIZE;
> +	hdr->init_boot_size = hdr->init_size + DIV_ROUND_UP(max_size, RK_BLK_SIZE);
> +	hdr->init_boot_size = ROUND(hdr->init_boot_size, 4);
>
> 	rc4_encode(buf, RK_BLK_SIZE, rc4_key);
> }
>
> -int rkcommon_set_header(void *buf, uint file_size,
> +int rkcommon_set_header(void *buf, uint file_size, uint max_size,
> 			struct image_tool_params *params)
> {
> 	struct header1_info *hdr = buf + RK_SPL_HDR_START;
> @@ -207,7 +209,7 @@ int rkcommon_set_header(void *buf, uint file_size,
> 	if (file_size > rkcommon_get_spl_size(params))
> 		return -ENOSPC;
>
> -	rkcommon_set_header0(buf, file_size, params);
> +	rkcommon_set_header0(buf, file_size, max_size, params);
>
> 	/* Set up the SPL name (i.e. copy spl_hdr over) */
> 	memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE);
> diff --git a/tools/rkcommon.h b/tools/rkcommon.h
> index 8790f1c..cd357c7 100644
> --- a/tools/rkcommon.h
> +++ b/tools/rkcommon.h
> @@ -45,6 +45,14 @@ const char *rkcommon_get_spl_hdr(struct image_tool_params *params);
> int rkcommon_get_spl_size(struct image_tool_params *params);
>
> /**
> + * rkcommon_spl_is_boot0() - is magic included in spl
> + *
> + * Returns true if magic (for example RK30) is included in spl
> + */
> +
> +bool rkcommon_spl_is_boot0(struct image_tool_params *params);
> +
> +/**
>  * rkcommon_set_header() - set up the header for a Rockchip boot image
>  *
>  * This sets up a 2KB header which can be interpreted by the Rockchip boot ROM.
> @@ -53,7 +61,7 @@ int rkcommon_get_spl_size(struct image_tool_params *params);
>  * @file_size:	Size of the file we want the boot ROM to load, in bytes
>  * @return 0 if OK, -ENOSPC if too large
>  */
> -int rkcommon_set_header(void *buf, uint file_size,
> +int rkcommon_set_header(void *buf, uint file_size, uint max_size,
> 			struct image_tool_params *params);
>
> /**
> diff --git a/tools/rknand.c b/tools/rknand.c
> new file mode 100644
> index 0000000..690af2d
> --- /dev/null
> +++ b/tools/rknand.c
> @@ -0,0 +1,156 @@
> +/*
> + * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include "imagetool.h"
> +#include <image.h>
> +#include <rc4.h>
> +#include "mkimage.h"
> +#include "rkcommon.h"
> +
> +enum {
> +	RKNAND_SECT_LEN = RK_BLK_SIZE * 4,
> +};
> +
> +struct rknand_info {
> +	uint32_t pagesize;
> +	uint32_t skippages;
> +	uint32_t tplsize;
> +	uint32_t splsize;
> +	uint32_t tplpaddedsize;
> +	uint32_t splpaddedsize;
> +	uint32_t itersize;
> +	uint32_t tplsplsize;
> +	char *tplfile;
> +	char *splfile;
> +};
> +
> +struct rknand_info ninfo;
> +
> +static uint32_t rknand_get_file_size(char *filename)
> +{
> +	int dfd;
> +	struct stat sbuf;
> +
> +	dfd = open(filename, O_RDONLY | O_BINARY);
> +	if (dfd < 0) {
> +		fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno));
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	if (fstat(dfd, &sbuf) < 0) {
> +		fprintf(stderr, "Can't stat %s: %s\n", filename, strerror(errno));
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	close(dfd);
> +
> +	return sbuf.st_size;
> +}
> +
> +static void rknand_fill_ninfo(struct image_tool_params *params)
> +{
> +	sscanf(params->extraparams, "%u,%u", &ninfo.pagesize, &ninfo.skippages);
> +
> +	ninfo.tplfile = params->datafile;
> +	if ((ninfo.splfile = strchr(params->datafile, ':')) != NULL) {
> +		*ninfo.splfile = '\0';
> +		ninfo.splfile += 1;
> +	}
> +
> +	ninfo.tplsize = rknand_get_file_size(ninfo.tplfile);
> +	ninfo.splsize = rknand_get_file_size(ninfo.splfile);
> +
> +	ninfo.tplpaddedsize = ROUND(ninfo.tplsize +
> +		(rkcommon_spl_is_boot0(params) ? 0 : 4), RKNAND_SECT_LEN);
> +
> +	ninfo.splpaddedsize = ROUND(ninfo.splsize, RKNAND_SECT_LEN);
> +
> +	ninfo.itersize = ninfo.pagesize * (ninfo.skippages + 1);
> +	ninfo.tplsplsize = ((ninfo.tplpaddedsize + ninfo.splpaddedsize) /
> +		     RKNAND_SECT_LEN) * ninfo.itersize;
> +}
> +
> +static void rknand_set_header(void *buf, struct stat *sbuf, int ifd,
> +			     struct image_tool_params *params)
> +{
> +	int sector, sploffset, splfd, ret;
> +
> +	ret = rkcommon_set_header(buf, ninfo.tplsize, ninfo.splsize, params);
> +	if (ret) {
> +		printf("Warning: TPL image is too large (size %#x) and will "
> +		       "not boot\n", ninfo.tplsize);
> +	}
> +
> +	if ((splfd = open(ninfo.splfile, O_RDONLY | O_BINARY)) < 0) {
> +		fprintf (stderr, "%s: Can't open %s: %s\n",
> +			params->cmdname, ninfo.splfile, strerror(errno));
> +		exit (EXIT_FAILURE);
> +	}
> +
> +	sploffset = RKNAND_SECT_LEN + ninfo.tplpaddedsize;
> +	if (read(splfd, buf + sploffset, ninfo.splsize) != ninfo.splsize) {
> +		fprintf (stderr, "%s: Read error on %s: %s\n",
> +			params->cmdname, ninfo.splfile, strerror(errno));
> +		exit (EXIT_FAILURE);
> +	}
> +	close(splfd);
> +
> +	if (rkcommon_need_rc4_spl(params))
> +		rkcommon_rc4_encode_spl(buf, sploffset, ninfo.splpaddedsize);
> +
> +	/*
> +	 * Spread the image out so we only use the first 2KB of each pagesize
> +	 * region. This is a feature of the NAND format required by the Rockchip
> +	 * boot ROM.
> +	 */
> +	for (sector = ninfo.tplsplsize / ninfo.itersize - 1; sector >= 0; sector--) {
> +		memmove(buf + sector * ninfo.itersize + ninfo.pagesize,
> +			buf + (sector + 1) * RKNAND_SECT_LEN, RKNAND_SECT_LEN);
> +
> +		if (sector < (ninfo.tplsplsize / ninfo.itersize - 1))
> +			memset(buf + sector * ninfo.itersize  + ninfo.pagesize +
> +			       RKNAND_SECT_LEN, 0xFF, ninfo.itersize -
> +			       RKNAND_SECT_LEN);
> +	}
> +	memset(buf + RKNAND_SECT_LEN, 0xFF, ninfo.pagesize - RKNAND_SECT_LEN);
> +	memset(buf + ninfo.tplsplsize - ninfo.pagesize + RKNAND_SECT_LEN, 0xFF,
> +	       ninfo.pagesize - RKNAND_SECT_LEN);
> +}
> +
> +static int rknand_check_image_type(uint8_t type)
> +{
> +	if (type == IH_TYPE_RKNAND)
> +		return EXIT_SUCCESS;
> +	else
> +		return EXIT_FAILURE;
> +}
> +
> +static int rknand_vrec_header(struct image_tool_params *params,
> +			     struct image_type_params *tparams)
> +{
> +	rknand_fill_ninfo(params);
> +	rkcommon_vrec_header(params, tparams, RKNAND_SECT_LEN);
> +
> +	return ninfo.tplsplsize - tparams->header_size - ninfo.tplsize;
> +}
> +
> +/*
> + * rknand parameters
> + */
> +U_BOOT_IMAGE_TYPE(
> +	rknand,
> +	"Rockchip NAND Boot Image support",
> +	0,
> +	NULL,
> +	rkcommon_check_params,
> +	rkcommon_verify_header,
> +	rkcommon_print_header,
> +	rknand_set_header,
> +	NULL,
> +	rknand_check_image_type,
> +	NULL,
> +	rknand_vrec_header
> +);
> diff --git a/tools/rksd.c b/tools/rksd.c
> index c56153d..164c1fb 100644
> --- a/tools/rksd.c
> +++ b/tools/rksd.c
> @@ -26,7 +26,7 @@ static void rksd_set_header(void *buf,  struct stat *sbuf,  int ifd,
> 	 * header).
> 	 */
> 	size = params->file_size - RK_SPL_HDR_START;
> -	ret = rkcommon_set_header(buf, size, params);
> +	ret = rkcommon_set_header(buf, size, RK_MAX_BOOT_SIZE, params);
> 	if (ret) {
> 		/* TODO(sjg at chromium.org): This method should return an error */
> 		printf("Warning: SPL image is too large (size %#x) and will "
> diff --git a/tools/rkspi.c b/tools/rkspi.c
> index 4332ce1..5005051 100644
> --- a/tools/rkspi.c
> +++ b/tools/rkspi.c
> @@ -25,7 +25,7 @@ static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd,
> 	int ret;
>
> 	size = params->orig_file_size;
> -	ret = rkcommon_set_header(buf, size, params);
> +	ret = rkcommon_set_header(buf, size, RK_MAX_BOOT_SIZE, params);
> 	debug("size %x\n", size);
> 	if (ret) {
> 		/* TODO(sjg at chromium.org): This method should return an error */
>

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

* [U-Boot] [U-Boot, v4, 14/19] mmc: dw_mmc: support transfer mode autodetection
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18  7:02   ` Jaehoon Chung
@ 2017-08-18 12:51   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  3 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 12:51 UTC (permalink / raw)
  To: u-boot



On Thu, 17 Aug 2017, Paweł Jarosz wrote:

> dw_mmc supports two transfer modes in u-boot: idma and fifo.
> This patch adds autodetection of transfer mode and eliminates setting this in host config struct
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
>
> Changes since v2:
> - none
>
> Changes since v3:
> - none
>
> drivers/mmc/dw_mmc.c | 8 ++++++++
> include/dwmmc.h      | 4 ++++
> 2 files changed, 12 insertions(+)
>
> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
> index 700f764..2cc4d67 100644
> --- a/drivers/mmc/dw_mmc.c
> +++ b/drivers/mmc/dw_mmc.c
> @@ -428,6 +428,7 @@ static int dwmci_set_ios(struct mmc *mmc)
> static int dwmci_init(struct mmc *mmc)
> {
> 	struct dwmci_host *host = mmc->priv;
> +	uint32_t use_dma;
>
> 	if (host->board_init)
> 		host->board_init(host);
> @@ -439,6 +440,13 @@ static int dwmci_init(struct mmc *mmc)
> 		return -EIO;
> 	}
>
> +	use_dma = SDMMC_GET_TRANS_MODE(dwmci_readl(host, DWMCI_HCON));
> +	if (use_dma == DMA_INTERFACE_IDMA) {
> +		host->fifo_mode = 0;
> +	} else {
> +		host->fifo_mode = 1;
> +	}
> +
> 	/* Enumerate at 400KHz */
> 	dwmci_setup_bus(host, mmc->cfg->f_min);
>
> diff --git a/include/dwmmc.h b/include/dwmmc.h
> index 4dda009..269536d 100644
> --- a/include/dwmmc.h
> +++ b/include/dwmmc.h
> @@ -115,6 +115,10 @@
> #define RX_WMARK_SHIFT		16
> #define RX_WMARK_MASK		(0xfff << RX_WMARK_SHIFT)

Could use GENMASK ...

> +/* HCON Register */
> +#define DMA_INTERFACE_IDMA		(0x0)
> +#define SDMMC_GET_TRANS_MODE(x)		(((x)>>16) & 0x3)

This might be clearer with bitfield_extract from bitfield.h

> +
> #define DWMCI_IDMAC_OWN		(1 << 31)
> #define DWMCI_IDMAC_CH		(1 << 4)
> #define DWMCI_IDMAC_FS		(1 << 3)
>

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

* [U-Boot] [U-Boot, v4, 16/19] armv7: support rk3066 early back to bootrom in vector.S
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 16/19] armv7: support rk3066 early back to bootrom in vector.S =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 12:54   ` Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 12:54 UTC (permalink / raw)
  To: u-boot



On Thu, 17 Aug 2017, Paweł Jarosz wrote:

> Rockchip bootrom first reads 1KB data from nand at offset 0x10080C00 and
> executes it. Then waits for back to bootrom and loads another 32KB to sram
> which also executes. Sdram initialisation code needs to be in one of these two
> steps. Then bootloader loads another ~200KB of data at offset 0x60000000
> and jumps to it.
>
> 32KB of data is a little low for tpl + spl part and ~200KB data is to low for
> u-boot part(for example to boot from mmc you need to disable usb support.
>
> My solution to size problem is to move sdram initialisation code to tpl stage,
> move spl part to third stage(reading 200KB data) and add support for loading
> u-boot by spl from ext2/4, fat partitions.
>
> But moving sdram initialisation code to tpl increases size of tpl above 1KB
> (first boot stage). Solution to this is to add code which will be below 1KB
> offset in tpl binary and do back to bootrom at very beginning of the tpl
> execution.
>
> Adding this few lines of code here meets these conditions.
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

See below on why this entire series has a dependency on getting boot0 
usage fixed for some unrelated architectures (I had hoped we'd already 
done this by now).

> ---
> Changes since v1:
> - moved to vector.S
>
> Changes since v2:
> - none
>
> Changes since v3:
> - none
>
> arch/arm/include/asm/arch-rockchip/boot0.h | 14 ++++++++++++++
> arch/arm/lib/vectors.S                     | 18 +++++++++---------
> configs/mk808_defconfig                    |  1 +
> 3 files changed, 24 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/include/asm/arch-rockchip/boot0.h b/arch/arm/include/asm/arch-rockchip/boot0.h
> index 72d264b..4179448 100644
> --- a/arch/arm/include/asm/arch-rockchip/boot0.h
> +++ b/arch/arm/include/asm/arch-rockchip/boot0.h
> @@ -5,6 +5,19 @@
>  * SPDX-License-Identifier:	GPL-2.0+
>  */
>
> +#if defined(CONFIG_ROCKCHIP_RK3066) && defined(CONFIG_TPL_BUILD)
> +	ldr	r3, =0x10080900
> +	ldr	r0, [r3]
> +	cmp	r0, #1
> +	movne	r0, #1
> +	strne	r0, [r3]
> +	beq	out_of_bootrom
> +	bx	lr
> +out_of_bootrom:
> +	mov	r0, #0
> +	str	r0, [r3]
> +#endif
> +
> /*
>  * Execution starts on the instruction following this 4-byte header
>  * (containing the magic 'RK33').
> @@ -26,6 +39,7 @@
> 	 */
> 	b reset	 /* may be overwritten --- should be 'nop' or a 'b reset' */
> #endif
> +
> 	b reset
>
> #if defined(CONFIG_ROCKCHIP_RK3399) && defined(CONFIG_SPL_BUILD)
> diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S
> index 1019091..e3c18da 100644
> --- a/arch/arm/lib/vectors.S
> +++ b/arch/arm/lib/vectors.S
> @@ -47,6 +47,15 @@
>
> _start:
>
> +#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
> +/*
> + * Various SoCs need something special and SoC-specific up front in
> + * order to boot, allow them to set that in their boot0.h file and then
> + * use it here.
> + */
> +#include <asm/arch/boot0.h>
> +#endif
> +

I agree on this one, but won't be able to merge it until we've resolved 
the abuse of boot0 by some of the other architectures.
For details, see the discussion following Kever's series to adjust this.

I have this on my plate for the next release cycle.

> #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
> 	.word	CONFIG_SYS_DV_NOR_BOOT_CFG
> #endif
> @@ -60,15 +69,6 @@ _start:
> 	ldr	pc, _irq
> 	ldr	pc, _fiq
>
> -#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
> -/*
> - * Various SoCs need something special and SoC-specific up front in
> - * order to boot, allow them to set that in their boot0.h file and then
> - * use it here.
> - */
> -#include <asm/arch/boot0.h>
> -#endif
> -
> /*
>  *************************************************************************
>  *
> diff --git a/configs/mk808_defconfig b/configs/mk808_defconfig
> index ab67e4f..bf4af82 100644
> --- a/configs/mk808_defconfig
> +++ b/configs/mk808_defconfig
> @@ -13,6 +13,7 @@ CONFIG_USE_PRIVATE_LIBGCC=y
> CONFIG_CMD_DHRYSTONE=y
> CONFIG_ERRNO_STR=y
> CONFIG_SYS_NS16550=y
> +CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK=y
> CONFIG_BOOTDELAY=1
> CONFIG_CONSOLE_MUX=y
> CONFIG_DISPLAY_BOARDINFO=y
>

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

* [U-Boot] [U-Boot, v4, 01/19] rockchip: rk3066: add grf header file
  2017-08-17 13:11 ` [U-Boot] [PATCH v4 01/19] rockchip: rk3066: add grf header file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> grf is needed by various drivers for rk3066 soc.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
> ---
> Changes since v1:
> - updated to shifted masks
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/include/asm/arch-rockchip/grf_rk3066.h | 621 ++++++++++++++++++++++++
>  1 file changed, 621 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rk3066.h
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 02/19] rockchip: rk3066: add rk3066 pinctrl driver
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 02/19] rockchip: rk3066: add rk3066 pinctrl driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> Add driver supporting pin multiplexing on rk3066 platform.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
> ---
> Changes since v1:
> - updated to shifted masks
> - added nand support
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/include/asm/arch-rockchip/periph.h |   1 +
>  drivers/pinctrl/Kconfig                     |   9 +
>  drivers/pinctrl/rockchip/Makefile           |   1 +
>  drivers/pinctrl/rockchip/pinctrl_rk3066.c   | 340 ++++++++++++++++++++++++++++
>  4 files changed, 351 insertions(+)
>  create mode 100644 drivers/pinctrl/rockchip/pinctrl_rk3066.c
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 03/19] rockchip: rk3066: add sysreset driver
  2017-08-17 13:12 ` [U-Boot] [PATCH v4 03/19] rockchip: rk3066: add sysreset driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> Add support for system reset for rk3066 socs.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
> ---
> Changes since v1:
> - updated to shifted masks
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/sysreset/Makefile          |  1 +
>  drivers/sysreset/sysreset_rk3066.c | 61 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 62 insertions(+)
>  create mode 100644 drivers/sysreset/sysreset_rk3066.c
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> Sandisk SDTNQGAMA is a 8GB size, 3.3V 8 bit chip with 16KB page size, 1KB write size and 40 bit ecc support
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/nand_ids.c | 3 +++
>  1 file changed, 3 insertions(+)
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> Use live tree functions to fill dwc2_plat_otg_data structure in board_usb_init.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/mach-rockchip/rk3066-board.c | 52 +++++------------------------------
>  1 file changed, 7 insertions(+), 45 deletions(-)
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> rk3xxx.dtsi is used by rk3188 and rk3066. rk3188 uses alocated data in spl but rk3066 needs it in tpl.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/dts/rk3xxx.dtsi | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18  7:02   ` Jaehoon Chung
@ 2017-08-18 13:01   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  3 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> This patch enables support for the Rockchip RK3066 SD/MMC controller, which is based on Designware IP. The device supports SD, SDIO, MMC and eMMC.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---
> Changes since v1:
> - dropped OF_PLATDATA
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mmc/rockchip_dw_mmc.c | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> Sysreset drivers for rk3066 and rk3188 contain common elements which can be reused.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  .../include/asm/arch-rockchip/sysreset_common.h    | 20 +++++++++++
>  arch/arm/mach-rockchip/Makefile                    |  3 ++
>  arch/arm/mach-rockchip/sysreset-common.c           | 39 ++++++++++++++++++++++
>  drivers/sysreset/sysreset_rk3066.c                 | 34 ++++++-------------
>  drivers/sysreset/sysreset_rk3188.c                 | 35 ++++++-------------
>  5 files changed, 84 insertions(+), 47 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-rockchip/sysreset_common.h
>  create mode 100644 arch/arm/mach-rockchip/sysreset-common.c
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> This patch allows building of nand_bbt, nand_ids, nand_util for nand drivers that need it.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/Makefile | 3 +++
>  1 file changed, 3 insertions(+)
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot,v4,18/19] dfu: fix spl build
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 18/19] dfu: fix spl build =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-18 13:01   ` Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 13:01 UTC (permalink / raw)
  To: u-boot

> In current state dfu depends on cmd/mtdparts.c which isn't build in SPL.
> This patch resolves it by cutting out unwanted code in SPL build.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - removed unneded space
> 
>  drivers/dfu/dfu_nand.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> Sandisk SDTNQGAMA is a 8GB size, 3.3V 8 bit chip with 16KB page size, 1KB write size and 40 bit ecc support
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/nand_ids.c | 3 +++
>  1 file changed, 3 insertions(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 10/19] mtd: nand: add the rockchip nand controller driver
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 10/19] mtd: nand: add the rockchip nand controller driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:45   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> Add basic Rockchip nand driver.
> 
> Driver in current state has 16, 24, 40, 60 per 1024B BCH/ECC ability and 8 bit asynchronous flash interface support. Other features will come later.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - fixed correct ecc checking
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/Kconfig         |   6 +
>  drivers/mtd/nand/Makefile        |   1 +
>  drivers/mtd/nand/rockchip_nand.c | 660 +++++++++++++++++++++++++++++++++++++++
>  include/fdtdec.h                 |   1 +
>  lib/fdtdec.c                     |   1 +
>  5 files changed, 669 insertions(+)
>  create mode 100644 drivers/mtd/nand/rockchip_nand.c
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 11/19] rockchip: mkimage: add support for rockchip nand boot image
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 11/19] rockchip: mkimage: add support for rockchip nand boot image =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:49   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> The Rockchip boot ROM requires a particular file format for booting from NAND:
> 
> * It starts with 512-byte, rc4 encoded header and is aligned to nand page size
> 
> * Then first 2KB of first stage loader (tpl) aligned to nand page size
> * n empty pages
> 
> * second 2KB of first stage loader (tpl) aligned to nand page size
> * n empty pages
> 
> * ...
> 
> * first 2KB of second stage loader (spl) aligned to nand page size
> * n empty pages
> 
> * second 2KB of first stage loader (spl) aligned to nand page size
> * n empty pages
> 
> * ...
> 
> Size of spl and tpl must be aligned to 2KB.
> 
> example usage for nand with page size 16384 and one empty page in iteration:
> 
>     # mkimage -n rk3066 -T rknand -d ./u-boot/tpl/u-boot-tpl.bin:./u-boot/spl/u-boot-spl.bin -X 16384,1 out
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  common/image.c    |   1 +
>  include/image.h   |   1 +
>  tools/Makefile    |   2 +-
>  tools/imagetool.h |   1 +
>  tools/mkimage.c   |   8 ++-
>  tools/rkcommon.c  |  10 ++--
>  tools/rkcommon.h  |  10 +++-
>  tools/rknand.c    | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/rksd.c      |   2 +-
>  tools/rkspi.c     |   2 +-
>  10 files changed, 183 insertions(+), 10 deletions(-)
>  create mode 100644 tools/rknand.c
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> Use live tree functions to fill dwc2_plat_otg_data structure in board_usb_init.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/mach-rockchip/rk3066-board.c | 52 +++++------------------------------
>  1 file changed, 7 insertions(+), 45 deletions(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 14/19] mmc: dw_mmc: support transfer mode autodetection
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18  7:02   ` Jaehoon Chung
  2017-08-18 12:51   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  3 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> dw_mmc supports two transfer modes in u-boot: idma and fifo.
> This patch adds autodetection of transfer mode and eliminates setting this in host config struct
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mmc/dw_mmc.c | 8 ++++++++
>  include/dwmmc.h      | 4 ++++
>  2 files changed, 12 insertions(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> rk3xxx.dtsi is used by rk3188 and rk3066. rk3188 uses alocated data in spl but rk3066 needs it in tpl.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/dts/rk3xxx.dtsi | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> Sysreset drivers for rk3066 and rk3188 contain common elements which can be reused.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  .../include/asm/arch-rockchip/sysreset_common.h    | 20 +++++++++++
>  arch/arm/mach-rockchip/Makefile                    |  3 ++
>  arch/arm/mach-rockchip/sysreset-common.c           | 39 ++++++++++++++++++++++
>  drivers/sysreset/sysreset_rk3066.c                 | 34 ++++++-------------
>  drivers/sysreset/sysreset_rk3188.c                 | 35 ++++++-------------
>  5 files changed, 84 insertions(+), 47 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-rockchip/sysreset_common.h
>  create mode 100644 arch/arm/mach-rockchip/sysreset-common.c
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot,v4,18/19] dfu: fix spl build
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 18/19] dfu: fix spl build =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot,v4,18/19] " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> In current state dfu depends on cmd/mtdparts.c which isn't build in SPL.
> This patch resolves it by cutting out unwanted code in SPL build.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - removed unneded space
> 
>  drivers/dfu/dfu_nand.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18  7:02   ` Jaehoon Chung
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  3 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> This patch enables support for the Rockchip RK3066 SD/MMC controller, which is based on Designware IP. The device supports SD, SDIO, MMC and eMMC.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---
> Changes since v1:
> - dropped OF_PLATDATA
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mmc/rockchip_dw_mmc.c | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 16:06   ` Philipp Tomsich
  2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-18 16:06 UTC (permalink / raw)
  To: u-boot

> This patch allows building of nand_bbt, nand_ids, nand_util for nand drivers that need it.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/Makefile | 3 +++
>  1 file changed, 3 insertions(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 10/19] mtd: nand: add the rockchip nand controller driver
  2017-08-18 12:45   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
@ 2017-08-18 18:14     ` Paweł Jarosz
  2017-08-21 18:03       ` Dr. Philipp Tomsich
  0 siblings, 1 reply; 64+ messages in thread
From: Paweł Jarosz @ 2017-08-18 18:14 UTC (permalink / raw)
  To: u-boot

Hi,


W dniu 18.08.2017 o 14:45, Philipp Tomsich pisze:
>
>
> On Thu, 17 Aug 2017, Paweł Jarosz wrote:
>
>> Add basic Rockchip nand driver.
>>
>> Driver in current state has 16, 24, 40, 60 per 1024B BCH/ECC ability 
>> and 8 bit asynchronous flash interface support. Other features will 
>> come later.
>>
>> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
>> ---
>> Changes since v1:
>> - none
>>
>> Changes since v2:
>> - fixed correct ecc checking
>>
>> Changes since v3:
>> - none
>>
>> drivers/mtd/nand/Kconfig         |   6 +
>> drivers/mtd/nand/Makefile        |   1 +
>> drivers/mtd/nand/rockchip_nand.c | 660 
>> +++++++++++++++++++++++++++++++++++++++
>> include/fdtdec.h                 |   1 +
>> lib/fdtdec.c                     |   1 +
>> 5 files changed, 669 insertions(+)
>> create mode 100644 drivers/mtd/nand/rockchip_nand.c
>>
>> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
>> index 71d678f..c308497 100644
>> --- a/drivers/mtd/nand/Kconfig
>> +++ b/drivers/mtd/nand/Kconfig
>> @@ -69,6 +69,12 @@ config NAND_PXA3XX
>>       This enables the driver for the NAND flash device found on
>>       PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
>>
>> +config NAND_ROCKCHIP
>> +    bool "Support for NAND on Rockchip SoCs"
>> +    select SYS_NAND_SELF_INIT
>> +    ---help---
>> +    Enable support for Rockchip nand.
>> +
>> config NAND_SUNXI
>>     bool "Support for NAND on Allwinner SoCs"
>>     depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
>> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
>> index c3d4a99..0659253 100644
>> --- a/drivers/mtd/nand/Makefile
>> +++ b/drivers/mtd/nand/Makefile
>> @@ -65,6 +65,7 @@ obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
>> obj-$(CONFIG_NAND_PLAT) += nand_plat.o
>> obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
>> obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
>> +obj-$(CONFIG_NAND_ROCKCHIP) += rockchip_nand.o
>>
>> else  # minimal SPL drivers
>>
>> diff --git a/drivers/mtd/nand/rockchip_nand.c 
>> b/drivers/mtd/nand/rockchip_nand.c
>> new file mode 100644
>> index 0000000..d8f4439
>> --- /dev/null
>> +++ b/drivers/mtd/nand/rockchip_nand.c
>> @@ -0,0 +1,660 @@
>> +/*
>> + * Copyright (c) 2017 Yifeng Zhao <yifeng.zhao@rock-chips.com>
>> + * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
>> + *
>> + * SPDX-License-Identifier:     GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <fdtdec.h>
>> +#include <inttypes.h>
>> +#include <nand.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mtd/mtd.h>
>> +#include <linux/mtd/nand.h>
>> +#include <linux/mtd/partitions.h>
>> +#include <linux/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#define NANDC_V6_BOOTROM_ECC    24
>> +#define    NANDC_V6_NUM_BANKS    8
>> +#define NANDC_V6_DEF_TIMEOUT    20000
>> +#define NANDC_V6_READ        0
>> +#define NANDC_V6_WRITE        1
>> +
>> +#define    NANDC_REG_V6_FMCTL    0x00
>> +#define    NANDC_REG_V6_FMWAIT    0x04
>> +#define    NANDC_REG_V6_FLCTL    0x08
>> +#define    NANDC_REG_V6_BCHCTL    0x0c
>> +#define    NANDC_REG_V6_DMA_CFG    0x10
>> +#define    NANDC_REG_V6_DMA_BUF0    0x14
>> +#define    NANDC_REG_V6_DMA_BUF1    0x18
>> +#define    NANDC_REG_V6_DMA_ST    0x1C
>> +#define    NANDC_REG_V6_BCHST    0x20
>> +#define    NANDC_REG_V6_RANDMZ    0x150
>> +#define    NANDC_REG_V6_VER    0x160
>> +#define    NANDC_REG_V6_INTEN    0x16C
>> +#define    NANDC_REG_V6_INTCLR     0x170
>> +#define    NANDC_REG_V6_INTST    0x174
>> +#define    NANDC_REG_V6_SPARE0    0x200
>> +#define    NANDC_REG_V6_SPARE1    0x230
>> +#define    NANDC_REG_V6_BANK0    0x800
>> +#define    NANDC_REG_V6_SRAM0    0x1000
>> +#define    NANDC_REG_V6_SRAM_SIZE    0x400
>
> For the Rockchip drivers we have usually used structures to represent
> the layout. I know that this will be very sparse for this particular
> case, but it seems to be worth this for consistency.
>

If it's not a problem i would leave this as is. The reason for that is
rockchip kernel nand driver (currently in backing stage) as it would
be easier to maintain both of them and add new features.
At least one driver in u-boot (sunxi nand) is doing the same thing.

>> +
>> +#define NANDC_REG_V6_DATA    0x00
>> +#define NANDC_REG_V6_ADDR    0x04
>> +#define NANDC_REG_V6_CMD    0x08
>> +
>> +/* FMCTL */
>> +#define NANDC_V6_FM_WP        BIT(8)
>> +#define NANDC_V6_FM_CE_SEL_M    0xFF
>> +#define NANDC_V6_FM_CE_SEL(x)    (1 << (x))
>
> BIT(x) ?
>
>> +#define NANDC_V6_FM_FREADY    BIT(9)
>> +
>> +/* FLCTL */
>> +#define NANDC_V6_FL_RST        BIT(0)
>> +#define NANDC_V6_FL_DIR_S    0x1
>> +#define NANDC_V6_FL_XFER_START    BIT(2)
>> +#define NANDC_V6_FL_XFER_EN    BIT(3)
>> +#define NANDC_V6_FL_ST_BUF_S    0x4
>> +#define NANDC_V6_FL_XFER_COUNT    BIT(5)
>> +#define NANDC_V6_FL_ACORRECT    BIT(10)
>> +#define NANDC_V6_FL_XFER_READY    BIT(20)
>> +
>> +/* BCHCTL */
>> +#define NAND_V6_BCH_REGION_S    0x5
>> +#define NAND_V6_BCH_REGION_M    0x7
>> +
>> +/* BCHST */
>> +#define NANDC_V6_BCH0_ST_ERR    BIT(2)
>> +#define NANDC_V6_BCH1_ST_ERR    BIT(15)
>> +#define NANDC_V6_ECC_ERR_CNT0(x) ((((x & (0x1F << 3)) >> 3) \
>> +                | ((x & (1 << 27)) >> 22)) & 0x3F)
>> +#define NANDC_V6_ECC_ERR_CNT1(x) ((((x & (0x1F << 16)) >> 16) \
>> +                | ((x & (1 << 29)) >> 24)) & 0x3F)
>
> This might benefit from using functions from bitfield.h?
>
>> +
>> +struct rk_nand {
>> +    uint32_t banks[NANDC_V6_NUM_BANKS];
>
> Is the number of banks fixed or should this be dynamically allocated 
> based
> on a device-tree property (or driver-data, if it is dependent on how 
> the controller was synthesized)?
>

This should be dynamically allocated and i will change this in the next 
version.

>> +    struct nand_hw_control controller;
>> +    uint32_t ecc_strength;
>> +    struct mtd_info mtd;
>> +    bool bootromblocks;
>> +    void __iomem *regs;
>> +    int selected_bank;
>> +};
>> +
>> +static struct nand_ecclayout nand_oob_fix = {
>> +    .eccbytes = 24,
>> +    .eccpos = {
>> +           4, 5, 6, 7, 8, 9, 10},
>> +    .oobfree = {
>> +        {.offset = 0,
>> +         .length = 4} }
>
> The indentation looks odd on those.
>
>> +};
>> +
>> +static inline struct rk_nand *to_rknand(struct nand_hw_control *ctrl)
>> +{
>> +    return container_of(ctrl, struct rk_nand, controller);
>> +}
>> +
>> +static void rockchip_nand_init(struct rk_nand *rknand)
>> +{
>> +    writel(0, rknand->regs + NANDC_REG_V6_RANDMZ);
>> +    writel(0, rknand->regs + NANDC_REG_V6_DMA_CFG);
>> +    writel(0, rknand->regs + NANDC_REG_V6_BCHCTL);
>> +    writel(NANDC_V6_FM_WP, rknand->regs + NANDC_REG_V6_FMCTL);
>> +    writel(0x1081, rknand->regs + NANDC_REG_V6_FMWAIT);
>
> Why the 0x1081?

0x1081 is the default (and safe) async timing register value set by old 
rockchip loaders.
Currently nand driver doesn't support setting timings. This will change
in the feature as it is on my TODO list for this driver.

>
>> +}
>> +
>> +static void rockchip_nand_select_chip(struct mtd_info *mtd, int chipnr)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    void __iomem *bank_base;
>> +    uint32_t reg;
>> +    int banknr;
>> +
>> +    reg = readl(rknand->regs + NANDC_REG_V6_FMCTL);
>> +    reg &= ~NANDC_V6_FM_CE_SEL_M;
>> +
>> +    if (chipnr == -1) {
>> +        banknr = -1;
>> +    } else {
>> +        banknr = rknand->banks[chipnr];
>> +        bank_base = rknand->regs + NANDC_REG_V6_BANK0 + banknr * 0x100;
>
> Once converted to a structure, this could be as simple to read as
>     bank_base = &rknand->bank[banknr];
>
>> +
>> +        chip->IO_ADDR_R = bank_base;
>> +        chip->IO_ADDR_W = bank_base;
>> +
>> +        reg |= 1 << banknr;
>> +    }
>> +    writel(reg, rknand->regs + NANDC_REG_V6_FMCTL);
>
> Why not a clrsetbits?
>
>> +
>> +    rknand->selected_bank = banknr;
>> +}
>> +
>> +static void rockchip_nand_cmd_ctrl(struct mtd_info *mtd,
>> +                   int dat,
>> +                   unsigned int ctrl)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
>> +                + rknand->selected_bank * 0x100;
>
> See above.
>
>> +
>> +    if (ctrl & NAND_CTRL_CHANGE) {
>> +        if (ctrl & NAND_ALE)
>> +            bank_base += NANDC_REG_V6_ADDR;
>
> This is not the bank_base you are modifying.
> So this really is
>     if (ctrl & NAND_ALE)
>         chip->IO_ADDR_W = &rknand->bank[i].addr;
>     else if (ctrl & NAND_CLE)
>         chip->IO_ADDR_W = &rknand->bank[i].cmd;
>     else
>         chip->IO_ADDR_W = &rknand->bank[i];
>

Correct. Banks have three separate registers for io, addr cycle, cmd cycle.
When writing to addr: Nand pin ALE is being set to high.
To cmd: Nand pin CLE is being set to high. IO is for data.
Offsets from bank base are:

#define NANDC_REG_V6_DATA    0x00
#define NANDC_REG_V6_ADDR    0x04
#define NANDC_REG_V6_CMD    0x08

>> +        else if (ctrl & NAND_CLE)
>> +            bank_base += NANDC_REG_V6_CMD;
>> +        chip->IO_ADDR_W = bank_base;
>> +    }
>> +
>> +    if (dat != NAND_CMD_NONE)
>> +        writeb(dat & 0xFF, chip->IO_ADDR_W);
>> +}
>> +
>> +static void rockchip_nand_read_buf(struct mtd_info *mtd,
>> +                   uint8_t *buf,
>> +                   int len)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    int offs = 0;
>> +    void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
>> +                + rknand->selected_bank * 0x100;
>> +
>> +    for (offs = 0; offs < len; offs++)
>> +        buf[offs] = readb(bank_base);
>> +}
>> +
>> +static void rockchip_nand_write_buf(struct mtd_info *mtd,
>> +                    const uint8_t *buf,
>> +                    int len)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    int offs = 0;
>> +    void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
>> +                + rknand->selected_bank * 0x100;
>> +
>> +    for (offs = 0; offs < len; offs++)
>> +        writeb(buf[offs], bank_base);
>> +}
>
> See above.
>
>> +
>> +static uint8_t rockchip_nand_read_byte(struct mtd_info *mtd)
>> +{
>> +    uint8_t ret;
>> +
>> +    rockchip_nand_read_buf(mtd, &ret, 1);
>> +
>> +    return ret;
>> +}
>> +
>> +static int rockchip_nand_dev_ready(struct mtd_info *mtd)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +
>> +    if (readl(rknand->regs + NANDC_REG_V6_FMCTL) & NANDC_V6_FM_FREADY)
>> +        return 1;
>> +
>> +    return 0;
>> +}
>> +
>> +static int rockchip_nand_hw_ecc_setup(struct mtd_info *mtd,
>> +                      struct nand_ecc_ctrl *ecc,
>> +                      uint32_t strength)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    u32 reg;
>> +
>> +    ecc->strength = strength;
>> +    ecc->bytes = DIV_ROUND_UP(ecc->strength * 14, 8);
>> +    ecc->bytes = ALIGN(ecc->bytes, 2);
>> +
>> +    switch (ecc->strength) {
>> +    case 60:
>> +        reg = 0x00040010;
>> +        break;
>> +    case 40:
>> +        reg = 0x00040000;
>> +        break;
>> +    case 24:
>> +        reg = 0x00000010;
>> +        break;
>> +    case 16:
>> +        reg = 0x00000000;
>> +        break;
>> +    default:
>> +        return -EINVAL;
>> +    }
>
> Could you use symbolic constants?
I will change this in the next version.
>
>> +    writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);
>> +
>> +    return 0;
>> +}
>> +
>> +static void rockchip_nand_pio_xfer_start(struct rk_nand *rknand,
>> +                     u8 dir,
>> +                     u8 st_buf)
>> +{
>> +    u32 reg;
>> +
>> +    reg = readl(rknand->regs + NANDC_REG_V6_BCHCTL);
>> +    reg = (reg & (~(NAND_V6_BCH_REGION_M << NAND_V6_BCH_REGION_S))) |
>> +          (rknand->selected_bank << NAND_V6_BCH_REGION_S);
>> +    writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);
>
> clrsetbits?
>
>> +
>> +    reg = (dir << NANDC_V6_FL_DIR_S) | (st_buf << 
>> NANDC_V6_FL_ST_BUF_S) |
>> +          NANDC_V6_FL_XFER_EN | NANDC_V6_FL_XFER_COUNT |
>> +          NANDC_V6_FL_ACORRECT;
>> +    writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);
>> +
>> +    reg |= NANDC_V6_FL_XFER_START;
>> +    writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);
>
> setbits?
>
>> +}
>> +
>> +static int rockchip_nand_wait_pio_xfer_done(struct rk_nand *rknand)
>> +{
>> +    int timeout = NANDC_V6_DEF_TIMEOUT;
>> +    int reg;
>> +
>> +    while (timeout--) {
>> +        reg = readl(rknand->regs + NANDC_REG_V6_FLCTL);
>> +
>> +        if ((reg & NANDC_V6_FL_XFER_READY) != 0)
>> +            break;
>> +
>> +        udelay(1);
>> +    }
>> +
>> +    if (timeout == 0)
>> +        return -1;
>> +
>> +    return 0;
>> +}
>> +
>> +static void rockchip_nand_read_extra_oob(struct mtd_info *mtd, u8 *oob)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>> +    int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
>> +    int len = mtd->oobsize - offset;
>> +
>> +    if (len <= 0)
>> +        return;
>> +
>> +    chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1);
>> +
>> +    rockchip_nand_read_buf(mtd, oob + offset, len);
>> +}
>> +
>> +static void rockchip_nand_write_extra_oob(struct mtd_info *mtd, u8 
>> *oob)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>> +    int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
>> +    int len = mtd->oobsize - offset;
>> +
>> +    if (len <= 0)
>> +        return;
>> +
>> +    chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1);
>> +
>> +    rockchip_nand_write_buf(mtd, oob + offset, len);
>> +}
>> +
>> +
>> +static int rockchip_nand_hw_syndrome_pio_read_page(struct mtd_info 
>> *mtd,
>> +                           struct nand_chip *chip,
>> +                           uint8_t *buf,
>> +                           int oob_required,
>> +                           int page)
>> +{
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>> +    void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
>> +    unsigned int max_bitflips = 0;
>> +    int ret, step, bch_st;
>> +    int offset = page * mtd->writesize;
>> +
>> +    if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
>> +        rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
>> +
>> +    rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ, 0);
>> +
>> +    for (step = 0; step < ecc->steps; step++) {
>> +        int data_off = step * ecc->size;
>> +        int oob_off = step * (ecc->bytes + ecc->prepad);
>> +        u8 *data = buf + data_off;
>> +        u8 *oob = chip->oob_poi + oob_off;
>> +
>> +        ret = rockchip_nand_wait_pio_xfer_done(rknand);
>> +        if (ret)
>> +            return ret;
>> +
>> +        bch_st = readl(rknand->regs + NANDC_REG_V6_BCHST);
>> +
>> +        if (bch_st & NANDC_V6_BCH0_ST_ERR) {
>> +            mtd->ecc_stats.failed++;
>> +            max_bitflips = -1;
>> +        } else {
>> +            ret = NANDC_V6_ECC_ERR_CNT0(bch_st);
>> +            mtd->ecc_stats.corrected += ret;
>> +            max_bitflips = max_t(unsigned int, max_bitflips, ret);
>> +        }
>> +
>> +        if ((step + 1) < ecc->steps)
>> +            rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ,
>> +                                  (step + 1) & 0x1);
>> +
>> +        memcpy_fromio(data, sram_base + NANDC_REG_V6_SRAM_SIZE *
>> +                                 (step & 1), ecc->size);
>> +
>> +        if (step & 1)
>> +            memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE1, 4);
>> +        else
>> +            memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE0, 4);
>> +    }
>> +
>> +    rockchip_nand_read_extra_oob(mtd, chip->oob_poi);
>> +
>> +    if (rknand->bootromblocks)
>> +        rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
>> +
>> +    return max_bitflips;
>> +}
>> +
>> +static uint32_t rockchip_nand_make_bootrom_compat(struct mtd_info *mtd,
>> +                          int page,
>> +                          const u8 *oob,
>> +                          bool bootromblocks)
>> +{
>> +    int pages_per_block = mtd->erasesize / mtd->writesize;
>> +    int offset = page * mtd->writesize;
>> +
>> +    if ((offset < (2 * mtd->erasesize)) || !(page % 2) ||
>> +        (offset >= (7 * mtd->erasesize)) || !bootromblocks)
>> +        return oob[3] | (oob[2] << 8) | (oob[1] << 16) | (oob[0] << 
>> 24);
>> +
>> +    return (page % pages_per_block + 1) * 4;
>> +}
>> +
>> +static int rockchip_nand_hw_syndrome_pio_write_page(struct mtd_info 
>> *mtd,
>> +                            struct nand_chip *chip,
>> +                            const uint8_t *buf,
>> +                            int oob_required,
>> +                            int page)
>> +{
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>> +    void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
>> +    int ret, index, step = 0;
>> +    int offset = page * mtd->writesize;
>> +    int data_off = step * ecc->size;
>> +    int oob_off = step * (ecc->bytes + ecc->prepad);
>> +    const u8 *data = buf + data_off;
>> +    const u8 *oob = chip->oob_poi + oob_off;
>> +
>> +    if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
>> +        rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
>> +
>> +    index = rockchip_nand_make_bootrom_compat(mtd, page, oob,
>> +                       rknand->bootromblocks);
>> +
>> +    memcpy_toio(sram_base, data, ecc->size);
>> +    memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0, &index, 
>> ecc->prepad);
>> +
>> +    for (step = 1; step <= ecc->steps; step++) {
>> +        rockchip_nand_pio_xfer_start(rknand, NANDC_V6_WRITE,
>> +                         (step - 1) & 0x1);
>> +
>> +        data_off = step * ecc->size;
>> +        oob_off = step * (ecc->bytes + ecc->prepad);
>> +        data = buf + data_off;
>> +        oob = chip->oob_poi + oob_off;
>> +
>> +        if (step < ecc->steps) {
>> +            memcpy_toio(sram_base + NANDC_REG_V6_SRAM_SIZE *
>> +                    (step & 1), data, ecc->size);
>> +            if (step & 1)
>> +                memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE1,
>> +                        oob, ecc->prepad);
>> +            else
>> +                memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0,
>> +                        oob, ecc->prepad);
>> +        }
>> +
>> +        ret = rockchip_nand_wait_pio_xfer_done(rknand);
>> +        if (ret)
>> +            return ret;
>> +    }
>> +
>> +    rockchip_nand_write_extra_oob(mtd, chip->oob_poi);
>> +
>> +    rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
>> +
>> +    return 0;
>> +}
>> +
>> +static const u8 strengths[] = {60, 40, 24, 16};
>> +
>> +static int rockchip_nand_ecc_max_strength(struct mtd_info *mtd,
>> +                      struct nand_ecc_ctrl *ecc)
>> +{
>> +    uint32_t max_strength, index;
>> +
>> +    max_strength = ((mtd->oobsize / ecc->steps) - ecc->prepad) * 8 / 
>> 14;
>> +
>> +    for (index = 0; index < ARRAY_SIZE(strengths); index++)
>> +        if (max_strength >= strengths[index])
>> +            break;
>> +
>> +    if (index >= ARRAY_SIZE(strengths))
>> +        return -ENOTSUPP;
>> +
>> +    return strengths[index];
>> +}
>> +
>> +static bool rockchip_nand_strength_is_valid(int strength)
>> +{
>> +    uint32_t index;
>> +
>> +    for (index = 0; index < ARRAY_SIZE(strengths); index++)
>> +        if (strength == strengths[index])
>> +            break;
>> +
>> +    if (index == ARRAY_SIZE(strengths))
>> +        return false;
>> +
>> +    return true;
>> +}
>> +
>> +static int rockchip_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
>> +                      struct nand_ecc_ctrl *ecc)
>> +{
>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>> +    uint32_t strength;
>> +    int index;
>> +
>> +    ecc->prepad = 4;
>> +    ecc->steps = mtd->writesize / ecc->size;
>> +
>> +    if (fdtdec_get_bool(gd->fdt_blob, chip->flash_node,
>> +                "rockchip,protect-bootrom-blocks"))
>> +                rknand->bootromblocks = true;
>> +    else
>> +        rknand->bootromblocks = false;
>> +
>> +    if (rockchip_nand_strength_is_valid(ecc->strength))
>> +        strength = ecc->strength;
>> +    else
>> +        strength = rockchip_nand_ecc_max_strength(mtd, ecc);
>> +
>> +    rockchip_nand_hw_ecc_setup(mtd, ecc, strength);
>> +
>> +    rknand->ecc_strength = ecc->strength;
>> +
>> +    nand_oob_fix.eccbytes = ecc->bytes * ecc->steps;
>> +    for (index = 0; index < ecc->bytes; index++)
>> +        nand_oob_fix.eccpos[index] = index + ecc->prepad;
>> +    ecc->layout = &nand_oob_fix;
>> +
>> +    if (mtd->oobsize < ((ecc->bytes + ecc->prepad) * ecc->steps)) {
>> +        return -EINVAL;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int rockchip_nand_ecc_init(struct mtd_info *mtd,
>> +                  struct nand_ecc_ctrl *ecc)
>> +{
>> +    int ret;
>> +
>> +    switch (ecc->mode) {
>> +    case NAND_ECC_HW_SYNDROME:
>> +        ret = rockchip_nand_hw_ecc_ctrl_init(mtd, ecc);
>> +        if (ret)
>> +            return ret;
>> +        ecc->read_page = rockchip_nand_hw_syndrome_pio_read_page;
>> +        ecc->write_page = rockchip_nand_hw_syndrome_pio_write_page;
>> +        break;
>> +    case NAND_ECC_SOFT_BCH:
>> +    case NAND_ECC_NONE:
>> +    case NAND_ECC_SOFT:
>> +        break;
>> +    default:
>> +        return -EINVAL;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int rockchip_nand_chip_init(int node, struct rk_nand *rknand, 
>> int devnum)
>> +{
>> +    const void *blob = gd->fdt_blob;
>> +    struct nand_chip *chip;
>> +    struct mtd_info *mtd;
>> +    int ret;
>> +
>> +    chip = kzalloc(sizeof(*chip), GFP_KERNEL);
>> +
>> +    chip->chip_delay = 50;
>> +    chip->flash_node = node;
>> +    chip->select_chip = rockchip_nand_select_chip;
>> +    chip->cmd_ctrl = rockchip_nand_cmd_ctrl;
>> +    chip->read_buf = rockchip_nand_read_buf;
>> +    chip->write_buf = rockchip_nand_write_buf;
>> +    chip->read_byte = rockchip_nand_read_byte;
>> +    chip->dev_ready = rockchip_nand_dev_ready;
>> +    chip->controller = &rknand->controller;
>> +
>> +    rknand->banks[devnum] = fdtdec_get_int(blob, node, "reg", -1);
>> +
>> +    if (rknand->banks[devnum] < 0)
>> +        return -EINVAL;
>> +
>> +    mtd = nand_to_mtd(chip);
>> +    mtd->name = "rknand";
>> +
>> +    ret = nand_scan_ident(mtd, 1, NULL);
>> +    if (ret)
>> +        return ret;
>> +
>> +    ret = rockchip_nand_ecc_init(mtd, &chip->ecc);
>> +    if (ret) {
>> +        debug("rockchip_nand_ecc_init failed: %d\n", ret);
>> +        return ret;
>> +    }
>> +
>> +    ret = nand_scan_tail(mtd);
>> +    if (ret) {
>> +        debug("nand_scan_tail failed: %d\n", ret);
>> +        return ret;
>> +    }
>> +
>> +    ret = nand_register(devnum, mtd);
>> +    if (ret) {
>> +        debug("Failed to register mtd device: %d\n", ret);
>> +        return ret;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int rockchip_nand_chips_init(int node, struct rk_nand *rknand)
>> +{
>> +    const void *blob = gd->fdt_blob;
>> +    int nand_node;
>> +    int ret, i = 0;
>> +
>> +    for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
>> +         nand_node = fdt_next_subnode(blob, nand_node)) {
>> +        ret = rockchip_nand_chip_init(nand_node, rknand, i++);
>> +        if (ret)
>> +            return ret;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +void board_nand_init(void)
>> +{
>> +    const void *blob = gd->fdt_blob;
>> +    struct rk_nand *rknand;
>> +    fdt_addr_t regs;
>> +    int node;
>> +    int ret;
>> +
>> +    rknand = kzalloc(sizeof(*rknand), GFP_KERNEL);
>> +
>> +    node = fdtdec_next_compatible(blob, 0, COMPAT_ROCKCHIP_NANDC);
>> +
>> +    if (node < 0) {
>> +        debug("Nand node not found\n");
>> +        goto err;
>> +    }
>> +
>> +    if (!fdtdec_get_is_enabled(blob, node)) {
>> +        debug("Nand disabled in device tree\n");
>> +        goto err;
>> +    }
>> +
>> +    regs = fdtdec_get_addr(blob, node, "reg");
>> +    if (regs == FDT_ADDR_T_NONE) {
>> +        debug("Nand address not found\n");
>> +        goto err;
>> +    }
>> +
>> +    rknand->regs = (void *)regs;
>> +
>> +    spin_lock_init(&rknand->controller.lock);
>> +    init_waitqueue_head(&rknand->controller.wq);
>> +
>> +    rockchip_nand_init(rknand);
>> +
>> +    ret = rockchip_nand_chips_init(node, rknand);
>> +    if (ret) {
>> +        debug("Failed to init nand chips\n");
>> +        goto err;
>> +    }
>> +
>> +    return;
>> +err:
>> +    kfree(rknand);
>> +}
>> +
>> +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
>> +{
>> +    struct mtd_info *mtd;
>> +
>> +    mtd = get_nand_dev_by_index(0);
>> +    return nand_read_skip_bad(mtd, offs, &size, NULL, size, (u_char 
>> *)dst);
>> +}
>> +
>> +void nand_deselect(void) {}
>> diff --git a/include/fdtdec.h b/include/fdtdec.h
>> index 4a0947c..0e68788 100644
>> --- a/include/fdtdec.h
>> +++ b/include/fdtdec.h
>> @@ -157,6 +157,7 @@ enum fdt_compat_id {
>>     COMPAT_ALTERA_SOCFPGA_F2SDR0,           /* SoCFPGA fpga2SDRAM0 
>> bridge */
>>     COMPAT_ALTERA_SOCFPGA_F2SDR1,           /* SoCFPGA fpga2SDRAM1 
>> bridge */
>>     COMPAT_ALTERA_SOCFPGA_F2SDR2,           /* SoCFPGA fpga2SDRAM2 
>> bridge */
>> +    COMPAT_ROCKCHIP_NANDC,            /* Rockchip NAND controller */
>>
>>     COMPAT_COUNT,
>> };
>> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
>> index 107a892..4a8a8d7 100644
>> --- a/lib/fdtdec.c
>> +++ b/lib/fdtdec.c
>> @@ -70,6 +70,7 @@ static const char * const 
>> compat_names[COMPAT_COUNT] = {
>>     COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"),
>>     COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"),
>>     COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"),
>> +    COMPAT(ROCKCHIP_NANDC, "rockchip,nandc"),
>> };
>>
>> const char *fdtdec_get_compatible(enum fdt_compat_id id)
>>
Regards,
Paweł

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

* [U-Boot] [U-Boot, v4, 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip
  2017-08-17 13:13 ` [U-Boot] [PATCH v4 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> Sandisk SDTNQGAMA is a 8GB size, 3.3V 8 bit chip with 16KB page size, 1KB write size and 40 bit ecc support
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/nand_ids.c | 3 +++
>  1 file changed, 3 insertions(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 10/19] mtd: nand: add the rockchip nand controller driver
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 10/19] mtd: nand: add the rockchip nand controller driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:45   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> Add basic Rockchip nand driver.
> 
> Driver in current state has 16, 24, 40, 60 per 1024B BCH/ECC ability and 8 bit asynchronous flash interface support. Other features will come later.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - fixed correct ecc checking
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/Kconfig         |   6 +
>  drivers/mtd/nand/Makefile        |   1 +
>  drivers/mtd/nand/rockchip_nand.c | 660 +++++++++++++++++++++++++++++++++++++++
>  include/fdtdec.h                 |   1 +
>  lib/fdtdec.c                     |   1 +
>  5 files changed, 669 insertions(+)
>  create mode 100644 drivers/mtd/nand/rockchip_nand.c
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 11/19] rockchip: mkimage: add support for rockchip nand boot image
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 11/19] rockchip: mkimage: add support for rockchip nand boot image =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 12:49   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> The Rockchip boot ROM requires a particular file format for booting from NAND:
> 
> * It starts with 512-byte, rc4 encoded header and is aligned to nand page size
> 
> * Then first 2KB of first stage loader (tpl) aligned to nand page size
> * n empty pages
> 
> * second 2KB of first stage loader (tpl) aligned to nand page size
> * n empty pages
> 
> * ...
> 
> * first 2KB of second stage loader (spl) aligned to nand page size
> * n empty pages
> 
> * second 2KB of first stage loader (spl) aligned to nand page size
> * n empty pages
> 
> * ...
> 
> Size of spl and tpl must be aligned to 2KB.
> 
> example usage for nand with page size 16384 and one empty page in iteration:
> 
>     # mkimage -n rk3066 -T rknand -d ./u-boot/tpl/u-boot-tpl.bin:./u-boot/spl/u-boot-spl.bin -X 16384,1 out
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  common/image.c    |   1 +
>  include/image.h   |   1 +
>  tools/Makefile    |   2 +-
>  tools/imagetool.h |   1 +
>  tools/mkimage.c   |   8 ++-
>  tools/rkcommon.c  |  10 ++--
>  tools/rkcommon.h  |  10 +++-
>  tools/rknand.c    | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/rksd.c      |   2 +-
>  tools/rkspi.c     |   2 +-
>  10 files changed, 183 insertions(+), 10 deletions(-)
>  create mode 100644 tools/rknand.c
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> Use live tree functions to fill dwc2_plat_otg_data structure in board_usb_init.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/mach-rockchip/rk3066-board.c | 52 +++++------------------------------
>  1 file changed, 7 insertions(+), 45 deletions(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl
  2017-08-17 13:14 ` [U-Boot] [PATCH v4 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> rk3xxx.dtsi is used by rk3188 and rk3066. rk3188 uses alocated data in spl but rk3066 needs it in tpl.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  arch/arm/dts/rk3xxx.dtsi | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 14/19] mmc: dw_mmc: support transfer mode autodetection
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                     ` (2 preceding siblings ...)
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  3 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> dw_mmc supports two transfer modes in u-boot: idma and fifo.
> This patch adds autodetection of transfer mode and eliminates setting this in host config struct
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mmc/dw_mmc.c | 8 ++++++++
>  include/dwmmc.h      | 4 ++++
>  2 files changed, 12 insertions(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
  2017-08-17 13:15 ` [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                     ` (2 preceding siblings ...)
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  3 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> This patch enables support for the Rockchip RK3066 SD/MMC controller, which is based on Designware IP. The device supports SD, SDIO, MMC and eMMC.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---
> Changes since v1:
> - dropped OF_PLATDATA
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mmc/rockchip_dw_mmc.c | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> Sysreset drivers for rk3066 and rk3188 contain common elements which can be reused.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  .../include/asm/arch-rockchip/sysreset_common.h    | 20 +++++++++++
>  arch/arm/mach-rockchip/Makefile                    |  3 ++
>  arch/arm/mach-rockchip/sysreset-common.c           | 39 ++++++++++++++++++++++
>  drivers/sysreset/sysreset_rk3066.c                 | 34 ++++++-------------
>  drivers/sysreset/sysreset_rk3188.c                 | 35 ++++++-------------
>  5 files changed, 84 insertions(+), 47 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-rockchip/sysreset_common.h
>  create mode 100644 arch/arm/mach-rockchip/sysreset-common.c
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot,v4,18/19] dfu: fix spl build
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 18/19] dfu: fix spl build =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot,v4,18/19] " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> In current state dfu depends on cmd/mtdparts.c which isn't build in SPL.
> This patch resolves it by cutting out unwanted code in SPL build.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - removed unneded space
> 
>  drivers/dfu/dfu_nand.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [U-Boot, v4, 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util =?UTF-8?q?Pawe=C5=82=20Jarosz?=
  2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
  2017-08-18 16:06   ` Philipp Tomsich
@ 2017-08-21 12:01   ` Philipp Tomsich
  2 siblings, 0 replies; 64+ messages in thread
From: Philipp Tomsich @ 2017-08-21 12:01 UTC (permalink / raw)
  To: u-boot

> This patch allows building of nand_bbt, nand_ids, nand_util for nand drivers that need it.
> 
> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
> ---
> Changes since v1:
> - none
> 
> Changes since v2:
> - none
> 
> Changes since v3:
> - none
> 
>  drivers/mtd/nand/Makefile | 3 +++
>  1 file changed, 3 insertions(+)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

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

* [U-Boot] [PATCH v4 00/19] add support for rk3066 platform.
  2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
                   ` (18 preceding siblings ...)
  2017-08-17 13:16 ` [U-Boot] [PATCH v4 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util =?UTF-8?q?Pawe=C5=82=20Jarosz?=
@ 2017-08-21 15:46 ` Bin Meng
  2017-08-21 20:48   ` Dr. Philipp Tomsich
  19 siblings, 1 reply; 64+ messages in thread
From: Bin Meng @ 2017-08-21 15:46 UTC (permalink / raw)
  To: u-boot

Hi,

On Thu, Aug 17, 2017 at 9:11 PM, =?UTF-8?q?Pawe=C5=82=20Jarosz?=
<paweljarosz3691@gmail.com> wrote:
> This patch serie adds support for Rockchip RK3066 processor.
>
> Paweł Jarosz (19):
>   rockchip: rk3066: add grf header file
>   rockchip: rk3066: add rk3066 pinctrl driver
>   rockchip: rk3066: add sysreset driver
>   rockchip: rk3066: add clock driver for rk3066 soc
>   rockchip: rk3066: add rk3066 platform devicetree file
>   rockchip: rk3066: add core support
>   rockchip: rk3066: add mk808 board files
>   rockchip: rk3066: add sdram driver
>   mtd: nand: add support for the Sandisk SDTNQGAMA chip
>   mtd: nand: add the rockchip nand controller driver
>   rockchip: mkimage: add support for rockchip nand boot image
>   rockchip: board: rk3066: convert board_usb_init to live tree functions
>   ARM: dts: rockchip: prefer u-boot,dm-pre-reloc rather than
>     u-boot,dm-spl
>   mmc: dw_mmc: support transfer mode autodetection
>   mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
>   armv7: support rk3066 early back to bootrom in vector.S
>   rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers
>   dfu: fix spl build
>   mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util
>

I am not sure if anyone else on the ML sees your name as funny
characters. At least I see:

=?UTF-8?q?Pawe=C5=82=20Jarosz?= <paweljarosz3691@gmail.com>

Can you please figure out where the problem is?

Regards,
Bin

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

* [U-Boot] [U-Boot, v4, 10/19] mtd: nand: add the rockchip nand controller driver
  2017-08-18 18:14     ` Paweł Jarosz
@ 2017-08-21 18:03       ` Dr. Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Dr. Philipp Tomsich @ 2017-08-21 18:03 UTC (permalink / raw)
  To: u-boot


> On 18 Aug 2017, at 20:14, Paweł Jarosz <paweljarosz3691@gmail.com> wrote:
> 
> Hi,
> 
> 
> W dniu 18.08.2017 o 14:45, Philipp Tomsich pisze:
>> 
>> 
>> On Thu, 17 Aug 2017, Paweł Jarosz wrote:
>> 
>>> Add basic Rockchip nand driver.
>>> 
>>> Driver in current state has 16, 24, 40, 60 per 1024B BCH/ECC ability and 8 bit asynchronous flash interface support. Other features will come later.
>>> 
>>> Signed-off-by: Paweł Jarosz <paweljarosz3691@gmail.com>
>>> ---
>>> Changes since v1:
>>> - none
>>> 
>>> Changes since v2:
>>> - fixed correct ecc checking
>>> 
>>> Changes since v3:
>>> - none
>>> 
>>> drivers/mtd/nand/Kconfig         |   6 +
>>> drivers/mtd/nand/Makefile        |   1 +
>>> drivers/mtd/nand/rockchip_nand.c | 660 +++++++++++++++++++++++++++++++++++++++
>>> include/fdtdec.h                 |   1 +
>>> lib/fdtdec.c                     |   1 +
>>> 5 files changed, 669 insertions(+)
>>> create mode 100644 drivers/mtd/nand/rockchip_nand.c
>>> 
>>> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
>>> index 71d678f..c308497 100644
>>> --- a/drivers/mtd/nand/Kconfig
>>> +++ b/drivers/mtd/nand/Kconfig
>>> @@ -69,6 +69,12 @@ config NAND_PXA3XX
>>>      This enables the driver for the NAND flash device found on
>>>      PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
>>> 
>>> +config NAND_ROCKCHIP
>>> +    bool "Support for NAND on Rockchip SoCs"
>>> +    select SYS_NAND_SELF_INIT
>>> +    ---help---
>>> +    Enable support for Rockchip nand.
>>> +
>>> config NAND_SUNXI
>>>    bool "Support for NAND on Allwinner SoCs"
>>>    depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
>>> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
>>> index c3d4a99..0659253 100644
>>> --- a/drivers/mtd/nand/Makefile
>>> +++ b/drivers/mtd/nand/Makefile
>>> @@ -65,6 +65,7 @@ obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
>>> obj-$(CONFIG_NAND_PLAT) += nand_plat.o
>>> obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
>>> obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
>>> +obj-$(CONFIG_NAND_ROCKCHIP) += rockchip_nand.o
>>> 
>>> else  # minimal SPL drivers
>>> 
>>> diff --git a/drivers/mtd/nand/rockchip_nand.c b/drivers/mtd/nand/rockchip_nand.c
>>> new file mode 100644
>>> index 0000000..d8f4439
>>> --- /dev/null
>>> +++ b/drivers/mtd/nand/rockchip_nand.c
>>> @@ -0,0 +1,660 @@
>>> +/*
>>> + * Copyright (c) 2017 Yifeng Zhao <yifeng.zhao@rock-chips.com>
>>> + * Copyright (c) 2017 Paweł Jarosz <paweljarosz3691@gmail.com>
>>> + *
>>> + * SPDX-License-Identifier:     GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <fdtdec.h>
>>> +#include <inttypes.h>
>>> +#include <nand.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/mtd/mtd.h>
>>> +#include <linux/mtd/nand.h>
>>> +#include <linux/mtd/partitions.h>
>>> +#include <linux/io.h>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +#define NANDC_V6_BOOTROM_ECC    24
>>> +#define    NANDC_V6_NUM_BANKS    8
>>> +#define NANDC_V6_DEF_TIMEOUT    20000
>>> +#define NANDC_V6_READ        0
>>> +#define NANDC_V6_WRITE        1
>>> +
>>> +#define    NANDC_REG_V6_FMCTL    0x00
>>> +#define    NANDC_REG_V6_FMWAIT    0x04
>>> +#define    NANDC_REG_V6_FLCTL    0x08
>>> +#define    NANDC_REG_V6_BCHCTL    0x0c
>>> +#define    NANDC_REG_V6_DMA_CFG    0x10
>>> +#define    NANDC_REG_V6_DMA_BUF0    0x14
>>> +#define    NANDC_REG_V6_DMA_BUF1    0x18
>>> +#define    NANDC_REG_V6_DMA_ST    0x1C
>>> +#define    NANDC_REG_V6_BCHST    0x20
>>> +#define    NANDC_REG_V6_RANDMZ    0x150
>>> +#define    NANDC_REG_V6_VER    0x160
>>> +#define    NANDC_REG_V6_INTEN    0x16C
>>> +#define    NANDC_REG_V6_INTCLR     0x170
>>> +#define    NANDC_REG_V6_INTST    0x174
>>> +#define    NANDC_REG_V6_SPARE0    0x200
>>> +#define    NANDC_REG_V6_SPARE1    0x230
>>> +#define    NANDC_REG_V6_BANK0    0x800
>>> +#define    NANDC_REG_V6_SRAM0    0x1000
>>> +#define    NANDC_REG_V6_SRAM_SIZE    0x400
>> 
>> For the Rockchip drivers we have usually used structures to represent
>> the layout. I know that this will be very sparse for this particular
>> case, but it seems to be worth this for consistency.
>> 
> 
> If it's not a problem i would leave this as is. The reason for that is
> rockchip kernel nand driver (currently in backing stage) as it would
> be easier to maintain both of them and add new features.
> At least one driver in u-boot (sunxi nand) is doing the same thing.

I feel strongly about this one, as this is a matter of maintainability
and readability (and looking at the sunxi NAND driver, I would have
similar concerns… although at least they don’t multiply-add banks
into addresses).

I really don’t see the point of living with code sequences like:
	void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0 + rknand->selected_bank * 0x100;
	 if (ctrl & NAND_ALE)
		bank_base += NANDC_REG_V6_ADDR;
	chip->IO_ADDR_W = bank_base;
when you in fact you want to write:
	chip->IO_ADDR_W = &regs->bank[selected_bank].addr;

The only reason for using the “base + OFFSET” addressing would be
if you tried to support two closely related controllers that only differed
in the offset of registers (in which it would actually read more like
“base + driver_data->reg_offsets[REGISTER_NAME]”… and even
then, I’d insist on hiding this in a wrapper around readl/writel. 

So for the sake of clarity, please change this to either
(a)	use a structure to reflect the register layout
(b)	add read/write accessor functions, so the address arithmetic is
	properly abstracted away.

> 
>>> +
>>> +#define NANDC_REG_V6_DATA    0x00
>>> +#define NANDC_REG_V6_ADDR    0x04
>>> +#define NANDC_REG_V6_CMD    0x08
>>> +
>>> +/* FMCTL */
>>> +#define NANDC_V6_FM_WP        BIT(8)
>>> +#define NANDC_V6_FM_CE_SEL_M    0xFF
>>> +#define NANDC_V6_FM_CE_SEL(x)    (1 << (x))
>> 
>> BIT(x) ?
>> 
>>> +#define NANDC_V6_FM_FREADY    BIT(9)
>>> +
>>> +/* FLCTL */
>>> +#define NANDC_V6_FL_RST        BIT(0)
>>> +#define NANDC_V6_FL_DIR_S    0x1
>>> +#define NANDC_V6_FL_XFER_START    BIT(2)
>>> +#define NANDC_V6_FL_XFER_EN    BIT(3)
>>> +#define NANDC_V6_FL_ST_BUF_S    0x4
>>> +#define NANDC_V6_FL_XFER_COUNT    BIT(5)
>>> +#define NANDC_V6_FL_ACORRECT    BIT(10)
>>> +#define NANDC_V6_FL_XFER_READY    BIT(20)
>>> +
>>> +/* BCHCTL */
>>> +#define NAND_V6_BCH_REGION_S    0x5
>>> +#define NAND_V6_BCH_REGION_M    0x7
>>> +
>>> +/* BCHST */
>>> +#define NANDC_V6_BCH0_ST_ERR    BIT(2)
>>> +#define NANDC_V6_BCH1_ST_ERR    BIT(15)
>>> +#define NANDC_V6_ECC_ERR_CNT0(x) ((((x & (0x1F << 3)) >> 3) \
>>> +                | ((x & (1 << 27)) >> 22)) & 0x3F)
>>> +#define NANDC_V6_ECC_ERR_CNT1(x) ((((x & (0x1F << 16)) >> 16) \
>>> +                | ((x & (1 << 29)) >> 24)) & 0x3F)
>> 
>> This might benefit from using functions from bitfield.h?
>> 
>>> +
>>> +struct rk_nand {
>>> +    uint32_t banks[NANDC_V6_NUM_BANKS];
>> 
>> Is the number of banks fixed or should this be dynamically allocated based
>> on a device-tree property (or driver-data, if it is dependent on how the controller was synthesized)?
>> 
> 
> This should be dynamically allocated and i will change this in the next version.
> 
>>> +    struct nand_hw_control controller;
>>> +    uint32_t ecc_strength;
>>> +    struct mtd_info mtd;
>>> +    bool bootromblocks;
>>> +    void __iomem *regs;
>>> +    int selected_bank;
>>> +};
>>> +
>>> +static struct nand_ecclayout nand_oob_fix = {
>>> +    .eccbytes = 24,
>>> +    .eccpos = {
>>> +           4, 5, 6, 7, 8, 9, 10},
>>> +    .oobfree = {
>>> +        {.offset = 0,
>>> +         .length = 4} }
>> 
>> The indentation looks odd on those.
>> 
>>> +};
>>> +
>>> +static inline struct rk_nand *to_rknand(struct nand_hw_control *ctrl)
>>> +{
>>> +    return container_of(ctrl, struct rk_nand, controller);
>>> +}
>>> +
>>> +static void rockchip_nand_init(struct rk_nand *rknand)
>>> +{
>>> +    writel(0, rknand->regs + NANDC_REG_V6_RANDMZ);
>>> +    writel(0, rknand->regs + NANDC_REG_V6_DMA_CFG);
>>> +    writel(0, rknand->regs + NANDC_REG_V6_BCHCTL);
>>> +    writel(NANDC_V6_FM_WP, rknand->regs + NANDC_REG_V6_FMCTL);
>>> +    writel(0x1081, rknand->regs + NANDC_REG_V6_FMWAIT);
>> 
>> Why the 0x1081?
> 
> 0x1081 is the default (and safe) async timing register value set by old rockchip loaders.
> Currently nand driver doesn't support setting timings. This will change
> in the feature as it is on my TODO list for this driver.

I had to look up the FMWAIT register in one of the chip manuals to figure out
what exactly this is trying to do. And if I see this correctly, you are setting
CSRW, RWPW and RWCS timings at once.

Also: Why is this a safe value and are the reset-values of the controller
unsafe? You might want to leave at least a comment here as a starting
point for people who might need to touch this driver in the future.

> 
>> 
>>> +}
>>> +
>>> +static void rockchip_nand_select_chip(struct mtd_info *mtd, int chipnr)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    void __iomem *bank_base;
>>> +    uint32_t reg;
>>> +    int banknr;
>>> +
>>> +    reg = readl(rknand->regs + NANDC_REG_V6_FMCTL);
>>> +    reg &= ~NANDC_V6_FM_CE_SEL_M;
>>> +
>>> +    if (chipnr == -1) {
>>> +        banknr = -1;
>>> +    } else {
>>> +        banknr = rknand->banks[chipnr];
>>> +        bank_base = rknand->regs + NANDC_REG_V6_BANK0 + banknr * 0x100;
>> 
>> Once converted to a structure, this could be as simple to read as
>>    bank_base = &rknand->bank[banknr];
>> 
>>> +
>>> +        chip->IO_ADDR_R = bank_base;
>>> +        chip->IO_ADDR_W = bank_base;
>>> +
>>> +        reg |= 1 << banknr;
>>> +    }
>>> +    writel(reg, rknand->regs + NANDC_REG_V6_FMCTL);
>> 
>> Why not a clrsetbits?
>> 
>>> +
>>> +    rknand->selected_bank = banknr;
>>> +}
>>> +
>>> +static void rockchip_nand_cmd_ctrl(struct mtd_info *mtd,
>>> +                   int dat,
>>> +                   unsigned int ctrl)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
>>> +                + rknand->selected_bank * 0x100;
>> 
>> See above.
>> 
>>> +
>>> +    if (ctrl & NAND_CTRL_CHANGE) {
>>> +        if (ctrl & NAND_ALE)
>>> +            bank_base += NANDC_REG_V6_ADDR;
>> 
>> This is not the bank_base you are modifying.
>> So this really is
>>    if (ctrl & NAND_ALE)
>>        chip->IO_ADDR_W = &rknand->bank[i].addr;
>>    else if (ctrl & NAND_CLE)
>>        chip->IO_ADDR_W = &rknand->bank[i].cmd;
>>    else
>>        chip->IO_ADDR_W = &rknand->bank[i];
>> 
> 
> Correct. Banks have three separate registers for io, addr cycle, cmd cycle.
> When writing to addr: Nand pin ALE is being set to high.
> To cmd: Nand pin CLE is being set to high. IO is for data.
> Offsets from bank base are:
> 
> #define NANDC_REG_V6_DATA    0x00
> #define NANDC_REG_V6_ADDR    0x04
> #define NANDC_REG_V6_CMD    0x08
> 
>>> +        else if (ctrl & NAND_CLE)
>>> +            bank_base += NANDC_REG_V6_CMD;
>>> +        chip->IO_ADDR_W = bank_base;
>>> +    }
>>> +
>>> +    if (dat != NAND_CMD_NONE)
>>> +        writeb(dat & 0xFF, chip->IO_ADDR_W);
>>> +}
>>> +
>>> +static void rockchip_nand_read_buf(struct mtd_info *mtd,
>>> +                   uint8_t *buf,
>>> +                   int len)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    int offs = 0;
>>> +    void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
>>> +                + rknand->selected_bank * 0x100;
>>> +
>>> +    for (offs = 0; offs < len; offs++)
>>> +        buf[offs] = readb(bank_base);
>>> +}
>>> +
>>> +static void rockchip_nand_write_buf(struct mtd_info *mtd,
>>> +                    const uint8_t *buf,
>>> +                    int len)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    int offs = 0;
>>> +    void __iomem *bank_base = rknand->regs + NANDC_REG_V6_BANK0
>>> +                + rknand->selected_bank * 0x100;
>>> +
>>> +    for (offs = 0; offs < len; offs++)
>>> +        writeb(buf[offs], bank_base);
>>> +}
>> 
>> See above.
>> 
>>> +
>>> +static uint8_t rockchip_nand_read_byte(struct mtd_info *mtd)
>>> +{
>>> +    uint8_t ret;
>>> +
>>> +    rockchip_nand_read_buf(mtd, &ret, 1);
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static int rockchip_nand_dev_ready(struct mtd_info *mtd)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +
>>> +    if (readl(rknand->regs + NANDC_REG_V6_FMCTL) & NANDC_V6_FM_FREADY)
>>> +        return 1;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int rockchip_nand_hw_ecc_setup(struct mtd_info *mtd,
>>> +                      struct nand_ecc_ctrl *ecc,
>>> +                      uint32_t strength)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    u32 reg;
>>> +
>>> +    ecc->strength = strength;
>>> +    ecc->bytes = DIV_ROUND_UP(ecc->strength * 14, 8);
>>> +    ecc->bytes = ALIGN(ecc->bytes, 2);
>>> +
>>> +    switch (ecc->strength) {
>>> +    case 60:
>>> +        reg = 0x00040010;
>>> +        break;
>>> +    case 40:
>>> +        reg = 0x00040000;
>>> +        break;
>>> +    case 24:
>>> +        reg = 0x00000010;
>>> +        break;
>>> +    case 16:
>>> +        reg = 0x00000000;
>>> +        break;
>>> +    default:
>>> +        return -EINVAL;
>>> +    }
>> 
>> Could you use symbolic constants?
> I will change this in the next version.
>> 
>>> +    writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static void rockchip_nand_pio_xfer_start(struct rk_nand *rknand,
>>> +                     u8 dir,
>>> +                     u8 st_buf)
>>> +{
>>> +    u32 reg;
>>> +
>>> +    reg = readl(rknand->regs + NANDC_REG_V6_BCHCTL);
>>> +    reg = (reg & (~(NAND_V6_BCH_REGION_M << NAND_V6_BCH_REGION_S))) |
>>> +          (rknand->selected_bank << NAND_V6_BCH_REGION_S);
>>> +    writel(reg, rknand->regs + NANDC_REG_V6_BCHCTL);
>> 
>> clrsetbits?
>> 
>>> +
>>> +    reg = (dir << NANDC_V6_FL_DIR_S) | (st_buf << NANDC_V6_FL_ST_BUF_S) |
>>> +          NANDC_V6_FL_XFER_EN | NANDC_V6_FL_XFER_COUNT |
>>> +          NANDC_V6_FL_ACORRECT;
>>> +    writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);
>>> +
>>> +    reg |= NANDC_V6_FL_XFER_START;
>>> +    writel(reg, rknand->regs + NANDC_REG_V6_FLCTL);
>> 
>> setbits?
>> 
>>> +}
>>> +
>>> +static int rockchip_nand_wait_pio_xfer_done(struct rk_nand *rknand)
>>> +{
>>> +    int timeout = NANDC_V6_DEF_TIMEOUT;
>>> +    int reg;
>>> +
>>> +    while (timeout--) {
>>> +        reg = readl(rknand->regs + NANDC_REG_V6_FLCTL);
>>> +
>>> +        if ((reg & NANDC_V6_FL_XFER_READY) != 0)
>>> +            break;
>>> +
>>> +        udelay(1);
>>> +    }
>>> +
>>> +    if (timeout == 0)
>>> +        return -1;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static void rockchip_nand_read_extra_oob(struct mtd_info *mtd, u8 *oob)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>>> +    int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
>>> +    int len = mtd->oobsize - offset;
>>> +
>>> +    if (len <= 0)
>>> +        return;
>>> +
>>> +    chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset + mtd->writesize, -1);
>>> +
>>> +    rockchip_nand_read_buf(mtd, oob + offset, len);
>>> +}
>>> +
>>> +static void rockchip_nand_write_extra_oob(struct mtd_info *mtd, u8 *oob)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>>> +    int offset = ((ecc->bytes + ecc->prepad) * ecc->steps);
>>> +    int len = mtd->oobsize - offset;
>>> +
>>> +    if (len <= 0)
>>> +        return;
>>> +
>>> +    chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset + mtd->writesize, -1);
>>> +
>>> +    rockchip_nand_write_buf(mtd, oob + offset, len);
>>> +}
>>> +
>>> +
>>> +static int rockchip_nand_hw_syndrome_pio_read_page(struct mtd_info *mtd,
>>> +                           struct nand_chip *chip,
>>> +                           uint8_t *buf,
>>> +                           int oob_required,
>>> +                           int page)
>>> +{
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>>> +    void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
>>> +    unsigned int max_bitflips = 0;
>>> +    int ret, step, bch_st;
>>> +    int offset = page * mtd->writesize;
>>> +
>>> +    if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
>>> +        rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
>>> +
>>> +    rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ, 0);
>>> +
>>> +    for (step = 0; step < ecc->steps; step++) {
>>> +        int data_off = step * ecc->size;
>>> +        int oob_off = step * (ecc->bytes + ecc->prepad);
>>> +        u8 *data = buf + data_off;
>>> +        u8 *oob = chip->oob_poi + oob_off;
>>> +
>>> +        ret = rockchip_nand_wait_pio_xfer_done(rknand);
>>> +        if (ret)
>>> +            return ret;
>>> +
>>> +        bch_st = readl(rknand->regs + NANDC_REG_V6_BCHST);
>>> +
>>> +        if (bch_st & NANDC_V6_BCH0_ST_ERR) {
>>> +            mtd->ecc_stats.failed++;
>>> +            max_bitflips = -1;
>>> +        } else {
>>> +            ret = NANDC_V6_ECC_ERR_CNT0(bch_st);
>>> +            mtd->ecc_stats.corrected += ret;
>>> +            max_bitflips = max_t(unsigned int, max_bitflips, ret);
>>> +        }
>>> +
>>> +        if ((step + 1) < ecc->steps)
>>> +            rockchip_nand_pio_xfer_start(rknand, NANDC_V6_READ,
>>> +                                  (step + 1) & 0x1);
>>> +
>>> +        memcpy_fromio(data, sram_base + NANDC_REG_V6_SRAM_SIZE *
>>> +                                 (step & 1), ecc->size);
>>> +
>>> +        if (step & 1)
>>> +            memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE1, 4);
>>> +        else
>>> +            memcpy_fromio(oob, rknand->regs + NANDC_REG_V6_SPARE0, 4);
>>> +    }
>>> +
>>> +    rockchip_nand_read_extra_oob(mtd, chip->oob_poi);
>>> +
>>> +    if (rknand->bootromblocks)
>>> +        rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
>>> +
>>> +    return max_bitflips;
>>> +}
>>> +
>>> +static uint32_t rockchip_nand_make_bootrom_compat(struct mtd_info *mtd,
>>> +                          int page,
>>> +                          const u8 *oob,
>>> +                          bool bootromblocks)
>>> +{
>>> +    int pages_per_block = mtd->erasesize / mtd->writesize;
>>> +    int offset = page * mtd->writesize;
>>> +
>>> +    if ((offset < (2 * mtd->erasesize)) || !(page % 2) ||
>>> +        (offset >= (7 * mtd->erasesize)) || !bootromblocks)
>>> +        return oob[3] | (oob[2] << 8) | (oob[1] << 16) | (oob[0] << 24);
>>> +
>>> +    return (page % pages_per_block + 1) * 4;
>>> +}
>>> +
>>> +static int rockchip_nand_hw_syndrome_pio_write_page(struct mtd_info *mtd,
>>> +                            struct nand_chip *chip,
>>> +                            const uint8_t *buf,
>>> +                            int oob_required,
>>> +                            int page)
>>> +{
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    struct nand_ecc_ctrl *ecc = &chip->ecc;
>>> +    void __iomem *sram_base = rknand->regs + NANDC_REG_V6_SRAM0;
>>> +    int ret, index, step = 0;
>>> +    int offset = page * mtd->writesize;
>>> +    int data_off = step * ecc->size;
>>> +    int oob_off = step * (ecc->bytes + ecc->prepad);
>>> +    const u8 *data = buf + data_off;
>>> +    const u8 *oob = chip->oob_poi + oob_off;
>>> +
>>> +    if (rknand->bootromblocks && (offset < (7 * mtd->erasesize)))
>>> +        rockchip_nand_hw_ecc_setup(mtd, ecc, NANDC_V6_BOOTROM_ECC);
>>> +
>>> +    index = rockchip_nand_make_bootrom_compat(mtd, page, oob,
>>> +                       rknand->bootromblocks);
>>> +
>>> +    memcpy_toio(sram_base, data, ecc->size);
>>> +    memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0, &index, ecc->prepad);
>>> +
>>> +    for (step = 1; step <= ecc->steps; step++) {
>>> +        rockchip_nand_pio_xfer_start(rknand, NANDC_V6_WRITE,
>>> +                         (step - 1) & 0x1);
>>> +
>>> +        data_off = step * ecc->size;
>>> +        oob_off = step * (ecc->bytes + ecc->prepad);
>>> +        data = buf + data_off;
>>> +        oob = chip->oob_poi + oob_off;
>>> +
>>> +        if (step < ecc->steps) {
>>> +            memcpy_toio(sram_base + NANDC_REG_V6_SRAM_SIZE *
>>> +                    (step & 1), data, ecc->size);
>>> +            if (step & 1)
>>> +                memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE1,
>>> +                        oob, ecc->prepad);
>>> +            else
>>> +                memcpy_toio(rknand->regs + NANDC_REG_V6_SPARE0,
>>> +                        oob, ecc->prepad);
>>> +        }
>>> +
>>> +        ret = rockchip_nand_wait_pio_xfer_done(rknand);
>>> +        if (ret)
>>> +            return ret;
>>> +    }
>>> +
>>> +    rockchip_nand_write_extra_oob(mtd, chip->oob_poi);
>>> +
>>> +    rockchip_nand_hw_ecc_setup(mtd, ecc, rknand->ecc_strength);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static const u8 strengths[] = {60, 40, 24, 16};
>>> +
>>> +static int rockchip_nand_ecc_max_strength(struct mtd_info *mtd,
>>> +                      struct nand_ecc_ctrl *ecc)
>>> +{
>>> +    uint32_t max_strength, index;
>>> +
>>> +    max_strength = ((mtd->oobsize / ecc->steps) - ecc->prepad) * 8 / 14;
>>> +
>>> +    for (index = 0; index < ARRAY_SIZE(strengths); index++)
>>> +        if (max_strength >= strengths[index])
>>> +            break;
>>> +
>>> +    if (index >= ARRAY_SIZE(strengths))
>>> +        return -ENOTSUPP;
>>> +
>>> +    return strengths[index];
>>> +}
>>> +
>>> +static bool rockchip_nand_strength_is_valid(int strength)
>>> +{
>>> +    uint32_t index;
>>> +
>>> +    for (index = 0; index < ARRAY_SIZE(strengths); index++)
>>> +        if (strength == strengths[index])
>>> +            break;
>>> +
>>> +    if (index == ARRAY_SIZE(strengths))
>>> +        return false;
>>> +
>>> +    return true;
>>> +}
>>> +
>>> +static int rockchip_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
>>> +                      struct nand_ecc_ctrl *ecc)
>>> +{
>>> +    struct nand_chip *chip = mtd_to_nand(mtd);
>>> +    struct rk_nand *rknand = to_rknand(chip->controller);
>>> +    uint32_t strength;
>>> +    int index;
>>> +
>>> +    ecc->prepad = 4;
>>> +    ecc->steps = mtd->writesize / ecc->size;
>>> +
>>> +    if (fdtdec_get_bool(gd->fdt_blob, chip->flash_node,
>>> +                "rockchip,protect-bootrom-blocks”))

I didn’t see documentation for the DTS binding?
This I just miss this?

>>> +                rknand->bootromblocks = true;
>>> +    else
>>> +        rknand->bootromblocks = false;
>>> +
>>> +    if (rockchip_nand_strength_is_valid(ecc->strength))
>>> +        strength = ecc->strength;
>>> +    else
>>> +        strength = rockchip_nand_ecc_max_strength(mtd, ecc);
>>> +
>>> +    rockchip_nand_hw_ecc_setup(mtd, ecc, strength);
>>> +
>>> +    rknand->ecc_strength = ecc->strength;
>>> +
>>> +    nand_oob_fix.eccbytes = ecc->bytes * ecc->steps;
>>> +    for (index = 0; index < ecc->bytes; index++)
>>> +        nand_oob_fix.eccpos[index] = index + ecc->prepad;
>>> +    ecc->layout = &nand_oob_fix;
>>> +
>>> +    if (mtd->oobsize < ((ecc->bytes + ecc->prepad) * ecc->steps)) {
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int rockchip_nand_ecc_init(struct mtd_info *mtd,
>>> +                  struct nand_ecc_ctrl *ecc)
>>> +{
>>> +    int ret;
>>> +
>>> +    switch (ecc->mode) {
>>> +    case NAND_ECC_HW_SYNDROME:
>>> +        ret = rockchip_nand_hw_ecc_ctrl_init(mtd, ecc);
>>> +        if (ret)
>>> +            return ret;
>>> +        ecc->read_page = rockchip_nand_hw_syndrome_pio_read_page;
>>> +        ecc->write_page = rockchip_nand_hw_syndrome_pio_write_page;
>>> +        break;
>>> +    case NAND_ECC_SOFT_BCH:
>>> +    case NAND_ECC_NONE:
>>> +    case NAND_ECC_SOFT:
>>> +        break;
>>> +    default:
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int rockchip_nand_chip_init(int node, struct rk_nand *rknand, int devnum)
>>> +{
>>> +    const void *blob = gd->fdt_blob;
>>> +    struct nand_chip *chip;
>>> +    struct mtd_info *mtd;
>>> +    int ret;
>>> +
>>> +    chip = kzalloc(sizeof(*chip), GFP_KERNEL);
>>> +
>>> +    chip->chip_delay = 50;
>>> +    chip->flash_node = node;
>>> +    chip->select_chip = rockchip_nand_select_chip;
>>> +    chip->cmd_ctrl = rockchip_nand_cmd_ctrl;
>>> +    chip->read_buf = rockchip_nand_read_buf;
>>> +    chip->write_buf = rockchip_nand_write_buf;
>>> +    chip->read_byte = rockchip_nand_read_byte;
>>> +    chip->dev_ready = rockchip_nand_dev_ready;
>>> +    chip->controller = &rknand->controller;
>>> +
>>> +    rknand->banks[devnum] = fdtdec_get_int(blob, node, "reg", -1);
>>> +
>>> +    if (rknand->banks[devnum] < 0)
>>> +        return -EINVAL;
>>> +
>>> +    mtd = nand_to_mtd(chip);
>>> +    mtd->name = "rknand";
>>> +
>>> +    ret = nand_scan_ident(mtd, 1, NULL);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    ret = rockchip_nand_ecc_init(mtd, &chip->ecc);
>>> +    if (ret) {
>>> +        debug("rockchip_nand_ecc_init failed: %d\n", ret);
>>> +        return ret;
>>> +    }
>>> +
>>> +    ret = nand_scan_tail(mtd);
>>> +    if (ret) {
>>> +        debug("nand_scan_tail failed: %d\n", ret);
>>> +        return ret;
>>> +    }
>>> +
>>> +    ret = nand_register(devnum, mtd);
>>> +    if (ret) {
>>> +        debug("Failed to register mtd device: %d\n", ret);
>>> +        return ret;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int rockchip_nand_chips_init(int node, struct rk_nand *rknand)
>>> +{
>>> +    const void *blob = gd->fdt_blob;
>>> +    int nand_node;
>>> +    int ret, i = 0;
>>> +
>>> +    for (nand_node = fdt_first_subnode(blob, node); nand_node >= 0;
>>> +         nand_node = fdt_next_subnode(blob, nand_node)) {
>>> +        ret = rockchip_nand_chip_init(nand_node, rknand, i++);
>>> +        if (ret)
>>> +            return ret;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +void board_nand_init(void)
>>> +{
>>> +    const void *blob = gd->fdt_blob;
>>> +    struct rk_nand *rknand;
>>> +    fdt_addr_t regs;
>>> +    int node;
>>> +    int ret;
>>> +
>>> +    rknand = kzalloc(sizeof(*rknand), GFP_KERNEL);
>>> +
>>> +    node = fdtdec_next_compatible(blob, 0, COMPAT_ROCKCHIP_NANDC);
>>> +
>>> +    if (node < 0) {
>>> +        debug("Nand node not found\n");
>>> +        goto err;
>>> +    }
>>> +
>>> +    if (!fdtdec_get_is_enabled(blob, node)) {
>>> +        debug("Nand disabled in device tree\n");
>>> +        goto err;
>>> +    }
>>> +
>>> +    regs = fdtdec_get_addr(blob, node, "reg");
>>> +    if (regs == FDT_ADDR_T_NONE) {
>>> +        debug("Nand address not found\n");
>>> +        goto err;
>>> +    }
>>> +
>>> +    rknand->regs = (void *)regs;
>>> +
>>> +    spin_lock_init(&rknand->controller.lock);
>>> +    init_waitqueue_head(&rknand->controller.wq);
>>> +
>>> +    rockchip_nand_init(rknand);
>>> +
>>> +    ret = rockchip_nand_chips_init(node, rknand);
>>> +    if (ret) {
>>> +        debug("Failed to init nand chips\n");
>>> +        goto err;
>>> +    }
>>> +
>>> +    return;
>>> +err:
>>> +    kfree(rknand);
>>> +}
>>> +
>>> +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
>>> +{
>>> +    struct mtd_info *mtd;
>>> +
>>> +    mtd = get_nand_dev_by_index(0);
>>> +    return nand_read_skip_bad(mtd, offs, &size, NULL, size, (u_char *)dst);
>>> +}
>>> +
>>> +void nand_deselect(void) {}
>>> diff --git a/include/fdtdec.h b/include/fdtdec.h
>>> index 4a0947c..0e68788 100644
>>> --- a/include/fdtdec.h
>>> +++ b/include/fdtdec.h
>>> @@ -157,6 +157,7 @@ enum fdt_compat_id {
>>>    COMPAT_ALTERA_SOCFPGA_F2SDR0,           /* SoCFPGA fpga2SDRAM0 bridge */
>>>    COMPAT_ALTERA_SOCFPGA_F2SDR1,           /* SoCFPGA fpga2SDRAM1 bridge */
>>>    COMPAT_ALTERA_SOCFPGA_F2SDR2,           /* SoCFPGA fpga2SDRAM2 bridge */
>>> +    COMPAT_ROCKCHIP_NANDC,            /* Rockchip NAND controller */
>>> 
>>>    COMPAT_COUNT,
>>> };
>>> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
>>> index 107a892..4a8a8d7 100644
>>> --- a/lib/fdtdec.c
>>> +++ b/lib/fdtdec.c
>>> @@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>>>    COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"),
>>>    COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"),
>>>    COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"),
>>> +    COMPAT(ROCKCHIP_NANDC, "rockchip,nandc"),
>>> };
>>> 
>>> const char *fdtdec_get_compatible(enum fdt_compat_id id)
>>> 
> Regards,
> Paweł

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

* [U-Boot] [PATCH v4 00/19] add support for rk3066 platform.
  2017-08-21 15:46 ` [U-Boot] [PATCH v4 00/19] add support for rk3066 platform Bin Meng
@ 2017-08-21 20:48   ` Dr. Philipp Tomsich
  0 siblings, 0 replies; 64+ messages in thread
From: Dr. Philipp Tomsich @ 2017-08-21 20:48 UTC (permalink / raw)
  To: u-boot

Pawel,

> On 21 Aug 2017, at 17:46, Bin Meng <bmeng.cn@gmail.com> wrote:
> 
> Hi,
> 
> On Thu, Aug 17, 2017 at 9:11 PM, =?UTF-8?q?Pawe=C5=82=20Jarosz?=
> <paweljarosz3691@gmail.com> wrote:
>> This patch serie adds support for Rockchip RK3066 processor.
>> 
>> Paweł Jarosz (19):
>>  rockchip: rk3066: add grf header file
>>  rockchip: rk3066: add rk3066 pinctrl driver
>>  rockchip: rk3066: add sysreset driver
>>  rockchip: rk3066: add clock driver for rk3066 soc
>>  rockchip: rk3066: add rk3066 platform devicetree file
>>  rockchip: rk3066: add core support
>>  rockchip: rk3066: add mk808 board files
>>  rockchip: rk3066: add sdram driver
>>  mtd: nand: add support for the Sandisk SDTNQGAMA chip
>>  mtd: nand: add the rockchip nand controller driver
>>  rockchip: mkimage: add support for rockchip nand boot image
>>  rockchip: board: rk3066: convert board_usb_init to live tree functions
>>  ARM: dts: rockchip: prefer u-boot,dm-pre-reloc rather than
>>    u-boot,dm-spl
>>  mmc: dw_mmc: support transfer mode autodetection
>>  mmc: dw_mmc: rockchip: add support for rk3066 sdmmc
>>  armv7: support rk3066 early back to bootrom in vector.S
>>  rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers
>>  dfu: fix spl build
>>  mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util
>> 
> 
> I am not sure if anyone else on the ML sees your name as funny
> characters. At least I see:
> 
> =?UTF-8?q?Pawe=C5=82=20Jarosz?= <paweljarosz3691@gmail.com>

Note that we see two different encoding, depending on the mail-client you
send this from:
	From: =?utf-8?B?UGF3ZcWC?= Jarosz <paweljarosz3691@gmail.com> 		(User-Agent: Mutt/1.5.24 (2015-08-30)
	From: =?UTF-8?Q?Pawe=c5=82_Jarosz?= <paweljarosz3691@gmail.com> 	(User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1)

Both encodings seem to be correct RFC2047, as far as I can tell.

However, the encoding used by Mutt seems to work better (e.g. it shows
correctly for me in both the list-view of Mail.app and in the message view,
whereas the encoding used by Thunderbird only shows correctly in the
message view).

> 
> Can you please figure out where the problem is?
> 
> Regards,
> Bin
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

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

end of thread, other threads:[~2017-08-21 20:48 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-17 13:11 [U-Boot] [PATCH v4 00/19] add support for rk3066 platform =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-17 13:11 ` [U-Boot] [PATCH v4 01/19] rockchip: rk3066: add grf header file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-17 13:12 ` [U-Boot] [PATCH v4 02/19] rockchip: rk3066: add rk3066 pinctrl driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-17 13:12 ` [U-Boot] [PATCH v4 03/19] rockchip: rk3066: add sysreset driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-17 13:12 ` [U-Boot] [PATCH v4 04/19] rockchip: rk3066: add clock driver for rk3066 soc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 11:26   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-17 13:12 ` [U-Boot] [PATCH v4 05/19] rockchip: rk3066: add rk3066 platform devicetree file =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-17 13:13 ` [U-Boot] [PATCH v4 06/19] rockchip: rk3066: add core support =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 12:26   ` [U-Boot] [U-Boot,v4,06/19] " Philipp Tomsich
2017-08-17 13:13 ` [U-Boot] [PATCH v4 07/19] rockchip: rk3066: add mk808 board files =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-17 13:13 ` [U-Boot] [PATCH v4 08/19] rockchip: rk3066: add sdram driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 12:34   ` [U-Boot] [U-Boot,v4,08/19] " Philipp Tomsich
2017-08-17 13:13 ` [U-Boot] [PATCH v4 09/19] mtd: nand: add support for the Sandisk SDTNQGAMA chip =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:14 ` [U-Boot] [PATCH v4 10/19] mtd: nand: add the rockchip nand controller driver =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 12:45   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 18:14     ` Paweł Jarosz
2017-08-21 18:03       ` Dr. Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:14 ` [U-Boot] [PATCH v4 11/19] rockchip: mkimage: add support for rockchip nand boot image =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 12:49   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:14 ` [U-Boot] [PATCH v4 12/19] rockchip: board: rk3066: convert board_usb_init to live tree functions =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:14 ` [U-Boot] [PATCH v4 13/19] ARM: dts: rockchip: prefer u-boot, dm-pre-reloc rather than u-boot, dm-spl =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:15 ` [U-Boot] [PATCH v4 14/19] mmc: dw_mmc: support transfer mode autodetection =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18  7:02   ` Jaehoon Chung
2017-08-18  9:36     ` Paweł Jarosz
2017-08-18 12:51   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:15 ` [U-Boot] [PATCH v4 15/19] mmc: dw_mmc: rockchip: add support for rk3066 sdmmc =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18  7:02   ` Jaehoon Chung
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:16 ` [U-Boot] [PATCH v4 16/19] armv7: support rk3066 early back to bootrom in vector.S =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 12:54   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-17 13:16 ` [U-Boot] [PATCH v4 17/19] rockchip: sysreset: deduplicate rk3066 and rk3188 sysreset drivers =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:16 ` [U-Boot] [PATCH v4 18/19] dfu: fix spl build =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot,v4,18/19] " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-17 13:16 ` [U-Boot] [PATCH v4 19/19] mtd: nand: spl: allow build nand_bbt, nand_ids and nand_util =?UTF-8?q?Pawe=C5=82=20Jarosz?=
2017-08-18 13:01   ` [U-Boot] [U-Boot, v4, " Philipp Tomsich
2017-08-18 16:06   ` Philipp Tomsich
2017-08-21 12:01   ` Philipp Tomsich
2017-08-21 15:46 ` [U-Boot] [PATCH v4 00/19] add support for rk3066 platform Bin Meng
2017-08-21 20:48   ` Dr. Philipp Tomsich

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.