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 <asm/io.h> 9 10 DECLARE_GLOBAL_DATA_PTR; 11 12 const ulong patterns[] = { 0x00000000, 13 0xFFFFFFFF, 14 0xFF00FF00, 15 0x0F0F0F0F, 16 0xF0F0F0F0}; 17 const ulong NBR_OF_PATTERNS = sizeof(patterns) / sizeof(*patterns); 18 const ulong OFFS_PATTERN = 3; 19 const ulong REPEAT_PATTERN = 1000; 20 21 void bootcount_store(ulong a) 22 { 23 ulong *save_addr; 24 ulong size = 0; 25 int i; 26 27 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) 28 size += gd->bd->bi_dram[i].size; 29 save_addr = (ulong *)(size - BOOTCOUNT_ADDR); 30 writel(a, save_addr); 31 writel(BOOTCOUNT_MAGIC, &save_addr[1]); 32 33 for (i = 0; i < REPEAT_PATTERN; i++) 34 writel(patterns[i % NBR_OF_PATTERNS], 35 &save_addr[i + OFFS_PATTERN]); 36 37 /* Make sure the data is written to RAM */ 38 flush_dcache_range((ulong)&save_addr[0], 39 (((ulong)&save_addr[REPEAT_PATTERN + OFFS_PATTERN] & 40 ~(ARCH_DMA_MINALIGN - 1)) + ARCH_DMA_MINALIGN)); 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