1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2010 4 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 5 */ 6 7#include <common.h> 8#include <cpu_func.h> 9#include <asm/cache.h> 10#include <asm/global_data.h> 11#include <asm/io.h> 12 13DECLARE_GLOBAL_DATA_PTR; 14 15const ulong patterns[] = { 0x00000000, 16 0xFFFFFFFF, 17 0xFF00FF00, 18 0x0F0F0F0F, 19 0xF0F0F0F0}; 20const ulong NBR_OF_PATTERNS = sizeof(patterns) / sizeof(*patterns); 21const ulong OFFS_PATTERN = 3; 22const ulong REPEAT_PATTERN = 1000; 23 24void bootcount_store(ulong a) 25{ 26 ulong *save_addr; 27 ulong size = 0; 28 int i; 29 30 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) 31 size += gd->bd->bi_dram[i].size; 32 save_addr = (ulong *)(size - BOOTCOUNT_ADDR); 33 writel(a, save_addr); 34 writel(CONFIG_SYS_BOOTCOUNT_MAGIC, &save_addr[1]); 35 36 for (i = 0; i < REPEAT_PATTERN; i++) 37 writel(patterns[i % NBR_OF_PATTERNS], 38 &save_addr[i + OFFS_PATTERN]); 39 40 /* Make sure the data is written to RAM */ 41 flush_dcache_range((ulong)&save_addr[0], 42 (((ulong)&save_addr[REPEAT_PATTERN + OFFS_PATTERN] & 43 ~(ARCH_DMA_MINALIGN - 1)) + ARCH_DMA_MINALIGN)); 44} 45 46ulong bootcount_load(void) 47{ 48 ulong *save_addr; 49 ulong size = 0; 50 ulong counter = 0; 51 int i, tmp; 52 53 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) 54 size += gd->bd->bi_dram[i].size; 55 save_addr = (ulong *)(size - BOOTCOUNT_ADDR); 56 57 counter = readl(&save_addr[0]); 58 59 /* Is the counter reliable, check in the big pattern for bit errors */ 60 for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) { 61 tmp = readl(&save_addr[i + OFFS_PATTERN]); 62 if (tmp != patterns[i % NBR_OF_PATTERNS]) 63 counter = 0; 64 } 65 return counter; 66} 67