1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 20044c42eSStefan Roese /* 30044c42eSStefan Roese * (C) Copyright 2010 40044c42eSStefan Roese * Heiko Schocher, DENX Software Engineering, hs@denx.de. 50044c42eSStefan Roese */ 60044c42eSStefan Roese 70044c42eSStefan Roese #include <common.h> 80044c42eSStefan Roese #include <asm/io.h> 90044c42eSStefan Roese 100044c42eSStefan Roese DECLARE_GLOBAL_DATA_PTR; 110044c42eSStefan Roese 120044c42eSStefan Roese const ulong patterns[] = { 0x00000000, 130044c42eSStefan Roese 0xFFFFFFFF, 140044c42eSStefan Roese 0xFF00FF00, 150044c42eSStefan Roese 0x0F0F0F0F, 160044c42eSStefan Roese 0xF0F0F0F0}; 170044c42eSStefan Roese const ulong NBR_OF_PATTERNS = sizeof(patterns) / sizeof(*patterns); 180044c42eSStefan Roese const ulong OFFS_PATTERN = 3; 190044c42eSStefan Roese const ulong REPEAT_PATTERN = 1000; 200044c42eSStefan Roese 210044c42eSStefan Roese void bootcount_store(ulong a) 220044c42eSStefan Roese { 230044c42eSStefan Roese ulong *save_addr; 240044c42eSStefan Roese ulong size = 0; 250044c42eSStefan Roese int i; 260044c42eSStefan Roese 270044c42eSStefan Roese for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) 280044c42eSStefan Roese size += gd->bd->bi_dram[i].size; 290044c42eSStefan Roese save_addr = (ulong *)(size - BOOTCOUNT_ADDR); 300044c42eSStefan Roese writel(a, save_addr); 310044c42eSStefan Roese writel(BOOTCOUNT_MAGIC, &save_addr[1]); 320044c42eSStefan Roese 330044c42eSStefan Roese for (i = 0; i < REPEAT_PATTERN; i++) 340044c42eSStefan Roese writel(patterns[i % NBR_OF_PATTERNS], 350044c42eSStefan Roese &save_addr[i + OFFS_PATTERN]); 360044c42eSStefan Roese 3720adda4cSStefan Roese /* Make sure the data is written to RAM */ 3820adda4cSStefan Roese flush_dcache_range((ulong)&save_addr[0], 39384b1d50SStefan Roese (((ulong)&save_addr[REPEAT_PATTERN + OFFS_PATTERN] & 40384b1d50SStefan Roese ~(ARCH_DMA_MINALIGN - 1)) + ARCH_DMA_MINALIGN)); 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