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