[U-Boot] [PATCH V2 05/20] imx: mx7ulp: Add soc level initialization codes and functions

Stefano Babic sbabic at denx.de
Sun Feb 12 09:19:41 UTC 2017


Hi Peng,

On 27/12/2016 11:04, Peng Fan wrote:
> Implement soc level functions to get cpu rev, reset cause, enable cache,
> etc. We will disable the wdog and init clocks in s_init at very early u-boot
> phase.
> 
> Since the we are seeking the way to get chip id for mx7ulp, the get_cpu_rev
> is hard coded to a fixed value. This may change in future.
> 

ok, understood, noted

> Reuse some code in imx-common.
> 
> Signed-off-by: Peng Fan <peng.fan at nxp.com>
> Signed-off-by: Ye Li <ye.li at nxp.com>
> Cc: Stefano Babic <sbabic at denx.de>
> ---
> 
> V2:
>  Reuse code in imx-common
> 
>  arch/arm/Makefile                            |   2 +-
>  arch/arm/cpu/armv7/mx7ulp/Makefile           |   2 +-
>  arch/arm/cpu/armv7/mx7ulp/soc.c              | 274 +++++++++++++++++++++++++++
>  arch/arm/imx-common/Makefile                 |   4 +
>  arch/arm/include/asm/arch-imx/cpu.h          |   2 +
>  arch/arm/include/asm/arch-mx7ulp/imx-regs.h  |   5 +
>  arch/arm/include/asm/arch-mx7ulp/sys_proto.h |  21 ++
>  7 files changed, 308 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/mx7ulp/soc.c
>  create mode 100644 arch/arm/include/asm/arch-mx7ulp/sys_proto.h
> 
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index ef4f69d..0921a66 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -99,7 +99,7 @@ ifneq (,$(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_MX35)$(filter $(SOC), mx25 mx27 mx5
>  libs-y += arch/arm/imx-common/
>  endif
>  else
> -ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx31 mx35 mxs vf610))
> +ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx7ulp mx31 mx35 mxs vf610))
>  libs-y += arch/arm/imx-common/
>  endif
>  endif
> diff --git a/arch/arm/cpu/armv7/mx7ulp/Makefile b/arch/arm/cpu/armv7/mx7ulp/Makefile
> index 6f37e8c..0248ea8 100644
> --- a/arch/arm/cpu/armv7/mx7ulp/Makefile
> +++ b/arch/arm/cpu/armv7/mx7ulp/Makefile
> @@ -5,4 +5,4 @@
>  #
>  #
>  
> -obj-y	:= clock.o iomux.o pcc.o scg.o
> +obj-y	:= soc.o clock.o iomux.o pcc.o scg.o
> diff --git a/arch/arm/cpu/armv7/mx7ulp/soc.c b/arch/arm/cpu/armv7/mx7ulp/soc.c
> new file mode 100644
> index 0000000..d04edc5
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/mx7ulp/soc.c
> @@ -0,0 +1,274 @@
> +/*
> + * Copyright (C) 2016 Freescale Semiconductor, Inc.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/sys_proto.h>
> +
> +static char *get_reset_cause(char *);
> +
> +u32 get_cpu_rev(void)
> +{
> +	/* Temporally hard code the CPU rev to 0x73, rev 1.0. Fix it later */
> +	return (MXC_CPU_MX7ULP << 12) | (1 << 4);
> +}
> +
> +#ifdef CONFIG_REVISION_TAG
> +u32 __weak get_board_rev(void)
> +{
> +	return get_cpu_rev();
> +}
> +#endif
> +
> +enum bt_mode get_boot_mode(void)
> +{
> +	u32 bt0_cfg = 0;
> +
> +	bt0_cfg = readl(CMC0_RBASE + 0x40);
> +	bt0_cfg &= (BT0CFG_LPBOOT_MASK | BT0CFG_DUALBOOT_MASK);
> +
> +	if (!(bt0_cfg & BT0CFG_LPBOOT_MASK)) {
> +		/* No low power boot */
> +		if (bt0_cfg & BT0CFG_DUALBOOT_MASK)
> +			return DUAL_BOOT;
> +		else
> +			return SINGLE_BOOT;
> +	}
> +
> +	return LOW_POWER_BOOT;
> +}
> +
> +int arch_cpu_init(void)
> +{
> +	return 0;
> +}
> +
> +#ifdef CONFIG_BOARD_POSTCLK_INIT
> +int board_postclk_init(void)
> +{
> +	return 0;
> +}
> +#endif
> +
> +#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
> +#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
> +#define REFRESH_WORD0 0xA602 /* 1st refresh word */
> +#define REFRESH_WORD1 0xB480 /* 2nd refresh word */
> +
> +static void disable_wdog(u32 wdog_base)
> +{
> +	writel(UNLOCK_WORD0, (wdog_base + 0x04));
> +	writel(UNLOCK_WORD1, (wdog_base + 0x04));
> +	writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */
> +	writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */
> +	writel(0x120, (wdog_base + 0x00)); /* Disable it and set update */
> +
> +	writel(REFRESH_WORD0, (wdog_base + 0x04)); /* Refresh the CNT */
> +	writel(REFRESH_WORD1, (wdog_base + 0x04));
> +}
> +
> +void init_wdog(void)
> +{
> +	/*
> +	 * ROM will configure WDOG1, disable it or enable it
> +	 * depending on FUSE. The update bit is set for reconfigurable.
> +	 * We have to use unlock sequence to reconfigure it.
> +	 * WDOG2 is not touched by ROM, so it will have default value
> +	 * which is enabled. We can directly configure it.
> +	 * To simplify the codes, we still use same reconfigure
> +	 * process as WDOG1. Because the update bit is not set for
> +	 * WDOG2, the unlock sequence won't take effect really.
> +	 * It actually directly configure the wdog.
> +	 * In this function, we will disable both WDOG1 and WDOG2,
> +	 * and set update bit for both. So that kernel can reconfigure them.
> +	 */
> +	disable_wdog(WDG1_RBASE);
> +	disable_wdog(WDG2_RBASE);
> +}
> +
> +
> +void s_init(void)
> +{
> +	/* Disable wdog */
> +	init_wdog();
> +
> +	/* clock configuration. */
> +	clock_init();
> +
> +	return;
> +}
> +
> +#ifndef CONFIG_ULP_WATCHDOG
> +void reset_cpu(ulong addr)
> +{
> +	setbits_le32(SIM0_RBASE, SIM_SOPT1_A7_SW_RESET);
> +	while (1)
> +		;
> +}
> +#endif
> +
> +#if defined(CONFIG_DISPLAY_CPUINFO)
> +const char *get_imx_type(u32 imxtype)
> +{
> +#ifdef CONFIG_MXC_OCOTP
> +
> +	u8 uid[8];
> +	u32 val;
> +
> +	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
> +	struct fuse_bank *bank = &ocotp->bank[0];
> +	struct fuse_bank1_regs *fuse =
> +		(struct fuse_bank1_regs *)bank->fuse_regs;
> +
> +	val = readl(&fuse->cfg0);
> +	*uid = val & 0xFF;
> +	*(uid + 1) = (val & 0xFF00) >> 8;
> +
> +	val = readl(&fuse->cfg1);
> +	*(uid + 2) = val & 0xFF;
> +	*(uid + 3) = (val & 0xFF00) >> 8;
> +
> +	val = readl(&fuse->cfg2);
> +	*(uid + 4) = val & 0xFF;
> +	*(uid + 5) = (val & 0xFF00) >> 8;
> +
> +	val = readl(&fuse->cfg3);
> +	*(uid + 6) = val & 0xFF;
> +	*(uid + 7) = (val & 0xFF00) >> 8;

I think it can be better described here, at least what you want to read
for fuse->cfg0..cfg3.

> +
> +	debug("UID = %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
> +	      uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
> +
> +#endif
> +	return "7ULP";
> +}
> +
> +int print_cpuinfo(void)
> +{
> +	u32 cpurev;
> +	char cause[18];
> +
> +	cpurev = get_cpu_rev();
> +
> +	printf("CPU:   Freescale i.MX%s rev%d.%d at %d MHz\n",
> +	       get_imx_type((cpurev & 0xFF000) >> 12),
> +	       (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0,
> +	       mxc_get_clock(MXC_ARM_CLK) / 1000000);
> +
> +	printf("Reset cause: %s\n", get_reset_cause(cause));
> +
> +	printf("Boot mode: ");
> +	switch (get_boot_mode()) {
> +	case LOW_POWER_BOOT:
> +		printf("Low power boot\n");
> +		break;
> +	case DUAL_BOOT:
> +		printf("Dual boot\n");
> +		break;
> +	case SINGLE_BOOT:
> +	default:
> +		printf("Single boot\n");
> +		break;
> +	}
> +
> +	return 0;
> +}
> +#endif
> +
> +#define CMC_SRS_TAMPER                    (1 << 31)
> +#define CMC_SRS_SECURITY                  (1 << 30)
> +#define CMC_SRS_TZWDG                     (1 << 29)
> +#define CMC_SRS_JTAG_RST                  (1 << 28)
> +#define CMC_SRS_CORE1                     (1 << 16)
> +#define CMC_SRS_LOCKUP                    (1 << 15)
> +#define CMC_SRS_SW                        (1 << 14)
> +#define CMC_SRS_WDG                       (1 << 13)
> +#define CMC_SRS_PIN_RESET                 (1 << 8)
> +#define CMC_SRS_WARM                      (1 << 4)
> +#define CMC_SRS_HVD                       (1 << 3)
> +#define CMC_SRS_LVD                       (1 << 2)
> +#define CMC_SRS_POR                       (1 << 1)
> +#define CMC_SRS_WUP                       (1 << 0)
> +
> +static u32 reset_cause = -1;
> +
> +static char *get_reset_cause(char *ret)
> +{
> +	u32 cause1, cause = 0, srs = 0;
> +	u32 *reg_ssrs = (u32 *)(SRC_BASE_ADDR + 0x28);
> +	u32 *reg_srs = (u32 *)(SRC_BASE_ADDR + 0x20);
> +
> +	if (!ret)
> +		return "null";
> +
> +	srs = readl(reg_srs);
> +	cause1 = readl(reg_ssrs);
> +	writel(cause1, reg_ssrs);
> +
> +	reset_cause = cause1;
> +
> +	cause = cause1 & (CMC_SRS_POR | CMC_SRS_WUP | CMC_SRS_WARM);
> +
> +	switch (cause) {
> +	case CMC_SRS_POR:
> +		sprintf(ret, "%s", "POR");
> +		break;
> +	case CMC_SRS_WUP:
> +		sprintf(ret, "%s", "WUP");
> +		break;
> +	case CMC_SRS_WARM:
> +		cause = cause1 & (CMC_SRS_WDG | CMC_SRS_SW |
> +			CMC_SRS_JTAG_RST);
> +		switch (cause) {
> +		case CMC_SRS_WDG:
> +			sprintf(ret, "%s", "WARM-WDG");
> +			break;
> +		case CMC_SRS_SW:
> +			sprintf(ret, "%s", "WARM-SW");
> +			break;
> +		case CMC_SRS_JTAG_RST:
> +			sprintf(ret, "%s", "WARM-JTAG");
> +			break;
> +		default:
> +			sprintf(ret, "%s", "WARM-UNKN");
> +			break;
> +		}
> +		break;
> +	default:
> +		sprintf(ret, "%s-%X", "UNKN", cause1);
> +		break;
> +	}
> +
> +	debug("[%X] SRS[%X] %X - ", cause1, srs, srs^cause1);
> +	return ret;
> +}
> +
> +u32 get_imx_reset_cause(void)
> +{
> +	return reset_cause;

Why do you stored it ain a static variable ? Is it read just once from
registers ?

> +}
> +
> +#ifdef CONFIG_ENV_IS_IN_MMC
> +__weak int board_mmc_get_env_dev(int devno)
> +{
> +	return CONFIG_SYS_MMC_ENV_DEV;
> +}
> +
> +int mmc_get_env_dev(void)
> +{
> +	int devno = 0;
> +	u32 bt1_cfg = 0;
> +
> +	/* If not boot from sd/mmc, use default value */
> +	if (get_boot_mode() == LOW_POWER_BOOT)
> +		return CONFIG_SYS_MMC_ENV_DEV;
> +
> +	bt1_cfg = readl(CMC1_RBASE + 0x40);
> +	devno = (bt1_cfg >> 9) & 0x7;
> +
> +	return board_mmc_get_env_dev(devno);
> +}
> +#endif
> diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile
> index 1873185..68ee60f 100644
> --- a/arch/arm/imx-common/Makefile
> +++ b/arch/arm/imx-common/Makefile
> @@ -31,6 +31,10 @@ obj-$(CONFIG_IMX_RDC) += rdc-sema.o
>  obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o
>  obj-$(CONFIG_SECURE_BOOT)    += hab.o
>  endif
> +ifeq ($(SOC),$(filter $(SOC),mx7ulp))
> +obj-y  += cache.o
> +obj-$(CONFIG_SECURE_BOOT) += hab.o
> +endif
>  ifeq ($(SOC),$(filter $(SOC),vf610))
>  obj-y += ddrmc-vf610.o
>  endif
> diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h
> index 8bd1421..b052406 100644
> --- a/arch/arm/include/asm/arch-imx/cpu.h
> +++ b/arch/arm/include/asm/arch-imx/cpu.h
> @@ -25,10 +25,12 @@
>  #define MXC_CPU_MX6QP		0x69
>  #define MXC_CPU_MX7S		0x71 /* dummy ID */
>  #define MXC_CPU_MX7D		0x72
> +#define MXC_CPU_MX7ULP		0x81 /* Temporally hard code */

ok

>  #define MXC_CPU_VF610		0xF6 /* dummy ID */
>  
>  #define MXC_SOC_MX6		0x60
>  #define MXC_SOC_MX7		0x70
> +#define MXC_SOC_MX7ULP		0x80 /* dummy */
>  
>  #define CHIP_REV_1_0            0x10
>  #define CHIP_REV_1_1            0x11
> diff --git a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h
> index 30d0ba4..cdfbe2e 100644
> --- a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h
> +++ b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h
> @@ -97,6 +97,11 @@
>  #define CORE_B_ROM_SIZE			(SZ_32K + SZ_64K)
>  #define CORE_B_ROM_BASE			(0x00000000)
>  
> +#define ROMCP_ARB_BASE_ADDR		CORE_B_ROM_BASE
> +#define ROMCP_ARB_END_ADDR		CORE_B_ROM_SIZE
> +#define IRAM_BASE_ADDR			OCRAM_0_BASE
> +#define IRAM_SIZE			(SZ_128K + SZ_128K)
> +

Why is it here and not in Patch 2/20 ?

>  #define IOMUXC_PCR_MUX_ALT0		(0<<8)
>  #define IOMUXC_PCR_MUX_ALT1		(1<<8)
>  #define IOMUXC_PCR_MUX_ALT2		(2<<8)
> diff --git a/arch/arm/include/asm/arch-mx7ulp/sys_proto.h b/arch/arm/include/asm/arch-mx7ulp/sys_proto.h
> new file mode 100644
> index 0000000..d01748f
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mx7ulp/sys_proto.h
> @@ -0,0 +1,21 @@
> +/*
> + * Copyright (C) 2016 Freescale Semiconductor, Inc.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef _SYS_PROTO_MX7ULP_H_
> +#define _SYS_PROTO_MX7ULP_H_
> +
> +#include <asm/imx-common/sys_proto.h>
> +
> +#define BT0CFG_LPBOOT_MASK 0x1
> +#define BT0CFG_DUALBOOT_MASK 0x2
> +
> +enum bt_mode {
> +	LOW_POWER_BOOT,		/* LP_BT = 1 */
> +	DUAL_BOOT,		/* LP_BT = 0, DUAL_BT = 1 */
> +	SINGLE_BOOT		/* LP_BT = 0, DUAL_BT = 0 */
> +};
> +
> +#endif
> 

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================


More information about the U-Boot mailing list