#if defined(CONFIG_BCM_KF_MTD_BCMNAND) /* * drivers/mtd/mtd64.h * <:copyright-BRCM:2012:DUAL/GPL:standard Copyright (c) 2012 Broadcom All Rights Reserved 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 (the "GPL"). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php, or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. :> * * Data structures for MTD 64 bit ops (Borrowed heavily from broadcom NAND * controller brcmnand_priv.h) * * when who what * 20080805 sidc Original coding */ #ifndef _MTD64_H_ #define _MTD64_H_ #include /* * 64 bit arithmetics */ #include #include #define LONGLONG_TO_BITS (sizeof(uint64_t)*BITS_PER_UNIT) /* * Create a 64 bit number out of a 32 bit */ static inline int64_t mtd64_constructor(long hi, unsigned long low) { DIunion ull; ull.s.high = hi; ull.s.low = low; return ull.ll; } /* * Allow inline printing of 64 bit integer values */ static inline char *mtd64_sprintf(char* msg, int64_t offset) { DIunion llw; llw.ll = offset; sprintf(msg, "%08x:%08x", llw.s.high, llw.s.low); return msg; } static inline int mtd64_is_positive(int64_t ll) { DIunion u; u.ll = ll; return ((int) u.s.high > 0 || (((int) u.s.high) == 0 && ((unsigned int) u.s.low) > 0)); } static inline int mtd64_is_positiveorzero(int64_t ll) { DIunion u; u.ll = ll; return ((int) u.s.high >= 0 || (((int) u.s.high) == 0 && ((unsigned int) u.s.low) >= 0)); } /* * Returns low DWord */ static inline uint32_t mtd64_ll_low(int64_t ll) { DIunion ull; ull.ll = ll; return (uint32_t) ull.s.low; } /* * Returns high DWord */ static inline int32_t mtd64_ll_high(int64_t ll) { DIunion ull; ull.ll = ll; return (int32_t) ull.s.high; } static inline int mtd64_ll_ffs(uint64_t ll) { DIunion ull; int res; ull.ll = ll; res = ffs(ull.s.low); if (res) return res; res = ffs(ull.s.high); return (32 + res); } #if 0 /* * Returns (ll >> shift) */ static inline uint64_t mtd64_rshft(uint64_t ll, int shift) { DIunion src, res; src.ll = ll; bitmap_shift_right((unsigned long*) &res, (unsigned long*) &src, shift, LONGLONG_TO_BITS); return res.ll; } #define mtd64_rshft32(ll,s) mtd64_rshft(ll, s) /* * Returns (ul << shift) with ul a 32-bit unsigned integer. Returned value is a 64bit integer */ static inline uint64_t mtd64_lshft32(uint64_t ll, int shift) { DIunion src, res; src.ll = ll; bitmap_shift_left((unsigned long*) &res, (unsigned long*) &src, shift, LONGLONG_TO_BITS); return res.ll; } /* * returns (left + right) */ static inline int64_t mtd64_add(int64_t left, int64_t right) { DIunion l, r, sum; l.ll = left; r.ll = right; add_ssaaaa(sum.s.high, sum.s.low, l.s.high, l.s.low, r.s.high, r.s.low); return sum.ll; } /* * returns (left + right), with right being a 32-bit integer */ static inline int64_t mtd64_add32(int64_t left, int right) { DIunion l, r, sum; l.ll = left; r.s.high = 0; r.s.low = right; add_ssaaaa(sum.s.high, sum.s.low, l.s.high, l.s.low, r.s.high, r.s.low); return sum.ll; } /* * returns (left - right) */ static inline int64_t mtd64_sub(int64_t left, int64_t right) { DIunion l, r, diff; l.ll = left; r.ll = right; sub_ddmmss(diff.s.high, diff.s.low, l.s.high, l.s.low, r.s.high, r.s.low); return diff.ll; } /* * returns (left - right) */ static inline int64_t mtd64_sub32(int64_t left, int right) { DIunion l, r, diff; l.ll = left; r.s.low = right; r.s.high = 0; sub_ddmmss(diff.s.high, diff.s.low, l.s.high, l.s.low, r.s.high, r.s.low); return diff.ll; } static inline int mtd64_notequals(int64_t left, int64_t right) { DIunion l, r; l.ll = left; r.ll = right; if (l.s.high == r.s.high && l.s.low == r.s.low) return 0; return 1; } static inline int mtd64_equals(int64_t left, int64_t right) { DIunion l, r; l.ll = left; r.ll = right; if (l.s.high == r.s.high && l.s.low == r.s.low) return 1; return 0; } static inline int mtd64_is_greater(int64_t left, int64_t right) { return mtd64_is_positive(mtd64_sub(left, right)); } static inline int mtd64_is_gteq(int64_t left, int64_t right) { return mtd64_is_positiveorzero(mtd64_sub(left, right)); } static inline int mtd64_is_less(int64_t left, int64_t right) { return mtd64_is_positive(mtd64_sub(right, left)); } static inline int mtd64_is_lteq(int64_t left, int64_t right) { return mtd64_is_positiveorzero(mtd64_sub(right, left)); } /* * Returns (left & right) */ static inline uint64_t mtd64_and(uint64_t left, uint64_t right) { uint64_t res; bitmap_and((unsigned long*) &res, (unsigned long*) &left, (unsigned long*) &right, LONGLONG_TO_BITS); return res; } static inline uint64_t mtd64_or(uint64_t left, uint64_t right) { uint64_t res; bitmap_or((unsigned long *) &res, (unsigned long *) &left, (unsigned long *) &right, LONGLONG_TO_BITS); return res; } /* * Multiply 2 32-bit integer, result is 64bit */ static inline uint64_t mtd64_mul(unsigned int left, unsigned int right) { DIunion llw; umul_ppmm(llw.s.high, llw.s.low, left, right); return llw.ll; } /* * res Result * high:low u64 bit * base Divisor * rem Remainder */ #define do_mtd_div64_32(res, high, low, base, rem) ({ \ unsigned long __quot, __mod; \ unsigned long __cf, __tmp, __tmp2, __i; \ \ __asm__(".set push\n\t" \ ".set noat\n\t" \ ".set noreorder\n\t" \ "move %2, $0\n\t" \ "move %3, $0\n\t" \ "b 1f\n\t" \ " li %4, 0x21\n" \ "0:\n\t" \ "sll $1, %0, 0x1\n\t" \ "srl %3, %0, 0x1f\n\t" \ "or %0, $1, %5\n\t" \ "sll %1, %1, 0x1\n\t" \ "sll %2, %2, 0x1\n" \ "1:\n\t" \ "bnez %3, 2f\n\t" \ " sltu %5, %0, %z6\n\t" \ "bnez %5, 3f\n" \ "2:\n\t" \ " addiu %4, %4, -1\n\t" \ "subu %0, %0, %z6\n\t" \ "addiu %2, %2, 1\n" \ "3:\n\t" \ "bnez %4, 0b\n\t" \ " srl %5, %1, 0x1f\n\t" \ ".set pop" \ : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ "=&r" (__i), "=&r" (__tmp2) \ : "Jr" (base), "0" (high), "1" (low)); \ \ (res) = __quot; \ (rem) = __mod; \ __quot; }) #endif #endif #endif // CONFIG_BCM_KF_MTD_BCMNAND