diff options
Diffstat (limited to 'arch/arm/mach-stm32mp')
-rw-r--r-- | arch/arm/mach-stm32mp/bsec.c | 92 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cpu.c | 38 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/fdt.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/ddr.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/stm32.h | 9 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/sys_proto.h | 12 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/psci.c | 22 |
8 files changed, 236 insertions, 55 deletions
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c index a77c706a1a..3b923f088e 100644 --- a/arch/arm/mach-stm32mp/bsec.c +++ b/arch/arm/mach-stm32mp/bsec.c @@ -12,8 +12,6 @@ #include <linux/iopoll.h> #define BSEC_OTP_MAX_VALUE 95 - -#ifndef CONFIG_STM32MP1_TRUSTED #define BSEC_TIMEOUT_US 10000 /* BSEC REGISTER OFFSET (base relative) */ @@ -24,9 +22,10 @@ #define BSEC_OTP_LOCK_OFF 0x010 #define BSEC_DISTURBED_OFF 0x01C #define BSEC_ERROR_OFF 0x034 -#define BSEC_SPLOCK_OFF 0x064 /* Program safmem sticky lock */ -#define BSEC_SWLOCK_OFF 0x07C /* write in OTP sticky lock */ -#define BSEC_SRLOCK_OFF 0x094 /* shadowing sticky lock */ +#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */ +#define BSEC_SPLOCK_OFF 0x064 /* OTP write sticky lock */ +#define BSEC_SWLOCK_OFF 0x07C /* shadow write sticky lock */ +#define BSEC_SRLOCK_OFF 0x094 /* shadow read sticky lock */ #define BSEC_OTP_DATA_OFF 0x200 /* BSEC_CONFIGURATION Register MASK */ @@ -53,12 +52,12 @@ #define BSEC_LOCK_PROGRAM 0x04 /** - * bsec_check_error() - Check status of one otp - * @base: base address of bsec IP + * bsec_lock() - manage lock for each type SR/SP/SW + * @address: address of bsec IP register * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) - * Return: 0 if no error, -EAGAIN or -ENOTSUPP + * Return: true if locked else false */ -static u32 bsec_check_error(u32 base, u32 otp) +static bool bsec_read_lock(u32 address, u32 otp) { u32 bit; u32 bank; @@ -66,21 +65,17 @@ static u32 bsec_check_error(u32 base, u32 otp) bit = 1 << (otp & OTP_LOCK_MASK); bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); - if (readl(base + BSEC_DISTURBED_OFF + bank) & bit) - return -EAGAIN; - else if (readl(base + BSEC_ERROR_OFF + bank) & bit) - return -ENOTSUPP; - - return 0; + return !!(readl(address + bank) & bit); } +#ifndef CONFIG_STM32MP1_TRUSTED /** - * bsec_lock() - manage lock for each type SR/SP/SW - * @address: address of bsec IP register + * bsec_check_error() - Check status of one otp + * @base: base address of bsec IP * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) - * Return: true if locked else false + * Return: 0 if no error, -EAGAIN or -ENOTSUPP */ -static bool bsec_read_lock(u32 address, u32 otp) +static u32 bsec_check_error(u32 base, u32 otp) { u32 bit; u32 bank; @@ -88,7 +83,12 @@ static bool bsec_read_lock(u32 address, u32 otp) bit = 1 << (otp & OTP_LOCK_MASK); bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); - return !!(readl(address + bank) & bit); + if (readl(base + BSEC_DISTURBED_OFF + bank) & bit) + return -EAGAIN; + else if (readl(base + BSEC_ERROR_OFF + bank) & bit) + return -ENOTSUPP; + + return 0; } /** @@ -324,6 +324,16 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp) #endif } +static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp) +{ + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + + /* return OTP permanent write lock status */ + *val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp); + + return 0; +} + static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp) { #ifdef CONFIG_STM32MP1_TRUSTED @@ -350,22 +360,41 @@ static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp) #endif } +static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp) +{ +#ifdef CONFIG_STM32MP1_TRUSTED + if (val == 1) + return stm32_smc_exec(STM32_SMC_BSEC, + STM32_SMC_WRLOCK_OTP, + otp, 0); + if (val == 0) + return 0; /* nothing to do */ + + return -EINVAL; +#else + return -ENOTSUPP; +#endif +} + static int stm32mp_bsec_read(struct udevice *dev, int offset, void *buf, int size) { int ret; int i; - bool shadow = true; + bool shadow = true, lock = false; int nb_otp = size / sizeof(u32); int otp; unsigned int offs = offset; - if (offs >= STM32_BSEC_OTP_OFFSET) { + if (offs >= STM32_BSEC_LOCK_OFFSET) { + offs -= STM32_BSEC_LOCK_OFFSET; + lock = true; + } else if (offs >= STM32_BSEC_OTP_OFFSET) { offs -= STM32_BSEC_OTP_OFFSET; shadow = false; } - if (offs < 0 || (offs % 4) || (size % 4)) + if ((offs % 4) || (size % 4)) return -EINVAL; otp = offs / sizeof(u32); @@ -373,7 +402,9 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset, for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) { u32 *addr = &((u32 *)buf)[i - otp]; - if (shadow) + if (lock) + ret = stm32mp_bsec_read_lock(dev, addr, i); + else if (shadow) ret = stm32mp_bsec_read_shadow(dev, addr, i); else ret = stm32mp_bsec_read_otp(dev, addr, i); @@ -392,17 +423,20 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset, { int ret = 0; int i; - bool shadow = true; + bool shadow = true, lock = false; int nb_otp = size / sizeof(u32); int otp; unsigned int offs = offset; - if (offs >= STM32_BSEC_OTP_OFFSET) { + if (offs >= STM32_BSEC_LOCK_OFFSET) { + offs -= STM32_BSEC_LOCK_OFFSET; + lock = true; + } else if (offs >= STM32_BSEC_OTP_OFFSET) { offs -= STM32_BSEC_OTP_OFFSET; shadow = false; } - if (offs < 0 || (offs % 4) || (size % 4)) + if ((offs % 4) || (size % 4)) return -EINVAL; otp = offs / sizeof(u32); @@ -410,7 +444,9 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset, for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) { u32 *val = &((u32 *)buf)[i - otp]; - if (shadow) + if (lock) + ret = stm32mp_bsec_write_lock(dev, *val, i); + else if (shadow) ret = stm32mp_bsec_write_shadow(dev, *val, i); else ret = stm32mp_bsec_write_otp(dev, *val, i); diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index ea0bd94605..9aa5794334 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -61,12 +61,6 @@ #define BOOTROM_INSTANCE_MASK GENMASK(31, 16) #define BOOTROM_INSTANCE_SHIFT 16 -/* BSEC OTP index */ -#define BSEC_OTP_RPN 1 -#define BSEC_OTP_SERIAL 13 -#define BSEC_OTP_PKG 16 -#define BSEC_OTP_MAC 57 - /* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */ #define RPN_SHIFT 0 #define RPN_MASK GENMASK(7, 0) @@ -285,25 +279,42 @@ u32 get_cpu_package(void) return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK); } -#if defined(CONFIG_DISPLAY_CPUINFO) -int print_cpuinfo(void) +void get_soc_name(char name[SOC_NAME_SIZE]) { char *cpu_s, *cpu_r, *pkg; /* MPUs Part Numbers */ switch (get_cpu_type()) { + case CPU_STM32MP157Fxx: + cpu_s = "157F"; + break; + case CPU_STM32MP157Dxx: + cpu_s = "157D"; + break; case CPU_STM32MP157Cxx: cpu_s = "157C"; break; case CPU_STM32MP157Axx: cpu_s = "157A"; break; + case CPU_STM32MP153Fxx: + cpu_s = "153F"; + break; + case CPU_STM32MP153Dxx: + cpu_s = "153D"; + break; case CPU_STM32MP153Cxx: cpu_s = "153C"; break; case CPU_STM32MP153Axx: cpu_s = "153A"; break; + case CPU_STM32MP151Fxx: + cpu_s = "151F"; + break; + case CPU_STM32MP151Dxx: + cpu_s = "151D"; + break; case CPU_STM32MP151Cxx: cpu_s = "151C"; break; @@ -350,7 +361,16 @@ int print_cpuinfo(void) break; } - printf("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r); + snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char name[SOC_NAME_SIZE]; + + get_soc_name(name); + printf("CPU: %s\n", name); return 0; } diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c index 82c430b7c7..3ee7d6a833 100644 --- a/arch/arm/mach-stm32mp/fdt.c +++ b/arch/arm/mach-stm32mp/fdt.c @@ -23,6 +23,12 @@ #define ETZPC_RESERVED 0xffffffff +#define STM32_FDCAN_BASE 0x4400e000 +#define STM32_CRYP2_BASE 0x4c005000 +#define STM32_CRYP1_BASE 0x54001000 +#define STM32_GPU_BASE 0x59000000 +#define STM32_DSI_BASE 0x5a000000 + static const u32 stm32mp1_ip_addr[] = { 0x5c008000, /* 00 stgenc */ 0x54000000, /* 01 bkpsram */ @@ -33,7 +39,7 @@ static const u32 stm32mp1_ip_addr[] = { ETZPC_RESERVED, /* 06 reserved */ 0x54003000, /* 07 rng1 */ 0x54002000, /* 08 hash1 */ - 0x54001000, /* 09 cryp1 */ + STM32_CRYP1_BASE, /* 09 cryp1 */ 0x5a003000, /* 0A ddrctrl */ 0x5a004000, /* 0B ddrphyc */ 0x5c009000, /* 0C i2c6 */ @@ -86,7 +92,7 @@ static const u32 stm32mp1_ip_addr[] = { 0x4400b000, /* 3B sai2 */ 0x4400c000, /* 3C sai3 */ 0x4400d000, /* 3D dfsdm */ - 0x4400e000, /* 3E tt_fdcan */ + STM32_FDCAN_BASE, /* 3E tt_fdcan */ ETZPC_RESERVED, /* 3F reserved */ 0x50021000, /* 40 lptim2 */ 0x50022000, /* 41 lptim3 */ @@ -99,7 +105,7 @@ static const u32 stm32mp1_ip_addr[] = { 0x48003000, /* 48 adc */ 0x4c002000, /* 49 hash2 */ 0x4c003000, /* 4A rng2 */ - 0x4c005000, /* 4B cryp2 */ + STM32_CRYP2_BASE, /* 4B cryp2 */ ETZPC_RESERVED, /* 4C reserved */ ETZPC_RESERVED, /* 4D reserved */ ETZPC_RESERVED, /* 4E reserved */ @@ -126,11 +132,13 @@ static const u32 stm32mp1_ip_addr[] = { static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr) { int node; + fdt_addr_t regs; for (node = fdt_first_subnode(fdt, offset); node >= 0; node = fdt_next_subnode(fdt, node)) { - if (addr == (u32)fdt_getprop(fdt, node, "reg", 0)) { + regs = fdtdec_get_addr(fdt, node, "reg"); + if (addr == regs) { if (fdtdec_get_is_enabled(fdt, node)) { fdt_status_disabled(fdt, node); @@ -143,11 +151,11 @@ static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr) return false; } -static int stm32_fdt_fixup_etzpc(void *fdt) +static int stm32_fdt_fixup_etzpc(void *fdt, int soc_node) { const u32 *array; int array_size, i; - int soc_node, offset, shift; + int offset, shift; u32 addr, status, decprot[ETZPC_DECPROT_NB]; array = stm32mp1_ip_addr; @@ -156,10 +164,6 @@ static int stm32_fdt_fixup_etzpc(void *fdt) for (i = 0; i < ETZPC_DECPROT_NB; i++) decprot[i] = readl(ETZPC_DECPROT(i)); - soc_node = fdt_path_offset(fdt, "/soc"); - if (soc_node < 0) - return soc_node; - for (i = 0; i < array_size; i++) { offset = i / NB_PROT_PER_REG; shift = (i % NB_PROT_PER_REG) * DECPROT_NB_BITS; @@ -180,6 +184,40 @@ static int stm32_fdt_fixup_etzpc(void *fdt) return 0; } +/* deactivate all the cpu except core 0 */ +static void stm32_fdt_fixup_cpu(void *blob, char *name) +{ + int off; + u32 reg; + + off = fdt_path_offset(blob, "/cpus"); + if (off < 0) { + printf("%s: couldn't find /cpus node\n", __func__); + return; + } + + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); + while (off != -FDT_ERR_NOTFOUND) { + reg = fdtdec_get_addr(blob, off, "reg"); + if (reg != 0) { + fdt_del_node(blob, off); + printf("FDT: cpu %d node remove for %s\n", reg, name); + /* after delete we can't trust the offsets anymore */ + off = -1; + } + off = fdt_node_offset_by_prop_value(blob, off, + "device_type", "cpu", 4); + } +} + +static void stm32_fdt_disable(void *fdt, int offset, u32 addr, + const char *string, const char *name) +{ + if (fdt_disable_subnode_by_address(fdt, offset, addr)) + printf("FDT: %s@%08x node disabled for %s\n", + string, addr, name); +} + /* * This function is called right before the kernel is booted. "blob" is the * device tree that will be passed to the kernel. @@ -187,14 +225,59 @@ static int stm32_fdt_fixup_etzpc(void *fdt) int ft_system_setup(void *blob, bd_t *bd) { int ret = 0; - u32 pkg; + int soc; + u32 pkg, cpu; + char name[SOC_NAME_SIZE]; + + soc = fdt_path_offset(blob, "/soc"); + if (soc < 0) + return soc; if (CONFIG_IS_ENABLED(STM32_ETZPC)) { - ret = stm32_fdt_fixup_etzpc(blob); + ret = stm32_fdt_fixup_etzpc(blob, soc); if (ret) return ret; } + /* MPUs Part Numbers and name*/ + cpu = get_cpu_type(); + get_soc_name(name); + + switch (cpu) { + case CPU_STM32MP151Fxx: + case CPU_STM32MP151Dxx: + case CPU_STM32MP151Cxx: + case CPU_STM32MP151Axx: + stm32_fdt_fixup_cpu(blob, name); + /* after cpu delete we can't trust the soc offsets anymore */ + soc = fdt_path_offset(blob, "/soc"); + stm32_fdt_disable(blob, soc, STM32_FDCAN_BASE, "can", name); + /* fall through */ + case CPU_STM32MP153Fxx: + case CPU_STM32MP153Dxx: + case CPU_STM32MP153Cxx: + case CPU_STM32MP153Axx: + stm32_fdt_disable(blob, soc, STM32_GPU_BASE, "gpu", name); + stm32_fdt_disable(blob, soc, STM32_DSI_BASE, "dsi", name); + break; + default: + break; + } + + switch (cpu) { + case CPU_STM32MP157Dxx: + case CPU_STM32MP157Axx: + case CPU_STM32MP153Dxx: + case CPU_STM32MP153Axx: + case CPU_STM32MP151Dxx: + case CPU_STM32MP151Axx: + stm32_fdt_disable(blob, soc, STM32_CRYP1_BASE, "cryp", name); + stm32_fdt_disable(blob, soc, STM32_CRYP2_BASE, "cryp", name); + break; + default: + break; + } + switch (get_cpu_package()) { case PKG_AA_LBGA448: pkg = STM32MP_PKG_AA; diff --git a/arch/arm/mach-stm32mp/include/mach/ddr.h b/arch/arm/mach-stm32mp/include/mach/ddr.h index b8a17cfbdd..bfc42a7c48 100644 --- a/arch/arm/mach-stm32mp/include/mach/ddr.h +++ b/arch/arm/mach-stm32mp/include/mach/ddr.h @@ -9,8 +9,10 @@ /* DDR power initializations */ enum ddr_type { STM32MP_DDR3, - STM32MP_LPDDR2, - STM32MP_LPDDR3, + STM32MP_LPDDR2_16, + STM32MP_LPDDR2_32, + STM32MP_LPDDR3_16, + STM32MP_LPDDR3_32, }; int board_ddr_power_init(enum ddr_type ddr_type); diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index f0636005e5..6daf9f7121 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -119,7 +119,14 @@ enum forced_boot_mode { #define STM32_BSEC_SHADOW(id) (STM32_BSEC_SHADOW_OFFSET + (id) * 4) #define STM32_BSEC_OTP_OFFSET 0x80000000 #define STM32_BSEC_OTP(id) (STM32_BSEC_OTP_OFFSET + (id) * 4) - +#define STM32_BSEC_LOCK_OFFSET 0xC0000000 +#define STM32_BSEC_LOCK(id) (STM32_BSEC_LOCK_OFFSET + (id) * 4) + +/* BSEC OTP index */ +#define BSEC_OTP_RPN 1 +#define BSEC_OTP_SERIAL 13 +#define BSEC_OTP_PKG 16 +#define BSEC_OTP_MAC 57 #define BSEC_OTP_BOARD 59 #endif /* __ASSEMBLY__*/ diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h index 8130546b27..4ad14f963b 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h @@ -27,6 +27,7 @@ #define STM32_SMC_READ_OTP 0x04 #define STM32_SMC_READ_ALL 0x05 #define STM32_SMC_WRITE_ALL 0x06 +#define STM32_SMC_WRLOCK_OTP 0x07 /* SMC error codes */ #define STM32_SMC_OK 0x0 @@ -45,8 +46,8 @@ static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result) arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res); if (res.a0) { - pr_err("%s: Failed to exec in secure mode (err = %ld)\n", - __func__, res.a0); + pr_err("%s: Failed to exec svc=%x op=%x in secure mode (err = %ld)\n", + __func__, svc, op, res.a0); return -EINVAL; } if (result) diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h index da46c11573..1617126bea 100644 --- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h +++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h @@ -3,13 +3,19 @@ * Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved */ -/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0)*/ +/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit7:0) */ #define CPU_STM32MP157Cxx 0x05000000 #define CPU_STM32MP157Axx 0x05000001 #define CPU_STM32MP153Cxx 0x05000024 #define CPU_STM32MP153Axx 0x05000025 #define CPU_STM32MP151Cxx 0x0500002E #define CPU_STM32MP151Axx 0x0500002F +#define CPU_STM32MP157Fxx 0x05000080 +#define CPU_STM32MP157Dxx 0x05000081 +#define CPU_STM32MP153Fxx 0x050000A4 +#define CPU_STM32MP153Dxx 0x050000A5 +#define CPU_STM32MP151Fxx 0x050000AE +#define CPU_STM32MP151Dxx 0x050000AF /* return CPU_STMP32MP...Xxx constants */ u32 get_cpu_type(void); @@ -29,6 +35,10 @@ u32 get_cpu_package(void); #define PKG_AC_TFBGA361 2 #define PKG_AD_TFBGA257 1 +/* Get SOC name */ +#define SOC_NAME_SIZE 20 +void get_soc_name(char name[SOC_NAME_SIZE]); + /* return boot mode */ u32 get_bootmode(void); diff --git a/arch/arm/mach-stm32mp/psci.c b/arch/arm/mach-stm32mp/psci.c index 1d91b2d324..3fb038d3e7 100644 --- a/arch/arm/mach-stm32mp/psci.c +++ b/arch/arm/mach-stm32mp/psci.c @@ -30,6 +30,22 @@ u8 psci_state[STM32MP1_PSCI_NR_CPUS] __secure_data = { PSCI_AFFINITY_LEVEL_ON, PSCI_AFFINITY_LEVEL_OFF}; +static u32 __secure_data cntfrq; + +static u32 __secure cp15_read_cntfrq(void) +{ + u32 frq; + + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq)); + + return frq; +} + +static void __secure cp15_write_cntfrq(u32 frq) +{ + asm volatile ("mcr p15, 0, %0, c14, c0, 0" : : "r" (frq)); +} + static inline void psci_set_state(int cpu, u8 state) { psci_state[cpu] = state; @@ -63,6 +79,9 @@ void __secure psci_arch_cpu_entry(void) psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON); + /* write the saved cntfrq */ + cp15_write_cntfrq(cntfrq); + /* reset magic in TAMP register */ writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER); } @@ -130,6 +149,9 @@ s32 __secure psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc, if (psci_state[cpu] == PSCI_AFFINITY_LEVEL_ON) return ARM_PSCI_RET_ALREADY_ON; + /* read and save cntfrq of current cpu to write on target cpu */ + cntfrq = cp15_read_cntfrq(); + /* reset magic in TAMP register */ if (readl(TAMP_BACKUP_MAGIC_NUMBER)) writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER); |