/*
 * Copyright (C) 2004-2006 Atmel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#ifndef __ASM_AVR32_BITOPS_H
#define __ASM_AVR32_BITOPS_H

#include <asm/byteorder.h>
#include <asm/system.h>

/*
 * clear_bit() doesn't provide any barrier for the compiler
 */
#define smp_mb__before_clear_bit()	barrier()
#define smp_mb__after_clear_bit()	barrier()

/*
 * set_bit - Atomically set a bit in memory
 * @nr: the bit to set
 * @addr: the address to start counting from
 *
 * This function is atomic and may not be reordered.  See __set_bit()
 * if you do not require the atomic guarantees.
 *
 * Note that @nr may be almost arbitrarily large; this function is not
 * restricted to acting on a single-word quantity.
 */
static inline void set_bit(int nr, volatile void * addr)
{
	unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
	unsigned long tmp;

	if (__builtin_constant_p(nr)) {
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%0, %2\n"
			"	sbr	%0, %3\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p)
			: "m"(*p), "i"(nr)
			: "cc");
	} else {
		unsigned long mask = 1UL << (nr % BITS_PER_LONG);
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%0, %2\n"
			"	or	%0, %3\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p)
			: "m"(*p), "r"(mask)
			: "cc");
	}
}

/*
 * clear_bit - Clears a bit in memory
 * @nr: Bit to clear
 * @addr: Address to start counting from
 *
 * clear_bit() is atomic and may not be reordered.  However, it does
 * not contain a memory barrier, so if it is used for locking purposes,
 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
 * in order to ensure changes are visible on other processors.
 */
static inline void clear_bit(int nr, volatile void * addr)
{
	unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
	unsigned long tmp;

	if (__builtin_constant_p(nr)) {
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%0, %2\n"
			"	cbr	%0, %3\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p)
			: "m"(*p), "i"(nr)
			: "cc");
	} else {
		unsigned long mask = 1UL << (nr % BITS_PER_LONG);
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%0, %2\n"
			"	andn	%0, %3\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p)
			: "m"(*p), "r"(mask)
			: "cc");
	}
}

/*
 * change_bit - Toggle a bit in memory
 * @nr: Bit to change
 * @addr: Address to start counting from
 *
 * change_bit() is atomic and may not be reordered.
 * Note that @nr may be almost arbitrarily large; this function is not
 * restricted to acting on a single-word quantity.
 */
static inline void change_bit(int nr, volatile void * addr)
{
	unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
	unsigned long mask = 1UL << (nr % BITS_PER_LONG);
	unsigned long tmp;

	asm volatile(
		"1:	ssrf	5\n"
		"	ld.w	%0, %2\n"
		"	eor	%0, %3\n"
		"	stcond	%1, %0\n"
		"	brne	1b"
		: "=&r"(tmp), "=o"(*p)
		: "m"(*p), "r"(mask)
		: "cc");
}

/*
 * test_and_set_bit - Set a bit and return its old value
 * @nr: Bit to set
 * @addr: Address to count from
 *
 * This operation is atomic and cannot be reordered.
 * It also implies a memory barrier.
 */
static inline int test_and_set_bit(int nr, volatile void * addr)
{
	unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
	unsigned long mask = 1UL << (nr % BITS_PER_LONG);
	unsigned long tmp, old;

	if (__builtin_constant_p(nr)) {
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%0, %3\n"
			"	mov	%2, %0\n"
			"	sbr	%0, %4\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p), "=&r"(old)
			: "m"(*p), "i"(nr)
			: "memory", "cc");
	} else {
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%2, %3\n"
			"	or	%0, %2, %4\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p), "=&r"(old)
			: "m"(*p), "r"(mask)
			: "memory", "cc");
	}

	return (old & mask) != 0;
}

/*
 * test_and_clear_bit - Clear a bit and return its old value
 * @nr: Bit to clear
 * @addr: Address to count from
 *
 * This operation is atomic and cannot be reordered.
 * It also implies a memory barrier.
 */
static inline int test_and_clear_bit(int nr, volatile void * addr)
{
	unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
	unsigned long mask = 1UL << (nr % BITS_PER_LONG);
	unsigned long tmp, old;

	if (__builtin_constant_p(nr)) {
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%0, %3\n"
			"	mov	%2, %0\n"
			"	cbr	%0, %4\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p), "=&r"(old)
			: "m"(*p), "i"(nr)
			: "memory", "cc");
	} else {
		asm volatile(
			"1:	ssrf	5\n"
			"	ld.w	%0, %3\n"
			"	mov	%2, %0\n"
			"	andn	%0, %4\n"
			"	stcond	%1, %0\n"
			"	brne	1b"
			: "=&r"(tmp), "=o"(*p), "=&r"(old)
			: "m"(*p), "r"(mask)
			: "memory", "cc");
	}

	return (old & mask) != 0;
}

/*
 * test_and_change_bit - Change a bit and return its old value
 * @nr: Bit to change
 * @addr: Address to count from
 *
 * This operation is atomic and cannot be reordered.
 * It also implies a memory barrier.
 */
static inline int test_and_change_bit(int nr, volatile void * addr)
{
	unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
	unsigned long mask = 1UL << (nr % BITS_PER_LONG);
	unsigned long tmp, old;

	asm volatile(
		"1:	ssrf	5\n"
		"	ld.w	%2, %3\n"
		"	eor	%0, %2, %4\n"
		"	stcond	%1, %0\n"
		"	brne	1b"
		: "=&r"(tmp), "=o"(*p), "=&r"(old)
		: "m"(*p), "r"(mask)
		: "memory", "cc");

	return (old & mask) != 0;
}

#include <asm-generic/bitops/non-atomic.h>

/* Find First bit Set */
static inline unsigned long __ffs(unsigned long word)
{
	unsigned long result;

	asm("brev %1\n\t"
	    "clz %0,%1"
	    : "=r"(result), "=&r"(word)
	    : "1"(word));
	return result;
}

/* Find First Zero */
static inline unsigned long ffz(unsigned long word)
{
	return __ffs(~word);
}

/* Find Last bit Set */
static inline int fls(unsigned long word)
{
	unsigned long result;

	asm("clz %0,%1" : "=r"(result) : "r"(word));
	return 32 - result;
}

unsigned long find_first_zero_bit(const unsigned long *addr,
				  unsigned long size);
unsigned long find_next_zero_bit(const unsigned long *addr,
				 unsigned long size,
				 unsigned long offset);
unsigned long find_first_bit(const unsigned long *addr,
			     unsigned long size);
unsigned long find_next_bit(const unsigned long *addr,
				 unsigned long size,
				 unsigned long offset);

/*
 * ffs: find first bit set. This is defined the same way as
 * the libc and compiler builtin ffs routines, therefore
 * differs in spirit from the above ffz (man ffs).
 *
 * The difference is that bit numbering starts at 1, and if no bit is set,
 * the function returns 0.
 */
static inline int ffs(unsigned long word)
{
	if(word == 0)
		return 0;
	return __ffs(word) + 1;
}

#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>

#include <asm-generic/bitops/ext2-non-atomic.h>
#include <asm-generic/bitops/ext2-atomic.h>
#include <asm-generic/bitops/minix-le.h>

#endif /* __ASM_AVR32_BITOPS_H */
