]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/bootcount/bootcount_ram.c
8655af7eab07bd377308477c379ef04b9636c25b
[people/ms/u-boot.git] / drivers / bootcount / bootcount_ram.c
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 }