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