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 } 42 43 ulong bootcount_load(void) 44 { 45 ulong *save_addr; 46 ulong size = 0; 47 ulong counter = 0; 48 int i, tmp; 49 50 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) 51 size += gd->bd->bi_dram[i].size; 52 save_addr = (ulong *)(size - BOOTCOUNT_ADDR); 53 54 counter = readl(&save_addr[0]); 55 56 /* Is the counter reliable, check in the big pattern for bit errors */ 57 for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) { 58 tmp = readl(&save_addr[i + OFFS_PATTERN]); 59 if (tmp != patterns[i % NBR_OF_PATTERNS]) 60 counter = 0; 61 } 62 return counter; 63 } 64