1867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
2867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Copyright 2010 Tilera Corporation. All Rights Reserved.
3867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
4867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   This program is free software; you can redistribute it and/or
5867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   modify it under the terms of the GNU General Public License
6867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   as published by the Free Software Foundation, version 2.
7867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
8867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   This program is distributed in the hope that it will be useful, but
9867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   WITHOUT ANY WARRANTY; without even the implied warranty of
10867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   NON INFRINGEMENT.  See the GNU General Public License for
12867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   more details.
13867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
14867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
15867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifndef _ASM_TILE_BITOPS_32_H
16867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define _ASM_TILE_BITOPS_32_H
17867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
18867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/compiler.h>
196dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#include <asm/barrier.h>
20867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
21867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/* Tile-specific routines to support <asm/bitops.h>. */
22867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfunsigned long _atomic_or(volatile unsigned long *p, unsigned long mask);
23867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfunsigned long _atomic_andn(volatile unsigned long *p, unsigned long mask);
24867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfunsigned long _atomic_xor(volatile unsigned long *p, unsigned long mask);
25867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
26867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/**
27867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * set_bit - Atomically set a bit in memory
28867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @nr: the bit to set
29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @addr: the address to start counting from
30867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
31867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This function is atomic and may not be reordered.
32867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * See __set_bit() if you do not require the atomic guarantees.
33867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Note that @nr may be almost arbitrarily large; this function is not
34867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * restricted to acting on a single-word quantity.
35867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
36867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void set_bit(unsigned nr, volatile unsigned long *addr)
37867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
38867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	_atomic_or(addr + BIT_WORD(nr), BIT_MASK(nr));
39867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
40867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
41867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/**
42867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * clear_bit - Clears a bit in memory
43867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @nr: Bit to clear
44867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @addr: Address to start counting from
45867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
46867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * clear_bit() is atomic and may not be reordered.
47867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * See __clear_bit() if you do not require the atomic guarantees.
48867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Note that @nr may be almost arbitrarily large; this function is not
49867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * restricted to acting on a single-word quantity.
50867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
51867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * clear_bit() may not contain a memory barrier, so if it is used for
52ce3609f93445846f7b5a5b4bacb236a9bdc35216Peter Zijlstra * locking purposes, you should call smp_mb__before_atomic() and/or
53ce3609f93445846f7b5a5b4bacb236a9bdc35216Peter Zijlstra * smp_mb__after_atomic() to ensure changes are visible on other cpus.
54867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
55867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void clear_bit(unsigned nr, volatile unsigned long *addr)
56867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
57867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	_atomic_andn(addr + BIT_WORD(nr), BIT_MASK(nr));
58867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
59867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
60867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/**
61867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * change_bit - Toggle a bit in memory
62867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @nr: Bit to change
63867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @addr: Address to start counting from
64867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
65867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * change_bit() is atomic and may not be reordered.
66867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * See __change_bit() if you do not require the atomic guarantees.
67867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Note that @nr may be almost arbitrarily large; this function is not
68867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * restricted to acting on a single-word quantity.
69867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
70867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void change_bit(unsigned nr, volatile unsigned long *addr)
71867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
72867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	_atomic_xor(addr + BIT_WORD(nr), BIT_MASK(nr));
73867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
74867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
75867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/**
76867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * test_and_set_bit - Set a bit and return its old value
77867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @nr: Bit to set
78867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @addr: Address to count from
79867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
80867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This operation is atomic and cannot be reordered.
81867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * It also implies a memory barrier.
82867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
83867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline int test_and_set_bit(unsigned nr, volatile unsigned long *addr)
84867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
85867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned long mask = BIT_MASK(nr);
86867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	addr += BIT_WORD(nr);
87867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	smp_mb();  /* barrier for proper semantics */
88867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return (_atomic_or(addr, mask) & mask) != 0;
89867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
90867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
91867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/**
92867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * test_and_clear_bit - Clear a bit and return its old value
93867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @nr: Bit to clear
94867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @addr: Address to count from
95867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
96867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This operation is atomic and cannot be reordered.
97867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * It also implies a memory barrier.
98867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
99867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline int test_and_clear_bit(unsigned nr, volatile unsigned long *addr)
100867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
101867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned long mask = BIT_MASK(nr);
102867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	addr += BIT_WORD(nr);
103867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	smp_mb();  /* barrier for proper semantics */
104867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return (_atomic_andn(addr, mask) & mask) != 0;
105867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
106867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
107867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/**
108867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * test_and_change_bit - Change a bit and return its old value
109867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @nr: Bit to change
110867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * @addr: Address to count from
111867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
112867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * This operation is atomic and cannot be reordered.
113867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * It also implies a memory barrier.
114867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
115867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline int test_and_change_bit(unsigned nr,
116867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf				      volatile unsigned long *addr)
117867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
118867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned long mask = BIT_MASK(nr);
119867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	addr += BIT_WORD(nr);
120867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	smp_mb();  /* barrier for proper semantics */
121867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return (_atomic_xor(addr, mask) & mask) != 0;
122867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
123867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
124867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm-generic/bitops/ext2-atomic.h>
125867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
126867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif /* _ASM_TILE_BITOPS_32_H */
127