From 32191a3912018b2dd3645cfe9c52ae3eb1031e30 Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Mon, 21 Aug 2017 10:59:00 +0200 Subject: [PATCH 1/5] rockchip: phycore: Read configuration EEPROM & set ethaddr in late init Read SoM information from EEPROM and set ethaddr in late init. Signed-off-by: Wadim Egorov Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich --- board/phytec/phycore_rk3288/phycore-rk3288.c | 62 ++++++++++++++++++++ board/phytec/phycore_rk3288/som.h | 21 +++++++ configs/phycore-rk3288_defconfig | 2 + 3 files changed, 85 insertions(+) create mode 100644 board/phytec/phycore_rk3288/som.h diff --git a/board/phytec/phycore_rk3288/phycore-rk3288.c b/board/phytec/phycore_rk3288/phycore-rk3288.c index 20696f6dca..47b069e2ad 100644 --- a/board/phytec/phycore_rk3288/phycore-rk3288.c +++ b/board/phytec/phycore_rk3288/phycore-rk3288.c @@ -5,4 +5,66 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include #include +#include +#include +#include +#include +#include "som.h" + +static int valid_rk3288_som(struct rk3288_som *som) +{ + unsigned char *p = (unsigned char *)som; + unsigned char *e = p + sizeof(struct rk3288_som) - 1; + int hw = 0; + + while (p < e) { + hw += hweight8(*p); + p++; + } + + return hw == som->bs; +} + +int rk_board_late_init(void) +{ + int ret; + struct udevice *dev; + struct rk3288_som opt; + int off; + + /* Get the identificatioin page of M24C32-D EEPROM */ + off = fdt_path_offset(gd->fdt_blob, "eeprom0"); + if (off < 0) { + printf("%s: No eeprom0 path offset\n", __func__); + return off; + } + + ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev); + if (ret) { + printf("%s: Could not find EEPROM\n", __func__); + return ret; + } + + ret = i2c_set_chip_offset_len(dev, 2); + if (ret) + return ret; + + ret = i2c_eeprom_read(dev, 0, (uint8_t *)&opt, + sizeof(struct rk3288_som)); + if (ret) { + printf("%s: Could not read EEPROM\n", __func__); + return ret; + } + + if (opt.api_version != 0 || !valid_rk3288_som(&opt)) { + printf("Invalid data or wrong EEPROM layout version.\n"); + /* Proceed anyway, since there is no fallback option */ + } + + if (is_valid_ethaddr(opt.mac)) + eth_env_set_enetaddr("ethaddr", opt.mac); + + return 0; +} diff --git a/board/phytec/phycore_rk3288/som.h b/board/phytec/phycore_rk3288/som.h new file mode 100644 index 0000000000..1b7f9a13b7 --- /dev/null +++ b/board/phytec/phycore_rk3288/som.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2017 PHYTEC Messtechnik GmbH + * Author: Wadim Egorov + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * rk3288_som struct represents the eeprom layout for PHYTEC RK3288 based SoMs + */ +struct rk3288_som { + unsigned char api_version; /* EEPROM layout API version */ + unsigned char mod_version; /* PCM/PFL/PCA */ + unsigned char option[12]; /* coding for variants */ + unsigned char som_rev; /* SOM revision */ + unsigned char mac[6]; + unsigned char ksp; /* 1: KSP, 2: KSM */ + unsigned char kspno; /* Number for KSP/KSM module */ + unsigned char reserved[8]; /* not used */ + unsigned char bs; /* Bits set in previous bytes */ +} __attribute__ ((__packed__)); diff --git a/configs/phycore-rk3288_defconfig b/configs/phycore-rk3288_defconfig index 17855a94b5..338efc484c 100644 --- a/configs/phycore-rk3288_defconfig +++ b/configs/phycore-rk3288_defconfig @@ -46,6 +46,8 @@ CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_ROCKCHIP_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_I2C_EEPROM=y CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_DM_ETH=y From 40d4f79b819588751a07a01c40bab5173f4e5a73 Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Mon, 21 Aug 2017 13:36:57 +0200 Subject: [PATCH 2/5] rockchip: rk3288: Add reset reason detection Sometimes it's helpful to know the reset reason caused in the SoC. Add reset reason detection for the RK3288 SoC. This will set an environment variable which represents the reset reason. Signed-off-by: Wadim Egorov Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich --- .../include/asm/arch-rockchip/cru_rk3288.h | 12 ++++++ arch/arm/mach-rockchip/rk3288-board.c | 39 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h index c7e21bd605..79a6d6db80 100644 --- a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h @@ -220,4 +220,16 @@ enum { CLKF_MASK = 0x1fff << CLKF_SHIFT, }; +/* CRU_GLB_RST_ST */ +enum { + GLB_POR_RST, + FST_GLB_RST_ST = BIT(0), + SND_GLB_RST_ST = BIT(1), + FST_GLB_TSADC_RST_ST = BIT(2), + SND_GLB_TSADC_RST_ST = BIT(3), + FST_GLB_WDT_RST_ST = BIT(4), + SND_GLB_WDT_RST_ST = BIT(5), + GLB_RST_ST_MASK = GENMASK(5, 0), +}; + #endif diff --git a/arch/arm/mach-rockchip/rk3288-board.c b/arch/arm/mach-rockchip/rk3288-board.c index 74c6cc14a1..278bb406f0 100644 --- a/arch/arm/mach-rockchip/rk3288-board.c +++ b/arch/arm/mach-rockchip/rk3288-board.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -70,10 +71,48 @@ int rk3288_qos_init(void) return 0; } +static void rk3288_detect_reset_reason(void) +{ + struct rk3288_cru *cru = rockchip_get_cru(); + const char *reason; + + if (IS_ERR(cru)) + return; + + switch (cru->cru_glb_rst_st) { + case GLB_POR_RST: + reason = "POR"; + break; + case FST_GLB_RST_ST: + case SND_GLB_RST_ST: + reason = "RST"; + break; + case FST_GLB_TSADC_RST_ST: + case SND_GLB_TSADC_RST_ST: + reason = "THERMAL"; + break; + case FST_GLB_WDT_RST_ST: + case SND_GLB_WDT_RST_ST: + reason = "WDOG"; + break; + default: + reason = "unknown reset"; + } + + env_set("reset_reason", reason); + + /* + * Clear cru_glb_rst_st, so we can determine the last reset cause + * for following resets. + */ + rk_clrreg(&cru->cru_glb_rst_st, GLB_RST_ST_MASK); +} + int board_late_init(void) { setup_boot_mode(); rk3288_qos_init(); + rk3288_detect_reset_reason(); return rk_board_late_init(); } From 5798d503fcae62fe1b82bef12adbce25cc2c1c0c Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 25 Aug 2017 13:22:00 +0200 Subject: [PATCH 3/5] rockchip: timer: fix U_BOOT_DRIVER name When I originally added this driver, I did some careless (and in retrospect: mindless) copy & paste for the U_BOOT_DRIVER structure skeletion... unfortunately, the 'arc_timer' string was committed and slipped through all reviews. This fixes the U_BOOT_DRIVER name to read 'rockchip_rk3368_timer' (as originally intended). Signed-off-by: Philipp Tomsich Reported-by: Artturi Alm --- drivers/timer/rockchip_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/timer/rockchip_timer.c b/drivers/timer/rockchip_timer.c index 0848033c66..eb44965a19 100644 --- a/drivers/timer/rockchip_timer.c +++ b/drivers/timer/rockchip_timer.c @@ -92,7 +92,7 @@ static const struct udevice_id rockchip_timer_ids[] = { {} }; -U_BOOT_DRIVER(arc_timer) = { +U_BOOT_DRIVER(rockchip_rk3368_timer) = { .name = "rockchip_rk3368_timer", .id = UCLASS_TIMER, .of_match = rockchip_timer_ids, From 313bbcf0ea91db33bdf6ac394e26acff4215bfcf Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Thu, 27 Jul 2017 20:38:52 +0800 Subject: [PATCH 4/5] rockchip: firefly-rk3399: enable ATF and dwmmc enable the ATF option and SDCard in defconfig. Signed-off-by: Kever Yang Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich --- configs/firefly-rk3399_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/firefly-rk3399_defconfig b/configs/firefly-rk3399_defconfig index 7e3d107072..58eaab3783 100644 --- a/configs/firefly-rk3399_defconfig +++ b/configs/firefly-rk3399_defconfig @@ -13,6 +13,8 @@ CONFIG_SPL_LOAD_FIT=y CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200 +CONFIG_SPL_ATF_SUPPORT=y +CONFIG_SPL_ATF_TEXT_BASE=0x00010000 CONFIG_CMD_BOOTZ=y # CONFIG_CMD_IMLS is not set CONFIG_CMD_GPT=y From 5deaa530280fda91b8fef632c62c94e7bfd89561 Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Thu, 3 Aug 2017 13:48:11 +0200 Subject: [PATCH 5/5] rockchip: i2c: fix >32 byte reads The hw can read up to 32 bytes at a time. If we need more than one chunk, we have to enter the plain RX mode. Signed-off-by: Wadim Egorov Acked-by: Philipp Tomsich --- drivers/i2c/rk_i2c.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c index 8bc045a1a0..68e66536e4 100644 --- a/drivers/i2c/rk_i2c.c +++ b/drivers/i2c/rk_i2c.c @@ -164,6 +164,7 @@ static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uint rxdata; uint i, j; int err; + bool snd_chunk = false; debug("rk_i2c_read: chip = %d, reg = %d, r_len = %d, b_len = %d\n", chip, reg, r_len, b_len); @@ -184,15 +185,26 @@ static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, while (bytes_remain_len) { if (bytes_remain_len > RK_I2C_FIFO_SIZE) { - con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX); + con = I2C_CON_EN; bytes_xferred = 32; } else { - con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX) | - I2C_CON_LASTACK; + /* + * The hw can read up to 32 bytes at a time. If we need + * more than one chunk, send an ACK after the last byte. + */ + con = I2C_CON_EN | I2C_CON_LASTACK; bytes_xferred = bytes_remain_len; } words_xferred = DIV_ROUND_UP(bytes_xferred, 4); + /* + * make sure we are in plain RX mode if we read a second chunk + */ + if (snd_chunk) + con |= I2C_CON_MOD(I2C_MODE_RX); + else + con |= I2C_CON_MOD(I2C_MODE_TRX); + writel(con, ®s->con); writel(bytes_xferred, ®s->mrxcnt); writel(I2C_MBRFIEN | I2C_NAKRCVIEN, ®s->ien); @@ -227,6 +239,7 @@ static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, } bytes_remain_len -= bytes_xferred; + snd_chunk = true; debug("I2C Read bytes_remain_len %d\n", bytes_remain_len); }