18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#ifndef __ASM_CSKY_ATOMIC_H 48c2ecf20Sopenharmony_ci#define __ASM_CSKY_ATOMIC_H 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/version.h> 78c2ecf20Sopenharmony_ci#include <asm/cmpxchg.h> 88c2ecf20Sopenharmony_ci#include <asm/barrier.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_HAS_LDSTEX 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define __atomic_add_unless __atomic_add_unless 138c2ecf20Sopenharmony_cistatic inline int __atomic_add_unless(atomic_t *v, int a, int u) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci unsigned long tmp, ret; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci smp_mb(); 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci asm volatile ( 208c2ecf20Sopenharmony_ci "1: ldex.w %0, (%3) \n" 218c2ecf20Sopenharmony_ci " mov %1, %0 \n" 228c2ecf20Sopenharmony_ci " cmpne %0, %4 \n" 238c2ecf20Sopenharmony_ci " bf 2f \n" 248c2ecf20Sopenharmony_ci " add %0, %2 \n" 258c2ecf20Sopenharmony_ci " stex.w %0, (%3) \n" 268c2ecf20Sopenharmony_ci " bez %0, 1b \n" 278c2ecf20Sopenharmony_ci "2: \n" 288c2ecf20Sopenharmony_ci : "=&r" (tmp), "=&r" (ret) 298c2ecf20Sopenharmony_ci : "r" (a), "r"(&v->counter), "r"(u) 308c2ecf20Sopenharmony_ci : "memory"); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci if (ret != u) 338c2ecf20Sopenharmony_ci smp_mb(); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci return ret; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define ATOMIC_OP(op, c_op) \ 398c2ecf20Sopenharmony_cistatic inline void atomic_##op(int i, atomic_t *v) \ 408c2ecf20Sopenharmony_ci{ \ 418c2ecf20Sopenharmony_ci unsigned long tmp; \ 428c2ecf20Sopenharmony_ci \ 438c2ecf20Sopenharmony_ci asm volatile ( \ 448c2ecf20Sopenharmony_ci "1: ldex.w %0, (%2) \n" \ 458c2ecf20Sopenharmony_ci " " #op " %0, %1 \n" \ 468c2ecf20Sopenharmony_ci " stex.w %0, (%2) \n" \ 478c2ecf20Sopenharmony_ci " bez %0, 1b \n" \ 488c2ecf20Sopenharmony_ci : "=&r" (tmp) \ 498c2ecf20Sopenharmony_ci : "r" (i), "r"(&v->counter) \ 508c2ecf20Sopenharmony_ci : "memory"); \ 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define ATOMIC_OP_RETURN(op, c_op) \ 548c2ecf20Sopenharmony_cistatic inline int atomic_##op##_return(int i, atomic_t *v) \ 558c2ecf20Sopenharmony_ci{ \ 568c2ecf20Sopenharmony_ci unsigned long tmp, ret; \ 578c2ecf20Sopenharmony_ci \ 588c2ecf20Sopenharmony_ci smp_mb(); \ 598c2ecf20Sopenharmony_ci asm volatile ( \ 608c2ecf20Sopenharmony_ci "1: ldex.w %0, (%3) \n" \ 618c2ecf20Sopenharmony_ci " " #op " %0, %2 \n" \ 628c2ecf20Sopenharmony_ci " mov %1, %0 \n" \ 638c2ecf20Sopenharmony_ci " stex.w %0, (%3) \n" \ 648c2ecf20Sopenharmony_ci " bez %0, 1b \n" \ 658c2ecf20Sopenharmony_ci : "=&r" (tmp), "=&r" (ret) \ 668c2ecf20Sopenharmony_ci : "r" (i), "r"(&v->counter) \ 678c2ecf20Sopenharmony_ci : "memory"); \ 688c2ecf20Sopenharmony_ci smp_mb(); \ 698c2ecf20Sopenharmony_ci \ 708c2ecf20Sopenharmony_ci return ret; \ 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define ATOMIC_FETCH_OP(op, c_op) \ 748c2ecf20Sopenharmony_cistatic inline int atomic_fetch_##op(int i, atomic_t *v) \ 758c2ecf20Sopenharmony_ci{ \ 768c2ecf20Sopenharmony_ci unsigned long tmp, ret; \ 778c2ecf20Sopenharmony_ci \ 788c2ecf20Sopenharmony_ci smp_mb(); \ 798c2ecf20Sopenharmony_ci asm volatile ( \ 808c2ecf20Sopenharmony_ci "1: ldex.w %0, (%3) \n" \ 818c2ecf20Sopenharmony_ci " mov %1, %0 \n" \ 828c2ecf20Sopenharmony_ci " " #op " %0, %2 \n" \ 838c2ecf20Sopenharmony_ci " stex.w %0, (%3) \n" \ 848c2ecf20Sopenharmony_ci " bez %0, 1b \n" \ 858c2ecf20Sopenharmony_ci : "=&r" (tmp), "=&r" (ret) \ 868c2ecf20Sopenharmony_ci : "r" (i), "r"(&v->counter) \ 878c2ecf20Sopenharmony_ci : "memory"); \ 888c2ecf20Sopenharmony_ci smp_mb(); \ 898c2ecf20Sopenharmony_ci \ 908c2ecf20Sopenharmony_ci return ret; \ 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#else /* CONFIG_CPU_HAS_LDSTEX */ 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#include <linux/irqflags.h> 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#define __atomic_add_unless __atomic_add_unless 988c2ecf20Sopenharmony_cistatic inline int __atomic_add_unless(atomic_t *v, int a, int u) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci unsigned long tmp, ret, flags; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci raw_local_irq_save(flags); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci asm volatile ( 1058c2ecf20Sopenharmony_ci " ldw %0, (%3) \n" 1068c2ecf20Sopenharmony_ci " mov %1, %0 \n" 1078c2ecf20Sopenharmony_ci " cmpne %0, %4 \n" 1088c2ecf20Sopenharmony_ci " bf 2f \n" 1098c2ecf20Sopenharmony_ci " add %0, %2 \n" 1108c2ecf20Sopenharmony_ci " stw %0, (%3) \n" 1118c2ecf20Sopenharmony_ci "2: \n" 1128c2ecf20Sopenharmony_ci : "=&r" (tmp), "=&r" (ret) 1138c2ecf20Sopenharmony_ci : "r" (a), "r"(&v->counter), "r"(u) 1148c2ecf20Sopenharmony_ci : "memory"); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return ret; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci#define ATOMIC_OP(op, c_op) \ 1228c2ecf20Sopenharmony_cistatic inline void atomic_##op(int i, atomic_t *v) \ 1238c2ecf20Sopenharmony_ci{ \ 1248c2ecf20Sopenharmony_ci unsigned long tmp, flags; \ 1258c2ecf20Sopenharmony_ci \ 1268c2ecf20Sopenharmony_ci raw_local_irq_save(flags); \ 1278c2ecf20Sopenharmony_ci \ 1288c2ecf20Sopenharmony_ci asm volatile ( \ 1298c2ecf20Sopenharmony_ci " ldw %0, (%2) \n" \ 1308c2ecf20Sopenharmony_ci " " #op " %0, %1 \n" \ 1318c2ecf20Sopenharmony_ci " stw %0, (%2) \n" \ 1328c2ecf20Sopenharmony_ci : "=&r" (tmp) \ 1338c2ecf20Sopenharmony_ci : "r" (i), "r"(&v->counter) \ 1348c2ecf20Sopenharmony_ci : "memory"); \ 1358c2ecf20Sopenharmony_ci \ 1368c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); \ 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci#define ATOMIC_OP_RETURN(op, c_op) \ 1408c2ecf20Sopenharmony_cistatic inline int atomic_##op##_return(int i, atomic_t *v) \ 1418c2ecf20Sopenharmony_ci{ \ 1428c2ecf20Sopenharmony_ci unsigned long tmp, ret, flags; \ 1438c2ecf20Sopenharmony_ci \ 1448c2ecf20Sopenharmony_ci raw_local_irq_save(flags); \ 1458c2ecf20Sopenharmony_ci \ 1468c2ecf20Sopenharmony_ci asm volatile ( \ 1478c2ecf20Sopenharmony_ci " ldw %0, (%3) \n" \ 1488c2ecf20Sopenharmony_ci " " #op " %0, %2 \n" \ 1498c2ecf20Sopenharmony_ci " stw %0, (%3) \n" \ 1508c2ecf20Sopenharmony_ci " mov %1, %0 \n" \ 1518c2ecf20Sopenharmony_ci : "=&r" (tmp), "=&r" (ret) \ 1528c2ecf20Sopenharmony_ci : "r" (i), "r"(&v->counter) \ 1538c2ecf20Sopenharmony_ci : "memory"); \ 1548c2ecf20Sopenharmony_ci \ 1558c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); \ 1568c2ecf20Sopenharmony_ci \ 1578c2ecf20Sopenharmony_ci return ret; \ 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci#define ATOMIC_FETCH_OP(op, c_op) \ 1618c2ecf20Sopenharmony_cistatic inline int atomic_fetch_##op(int i, atomic_t *v) \ 1628c2ecf20Sopenharmony_ci{ \ 1638c2ecf20Sopenharmony_ci unsigned long tmp, ret, flags; \ 1648c2ecf20Sopenharmony_ci \ 1658c2ecf20Sopenharmony_ci raw_local_irq_save(flags); \ 1668c2ecf20Sopenharmony_ci \ 1678c2ecf20Sopenharmony_ci asm volatile ( \ 1688c2ecf20Sopenharmony_ci " ldw %0, (%3) \n" \ 1698c2ecf20Sopenharmony_ci " mov %1, %0 \n" \ 1708c2ecf20Sopenharmony_ci " " #op " %0, %2 \n" \ 1718c2ecf20Sopenharmony_ci " stw %0, (%3) \n" \ 1728c2ecf20Sopenharmony_ci : "=&r" (tmp), "=&r" (ret) \ 1738c2ecf20Sopenharmony_ci : "r" (i), "r"(&v->counter) \ 1748c2ecf20Sopenharmony_ci : "memory"); \ 1758c2ecf20Sopenharmony_ci \ 1768c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); \ 1778c2ecf20Sopenharmony_ci \ 1788c2ecf20Sopenharmony_ci return ret; \ 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci#endif /* CONFIG_CPU_HAS_LDSTEX */ 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci#define atomic_add_return atomic_add_return 1848c2ecf20Sopenharmony_ciATOMIC_OP_RETURN(add, +) 1858c2ecf20Sopenharmony_ci#define atomic_sub_return atomic_sub_return 1868c2ecf20Sopenharmony_ciATOMIC_OP_RETURN(sub, -) 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci#define atomic_fetch_add atomic_fetch_add 1898c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(add, +) 1908c2ecf20Sopenharmony_ci#define atomic_fetch_sub atomic_fetch_sub 1918c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(sub, -) 1928c2ecf20Sopenharmony_ci#define atomic_fetch_and atomic_fetch_and 1938c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(and, &) 1948c2ecf20Sopenharmony_ci#define atomic_fetch_or atomic_fetch_or 1958c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(or, |) 1968c2ecf20Sopenharmony_ci#define atomic_fetch_xor atomic_fetch_xor 1978c2ecf20Sopenharmony_ciATOMIC_FETCH_OP(xor, ^) 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#define atomic_and atomic_and 2008c2ecf20Sopenharmony_ciATOMIC_OP(and, &) 2018c2ecf20Sopenharmony_ci#define atomic_or atomic_or 2028c2ecf20Sopenharmony_ciATOMIC_OP(or, |) 2038c2ecf20Sopenharmony_ci#define atomic_xor atomic_xor 2048c2ecf20Sopenharmony_ciATOMIC_OP(xor, ^) 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci#undef ATOMIC_FETCH_OP 2078c2ecf20Sopenharmony_ci#undef ATOMIC_OP_RETURN 2088c2ecf20Sopenharmony_ci#undef ATOMIC_OP 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci#include <asm-generic/atomic.h> 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci#endif /* __ASM_CSKY_ATOMIC_H */ 213