1 /*
2  * (C) Copyright 2010
3  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
16  * GNU General Public License for more details.
17  *
18  */
19 
20 #include <common.h>
21 #include <asm/io.h>
22 
23 DECLARE_GLOBAL_DATA_PTR;
24 
25 const ulong patterns[]      = {	0x00000000,
26 				0xFFFFFFFF,
27 				0xFF00FF00,
28 				0x0F0F0F0F,
29 				0xF0F0F0F0};
30 const ulong NBR_OF_PATTERNS = sizeof(patterns) / sizeof(*patterns);
31 const ulong OFFS_PATTERN    = 3;
32 const ulong REPEAT_PATTERN  = 1000;
33 
34 void bootcount_store(ulong a)
35 {
36 	ulong *save_addr;
37 	ulong size = 0;
38 	int i;
39 
40 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
41 		size += gd->bd->bi_dram[i].size;
42 	save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
43 	writel(a, save_addr);
44 	writel(BOOTCOUNT_MAGIC, &save_addr[1]);
45 
46 	for (i = 0; i < REPEAT_PATTERN; i++)
47 		writel(patterns[i % NBR_OF_PATTERNS],
48 			&save_addr[i + OFFS_PATTERN]);
49 
50 }
51 
52 ulong bootcount_load(void)
53 {
54 	ulong *save_addr;
55 	ulong size = 0;
56 	ulong counter = 0;
57 	int i, tmp;
58 
59 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
60 		size += gd->bd->bi_dram[i].size;
61 	save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
62 
63 	counter = readl(&save_addr[0]);
64 
65 	/* Is the counter reliable, check in the big pattern for bit errors */
66 	for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) {
67 		tmp = readl(&save_addr[i + OFFS_PATTERN]);
68 		if (tmp != patterns[i % NBR_OF_PATTERNS])
69 			counter = 0;
70 	}
71 	return counter;
72 }
73