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