18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2011 Calxeda, Inc. 48c2ecf20Sopenharmony_ci * Based on PPC version Copyright 2007 MontaVista Software, Inc. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#ifndef ASM_EDAC_H 78c2ecf20Sopenharmony_ci#define ASM_EDAC_H 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * ECC atomic, DMA, SMP and interrupt safe scrub function. 108c2ecf20Sopenharmony_ci * Implements the per arch edac_atomic_scrub() that EDAC use for software 118c2ecf20Sopenharmony_ci * ECC scrubbing. It reads memory and then writes back the original 128c2ecf20Sopenharmony_ci * value, allowing the hardware to detect and correct memory errors. 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic inline void edac_atomic_scrub(void *va, u32 size) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 188c2ecf20Sopenharmony_ci unsigned int *virt_addr = va; 198c2ecf20Sopenharmony_ci unsigned int temp, temp2; 208c2ecf20Sopenharmony_ci unsigned int i; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci for (i = 0; i < size / sizeof(*virt_addr); i++, virt_addr++) { 238c2ecf20Sopenharmony_ci /* Very carefully read and write to memory atomically 248c2ecf20Sopenharmony_ci * so we are interrupt, DMA and SMP safe. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci __asm__ __volatile__("\n" 278c2ecf20Sopenharmony_ci "1: ldrex %0, [%2]\n" 288c2ecf20Sopenharmony_ci " strex %1, %0, [%2]\n" 298c2ecf20Sopenharmony_ci " teq %1, #0\n" 308c2ecf20Sopenharmony_ci " bne 1b\n" 318c2ecf20Sopenharmony_ci : "=&r"(temp), "=&r"(temp2) 328c2ecf20Sopenharmony_ci : "r"(virt_addr) 338c2ecf20Sopenharmony_ci : "cc"); 348c2ecf20Sopenharmony_ci } 358c2ecf20Sopenharmony_ci#endif 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#endif 39