10044c42eSStefan Roese /* 20044c42eSStefan Roese * (C) Copyright 2010 30044c42eSStefan Roese * Heiko Schocher, DENX Software Engineering, hs@denx.de. 40044c42eSStefan Roese * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 60044c42eSStefan Roese */ 70044c42eSStefan Roese 80044c42eSStefan Roese #include <common.h> 90044c42eSStefan Roese #include <asm/io.h> 100044c42eSStefan Roese 110044c42eSStefan Roese DECLARE_GLOBAL_DATA_PTR; 120044c42eSStefan Roese 130044c42eSStefan Roese const ulong patterns[] = { 0x00000000, 140044c42eSStefan Roese 0xFFFFFFFF, 150044c42eSStefan Roese 0xFF00FF00, 160044c42eSStefan Roese 0x0F0F0F0F, 170044c42eSStefan Roese 0xF0F0F0F0}; 180044c42eSStefan Roese const ulong NBR_OF_PATTERNS = sizeof(patterns) / sizeof(*patterns); 190044c42eSStefan Roese const ulong OFFS_PATTERN = 3; 200044c42eSStefan Roese const ulong REPEAT_PATTERN = 1000; 210044c42eSStefan Roese 220044c42eSStefan Roese void bootcount_store(ulong a) 230044c42eSStefan Roese { 240044c42eSStefan Roese ulong *save_addr; 250044c42eSStefan Roese ulong size = 0; 260044c42eSStefan Roese int i; 270044c42eSStefan Roese 280044c42eSStefan Roese for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) 290044c42eSStefan Roese size += gd->bd->bi_dram[i].size; 300044c42eSStefan Roese save_addr = (ulong *)(size - BOOTCOUNT_ADDR); 310044c42eSStefan Roese writel(a, save_addr); 320044c42eSStefan Roese writel(BOOTCOUNT_MAGIC, &save_addr[1]); 330044c42eSStefan Roese 340044c42eSStefan Roese for (i = 0; i < REPEAT_PATTERN; i++) 350044c42eSStefan Roese writel(patterns[i % NBR_OF_PATTERNS], 360044c42eSStefan Roese &save_addr[i + OFFS_PATTERN]); 370044c42eSStefan Roese 38*20adda4cSStefan Roese /* Make sure the data is written to RAM */ 39*20adda4cSStefan Roese flush_dcache_range((ulong)&save_addr[0], 40*20adda4cSStefan Roese (ulong)&save_addr[REPEAT_PATTERN + OFFS_PATTERN]); 410044c42eSStefan Roese } 420044c42eSStefan Roese 430044c42eSStefan Roese ulong bootcount_load(void) 440044c42eSStefan Roese { 450044c42eSStefan Roese ulong *save_addr; 460044c42eSStefan Roese ulong size = 0; 470044c42eSStefan Roese ulong counter = 0; 480044c42eSStefan Roese int i, tmp; 490044c42eSStefan Roese 500044c42eSStefan Roese for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) 510044c42eSStefan Roese size += gd->bd->bi_dram[i].size; 520044c42eSStefan Roese save_addr = (ulong *)(size - BOOTCOUNT_ADDR); 530044c42eSStefan Roese 540044c42eSStefan Roese counter = readl(&save_addr[0]); 550044c42eSStefan Roese 560044c42eSStefan Roese /* Is the counter reliable, check in the big pattern for bit errors */ 570044c42eSStefan Roese for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) { 580044c42eSStefan Roese tmp = readl(&save_addr[i + OFFS_PATTERN]); 590044c42eSStefan Roese if (tmp != patterns[i % NBR_OF_PATTERNS]) 600044c42eSStefan Roese counter = 0; 610044c42eSStefan Roese } 620044c42eSStefan Roese return counter; 630044c42eSStefan Roese } 64