162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __ASM_SH_BITOPS_LLSC_H
362306a36Sopenharmony_ci#define __ASM_SH_BITOPS_LLSC_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_cistatic inline void set_bit(int nr, volatile void *addr)
662306a36Sopenharmony_ci{
762306a36Sopenharmony_ci	int	mask;
862306a36Sopenharmony_ci	volatile unsigned int *a = addr;
962306a36Sopenharmony_ci	unsigned long tmp;
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci	a += nr >> 5;
1262306a36Sopenharmony_ci	mask = 1 << (nr & 0x1f);
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci	__asm__ __volatile__ (
1562306a36Sopenharmony_ci		"1:						\n\t"
1662306a36Sopenharmony_ci		"movli.l	@%1, %0	! set_bit		\n\t"
1762306a36Sopenharmony_ci		"or		%2, %0				\n\t"
1862306a36Sopenharmony_ci		"movco.l	%0, @%1				\n\t"
1962306a36Sopenharmony_ci		"bf		1b				\n\t"
2062306a36Sopenharmony_ci		: "=&z" (tmp)
2162306a36Sopenharmony_ci		: "r" (a), "r" (mask)
2262306a36Sopenharmony_ci		: "t", "memory"
2362306a36Sopenharmony_ci	);
2462306a36Sopenharmony_ci}
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic inline void clear_bit(int nr, volatile void *addr)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	int	mask;
2962306a36Sopenharmony_ci	volatile unsigned int *a = addr;
3062306a36Sopenharmony_ci	unsigned long tmp;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	a += nr >> 5;
3362306a36Sopenharmony_ci	mask = 1 << (nr & 0x1f);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	__asm__ __volatile__ (
3662306a36Sopenharmony_ci		"1:						\n\t"
3762306a36Sopenharmony_ci		"movli.l	@%1, %0	! clear_bit		\n\t"
3862306a36Sopenharmony_ci		"and		%2, %0				\n\t"
3962306a36Sopenharmony_ci		"movco.l	%0, @%1				\n\t"
4062306a36Sopenharmony_ci		"bf		1b				\n\t"
4162306a36Sopenharmony_ci		: "=&z" (tmp)
4262306a36Sopenharmony_ci		: "r" (a), "r" (~mask)
4362306a36Sopenharmony_ci		: "t", "memory"
4462306a36Sopenharmony_ci	);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic inline void change_bit(int nr, volatile void *addr)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	int	mask;
5062306a36Sopenharmony_ci	volatile unsigned int *a = addr;
5162306a36Sopenharmony_ci	unsigned long tmp;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	a += nr >> 5;
5462306a36Sopenharmony_ci	mask = 1 << (nr & 0x1f);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	__asm__ __volatile__ (
5762306a36Sopenharmony_ci		"1:						\n\t"
5862306a36Sopenharmony_ci		"movli.l	@%1, %0	! change_bit		\n\t"
5962306a36Sopenharmony_ci		"xor		%2, %0				\n\t"
6062306a36Sopenharmony_ci		"movco.l	%0, @%1				\n\t"
6162306a36Sopenharmony_ci		"bf		1b				\n\t"
6262306a36Sopenharmony_ci		: "=&z" (tmp)
6362306a36Sopenharmony_ci		: "r" (a), "r" (mask)
6462306a36Sopenharmony_ci		: "t", "memory"
6562306a36Sopenharmony_ci	);
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic inline int test_and_set_bit(int nr, volatile void *addr)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	int	mask, retval;
7162306a36Sopenharmony_ci	volatile unsigned int *a = addr;
7262306a36Sopenharmony_ci	unsigned long tmp;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	a += nr >> 5;
7562306a36Sopenharmony_ci	mask = 1 << (nr & 0x1f);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	__asm__ __volatile__ (
7862306a36Sopenharmony_ci		"1:						\n\t"
7962306a36Sopenharmony_ci		"movli.l	@%2, %0	! test_and_set_bit	\n\t"
8062306a36Sopenharmony_ci		"mov		%0, %1				\n\t"
8162306a36Sopenharmony_ci		"or		%3, %0				\n\t"
8262306a36Sopenharmony_ci		"movco.l	%0, @%2				\n\t"
8362306a36Sopenharmony_ci		"bf		1b				\n\t"
8462306a36Sopenharmony_ci		"and		%3, %1				\n\t"
8562306a36Sopenharmony_ci		: "=&z" (tmp), "=&r" (retval)
8662306a36Sopenharmony_ci		: "r" (a), "r" (mask)
8762306a36Sopenharmony_ci		: "t", "memory"
8862306a36Sopenharmony_ci	);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	return retval != 0;
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic inline int test_and_clear_bit(int nr, volatile void *addr)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	int	mask, retval;
9662306a36Sopenharmony_ci	volatile unsigned int *a = addr;
9762306a36Sopenharmony_ci	unsigned long tmp;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	a += nr >> 5;
10062306a36Sopenharmony_ci	mask = 1 << (nr & 0x1f);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	__asm__ __volatile__ (
10362306a36Sopenharmony_ci		"1:						\n\t"
10462306a36Sopenharmony_ci		"movli.l	@%2, %0	! test_and_clear_bit	\n\t"
10562306a36Sopenharmony_ci		"mov		%0, %1				\n\t"
10662306a36Sopenharmony_ci		"and		%4, %0				\n\t"
10762306a36Sopenharmony_ci		"movco.l	%0, @%2				\n\t"
10862306a36Sopenharmony_ci		"bf		1b				\n\t"
10962306a36Sopenharmony_ci		"and		%3, %1				\n\t"
11062306a36Sopenharmony_ci		"synco						\n\t"
11162306a36Sopenharmony_ci		: "=&z" (tmp), "=&r" (retval)
11262306a36Sopenharmony_ci		: "r" (a), "r" (mask), "r" (~mask)
11362306a36Sopenharmony_ci		: "t", "memory"
11462306a36Sopenharmony_ci	);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	return retval != 0;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic inline int test_and_change_bit(int nr, volatile void *addr)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	int	mask, retval;
12262306a36Sopenharmony_ci	volatile unsigned int *a = addr;
12362306a36Sopenharmony_ci	unsigned long tmp;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	a += nr >> 5;
12662306a36Sopenharmony_ci	mask = 1 << (nr & 0x1f);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	__asm__ __volatile__ (
12962306a36Sopenharmony_ci		"1:						\n\t"
13062306a36Sopenharmony_ci		"movli.l	@%2, %0	! test_and_change_bit	\n\t"
13162306a36Sopenharmony_ci		"mov		%0, %1				\n\t"
13262306a36Sopenharmony_ci		"xor		%3, %0				\n\t"
13362306a36Sopenharmony_ci		"movco.l	%0, @%2				\n\t"
13462306a36Sopenharmony_ci		"bf		1b				\n\t"
13562306a36Sopenharmony_ci		"and		%3, %1				\n\t"
13662306a36Sopenharmony_ci		"synco						\n\t"
13762306a36Sopenharmony_ci		: "=&z" (tmp), "=&r" (retval)
13862306a36Sopenharmony_ci		: "r" (a), "r" (mask)
13962306a36Sopenharmony_ci		: "t", "memory"
14062306a36Sopenharmony_ci	);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return retval != 0;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci#include <asm-generic/bitops/non-atomic.h>
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci#endif /* __ASM_SH_BITOPS_LLSC_H */
148