From 0e9e7dcd10c4f0653252076ccc4289cfcf55c4b4 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 24 Jul 2012 20:39:17 +0000 Subject: adds target used by rapsberry pi Add support for Raspberry Pi / brcm2708 / 2835 Signed-off-by: Ian Ridge SVN-Revision: 32825 --- .../patches-3.3/0002-Main-bcm2708-linux-port.patch | 11023 +++++++++++++++++++ 1 file changed, 11023 insertions(+) create mode 100644 target/linux/brcm2708/patches-3.3/0002-Main-bcm2708-linux-port.patch (limited to 'target/linux/brcm2708/patches-3.3/0002-Main-bcm2708-linux-port.patch') diff --git a/target/linux/brcm2708/patches-3.3/0002-Main-bcm2708-linux-port.patch b/target/linux/brcm2708/patches-3.3/0002-Main-bcm2708-linux-port.patch new file mode 100644 index 0000000000..78de767b1e --- /dev/null +++ b/target/linux/brcm2708/patches-3.3/0002-Main-bcm2708-linux-port.patch @@ -0,0 +1,11023 @@ +From d5ef856b4628a4531c1627dec100eeff15e8b31e Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 17 Jan 2012 19:20:11 +0000 +Subject: [PATCH 2/7] Main bcm2708 linux port + +Signed-off-by: popcornmix +--- + arch/arm/Kconfig | 14 + + arch/arm/Makefile | 1 + + arch/arm/boot/compressed/Makefile | 8 +- + arch/arm/boot/compressed/divdi3.c | 338 +++++ + arch/arm/boot/compressed/longlong.h | 151 ++ + arch/arm/configs/bcmrpi_cutdown_defconfig | 1558 ++++++++++++++++++++ + arch/arm/kernel/armksyms.c | 4 + + arch/arm/lib/Makefile | 3 +- + arch/arm/lib/divdi3.c | 338 +++++ + arch/arm/lib/lib1funcs.S | 27 + + arch/arm/lib/longlong.h | 151 ++ + arch/arm/mach-bcm2708/Kconfig | 25 + + arch/arm/mach-bcm2708/Makefile | 8 + + arch/arm/mach-bcm2708/Makefile.boot | 3 + + arch/arm/mach-bcm2708/armctrl.c | 399 +++++ + arch/arm/mach-bcm2708/armctrl.h | 27 + + arch/arm/mach-bcm2708/bcm2708.c | 658 +++++++++ + arch/arm/mach-bcm2708/bcm2708.h | 51 + + arch/arm/mach-bcm2708/bcm2708_gpio.c | 323 ++++ + arch/arm/mach-bcm2708/clock.c | 61 + + arch/arm/mach-bcm2708/clock.h | 24 + + arch/arm/mach-bcm2708/dma.c | 397 +++++ + arch/arm/mach-bcm2708/include/mach/arm_control.h | 419 ++++++ + arch/arm/mach-bcm2708/include/mach/arm_power.h | 60 + + arch/arm/mach-bcm2708/include/mach/clkdev.h | 7 + + arch/arm/mach-bcm2708/include/mach/debug-macro.S | 24 + + arch/arm/mach-bcm2708/include/mach/dma.h | 84 ++ + arch/arm/mach-bcm2708/include/mach/entry-macro.S | 69 + + arch/arm/mach-bcm2708/include/mach/frc.h | 38 + + arch/arm/mach-bcm2708/include/mach/gpio.h | 48 + + arch/arm/mach-bcm2708/include/mach/hardware.h | 28 + + arch/arm/mach-bcm2708/include/mach/io.h | 28 + + arch/arm/mach-bcm2708/include/mach/irqs.h | 190 +++ + arch/arm/mach-bcm2708/include/mach/irqs.h.orig | 185 +++ + arch/arm/mach-bcm2708/include/mach/memory.h | 59 + + arch/arm/mach-bcm2708/include/mach/platform.h | 210 +++ + arch/arm/mach-bcm2708/include/mach/platform.h.orig | 210 +++ + arch/arm/mach-bcm2708/include/mach/power.h | 26 + + arch/arm/mach-bcm2708/include/mach/system.h | 53 + + arch/arm/mach-bcm2708/include/mach/timex.h | 23 + + arch/arm/mach-bcm2708/include/mach/uncompress.h | 49 + + arch/arm/mach-bcm2708/include/mach/vc_mem.h | 34 + + arch/arm/mach-bcm2708/include/mach/vcio.h | 42 + + arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 + + arch/arm/mach-bcm2708/power.c | 193 +++ + arch/arm/mach-bcm2708/vc_mem.c | 467 ++++++ + arch/arm/mach-bcm2708/vcio.c | 309 ++++ + arch/arm/mm/Kconfig | 2 +- + arch/arm/mm/alignment.c | 6 +- + arch/arm/mm/proc-v6.S | 15 +- + drivers/mmc/host/Kconfig | 29 + + drivers/mmc/host/Makefile | 2 + + drivers/mmc/host/bcm2708_mci.c | 889 +++++++++++ + drivers/mmc/host/bcm2708_mci.h | 101 ++ + drivers/mmc/host/sdhci-bcm2708.c | 1461 ++++++++++++++++++ + drivers/mmc/host/sdhci.c | 623 ++++++--- + drivers/mmc/host/sdhci.h | 46 + + include/linux/mmc/host.h | 29 + + include/linux/mmc/sdhci.h | 10 + + 59 files changed, 10481 insertions(+), 176 deletions(-) + create mode 100644 arch/arm/boot/compressed/divdi3.c + create mode 100644 arch/arm/boot/compressed/longlong.h + create mode 100644 arch/arm/configs/bcmrpi_cutdown_defconfig + create mode 100644 arch/arm/lib/divdi3.c + create mode 100644 arch/arm/lib/longlong.h + create mode 100644 arch/arm/mach-bcm2708/Kconfig + create mode 100644 arch/arm/mach-bcm2708/Makefile + create mode 100644 arch/arm/mach-bcm2708/Makefile.boot + create mode 100644 arch/arm/mach-bcm2708/armctrl.c + create mode 100644 arch/arm/mach-bcm2708/armctrl.h + create mode 100644 arch/arm/mach-bcm2708/bcm2708.c + create mode 100644 arch/arm/mach-bcm2708/bcm2708.h + create mode 100644 arch/arm/mach-bcm2708/bcm2708_gpio.c + create mode 100644 arch/arm/mach-bcm2708/clock.c + create mode 100644 arch/arm/mach-bcm2708/clock.h + create mode 100644 arch/arm/mach-bcm2708/dma.c + create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_control.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_power.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/clkdev.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S + create mode 100644 arch/arm/mach-bcm2708/include/mach/dma.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/entry-macro.S + create mode 100644 arch/arm/mach-bcm2708/include/mach/frc.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/gpio.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/hardware.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/io.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/irqs.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/irqs.h.orig + create mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h.orig + create mode 100644 arch/arm/mach-bcm2708/include/mach/power.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/system.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/timex.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_mem.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/vcio.h + create mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h + create mode 100644 arch/arm/mach-bcm2708/power.c + create mode 100644 arch/arm/mach-bcm2708/vc_mem.c + create mode 100644 arch/arm/mach-bcm2708/vcio.c + create mode 100644 drivers/mmc/host/bcm2708_mci.c + create mode 100644 drivers/mmc/host/bcm2708_mci.h + create mode 100644 drivers/mmc/host/sdhci-bcm2708.c + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -961,6 +961,20 @@ config PLAT_SPEAR + help + Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx). + ++config ARCH_BCM2708 ++ bool "Broadcom BCM2708 family" ++ select CPU_V6 ++ select ARM_AMBA ++ select HAVE_CLK ++ select CLKDEV_LOOKUP ++ select GENERIC_CLOCKEVENTS ++ select ARM_ERRATA_411920 ++ select MACH_BCM2708 ++ select VC4 ++ select NEED_MACH_MEMORY_H ++ help ++ This enables support for Broadcom BCM2708 boards. ++ + config ARCH_VT8500 + bool "VIA/WonderMedia 85xx" + select CPU_ARM926T +@@ -1103,6 +1117,7 @@ source "arch/arm/plat-versatile/Kconfig" + source "arch/arm/mach-vt8500/Kconfig" + + source "arch/arm/mach-w90x900/Kconfig" ++source "arch/arm/mach-bcm2708/Kconfig" + + # Definitions to make life easier + config ARCH_ACORN +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -196,6 +196,7 @@ machine-$(CONFIG_MACH_SPEAR310) := spea + machine-$(CONFIG_MACH_SPEAR320) := spear3xx + machine-$(CONFIG_MACH_SPEAR600) := spear6xx + machine-$(CONFIG_ARCH_ZYNQ) := zynq ++machine-$(CONFIG_ARCH_BCM2708) := bcm2708 + + # Platform directory name. This list is sorted alphanumerically + # by CONFIG_* macro name. +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -147,11 +147,17 @@ LDFLAGS_vmlinux += -X + LDFLAGS_vmlinux += -T + + # For __aeabi_uidivmod +-lib1funcs = $(obj)/lib1funcs.o ++lib1funcs = $(obj)/lib1funcs.o $(obj)/divdi3.o + + $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S + $(call cmd,shipped) + ++$(obj)/longlong.h: $(srctree)/arch/$(SRCARCH)/lib/longlong.h FORCE ++ $(call cmd,shipped) ++ ++$(obj)/divdi3.c: $(srctree)/arch/$(SRCARCH)/lib/divdi3.c $(obj)/longlong.h FORCE ++ $(call cmd,shipped) ++ + # We need to prevent any GOTOFF relocs being used with references + # to symbols in the .bss section since we cannot relocate them + # independently from the rest at run time. This can be achieved by +--- /dev/null ++++ b/arch/arm/boot/compressed/divdi3.c +@@ -0,0 +1,338 @@ ++/* 64-bit multiplication and division ++ Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include "longlong.h" ++ ++#define W_TYPE_SIZE (sizeof(long)) ++ ++#ifdef __ARMEB__ ++struct DWstruct { long high, low;}; ++#else ++struct DWstruct { long low, high;}; ++#endif ++ ++typedef union { struct DWstruct s; long long ll; } DWunion; ++ ++/* Prototypes of exported functions. */ ++long long __divdi3 (long long u, long long v); ++long long __moddi3 (long long u, long long v); ++unsigned long long __udivdi3 (unsigned long long u, unsigned long long v); ++unsigned long long __umoddi3 (unsigned long long u, unsigned long long v); ++ ++static unsigned long long ++__udivmoddi4 (unsigned long long n, unsigned long long d, unsigned long long *rp) ++{ ++ DWunion ww; ++ DWunion nn, dd; ++ DWunion rr; ++ unsigned long d0, d1, n0, n1, n2; ++ unsigned long q0, q1; ++ unsigned long b, bm; ++ ++ nn.ll = n; ++ dd.ll = d; ++ ++ d0 = dd.s.low; ++ d1 = dd.s.high; ++ n0 = nn.s.low; ++ n1 = nn.s.high; ++ ++#if !UDIV_NEEDS_NORMALIZATION ++ if (d1 == 0) ++ { ++ if (d0 > n1) ++ { ++ /* 0q = nn / 0D */ ++ ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ q1 = 0; ++ ++ /* Remainder in n0. */ ++ } ++ else ++ { ++ /* qq = NN / 0d */ ++ ++ if (d0 == 0) ++ d0 = 1 / d0; /* Divide intentionally by zero. */ ++ ++ udiv_qrnnd (q1, n1, 0, n1, d0); ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ ++ /* Remainder in n0. */ ++ } ++ ++ if (rp != 0) ++ { ++ rr.s.low = n0; ++ rr.s.high = 0; ++ *rp = rr.ll; ++ } ++ } ++ ++#else /* UDIV_NEEDS_NORMALIZATION */ ++ ++ if (d1 == 0) ++ { ++ if (d0 > n1) ++ { ++ /* 0q = nn / 0D */ ++ ++ count_leading_zeros (bm, d0); ++ ++ if (bm != 0) ++ { ++ /* Normalize, i.e. make the most significant bit of the ++ denominator set. */ ++ ++ d0 = d0 << bm; ++ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); ++ n0 = n0 << bm; ++ } ++ ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ q1 = 0; ++ ++ /* Remainder in n0 >> bm. */ ++ } ++ else ++ { ++ /* qq = NN / 0d */ ++ ++ if (d0 == 0) ++ d0 = 1 / d0; /* Divide intentionally by zero. */ ++ ++ count_leading_zeros (bm, d0); ++ ++ if (bm == 0) ++ { ++ /* From (n1 >= d0) /\ (the most significant bit of d0 is set), ++ conclude (the most significant bit of n1 is set) /\ (the ++ leading quotient digit q1 = 1). ++ ++ This special case is necessary, not an optimization. ++ (Shifts counts of W_TYPE_SIZE are undefined.) */ ++ ++ n1 -= d0; ++ q1 = 1; ++ } ++ else ++ { ++ /* Normalize. */ ++ ++ b = W_TYPE_SIZE - bm; ++ ++ d0 = d0 << bm; ++ n2 = n1 >> b; ++ n1 = (n1 << bm) | (n0 >> b); ++ n0 = n0 << bm; ++ ++ udiv_qrnnd (q1, n1, n2, n1, d0); ++ } ++ ++ /* n1 != d0... */ ++ ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ ++ /* Remainder in n0 >> bm. */ ++ } ++ ++ if (rp != 0) ++ { ++ rr.s.low = n0 >> bm; ++ rr.s.high = 0; ++ *rp = rr.ll; ++ } ++ } ++#endif /* UDIV_NEEDS_NORMALIZATION */ ++ ++ else ++ { ++ if (d1 > n1) ++ { ++ /* 00 = nn / DD */ ++ ++ q0 = 0; ++ q1 = 0; ++ ++ /* Remainder in n1n0. */ ++ if (rp != 0) ++ { ++ rr.s.low = n0; ++ rr.s.high = n1; ++ *rp = rr.ll; ++ } ++ } ++ else ++ { ++ /* 0q = NN / dd */ ++ ++ count_leading_zeros (bm, d1); ++ if (bm == 0) ++ { ++ /* From (n1 >= d1) /\ (the most significant bit of d1 is set), ++ conclude (the most significant bit of n1 is set) /\ (the ++ quotient digit q0 = 0 or 1). ++ ++ This special case is necessary, not an optimization. */ ++ ++ /* The condition on the next line takes advantage of that ++ n1 >= d1 (true due to program flow). */ ++ if (n1 > d1 || n0 >= d0) ++ { ++ q0 = 1; ++ sub_ddmmss (n1, n0, n1, n0, d1, d0); ++ } ++ else ++ q0 = 0; ++ ++ q1 = 0; ++ ++ if (rp != 0) ++ { ++ rr.s.low = n0; ++ rr.s.high = n1; ++ *rp = rr.ll; ++ } ++ } ++ else ++ { ++ unsigned long m1, m0; ++ /* Normalize. */ ++ ++ b = W_TYPE_SIZE - bm; ++ ++ d1 = (d1 << bm) | (d0 >> b); ++ d0 = d0 << bm; ++ n2 = n1 >> b; ++ n1 = (n1 << bm) | (n0 >> b); ++ n0 = n0 << bm; ++ ++ udiv_qrnnd (q0, n1, n2, n1, d1); ++ umul_ppmm (m1, m0, q0, d0); ++ ++ if (m1 > n1 || (m1 == n1 && m0 > n0)) ++ { ++ q0--; ++ sub_ddmmss (m1, m0, m1, m0, d1, d0); ++ } ++ ++ q1 = 0; ++ ++ /* Remainder in (n1n0 - m1m0) >> bm. */ ++ if (rp != 0) ++ { ++ sub_ddmmss (n1, n0, n1, n0, m1, m0); ++ rr.s.low = (n1 << b) | (n0 >> bm); ++ rr.s.high = n1 >> bm; ++ *rp = rr.ll; ++ } ++ } ++ } ++ } ++ ++ ww.s.low = q0; ++ ww.s.high = q1; ++ return ww.ll; ++} ++ ++long long ++__divdi3 (long long u, long long v) ++{ ++ long c = 0; ++ long long w; ++ ++ if (u < 0) ++ { ++ c = ~c; ++ u = -u; ++ } ++ if (v < 0) ++ { ++ c = ~c; ++ v = -v; ++ } ++ w = __udivmoddi4 (u, v, 0); ++ if (c) ++ w = -w; ++ return w; ++} ++ ++long long ++__moddi3 (long long u, long long v) ++{ ++ long c = 0; ++ long long w; ++ ++ if (u < 0) ++ { ++ c = ~c; ++ u = -u; ++ } ++ if (v < 0) ++ v = -v; ++ __udivmoddi4 (u, v, &w); ++ if (c) ++ w = -w; ++ return w; ++} ++ ++unsigned long long ++__udivdi3 (unsigned long long u, unsigned long long v) ++{ ++ return __udivmoddi4 (u, v, 0); ++} ++ ++unsigned long long ++__umoddi3 (unsigned long long u, unsigned long long v) ++{ ++ unsigned long long w; ++ ++ __udivmoddi4 (u, v, &w); ++ return w; ++} ++ ++long long ++__gnu_ldivmod_helper (long long a, ++ ++ long long b, ++ long long *remainder) ++{ ++ long long quotient; ++ ++ quotient = __divdi3 (a, b); ++ *remainder = a - b * quotient; ++ ++ return quotient; ++} ++ ++unsigned long long ++ ++__gnu_uldivmod_helper (unsigned long long a, ++ ++ unsigned long long b, ++ unsigned long long *remainder) ++{ ++ unsigned long long quotient; ++ ++ quotient = __udivdi3 (a, b); ++ *remainder = a - b * quotient; ++ return quotient; ++} +--- /dev/null ++++ b/arch/arm/boot/compressed/longlong.h +@@ -0,0 +1,151 @@ ++/* longlong.h -- based on code from gcc-2.95.3 ++ ++ definitions for mixed size 32/64 bit arithmetic. ++ Copyright (C) 1991, 92, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc. ++ ++ This definition file is free software; you can redistribute it ++ and/or modify it under the terms of the GNU General Public ++ License as published by the Free Software Foundation; either ++ version 2, or (at your option) any later version. ++ ++ This definition file 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. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++/* Borrowed from GCC 2.95.3, I Molton 29/07/01 */ ++ ++#define USItype unsigned long ++#define SI_TYPE_SIZE sizeof(USItype) ++ ++#define __BITS4 (SI_TYPE_SIZE / 4) ++#define __ll_B (1L << (SI_TYPE_SIZE / 2)) ++#define __ll_lowpart(t) ((USItype) (t) % __ll_B) ++#define __ll_highpart(t) ((USItype) (t) / __ll_B) ++ ++/* Define auxiliary asm macros. ++ ++ 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) ++ multiplies two USItype integers MULTIPLER and MULTIPLICAND, ++ and generates a two-part USItype product in HIGH_PROD and ++ LOW_PROD. ++ ++ 2) __umulsidi3(a,b) multiplies two USItype integers A and B, ++ and returns a UDItype product. This is just a variant of umul_ppmm. ++ ++ 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, ++ denominator) divides a two-word unsigned integer, composed by the ++ integers HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and ++ places the quotient in QUOTIENT and the remainder in REMAINDER. ++ HIGH_NUMERATOR must be less than DENOMINATOR for correct operation. ++ If, in addition, the most significant bit of DENOMINATOR must be 1, ++ then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1. ++ ++ 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, ++ denominator). Like udiv_qrnnd but the numbers are signed. The ++ quotient is rounded towards 0. ++ ++ 5) count_leading_zeros(count, x) counts the number of zero-bits from ++ the msb to the first non-zero bit. This is the number of steps X ++ needs to be shifted left to set the msb. Undefined for X == 0. ++ ++ 6) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, ++ high_addend_2, low_addend_2) adds two two-word unsigned integers, ++ composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and ++ LOW_ADDEND_2 respectively. The result is placed in HIGH_SUM and ++ LOW_SUM. Overflow (i.e. carry out) is not stored anywhere, and is ++ lost. ++ ++ 7) sub_ddmmss(high_difference, low_difference, high_minuend, ++ low_minuend, high_subtrahend, low_subtrahend) subtracts two ++ two-word unsigned integers, composed by HIGH_MINUEND_1 and ++ LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and LOW_SUBTRAHEND_2 ++ respectively. The result is placed in HIGH_DIFFERENCE and ++ LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, ++ and is lost. ++ ++ If any of these macros are left undefined for a particular CPU, ++ C macros are used. */ ++ ++#if defined (__arm__) ++#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ ++ __asm__ ("adds %1, %4, %5 \n\ ++ adc %0, %2, %3" \ ++ : "=r" ((USItype) (sh)), \ ++ "=&r" ((USItype) (sl)) \ ++ : "%r" ((USItype) (ah)), \ ++ "rI" ((USItype) (bh)), \ ++ "%r" ((USItype) (al)), \ ++ "rI" ((USItype) (bl))) ++#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ ++ __asm__ ("subs %1, %4, %5 \n\ ++ sbc %0, %2, %3" \ ++ : "=r" ((USItype) (sh)), \ ++ "=&r" ((USItype) (sl)) \ ++ : "r" ((USItype) (ah)), \ ++ "rI" ((USItype) (bh)), \ ++ "r" ((USItype) (al)), \ ++ "rI" ((USItype) (bl))) ++#define umul_ppmm(xh, xl, a, b) \ ++ __asm__ ("%@ Inlined umul_ppmm\n" \ ++ "umull %r1, %r0, %r2, %r3" \ ++ : "=&r" ((USItype)(xh)), \ ++ "=r" ((USItype)(xl)) \ ++ : "r" ((USItype)(a)), \ ++ "r" ((USItype)(b)) \ ++ : "r0", "r1") ++#define count_leading_zeros(count, x) \ ++ __asm__ ("clz %0, %1" : "=r"(count) : "r"(x)) ++#define UMUL_TIME 20 ++#define UDIV_TIME 100 ++#endif /* __arm__ */ ++ ++#define __umulsidi3(u, v) \ ++ ({DIunion __w; \ ++ umul_ppmm (__w.s.high, __w.s.low, u, v); \ ++ __w.ll; }) ++ ++#define __udiv_qrnnd_c(q, r, n1, n0, d) \ ++ do { \ ++ USItype __d1, __d0, __q1, __q0; \ ++ USItype __r1, __r0, __m; \ ++ __d1 = __ll_highpart (d); \ ++ __d0 = __ll_lowpart (d); \ ++ \ ++ __r1 = (n1) % __d1; \ ++ __q1 = (n1) / __d1; \ ++ __m = (USItype) __q1 * __d0; \ ++ __r1 = __r1 * __ll_B | __ll_highpart (n0); \ ++ if (__r1 < __m) \ ++ { \ ++ __q1--, __r1 += (d); \ ++ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ ++ if (__r1 < __m) \ ++ __q1--, __r1 += (d); \ ++ } \ ++ __r1 -= __m; \ ++ \ ++ __r0 = __r1 % __d1; \ ++ __q0 = __r1 / __d1; \ ++ __m = (USItype) __q0 * __d0; \ ++ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ ++ if (__r0 < __m) \ ++ { \ ++ __q0--, __r0 += (d); \ ++ if (__r0 >= (d)) \ ++ if (__r0 < __m) \ ++ __q0--, __r0 += (d); \ ++ } \ ++ __r0 -= __m; \ ++ \ ++ (q) = (USItype) __q1 * __ll_B | __q0; \ ++ (r) = __r0; \ ++ } while (0) ++ ++#define UDIV_NEEDS_NORMALIZATION 1 ++#define udiv_qrnnd __udiv_qrnnd_c +--- /dev/null ++++ b/arch/arm/configs/bcmrpi_cutdown_defconfig +@@ -0,0 +1,1558 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.1.9 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++# CONFIG_ARCH_USES_GETTIMEOFFSET is not set ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_KTIME_SCALAR=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_VECTORS_BASE=0xffff0000 ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_HAVE_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_FHANDLE is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_HAVE_SPARSE_IRQ=y ++CONFIG_GENERIC_IRQ_SHOW=y ++# CONFIG_SPARSE_IRQ is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TINY_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_TREE_RCU_TRACE is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=17 ++# CONFIG_CGROUPS is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++# CONFIG_BLK_DEV_INITRD is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_EXPERT=y ++# CONFIG_UID16 is not set ++CONFIG_SYSCTL_SYSCALL=y ++# CONFIG_KALLSYMS is not set ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++# CONFIG_ELF_CORE is not set ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++# CONFIG_PERF_EVENTS is not set ++# CONFIG_PERF_COUNTERS is not set ++# CONFIG_VM_EVENT_COUNTERS is not set ++# CONFIG_COMPAT_BRK is not set ++CONFIG_SLAB=y ++# CONFIG_SLUB is not set ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++CONFIG_INLINE_SPIN_UNLOCK=y ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++# CONFIG_MUTEX_SPIN_ON_OWNER is not set ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCMRING is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_GEMINI is not set ++# CONFIG_ARCH_PRIMA2 is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_LPC32XX is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_W90X900 is not set ++# CONFIG_ARCH_NUC93X is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_MSM is not set ++# CONFIG_ARCH_SHMOBILE is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_S5P64X0 is not set ++# CONFIG_ARCH_S5PC100 is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS4 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_TCC_926 is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_PLAT_SPEAR is not set ++CONFIG_ARCH_BCM2708=y ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# System MMU ++# ++ ++# ++# Broadcom BCM2708 Implementations ++# ++CONFIG_MACH_BCM2708=y ++CONFIG_BCM2708_GPIO=y ++CONFIG_BCM2708_VCMEM=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V6=y ++CONFIG_CPU_32v6=y ++CONFIG_CPU_ABRT_EV6=y ++CONFIG_CPU_PABRT_V6=y ++CONFIG_CPU_CACHE_V6=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V6=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_CPU_HAS_PMU=y ++CONFIG_ARM_ERRATA_411920=y ++# CONFIG_ARM_ERRATA_364296 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++# CONFIG_HIGH_RES_TIMERS is not set ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++# CONFIG_HIGHMEM is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++CONFIG_ALIGNMENT_TRAP=y ++# CONFIG_UACCESS_WITH_MEMCPY is not set ++# CONFIG_SECCOMP is not set ++# CONFIG_CC_STACKPROTECTOR is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++ ++# ++# Boot options ++# ++# CONFIG_USE_OF is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait" ++CONFIG_CMDLINE_FROM_BOOTLOADER=y ++# CONFIG_CMDLINE_EXTEND is not set ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++CONFIG_CPU_IDLE_GOV_MENU=y ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++# CONFIG_FPE_NWFPE is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_HAVE_AOUT=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=m ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# CONFIG_IP_PNP_BOOTP is not set ++CONFIG_IP_PNP_RARP=y ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++CONFIG_SYN_COOKIES=y ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++# CONFIG_INET_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++# CONFIG_IPV6 is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++# CONFIG_NETFILTER is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++# CONFIG_VLAN_8021Q is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++ ++# ++# Network testing ++# ++CONFIG_NET_PKTGEN=m ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++CONFIG_WIRELESS=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=y ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_REG_DEBUG is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_WEXT=y ++CONFIG_WIRELESS_EXT_SYSFS=y ++# CONFIG_LIB80211 is not set ++# CONFIG_MAC80211 is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_NET_9P is not set ++# CONFIG_CAIF is not set ++# CONFIG_CEPH_LIB is not set ++# CONFIG_NFC is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_CONNECTOR is not set ++# CONFIG_MTD is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_SENSORS_LIS3LV02D is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_IWMC3200TOP is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# CONFIG_TI_ST is not set ++CONFIG_BCM2708_VCHIQ=y ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_TGT is not set ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=m ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=m ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++CONFIG_SCSI_MULTI_LUN=y ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++CONFIG_MII=y ++CONFIG_PHYLIB=m ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++CONFIG_MDIO_BITBANG=m ++# CONFIG_MDIO_GPIO is not set ++CONFIG_NET_ETHERNET=y ++CONFIG_AX88796=m ++# CONFIG_AX88796_93CX6 is not set ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set ++# CONFIG_ETHOC is not set ++# CONFIG_SMC911X is not set ++# CONFIG_SMSC911X is not set ++# CONFIG_DNET is not set ++# CONFIG_IBM_NEW_EMAC_ZMII is not set ++# CONFIG_IBM_NEW_EMAC_RGMII is not set ++# CONFIG_IBM_NEW_EMAC_TAH is not set ++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set ++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set ++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set ++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set ++# CONFIG_B44 is not set ++# CONFIG_KS8851_MLL is not set ++# CONFIG_FTMAC100 is not set ++# CONFIG_NETDEV_1000 is not set ++# CONFIG_NETDEV_10000 is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++# CONFIG_USB_NET_CDCETHER is not set ++# CONFIG_USB_NET_CDC_EEM is not set ++CONFIG_USB_NET_CDC_NCM=y ++# CONFIG_USB_NET_DM9601 is not set ++# CONFIG_USB_NET_SMSC75XX is not set ++CONFIG_USB_NET_SMSC95XX=y ++# CONFIG_USB_NET_GL620A is not set ++# CONFIG_USB_NET_NET1080 is not set ++# CONFIG_USB_NET_PLUSB is not set ++# CONFIG_USB_NET_MCS7830 is not set ++# CONFIG_USB_NET_RNDIS_HOST is not set ++# CONFIG_USB_NET_CDC_SUBSET is not set ++# CONFIG_USB_NET_ZAURUS is not set ++# CONFIG_USB_NET_CX82310_ETH is not set ++# CONFIG_USB_NET_KALMIA is not set ++# CONFIG_USB_NET_INT51X1 is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_USB_SIERRA_NET is not set ++# CONFIG_WAN is not set ++ ++# ++# CAIF transport drivers ++# ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_ISDN is not set ++# CONFIG_PHONE is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=m ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATI_REMOTE is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=m ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=m ++CONFIG_SERIO_SERPORT=m ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_LIBPS2 is not set ++CONFIG_SERIO_RAW=m ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++CONFIG_GAMEPORT=m ++CONFIG_GAMEPORT_NS558=m ++CONFIG_GAMEPORT_L4=m ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++CONFIG_VT_HW_CONSOLE_BINDING=y ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++# CONFIG_DEVKMEM is not set ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++# CONFIG_HW_RANDOM is not set ++# CONFIG_R3964 is not set ++CONFIG_RAW_DRIVER=y ++CONFIG_MAX_RAW_DEVS=256 ++# CONFIG_TCG_TPM is not set ++# CONFIG_RAMOOPS is not set ++# CONFIG_I2C is not set ++# CONFIG_SPI is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_IT8761E is not set ++# CONFIG_GPIO_PL061 is not set ++ ++# ++# I2C GPIO expanders: ++# ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++CONFIG_BCMA_POSSIBLE=y ++ ++# ++# Broadcom specific AMBA ++# ++# CONFIG_BCMA is not set ++# CONFIG_MFD_SUPPORT is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_DRM is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_WMT_GE_ROPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++CONFIG_FB_BCM2708=y ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++# CONFIG_FONTS is not set ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_LOGO_LINUX_CLUT224=y ++# CONFIG_SOUND is not set ++CONFIG_HID_SUPPORT=y ++CONFIG_HID=y ++# CONFIG_HIDRAW is not set ++ ++# ++# USB Input Devices ++# ++CONFIG_USB_HID=y ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=m ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++# CONFIG_DRAGONRISE_FF is not set ++# CONFIG_HID_EMS_FF is not set ++CONFIG_HID_EZKEY=m ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++CONFIG_HID_KYE=m ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++CONFIG_HID_GYRATION=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++# CONFIG_HID_LCPOWER is not set ++CONFIG_HID_LOGITECH=m ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWII_FF is not set ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++# CONFIG_PANTHERLORD_FF is not set ++CONFIG_HID_PETALYNX=m ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_QUANTA is not set ++# CONFIG_HID_ROCCAT is not set ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SONY=m ++# CONFIG_HID_SPEEDLINK is not set ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_GREENASIA=m ++# CONFIG_GREENASIA_FF is not set ++CONFIG_HID_SMARTJOYPLUS=m ++# CONFIG_SMARTJOYPLUS_FF is not set ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THRUSTMASTER=m ++# CONFIG_THRUSTMASTER_FF is not set ++CONFIG_HID_ZEROPLUS=m ++# CONFIG_ZEROPLUS_FF is not set ++# CONFIG_HID_ZYDACRON is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++# CONFIG_USB_ARCH_HAS_OHCI is not set ++# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEVICEFS is not set ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++CONFIG_USB_MON=m ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++CONFIG_USB_DWCOTG=y ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may ++# ++ ++# ++# also be needed; see USB_STORAGE Help for more info ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++CONFIG_USB_LIBUSUAL=y ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_GADGET is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_NOP_USB_XCEIV is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_UNSAFE_RESUME is not set ++# CONFIG_MMC_CLKGATE is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_IO_ACCESSORS=y ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++CONFIG_MMC_SDHCI_BCM2708=y ++CONFIG_MMC_SDHCI_BCM2708_DMA=y ++# CONFIG_MMC_BCM2708 is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MEMSTICK is not set ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++ ++# ++# LED drivers ++# ++CONFIG_LEDS_GPIO=y ++# CONFIG_LEDS_LT3593 is not set ++CONFIG_LEDS_TRIGGERS=y ++ ++# ++# LED Triggers ++# ++CONFIG_LEDS_TRIGGER_TIMER=m ++CONFIG_LEDS_TRIGGER_HEARTBEAT=m ++# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set ++# CONFIG_LEDS_TRIGGER_GPIO is not set ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=m ++ ++# ++# iptables trigger is under Netfilter config (LED target) ++# ++# CONFIG_ACCESSIBILITY is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++ ++# ++# Virtio drivers ++# ++# CONFIG_VIRTIO_BALLOON is not set ++# CONFIG_STAGING is not set ++CONFIG_CLKDEV_LOOKUP=y ++# CONFIG_IOMMU_SUPPORT is not set ++# CONFIG_VIRT_DRIVERS is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=m ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT2_FS_XIP=y ++CONFIG_EXT3_FS=y ++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set ++CONFIG_EXT3_FS_XATTR=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=m ++CONFIG_EXT4_FS_XATTR=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_FS_XIP=y ++CONFIG_JBD=y ++CONFIG_JBD2=m ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_FANOTIFY is not set ++# CONFIG_QUOTA is not set ++# CONFIG_QUOTACTL is not set ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_CUSE=m ++ ++# ++# Caches ++# ++CONFIG_FSCACHE=y ++# CONFIG_FSCACHE_STATS is not set ++# CONFIG_FSCACHE_HISTOGRAM is not set ++# CONFIG_FSCACHE_DEBUG is not set ++# CONFIG_FSCACHE_OBJECT_LIST is not set ++CONFIG_CACHEFILES=y ++# CONFIG_CACHEFILES_DEBUG is not set ++# CONFIG_CACHEFILES_HISTOGRAM is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_NTFS_FS=m ++# CONFIG_NTFS_DEBUG is not set ++# CONFIG_NTFS_RW is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++# CONFIG_TMPFS_XATTR is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_CONFIGFS_FS=y ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++# CONFIG_LOGFS is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_SQUASHFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFS_USE_NEW_IDMAPPER is not set ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# CONFIG_CEPH_FS is not set ++CONFIG_CIFS=m ++# CONFIG_CIFS_STATS is not set ++CONFIG_CIFS_WEAK_PW_HASH=y ++# CONFIG_CIFS_UPCALL is not set ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++# CONFIG_CIFS_DEBUG2 is not set ++# CONFIG_CIFS_DFS_UPCALL is not set ++# CONFIG_CIFS_FSCACHE is not set ++# CONFIG_CIFS_ACL is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++CONFIG_MAC_PARTITION=y ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_NLS_UTF8=m ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++# CONFIG_MAGIC_SYSRQ is not set ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_DEBUG_SHIRQ is not set ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_TIMER_STATS is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_RT_MUTEX_TESTER is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_WRITECOUNT is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_STRICT_DEVMEM is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++# CONFIG_OC_ETM is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_KEYS_DEBUG_PROC_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=m ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++CONFIG_CRYPTO_ECB=m ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=y ++CONFIG_CRYPTO_XCBC=m ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_GHASH is not set ++CONFIG_CRYPTO_MD4=m ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_MICHAEL_MIC=m ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=y ++CONFIG_CRYPTO_SHA256=m ++CONFIG_CRYPTO_SHA512=m ++CONFIG_CRYPTO_TGR192=m ++CONFIG_CRYPTO_WP512=m ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++CONFIG_CRYPTO_ARC4=m ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++CONFIG_CRYPTO_CAST5=m ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=m ++# CONFIG_CRYPTO_ZLIB is not set ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_HW is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_CRC_CCITT=m ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++CONFIG_LIBCRC32C=y ++# CONFIG_CRC8 is not set ++CONFIG_ZLIB_INFLATE=m ++CONFIG_ZLIB_DEFLATE=m ++# CONFIG_XZ_DEC is not set ++# CONFIG_XZ_DEC_BCJ is not set ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_NLATTR=y ++CONFIG_GENERIC_ATOMIC64=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set +--- a/arch/arm/kernel/armksyms.c ++++ b/arch/arm/kernel/armksyms.c +@@ -46,6 +46,8 @@ extern void __aeabi_lmul(void); + extern void __aeabi_uidiv(void); + extern void __aeabi_uidivmod(void); + extern void __aeabi_ulcmp(void); ++extern void __aeabi_ldivmod(void); ++extern void __aeabi_uldivmod(void); + + extern void fpundefinstr(void); + +@@ -131,6 +133,8 @@ EXPORT_SYMBOL(__aeabi_lmul); + EXPORT_SYMBOL(__aeabi_uidiv); + EXPORT_SYMBOL(__aeabi_uidivmod); + EXPORT_SYMBOL(__aeabi_ulcmp); ++EXPORT_SYMBOL(__aeabi_ldivmod); ++EXPORT_SYMBOL(__aeabi_uldivmod); + #endif + + /* bitops */ +--- /dev/null ++++ b/arch/arm/lib/divdi3.c +@@ -0,0 +1,338 @@ ++/* 64-bit multiplication and division ++ Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include "longlong.h" ++ ++#define W_TYPE_SIZE (sizeof(long)) ++ ++#ifdef __ARMEB__ ++struct DWstruct { long high, low;}; ++#else ++struct DWstruct { long low, high;}; ++#endif ++ ++typedef union { struct DWstruct s; long long ll; } DWunion; ++ ++/* Prototypes of exported functions. */ ++long long __divdi3 (long long u, long long v); ++long long __moddi3 (long long u, long long v); ++unsigned long long __udivdi3 (unsigned long long u, unsigned long long v); ++unsigned long long __umoddi3 (unsigned long long u, unsigned long long v); ++ ++static unsigned long long ++__udivmoddi4 (unsigned long long n, unsigned long long d, unsigned long long *rp) ++{ ++ DWunion ww; ++ DWunion nn, dd; ++ DWunion rr; ++ unsigned long d0, d1, n0, n1, n2; ++ unsigned long q0, q1; ++ unsigned long b, bm; ++ ++ nn.ll = n; ++ dd.ll = d; ++ ++ d0 = dd.s.low; ++ d1 = dd.s.high; ++ n0 = nn.s.low; ++ n1 = nn.s.high; ++ ++#if !UDIV_NEEDS_NORMALIZATION ++ if (d1 == 0) ++ { ++ if (d0 > n1) ++ { ++ /* 0q = nn / 0D */ ++ ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ q1 = 0; ++ ++ /* Remainder in n0. */ ++ } ++ else ++ { ++ /* qq = NN / 0d */ ++ ++ if (d0 == 0) ++ d0 = 1 / d0; /* Divide intentionally by zero. */ ++ ++ udiv_qrnnd (q1, n1, 0, n1, d0); ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ ++ /* Remainder in n0. */ ++ } ++ ++ if (rp != 0) ++ { ++ rr.s.low = n0; ++ rr.s.high = 0; ++ *rp = rr.ll; ++ } ++ } ++ ++#else /* UDIV_NEEDS_NORMALIZATION */ ++ ++ if (d1 == 0) ++ { ++ if (d0 > n1) ++ { ++ /* 0q = nn / 0D */ ++ ++ count_leading_zeros (bm, d0); ++ ++ if (bm != 0) ++ { ++ /* Normalize, i.e. make the most significant bit of the ++ denominator set. */ ++ ++ d0 = d0 << bm; ++ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); ++ n0 = n0 << bm; ++ } ++ ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ q1 = 0; ++ ++ /* Remainder in n0 >> bm. */ ++ } ++ else ++ { ++ /* qq = NN / 0d */ ++ ++ if (d0 == 0) ++ d0 = 1 / d0; /* Divide intentionally by zero. */ ++ ++ count_leading_zeros (bm, d0); ++ ++ if (bm == 0) ++ { ++ /* From (n1 >= d0) /\ (the most significant bit of d0 is set), ++ conclude (the most significant bit of n1 is set) /\ (the ++ leading quotient digit q1 = 1). ++ ++ This special case is necessary, not an optimization. ++ (Shifts counts of W_TYPE_SIZE are undefined.) */ ++ ++ n1 -= d0; ++ q1 = 1; ++ } ++ else ++ { ++ /* Normalize. */ ++ ++ b = W_TYPE_SIZE - bm; ++ ++ d0 = d0 << bm; ++ n2 = n1 >> b; ++ n1 = (n1 << bm) | (n0 >> b); ++ n0 = n0 << bm; ++ ++ udiv_qrnnd (q1, n1, n2, n1, d0); ++ } ++ ++ /* n1 != d0... */ ++ ++ udiv_qrnnd (q0, n0, n1, n0, d0); ++ ++ /* Remainder in n0 >> bm. */ ++ } ++ ++ if (rp != 0) ++ { ++ rr.s.low = n0 >> bm; ++ rr.s.high = 0; ++ *rp = rr.ll; ++ } ++ } ++#endif /* UDIV_NEEDS_NORMALIZATION */ ++ ++ else ++ { ++ if (d1 > n1) ++ { ++ /* 00 = nn / DD */ ++ ++ q0 = 0; ++ q1 = 0; ++ ++ /* Remainder in n1n0. */ ++ if (rp != 0) ++ { ++ rr.s.low = n0; ++ rr.s.high = n1; ++ *rp = rr.ll; ++ } ++ } ++ else ++ { ++ /* 0q = NN / dd */ ++ ++ count_leading_zeros (bm, d1); ++ if (bm == 0) ++ { ++ /* From (n1 >= d1) /\ (the most significant bit of d1 is set), ++ conclude (the most significant bit of n1 is set) /\ (the ++ quotient digit q0 = 0 or 1). ++ ++ This special case is necessary, not an optimization. */ ++ ++ /* The condition on the next line takes advantage of that ++ n1 >= d1 (true due to program flow). */ ++ if (n1 > d1 || n0 >= d0) ++ { ++ q0 = 1; ++ sub_ddmmss (n1, n0, n1, n0, d1, d0); ++ } ++ else ++ q0 = 0; ++ ++ q1 = 0; ++ ++ if (rp != 0) ++ { ++ rr.s.low = n0; ++ rr.s.high = n1; ++ *rp = rr.ll; ++ } ++ } ++ else ++ { ++ unsigned long m1, m0; ++ /* Normalize. */ ++ ++ b = W_TYPE_SIZE - bm; ++ ++ d1 = (d1 << bm) | (d0 >> b); ++ d0 = d0 << bm; ++ n2 = n1 >> b; ++ n1 = (n1 << bm) | (n0 >> b); ++ n0 = n0 << bm; ++ ++ udiv_qrnnd (q0, n1, n2, n1, d1); ++ umul_ppmm (m1, m0, q0, d0); ++ ++ if (m1 > n1 || (m1 == n1 && m0 > n0)) ++ { ++ q0--; ++ sub_ddmmss (m1, m0, m1, m0, d1, d0); ++ } ++ ++ q1 = 0; ++ ++ /* Remainder in (n1n0 - m1m0) >> bm. */ ++ if (rp != 0) ++ { ++ sub_ddmmss (n1, n0, n1, n0, m1, m0); ++ rr.s.low = (n1 << b) | (n0 >> bm); ++ rr.s.high = n1 >> bm; ++ *rp = rr.ll; ++ } ++ } ++ } ++ } ++ ++ ww.s.low = q0; ++ ww.s.high = q1; ++ return ww.ll; ++} ++ ++long long ++__divdi3 (long long u, long long v) ++{ ++ long c = 0; ++ long long w; ++ ++ if (u < 0) ++ { ++ c = ~c; ++ u = -u; ++ } ++ if (v < 0) ++ { ++ c = ~c; ++ v = -v; ++ } ++ w = __udivmoddi4 (u, v, 0); ++ if (c) ++ w = -w; ++ return w; ++} ++ ++long long ++__moddi3 (long long u, long long v) ++{ ++ long c = 0; ++ long long w; ++ ++ if (u < 0) ++ { ++ c = ~c; ++ u = -u; ++ } ++ if (v < 0) ++ v = -v; ++ __udivmoddi4 (u, v, &w); ++ if (c) ++ w = -w; ++ return w; ++} ++ ++unsigned long long ++__udivdi3 (unsigned long long u, unsigned long long v) ++{ ++ return __udivmoddi4 (u, v, 0); ++} ++ ++unsigned long long ++__umoddi3 (unsigned long long u, unsigned long long v) ++{ ++ unsigned long long w; ++ ++ __udivmoddi4 (u, v, &w); ++ return w; ++} ++ ++long long ++__gnu_ldivmod_helper (long long a, ++ ++ long long b, ++ long long *remainder) ++{ ++ long long quotient; ++ ++ quotient = __divdi3 (a, b); ++ *remainder = a - b * quotient; ++ ++ return quotient; ++} ++ ++unsigned long long ++ ++__gnu_uldivmod_helper (unsigned long long a, ++ ++ unsigned long long b, ++ unsigned long long *remainder) ++{ ++ unsigned long long quotient; ++ ++ quotient = __udivdi3 (a, b); ++ *remainder = a - b * quotient; ++ return quotient; ++} +--- a/arch/arm/lib/lib1funcs.S ++++ b/arch/arm/lib/lib1funcs.S +@@ -349,6 +349,33 @@ UNWIND(.save {r0, r1, ip, lr} ) + UNWIND(.fnend) + ENDPROC(__aeabi_idivmod) + ++/* Added 64x64 bit division for use with OTG USB driver - multi-precision ++ * arithmetic for RSA encyrption. ++ */ ++ENTRY(__aeabi_ldivmod) ++ ++ sub sp, sp, #8 ++ stmfd sp!, {sp, lr} ++ bl __gnu_ldivmod_helper ++ ldr lr, [sp, #4] ++ add sp, sp, #8 ++ ldmfd sp!, {r2, r3} ++ mov pc, lr ++ ++ENDPROC(__aeabi_ldivmod) ++ ++ENTRY(__aeabi_uldivmod) ++ ++ sub sp, sp, #8 ++ stmfd sp!, {sp, lr} ++ bl __gnu_uldivmod_helper ++ ldr lr, [sp, #4] ++ add sp, sp, #8 ++ ldmfd sp!, {r2, r3} ++ mov pc, lr ++ ++ENDPROC(__aeabi_uldivmod) ++ + #endif + + Ldiv0: +--- /dev/null ++++ b/arch/arm/lib/longlong.h +@@ -0,0 +1,151 @@ ++/* longlong.h -- based on code from gcc-2.95.3 ++ ++ definitions for mixed size 32/64 bit arithmetic. ++ Copyright (C) 1991, 92, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc. ++ ++ This definition file is free software; you can redistribute it ++ and/or modify it under the terms of the GNU General Public ++ License as published by the Free Software Foundation; either ++ version 2, or (at your option) any later version. ++ ++ This definition file 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. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++/* Borrowed from GCC 2.95.3, I Molton 29/07/01 */ ++ ++#define USItype unsigned long ++#define SI_TYPE_SIZE sizeof(USItype) ++ ++#define __BITS4 (SI_TYPE_SIZE / 4) ++#define __ll_B (1L << (SI_TYPE_SIZE / 2)) ++#define __ll_lowpart(t) ((USItype) (t) % __ll_B) ++#define __ll_highpart(t) ((USItype) (t) / __ll_B) ++ ++/* Define auxiliary asm macros. ++ ++ 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) ++ multiplies two USItype integers MULTIPLER and MULTIPLICAND, ++ and generates a two-part USItype product in HIGH_PROD and ++ LOW_PROD. ++ ++ 2) __umulsidi3(a,b) multiplies two USItype integers A and B, ++ and returns a UDItype product. This is just a variant of umul_ppmm. ++ ++ 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, ++ denominator) divides a two-word unsigned integer, composed by the ++ integers HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and ++ places the quotient in QUOTIENT and the remainder in REMAINDER. ++ HIGH_NUMERATOR must be less than DENOMINATOR for correct operation. ++ If, in addition, the most significant bit of DENOMINATOR must be 1, ++ then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1. ++ ++ 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, ++ denominator). Like udiv_qrnnd but the numbers are signed. The ++ quotient is rounded towards 0. ++ ++ 5) count_leading_zeros(count, x) counts the number of zero-bits from ++ the msb to the first non-zero bit. This is the number of steps X ++ needs to be shifted left to set the msb. Undefined for X == 0. ++ ++ 6) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, ++ high_addend_2, low_addend_2) adds two two-word unsigned integers, ++ composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and ++ LOW_ADDEND_2 respectively. The result is placed in HIGH_SUM and ++ LOW_SUM. Overflow (i.e. carry out) is not stored anywhere, and is ++ lost. ++ ++ 7) sub_ddmmss(high_difference, low_difference, high_minuend, ++ low_minuend, high_subtrahend, low_subtrahend) subtracts two ++ two-word unsigned integers, composed by HIGH_MINUEND_1 and ++ LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and LOW_SUBTRAHEND_2 ++ respectively. The result is placed in HIGH_DIFFERENCE and ++ LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, ++ and is lost. ++ ++ If any of these macros are left undefined for a particular CPU, ++ C macros are used. */ ++ ++#if defined (__arm__) ++#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ ++ __asm__ ("adds %1, %4, %5 \n\ ++ adc %0, %2, %3" \ ++ : "=r" ((USItype) (sh)), \ ++ "=&r" ((USItype) (sl)) \ ++ : "%r" ((USItype) (ah)), \ ++ "rI" ((USItype) (bh)), \ ++ "%r" ((USItype) (al)), \ ++ "rI" ((USItype) (bl))) ++#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ ++ __asm__ ("subs %1, %4, %5 \n\ ++ sbc %0, %2, %3" \ ++ : "=r" ((USItype) (sh)), \ ++ "=&r" ((USItype) (sl)) \ ++ : "r" ((USItype) (ah)), \ ++ "rI" ((USItype) (bh)), \ ++ "r" ((USItype) (al)), \ ++ "rI" ((USItype) (bl))) ++#define umul_ppmm(xh, xl, a, b) \ ++ __asm__ ("%@ Inlined umul_ppmm\n" \ ++ "umull %r1, %r0, %r2, %r3" \ ++ : "=&r" ((USItype)(xh)), \ ++ "=r" ((USItype)(xl)) \ ++ : "r" ((USItype)(a)), \ ++ "r" ((USItype)(b)) \ ++ : "r0", "r1") ++#define count_leading_zeros(count, x) \ ++ __asm__ ("clz %0, %1" : "=r"(count) : "r"(x)) ++#define UMUL_TIME 20 ++#define UDIV_TIME 100 ++#endif /* __arm__ */ ++ ++#define __umulsidi3(u, v) \ ++ ({DIunion __w; \ ++ umul_ppmm (__w.s.high, __w.s.low, u, v); \ ++ __w.ll; }) ++ ++#define __udiv_qrnnd_c(q, r, n1, n0, d) \ ++ do { \ ++ USItype __d1, __d0, __q1, __q0; \ ++ USItype __r1, __r0, __m; \ ++ __d1 = __ll_highpart (d); \ ++ __d0 = __ll_lowpart (d); \ ++ \ ++ __r1 = (n1) % __d1; \ ++ __q1 = (n1) / __d1; \ ++ __m = (USItype) __q1 * __d0; \ ++ __r1 = __r1 * __ll_B | __ll_highpart (n0); \ ++ if (__r1 < __m) \ ++ { \ ++ __q1--, __r1 += (d); \ ++ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ ++ if (__r1 < __m) \ ++ __q1--, __r1 += (d); \ ++ } \ ++ __r1 -= __m; \ ++ \ ++ __r0 = __r1 % __d1; \ ++ __q0 = __r1 / __d1; \ ++ __m = (USItype) __q0 * __d0; \ ++ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ ++ if (__r0 < __m) \ ++ { \ ++ __q0--, __r0 += (d); \ ++ if (__r0 >= (d)) \ ++ if (__r0 < __m) \ ++ __q0--, __r0 += (d); \ ++ } \ ++ __r0 -= __m; \ ++ \ ++ (q) = (USItype) __q1 * __ll_B | __q0; \ ++ (r) = __r0; \ ++ } while (0) ++ ++#define UDIV_NEEDS_NORMALIZATION 1 ++#define udiv_qrnnd __udiv_qrnnd_c +--- /dev/null ++++ b/arch/arm/mach-bcm2708/Kconfig +@@ -0,0 +1,25 @@ ++menu "Broadcom BCM2708 Implementations" ++ depends on ARCH_BCM2708 ++ ++config MACH_BCM2708 ++ bool "Broadcom BCM2708 Development Platform" ++ select CPU_V6 ++ help ++ Include support for the Broadcom(R) BCM2708 platform. ++ ++config BCM2708_GPIO ++ bool "BCM2708 gpio support" ++ depends on MACH_BCM2708 ++ select ARCH_REQUIRE_GPIOLIB ++ default y ++ help ++ Include support for the Broadcom(R) BCM2708 gpio. ++ ++config BCM2708_VCMEM ++ bool "Videocore Memory" ++ depends on MACH_BCM2708 ++ default y ++ help ++ Helper for videocore memory access and total size allocation. ++ ++endmenu +--- /dev/null ++++ b/arch/arm/mach-bcm2708/Makefile +@@ -0,0 +1,8 @@ ++# ++# Makefile for the linux kernel. ++# ++ ++obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o ++obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o ++obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o ++ +--- /dev/null ++++ b/arch/arm/mach-bcm2708/Makefile.boot +@@ -0,0 +1,3 @@ ++ zreladdr-y := 0x00008000 ++params_phys-y := 0x00000100 ++initrd_phys-y := 0x00800000 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/armctrl.c +@@ -0,0 +1,399 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/armctrl.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39) ++#include ++#else ++#include ++#endif ++#include ++ ++#include ++#include ++#include "armctrl.h" ++ ++/* For support of kernels >= 3.0 assume only one VIC for now*/ ++static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { ++ INTERRUPT_VC_JPEG, ++ INTERRUPT_VC_USB, ++ INTERRUPT_VC_3D, ++ INTERRUPT_VC_DMA2, ++ INTERRUPT_VC_DMA3, ++ INTERRUPT_VC_I2C, ++ INTERRUPT_VC_SPI, ++ INTERRUPT_VC_I2SPCM, ++ INTERRUPT_VC_SDIO, ++ INTERRUPT_VC_UART, ++ INTERRUPT_VC_ARASANSDIO ++}; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++static void armctrl_mask_irq(struct irq_data *d) ++#else ++static void armctrl_mask_irq(unsigned int irq) ++#endif ++{ ++ static const unsigned int disables[4] = { ++ IO_ADDRESS(ARM_IRQ_DIBL1), ++ IO_ADDRESS(ARM_IRQ_DIBL2), ++ IO_ADDRESS(ARM_IRQ_DIBL3), ++ 0 ++ }; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++ unsigned int data = (unsigned int)irq_get_chip_data(d->irq); ++#else ++ unsigned int data = (unsigned int)get_irq_chip_data(irq); ++#endif ++ writel(1 << (data & 0x1f), __io(disables[(data >> 5) & 0x3])); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++static void armctrl_unmask_irq(struct irq_data *d) ++#else ++static void armctrl_unmask_irq(unsigned int irq) ++#endif ++{ ++ static const unsigned int enables[4] = { ++ IO_ADDRESS(ARM_IRQ_ENBL1), ++ IO_ADDRESS(ARM_IRQ_ENBL2), ++ IO_ADDRESS(ARM_IRQ_ENBL3), ++ 0 ++ }; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++ unsigned int data = (unsigned int)irq_get_chip_data(d->irq); ++#else ++ unsigned int data = (unsigned int)get_irq_chip_data(irq); ++#endif ++ writel(1 << (data & 0x1f), __io(enables[(data >> 5) & 0x3])); ++} ++ ++#if defined(CONFIG_PM) ++ ++/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ ++ ++/* Static defines ++ * struct armctrl_device - VIC PM device (< 3.xx) ++ * @sysdev: The system device which is registered. (< 3.xx) ++ * @irq: The IRQ number for the base of the VIC. ++ * @base: The register base for the VIC. ++ * @resume_sources: A bitmask of interrupts for resume. ++ * @resume_irqs: The IRQs enabled for resume. ++ * @int_select: Save for VIC_INT_SELECT. ++ * @int_enable: Save for VIC_INT_ENABLE. ++ * @soft_int: Save for VIC_INT_SOFT. ++ * @protect: Save for VIC_PROTECT. ++ */ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) ++struct armctrl_device { ++ struct sys_device sysdev; ++#else ++ struct armctrl_info { ++#endif ++ void __iomem *base; ++ int irq; ++ u32 resume_sources; ++ u32 resume_irqs; ++ u32 int_select; ++ u32 int_enable; ++ u32 soft_int; ++ u32 protect; ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) ++}; ++#else ++ } armctrl; ++#endif ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) ++ ++static struct armctrl_device armctrl_devices[1]; ++ ++static inline struct armctrl_device *to_vic(struct sys_device *sys) ++{ ++ return container_of(sys, struct armctrl_device, sysdev); ++} ++ ++static int armctrl_id; ++ ++static int armctrl_class_resume(struct sys_device *dev) ++{ ++#if 0 // FIXME ++ struct armctrl_device *armctrl = to_vic(dev); ++ void __iomem *base = armctrl->base; ++ ++ printk(KERN_DEBUG "%s: resuming armctrl at %p\n", __func__, base); ++ ++ writel(armctrl->int_select, base + VIC_INT_SELECT); ++ writel(armctrl->protect, base + VIC_PROTECT); ++ ++ /* set the enabled ints and then clear the non-enabled */ ++ writel(armctrl->int_enable, base + VIC_INT_ENABLE); ++ writel(~armctrl->int_enable, base + VIC_INT_ENABLE_CLEAR); ++ ++ /* and the same for the soft-int register */ ++ ++ writel(armctrl->soft_int, base + VIC_INT_SOFT); ++ writel(~armctrl->soft_int, base + VIC_INT_SOFT_CLEAR); ++#endif ++ return 0; ++} ++ ++static int armctrl_class_suspend(struct sys_device *dev, pm_message_t state) ++{ ++#if 0 // FIXME ++ struct armctrl_device *armctrl = to_vic(dev); ++ void __iomem *base = armctrl->base; ++ ++ printk(KERN_DEBUG "%s: suspending armctrl at %p\n", __func__, base); ++ ++ armctrl->int_select = readl(base + VIC_INT_SELECT); ++ armctrl->int_enable = readl(base + VIC_INT_ENABLE); ++ armctrl->soft_int = readl(base + VIC_INT_SOFT); ++ armctrl->protect = readl(base + VIC_PROTECT); ++ ++ /* set the interrupts (if any) that are used for ++ * resuming the system */ ++ ++ writel(armctrl->resume_irqs, base + VIC_INT_ENABLE); ++ writel(~armctrl->resume_irqs, base + VIC_INT_ENABLE_CLEAR); ++#endif ++ return 0; ++} ++ ++struct sysdev_class armctrl_class = { ++ .name = "armctrl", ++ .suspend = armctrl_class_suspend, ++ .resume = armctrl_class_resume, ++}; ++ ++#endif // < 2.6.39 ++ ++static int armctrl_suspend(void) ++{ ++ return 0; ++} ++ ++static void armctrl_resume(void) ++{ ++ return; ++} ++ ++ ++/** ++ * armctrl_pm_register - Register a VIC for later power management control ++ * @base: The base address of the VIC. ++ * @irq: The base IRQ for the VIC. ++ * @resume_sources: bitmask of interrupts allowed for resume sources. ++ * ++ * For older kernels (< 3.xx) do - ++ * Register the VIC with the system device tree so that it can be notified ++ * of suspend and resume requests and ensure that the correct actions are ++ * taken to re-instate the settings on resume. ++ */ ++static void __init armctrl_pm_register(void __iomem * base, unsigned int irq, ++ u32 resume_sources) ++{ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) ++ struct armctrl_device *v; ++ ++ if (armctrl_id >= ARRAY_SIZE(armctrl_devices)) ++ printk(KERN_ERR ++ "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", ++ __func__); ++ else { ++ v = &armctrl_devices[armctrl_id]; ++ v->base = base; ++ v->resume_sources = resume_sources; ++ v->irq = irq; ++ armctrl_id++; ++ } ++#else ++ armctrl.base = base; ++ armctrl.resume_sources = resume_sources; ++ armctrl.irq = irq; ++#endif ++} ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) ++ ++/** ++ * armctrl_pm_init - initicall to register VIC pm ++ * ++ * This is called via late_initcall() to register ++ * the resources for the VICs due to the early ++ * nature of the VIC's registration. ++*/ ++static int __init armctrl_pm_init(void) ++{ ++ struct armctrl_device *dev = armctrl_devices; ++ int err; ++ int id; ++ ++ if (armctrl_id == 0) ++ return 0; ++ ++ err = sysdev_class_register(&armctrl_class); ++ if (err) { ++ printk(KERN_ERR "%s: cannot register class\n", __func__); ++ return err; ++ } ++ ++ for (id = 0; id < armctrl_id; id++, dev++) { ++ dev->sysdev.id = id; ++ dev->sysdev.cls = &armctrl_class; ++ ++ err = sysdev_register(&dev->sysdev); ++ if (err) { ++ printk(KERN_ERR "%s: failed to register device\n", ++ __func__); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++late_initcall(armctrl_pm_init); ++ ++#endif // VERSION check ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++static int armctrl_set_wake(struct irq_data *d, unsigned int on) ++#else ++static int armctrl_set_wake(unsigned int irq, unsigned int on) ++#endif ++{ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) ++ struct armctrl_device *armctrl = &armctrl_devices[0]; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++ unsigned int off = d->irq & 31; ++#else ++ unsigned int off = irq & 31; ++#endif ++ u32 bit = 1 << off; ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) ++ if (!armctrl) ++ return -EINVAL; ++ ++ if (!(bit & armctrl->resume_sources)) ++ return -EINVAL; ++ ++ if (on) ++ armctrl->resume_irqs |= bit; ++ else ++ armctrl->resume_irqs &= ~bit; ++#else ++ if (!(bit & armctrl.resume_sources)) ++ return -EINVAL; ++ ++ if (on) ++ armctrl.resume_irqs |= bit; ++ else ++ armctrl.resume_irqs &= ~bit; ++#endif ++ ++ return 0; ++} ++ ++#else ++static inline void armctrl_pm_register(void __iomem *base, unsigned int irq, ++ u32 arg1) ++{ ++} ++#define armctrl_suspend NULL ++#define armctrl_resume NULL ++#define armctrl_set_wake NULL ++#endif /* CONFIG_PM */ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39) ++ ++static struct syscore_ops armctrl_syscore_ops = { ++ .suspend = armctrl_suspend, ++ .resume = armctrl_resume, ++}; ++ ++/** ++ * armctrl_syscore_init - initicall to register VIC pm functions ++ * ++ * This is called via late_initcall() to register ++ * the resources for the VICs due to the early ++ * nature of the VIC's registration. ++*/ ++static int __init armctrl_syscore_init(void) ++{ ++ register_syscore_ops(&armctrl_syscore_ops); ++ return 0; ++} ++ ++late_initcall(armctrl_syscore_init); ++ ++#endif ++ ++static struct irq_chip armctrl_chip = { ++ .name = "ARMCTRL", ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++ .irq_ack = armctrl_mask_irq, ++ .irq_mask = armctrl_mask_irq, ++ .irq_unmask = armctrl_unmask_irq, ++ .irq_set_wake = armctrl_set_wake, ++#else ++ .ack = armctrl_mask_irq, ++ .mask = armctrl_mask_irq, ++ .unmask = armctrl_unmask_irq, ++ .set_wake = armctrl_set_wake, ++#endif ++}; ++ ++/** ++ * armctrl_init - initialise a vectored interrupt controller ++ * @base: iomem base address ++ * @irq_start: starting interrupt number, must be muliple of 32 ++ * @armctrl_sources: bitmask of interrupt sources to allow ++ * @resume_sources: bitmask of interrupt sources to allow for resume ++ */ ++int __init armctrl_init(void __iomem * base, unsigned int irq_start, ++ u32 armctrl_sources, u32 resume_sources) ++{ ++ unsigned int irq; ++ ++ for (irq = 0; irq < NR_IRQS; irq++) { ++ unsigned int data = irq; ++ if (irq >= INTERRUPT_JPEG) ++ data = remap_irqs[irq - INTERRUPT_JPEG]; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++ irq_set_chip(irq, &armctrl_chip); ++ irq_set_chip_data(irq, (void *)data); ++ irq_set_handler(irq, handle_level_irq); ++#else ++ set_irq_chip(irq, &armctrl_chip); ++ set_irq_chip_data(irq, (void *)data); ++ set_irq_handler(irq, handle_level_irq); ++#endif ++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); ++ } ++ ++ armctrl_pm_register(base, irq_start, resume_sources); ++ return 0; ++} +--- /dev/null ++++ b/arch/arm/mach-bcm2708/armctrl.h +@@ -0,0 +1,27 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/armctrl.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef __BCM2708_ARMCTRL_H ++#define __BCM2708_ARMCTRL_H ++ ++extern int __init armctrl_init(void __iomem * base, unsigned int irq_start, ++ u32 armctrl_sources, u32 resume_sources); ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -0,0 +1,657 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/bcm2708.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "bcm2708.h" ++#include "armctrl.h" ++#include "clock.h" ++ ++/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to ++ * give us IO access only to 64Mbytes of physical memory (26 bits). We could ++ * represent this window by setting our dmamasks to 26 bits but, in fact ++ * we're not going to use addresses outside this range (they're not in real ++ * memory) so we don't bother. ++ * ++ * In the future we might include code to use this IOMMU to remap other ++ * physical addresses onto VideoCore memory then the use of 32-bits would be ++ * more legitimate. ++ */ ++#define DMA_MASK_BITS_COMMON 32 ++ ++static void __init bcm2708_init_led(void); ++ ++void __init bcm2708_init_irq(void) ++{ ++ armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0); ++} ++ ++static struct map_desc bcm2708_io_desc[] __initdata = { ++ { ++ .virtual = IO_ADDRESS(ARMCTRL_BASE), ++ .pfn = __phys_to_pfn(ARMCTRL_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++ .virtual = IO_ADDRESS(UART0_BASE), ++ .pfn = __phys_to_pfn(UART0_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++ .virtual = IO_ADDRESS(UART1_BASE), ++ .pfn = __phys_to_pfn(UART1_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++#ifdef CONFIG_MMC_BCM2708 /* broadcom legacy SD */ ++ .virtual = IO_ADDRESS(MMCI0_BASE), ++ .pfn = __phys_to_pfn(MMCI0_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++#endif ++ .virtual = IO_ADDRESS(DMA_BASE), ++ .pfn = __phys_to_pfn(DMA_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++ .virtual = IO_ADDRESS(MCORE_BASE), ++ .pfn = __phys_to_pfn(MCORE_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++ .virtual = IO_ADDRESS(ST_BASE), ++ .pfn = __phys_to_pfn(ST_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++ .virtual = IO_ADDRESS(USB_BASE), ++ .pfn = __phys_to_pfn(USB_BASE), ++ .length = SZ_128K, ++ .type = MT_DEVICE ++ }, { ++ .virtual = IO_ADDRESS(PM_BASE), ++ .pfn = __phys_to_pfn(PM_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ }, { ++ .virtual = IO_ADDRESS(GPIO_BASE), ++ .pfn = __phys_to_pfn(GPIO_BASE), ++ .length = SZ_4K, ++ .type = MT_DEVICE ++ } ++}; ++ ++void __init bcm2708_map_io(void) ++{ ++ iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); ++} ++ ++unsigned long frc_clock_ticks32(void) ++{ ++ /* STC: a free running counter that increments at the rate of 1MHz */ ++ return readl(__io_address(ST_BASE+0x04)); ++} ++ ++unsigned long long frc_clock_ticks63(void) ++{ ++ unsigned long t = frc_clock_ticks32(); ++ /* For cnt32_to_63 to work correctly we MUST call this routine ++ * at least once every half-32-bit-wraparound period - that's once ++ * every 35minutes or so - using it in sched_clock() should ensure this ++ */ ++ return cnt32_to_63(t); ++} ++ ++unsigned long long sched_clock(void) ++{ ++ return 1000ull * frc_clock_ticks63(); ++} ++ ++/* ++ * These are fixed clocks. ++ */ ++static struct clk ref24_clk = { ++ .rate = 3000000, /* The UART is clocked at 3MHz via APB_CLK */ ++}; ++static struct clk osc_clk = { ++#ifdef CONFIG_ARCH_BCM2708_CHIPIT ++ .rate = 27000000, ++#else ++ .rate = 500000000, /* ARM clock is set from the VideoCore booter */ ++#endif ++}; ++/* warning - the USB needs a clock > 34MHz */ ++ ++#ifdef CONFIG_MMC_BCM2708 ++static struct clk sdhost_clk = { ++#ifdef CONFIG_ARCH_BCM2708_CHIPIT ++ .rate = 4000000, /* 4MHz */ ++#else ++ .rate = 250000000, /* 250MHz */ ++#endif ++}; ++#endif ++ ++static struct clk_lookup lookups[] = { ++ { /* UART0 */ ++ .dev_id = "dev:f1", ++ .clk = &ref24_clk, ++ }, ++ { /* USB */ ++ .dev_id = "bcm2708_usb", ++ .clk = &osc_clk, ++#ifdef CONFIG_MMC_BCM2708 ++ }, ++ { /* MCI */ ++ .dev_id = "bcm2708_mci.0", ++ .clk = &sdhost_clk, ++#endif ++ } ++}; ++ ++ ++#define UART0_IRQ { IRQ_UART, NO_IRQ } ++#define UART0_DMA { 15, 14 } ++ ++AMBA_DEVICE(uart0, "dev:f1", UART0, NULL); ++ ++static struct amba_device *amba_devs[] __initdata = { ++ &uart0_device, ++}; ++ ++static struct resource bcm2708_dmaman_resources[] = { ++ { ++ .start = DMA_BASE, ++ .end = DMA_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct platform_device bcm2708_dmaman_device = { ++ .name = BCM_DMAMAN_DRIVER_NAME, ++ .id = 0, /* first bcm2708_dma */ ++ .resource = bcm2708_dmaman_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), ++}; ++ ++#ifdef CONFIG_MMC_BCM2708 ++static struct resource bcm2708_mci_resources[] = { ++ { ++ .start = MMCI0_BASE, ++ .end = MMCI0_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_SDIO, ++ .end = IRQ_SDIO, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++ ++static struct platform_device bcm2708_mci_device = { ++ .name = "bcm2708_mci", ++ .id = 0, /* first bcm2708_mci */ ++ .resource = bcm2708_mci_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_mci_resources), ++ .dev = { ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++#endif /* CONFIG_MMC_BCM2708 */ ++ ++ ++static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_fb_device = { ++ .name = "bcm2708_fb", ++ .id = -1, /* only one bcm2708_fb */ ++ .resource = NULL, ++ .num_resources = 0, ++ .dev = { ++ .dma_mask = &fb_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ ++static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { ++ { ++ .mapbase = UART1_BASE + 0x40, ++ .irq = IRQ_AUX, ++ .uartclk = 125000000, ++ .regshift = 2, ++ .iotype = UPIO_MEM, ++ .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, ++ .type = PORT_8250, ++ }, ++ { }, ++}; ++ ++static struct platform_device bcm2708_uart1_device = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = bcm2708_uart1_platform_data, ++ }, ++}; ++ ++static struct resource bcm2708_usb_resources[] = { ++ [0] = { ++ .start = USB_BASE, ++ .end = USB_BASE + SZ_128K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IRQ_USB, ++ .end = IRQ_USB, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_usb_device = { ++ .name = "bcm2708_usb", ++ .id = -1, /* only one bcm2708_usb */ ++ .resource = bcm2708_usb_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_usb_resources), ++ .dev = { ++ .dma_mask = &usb_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ ++static struct resource bcm2708_vcio_resources[] = { ++ [0] = { /* mailbox/semaphore/doorbell access */ ++ .start = MCORE_BASE, ++ .end = MCORE_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_vcio_device = { ++ .name = BCM_VCIO_DRIVER_NAME, ++ .id = -1, /* only one VideoCore I/O area */ ++ .resource = bcm2708_vcio_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), ++ .dev = { ++ .dma_mask = &vcio_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ ++#ifdef CONFIG_BCM2708_GPIO ++#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" ++ ++static struct resource bcm2708_gpio_resources[] = { ++ [0] = { /* general purpose I/O */ ++ .start = GPIO_BASE, ++ .end = GPIO_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_gpio_device = { ++ .name = BCM_GPIO_DRIVER_NAME, ++ .id = -1, /* only one VideoCore I/O area */ ++ .resource = bcm2708_gpio_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), ++ .dev = { ++ .dma_mask = &gpio_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++#endif ++ ++#ifdef CONFIG_BCM2708_BUTTONS ++static struct resource bcm2708_vcbuttons_resources[] = { ++}; ++ ++static u64 vcbuttons_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_vcbuttons_device = { ++ .name = "bcm2708_vcbuttons", ++ .id = -1, /* only one VideoCore I/O area */ ++ .resource = bcm2708_vcbuttons_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_vcbuttons_resources), ++ .dev = { ++ .dma_mask = &vcbuttons_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++#endif ++ ++#ifdef CONFIG_BCM2708_TOUCHSCREEN ++static struct resource bcm2708_vctouch_resources[] = { ++}; ++ ++static u64 vctouch_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_vctouch_device = { ++ .name = "bcm2708_vctouch", ++ .id = -1, /* only one VideoCore I/O area */ ++ .resource = bcm2708_vctouch_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_vctouch_resources), ++ .dev = { ++ .dma_mask = &vctouch_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++#endif ++ ++static struct resource bcm2708_systemtimer_resources[] = { ++ [0] = { /* system timer access */ ++ .start = ST_BASE, ++ .end = ST_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = IRQ_TIMER3, ++ .end = IRQ_TIMER3, ++ .flags = IORESOURCE_IRQ, ++ } ++ ++ ++}; ++ ++static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++static struct platform_device bcm2708_systemtimer_device = { ++ .name = "bcm2708_systemtimer", ++ .id = -1, /* only one VideoCore I/O area */ ++ .resource = bcm2708_systemtimer_resources, ++ .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), ++ .dev = { ++ .dma_mask = &systemtimer_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), ++ }, ++}; ++ ++#ifdef CONFIG_MMC_SDHCI_BCM2708 /* Arasan emmc SD */ ++static struct resource bcm2708_emmc_resources[] = { ++ [0] = { ++ .start = EMMC_BASE, ++ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ ++ /* the memory map actually makes SZ_4K available */ ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IRQ_ARASANSDIO, ++ .end = IRQ_ARASANSDIO, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 bcm2708_emmc_dmamask = 0xffffffffUL; ++ ++struct platform_device bcm2708_emmc_device = { ++ .name = "bcm2708_sdhci", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_emmc_resources), ++ .resource = bcm2708_emmc_resources, ++ .dev = { ++ .dma_mask = &bcm2708_emmc_dmamask, ++ .coherent_dma_mask = 0xffffffffUL ++ }, ++}; ++#endif /* CONFIG_MMC_SDHCI_BCM2708 */ ++ ++static struct resource bcm2708_powerman_resources[] = { ++ [0] = { ++ .start = PM_BASE, ++ .end = PM_BASE + SZ_256 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); ++ ++struct platform_device bcm2708_powerman_device = { ++ .name = "bcm2708_powerman", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), ++ .resource = bcm2708_powerman_resources, ++ .dev = { ++ .dma_mask = &powerman_dmamask, ++ .coherent_dma_mask = 0xffffffffUL ++ }, ++}; ++ ++int __init bcm_register_device(struct platform_device *pdev) ++{ ++ int ret; ++ ++ ret = platform_device_register(pdev); ++ if (ret) ++ pr_debug("Unable to register platform device '%s': %d\n", ++ pdev->name, ret); ++ ++ return ret; ++} ++ ++void __init bcm2708_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(lookups); i++) ++ clkdev_add(&lookups[i]); ++ ++ bcm_register_device(&bcm2708_dmaman_device); ++ bcm_register_device(&bcm2708_vcio_device); ++#ifdef CONFIG_BCM2708_GPIO ++ bcm_register_device(&bcm2708_gpio_device); ++#endif ++ bcm_register_device(&bcm2708_systemtimer_device); ++#ifdef CONFIG_MMC_BCM2708 ++ bcm_register_device(&bcm2708_mci_device); ++#endif ++ bcm_register_device(&bcm2708_fb_device); ++ bcm_register_device(&bcm2708_usb_device); ++ bcm_register_device(&bcm2708_uart1_device); ++#ifdef CONFIG_BCM2708_BUTTONS ++ bcm_register_device(&bcm2708_vcbuttons_device); ++#endif ++#ifdef CONFIG_BCM2708_TOUCHSCREEN ++ bcm_register_device(&bcm2708_vctouch_device); ++#endif ++ bcm_register_device(&bcm2708_powerman_device); ++#ifdef CONFIG_MMC_SDHCI_BCM2708 ++ bcm_register_device(&bcm2708_emmc_device); ++#endif ++ bcm2708_init_led(); ++#ifdef CONFIG_BCM2708_VCMEM ++{ ++ extern void vc_mem_connected_init(void); ++ vc_mem_connected_init(); ++} ++#endif ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ struct amba_device *d = amba_devs[i]; ++ amba_device_register(d, &iomem_resource); ++ } ++} ++ ++#define TIMER_PERIOD 10000 /* HZ in microsecs */ ++ ++static void timer_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *clk) ++{ ++ unsigned long stc; ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ stc = readl(__io_address(ST_BASE+0x04)); ++ writel(stc + TIMER_PERIOD, ++ __io_address(ST_BASE+0x18));/* stc3 */ ++ break; ++ case CLOCK_EVT_MODE_ONESHOT: ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ default: ++ printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n", ++ (int)mode); ++ break; ++ } ++ ++} ++ ++static int timer_set_next_event(unsigned long evt, ++ struct clock_event_device *unused) ++{ ++ unsigned long stc; ++ ++ stc = readl(__io_address(ST_BASE + 0x04)); ++ writel(stc + TIMER_PERIOD, __io_address(ST_BASE+0x18)); /* stc3 */ ++ return 0; ++} ++ ++static struct clock_event_device timer0_clockevent = { ++ .name = "timer0", ++ .shift = 32, ++ .features = CLOCK_EVT_FEAT_ONESHOT, ++ .set_mode = timer_set_mode, ++ .set_next_event = timer_set_next_event, ++}; ++ ++/* ++ * IRQ handler for the timer ++ */ ++static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *evt = &timer0_clockevent; ++ ++ writel(1<<3, __io_address(ST_BASE+0x00)); /* stcs clear timer int */ ++ ++ evt->event_handler(evt); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction bcm2708_timer_irq = { ++ .name = "BCM2708 Timer Tick", ++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .handler = bcm2708_timer_interrupt, ++}; ++ ++/* ++ * Set up timer interrupt, and return the current time in seconds. ++ */ ++static void __init bcm2708_timer_init(void) ++{ ++ /* ++ * Initialise to a known state (all timers off) ++ */ ++ writel(0, __io_address(ARM_T_CONTROL)); ++ /* ++ * Make irqs happen for the system timer ++ */ ++ setup_irq(IRQ_TIMER3, &bcm2708_timer_irq); ++ ++ timer0_clockevent.mult = ++ div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift); ++ timer0_clockevent.max_delta_ns = ++ clockevent_delta2ns(0xffffffff, &timer0_clockevent); ++ timer0_clockevent.min_delta_ns = ++ clockevent_delta2ns(0xf, &timer0_clockevent); ++ ++ timer0_clockevent.cpumask = cpumask_of(0); ++ clockevents_register_device(&timer0_clockevent); ++} ++ ++struct sys_timer bcm2708_timer = { ++ .init = bcm2708_timer_init, ++}; ++ ++#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) ++#include ++ ++static struct gpio_led bcm2708_leds[] = { ++ [0] = { ++ .gpio = 16, ++ .name = "led0", ++ .default_trigger = "mmc0", ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_led_platform_data bcm2708_led_pdata = { ++ .num_leds = ARRAY_SIZE(bcm2708_leds), ++ .leds = bcm2708_leds, ++}; ++ ++static struct platform_device bcm2708_led_device = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev = { ++ .platform_data = &bcm2708_led_pdata, ++ }, ++}; ++ ++static void __init bcm2708_init_led(void) ++{ ++ platform_device_register(&bcm2708_led_device); ++} ++#else ++static inline void bcm2708_init_led(void) {} ++#endif ++ ++ ++MACHINE_START(BCM2708, "BCM2708") ++ /* Maintainer: Broadcom Europe Ltd. */ ++ .map_io = bcm2708_map_io, ++ .init_irq = bcm2708_init_irq, ++ .timer = &bcm2708_timer, ++ .init_machine = bcm2708_init, ++MACHINE_END +--- /dev/null ++++ b/arch/arm/mach-bcm2708/bcm2708.h +@@ -0,0 +1,51 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/bcm2708.h ++ * ++ * BCM2708 machine support header ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef __BCM2708_BCM2708_H ++#define __BCM2708_BCM2708_H ++ ++#include ++ ++extern void __init bcm2708_init(void); ++extern void __init bcm2708_init_irq(void); ++extern void __init bcm2708_map_io(void); ++extern struct sys_timer bcm2708_timer; ++extern unsigned int mmc_status(struct device *dev); ++ ++#define AMBA_DEVICE(name, busid, base, plat) \ ++static struct amba_device name##_device = { \ ++ .dev = { \ ++ .coherent_dma_mask = ~0, \ ++ .init_name = busid, \ ++ .platform_data = plat, \ ++ }, \ ++ .res = { \ ++ .start = base##_BASE, \ ++ .end = (base##_BASE) + SZ_4K - 1,\ ++ .flags = IORESOURCE_MEM, \ ++ }, \ ++ .dma_mask = ~0, \ ++ .irq = base##_IRQ, \ ++ /* .dma = base##_DMA,*/ \ ++} ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c +@@ -0,0 +1,323 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" ++#define DRIVER_NAME BCM_GPIO_DRIVER_NAME ++#define BCM_GPIO_USE_IRQ 0 ++ ++#define GPIOFSEL(x) (0x00+(x)*4) ++#define GPIOSET(x) (0x1c+(x)*4) ++#define GPIOCLR(x) (0x28+(x)*4) ++#define GPIOLEV(x) (0x34+(x)*4) ++#define GPIOEDS(x) (0x40+(x)*4) ++#define GPIOREN(x) (0x4c+(x)*4) ++#define GPIOFEN(x) (0x58+(x)*4) ++#define GPIOHEN(x) (0x64+(x)*4) ++#define GPIOLEN(x) (0x70+(x)*4) ++#define GPIOAREN(x) (0x7c+(x)*4) ++#define GPIOAFEN(x) (0x88+(x)*4) ++#define GPIOUD(x) (0x94+(x)*4) ++#define GPIOUDCLK(x) (0x98+(x)*4) ++ ++enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT, ++ GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4, ++ GPIO_FSEL_ALT0, GPIO_FSEL_ALT1, ++ GPIO_FSEL_ALT2, GPIO_FSEL_ALT3, }; ++ ++ /* Each of the two spinlocks protects a different set of hardware ++ * regiters and data structurs. This decouples the code of the IRQ from ++ * the GPIO code. This also makes the case of a GPIO routine call from ++ * the IRQ code simpler. ++ */ ++static DEFINE_SPINLOCK(lock); /* GPIO registers */ ++static DEFINE_SPINLOCK(irq_lock); /* IRQ registers */ ++ ++ ++struct bcm2708_gpio { ++ /* We use a list of bcm2708_gpio structs for each trigger IRQ in the main ++ * interrupts controller of the system. We need this to support systems ++ * in which more that one bcm2708s are connected to the same IRQ. The ISR ++ * interates through this list to find the source of the interrupt. ++ */ ++ struct list_head list; ++ ++ void __iomem *base; ++ unsigned irq_base; ++ struct gpio_chip gc; ++}; ++ ++static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, int function) ++{ ++ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); ++ unsigned long flags; ++ unsigned gpiodir; ++ unsigned gpio_bank = offset/10; ++ unsigned gpio_field_offset = (offset - 10*gpio_bank) * 3; ++ ++//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function); ++ if (offset >= ARCH_NR_GPIOS) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); ++ gpiodir &= ~(7 << gpio_field_offset); ++ gpiodir |= function << gpio_field_offset; ++ writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank)); ++ spin_unlock_irqrestore(&lock, flags); ++ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); ++ ++ return 0; ++} ++ ++ ++static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset) ++{ ++ return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT); ++} ++ ++static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value); ++static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset, int value) ++{ ++ int ret; ++ ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT); ++ if (ret >= 0) ++ bcm2708_gpio_set(gc, offset, value); ++ return ret; ++} ++ ++static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset) ++{ ++ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); ++ unsigned gpio_bank = offset/32; ++ unsigned gpio_field_offset = (offset - 32*gpio_bank); ++ unsigned lev; ++ ++ if (offset >= ARCH_NR_GPIOS) ++ return 0; ++ lev = readl(gpio->base + GPIOLEV(gpio_bank)); ++//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset)); ++ return 0x1 & (lev>>gpio_field_offset); ++} ++ ++static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) ++{ ++ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); ++ unsigned gpio_bank = offset/32; ++ unsigned gpio_field_offset = (offset - 32*gpio_bank); ++//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value); ++ if (offset >= ARCH_NR_GPIOS) ++ return; ++ if (value) ++ writel(1<base + GPIOSET(gpio_bank)); ++ else ++ writel(1<base + GPIOCLR(gpio_bank)); ++} ++ ++/* ++ * bcm2708 GPIO IRQ ++ */ ++ ++#if BCM_GPIO_USE_IRQ ++static void bcm2708_irq_disable(unsigned irq) ++{ ++ struct bcm2708_gpio *chip = get_irq_chip_data(irq); ++ //int offset = irq - gpio->irq_base; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chip->irq_lock, flags); ++ // disable gpio interrupts here ++ spin_unlock_irqrestore(&chip->irq_lock, flags); ++} ++ ++static void bcm2708_irq_enable(unsigned irq) ++{ ++ struct bcm2708_gpio *chip = get_irq_chip_data(irq); ++ //int offset = irq - chip->irq_base; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chip->irq_lock, flags); ++ // enable gpio interrupts here ++ spin_unlock_irqrestore(&chip->irq_lock, flags); ++} ++ ++static int bcm2708_irq_type(unsigned irq, unsigned trigger) ++{ ++ struct bcm2708_gpio *chip = get_irq_chip_data(irq); ++ int offset = irq - chip->irq_base; ++ unsigned long flags; ++ unsigned gpio_bank = offset/32; ++ unsigned gpio_field_offset = (offset - 32*gpio_bank); ++ unsigned gpioren, gpiofen, gpiohen, gpiolen; ++ ++ if (offset < 0 || offset >= ARCH_NR_GPIOS) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&chip->irq_lock, flags); ++ ++ gpioren = readl(chip->base + GPIOREN(gpio_bank)); ++ gpiofen = readl(chip->base + GPIOFEN(gpio_bank)); ++ gpiohen = readl(chip->base + GPIOHEN(gpio_bank)); ++ gpiolen = readl(chip->base + GPIOLEN(gpio_bank)); ++ ++ if (trigger & (IRQ_TYPE_EDGE_RISING)) ++ gpioren |= (1<base + GPIOREN(gpio_bank)); ++ writel(gpiofen, chip->base + GPIOFEN(gpio_bank)); ++ writel(gpiohen, chip->base + GPIOHEN(gpio_bank)); ++ writel(gpiolen, chip->base + GPIOLEN(gpio_bank)); ++ ++ spin_unlock_irqrestore(&chip->irq_lock, flags); ++ ++ return 0; ++} ++ ++static struct irq_chip bcm2708_irqchip = { ++ .name = "GPIO", ++ .enable = bcm2708_irq_enable, ++ .disable = bcm2708_irq_disable, ++ .set_type = bcm2708_irq_type, ++}; ++ ++static void bcm2708_irq_handler(unsigned irq, struct irq_desc *desc) ++{ ++ struct list_head *chip_list = get_irq_data(irq); ++ struct list_head *ptr; ++ struct bcm2708_gpio *chip; ++ unsigned gpio_bank; ++ ++ desc->chip->ack(irq); ++ list_for_each(ptr, chip_list) { ++ unsigned long pending; ++ int offset; ++ ++ chip = list_entry(ptr, struct bcm2708_gpio, list); ++ for (gpio_bank = 0; gpio_bank < ARCH_NR_GPIOS/32; gpio_bank++) { ++ pending = readl(chip->base + GPIOEDS(gpio_bank)); ++ writel(pending, chip->base + GPIOEDS(gpio_bank)); ++ ++ if (pending == 0) ++ continue; ++ ++ for_each_set_bit(offset, &pending, ARCH_NR_GPIOS) ++ generic_handle_irq(gpio_to_irq(offset+32*gpio_bank)); ++ } ++ } ++ desc->chip->unmask(irq); ++} ++#endif /* #if BCM_GPIO_USE_IRQ */ ++ ++static int bcm2708_gpio_probe(struct platform_device *dev) ++{ ++ struct bcm2708_gpio *ucb; ++ struct resource *res; ++ int err = 0; ++ ++ printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev); ++ ++ ucb = kzalloc(sizeof(*ucb), GFP_KERNEL); ++ if (NULL == ucb) { ++ printk(KERN_ERR DRIVER_NAME ": failed to allocate " ++ "mailbox memory\n"); ++ err = -ENOMEM; ++ goto err; ++ } ++ ++ res = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ ++ platform_set_drvdata(dev, ucb); ++ ucb->base = __io_address(GPIO_BASE); ++ ++ ucb->gc.label = "bcm2708_gpio"; ++ ucb->gc.base = 0; ++ ucb->gc.ngpio = ARCH_NR_GPIOS; ++ ucb->gc.owner = THIS_MODULE; ++ ++ ucb->gc.direction_input = bcm2708_gpio_dir_in; ++ ucb->gc.direction_output = bcm2708_gpio_dir_out; ++ ucb->gc.get = bcm2708_gpio_get; ++ ucb->gc.set = bcm2708_gpio_set; ++ ucb->gc.can_sleep = 0; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) ++ goto err; ++ ++err: ++ return err; ++ ++} ++ ++static int bcm2708_gpio_remove(struct platform_device *dev) ++{ ++ int err = 0; ++ struct bcm2708_gpio *ucb = platform_get_drvdata(dev); ++ ++ printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev); ++ ++ err = gpiochip_remove(&ucb->gc); ++ ++ platform_set_drvdata(dev, NULL); ++ kfree(ucb); ++ ++ return err; ++} ++ ++static struct platform_driver bcm2708_gpio_driver = { ++ .probe = bcm2708_gpio_probe, ++ .remove = bcm2708_gpio_remove, ++ .driver = { ++ .name = "bcm2708_gpio" ++ }, ++}; ++ ++static int __init bcm2708_gpio_init(void) ++{ ++ return platform_driver_register(&bcm2708_gpio_driver); ++} ++ ++static void __exit bcm2708_gpio_exit(void) ++{ ++ platform_driver_unregister(&bcm2708_gpio_driver); ++} ++ ++module_init(bcm2708_gpio_init); ++module_exit(bcm2708_gpio_exit); ++ ++MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver"); ++MODULE_LICENSE("GPL"); ++ +--- /dev/null ++++ b/arch/arm/mach-bcm2708/clock.c +@@ -0,0 +1,61 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/clock.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "clock.h" ++ ++int clk_enable(struct clk *clk) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(clk_enable); ++ ++void clk_disable(struct clk *clk) ++{ ++} ++EXPORT_SYMBOL(clk_disable); ++ ++unsigned long clk_get_rate(struct clk *clk) ++{ ++ return clk->rate; ++} ++EXPORT_SYMBOL(clk_get_rate); ++ ++long clk_round_rate(struct clk *clk, unsigned long rate) ++{ ++ return clk->rate; ++} ++EXPORT_SYMBOL(clk_round_rate); ++ ++int clk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ return -EIO; ++} ++EXPORT_SYMBOL(clk_set_rate); +--- /dev/null ++++ b/arch/arm/mach-bcm2708/clock.h +@@ -0,0 +1,24 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/clock.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++struct module; ++ ++struct clk { ++ unsigned long rate; ++}; +--- /dev/null ++++ b/arch/arm/mach-bcm2708/dma.c +@@ -0,0 +1,397 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/dma.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/*****************************************************************************\ ++ * * ++ * Configuration * ++ * * ++\*****************************************************************************/ ++ ++#define CACHE_LINE_MASK 31 ++#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME ++#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ ++ ++/* valid only for channels 0 - 14, 15 has its own base address */ ++#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ ++#define BCM2708_DMA_CHANIO(dma_base, n) \ ++ ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) ++ ++ ++/*****************************************************************************\ ++ * * ++ * DMA Auxilliary Functions * ++ * * ++\*****************************************************************************/ ++ ++/* A DMA buffer on an arbitrary boundary may separate a cache line into a ++ section inside the DMA buffer and another section outside it. ++ Even if we flush DMA buffers from the cache there is always the chance that ++ during a DMA someone will access the part of a cache line that is outside ++ the DMA buffer - which will then bring in unwelcome data. ++ Without being able to dictate our own buffer pools we must insist that ++ DMA buffers consist of a whole number of cache lines. ++*/ ++ ++extern int ++bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) ++{ ++ int i; ++ ++ for (i = 0; i < sg_len; i++) { ++ if (sg_ptr[i].offset & CACHE_LINE_MASK || ++ sg_ptr[i].length & CACHE_LINE_MASK) ++ return 0; ++ } ++ ++ return 1; ++} ++EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); ++ ++extern void ++bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) ++{ ++ dsb(); /* ARM data synchronization (push) operation */ ++ ++ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); ++ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); ++} ++ ++extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) ++{ ++ dsb(); ++ ++ /* ugly busy wait only option for now */ ++ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE); ++} ++ ++EXPORT_SYMBOL_GPL(bcm_dma_start); ++ ++/* Complete an ongoing DMA (assuming its results are to be ignored) ++ Does nothing if there is no DMA in progress. ++ This routine waits for the current AXI transfer to complete before ++ terminating the current DMA. If the current transfer is hung on a DREQ used ++ by an uncooperative peripheral the AXI transfer may never complete. In this ++ case the routine times out and return a non-zero error code. ++ Use of this routine doesn't guarantee that the ongoing or aborted DMA ++ does not produce an interrupt. ++*/ ++extern int ++bcm_dma_abort(void __iomem *dma_chan_base) ++{ ++ unsigned long int cs; ++ int rc = 0; ++ ++ cs = readl(dma_chan_base + BCM2708_DMA_CS); ++ ++ if (BCM2708_DMA_ACTIVE & cs) { ++ long int timeout = 10000; ++ ++ /* write 0 to the active bit - pause the DMA */ ++ writel(0, dma_chan_base + BCM2708_DMA_CS); ++ ++ /* wait for any current AXI transfer to complete */ ++ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) ++ cs = readl(dma_chan_base + BCM2708_DMA_CS); ++ ++ if (0 != (cs & BCM2708_DMA_ISPAUSED)) { ++ /* we'll un-pause when we set of our next DMA */ ++ rc = -ETIMEDOUT; ++ ++ } else if (BCM2708_DMA_ACTIVE & cs) { ++ /* terminate the control block chain */ ++ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); ++ ++ /* abort the whole DMA */ ++ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, ++ dma_chan_base + BCM2708_DMA_CS); ++ } ++ } ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_abort); ++ ++ ++/***************************************************************************** \ ++ * * ++ * DMA Manager Device Methods * ++ * * ++\*****************************************************************************/ ++ ++struct vc_dmaman { ++ void __iomem *dma_base; ++ u32 chan_available; /* bitmap of available channels */ ++ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ ++}; ++ ++static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, ++ u32 chans_available) ++{ ++ dmaman->dma_base = dma_base; ++ dmaman->chan_available = chans_available; ++ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ ++} ++ ++static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, ++ unsigned preferred_feature_set) ++{ ++ u32 chans; ++ int feature; ++ ++ chans = dmaman->chan_available; ++ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) ++ /* select the subset of available channels with the desired ++ feature so long as some of the candidate channels have that ++ feature */ ++ if ((preferred_feature_set & (1 << feature)) && ++ (chans & dmaman->has_feature[feature])) ++ chans &= dmaman->has_feature[feature]; ++ ++ if (chans) { ++ int chan = 0; ++ /* return the ordinal of the first channel in the bitmap */ ++ while (chans != 0 && (chans & 1) == 0) { ++ chans >>= 1; ++ chan++; ++ } ++ /* claim the channel */ ++ dmaman->chan_available &= ~(1 << chan); ++ return chan; ++ } else ++ return -ENOMEM; ++} ++ ++static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) ++{ ++ if (chan < 0) ++ return -EINVAL; ++ else if ((1 << chan) & dmaman->chan_available) ++ return -EIDRM; ++ else { ++ dmaman->chan_available |= (1 << chan); ++ return 0; ++ } ++} ++ ++/*****************************************************************************\ ++ * * ++ * DMA IRQs * ++ * * ++\*****************************************************************************/ ++ ++static unsigned char bcm_dma_irqs[] = { ++ IRQ_DMA0, ++ IRQ_DMA1, ++ IRQ_DMA2, ++ IRQ_DMA3, ++ IRQ_DMA4, ++ IRQ_DMA5, ++ IRQ_DMA6, ++ IRQ_DMA7, ++ IRQ_DMA8, ++ IRQ_DMA9, ++ IRQ_DMA10, ++ IRQ_DMA11, ++ IRQ_DMA12 ++}; ++ ++ ++/***************************************************************************** \ ++ * * ++ * DMA Manager Monitor * ++ * * ++\*****************************************************************************/ ++ ++static struct device *dmaman_dev; /* we assume there's only one! */ ++ ++extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, ++ void __iomem **out_dma_base, int *out_dma_irq) ++{ ++ if (!dmaman_dev) ++ return -ENODEV; ++ else { ++ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); ++ int rc; ++ ++ device_lock(dmaman_dev); ++ rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); ++ if (rc >= 0) { ++ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, ++ rc); ++ *out_dma_irq = bcm_dma_irqs[rc]; ++ } ++ device_unlock(dmaman_dev); ++ ++ return rc; ++ } ++} ++EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); ++ ++extern int bcm_dma_chan_free(int channel) ++{ ++ if (dmaman_dev) { ++ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); ++ int rc; ++ ++ device_lock(dmaman_dev); ++ rc = vc_dmaman_chan_free(dmaman, channel); ++ device_unlock(dmaman_dev); ++ ++ return rc; ++ } else ++ return -ENODEV; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_chan_free); ++ ++static int dev_dmaman_register(const char *dev_name, struct device *dev) ++{ ++ int rc = dmaman_dev ? -EINVAL : 0; ++ dmaman_dev = dev; ++ return rc; ++} ++ ++static void dev_dmaman_deregister(const char *dev_name, struct device *dev) ++{ ++ dmaman_dev = NULL; ++} ++ ++/*****************************************************************************\ ++ * * ++ * DMA Device * ++ * * ++\*****************************************************************************/ ++ ++static int dmachans = -1; /* module parameter */ ++ ++static int bcm_dmaman_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct vc_dmaman *dmaman; ++ struct resource *dma_res = NULL; ++ void __iomem *dma_base = NULL; ++ int have_dma_region = 0; ++ ++ dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); ++ if (NULL == dmaman) { ++ printk(KERN_ERR DRIVER_NAME ": failed to allocate " ++ "DMA management memory\n"); ++ ret = -ENOMEM; ++ } else { ++ ++ dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (dma_res == NULL) { ++ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " ++ "resource\n"); ++ ret = -ENODEV; ++ } else if (!request_mem_region(dma_res->start, ++ resource_size(dma_res), ++ DRIVER_NAME)) { ++ dev_err(&pdev->dev, "cannot obtain DMA region\n"); ++ ret = -EBUSY; ++ } else { ++ have_dma_region = 1; ++ dma_base = ioremap(dma_res->start, ++ resource_size(dma_res)); ++ if (!dma_base) { ++ dev_err(&pdev->dev, "cannot map DMA region\n"); ++ ret = -ENOMEM; ++ } else { ++ /* use module parameter if one was provided */ ++ if (dmachans > 0) ++ vc_dmaman_init(dmaman, dma_base, ++ dmachans); ++ else ++ vc_dmaman_init(dmaman, dma_base, ++ DEFAULT_DMACHAN_BITMAP); ++ ++ platform_set_drvdata(pdev, dmaman); ++ dev_dmaman_register(DRIVER_NAME, &pdev->dev); ++ ++ printk(KERN_INFO DRIVER_NAME ": DMA manager " ++ "at %p\n", dma_base); ++ } ++ } ++ } ++ if (ret != 0) { ++ if (dma_base) ++ iounmap(dma_base); ++ if (dma_res && have_dma_region) ++ release_mem_region(dma_res->start, ++ resource_size(dma_res)); ++ if (dmaman) ++ kfree(dmaman); ++ } ++ return ret; ++} ++ ++static int bcm_dmaman_remove(struct platform_device *pdev) ++{ ++ struct vc_dmaman *dmaman = platform_get_drvdata(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); ++ kfree(dmaman); ++ ++ return 0; ++} ++ ++static struct platform_driver bcm_dmaman_driver = { ++ .probe = bcm_dmaman_probe, ++ .remove = bcm_dmaman_remove, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++/*****************************************************************************\ ++ * * ++ * Driver init/exit * ++ * * ++\*****************************************************************************/ ++ ++static int __init bcm_dmaman_drv_init(void) ++{ ++ int ret; ++ ++ ret = platform_driver_register(&bcm_dmaman_driver); ++ if (ret != 0) { ++ printk(KERN_ERR DRIVER_NAME ": failed to register " ++ "on platform\n"); ++ } ++ ++ return ret; ++} ++ ++static void __exit bcm_dmaman_drv_exit(void) ++{ ++ platform_driver_unregister(&bcm_dmaman_driver); ++} ++ ++module_init(bcm_dmaman_drv_init); ++module_exit(bcm_dmaman_drv_exit); ++ ++module_param(dmachans, int, 0644); ++ ++MODULE_AUTHOR("Gray Girling "); ++MODULE_DESCRIPTION("DMA channel manager driver"); ++MODULE_LICENSE("GPL"); ++ ++MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/arm_control.h +@@ -0,0 +1,419 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/arm_control.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef __BCM2708_ARM_CONTROL_H ++#define __BCM2708_ARM_CONTROL_H ++ ++/* ++ * Definitions and addresses for the ARM CONTROL logic ++ * This file is manually generated. ++ */ ++ ++#define ARM_BASE 0x7E00B000 ++ ++/* Basic configuration */ ++#define ARM_CONTROL0 HW_REGISTER_RW(ARM_BASE+0x000) ++#define ARM_C0_SIZ128M 0x00000000 ++#define ARM_C0_SIZ256M 0x00000001 ++#define ARM_C0_SIZ512M 0x00000002 ++#define ARM_C0_SIZ1G 0x00000003 ++#define ARM_C0_BRESP0 0x00000000 ++#define ARM_C0_BRESP1 0x00000004 ++#define ARM_C0_BRESP2 0x00000008 ++#define ARM_C0_BOOTHI 0x00000010 ++#define ARM_C0_UNUSED05 0x00000020 /* free */ ++#define ARM_C0_FULLPERI 0x00000040 ++#define ARM_C0_UNUSED78 0x00000180 /* free */ ++#define ARM_C0_JTAGMASK 0x00000E00 ++#define ARM_C0_JTAGOFF 0x00000000 ++#define ARM_C0_JTAGBASH 0x00000800 /* Debug on GPIO off */ ++#define ARM_C0_JTAGGPIO 0x00000C00 /* Debug on GPIO on */ ++#define ARM_C0_APROTMSK 0x0000F000 ++#define ARM_C0_DBG0SYNC 0x00010000 /* VPU0 halt sync */ ++#define ARM_C0_DBG1SYNC 0x00020000 /* VPU1 halt sync */ ++#define ARM_C0_SWDBGREQ 0x00040000 /* HW debug request */ ++#define ARM_C0_PASSHALT 0x00080000 /* ARM halt passed to debugger */ ++#define ARM_C0_PRIO_PER 0x00F00000 /* per priority mask */ ++#define ARM_C0_PRIO_L2 0x0F000000 ++#define ARM_C0_PRIO_UC 0xF0000000 ++ ++#define ARM_C0_APROTPASS 0x0000A000 /* Translate 1:1 */ ++#define ARM_C0_APROTUSER 0x00000000 /* Only user mode */ ++#define ARM_C0_APROTSYST 0x0000F000 /* Only system mode */ ++ ++ ++#define ARM_CONTROL1 HW_REGISTER_RW(ARM_BASE+0x440) ++#define ARM_C1_TIMER 0x00000001 /* re-route timer IRQ to VC */ ++#define ARM_C1_MAIL 0x00000002 /* re-route Mail IRQ to VC */ ++#define ARM_C1_BELL0 0x00000004 /* re-route Doorbell 0 to VC */ ++#define ARM_C1_BELL1 0x00000008 /* re-route Doorbell 1 to VC */ ++#define ARM_C1_PERSON 0x00000100 /* peripherals on */ ++#define ARM_C1_REQSTOP 0x00000200 /* ASYNC bridge request stop */ ++ ++#define ARM_STATUS HW_REGISTER_RW(ARM_BASE+0x444) ++#define ARM_S_ACKSTOP 0x80000000 /* Bridge stopped */ ++#define ARM_S_READPEND 0x000003FF /* pending reads counter */ ++#define ARM_S_WRITPEND 0x000FFC00 /* pending writes counter */ ++ ++#define ARM_ERRHALT HW_REGISTER_RW(ARM_BASE+0x448) ++#define ARM_EH_PERIBURST 0x00000001 /* Burst write seen on peri bus */ ++#define ARM_EH_ILLADDRS1 0x00000002 /* Address bits 25-27 error */ ++#define ARM_EH_ILLADDRS2 0x00000004 /* Address bits 31-28 error */ ++#define ARM_EH_VPU0HALT 0x00000008 /* VPU0 halted & in debug mode */ ++#define ARM_EH_VPU1HALT 0x00000010 /* VPU1 halted & in debug mode */ ++#define ARM_EH_ARMHALT 0x00000020 /* ARM in halted debug mode */ ++ ++#define ARM_ID_SECURE HW_REGISTER_RW(ARM_BASE+0x00C) ++#define ARM_ID HW_REGISTER_RW(ARM_BASE+0x44C) ++#define ARM_IDVAL 0x364D5241 ++ ++/* Translation memory */ ++#define ARM_TRANSLATE HW_REGISTER_RW(ARM_BASE+0x100) ++/* 32 locations: 0x100.. 0x17F */ ++/* 32 spare means we CAN go to 64 pages.... */ ++ ++ ++/* Interrupts */ ++#define ARM_IRQ_PEND0 HW_REGISTER_RW(ARM_BASE+0x200) /* Top IRQ bits */ ++#define ARM_I0_TIMER 0x00000001 /* timer IRQ */ ++#define ARM_I0_MAIL 0x00000002 /* Mail IRQ */ ++#define ARM_I0_BELL0 0x00000004 /* Doorbell 0 */ ++#define ARM_I0_BELL1 0x00000008 /* Doorbell 1 */ ++#define ARM_I0_BANK1 0x00000100 /* Bank1 IRQ */ ++#define ARM_I0_BANK2 0x00000200 /* Bank2 IRQ */ ++ ++#define ARM_IRQ_PEND1 HW_REGISTER_RW(ARM_BASE+0x204) /* All bank1 IRQ bits */ ++/* todo: all I1_interrupt sources */ ++#define ARM_IRQ_PEND2 HW_REGISTER_RW(ARM_BASE+0x208) /* All bank2 IRQ bits */ ++/* todo: all I2_interrupt sources */ ++ ++#define ARM_IRQ_FAST HW_REGISTER_RW(ARM_BASE+0x20C) /* FIQ control */ ++#define ARM_IF_INDEX 0x0000007F /* FIQ select */ ++#define ARM_IF_ENABLE 0x00000080 /* FIQ enable */ ++#define ARM_IF_VCMASK 0x0000003F /* FIQ = (index from VC source) */ ++#define ARM_IF_TIMER 0x00000040 /* FIQ = ARM timer */ ++#define ARM_IF_MAIL 0x00000041 /* FIQ = ARM Mail */ ++#define ARM_IF_BELL0 0x00000042 /* FIQ = ARM Doorbell 0 */ ++#define ARM_IF_BELL1 0x00000043 /* FIQ = ARM Doorbell 1 */ ++#define ARM_IF_VP0HALT 0x00000044 /* FIQ = VPU0 Halt seen */ ++#define ARM_IF_VP1HALT 0x00000045 /* FIQ = VPU1 Halt seen */ ++#define ARM_IF_ILLEGAL 0x00000046 /* FIQ = Illegal access seen */ ++ ++#define ARM_IRQ_ENBL1 HW_REGISTER_RW(ARM_BASE+0x210) /* Bank1 enable bits */ ++#define ARM_IRQ_ENBL2 HW_REGISTER_RW(ARM_BASE+0x214) /* Bank2 enable bits */ ++#define ARM_IRQ_ENBL3 HW_REGISTER_RW(ARM_BASE+0x218) /* ARM irqs enable bits */ ++#define ARM_IRQ_DIBL1 HW_REGISTER_RW(ARM_BASE+0x21C) /* Bank1 disable bits */ ++#define ARM_IRQ_DIBL2 HW_REGISTER_RW(ARM_BASE+0x220) /* Bank2 disable bits */ ++#define ARM_IRQ_DIBL3 HW_REGISTER_RW(ARM_BASE+0x224) /* ARM irqs disable bits */ ++#define ARM_IE_TIMER 0x00000001 /* Timer IRQ */ ++#define ARM_IE_MAIL 0x00000002 /* Mail IRQ */ ++#define ARM_IE_BELL0 0x00000004 /* Doorbell 0 */ ++#define ARM_IE_BELL1 0x00000008 /* Doorbell 1 */ ++#define ARM_IE_VP0HALT 0x00000010 /* VPU0 Halt */ ++#define ARM_IE_VP1HALT 0x00000020 /* VPU1 Halt */ ++#define ARM_IE_ILLEGAL 0x00000040 /* Illegal access seen */ ++ ++/* Timer */ ++/* For reg. fields see sp804 spec. */ ++#define ARM_T_LOAD HW_REGISTER_RW(ARM_BASE+0x400) ++#define ARM_T_VALUE HW_REGISTER_RW(ARM_BASE+0x404) ++#define ARM_T_CONTROL HW_REGISTER_RW(ARM_BASE+0x408) ++#define ARM_T_IRQCNTL HW_REGISTER_RW(ARM_BASE+0x40C) ++#define ARM_T_RAWIRQ HW_REGISTER_RW(ARM_BASE+0x410) ++#define ARM_T_MSKIRQ HW_REGISTER_RW(ARM_BASE+0x414) ++#define ARM_T_RELOAD HW_REGISTER_RW(ARM_BASE+0x418) ++#define ARM_T_PREDIV HW_REGISTER_RW(ARM_BASE+0x41c) ++#define ARM_T_FREECNT HW_REGISTER_RW(ARM_BASE+0x420) ++ ++#define TIMER_CTRL_ONESHOT (1 << 0) ++#define TIMER_CTRL_32BIT (1 << 1) ++#define TIMER_CTRL_DIV1 (0 << 2) ++#define TIMER_CTRL_DIV16 (1 << 2) ++#define TIMER_CTRL_DIV256 (2 << 2) ++#define TIMER_CTRL_IE (1 << 5) ++#define TIMER_CTRL_PERIODIC (1 << 6) ++#define TIMER_CTRL_ENABLE (1 << 7) ++#define TIMER_CTRL_DBGHALT (1 << 8) ++#define TIMER_CTRL_ENAFREE (1 << 9) ++#define TIMER_CTRL_FREEDIV_SHIFT 16) ++#define TIMER_CTRL_FREEDIV_MASK 0xff ++ ++/* Semaphores, Doorbells, Mailboxes */ ++#define ARM_SBM_OWN0 (ARM_BASE+0x800) ++#define ARM_SBM_OWN1 (ARM_BASE+0x900) ++#define ARM_SBM_OWN2 (ARM_BASE+0xA00) ++#define ARM_SBM_OWN3 (ARM_BASE+0xB00) ++ ++/* MAILBOXES ++ * Register flags are common across all ++ * owner registers. See end of this section ++ * ++ * Semaphores, Doorbells, Mailboxes Owner 0 ++ * ++ */ ++ ++#define ARM_0_SEMS HW_REGISTER_RW(ARM_SBM_OWN0+0x00) ++#define ARM_0_SEM0 HW_REGISTER_RW(ARM_SBM_OWN0+0x00) ++#define ARM_0_SEM1 HW_REGISTER_RW(ARM_SBM_OWN0+0x04) ++#define ARM_0_SEM2 HW_REGISTER_RW(ARM_SBM_OWN0+0x08) ++#define ARM_0_SEM3 HW_REGISTER_RW(ARM_SBM_OWN0+0x0C) ++#define ARM_0_SEM4 HW_REGISTER_RW(ARM_SBM_OWN0+0x10) ++#define ARM_0_SEM5 HW_REGISTER_RW(ARM_SBM_OWN0+0x14) ++#define ARM_0_SEM6 HW_REGISTER_RW(ARM_SBM_OWN0+0x18) ++#define ARM_0_SEM7 HW_REGISTER_RW(ARM_SBM_OWN0+0x1C) ++#define ARM_0_BELL0 HW_REGISTER_RW(ARM_SBM_OWN0+0x40) ++#define ARM_0_BELL1 HW_REGISTER_RW(ARM_SBM_OWN0+0x44) ++#define ARM_0_BELL2 HW_REGISTER_RW(ARM_SBM_OWN0+0x48) ++#define ARM_0_BELL3 HW_REGISTER_RW(ARM_SBM_OWN0+0x4C) ++/* MAILBOX 0 access in Owner 0 area */ ++/* Some addresses should ONLY be used by owner 0 */ ++#define ARM_0_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) */ ++#define ARM_0_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) Normal read */ ++#define ARM_0_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN0+0x90) /* none-pop read */ ++#define ARM_0_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN0+0x94) /* Sender read (only LS 2 bits) */ ++#define ARM_0_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN0+0x98) /* Status read */ ++#define ARM_0_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0x9C) /* Config read/write */ ++/* MAILBOX 1 access in Owner 0 area */ ++/* Owner 0 should only WRITE to this mailbox */ ++#define ARM_0_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) /* .. 0xAC (4 locations) */ ++/*#define ARM_0_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_0_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN0+0xB0) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_0_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN0+0xB4) */ /* DO NOT USE THIS !!!!! */ ++#define ARM_0_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN0+0xB8) /* Status read */ ++/*#define ARM_0_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0xBC) */ /* DO NOT USE THIS !!!!! */ ++/* General SEM, BELL, MAIL config/status */ ++#define ARM_0_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE0) /* semaphore clear/debug register */ ++#define ARM_0_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE4) /* Doorbells clear/debug register */ ++#define ARM_0_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xF8) /* ALL interrupts */ ++#define ARM_0_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xFC) /* IRQS pending for owner 0 */ ++ ++/* Semaphores, Doorbells, Mailboxes Owner 1 */ ++#define ARM_1_SEMS HW_REGISTER_RW(ARM_SBM_OWN1+0x00) ++#define ARM_1_SEM0 HW_REGISTER_RW(ARM_SBM_OWN1+0x00) ++#define ARM_1_SEM1 HW_REGISTER_RW(ARM_SBM_OWN1+0x04) ++#define ARM_1_SEM2 HW_REGISTER_RW(ARM_SBM_OWN1+0x08) ++#define ARM_1_SEM3 HW_REGISTER_RW(ARM_SBM_OWN1+0x0C) ++#define ARM_1_SEM4 HW_REGISTER_RW(ARM_SBM_OWN1+0x10) ++#define ARM_1_SEM5 HW_REGISTER_RW(ARM_SBM_OWN1+0x14) ++#define ARM_1_SEM6 HW_REGISTER_RW(ARM_SBM_OWN1+0x18) ++#define ARM_1_SEM7 HW_REGISTER_RW(ARM_SBM_OWN1+0x1C) ++#define ARM_1_BELL0 HW_REGISTER_RW(ARM_SBM_OWN1+0x40) ++#define ARM_1_BELL1 HW_REGISTER_RW(ARM_SBM_OWN1+0x44) ++#define ARM_1_BELL2 HW_REGISTER_RW(ARM_SBM_OWN1+0x48) ++#define ARM_1_BELL3 HW_REGISTER_RW(ARM_SBM_OWN1+0x4C) ++/* MAILBOX 0 access in Owner 0 area */ ++/* Owner 1 should only WRITE to this mailbox */ ++#define ARM_1_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0x80) /* .. 0x8C (4 locations) */ ++/*#define ARM_1_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN1+0x80) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_1_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN1+0x90) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_1_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN1+0x94) */ /* DO NOT USE THIS !!!!! */ ++#define ARM_1_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN1+0x98) /* Status read */ ++/*#define ARM_1_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0x9C) */ /* DO NOT USE THIS !!!!! */ ++/* MAILBOX 1 access in Owner 0 area */ ++#define ARM_1_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) */ ++#define ARM_1_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) Normal read */ ++#define ARM_1_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN1+0xB0) /* none-pop read */ ++#define ARM_1_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN1+0xB4) /* Sender read (only LS 2 bits) */ ++#define ARM_1_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN1+0xB8) /* Status read */ ++#define ARM_1_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0xBC) ++/* General SEM, BELL, MAIL config/status */ ++#define ARM_1_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE0) /* semaphore clear/debug register */ ++#define ARM_1_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE4) /* Doorbells clear/debug register */ ++#define ARM_1_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xFC) /* IRQS pending for owner 1 */ ++#define ARM_1_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xF8) /* ALL interrupts */ ++ ++/* Semaphores, Doorbells, Mailboxes Owner 2 */ ++#define ARM_2_SEMS HW_REGISTER_RW(ARM_SBM_OWN2+0x00) ++#define ARM_2_SEM0 HW_REGISTER_RW(ARM_SBM_OWN2+0x00) ++#define ARM_2_SEM1 HW_REGISTER_RW(ARM_SBM_OWN2+0x04) ++#define ARM_2_SEM2 HW_REGISTER_RW(ARM_SBM_OWN2+0x08) ++#define ARM_2_SEM3 HW_REGISTER_RW(ARM_SBM_OWN2+0x0C) ++#define ARM_2_SEM4 HW_REGISTER_RW(ARM_SBM_OWN2+0x10) ++#define ARM_2_SEM5 HW_REGISTER_RW(ARM_SBM_OWN2+0x14) ++#define ARM_2_SEM6 HW_REGISTER_RW(ARM_SBM_OWN2+0x18) ++#define ARM_2_SEM7 HW_REGISTER_RW(ARM_SBM_OWN2+0x1C) ++#define ARM_2_BELL0 HW_REGISTER_RW(ARM_SBM_OWN2+0x40) ++#define ARM_2_BELL1 HW_REGISTER_RW(ARM_SBM_OWN2+0x44) ++#define ARM_2_BELL2 HW_REGISTER_RW(ARM_SBM_OWN2+0x48) ++#define ARM_2_BELL3 HW_REGISTER_RW(ARM_SBM_OWN2+0x4C) ++/* MAILBOX 0 access in Owner 2 area */ ++/* Owner 2 should only WRITE to this mailbox */ ++#define ARM_2_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0x80) /* .. 0x8C (4 locations) */ ++/*#define ARM_2_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN2+0x80) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_2_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN2+0x90) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_2_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN2+0x94) */ /* DO NOT USE THIS !!!!! */ ++#define ARM_2_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN2+0x98) /* Status read */ ++/*#define ARM_2_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0x9C) */ /* DO NOT USE THIS !!!!! */ ++/* MAILBOX 1 access in Owner 2 area */ ++/* Owner 2 should only WRITE to this mailbox */ ++#define ARM_2_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) /* .. 0xAC (4 locations) */ ++/*#define ARM_2_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_2_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN2+0xB0) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_2_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN2+0xB4) */ /* DO NOT USE THIS !!!!! */ ++#define ARM_2_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN2+0xB8) /* Status read */ ++/*#define ARM_2_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0xBC) */ /* DO NOT USE THIS !!!!! */ ++/* General SEM, BELL, MAIL config/status */ ++#define ARM_2_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE0) /* semaphore clear/debug register */ ++#define ARM_2_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE4) /* Doorbells clear/debug register */ ++#define ARM_2_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xFC) /* IRQS pending for owner 2 */ ++#define ARM_2_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xF8) /* ALL interrupts */ ++ ++/* Semaphores, Doorbells, Mailboxes Owner 3 */ ++#define ARM_3_SEMS HW_REGISTER_RW(ARM_SBM_OWN3+0x00) ++#define ARM_3_SEM0 HW_REGISTER_RW(ARM_SBM_OWN3+0x00) ++#define ARM_3_SEM1 HW_REGISTER_RW(ARM_SBM_OWN3+0x04) ++#define ARM_3_SEM2 HW_REGISTER_RW(ARM_SBM_OWN3+0x08) ++#define ARM_3_SEM3 HW_REGISTER_RW(ARM_SBM_OWN3+0x0C) ++#define ARM_3_SEM4 HW_REGISTER_RW(ARM_SBM_OWN3+0x10) ++#define ARM_3_SEM5 HW_REGISTER_RW(ARM_SBM_OWN3+0x14) ++#define ARM_3_SEM6 HW_REGISTER_RW(ARM_SBM_OWN3+0x18) ++#define ARM_3_SEM7 HW_REGISTER_RW(ARM_SBM_OWN3+0x1C) ++#define ARM_3_BELL0 HW_REGISTER_RW(ARM_SBM_OWN3+0x40) ++#define ARM_3_BELL1 HW_REGISTER_RW(ARM_SBM_OWN3+0x44) ++#define ARM_3_BELL2 HW_REGISTER_RW(ARM_SBM_OWN3+0x48) ++#define ARM_3_BELL3 HW_REGISTER_RW(ARM_SBM_OWN3+0x4C) ++/* MAILBOX 0 access in Owner 3 area */ ++/* Owner 3 should only WRITE to this mailbox */ ++#define ARM_3_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0x80) /* .. 0x8C (4 locations) */ ++/*#define ARM_3_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN3+0x80) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_3_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN3+0x90) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_3_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN3+0x94) */ /* DO NOT USE THIS !!!!! */ ++#define ARM_3_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN3+0x98) /* Status read */ ++/*#define ARM_3_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0x9C) */ /* DO NOT USE THIS !!!!! */ ++/* MAILBOX 1 access in Owner 3 area */ ++/* Owner 3 should only WRITE to this mailbox */ ++#define ARM_3_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) /* .. 0xAC (4 locations) */ ++/*#define ARM_3_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_3_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN3+0xB0) */ /* DO NOT USE THIS !!!!! */ ++/*#define ARM_3_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN3+0xB4) */ /* DO NOT USE THIS !!!!! */ ++#define ARM_3_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN3+0xB8) /* Status read */ ++/*#define ARM_3_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0xBC) */ /* DO NOT USE THIS !!!!! */ ++/* General SEM, BELL, MAIL config/status */ ++#define ARM_3_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE0) /* semaphore clear/debug register */ ++#define ARM_3_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE4) /* Doorbells clear/debug register */ ++#define ARM_3_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xFC) /* IRQS pending for owner 3 */ ++#define ARM_3_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xF8) /* ALL interrupts */ ++ ++ ++ ++/* Mailbox flags. Valid for all owners */ ++ ++/* Mailbox status register (...0x98) */ ++#define ARM_MS_FULL 0x80000000 ++#define ARM_MS_EMPTY 0x40000000 ++#define ARM_MS_LEVEL 0x400000FF /* Max. value depdnds on mailbox depth parameter */ ++ ++/* MAILBOX config/status register (...0x9C) */ ++/* ANY write to this register clears the error bits! */ ++#define ARM_MC_IHAVEDATAIRQEN 0x00000001 /* mailbox irq enable: has data */ ++#define ARM_MC_IHAVESPACEIRQEN 0x00000002 /* mailbox irq enable: has space */ ++#define ARM_MC_OPPISEMPTYIRQEN 0x00000004 /* mailbox irq enable: Opp. is empty */ ++#define ARM_MC_MAIL_CLEAR 0x00000008 /* mailbox clear write 1, then 0 */ ++#define ARM_MC_IHAVEDATAIRQPEND 0x00000010 /* mailbox irq pending: has space */ ++#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mailbox irq pending: Opp. is empty */ ++#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mailbox irq pending */ ++/* Bit 7 is unused */ ++#define ARM_MC_ERRNOOWN 0x00000100 /* error : none owner read from mailbox */ ++#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */ ++#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */ ++ ++/* Semaphore clear/debug register (...0xE0) */ ++#define ARM_SD_OWN0 0x00000003 /* Owner of sem 0 */ ++#define ARM_SD_OWN1 0x0000000C /* Owner of sem 1 */ ++#define ARM_SD_OWN2 0x00000030 /* Owner of sem 2 */ ++#define ARM_SD_OWN3 0x000000C0 /* Owner of sem 3 */ ++#define ARM_SD_OWN4 0x00000300 /* Owner of sem 4 */ ++#define ARM_SD_OWN5 0x00000C00 /* Owner of sem 5 */ ++#define ARM_SD_OWN6 0x00003000 /* Owner of sem 6 */ ++#define ARM_SD_OWN7 0x0000C000 /* Owner of sem 7 */ ++#define ARM_SD_SEM0 0x00010000 /* Status of sem 0 */ ++#define ARM_SD_SEM1 0x00020000 /* Status of sem 1 */ ++#define ARM_SD_SEM2 0x00040000 /* Status of sem 2 */ ++#define ARM_SD_SEM3 0x00080000 /* Status of sem 3 */ ++#define ARM_SD_SEM4 0x00100000 /* Status of sem 4 */ ++#define ARM_SD_SEM5 0x00200000 /* Status of sem 5 */ ++#define ARM_SD_SEM6 0x00400000 /* Status of sem 6 */ ++#define ARM_SD_SEM7 0x00800000 /* Status of sem 7 */ ++ ++/* Doorbells clear/debug register (...0xE4) */ ++#define ARM_BD_OWN0 0x00000003 /* Owner of doorbell 0 */ ++#define ARM_BD_OWN1 0x0000000C /* Owner of doorbell 1 */ ++#define ARM_BD_OWN2 0x00000030 /* Owner of doorbell 2 */ ++#define ARM_BD_OWN3 0x000000C0 /* Owner of doorbell 3 */ ++#define ARM_BD_BELL0 0x00000100 /* Status of doorbell 0 */ ++#define ARM_BD_BELL1 0x00000200 /* Status of doorbell 1 */ ++#define ARM_BD_BELL2 0x00000400 /* Status of doorbell 2 */ ++#define ARM_BD_BELL3 0x00000800 /* Status of doorbell 3 */ ++ ++/* MY IRQS register (...0xF8) */ ++#define ARM_MYIRQ_BELL 0x00000001 /* This owner has a doorbell IRQ */ ++#define ARM_MYIRQ_MAIL 0x00000002 /* This owner has a mailbox IRQ */ ++ ++/* ALL IRQS register (...0xF8) */ ++#define ARM_AIS_BELL0 0x00000001 /* Doorbell 0 IRQ pending */ ++#define ARM_AIS_BELL1 0x00000002 /* Doorbell 1 IRQ pending */ ++#define ARM_AIS_BELL2 0x00000004 /* Doorbell 2 IRQ pending */ ++#define ARM_AIS_BELL3 0x00000008 /* Doorbell 3 IRQ pending */ ++#define ARM_AIS0_HAVEDATA 0x00000010 /* MAIL 0 has data IRQ pending */ ++#define ARM_AIS0_HAVESPAC 0x00000020 /* MAIL 0 has space IRQ pending */ ++#define ARM_AIS0_OPPEMPTY 0x00000040 /* MAIL 0 opposite is empty IRQ */ ++#define ARM_AIS1_HAVEDATA 0x00000080 /* MAIL 1 has data IRQ pending */ ++#define ARM_AIS1_HAVESPAC 0x00000100 /* MAIL 1 has space IRQ pending */ ++#define ARM_AIS1_OPPEMPTY 0x00000200 /* MAIL 1 opposite is empty IRQ */ ++/* Note that bell-0, bell-1 and MAIL0 IRQ go only to the ARM */ ++/* Whilst that bell-2, bell-3 and MAIL1 IRQ go only to the VC */ ++/* */ ++/* ARM JTAG BASH */ ++/* */ ++#define AJB_BASE 0x7e2000c0 ++ ++#define AJBCONF HW_REGISTER_RW(AJB_BASE+0x00) ++#define AJB_BITS0 0x000000 ++#define AJB_BITS4 0x000004 ++#define AJB_BITS8 0x000008 ++#define AJB_BITS12 0x00000C ++#define AJB_BITS16 0x000010 ++#define AJB_BITS20 0x000014 ++#define AJB_BITS24 0x000018 ++#define AJB_BITS28 0x00001C ++#define AJB_BITS32 0x000020 ++#define AJB_BITS34 0x000022 ++#define AJB_OUT_MS 0x000040 ++#define AJB_OUT_LS 0x000000 ++#define AJB_INV_CLK 0x000080 ++#define AJB_D0_RISE 0x000100 ++#define AJB_D0_FALL 0x000000 ++#define AJB_D1_RISE 0x000200 ++#define AJB_D1_FALL 0x000000 ++#define AJB_IN_RISE 0x000400 ++#define AJB_IN_FALL 0x000000 ++#define AJB_ENABLE 0x000800 ++#define AJB_HOLD0 0x000000 ++#define AJB_HOLD1 0x001000 ++#define AJB_HOLD2 0x002000 ++#define AJB_HOLD3 0x003000 ++#define AJB_RESETN 0x004000 ++#define AJB_CLKSHFT 16 ++#define AJB_BUSY 0x80000000 ++#define AJBTMS HW_REGISTER_RW(AJB_BASE+0x04) ++#define AJBTDI HW_REGISTER_RW(AJB_BASE+0x08) ++#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/arm_power.h +@@ -0,0 +1,60 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _ARM_POWER_H ++#define _ARM_POWER_H ++ ++/* Use meaningful names on each side */ ++#ifdef __VIDEOCORE__ ++#define PREFIX(x) ARM_##x ++#else ++#define PREFIX(x) BCM_##x ++#endif ++ ++enum { ++ PREFIX(POWER_SDCARD_BIT), ++ PREFIX(POWER_UART_BIT), ++ PREFIX(POWER_MINIUART_BIT), ++ PREFIX(POWER_USB_BIT), ++ PREFIX(POWER_I2C0_BIT), ++ PREFIX(POWER_I2C1_BIT), ++ PREFIX(POWER_I2C2_BIT), ++ PREFIX(POWER_SPI_BIT), ++ PREFIX(POWER_CCP2TX_BIT), ++ ++ PREFIX(POWER_MAX) ++}; ++ ++enum { ++ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), ++ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), ++ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), ++ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), ++ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), ++ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), ++ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), ++ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), ++ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), ++ ++ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, ++ PREFIX(POWER_NONE) = 0 ++}; ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/clkdev.h +@@ -0,0 +1,7 @@ ++#ifndef __ASM_MACH_CLKDEV_H ++#define __ASM_MACH_CLKDEV_H ++ ++#define __clk_get(clk) ({ 1; }) ++#define __clk_put(clk) do { } while (0) ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/debug-macro.S +@@ -0,0 +1,24 @@ ++/* arch/arm/mach-bcm2708/include/mach/debug-macro.S ++ * ++ * Debugging macro include header ++ * ++ * Copyright (C) 2010 Broadcom ++ * Copyright (C) 1994-1999 Russell King ++ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks ++ * ++ * 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. ++ * ++*/ ++ ++ .macro addruart, rx, tmp ++ mrc p15, 0, \rx, c1, c0 ++ tst \rx, #1 @ MMU enabled? ++ moveq \rx, #0x08000000 ++ movne \rx, #0xf8000000 @ virtual base ++ orr \rx, \rx, #0x00200000 ++ orr \rx, \rx, #0x00001000 ++ .endm ++ ++#include +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/dma.h +@@ -0,0 +1,84 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/include/mach/dma.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * 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 _MACH_BCM2708_DMA_H ++#define _MACH_BCM2708_DMA_H ++ ++#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" ++ ++/* DMA CS Control and Status bits */ ++#define BCM2708_DMA_ACTIVE (1 << 0) ++#define BCM2708_DMA_INT (1 << 2) ++#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ ++#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ ++#define BCM2708_DMA_ERR (1 << 8) ++#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ ++#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ ++ ++/* DMA control block "info" field bits */ ++#define BCM2708_DMA_INT_EN (1 << 0) ++#define BCM2708_DMA_TDMODE (1 << 1) ++#define BCM2708_DMA_WAIT_RESP (1 << 3) ++#define BCM2708_DMA_D_INC (1 << 4) ++#define BCM2708_DMA_D_WIDTH (1 << 5) ++#define BCM2708_DMA_D_DREQ (1 << 6) ++#define BCM2708_DMA_S_INC (1 << 8) ++#define BCM2708_DMA_S_WIDTH (1 << 9) ++#define BCM2708_DMA_S_DREQ (1 << 10) ++ ++#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) ++#define BCM2708_DMA_PER_MAP(x) ((x) << 16) ++#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) ++ ++#define BCM2708_DMA_DREQ_EMMC 11 ++#define BCM2708_DMA_DREQ_SDHOST 13 ++ ++#define BCM2708_DMA_CS 0x00 /* Control and Status */ ++#define BCM2708_DMA_ADDR 0x04 ++/* the current control block appears in the following registers - read only */ ++#define BCM2708_DMA_INFO 0x08 ++#define BCM2708_DMA_NEXTCB 0x1C ++#define BCM2708_DMA_DEBUG 0x20 ++ ++#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) ++#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) ++ ++#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) ++ ++struct bcm2708_dma_cb { ++ unsigned long info; ++ unsigned long src; ++ unsigned long dst; ++ unsigned long length; ++ unsigned long stride; ++ unsigned long next; ++ unsigned long pad[2]; ++}; ++ ++extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); ++extern void bcm_dma_start(void __iomem *dma_chan_base, ++ dma_addr_t control_block); ++extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); ++extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); ++ ++/* When listing features we can ask for when allocating DMA channels give ++ those with higher priority smaller ordinal numbers */ ++#define BCM_DMA_FEATURE_FAST_ORD 0 ++#define BCM_DMA_FEATURE_FAST (1< ++ ++ .macro disable_fiq ++ .endm ++ ++ .macro get_irqnr_preamble, base, tmp ++ ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) ++ .endm ++ ++ .macro arch_ret_to_user, tmp1, tmp2 ++ .endm ++ ++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ++ /* get masked status */ ++ ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] ++ mov \irqnr, #(ARM_IRQ0_BASE + 31) ++ and \tmp, \irqstat, #0x300 @ save bits 8 and 9 ++ /* clear bits 8 and 9, and test */ ++ bics \irqstat, \irqstat, #0x300 ++ bne 1010f ++ ++ tst \tmp, #0x100 ++ ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] ++ movne \irqnr, #(ARM_IRQ1_BASE + 31) ++ @ Mask out the interrupts also present in PEND0 - see SW-5809 ++ bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) ++ bicne \irqstat, #((1<<18) | (1<<19)) ++ bne 1010f ++ ++ tst \tmp, #0x200 ++ ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] ++ movne \irqnr, #(ARM_IRQ2_BASE + 31) ++ @ Mask out the interrupts also present in PEND0 - see SW-5809 ++ bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) ++ bicne \irqstat, #((1<<30)) ++ beq 1020f ++ ++1010: ++ @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) ++ @ N.B. CLZ is an ARM5 instruction. ++ sub \tmp, \irqstat, #1 ++ eor \irqstat, \irqstat, \tmp ++ clz \tmp, \irqstat ++ sub \irqnr, \tmp ++ ++1020: @ EQ will be set if no irqs pending ++ ++ .endm +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/frc.h +@@ -0,0 +1,38 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/timex.h ++ * ++ * BCM2708 free running counter (timer) ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _MACH_FRC_H ++#define _MACH_FRC_H ++ ++#define FRC_TICK_RATE (1000000) ++ ++/*! Free running counter incrementing at the CLOCK_TICK_RATE ++ (slightly faster than frc_clock_ticks63() ++ */ ++extern unsigned long frc_clock_ticks32(void); ++ ++/*! Free running counter incrementing at the CLOCK_TICK_RATE ++ * Note - top bit should be ignored (see cnt32_to_63) ++ */ ++extern unsigned long long frc_clock_ticks63(void); ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/gpio.h +@@ -0,0 +1,48 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/gpio.h ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#ifndef __ASM_ARCH_GPIO_H ++#define __ASM_ARCH_GPIO_H ++ ++#define ARCH_NR_GPIOS 54 // number of gpio lines ++ ++#include ++ ++ ++#ifdef CONFIG_GPIOLIB ++ ++static inline int gpio_get_value(unsigned gpio) ++{ ++ return __gpio_get_value(gpio); ++} ++ ++static inline void gpio_set_value(unsigned gpio, int value) ++{ ++ __gpio_set_value(gpio, value); ++} ++ ++static inline int gpio_cansleep(unsigned gpio) ++{ ++ return __gpio_cansleep(gpio); ++} ++ ++static inline int gpio_to_irq(unsigned gpio) ++{ ++ WARN_ON(1); ++ return -ENOSYS; ++} ++ ++static inline int irq_to_gpio(unsigned int irq) ++{ ++ WARN_ON(1); ++ return -EINVAL; ++} ++ ++#endif /* CONFIG_GPIOLIB */ ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/hardware.h +@@ -0,0 +1,28 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/hardware.h ++ * ++ * This file contains the hardware definitions of the BCM2708 devices. ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARCH_HARDWARE_H ++#define __ASM_ARCH_HARDWARE_H ++ ++#include ++#include ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/io.h +@@ -0,0 +1,28 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/io.h ++ * ++ * Copyright (C) 2003 ARM Limited ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARM_ARCH_IO_H ++#define __ASM_ARM_ARCH_IO_H ++ ++#define IO_SPACE_LIMIT 0xffffffff ++ ++#define __io(a) __typesafe_io(a) ++#define __mem_pci(a) (a) ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/irqs.h +@@ -0,0 +1,190 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/irqs.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * Copyright (C) 2003 ARM Limited ++ * Copyright (C) 2000 Deep Blue Solutions Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _BCM2708_IRQS_H_ ++#define _BCM2708_IRQS_H_ ++ ++#include ++ ++/* ++ * IRQ interrupts definitions are the same as the INT definitions ++ * held within platform.h ++ */ ++#define IRQ_ARMCTRL_START 0 ++#define IRQ_TIMER0 (IRQ_ARMCTRL_START + INTERRUPT_TIMER0) ++#define IRQ_TIMER1 (IRQ_ARMCTRL_START + INTERRUPT_TIMER1) ++#define IRQ_TIMER2 (IRQ_ARMCTRL_START + INTERRUPT_TIMER2) ++#define IRQ_TIMER3 (IRQ_ARMCTRL_START + INTERRUPT_TIMER3) ++#define IRQ_CODEC0 (IRQ_ARMCTRL_START + INTERRUPT_CODEC0) ++#define IRQ_CODEC1 (IRQ_ARMCTRL_START + INTERRUPT_CODEC1) ++#define IRQ_CODEC2 (IRQ_ARMCTRL_START + INTERRUPT_CODEC2) ++#define IRQ_JPEG (IRQ_ARMCTRL_START + INTERRUPT_JPEG) ++#define IRQ_ISP (IRQ_ARMCTRL_START + INTERRUPT_ISP) ++#define IRQ_USB (IRQ_ARMCTRL_START + INTERRUPT_USB) ++#define IRQ_3D (IRQ_ARMCTRL_START + INTERRUPT_3D) ++#define IRQ_TRANSPOSER (IRQ_ARMCTRL_START + INTERRUPT_TRANSPOSER) ++#define IRQ_MULTICORESYNC0 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC0) ++#define IRQ_MULTICORESYNC1 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC1) ++#define IRQ_MULTICORESYNC2 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC2) ++#define IRQ_MULTICORESYNC3 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC3) ++#define IRQ_DMA0 (IRQ_ARMCTRL_START + INTERRUPT_DMA0) ++#define IRQ_DMA1 (IRQ_ARMCTRL_START + INTERRUPT_DMA1) ++#define IRQ_DMA2 (IRQ_ARMCTRL_START + INTERRUPT_DMA2) ++#define IRQ_DMA3 (IRQ_ARMCTRL_START + INTERRUPT_DMA3) ++#define IRQ_DMA4 (IRQ_ARMCTRL_START + INTERRUPT_DMA4) ++#define IRQ_DMA5 (IRQ_ARMCTRL_START + INTERRUPT_DMA5) ++#define IRQ_DMA6 (IRQ_ARMCTRL_START + INTERRUPT_DMA6) ++#define IRQ_DMA7 (IRQ_ARMCTRL_START + INTERRUPT_DMA7) ++#define IRQ_DMA8 (IRQ_ARMCTRL_START + INTERRUPT_DMA8) ++#define IRQ_DMA9 (IRQ_ARMCTRL_START + INTERRUPT_DMA9) ++#define IRQ_DMA10 (IRQ_ARMCTRL_START + INTERRUPT_DMA10) ++#define IRQ_DMA11 (IRQ_ARMCTRL_START + INTERRUPT_DMA11) ++#define IRQ_DMA12 (IRQ_ARMCTRL_START + INTERRUPT_DMA12) ++#define IRQ_AUX (IRQ_ARMCTRL_START + INTERRUPT_AUX) ++#define IRQ_ARM (IRQ_ARMCTRL_START + INTERRUPT_ARM) ++#define IRQ_VPUDMA (IRQ_ARMCTRL_START + INTERRUPT_VPUDMA) ++#define IRQ_HOSTPORT (IRQ_ARMCTRL_START + INTERRUPT_HOSTPORT) ++#define IRQ_VIDEOSCALER (IRQ_ARMCTRL_START + INTERRUPT_VIDEOSCALER) ++#define IRQ_CCP2TX (IRQ_ARMCTRL_START + INTERRUPT_CCP2TX) ++#define IRQ_SDC (IRQ_ARMCTRL_START + INTERRUPT_SDC) ++#define IRQ_DSI0 (IRQ_ARMCTRL_START + INTERRUPT_DSI0) ++#define IRQ_AVE (IRQ_ARMCTRL_START + INTERRUPT_AVE) ++#define IRQ_CAM0 (IRQ_ARMCTRL_START + INTERRUPT_CAM0) ++#define IRQ_CAM1 (IRQ_ARMCTRL_START + INTERRUPT_CAM1) ++#define IRQ_HDMI0 (IRQ_ARMCTRL_START + INTERRUPT_HDMI0) ++#define IRQ_HDMI1 (IRQ_ARMCTRL_START + INTERRUPT_HDMI1) ++#define IRQ_PIXELVALVE1 (IRQ_ARMCTRL_START + INTERRUPT_PIXELVALVE1) ++#define IRQ_I2CSPISLV (IRQ_ARMCTRL_START + INTERRUPT_I2CSPISLV) ++#define IRQ_DSI1 (IRQ_ARMCTRL_START + INTERRUPT_DSI1) ++#define IRQ_PWA0 (IRQ_ARMCTRL_START + INTERRUPT_PWA0) ++#define IRQ_PWA1 (IRQ_ARMCTRL_START + INTERRUPT_PWA1) ++#define IRQ_CPR (IRQ_ARMCTRL_START + INTERRUPT_CPR) ++#define IRQ_SMI (IRQ_ARMCTRL_START + INTERRUPT_SMI) ++#define IRQ_GPIO0 (IRQ_ARMCTRL_START + INTERRUPT_GPIO0) ++#define IRQ_GPIO1 (IRQ_ARMCTRL_START + INTERRUPT_GPIO1) ++#define IRQ_GPIO2 (IRQ_ARMCTRL_START + INTERRUPT_GPIO2) ++#define IRQ_GPIO3 (IRQ_ARMCTRL_START + INTERRUPT_GPIO3) ++#define IRQ_I2C (IRQ_ARMCTRL_START + INTERRUPT_I2C) ++#define IRQ_SPI (IRQ_ARMCTRL_START + INTERRUPT_SPI) ++#define IRQ_I2SPCM (IRQ_ARMCTRL_START + INTERRUPT_I2SPCM) ++#define IRQ_SDIO (IRQ_ARMCTRL_START + INTERRUPT_SDIO) ++#define IRQ_UART (IRQ_ARMCTRL_START + INTERRUPT_UART) ++#define IRQ_SLIMBUS (IRQ_ARMCTRL_START + INTERRUPT_SLIMBUS) ++#define IRQ_VEC (IRQ_ARMCTRL_START + INTERRUPT_VEC) ++#define IRQ_CPG (IRQ_ARMCTRL_START + INTERRUPT_CPG) ++#define IRQ_RNG (IRQ_ARMCTRL_START + INTERRUPT_RNG) ++#define IRQ_ARASANSDIO (IRQ_ARMCTRL_START + INTERRUPT_ARASANSDIO) ++#define IRQ_AVSPMON (IRQ_ARMCTRL_START + INTERRUPT_AVSPMON) ++ ++#define IRQ_ARM_TIMER (IRQ_ARMCTRL_START + INTERRUPT_ARM_TIMER) ++#define IRQ_ARM_MAILBOX (IRQ_ARMCTRL_START + INTERRUPT_ARM_MAILBOX) ++#define IRQ_ARM_DOORBELL_0 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_0) ++#define IRQ_ARM_DOORBELL_1 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_1) ++#define IRQ_VPU0_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU0_HALTED) ++#define IRQ_VPU1_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU1_HALTED) ++#define IRQ_ILLEGAL_TYPE0 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE0) ++#define IRQ_ILLEGAL_TYPE1 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE1) ++#define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1) ++#define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2) ++ ++/* ++ * FIQ interrupts definitions are the same as the INT definitions. ++ */ ++#define FIQ_TIMER0 INT_TIMER0 ++#define FIQ_TIMER1 INT_TIMER1 ++#define FIQ_TIMER2 INT_TIMER2 ++#define FIQ_TIMER3 INT_TIMER3 ++#define FIQ_CODEC0 INT_CODEC0 ++#define FIQ_CODEC1 INT_CODEC1 ++#define FIQ_CODEC2 INT_CODEC2 ++#define FIQ_JPEG INT_JPEG ++#define FIQ_ISP INT_ISP ++#define FIQ_USB INT_USB ++#define FIQ_3D INT_3D ++#define FIQ_TRANSPOSER INT_TRANSPOSER ++#define FIQ_MULTICORESYNC0 INT_MULTICORESYNC0 ++#define FIQ_MULTICORESYNC1 INT_MULTICORESYNC1 ++#define FIQ_MULTICORESYNC2 INT_MULTICORESYNC2 ++#define FIQ_MULTICORESYNC3 INT_MULTICORESYNC3 ++#define FIQ_DMA0 INT_DMA0 ++#define FIQ_DMA1 INT_DMA1 ++#define FIQ_DMA2 INT_DMA2 ++#define FIQ_DMA3 INT_DMA3 ++#define FIQ_DMA4 INT_DMA4 ++#define FIQ_DMA5 INT_DMA5 ++#define FIQ_DMA6 INT_DMA6 ++#define FIQ_DMA7 INT_DMA7 ++#define FIQ_DMA8 INT_DMA8 ++#define FIQ_DMA9 INT_DMA9 ++#define FIQ_DMA10 INT_DMA10 ++#define FIQ_DMA11 INT_DMA11 ++#define FIQ_DMA12 INT_DMA12 ++#define FIQ_AUX INT_AUX ++#define FIQ_ARM INT_ARM ++#define FIQ_VPUDMA INT_VPUDMA ++#define FIQ_HOSTPORT INT_HOSTPORT ++#define FIQ_VIDEOSCALER INT_VIDEOSCALER ++#define FIQ_CCP2TX INT_CCP2TX ++#define FIQ_SDC INT_SDC ++#define FIQ_DSI0 INT_DSI0 ++#define FIQ_AVE INT_AVE ++#define FIQ_CAM0 INT_CAM0 ++#define FIQ_CAM1 INT_CAM1 ++#define FIQ_HDMI0 INT_HDMI0 ++#define FIQ_HDMI1 INT_HDMI1 ++#define FIQ_PIXELVALVE1 INT_PIXELVALVE1 ++#define FIQ_I2CSPISLV INT_I2CSPISLV ++#define FIQ_DSI1 INT_DSI1 ++#define FIQ_PWA0 INT_PWA0 ++#define FIQ_PWA1 INT_PWA1 ++#define FIQ_CPR INT_CPR ++#define FIQ_SMI INT_SMI ++#define FIQ_GPIO0 INT_GPIO0 ++#define FIQ_GPIO1 INT_GPIO1 ++#define FIQ_GPIO2 INT_GPIO2 ++#define FIQ_GPIO3 INT_GPIO3 ++#define FIQ_I2C INT_I2C ++#define FIQ_SPI INT_SPI ++#define FIQ_I2SPCM INT_I2SPCM ++#define FIQ_SDIO INT_SDIO ++#define FIQ_UART INT_UART ++#define FIQ_SLIMBUS INT_SLIMBUS ++#define FIQ_VEC INT_VEC ++#define FIQ_CPG INT_CPG ++#define FIQ_RNG INT_RNG ++#define FIQ_ARASANSDIO INT_ARASANSDIO ++#define FIQ_AVSPMON INT_AVSPMON ++ ++#define FIQ_ARM_TIMER INT_ARM_TIMER ++#define FIQ_ARM_MAILBOX INT_ARM_MAILBOX ++#define FIQ_ARM_DOORBELL_0 INT_ARM_DOORBELL_0 ++#define FIQ_ARM_DOORBELL_1 INT_ARM_DOORBELL_1 ++#define FIQ_VPU0_HALTED INT_VPU0_HALTED ++#define FIQ_VPU1_HALTED INT_VPU1_HALTED ++#define FIQ_ILLEGAL_TYPE0 INT_ILLEGAL_TYPE0 ++#define FIQ_ILLEGAL_TYPE1 INT_ILLEGAL_TYPE1 ++#define FIQ_PENDING1 INT_PENDING1 ++#define FIQ_PENDING2 INT_PENDING2 ++ ++#define NR_IRQS (64 + 21) ++ ++#endif /* _BCM2708_IRQS_H_ */ +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/irqs.h.orig +@@ -0,0 +1,185 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/irqs.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * Copyright (C) 2003 ARM Limited ++ * Copyright (C) 2000 Deep Blue Solutions Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++ ++/* ++ * IRQ interrupts definitions are the same as the INT definitions ++ * held within platform.h ++ */ ++#define IRQ_ARMCTRL_START 0 ++#define IRQ_TIMER0 (IRQ_ARMCTRL_START + INTERRUPT_TIMER0) ++#define IRQ_TIMER1 (IRQ_ARMCTRL_START + INTERRUPT_TIMER1) ++#define IRQ_TIMER2 (IRQ_ARMCTRL_START + INTERRUPT_TIMER2) ++#define IRQ_TIMER3 (IRQ_ARMCTRL_START + INTERRUPT_TIMER3) ++#define IRQ_CODEC0 (IRQ_ARMCTRL_START + INTERRUPT_CODEC0) ++#define IRQ_CODEC1 (IRQ_ARMCTRL_START + INTERRUPT_CODEC1) ++#define IRQ_CODEC2 (IRQ_ARMCTRL_START + INTERRUPT_CODEC2) ++#define IRQ_JPEG (IRQ_ARMCTRL_START + INTERRUPT_JPEG) ++#define IRQ_ISP (IRQ_ARMCTRL_START + INTERRUPT_ISP) ++#define IRQ_USB (IRQ_ARMCTRL_START + INTERRUPT_USB) ++#define IRQ_3D (IRQ_ARMCTRL_START + INTERRUPT_3D) ++#define IRQ_TRANSPOSER (IRQ_ARMCTRL_START + INTERRUPT_TRANSPOSER) ++#define IRQ_MULTICORESYNC0 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC0) ++#define IRQ_MULTICORESYNC1 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC1) ++#define IRQ_MULTICORESYNC2 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC2) ++#define IRQ_MULTICORESYNC3 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC3) ++#define IRQ_DMA0 (IRQ_ARMCTRL_START + INTERRUPT_DMA0) ++#define IRQ_DMA1 (IRQ_ARMCTRL_START + INTERRUPT_DMA1) ++#define IRQ_DMA2 (IRQ_ARMCTRL_START + INTERRUPT_DMA2) ++#define IRQ_DMA3 (IRQ_ARMCTRL_START + INTERRUPT_DMA3) ++#define IRQ_DMA4 (IRQ_ARMCTRL_START + INTERRUPT_DMA4) ++#define IRQ_DMA5 (IRQ_ARMCTRL_START + INTERRUPT_DMA5) ++#define IRQ_DMA6 (IRQ_ARMCTRL_START + INTERRUPT_DMA6) ++#define IRQ_DMA7 (IRQ_ARMCTRL_START + INTERRUPT_DMA7) ++#define IRQ_DMA8 (IRQ_ARMCTRL_START + INTERRUPT_DMA8) ++#define IRQ_DMA9 (IRQ_ARMCTRL_START + INTERRUPT_DMA9) ++#define IRQ_DMA10 (IRQ_ARMCTRL_START + INTERRUPT_DMA10) ++#define IRQ_DMA11 (IRQ_ARMCTRL_START + INTERRUPT_DMA11) ++#define IRQ_DMA12 (IRQ_ARMCTRL_START + INTERRUPT_DMA12) ++#define IRQ_AUX (IRQ_ARMCTRL_START + INTERRUPT_AUX) ++#define IRQ_ARM (IRQ_ARMCTRL_START + INTERRUPT_ARM) ++#define IRQ_VPUDMA (IRQ_ARMCTRL_START + INTERRUPT_VPUDMA) ++#define IRQ_HOSTPORT (IRQ_ARMCTRL_START + INTERRUPT_HOSTPORT) ++#define IRQ_VIDEOSCALER (IRQ_ARMCTRL_START + INTERRUPT_VIDEOSCALER) ++#define IRQ_CCP2TX (IRQ_ARMCTRL_START + INTERRUPT_CCP2TX) ++#define IRQ_SDC (IRQ_ARMCTRL_START + INTERRUPT_SDC) ++#define IRQ_DSI0 (IRQ_ARMCTRL_START + INTERRUPT_DSI0) ++#define IRQ_AVE (IRQ_ARMCTRL_START + INTERRUPT_AVE) ++#define IRQ_CAM0 (IRQ_ARMCTRL_START + INTERRUPT_CAM0) ++#define IRQ_CAM1 (IRQ_ARMCTRL_START + INTERRUPT_CAM1) ++#define IRQ_HDMI0 (IRQ_ARMCTRL_START + INTERRUPT_HDMI0) ++#define IRQ_HDMI1 (IRQ_ARMCTRL_START + INTERRUPT_HDMI1) ++#define IRQ_PIXELVALVE1 (IRQ_ARMCTRL_START + INTERRUPT_PIXELVALVE1) ++#define IRQ_I2CSPISLV (IRQ_ARMCTRL_START + INTERRUPT_I2CSPISLV) ++#define IRQ_DSI1 (IRQ_ARMCTRL_START + INTERRUPT_DSI1) ++#define IRQ_PWA0 (IRQ_ARMCTRL_START + INTERRUPT_PWA0) ++#define IRQ_PWA1 (IRQ_ARMCTRL_START + INTERRUPT_PWA1) ++#define IRQ_CPR (IRQ_ARMCTRL_START + INTERRUPT_CPR) ++#define IRQ_SMI (IRQ_ARMCTRL_START + INTERRUPT_SMI) ++#define IRQ_GPIO0 (IRQ_ARMCTRL_START + INTERRUPT_GPIO0) ++#define IRQ_GPIO1 (IRQ_ARMCTRL_START + INTERRUPT_GPIO1) ++#define IRQ_GPIO2 (IRQ_ARMCTRL_START + INTERRUPT_GPIO2) ++#define IRQ_GPIO3 (IRQ_ARMCTRL_START + INTERRUPT_GPIO3) ++#define IRQ_I2C (IRQ_ARMCTRL_START + INTERRUPT_I2C) ++#define IRQ_SPI (IRQ_ARMCTRL_START + INTERRUPT_SPI) ++#define IRQ_I2SPCM (IRQ_ARMCTRL_START + INTERRUPT_I2SPCM) ++#define IRQ_SDIO (IRQ_ARMCTRL_START + INTERRUPT_SDIO) ++#define IRQ_UART (IRQ_ARMCTRL_START + INTERRUPT_UART) ++#define IRQ_SLIMBUS (IRQ_ARMCTRL_START + INTERRUPT_SLIMBUS) ++#define IRQ_VEC (IRQ_ARMCTRL_START + INTERRUPT_VEC) ++#define IRQ_CPG (IRQ_ARMCTRL_START + INTERRUPT_CPG) ++#define IRQ_RNG (IRQ_ARMCTRL_START + INTERRUPT_RNG) ++#define IRQ_ARASANSDIO (IRQ_ARMCTRL_START + INTERRUPT_ARASANSDIO) ++#define IRQ_AVSPMON (IRQ_ARMCTRL_START + INTERRUPT_AVSPMON) ++ ++#define IRQ_ARM_TIMER (IRQ_ARMCTRL_START + INTERRUPT_ARM_TIMER) ++#define IRQ_ARM_MAILBOX (IRQ_ARMCTRL_START + INTERRUPT_ARM_MAILBOX) ++#define IRQ_ARM_DOORBELL_0 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_0) ++#define IRQ_ARM_DOORBELL_1 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_1) ++#define IRQ_VPU0_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU0_HALTED) ++#define IRQ_VPU1_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU1_HALTED) ++#define IRQ_ILLEGAL_TYPE0 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE0) ++#define IRQ_ILLEGAL_TYPE1 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE1) ++#define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1) ++#define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2) ++ ++/* ++ * FIQ interrupts definitions are the same as the INT definitions. ++ */ ++#define FIQ_TIMER0 INT_TIMER0 ++#define FIQ_TIMER1 INT_TIMER1 ++#define FIQ_TIMER2 INT_TIMER2 ++#define FIQ_TIMER3 INT_TIMER3 ++#define FIQ_CODEC0 INT_CODEC0 ++#define FIQ_CODEC1 INT_CODEC1 ++#define FIQ_CODEC2 INT_CODEC2 ++#define FIQ_JPEG INT_JPEG ++#define FIQ_ISP INT_ISP ++#define FIQ_USB INT_USB ++#define FIQ_3D INT_3D ++#define FIQ_TRANSPOSER INT_TRANSPOSER ++#define FIQ_MULTICORESYNC0 INT_MULTICORESYNC0 ++#define FIQ_MULTICORESYNC1 INT_MULTICORESYNC1 ++#define FIQ_MULTICORESYNC2 INT_MULTICORESYNC2 ++#define FIQ_MULTICORESYNC3 INT_MULTICORESYNC3 ++#define FIQ_DMA0 INT_DMA0 ++#define FIQ_DMA1 INT_DMA1 ++#define FIQ_DMA2 INT_DMA2 ++#define FIQ_DMA3 INT_DMA3 ++#define FIQ_DMA4 INT_DMA4 ++#define FIQ_DMA5 INT_DMA5 ++#define FIQ_DMA6 INT_DMA6 ++#define FIQ_DMA7 INT_DMA7 ++#define FIQ_DMA8 INT_DMA8 ++#define FIQ_DMA9 INT_DMA9 ++#define FIQ_DMA10 INT_DMA10 ++#define FIQ_DMA11 INT_DMA11 ++#define FIQ_DMA12 INT_DMA12 ++#define FIQ_AUX INT_AUX ++#define FIQ_ARM INT_ARM ++#define FIQ_VPUDMA INT_VPUDMA ++#define FIQ_HOSTPORT INT_HOSTPORT ++#define FIQ_VIDEOSCALER INT_VIDEOSCALER ++#define FIQ_CCP2TX INT_CCP2TX ++#define FIQ_SDC INT_SDC ++#define FIQ_DSI0 INT_DSI0 ++#define FIQ_AVE INT_AVE ++#define FIQ_CAM0 INT_CAM0 ++#define FIQ_CAM1 INT_CAM1 ++#define FIQ_HDMI0 INT_HDMI0 ++#define FIQ_HDMI1 INT_HDMI1 ++#define FIQ_PIXELVALVE1 INT_PIXELVALVE1 ++#define FIQ_I2CSPISLV INT_I2CSPISLV ++#define FIQ_DSI1 INT_DSI1 ++#define FIQ_PWA0 INT_PWA0 ++#define FIQ_PWA1 INT_PWA1 ++#define FIQ_CPR INT_CPR ++#define FIQ_SMI INT_SMI ++#define FIQ_GPIO0 INT_GPIO0 ++#define FIQ_GPIO1 INT_GPIO1 ++#define FIQ_GPIO2 INT_GPIO2 ++#define FIQ_GPIO3 INT_GPIO3 ++#define FIQ_I2C INT_I2C ++#define FIQ_SPI INT_SPI ++#define FIQ_I2SPCM INT_I2SPCM ++#define FIQ_SDIO INT_SDIO ++#define FIQ_UART INT_UART ++#define FIQ_SLIMBUS INT_SLIMBUS ++#define FIQ_VEC INT_VEC ++#define FIQ_CPG INT_CPG ++#define FIQ_RNG INT_RNG ++#define FIQ_ARASANSDIO INT_ARASANSDIO ++#define FIQ_AVSPMON INT_AVSPMON ++ ++#define FIQ_ARM_TIMER INT_ARM_TIMER ++#define FIQ_ARM_MAILBOX INT_ARM_MAILBOX ++#define FIQ_ARM_DOORBELL_0 INT_ARM_DOORBELL_0 ++#define FIQ_ARM_DOORBELL_1 INT_ARM_DOORBELL_1 ++#define FIQ_VPU0_HALTED INT_VPU0_HALTED ++#define FIQ_VPU1_HALTED INT_VPU1_HALTED ++#define FIQ_ILLEGAL_TYPE0 INT_ILLEGAL_TYPE0 ++#define FIQ_ILLEGAL_TYPE1 INT_ILLEGAL_TYPE1 ++#define FIQ_PENDING1 INT_PENDING1 ++#define FIQ_PENDING2 INT_PENDING2 ++ ++#define NR_IRQS (64 + 21) +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/memory.h +@@ -0,0 +1,59 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/memory.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARCH_MEMORY_H ++#define __ASM_ARCH_MEMORY_H ++ ++/* Memory overview: ++ ++ [ARMcore] <--virtual addr--> ++ [ARMmmu] <--physical addr--> ++ [GERTmap] <--bus add--> ++ [VCperiph] ++ ++*/ ++ ++/* ++ * Physical DRAM offset. ++ */ ++#define PHYS_OFFSET UL(0x00000000) ++#define ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ ++#define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ ++ ++/* We're using the memory at 64M in the VideoCore for Linux - this adjustment ++ * will provide the offset into this area as well as setting the bits that ++ * stop the L1 and L2 cache from being used ++ * ++ * WARNING: this only works because the ARM is given memory at a fixed location ++ * (ARMMEM_OFFSET) ++ */ ++#define BUS_OFFSET (ARMMEM_OFFSET + _REAL_BUS_OFFSET) ++#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) ++#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) ++#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET)) ++#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET)) ++ ++/* ++ * Consistent DMA area set to 2M. Framebuffer now allocated on host ++ */ ++ ++ ++#define CONSISTENT_DMA_SIZE 0x00200000 ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/platform.h +@@ -0,0 +1,210 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/platform.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _BCM2708_PLATFORM_H ++#define _BCM2708_PLATFORM_H ++ ++ ++/* macros to get at IO space when running virtually */ ++#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) ++ ++#define __io_address(a) __io(IO_ADDRESS(a)) ++ ++ ++/* ++ * SDRAM ++ */ ++#define BCM2708_SDRAM_BASE 0x00000000 ++ ++/* ++ * Logic expansion modules ++ * ++ */ ++ ++ ++/* ------------------------------------------------------------------------ ++ * BCM2708 ARMCTRL Registers ++ * ------------------------------------------------------------------------ ++ */ ++ ++#define HW_REGISTER_RW(addr) (addr) ++#define HW_REGISTER_RO(addr) (addr) ++ ++#include "arm_control.h" ++#undef ARM_BASE ++ ++/* ++ * Definitions and addresses for the ARM CONTROL logic ++ * This file is manually generated. ++ */ ++ ++#define BCM2708_PERI_BASE 0x20000000 ++#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ ++#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ ++#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ ++#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ ++#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ ++#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ ++#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ ++#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ ++#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ ++#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ ++#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ ++#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ ++ ++#define ARMCTRL_BASE (ARM_BASE + 0x000) ++#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ ++#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ ++#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ ++ ++ ++/* ++ * Interrupt assignments ++ */ ++ ++#define ARM_IRQ1_BASE 0 ++#define INTERRUPT_TIMER0 (ARM_IRQ1_BASE + 0) ++#define INTERRUPT_TIMER1 (ARM_IRQ1_BASE + 1) ++#define INTERRUPT_TIMER2 (ARM_IRQ1_BASE + 2) ++#define INTERRUPT_TIMER3 (ARM_IRQ1_BASE + 3) ++#define INTERRUPT_CODEC0 (ARM_IRQ1_BASE + 4) ++#define INTERRUPT_CODEC1 (ARM_IRQ1_BASE + 5) ++#define INTERRUPT_CODEC2 (ARM_IRQ1_BASE + 6) ++#define INTERRUPT_VC_JPEG (ARM_IRQ1_BASE + 7) ++#define INTERRUPT_ISP (ARM_IRQ1_BASE + 8) ++#define INTERRUPT_VC_USB (ARM_IRQ1_BASE + 9) ++#define INTERRUPT_VC_3D (ARM_IRQ1_BASE + 10) ++#define INTERRUPT_TRANSPOSER (ARM_IRQ1_BASE + 11) ++#define INTERRUPT_MULTICORESYNC0 (ARM_IRQ1_BASE + 12) ++#define INTERRUPT_MULTICORESYNC1 (ARM_IRQ1_BASE + 13) ++#define INTERRUPT_MULTICORESYNC2 (ARM_IRQ1_BASE + 14) ++#define INTERRUPT_MULTICORESYNC3 (ARM_IRQ1_BASE + 15) ++#define INTERRUPT_DMA0 (ARM_IRQ1_BASE + 16) ++#define INTERRUPT_DMA1 (ARM_IRQ1_BASE + 17) ++#define INTERRUPT_VC_DMA2 (ARM_IRQ1_BASE + 18) ++#define INTERRUPT_VC_DMA3 (ARM_IRQ1_BASE + 19) ++#define INTERRUPT_DMA4 (ARM_IRQ1_BASE + 20) ++#define INTERRUPT_DMA5 (ARM_IRQ1_BASE + 21) ++#define INTERRUPT_DMA6 (ARM_IRQ1_BASE + 22) ++#define INTERRUPT_DMA7 (ARM_IRQ1_BASE + 23) ++#define INTERRUPT_DMA8 (ARM_IRQ1_BASE + 24) ++#define INTERRUPT_DMA9 (ARM_IRQ1_BASE + 25) ++#define INTERRUPT_DMA10 (ARM_IRQ1_BASE + 26) ++#define INTERRUPT_DMA11 (ARM_IRQ1_BASE + 27) ++#define INTERRUPT_DMA12 (ARM_IRQ1_BASE + 28) ++#define INTERRUPT_AUX (ARM_IRQ1_BASE + 29) ++#define INTERRUPT_ARM (ARM_IRQ1_BASE + 30) ++#define INTERRUPT_VPUDMA (ARM_IRQ1_BASE + 31) ++ ++#define ARM_IRQ2_BASE 32 ++#define INTERRUPT_HOSTPORT (ARM_IRQ2_BASE + 0) ++#define INTERRUPT_VIDEOSCALER (ARM_IRQ2_BASE + 1) ++#define INTERRUPT_CCP2TX (ARM_IRQ2_BASE + 2) ++#define INTERRUPT_SDC (ARM_IRQ2_BASE + 3) ++#define INTERRUPT_DSI0 (ARM_IRQ2_BASE + 4) ++#define INTERRUPT_AVE (ARM_IRQ2_BASE + 5) ++#define INTERRUPT_CAM0 (ARM_IRQ2_BASE + 6) ++#define INTERRUPT_CAM1 (ARM_IRQ2_BASE + 7) ++#define INTERRUPT_HDMI0 (ARM_IRQ2_BASE + 8) ++#define INTERRUPT_HDMI1 (ARM_IRQ2_BASE + 9) ++#define INTERRUPT_PIXELVALVE1 (ARM_IRQ2_BASE + 10) ++#define INTERRUPT_I2CSPISLV (ARM_IRQ2_BASE + 11) ++#define INTERRUPT_DSI1 (ARM_IRQ2_BASE + 12) ++#define INTERRUPT_PWA0 (ARM_IRQ2_BASE + 13) ++#define INTERRUPT_PWA1 (ARM_IRQ2_BASE + 14) ++#define INTERRUPT_CPR (ARM_IRQ2_BASE + 15) ++#define INTERRUPT_SMI (ARM_IRQ2_BASE + 16) ++#define INTERRUPT_GPIO0 (ARM_IRQ2_BASE + 17) ++#define INTERRUPT_GPIO1 (ARM_IRQ2_BASE + 18) ++#define INTERRUPT_GPIO2 (ARM_IRQ2_BASE + 19) ++#define INTERRUPT_GPIO3 (ARM_IRQ2_BASE + 20) ++#define INTERRUPT_VC_I2C (ARM_IRQ2_BASE + 21) ++#define INTERRUPT_VC_SPI (ARM_IRQ2_BASE + 22) ++#define INTERRUPT_VC_I2SPCM (ARM_IRQ2_BASE + 23) ++#define INTERRUPT_VC_SDIO (ARM_IRQ2_BASE + 24) ++#define INTERRUPT_VC_UART (ARM_IRQ2_BASE + 25) ++#define INTERRUPT_SLIMBUS (ARM_IRQ2_BASE + 26) ++#define INTERRUPT_VEC (ARM_IRQ2_BASE + 27) ++#define INTERRUPT_CPG (ARM_IRQ2_BASE + 28) ++#define INTERRUPT_RNG (ARM_IRQ2_BASE + 29) ++#define INTERRUPT_VC_ARASANSDIO (ARM_IRQ2_BASE + 30) ++#define INTERRUPT_AVSPMON (ARM_IRQ2_BASE + 31) ++ ++#define ARM_IRQ0_BASE 64 ++#define INTERRUPT_ARM_TIMER (ARM_IRQ0_BASE + 0) ++#define INTERRUPT_ARM_MAILBOX (ARM_IRQ0_BASE + 1) ++#define INTERRUPT_ARM_DOORBELL_0 (ARM_IRQ0_BASE + 2) ++#define INTERRUPT_ARM_DOORBELL_1 (ARM_IRQ0_BASE + 3) ++#define INTERRUPT_VPU0_HALTED (ARM_IRQ0_BASE + 4) ++#define INTERRUPT_VPU1_HALTED (ARM_IRQ0_BASE + 5) ++#define INTERRUPT_ILLEGAL_TYPE0 (ARM_IRQ0_BASE + 6) ++#define INTERRUPT_ILLEGAL_TYPE1 (ARM_IRQ0_BASE + 7) ++#define INTERRUPT_PENDING1 (ARM_IRQ0_BASE + 8) ++#define INTERRUPT_PENDING2 (ARM_IRQ0_BASE + 9) ++#define INTERRUPT_JPEG (ARM_IRQ0_BASE + 10) ++#define INTERRUPT_USB (ARM_IRQ0_BASE + 11) ++#define INTERRUPT_3D (ARM_IRQ0_BASE + 12) ++#define INTERRUPT_DMA2 (ARM_IRQ0_BASE + 13) ++#define INTERRUPT_DMA3 (ARM_IRQ0_BASE + 14) ++#define INTERRUPT_I2C (ARM_IRQ0_BASE + 15) ++#define INTERRUPT_SPI (ARM_IRQ0_BASE + 16) ++#define INTERRUPT_I2SPCM (ARM_IRQ0_BASE + 17) ++#define INTERRUPT_SDIO (ARM_IRQ0_BASE + 18) ++#define INTERRUPT_UART (ARM_IRQ0_BASE + 19) ++#define INTERRUPT_ARASANSDIO (ARM_IRQ0_BASE + 20) ++ ++#define MAXIRQNUM (32 + 32 + 20) ++#define MAXFIQNUM (32 + 32 + 20) ++ ++#define MAX_TIMER 2 ++#define MAX_PERIOD 699050 ++#define TICKS_PER_uSEC 1 ++ ++/* ++ * These are useconds NOT ticks. ++ * ++ */ ++#define mSEC_1 1000 ++#define mSEC_5 (mSEC_1 * 5) ++#define mSEC_10 (mSEC_1 * 10) ++#define mSEC_25 (mSEC_1 * 25) ++#define SEC_1 (mSEC_1 * 1000) ++ ++/* ++ * Watchdog ++ */ ++#define PM_RSTC (PM_BASE+0x1c) ++#define PM_WDOG (PM_BASE+0x24) ++ ++#define PM_WDOG_RESET 0000000000 ++#define PM_PASSWORD 0x5a000000 ++#define PM_WDOG_TIME_SET 0x000fffff ++#define PM_RSTC_WRCFG_CLR 0xffffffcf ++#define PM_RSTC_WRCFG_SET 0x00000030 ++#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 ++#define PM_RSTC_RESET 0x00000102 ++ ++ ++ ++ ++ ++#endif ++ ++/* END */ +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/platform.h.orig +@@ -0,0 +1,210 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/platform.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _BCM2708_PLATFORM_H ++#define _BCM2708_PLATFORM_H ++ ++ ++/* macros to get at IO space when running virtually */ ++#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) ++ ++#define __io_address(a) __io(IO_ADDRESS(a)) ++ ++ ++/* ++ * SDRAM ++ */ ++#define BCM2708_SDRAM_BASE 0x00000000 ++ ++/* ++ * Logic expansion modules ++ * ++ */ ++ ++ ++/* ------------------------------------------------------------------------ ++ * BCM2708 ARMCTRL Registers ++ * ------------------------------------------------------------------------ ++ */ ++ ++#define HW_REGISTER_RW(addr) (addr) ++#define HW_REGISTER_RO(addr) (addr) ++ ++#include "arm_control.h" ++#undef ARM_BASE ++ ++/* ++ * Definitions and addresses for the ARM CONTROL logic ++ * This file is manually generated. ++ */ ++ ++#define BCM2708_PERI_BASE 0x20000000 ++#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ ++#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ ++#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ ++#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ ++#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ ++#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ ++#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ ++#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ ++#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ ++#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ ++#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ ++ ++ ++#define ARMCTRL_BASE (ARM_BASE + 0x000) ++#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ ++#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ ++#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ ++ ++ ++/* ++ * Interrupt assignments ++ */ ++ ++#define ARM_IRQ1_BASE 0 ++#define INTERRUPT_TIMER0 (ARM_IRQ1_BASE + 0) ++#define INTERRUPT_TIMER1 (ARM_IRQ1_BASE + 1) ++#define INTERRUPT_TIMER2 (ARM_IRQ1_BASE + 2) ++#define INTERRUPT_TIMER3 (ARM_IRQ1_BASE + 3) ++#define INTERRUPT_CODEC0 (ARM_IRQ1_BASE + 4) ++#define INTERRUPT_CODEC1 (ARM_IRQ1_BASE + 5) ++#define INTERRUPT_CODEC2 (ARM_IRQ1_BASE + 6) ++#define INTERRUPT_VC_JPEG (ARM_IRQ1_BASE + 7) ++#define INTERRUPT_ISP (ARM_IRQ1_BASE + 8) ++#define INTERRUPT_VC_USB (ARM_IRQ1_BASE + 9) ++#define INTERRUPT_VC_3D (ARM_IRQ1_BASE + 10) ++#define INTERRUPT_TRANSPOSER (ARM_IRQ1_BASE + 11) ++#define INTERRUPT_MULTICORESYNC0 (ARM_IRQ1_BASE + 12) ++#define INTERRUPT_MULTICORESYNC1 (ARM_IRQ1_BASE + 13) ++#define INTERRUPT_MULTICORESYNC2 (ARM_IRQ1_BASE + 14) ++#define INTERRUPT_MULTICORESYNC3 (ARM_IRQ1_BASE + 15) ++#define INTERRUPT_DMA0 (ARM_IRQ1_BASE + 16) ++#define INTERRUPT_DMA1 (ARM_IRQ1_BASE + 17) ++#define INTERRUPT_VC_DMA2 (ARM_IRQ1_BASE + 18) ++#define INTERRUPT_VC_DMA3 (ARM_IRQ1_BASE + 19) ++#define INTERRUPT_DMA4 (ARM_IRQ1_BASE + 20) ++#define INTERRUPT_DMA5 (ARM_IRQ1_BASE + 21) ++#define INTERRUPT_DMA6 (ARM_IRQ1_BASE + 22) ++#define INTERRUPT_DMA7 (ARM_IRQ1_BASE + 23) ++#define INTERRUPT_DMA8 (ARM_IRQ1_BASE + 24) ++#define INTERRUPT_DMA9 (ARM_IRQ1_BASE + 25) ++#define INTERRUPT_DMA10 (ARM_IRQ1_BASE + 26) ++#define INTERRUPT_DMA11 (ARM_IRQ1_BASE + 27) ++#define INTERRUPT_DMA12 (ARM_IRQ1_BASE + 28) ++#define INTERRUPT_AUX (ARM_IRQ1_BASE + 29) ++#define INTERRUPT_ARM (ARM_IRQ1_BASE + 30) ++#define INTERRUPT_VPUDMA (ARM_IRQ1_BASE + 31) ++ ++#define ARM_IRQ2_BASE 32 ++#define INTERRUPT_HOSTPORT (ARM_IRQ2_BASE + 0) ++#define INTERRUPT_VIDEOSCALER (ARM_IRQ2_BASE + 1) ++#define INTERRUPT_CCP2TX (ARM_IRQ2_BASE + 2) ++#define INTERRUPT_SDC (ARM_IRQ2_BASE + 3) ++#define INTERRUPT_DSI0 (ARM_IRQ2_BASE + 4) ++#define INTERRUPT_AVE (ARM_IRQ2_BASE + 5) ++#define INTERRUPT_CAM0 (ARM_IRQ2_BASE + 6) ++#define INTERRUPT_CAM1 (ARM_IRQ2_BASE + 7) ++#define INTERRUPT_HDMI0 (ARM_IRQ2_BASE + 8) ++#define INTERRUPT_HDMI1 (ARM_IRQ2_BASE + 9) ++#define INTERRUPT_PIXELVALVE1 (ARM_IRQ2_BASE + 10) ++#define INTERRUPT_I2CSPISLV (ARM_IRQ2_BASE + 11) ++#define INTERRUPT_DSI1 (ARM_IRQ2_BASE + 12) ++#define INTERRUPT_PWA0 (ARM_IRQ2_BASE + 13) ++#define INTERRUPT_PWA1 (ARM_IRQ2_BASE + 14) ++#define INTERRUPT_CPR (ARM_IRQ2_BASE + 15) ++#define INTERRUPT_SMI (ARM_IRQ2_BASE + 16) ++#define INTERRUPT_GPIO0 (ARM_IRQ2_BASE + 17) ++#define INTERRUPT_GPIO1 (ARM_IRQ2_BASE + 18) ++#define INTERRUPT_GPIO2 (ARM_IRQ2_BASE + 19) ++#define INTERRUPT_GPIO3 (ARM_IRQ2_BASE + 20) ++#define INTERRUPT_VC_I2C (ARM_IRQ2_BASE + 21) ++#define INTERRUPT_VC_SPI (ARM_IRQ2_BASE + 22) ++#define INTERRUPT_VC_I2SPCM (ARM_IRQ2_BASE + 23) ++#define INTERRUPT_VC_SDIO (ARM_IRQ2_BASE + 24) ++#define INTERRUPT_VC_UART (ARM_IRQ2_BASE + 25) ++#define INTERRUPT_SLIMBUS (ARM_IRQ2_BASE + 26) ++#define INTERRUPT_VEC (ARM_IRQ2_BASE + 27) ++#define INTERRUPT_CPG (ARM_IRQ2_BASE + 28) ++#define INTERRUPT_RNG (ARM_IRQ2_BASE + 29) ++#define INTERRUPT_VC_ARASANSDIO (ARM_IRQ2_BASE + 30) ++#define INTERRUPT_AVSPMON (ARM_IRQ2_BASE + 31) ++ ++#define ARM_IRQ0_BASE 64 ++#define INTERRUPT_ARM_TIMER (ARM_IRQ0_BASE + 0) ++#define INTERRUPT_ARM_MAILBOX (ARM_IRQ0_BASE + 1) ++#define INTERRUPT_ARM_DOORBELL_0 (ARM_IRQ0_BASE + 2) ++#define INTERRUPT_ARM_DOORBELL_1 (ARM_IRQ0_BASE + 3) ++#define INTERRUPT_VPU0_HALTED (ARM_IRQ0_BASE + 4) ++#define INTERRUPT_VPU1_HALTED (ARM_IRQ0_BASE + 5) ++#define INTERRUPT_ILLEGAL_TYPE0 (ARM_IRQ0_BASE + 6) ++#define INTERRUPT_ILLEGAL_TYPE1 (ARM_IRQ0_BASE + 7) ++#define INTERRUPT_PENDING1 (ARM_IRQ0_BASE + 8) ++#define INTERRUPT_PENDING2 (ARM_IRQ0_BASE + 9) ++#define INTERRUPT_JPEG (ARM_IRQ0_BASE + 10) ++#define INTERRUPT_USB (ARM_IRQ0_BASE + 11) ++#define INTERRUPT_3D (ARM_IRQ0_BASE + 12) ++#define INTERRUPT_DMA2 (ARM_IRQ0_BASE + 13) ++#define INTERRUPT_DMA3 (ARM_IRQ0_BASE + 14) ++#define INTERRUPT_I2C (ARM_IRQ0_BASE + 15) ++#define INTERRUPT_SPI (ARM_IRQ0_BASE + 16) ++#define INTERRUPT_I2SPCM (ARM_IRQ0_BASE + 17) ++#define INTERRUPT_SDIO (ARM_IRQ0_BASE + 18) ++#define INTERRUPT_UART (ARM_IRQ0_BASE + 19) ++#define INTERRUPT_ARASANSDIO (ARM_IRQ0_BASE + 20) ++ ++#define MAXIRQNUM (32 + 32 + 20) ++#define MAXFIQNUM (32 + 32 + 20) ++ ++#define MAX_TIMER 2 ++#define MAX_PERIOD 699050 ++#define TICKS_PER_uSEC 1 ++ ++/* ++ * These are useconds NOT ticks. ++ * ++ */ ++#define mSEC_1 1000 ++#define mSEC_5 (mSEC_1 * 5) ++#define mSEC_10 (mSEC_1 * 10) ++#define mSEC_25 (mSEC_1 * 25) ++#define SEC_1 (mSEC_1 * 1000) ++ ++/* ++ * Watchdog ++ */ ++#define PM_RSTC (PM_BASE+0x1c) ++#define PM_WDOG (PM_BASE+0x24) ++ ++#define PM_WDOG_RESET 0000000000 ++#define PM_PASSWORD 0x5a000000 ++#define PM_WDOG_TIME_SET 0x000fffff ++#define PM_RSTC_WRCFG_CLR 0xffffffcf ++#define PM_RSTC_WRCFG_SET 0x00000030 ++#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 ++#define PM_RSTC_RESET 0x00000102 ++ ++ ++ ++ ++ ++#endif ++ ++/* END */ +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/power.h +@@ -0,0 +1,26 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/power.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * 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. ++ * ++ * This device provides a shared mechanism for controlling the power to ++ * VideoCore subsystems. ++ */ ++ ++#ifndef _MACH_BCM2708_POWER_H ++#define _MACH_BCM2708_POWER_H ++ ++#include ++#include ++ ++typedef unsigned int BCM_POWER_HANDLE_T; ++ ++extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); ++extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); ++extern int bcm_power_close(BCM_POWER_HANDLE_T handle); ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/system.h +@@ -0,0 +1,53 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/system.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * Copyright (C) 2003 ARM Limited ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARCH_SYSTEM_H ++#define __ASM_ARCH_SYSTEM_H ++ ++#include ++#include ++#include ++ ++static inline void arch_idle(void) ++{ ++ /* ++ * This should do all the clock switching ++ * and wait for interrupt tricks ++ */ ++ cpu_do_idle(); ++} ++ ++static inline void arch_reset(char mode, const char *cmd) ++{ ++ uint32_t pm_rstc, pm_wdog; ++ uint32_t timeout = 10; ++ ++ /* Setup watchdog for reset */ ++ pm_rstc = readl(IO_ADDRESS(PM_RSTC)); ++ ++ pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) ++ pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; ++ ++ writel(pm_wdog, IO_ADDRESS(PM_WDOG)); ++ writel(pm_rstc, IO_ADDRESS(PM_RSTC)); ++} ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/timex.h +@@ -0,0 +1,23 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/timex.h ++ * ++ * BCM2708 sysem clock frequency ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#define CLOCK_TICK_RATE (1000000) +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/uncompress.h +@@ -0,0 +1,49 @@ ++/* ++ * arch/arm/mach-bcn2708/include/mach/uncompress.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * Copyright (C) 2003 ARM Limited ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++ ++#define BCM2708_UART_DR __io_address(UART0_BASE + 0x00) ++#define BCM2708_UART_FR __io_address(UART0_BASE + 0x18) ++ ++/* ++ * This does not append a newline ++ */ ++static inline void putc(int c) ++{ ++ while (readl(BCM2708_UART_FR) & (1 << 5)) ++ barrier(); ++ ++ writel(c, BCM2708_UART_DR); ++} ++ ++static inline void flush(void) ++{ ++ while (readl(BCM2708_UART_FR) & (1 << 3)) ++ barrier(); ++} ++ ++/* ++ * nothing to do ++ */ ++#define arch_decomp_setup() ++#define arch_decomp_wdog() +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/vc_mem.h +@@ -0,0 +1,34 @@ ++/***************************************************************************** ++* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#if !defined( VC_MEM_H ) ++#define VC_MEM_H ++ ++#include ++ ++#define VC_MEM_IOC_MAGIC 'v' ++ ++#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) ++#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) ++ ++#if defined( __KERNEL__ ) ++#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF ++ ++extern unsigned long mm_vc_mem_phys_addr; ++extern unsigned int mm_vc_mem_size; ++extern int vc_mem_get_current_size( void ); ++#endif ++ ++#endif /* VC_MEM_H */ ++ +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/vcio.h +@@ -0,0 +1,42 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/vcio.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef _MACH_BCM2708_VCIO_H ++#define _MACH_BCM2708_VCIO_H ++ ++/* Routines to handle I/O via the VideoCore "ARM control" registers ++ * (semaphores, doorbells, mailboxes) ++ */ ++ ++#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" ++ ++/* Constants shared with the ARM identifying separate mailbox channels */ ++#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ ++#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ ++#define MBOX_CHAN_VUART 2 /* for use by the virtual UART */ ++#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ ++#define MBOX_CHAN_LEDS 4 /* for use by the leds interface */ ++#define MBOX_CHAN_BUTTONS 5 /* for use by the buttons interface */ ++#define MBOX_CHAN_TOUCH 6 /* for use by the touchscreen interface */ ++#define MBOX_CHAN_COUNT 7 ++ ++extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); ++extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); ++ ++#endif +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/vmalloc.h +@@ -0,0 +1,20 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/vmalloc.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#define VMALLOC_END (0xd8000000) +--- /dev/null ++++ b/arch/arm/mach-bcm2708/power.c +@@ -0,0 +1,193 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/power.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * 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. ++ * ++ * This device provides a shared mechanism for controlling the power to ++ * VideoCore subsystems. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "bcm2708_power" ++ ++#define BCM_POWER_MAXCLIENTS 4 ++#define BCM_POWER_NOCLIENT (1<<31) ++ ++/* Some drivers expect there devices to be permanently powered */ ++#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) ++ ++#if 1 ++#define DPRINTK printk ++#else ++#define DPRINTK if (0) printk ++#endif ++ ++struct state_struct { ++ uint32_t global_request; ++ uint32_t client_request[BCM_POWER_MAXCLIENTS]; ++ struct semaphore client_mutex; ++ struct semaphore mutex; ++} g_state; ++ ++int bcm_power_open(BCM_POWER_HANDLE_T *handle) ++{ ++ BCM_POWER_HANDLE_T i; ++ int ret = -EBUSY; ++ ++ down(&g_state.client_mutex); ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { ++ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { ++ g_state.client_request[i] = BCM_POWER_NONE; ++ *handle = i; ++ ret = 0; ++ break; ++ } ++ } ++ ++ up(&g_state.client_mutex); ++ ++ DPRINTK("bcm_power_open() -> %d\n", *handle); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(bcm_power_open); ++ ++int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) ++{ ++ int rc = 0; ++ ++ DPRINTK("bcm_power_request(%d, %x)\n", handle, request); ++ ++ if ((handle < BCM_POWER_MAXCLIENTS) && ++ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { ++ if (down_interruptible(&g_state.mutex) != 0) { ++ DPRINTK("bcm_power_request -> interrupted\n"); ++ return -EINTR; ++ } ++ ++ if (request != g_state.client_request[handle]) { ++ uint32_t others_request = 0; ++ uint32_t global_request; ++ BCM_POWER_HANDLE_T i; ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { ++ if (i != handle) ++ others_request |= ++ g_state.client_request[i]; ++ } ++ others_request &= ~BCM_POWER_NOCLIENT; ++ ++ global_request = request | others_request; ++ if (global_request != g_state.global_request) { ++ uint32_t actual; ++ ++ /* Send a request to VideoCore */ ++ bcm_mailbox_write(MBOX_CHAN_POWER, ++ global_request << 4); ++ ++ /* Wait for a response during power-up */ ++ if (global_request & ~g_state.global_request) { ++ rc = bcm_mailbox_read(MBOX_CHAN_POWER, ++ &actual); ++ DPRINTK ++ ("bcm_mailbox_read -> %08x, %d\n", ++ actual, rc); ++ actual >>= 4; ++ } else { ++ rc = 0; ++ actual = global_request; ++ } ++ ++ if (rc == 0) { ++ if (actual != global_request) { ++ printk(KERN_ERR ++ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", ++ __func__, ++ g_state.global_request, ++ global_request, actual, request, others_request); ++ /* A failure */ ++ BUG_ON((others_request & actual) ++ != others_request); ++ request &= actual; ++ rc = -EIO; ++ } ++ ++ g_state.global_request = actual; ++ g_state.client_request[handle] = ++ request; ++ } ++ } ++ } ++ up(&g_state.mutex); ++ } else { ++ rc = -EINVAL; ++ } ++ DPRINTK("bcm_power_request -> %d\n", rc); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_power_request); ++ ++int bcm_power_close(BCM_POWER_HANDLE_T handle) ++{ ++ int rc; ++ ++ DPRINTK("bcm_power_close(%d)\n", handle); ++ ++ rc = bcm_power_request(handle, BCM_POWER_NONE); ++ if (rc == 0) ++ g_state.client_request[handle] = BCM_POWER_NOCLIENT; ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(bcm_power_close); ++ ++static int __init bcm_power_init(void) ++{ ++#if defined(BCM_POWER_ALWAYS_ON) ++ BCM_POWER_HANDLE_T always_on_handle; ++#endif ++ int rc = 0; ++ int i; ++ ++ printk(KERN_INFO "bcm_power: Broadcom power driver\n"); ++ ++ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) ++ g_state.client_request[i] = BCM_POWER_NOCLIENT; ++ ++ sema_init(&g_state.client_mutex, 1); ++ sema_init(&g_state.mutex, 1); ++ ++ g_state.global_request = 0; ++ ++#if defined(BCM_POWER_ALWAYS_ON) ++ if (BCM_POWER_ALWAYS_ON) { ++ bcm_power_open(&always_on_handle); ++ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); ++ } ++#endif ++ ++ return rc; ++} ++ ++static void __exit bcm_power_exit(void) ++{ ++ bcm_mailbox_write(MBOX_CHAN_POWER, 0); ++} ++ ++arch_initcall(bcm_power_init); /* Initialize early */ ++module_exit(bcm_power_exit); ++ ++MODULE_AUTHOR("Phil Elwell"); ++MODULE_DESCRIPTION("Interface to BCM2708 power management"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/arch/arm/mach-bcm2708/vc_mem.c +@@ -0,0 +1,467 @@ ++/***************************************************************************** ++* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_ARCH_KONA ++#include ++#elif CONFIG_ARCH_BCM2708 ++#else ++#include ++#endif ++ ++#include "mach/vc_mem.h" ++//#include "interface/vchiq_arm/vchiq_connected.h" ++ ++#define DRIVER_NAME "vc-mem" ++ ++// Uncomment to enable debug logging ++//#define ENABLE_DBG ++ ++#if defined(ENABLE_DBG) ++#define LOG_DBG( fmt, ... ) printk( KERN_INFO fmt "\n", ##__VA_ARGS__ ) ++#else ++#define LOG_DBG( fmt, ... ) ++#endif ++#define LOG_ERR( fmt, ... ) printk( KERN_ERR fmt "\n", ##__VA_ARGS__ ) ++ ++// Device (/dev) related variables ++static dev_t vc_mem_devnum = 0; ++static struct class *vc_mem_class = NULL; ++static struct cdev vc_mem_cdev; ++static int vc_mem_inited = 0; ++ ++// Proc entry ++static struct proc_dir_entry *vc_mem_proc_entry; ++ ++/* ++ * Videocore memory addresses and size ++ * ++ * Drivers that wish to know the videocore memory addresses and sizes should ++ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in ++ * headers. This allows the other drivers to not be tied down to a a certain ++ * address/size at compile time. ++ * ++ * In the future, the goal is to have the videocore memory virtual address and ++ * size be calculated at boot time rather than at compile time. The decision of ++ * where the videocore memory resides and its size would be in the hands of the ++ * bootloader (and/or kernel). When that happens, the values of these variables ++ * would be calculated and assigned in the init function. ++ */ ++#ifdef CONFIG_ARCH_KONA ++ ++#include ++unsigned long mm_vc_mem_phys_addr = VC_EMI; ++ ++#elif CONFIG_ARCH_BCM2708 ++ ++// in the 2835 VC in mapped above ARM, but ARM has full access to VC space ++unsigned long mm_vc_mem_phys_addr = 0x00000000; ++ ++#else ++ ++#include ++unsigned long mm_vc_mem_phys_addr = MM_ADDR_IO_VC_EMI; ++ ++#endif ++ ++unsigned int mm_vc_mem_size = 0; ++ ++EXPORT_SYMBOL(mm_vc_mem_phys_addr); ++EXPORT_SYMBOL(mm_vc_mem_size); ++ ++/**************************************************************************** ++* ++* vc_mem_open ++* ++***************************************************************************/ ++ ++static int ++vc_mem_open(struct inode *inode, struct file *file) ++{ ++ (void) inode; ++ (void) file; ++ ++ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ ++ return 0; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_release ++* ++***************************************************************************/ ++ ++static int ++vc_mem_release(struct inode *inode, struct file *file) ++{ ++ (void) inode; ++ (void) file; ++ ++ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ ++ return 0; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_size ++* ++***************************************************************************/ ++ ++static void ++vc_mem_get_size(void) ++{ ++#ifdef CONFIG_ARCH_BCM2708 ++ mm_vc_mem_size = 256 * 1024 * 1024; // Static for now ++#else ++ CHAL_IPC_HANDLE ipc_handle; ++ uint32_t wakeup_register; ++ ++ // Get the videocore memory size from the IPC mailbox if not yet ++ // assigned. ++ if (mm_vc_mem_size == 0) { ++ ipc_handle = chal_ipc_config(NULL); ++ if (ipc_handle == NULL) { ++ LOG_ERR("%s: failed to get IPC handlle", __func__); ++ return; ++ } ++ ++ chal_ipc_query_wakeup_vc(ipc_handle, &wakeup_register); ++ if ((wakeup_register & ~1) == 0) { ++ LOG_DBG("%s: videocore not yet loaded, skipping...", ++ __func__); ++ } else { ++ if (chal_ipc_read_mailbox(ipc_handle, ++ IPC_MAILBOX_ID_0, ++ &mm_vc_mem_size) != ++ BCM_SUCCESS) { ++ LOG_ERR("%s: failed to read from IPC mailbox", ++ __func__); ++ } ++ } ++ } ++#endif ++} ++ ++/**************************************************************************** ++* ++* vc_mem_get_current_size ++* ++***************************************************************************/ ++ ++int ++vc_mem_get_current_size(void) ++{ ++ vc_mem_get_size(); ++ return mm_vc_mem_size; ++} ++ ++EXPORT_SYMBOL_GPL(vc_mem_get_current_size); ++ ++/**************************************************************************** ++* ++* vc_mem_ioctl ++* ++***************************************************************************/ ++ ++static long ++vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ int rc = 0; ++ ++ (void) cmd; ++ (void) arg; ++ ++ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ ++ switch (cmd) { ++ case VC_MEM_IOC_MEM_PHYS_ADDR: ++ { ++ LOG_DBG("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p", ++ __func__, (void *) mm_vc_mem_phys_addr); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, ++ sizeof (mm_vc_mem_phys_addr)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ case VC_MEM_IOC_MEM_SIZE: ++ { ++ // Get the videocore memory size first ++ vc_mem_get_size(); ++ ++ LOG_DBG("%s: VC_MEM_IOC_MEM_SIZE=%u", __func__, ++ mm_vc_mem_size); ++ ++ if (copy_to_user((void *) arg, &mm_vc_mem_size, ++ sizeof (mm_vc_mem_size)) != 0) { ++ rc = -EFAULT; ++ } ++ break; ++ } ++ default: ++ { ++ return -ENOTTY; ++ } ++ } ++ LOG_DBG("%s: file = 0x%p returning %d", __func__, file, rc); ++ ++ return rc; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_mmap ++* ++***************************************************************************/ ++ ++static int ++vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ int rc = 0; ++ unsigned long length = vma->vm_end - vma->vm_start; ++ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; ++ ++ LOG_DBG("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx", ++ __func__, (long) vma->vm_start, (long) vma->vm_end, ++ (long) vma->vm_pgoff); ++ ++ if (offset + length > mm_vc_mem_size) { ++ LOG_ERR("%s: length %ld is too big", __func__, length); ++ return -EINVAL; ++ } ++ // Do not cache the memory map ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ ++ rc = remap_pfn_range(vma, vma->vm_start, ++ (mm_vc_mem_phys_addr >> PAGE_SHIFT) + ++ vma->vm_pgoff, length, vma->vm_page_prot); ++ if (rc != 0) { ++ LOG_ERR("%s: remap_pfn_range failed (rc=%d)", __func__, rc); ++ } ++ ++ return rc; ++} ++ ++/**************************************************************************** ++* ++* File Operations for the driver. ++* ++***************************************************************************/ ++ ++static const struct file_operations vc_mem_fops = { ++ .owner = THIS_MODULE, ++ .open = vc_mem_open, ++ .release = vc_mem_release, ++ .unlocked_ioctl = vc_mem_ioctl, ++ .mmap = vc_mem_mmap, ++}; ++ ++/**************************************************************************** ++* ++* vc_mem_proc_read ++* ++***************************************************************************/ ++ ++static int ++vc_mem_proc_read(char *buf, char **start, off_t offset, int count, int *eof, ++ void *data) ++{ ++ char *p = buf; ++ ++ (void) start; ++ (void) count; ++ (void) data; ++ ++ if (offset > 0) { ++ *eof = 1; ++ return 0; ++ } ++ // Get the videocore memory size first ++ vc_mem_get_size(); ++ ++ p += sprintf(p, "Videocore memory:\n"); ++ if (mm_vc_mem_phys_addr != 0) ++ p += sprintf(p, " Physical address: 0x%p\n", ++ (void *) mm_vc_mem_phys_addr); ++ else ++ p += sprintf(p, " Physical address: 0x00000000\n"); ++ p += sprintf(p, " Length (bytes): %u\n", mm_vc_mem_size); ++ ++ *eof = 1; ++ return p - buf; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_proc_write ++* ++***************************************************************************/ ++ ++static int ++vc_mem_proc_write(struct file *file, const char __user * buffer, ++ unsigned long count, void *data) ++{ ++ int rc = -EFAULT; ++ char input_str[10]; ++ ++ memset(input_str, 0, sizeof (input_str)); ++ ++ if (count > sizeof (input_str)) { ++ LOG_ERR("%s: input string length too long", __func__); ++ goto out; ++ } ++ ++ if (copy_from_user(input_str, buffer, count - 1)) { ++ LOG_ERR("%s: failed to get input string", __func__); ++ goto out; ++ } ++ ++ if (strncmp(input_str, "connect", strlen("connect")) == 0) { ++ // Get the videocore memory size from the videocore ++ vc_mem_get_size(); ++ } ++ ++ out: ++ return rc; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_connected_init ++* ++* This function is called once the videocore has been connected. ++* ++***************************************************************************/ ++ ++void ++vc_mem_connected_init(void) ++{ ++ int rc = -EFAULT; ++ struct device *dev; ++ ++ LOG_DBG("%s: called", __func__); ++ ++ vc_mem_get_size(); ++ ++ printk("vc-mem: mm_vc_mem_phys_addr = 0x%08lx\n", mm_vc_mem_phys_addr); ++ printk("vc-mem: mm_vc_mem_size = 0x%08x (%u MiB)\n", ++ mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); ++ ++ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { ++ LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc); ++ goto out_err; ++ } ++ ++ cdev_init(&vc_mem_cdev, &vc_mem_fops); ++ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { ++ LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc); ++ goto out_unregister; ++ } ++ ++ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); ++ if (IS_ERR(vc_mem_class)) { ++ rc = PTR_ERR(vc_mem_class); ++ LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc); ++ goto out_cdev_del; ++ } ++ ++ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, ++ DRIVER_NAME); ++ if (IS_ERR(dev)) { ++ rc = PTR_ERR(dev); ++ LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc); ++ goto out_class_destroy; ++ } ++ ++ vc_mem_proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL); ++ if (vc_mem_proc_entry == NULL) { ++ rc = -EFAULT; ++ LOG_ERR("%s: create_proc_entry failed", __func__); ++ goto out_device_destroy; ++ } ++ vc_mem_proc_entry->read_proc = vc_mem_proc_read; ++ vc_mem_proc_entry->write_proc = vc_mem_proc_write; ++ ++ vc_mem_inited = 1; ++ return; ++ ++ out_device_destroy: ++ device_destroy(vc_mem_class, vc_mem_devnum); ++ ++ out_class_destroy: ++ class_destroy(vc_mem_class); ++ vc_mem_class = NULL; ++ ++ out_cdev_del: ++ cdev_del(&vc_mem_cdev); ++ ++ out_unregister: ++ unregister_chrdev_region(vc_mem_devnum, 1); ++ ++ out_err: ++ return; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_init ++* ++***************************************************************************/ ++ ++static int __init ++vc_mem_init(void) ++{ ++ printk(KERN_INFO "vc-mem: Videocore memory driver\n"); ++ ++ //vchiq_add_connected_callback(vc_mem_connected_init); ++ ++ return 0; ++} ++ ++/**************************************************************************** ++* ++* vc_mem_exit ++* ++***************************************************************************/ ++ ++static void __exit ++vc_mem_exit(void) ++{ ++ LOG_DBG("%s: called", __func__); ++ ++ if (vc_mem_inited) { ++ remove_proc_entry(vc_mem_proc_entry->name, NULL); ++ device_destroy(vc_mem_class, vc_mem_devnum); ++ class_destroy(vc_mem_class); ++ cdev_del(&vc_mem_cdev); ++ unregister_chrdev_region(vc_mem_devnum, 1); ++ } ++} ++ ++module_init(vc_mem_init); ++module_exit(vc_mem_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Broadcom Corporation"); +--- /dev/null ++++ b/arch/arm/mach-bcm2708/vcio.c +@@ -0,0 +1,309 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/vcio.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * 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. ++ * ++ * This device provides a shared mechanism for writing to the mailboxes, ++ * semaphores, doorbells etc. that are shared between the ARM and the ++ * VideoCore processor ++ */ ++ ++#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++#define SUPPORT_SYSRQ ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#define DRIVER_NAME BCM_VCIO_DRIVER_NAME ++ ++/* ---------------------------------------------------------------------- ++ * Mailbox ++ * -------------------------------------------------------------------- */ ++ ++/* offsets from a mail box base address */ ++#define MAIL_WRT 0x00 /* write - and next 4 words */ ++#define MAIL_RD 0x00 /* read - and next 4 words */ ++#define MAIL_POL 0x10 /* read without popping the fifo */ ++#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ ++#define MAIL_STA 0x18 /* status */ ++#define MAIL_CNF 0x1C /* configuration */ ++ ++#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) ++#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) ++#define MBOX_CHAN(msg) ((msg) & 0xf) ++#define MBOX_DATA28(msg) ((msg) & ~0xf) ++#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) ++ ++#define MBOX_MAGIC 0xd0d0c0de ++ ++struct vc_mailbox { ++ struct device *dev; /* parent device */ ++ void __iomem *status; ++ void __iomem *config; ++ void __iomem *read; ++ void __iomem *write; ++ uint32_t msg[MBOX_CHAN_COUNT]; ++ struct semaphore sema[MBOX_CHAN_COUNT]; ++ uint32_t magic; ++}; ++ ++static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, ++ uint32_t addr_mbox) ++{ ++ int i; ++ ++ mbox_out->dev = dev; ++ mbox_out->status = __io_address(addr_mbox + MAIL_STA); ++ mbox_out->config = __io_address(addr_mbox + MAIL_CNF); ++ mbox_out->read = __io_address(addr_mbox + MAIL_RD); ++ /* Write to the other mailbox */ ++ mbox_out->write = ++ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + ++ MAIL_WRT); ++ ++ for (i = 0; i < MBOX_CHAN_COUNT; i++) { ++ mbox_out->msg[i] = 0; ++ sema_init(&mbox_out->sema[i], 0); ++ } ++ ++ /* Enable the interrupt on data reception */ ++ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); ++ ++ mbox_out->magic = MBOX_MAGIC; ++} ++ ++static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) ++{ ++ int rc; ++ ++ if (mbox->magic != MBOX_MAGIC) ++ rc = -EINVAL; ++ else { ++ /* wait for the mailbox FIFO to have some space in it */ ++ while (0 != (readl(mbox->status) & ARM_MS_FULL)) ++ cpu_relax(); ++ ++ writel(MBOX_MSG(chan, data28), mbox->write); ++ rc = 0; ++ } ++ return rc; ++} ++ ++static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) ++{ ++ int rc; ++ ++ if (mbox->magic != MBOX_MAGIC) ++ rc = -EINVAL; ++ else { ++ if (mbox->msg[chan] || ++ (down_interruptible(&mbox->sema[chan]) == 0)) { ++ *data28 = MBOX_DATA28(mbox->msg[chan]); ++ mbox->msg[chan] = 0; ++ rc = 0; ++ } else { ++ /* The wait was interrupted */ ++ rc = -EINTR; ++ } ++ } ++ return rc; ++} ++ ++static irqreturn_t mbox_irq(int irq, void *dev_id) ++{ ++ /* wait for the mailbox FIFO to have some data in it */ ++ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; ++ int status = readl(mbox->status); ++ int ret = IRQ_NONE; ++ ++ while (!(status & ARM_MS_EMPTY)) { ++ uint32_t msg = readl(mbox->read); ++ int chan = MBOX_CHAN(msg); ++ if (chan < MBOX_CHAN_COUNT) { ++ if (mbox->msg[chan]) { ++ /* Overflow */ ++ printk(KERN_ERR DRIVER_NAME ++ ": mbox chan %d overflow - drop %08x\n", ++ chan, msg); ++ } else { ++ mbox->msg[chan] = (msg | 0xf); ++ up(&mbox->sema[chan]); ++ } ++ } else { ++ printk(KERN_ERR DRIVER_NAME ++ ": invalid channel selector (msg %08x)\n", msg); ++ } ++ ret = IRQ_HANDLED; ++ status = readl(mbox->status); ++ } ++ return ret; ++} ++ ++static struct irqaction mbox_irqaction = { ++ .name = "ARM Mailbox IRQ", ++ .flags = IRQF_DISABLED | IRQF_IRQPOLL, ++ .handler = mbox_irq, ++}; ++ ++/* ---------------------------------------------------------------------- ++ * Mailbox Methods ++ * -------------------------------------------------------------------- */ ++ ++static struct device *mbox_dev; /* we assume there's only one! */ ++ ++static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) ++{ ++ int rc; ++ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ device_lock(dev); ++ rc = mbox_write(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) ++{ ++ int rc; ++ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ device_lock(dev); ++ rc = mbox_read(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++extern int bcm_mailbox_write(unsigned chan, uint32_t data28) ++{ ++ if (mbox_dev) ++ return dev_mbox_write(mbox_dev, chan, data28); ++ else ++ return -ENODEV; ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_write); ++ ++extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) ++{ ++ if (mbox_dev) ++ return dev_mbox_read(mbox_dev, chan, data28); ++ else ++ return -ENODEV; ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_read); ++ ++static void dev_mbox_register(const char *dev_name, struct device *dev) ++{ ++ mbox_dev = dev; ++} ++ ++/* ---------------------------------------------------------------------- ++ * Platform Device for Mailbox ++ * -------------------------------------------------------------------- */ ++ ++static int bcm_vcio_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct vc_mailbox *mailbox; ++ ++ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); ++ if (NULL == mailbox) { ++ printk(KERN_ERR DRIVER_NAME ": failed to allocate " ++ "mailbox memory\n"); ++ ret = -ENOMEM; ++ } else { ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " ++ "resource\n"); ++ ret = -ENODEV; ++ kfree(mailbox); ++ } else { ++ /* should be based on the registers from res really */ ++ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); ++ ++ platform_set_drvdata(pdev, mailbox); ++ dev_mbox_register(DRIVER_NAME, &pdev->dev); ++ ++ mbox_irqaction.dev_id = mailbox; ++ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); ++ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", ++ __io_address(ARM_0_MAIL0_RD)); ++ } ++ } ++ return ret; ++} ++ ++static int bcm_vcio_remove(struct platform_device *pdev) ++{ ++ struct vc_mailbox *mailbox = platform_get_drvdata(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ kfree(mailbox); ++ ++ return 0; ++} ++ ++static struct platform_driver bcm_mbox_driver = { ++ .probe = bcm_vcio_probe, ++ .remove = bcm_vcio_remove, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init bcm_mbox_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); ++ ++ ret = platform_driver_register(&bcm_mbox_driver); ++ if (ret != 0) { ++ printk(KERN_ERR DRIVER_NAME ": failed to register " ++ "on platform\n"); ++ } ++ ++ return ret; ++} ++ ++static void __exit bcm_mbox_exit(void) ++{ ++ platform_driver_unregister(&bcm_mbox_driver); ++} ++ ++arch_initcall(bcm_mbox_init); /* Initialize early */ ++module_exit(bcm_mbox_exit); ++ ++MODULE_AUTHOR("Gray Girling"); ++MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:bcm-mbox"); +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -390,7 +390,7 @@ config CPU_PJ4 + + # ARMv6 + config CPU_V6 +- bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX ++ bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708 + select CPU_32v6 + select CPU_ABRT_EV6 + select CPU_PABRT_V6 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -855,9 +855,11 @@ do_alignment(unsigned long addr, unsigne + case 0x08000000: /* ldm or stm, or thumb-2 32bit instruction */ + if (thumb2_32b) + handler = do_alignment_t32_to_handler(&instr, regs, &offset); +- else ++ else { ++ offset.un = 0; /* to keep compiler happy */ + handler = do_alignment_ldmstm; +- break; ++ } ++ break; + + default: + goto bad; +--- a/arch/arm/mm/proc-v6.S ++++ b/arch/arm/mm/proc-v6.S +@@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) + * + * IRQs are already disabled. + */ ++ ++/* See jira SW-5991 for details of this workaround */ + ENTRY(cpu_v6_do_idle) +- mov r1, #0 +- mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode +- mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt ++ .align 5 ++ mov r1, #2 ++1: subs r1, #1 ++ nop ++ mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode ++ mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt ++ nop ++ nop ++ nop ++ bne 1b + mov pc, lr + + ENTRY(cpu_v6_dcache_clean_area) +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -229,6 +229,27 @@ config MMC_SDHCI_S3C_DMA + + YMMV. + ++config MMC_SDHCI_BCM2708 ++ tristate "SDHCI support on BCM2708" ++ depends on MMC_SDHCI && MACH_BCM2708 ++ select MMC_SDHCI_IO_ACCESSORS ++ help ++ This selects the Secure Digital Host Controller Interface (SDHCI) ++ often referrered to as the eMMC block. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ ++config MMC_SDHCI_BCM2708_DMA ++ bool "DMA support on BCM2708 Arasan controller" ++ depends on MMC_SDHCI_BCM2708 && EXPERIMENTAL ++ help ++ Enable DMA support on the Arasan SDHCI controller in Broadcom 2708 ++ based chips. ++ ++ If unsure, say N. ++ + config MMC_OMAP + tristate "TI OMAP Multimedia Card Interface support" + depends on ARCH_OMAP +@@ -296,6 +317,14 @@ config MMC_ATMELMCI + If unsure, say N. + + endchoice ++config MMC_BCM2708 ++ tristate "BCM2708 Multimedia Card Interface support" ++ help ++ This selects the BCM2708 Multimedia Card Interface driver. If ++ you have a BCM2708 platform with a Multimedia Card ++ slot, say Y or M here. ++ ++ If unsure, say N. + + config MMC_ATMELMCI_DMA + bool "Atmel MCI DMA support" +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-p + obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o + obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o + obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o ++obj-$(CONFIG_MMC_SDHCI_BCM2708) += sdhci-bcm2708.o + obj-$(CONFIG_MMC_WBSD) += wbsd.o + obj-$(CONFIG_MMC_AU1X) += au1xmmc.o + obj-$(CONFIG_MMC_OMAP) += omap.o +@@ -53,6 +54,8 @@ obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci- + obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o + obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o + ++obj-$(CONFIG_MMC_BCM2708) += bcm2708_mci.o ++ + ifeq ($(CONFIG_CB710_DEBUG),y) + CFLAGS-cb710-mmc += -DDEBUG + endif +--- /dev/null ++++ b/drivers/mmc/host/bcm2708_mci.c +@@ -0,0 +1,889 @@ ++/* ++ * linux/drivers/mmc/host/bcm2708_mci.c - Broadcom BCM2708 MCI driver ++ * ++ * Copyright (C) 2010 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++//#include ++ ++#include ++ ++#include "bcm2708_mci.h" ++ ++#define DRIVER_NAME "bcm2708_mci" ++ ++//#define PIO_DEBUG ++#ifdef PIO_DEBUG ++#define DBG(host,fmt,args...) \ ++ printk(KERN_ERR"%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args) ++#else ++#define DBG(host,fmt,args...) \ ++ pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args) ++#endif ++ ++#define USE_DMA ++#define USE_DMA_IRQ ++ ++#ifdef USE_DMA ++#define SDHOST_DMA_CHANNEL 5 ++#endif ++ ++#define BCM2708_DMA_ACTIVE (1 << 0) ++#define BCM2708_DMA_INT (1 << 2) ++ ++#define BCM2708_DMA_INT_EN (1 << 0) ++#define BCM2708_DMA_D_INC (1 << 4) ++#define BCM2708_DMA_D_WIDTH (1 << 5) ++#define BCM2708_DMA_D_DREQ (1 << 6) ++#define BCM2708_DMA_S_INC (1 << 8) ++#define BCM2708_DMA_S_WIDTH (1 << 9) ++#define BCM2708_DMA_S_DREQ (1 << 10) ++ ++#define BCM2708_DMA_PER_MAP(x) ((x) << 16) ++ ++#define BCM2708_DMA_DREQ_SDHOST 13 ++ ++#define BCM2708_DMA_CS 0x00 ++#define BCM2708_DMA_ADDR 0x04 ++ ++static void dump_sd_regs(void * mmc_base ); ++static int bcm2708_mci_reset(struct bcm2708_mci_host *host); ++ ++static void do_command(void __iomem *base, u32 c, u32 a) ++{ ++ u32 cmdsts = 0; ++ writel(a, base + BCM2708_MCI_ARGUMENT); ++ writel(c | BCM2708_MCI_ENABLE, base + BCM2708_MCI_COMMAND); ++ ++ /* check for error and command done */ ++ cmdsts = readl(base + BCM2708_MCI_COMMAND); ++ while ((cmdsts & BCM2708_MCI_ENABLE) && (!(cmdsts & BCM2708_MCI_FAIL_FLAG))) ++ cmdsts = readl(base + BCM2708_MCI_COMMAND); ++ if (cmdsts & BCM2708_MCI_FAIL_FLAG) { ++ printk(KERN_DEBUG"%s: Command %d failed with arg %d\n", __func__, c, a); ++ dump_sd_regs(base); ++ } ++} ++ ++//static void discard_words(void __iomem *base, int words) ++//{ ++// int i; ++// for (i = 0; i < words; i++) { ++// while (!(readl(base + BCM2708_MCI_STATUS) & BCM2708_MCI_DATAFLAG)); ++// readl(base + BCM2708_MCI_DATA); ++// } ++//} ++ ++#define CACHE_LINE_MASK 31 ++ ++static int suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) ++{ ++ int i; ++ ++ for (i = 0; i < sg_len; i++) { ++ if (sg_ptr[i].offset & CACHE_LINE_MASK || sg_ptr[i].length & CACHE_LINE_MASK) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static void wait_for_complete(struct bcm2708_mci_host *host, ++ void __iomem *mmc_base) ++{ ++#ifdef USE_SDHOST_IRQ ++#error not implemented yet ++#else ++ while ((readl(mmc_base + BCM2708_MCI_STATUS) & ++ (BCM2708_MCI_HSTS_BUSY | BCM2708_MCI_HSTS_BLOCK)) == 0) ++ continue; ++ ++ writel(BCM2708_MCI_HSTS_BUSY | BCM2708_MCI_HSTS_BLOCK, ++ mmc_base + BCM2708_MCI_STATUS); ++#endif ++} ++ ++static void dump_sd_regs(void * mmc_base ) ++{ ++ printk(KERN_DEBUG"Registers:\n"); ++ printk(KERN_DEBUG"SDCMD:0x%x\n", readl(mmc_base + BCM2708_MCI_COMMAND)); ++ printk(KERN_DEBUG"SDARG:0x%x\n", readl(mmc_base + BCM2708_MCI_ARGUMENT)); ++ printk(KERN_DEBUG"SDTOUT:0x%x\n", readl(mmc_base + BCM2708_MCI_TIMEOUT)); ++ printk(KERN_DEBUG"SDCDIV:0x%x\n", readl(mmc_base + BCM2708_MCI_CLKDIV)); ++ printk(KERN_DEBUG"SDRSP0:0x%x\n", readl(mmc_base + BCM2708_MCI_RESPONSE0)); ++ printk(KERN_DEBUG"SDRSP1:0x%x\n", readl(mmc_base + BCM2708_MCI_RESPONSE1)); ++ printk(KERN_DEBUG"SDRSP2:0x%x\n", readl(mmc_base + BCM2708_MCI_RESPONSE2)); ++ printk(KERN_DEBUG"SDRSP3:0x%x\n", readl(mmc_base + BCM2708_MCI_RESPONSE3)); ++ printk(KERN_DEBUG"SDHSTS:0x%x\n", readl(mmc_base + BCM2708_MCI_STATUS)); ++ printk(KERN_DEBUG"SDPO:0x%x\n", readl(mmc_base + BCM2708_MCI_VDD)); ++ printk(KERN_DEBUG"SDEDM:0x%x\n", readl(mmc_base + BCM2708_MCI_EDM)); ++ printk(KERN_DEBUG"SDHCFG:0x%x\n", readl(mmc_base + BCM2708_MCI_HOSTCONFIG)); ++ printk(KERN_DEBUG"SDHBCT:0x%x\n", readl(mmc_base + BCM2708_MCI_HBCT)); ++ //printk(KERN_ERR"SDDATA:0x%x\n", readl(mmc_base + BCM2708_MCI_DATA)); ++ printk(KERN_DEBUG"SDHBLC:0x%x\n", readl(mmc_base + BCM2708_MCI_HBLC)); ++} ++ ++ ++static void ++bcm2708_mci_start_command(struct bcm2708_mci_host *host, struct mmc_command *cmd, struct mmc_data *data) ++{ ++ void __iomem *mmc_base = host->mmc_base; ++ void __iomem *dma_base = host->dma_base; ++ u32 status; ++ u32 c; ++ int redo = 0; ++ ++ DBG(host, "op %02x arg %08x flags %08x\n", ++ cmd->opcode, cmd->arg, cmd->flags); ++ ++back: ++ ++ /* ++ * clear the controller status register ++ */ ++ ++ writel(-1, mmc_base + BCM2708_MCI_STATUS); ++ ++ /* ++ * build the command register write, incorporating no ++ * response, long response, busy, read and write flags ++ */ ++ ++ c = cmd->opcode; ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ if (cmd->flags & MMC_RSP_136) ++ c |= BCM2708_MCI_LONGRESP; ++ } else ++ c |= BCM2708_MCI_NORESP; ++ if (cmd->flags & MMC_RSP_BUSY) ++ c |= BCM2708_MCI_BUSY; ++ ++ if (data) { ++ if (data->flags & MMC_DATA_READ) ++ c |= BCM2708_MCI_READ; ++ else ++ c |= BCM2708_MCI_WRITE; ++ ++ DBG(host, "BYTECOUT %d BLOCKCOUNT %d .. ",readl(mmc_base + BCM2708_MCI_HBCT), readl(mmc_base + BCM2708_MCI_HBLC)); ++ DBG(host, "set blocksize to %d\n", data->blksz); ++ DBG(host, "set blockcnt to %d\n", data->blocks); ++ writel( data->blksz, mmc_base + BCM2708_MCI_HBCT); ++ writel(data->blocks, mmc_base + BCM2708_MCI_HBLC); ++ } ++ ++ /* ++ * run the command and wait for it to complete ++ */ ++ ++ DBG(host, "executing command=%d\n", cmd->opcode); ++ ++ do_command(mmc_base, c, cmd->arg); ++ ++ DBG(host, "done cmd=%d\n", cmd->opcode); ++ ++ if (c & BCM2708_MCI_BUSY) { ++ ++ DBG(host, "waiting for command(%d) to complete\n", cmd->opcode); ++ wait_for_complete(host, mmc_base); ++ DBG(host, "done waiting for command(%d)\n", cmd->opcode); ++ } ++ ++ /* ++ * retrieve the response and error (if any) ++ */ ++ ++ status = readl(mmc_base + BCM2708_MCI_STATUS); ++ ++ if (cmd->flags & MMC_RSP_136) { ++ cmd->resp[3] = readl(mmc_base + BCM2708_MCI_RESPONSE0); ++ cmd->resp[2] = readl(mmc_base + BCM2708_MCI_RESPONSE1); ++ cmd->resp[1] = readl(mmc_base + BCM2708_MCI_RESPONSE2); ++ cmd->resp[0] = readl(mmc_base + BCM2708_MCI_RESPONSE3); ++ } else { ++ cmd->resp[0] = readl(mmc_base + BCM2708_MCI_RESPONSE0); ++ } ++ ++ if (status & BCM2708_MCI_CMDTIMEOUT) { ++ printk(KERN_DEBUG "mmc driver saw timeout with opcode = %d, data = 0x%08x, timeout = %d", cmd->opcode, (unsigned int)data, readl(mmc_base + BCM2708_MCI_TIMEOUT)); ++ if (data) ++ printk(KERN_DEBUG " data->sg_len = %d\n", data->sg_len); ++ else ++ printk(KERN_DEBUG "\n"); ++ if (!redo) { ++ printk(KERN_DEBUG "redo\n"); ++ redo = 1; ++ goto back; ++ } else ++ cmd->error = -ETIMEDOUT; ++ } ++ ++ /* ++ * pump data if necessary ++ */ ++ ++ if (data) { ++ unsigned int sg_len = data->sg_len; ++ struct scatterlist *sg_ptr = data->sg; ++ ++ data->bytes_xfered = 0; ++ ++#ifdef USE_DMA ++ if (suitable_for_dma(sg_ptr, sg_len)) { ++ int i, count = dma_map_sg(&host->dev->dev, sg_ptr, sg_len, data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); ++ ++ for (i = 0; i < count; i++) { ++ BCM2708_DMA_CB_T *cb = &host->cb_base[i]; ++ ++ if (data->flags & MMC_DATA_READ) { ++ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_SDHOST)|BCM2708_DMA_S_DREQ|BCM2708_DMA_D_WIDTH|BCM2708_DMA_D_INC; ++ cb->src = 0x7e202040; ++ cb->dst = sg_dma_address(&sg_ptr[i]); ++ } else { ++ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_SDHOST)|BCM2708_DMA_S_WIDTH|BCM2708_DMA_S_INC|BCM2708_DMA_D_DREQ; ++ cb->src = sg_dma_address(&sg_ptr[i]); ++ cb->dst = 0x7e202040; ++ } ++ ++ cb->length = sg_dma_len(&sg_ptr[i]); ++ cb->stride = 0; ++ ++ if (i == count - 1) { ++#ifdef USE_DMA_IRQ ++ cb->info |= BCM2708_DMA_INT_EN; ++#endif ++ cb->next = 0; ++ } else ++ cb->next = host->cb_handle + (i + 1) * sizeof(BCM2708_DMA_CB_T); ++ ++ cb->pad[0] = 0; ++ cb->pad[1] = 0; ++ ++ data->bytes_xfered += sg_ptr[i].length; ++ } ++ ++ dsb(); // data barrier operation ++ ++ writel(host->cb_handle, dma_base + BCM2708_DMA_ADDR); ++ writel(BCM2708_DMA_ACTIVE, dma_base + BCM2708_DMA_CS); ++ ++#ifdef USE_DMA_IRQ ++ down(&host->sem); ++#else ++ while ((readl(dma_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE)); ++#endif ++ dma_unmap_sg(&host->dev->dev, sg_ptr, sg_len, data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); ++ } else ++#endif ++ while (sg_len) { ++ unsigned long flags; ++ char *buffer; ++ u32 *ptr, *lim; ++ ++ DBG(host, "sg_len=%d sg_ptr=%p len=%d\n", sg_len, sg_ptr, sg_ptr->length); ++ ++ /* ++ * map the current scatter buffer ++ */ ++ ++ buffer = bcm2708_mci_kmap_atomic(sg_ptr, &flags); ++ ++ /* ++ * pump the data ++ */ ++ ++ ptr = (u32 *)(buffer); ++ lim = (u32 *)(buffer + sg_ptr->length); ++ ++ while (ptr < lim) ++ { ++#ifdef PIO_DEBUG ++ unsigned int wait_count = 1; ++#endif ++ while (!(readl(mmc_base + BCM2708_MCI_STATUS) & BCM2708_MCI_DATAFLAG)) ++ { ++#ifdef PIO_DEBUG ++ wait_count++; ++ if ( 0 == (wait_count % 20000) ) { ++ ++ printk(KERN_ERR"Timeout waiting for data flag\n"); ++ dump_sd_regs(mmc_base); ++ } ++#endif ++ } ++ ++ if (data->flags & MMC_DATA_READ) ++ *ptr++ = readl(mmc_base + BCM2708_MCI_DATA); ++ else ++ { ++#ifdef PIO_DEBUG ++ uint32_t fifo_bytes, fifo_wait_count = 1; ++ ++ fifo_bytes = readl(mmc_base + BCM2708_MCI_EDM); ++ fifo_bytes = (fifo_bytes >> 4) & 0xf; ++ ++ while(fifo_bytes > 3) ++ { ++ fifo_wait_count++; ++ if ( 0 == (fifo_wait_count % 20000) ) { ++ printk(KERN_ERR"waiting for fifo_bytes < 3\n"); ++ dump_sd_regs(mmc_base); ++ } ++ ++ fifo_bytes = readl(mmc_base + BCM2708_MCI_EDM); ++ fifo_bytes = (fifo_bytes >> 4) & 0xf; ++ } ++ ++ BUG_ON(fifo_bytes > 3); ++#endif ++ writel(*ptr++, mmc_base + BCM2708_MCI_DATA); ++ } ++ } ++ ++ DBG(host, "done reading/writing %d bytes from mmc\n", sg_ptr->length); ++ ++ ++ /* ++ * unmap the buffer ++ */ ++ ++ bcm2708_mci_kunmap_atomic(buffer, &flags); ++ ++ /* ++ * if we were reading, and we have completed this ++ * page, ensure that the data cache is coherent ++ */ ++ ++ if (data->flags & MMC_DATA_READ) ++ flush_dcache_page(sg_page(sg_ptr)); ++ ++ data->bytes_xfered += sg_ptr->length; ++ ++ sg_ptr++; ++ sg_len--; ++ } ++ ++// if (host->is_acmd && cmd->opcode == SD_APP_SEND_SCR) ++// discard_words(mmc_base, 126); ++// if (host->is_acmd && cmd->opcode == SD_APP_SEND_NUM_WR_BLKS) ++// discard_words(mmc_base, 127); ++// if (!host->is_acmd && cmd->opcode == SD_SWITCH) ++// discard_words(mmc_base, 112); ++ ++ if (data->stop) { ++ ++ DBG(host, "sending stop command %p\n", data->stop); ++ bcm2708_mci_start_command(host, data->stop, 0); ++ ++ while ((readl(mmc_base + BCM2708_MCI_STATUS) & ++ BCM2708_MCI_DATAFLAG)) ++ { ++ DBG(host, "error data flag still set read=%d bytes\n", sg_ptr->length); ++ printk(KERN_ERR"SDDATA:0x%x\n", readl(mmc_base + BCM2708_MCI_DATA)); ++ dump_sd_regs(mmc_base); ++ } ++ } ++ } ++ /* ++ * remember if we're an application command ++ */ ++ host->is_acmd = cmd->opcode == MMC_APP_CMD; ++} ++ ++static void bcm2708_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct bcm2708_mci_host *host = mmc_priv(mmc); ++ ++ if (mrq->data && !is_power_of_2(mrq->data->blksz)) { ++ printk(KERN_ERR "%s: Unsupported block size (%d bytes)\n", ++ mmc_hostname(mmc), mrq->data->blksz); ++ mrq->cmd->error = -EINVAL; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ bcm2708_mci_start_command(host, mrq->cmd, mrq->data); ++ ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static void bcm2708_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ ++ struct bcm2708_mci_host *host = mmc_priv(mmc); ++ void *mmc_base = host->mmc_base; ++ ++ ++ printk(KERN_DEBUG"%s: Want to set clock: %d width: %d\n", mmc_hostname(mmc), ++ ios->clock, ios->bus_width); ++ ++ if (ios->clock == 25000000 || ios->clock == 26000000) { ++ printk(KERN_DEBUG"%s setting clock div to 10 (8+2)\n", mmc_hostname(mmc)); ++ writel(0x8, mmc_base + BCM2708_MCI_CLKDIV); ++ } else if (ios->clock == 50000000 || ios->clock == 52000000) { ++ printk(KERN_DEBUG"%s setting clock div to 5 (3+2)\n", mmc_hostname(mmc)); ++ writel(0x3, mmc_base + BCM2708_MCI_CLKDIV); ++ } else { ++ // On init or unknown clock, we set the clock really low ++ printk(KERN_DEBUG"%s Setting clock div to 0x4e0\n", mmc_hostname(mmc)); ++ writel(0x4e0, mmc_base + BCM2708_MCI_CLKDIV); ++ } ++ ++ if (ios->bus_width) { ++ uint32_t hcfg; ++ hcfg = readl(mmc_base + BCM2708_MCI_HOSTCONFIG); ++ printk(KERN_DEBUG"%s setting bus width to %d\n", mmc_hostname(mmc), ios->bus_width); ++ ++ hcfg &= BCM2708_MCI_HOSTCONFIG_WIDEEXT_CLR; ++ hcfg |= (ios->bus_width == MMC_BUS_WIDTH_4) ? BCM2708_MCI_HOSTCONFIG_WIDEEXT_4BIT : 0; ++ ++ writel(hcfg, mmc_base + BCM2708_MCI_HOSTCONFIG); ++ } ++} ++ ++static int bcm2708_mci_get_cd(struct mmc_host *mmc) ++{ ++ int present = -ENOSYS; ++ ++ struct bcm2708_mci_host *host = mmc_priv(mmc); ++ void *gpio_base = host->gpio_base; ++ ++ present = readl( (gpio_base + GP_LEV0) ); ++ ++ if ((present & (1<<29))==(1<<29)) ++ present = 0; ++ else ++ present = 1; ++ ++ printk(KERN_DEBUG"***sdcard present***=%d\n", present); ++ ++ // FIXME - For now force SD card present for 2835DK ++ present = 1; ++ return present; ++} ++ ++/* ++ * Handle completion of command and data transfers. ++ */ ++ ++//static irqreturn_t bcm2708_mci_command_irq(int irq, void *dev_id) ++//{ ++// struct bcm2708_mci_host *host = dev_id; ++// ++// writel(BCM2708_DMA_INT, host->dma_base + BCM2708_DMA_CS); ++// ++// printk(KERN_ERR "irq\n"); ++// ++// return IRQ_RETVAL(0); ++//} ++ ++static irqreturn_t bcm2708_mci_sddet_irq(int irq, void *dev_id) ++{ ++ struct bcm2708_mci_host *host = dev_id; ++ irqreturn_t handled = IRQ_NONE; ++ int present; ++ ++ present = bcm2708_mci_get_cd(host->mmc); ++ ++ if (present!=host->present) ++ { ++ host->present = present; ++ printk(KERN_DEBUG "SDDET IRQ: sdcard present: %d\n",present); ++ bcm2708_mci_reset(host); ++ mmc_detect_change(host->mmc, msecs_to_jiffies(500)); ++ } ++ ++ return IRQ_RETVAL(handled); ++} ++ ++#ifdef USE_DMA_IRQ ++static irqreturn_t bcm2708_mci_data_irq(int irq, void *dev_id) ++{ ++ struct bcm2708_mci_host *host = dev_id; ++ irqreturn_t handled = IRQ_NONE; ++ ++ if (0 != (BCM2708_DMA_INT & readl(host->dma_base + BCM2708_DMA_CS))) { ++ writel(BCM2708_DMA_INT, host->dma_base + BCM2708_DMA_CS); ++ dsb(); ++ handled = IRQ_HANDLED; ++ up(&host->sem); ++ } else { ++ printk(KERN_ERR"bcm2708_mci irq check failed !!\n"); ++ } ++ ++ return IRQ_RETVAL(handled); ++} ++#endif ++ ++static const struct mmc_host_ops bcm2708_mci_ops = { ++ .request = bcm2708_mci_request, ++ .set_ios = bcm2708_mci_set_ios, ++ .get_cd = bcm2708_mci_get_cd, ++}; ++ ++static int bcm2708_mci_reset(struct bcm2708_mci_host *host) ++{ ++ ++ void *mmc_base = host->mmc_base; ++ ++ // pin muxing/gpios is done by vcloader ++ ++ printk(KERN_DEBUG"%s:Resetting BCM2708 MCI Controller.\n", __func__ ); ++ ++ writel(0, mmc_base + BCM2708_MCI_COMMAND); ++ writel(0, mmc_base + BCM2708_MCI_ARGUMENT); ++ writel(0x00F00000, mmc_base + BCM2708_MCI_TIMEOUT); ++ writel(0, mmc_base + BCM2708_MCI_CLKDIV); ++ writel(0, mmc_base + BCM2708_MCI_STATUS); ++ writel(0, mmc_base + BCM2708_MCI_VDD); ++ writel(0, mmc_base + BCM2708_MCI_HOSTCONFIG); ++ writel(0, mmc_base + BCM2708_MCI_HBCT); ++ writel(0, mmc_base + BCM2708_MCI_HBLC); ++ ++ writel( BCM2708_MCI_HOSTCONFIG_SLOW_CARD | BCM2708_MCI_HOSTCONFIG_BUSY_IRPT_EN | ++ BCM2708_MCI_HOSTCONFIG_BLOCK_IRPT_EN | BCM2708_MCI_HOSTCONFIG_WIDE_INT_BUS, ++ mmc_base + BCM2708_MCI_HOSTCONFIG); ++ ++ // On A0 silicon it has been observed that the following must hold ++ // WRITE_THRESHOLD<=5 and READ_THRESHOLD<=WRITE_THRESHOLD+1 ++ // with the chip running at 150MHz (with the interface running @ 150/22 = 6.8 MHz) ++ // the second requirement suggests that the verilog does not properly separate the read / write FIFOs ++ // On V3XDS Read=2 & Write=6 ++ ++#define READ_THRESHOLD 3 ++#define WRITE_THRESHOLD 3 ++#if 1 // !!! This is still required, without it we get CRC16 errors in data. ++ { ++ uint32_t temp; ++ temp = readl(mmc_base + BCM2708_MCI_EDM); ++ temp &= ~((0x1F<<14) | (0x1F<<9)); ++ temp |= (WRITE_THRESHOLD << 9) | (READ_THRESHOLD << 14); ++ writel(temp, mmc_base + BCM2708_MCI_EDM); ++ } ++#endif ++ ++ // Power on delay ++ mdelay(10); ++ writel(BCM2708_MCI_VDD_ENABLE, mmc_base + BCM2708_MCI_VDD); ++ mdelay(10); ++ ++ return 0; ++} ++ ++ ++static int __devinit bcm2708_mci_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct bcm2708_mci_host *host; ++ struct resource *mmc_res; ++ struct resource *dma_res; ++ struct resource *gpio_res; ++ struct resource *dat_res; ++ struct resource *sddet_res; ++ int ret; ++ ++ mmc = mmc_alloc_host(sizeof(struct bcm2708_mci_host), &pdev->dev); ++ if (!mmc) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "couldn't allocate mmc host\n"); ++ goto fail0; ++ } ++ ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ ++ host->dev = pdev; ++ ++ sema_init(&host->sem, 0); ++ ++#ifdef USE_DMA ++ host->cb_base = dma_alloc_writecombine(&pdev->dev, SZ_4K, &host->cb_handle, GFP_KERNEL); ++ if (!host->cb_base) { ++ ret = -ENOMEM; ++ dev_dbg(&pdev->dev, "couldn't allocate dma base\n"); ++ goto fail1; ++ } ++#endif ++ ++ mmc_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mmc_res) { ++ ret = -ENXIO; ++ dev_dbg(&pdev->dev, "couldn't allocate mmc memory resource 0\n"); ++ goto fail2; ++ } ++ ++ if (!request_mem_region(mmc_res->start, mmc_res->end - mmc_res->start + 1, DRIVER_NAME)) { ++ ret = -EBUSY; ++ goto fail2; ++ } ++ ++ dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!dma_res) { ++ ret = -ENXIO; ++ dev_dbg(&pdev->dev, "couldn't allocate dma memory resource 1\n"); ++ goto fail3; ++ } ++ ++ /* ++ * Map I/O regions ++ */ ++ ++ host->mmc_base = ioremap(mmc_res->start, resource_size(mmc_res)); ++ if (!host->mmc_base) { ++ ret = -ENOMEM; ++ goto fail3; ++ } ++ ++ gpio_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (!gpio_res) { ++ ret = -ENXIO; ++ dev_dbg(&pdev->dev, "couldn't allocate gpio resource\n"); ++ goto fail4; ++ } ++ ++ /* ++ * Map I/O regions ++ */ ++ ++ host->gpio_base = ioremap(gpio_res->start, resource_size(gpio_res)); ++ if (!host->gpio_base) { ++ ret = -ENOMEM; ++ goto fail4; ++ } ++ ++#ifdef USE_DMA ++ host->dma_base = __io_address(dma_res->start); ++ ++ if (!host->dma_base) { ++ ret = -ENOMEM; ++ goto fail5; ++ } ++ ++ // USE DMA5 channel ++ host->dma_base = (void __iomem *)((char *) host->dma_base + (SDHOST_DMA_CHANNEL * 0x100)); ++ ++ dev_dbg(&pdev->dev, "%s: using dma channel %d for sdhost\n", __func__, SDHOST_DMA_CHANNEL); ++ ++ /* ++ * Grab interrupts. ++ */ ++#ifdef USE_DMA_IRQ ++ dat_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!dat_res) { ++ ret = -ENXIO; ++ dev_dbg(&pdev->dev, "couldn't allocate irq for dma\n"); ++ goto fail5; ++ } ++ ++ ret = request_irq(dat_res->start, bcm2708_mci_data_irq, 0, DRIVER_NAME " (dat)", host); ++ if (ret) { ++ goto fail5; ++ } ++ dev_dbg(&pdev->dev, "%s: using dma interrupt number %d for sdhost\n", __func__, dat_res->start); ++ ++#endif ++#endif ++ ++ host->present = bcm2708_mci_get_cd(host->mmc); ++ ++ sddet_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); ++ if (!sddet_res) { ++ ret = -ENXIO; ++ dev_dbg(&pdev->dev, "couldn't allocate irq for sd detect\n"); ++ goto fail6; ++ } ++ ++ ret = request_irq(sddet_res->start, bcm2708_mci_sddet_irq, 0, DRIVER_NAME " (cmd)", host); ++ if (ret) { ++ goto fail6; ++ } ++ ++ host->is_acmd = 0; ++ ++ mmc->ops = &bcm2708_mci_ops; ++ mmc->f_min = 200000; ++ mmc->f_max = 52000000; ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ ++ /* ++ * We can do SGIO ++ */ ++ mmc->max_segs = NR_SG; ++ ++ /* ++ * Since we only have a 16-bit data length register, we must ++ * ensure that we don't exceed 2^16-1 bytes in a single request. ++ */ ++ mmc->max_req_size = 65535; ++ ++ /* ++ * Set the maximum segment size. Since we aren't doing DMA ++ * (yet) we are only limited by the data length register. ++ */ ++ mmc->max_seg_size = mmc->max_req_size; ++ ++ /* ++ * Block size can be up to 2048 bytes, but must be a power of two. ++ */ ++ mmc->max_blk_size = 2048; ++ ++ /* ++ * No limit on the number of blocks transferred. ++ */ ++ mmc->max_blk_count = mmc->max_req_size; ++ ++ /* ++ * We support 4-bit data (at least on the DB) ++ */ ++ ++ mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED) ; ++ ++ bcm2708_mci_reset(host); ++ ++ mmc_add_host(mmc); ++ ++ printk(KERN_INFO "%s: BCM2708 SD host at 0x%08llx 0x%08llx\n", ++ mmc_hostname(mmc), ++ (unsigned long long)mmc_res->start, (unsigned long long)dma_res->start); ++ ++ return 0; ++ ++fail6: ++#ifdef USE_DMA_IRQ ++ free_irq(dat_res->start, host); ++#endif ++fail5: ++ iounmap(host->gpio_base); ++fail4: ++ iounmap(host->mmc_base); ++fail3: ++ release_mem_region(mmc_res->start, mmc_res->end - mmc_res->start + 1); ++fail2: ++ dma_free_writecombine(&pdev->dev, SZ_4K, host->cb_base, host->cb_handle); ++fail1: ++ mmc_free_host(mmc); ++fail0: ++ dev_err(&pdev->dev, "probe failed, err %d\n", ret); ++ return ret; ++} ++ ++static int __devexit bcm2708_mci_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ ++ if (mmc) { ++ struct bcm2708_mci_host *host = mmc_priv(mmc); ++ struct resource *res; ++ struct resource *res2; ++ ++ mmc_remove_host(mmc); ++#ifdef USE_DMA ++#ifdef USE_DMA_IRQ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ free_irq(res->start, host); ++#endif ++#endif ++ ++ res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 1); ++ free_irq(res2->start, host); ++ ++ iounmap(host->mmc_base); ++ iounmap(host->gpio_base); ++ iounmap(host->dma_base); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(res->start, resource_size(res)); ++#ifdef USE_DMA ++ dma_free_writecombine(&pdev->dev, SZ_4K, host->cb_base, host->cb_handle); ++#endif ++ ++ mmc_free_host(mmc); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++ } else ++ return -1; ++} ++ ++#ifdef CONFIG_PM ++static int bcm2708_mci_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(dev); ++ int ret = 0; ++ ++ if (mmc) { ++ ret = mmc_suspend_host(mmc); ++ } ++ ++ return ret; ++} ++ ++static int bcm2708_mci_resume(struct platform_device *dev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(dev); ++ int ret = 0; ++ ++ if (mmc) { ++ ret = mmc_resume_host(mmc); ++ } ++ ++ return ret; ++} ++#else ++#define bcm2708_mci_suspend NULL ++#define bcm2708_mci_resume NULL ++#endif ++ ++static struct platform_driver bcm2708_mci_driver = { ++ .probe = bcm2708_mci_probe, ++ .remove = bcm2708_mci_remove, ++ .suspend = bcm2708_mci_suspend, ++ .resume = bcm2708_mci_resume, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init bcm2708_mci_init(void) ++{ ++ return platform_driver_register(&bcm2708_mci_driver); ++} ++ ++static void __exit bcm2708_mci_exit(void) ++{ ++ platform_driver_unregister(&bcm2708_mci_driver); ++} ++ ++module_init(bcm2708_mci_init); ++module_exit(bcm2708_mci_exit); ++ ++MODULE_DESCRIPTION("BCM2708 Multimedia Card Interface driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:bcm2708_mci"); +--- /dev/null ++++ b/drivers/mmc/host/bcm2708_mci.h +@@ -0,0 +1,101 @@ ++/* ++ * linux/drivers/mmc/host/bcm2708_mci.c - Broadcom BCM2708 MCI driver ++ * ++ * Copyright (C) 2010 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. ++ */ ++ ++struct clk; ++ ++#define BCM2708_MCI_COMMAND 0x00 ++ ++#define BCM2708_MCI_READ (1 << 6) ++#define BCM2708_MCI_WRITE (1 << 7) ++#define BCM2708_MCI_LONGRESP (1 << 9) ++#define BCM2708_MCI_NORESP (1 << 10) ++#define BCM2708_MCI_BUSY (1 << 11) ++#define BCM2708_MCI_FAIL_FLAG (1 << 14) ++#define BCM2708_MCI_ENABLE (1 << 15) ++ ++#define BCM2708_MCI_ARGUMENT 0x04 ++ ++#define BCM2708_MCI_TIMEOUT 0x08 ++#define BCM2708_MCI_CLKDIV 0x0c ++ ++ ++#define BCM2708_MCI_RESPONSE0 0x10 ++#define BCM2708_MCI_RESPONSE1 0x14 ++#define BCM2708_MCI_RESPONSE2 0x18 ++#define BCM2708_MCI_RESPONSE3 0x1c ++ ++#define BCM2708_MCI_STATUS 0x20 ++ ++#define BCM2708_MCI_VDD 0x30 ++#define BCM2708_MCI_VDD_ENABLE (1 << 0) ++ ++#define BCM2708_MCI_EDM 0x34 ++ ++#define BCM2708_MCI_HOSTCONFIG 0x38 ++ ++#define BCM2708_MCI_HOSTCONFIG_WIDE_INT_BUS 0x2 ++#define BCM2708_MCI_HOSTCONFIG_WIDEEXT_4BIT 0x4 ++#define BCM2708_MCI_HOSTCONFIG_SLOW_CARD 0x8 ++#define BCM2708_MCI_HOSTCONFIG_BLOCK_IRPT_EN (1<<8) ++#define BCM2708_MCI_HOSTCONFIG_BUSY_IRPT_EN (1<<10) ++#define BCM2708_MCI_HOSTCONFIG_WIDEEXT_CLR 0xFFFFFFFB ++ ++ ++#define BCM2708_MCI_DATAFLAG (1 << 0) ++#define BCM2708_MCI_CMDTIMEOUT (1 << 6) ++#define BCM2708_MCI_HSTS_BLOCK (1 << 9) /**< block flag in status reg */ ++#define BCM2708_MCI_HSTS_BUSY (1 << 10) /**< Busy flag in status reg */ ++ ++#define BCM2708_MCI_HBCT 0x3c ++#define BCM2708_MCI_DATA 0x40 ++#define BCM2708_MCI_HBLC 0x50 ++ ++#define NR_SG 16 ++ ++typedef struct bulk_data_struct ++{ ++ unsigned long info; ++ unsigned long src; ++ unsigned long dst; ++ unsigned long length; ++ unsigned long stride; ++ unsigned long next; ++ unsigned long pad[2]; ++} BCM2708_DMA_CB_T; ++ ++struct bcm2708_mci_host { ++ struct platform_device *dev; ++ ++ void __iomem *mmc_base; ++ void __iomem *dma_base; ++ void __iomem *gpio_base; ++ ++ BCM2708_DMA_CB_T *cb_base; ++ dma_addr_t cb_handle; ++ ++ struct mmc_host *mmc; ++ ++ struct semaphore sem; ++ ++ int is_acmd; ++ int present; ++}; ++ ++static inline char *bcm2708_mci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) ++{ ++// local_irq_save(*flags); ++ return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; ++} ++ ++static inline void bcm2708_mci_kunmap_atomic(void *buffer, unsigned long *flags) ++{ ++ kunmap_atomic(buffer, KM_BIO_SRC_IRQ); ++// local_irq_restore(*flags); ++} +--- /dev/null ++++ b/drivers/mmc/host/sdhci-bcm2708.c +@@ -0,0 +1,1461 @@ ++/* ++ * sdhci-bcm2708.c Support for SDHCI device on BCM2708 ++ * Copyright (c) 2010 Broadcom ++ * ++ * 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. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++/* Supports: ++ * SDHCI platform device - Arasan SD controller in BCM2708 ++ * ++ * Inspired by sdhci-pci.c, by Pierre Ossman ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "sdhci.h" ++ ++/*****************************************************************************\ ++ * * ++ * Configuration * ++ * * ++\*****************************************************************************/ ++ ++#define DRIVER_NAME "bcm2708_sdhci" ++ ++/* for the time being insist on DMA mode - PIO seems not to work */ ++#ifndef CONFIG_MMC_SDHCI_BCM2708_DMA ++#warning Non-DMA (PIO) version of this driver currently unavailable ++#endif ++#undef CONFIG_MMC_SDHCI_BCM2708_DMA ++#define CONFIG_MMC_SDHCI_BCM2708_DMA y ++ ++#define USE_SYNC_AFTER_DMA ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++/* #define CHECK_DMA_USE */ ++#endif ++//#define LOG_REGISTERS ++ ++#define USE_SCHED_TIME ++ ++#define SDHCI_BCM_DMA_CHAN 4 /* this default is normally overriden */ ++#define SDHCI_BCM_DMA_WAITS 0 /* delays slowing DMA transfers: 0-31 */ ++/* We are worried that SD card DMA use may be blocking the AXI bus for others */ ++ ++/*! TODO: obtain these from the physical address */ ++#define DMA_SDHCI_BASE 0x7e300000 /* EMMC register block on Videocore */ ++#define DMA_SDHCI_BUFFER (DMA_SDHCI_BASE + SDHCI_BUFFER) ++ ++#define BCM2708_SDHCI_SLEEP_TIMEOUT 1000 /* msecs */ ++ ++#define POWER_OFF 0 ++#define POWER_LAZY_OFF 1 ++#define POWER_ON 2 ++ ++ ++/*****************************************************************************\ ++ * * ++ * Debug * ++ * * ++\*****************************************************************************/ ++ ++ ++ ++#define DBG(f, x...) \ ++ pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) ++// printk(KERN_INFO DRIVER_NAME " [%s()]: " f, __func__,## x)//GRAYG ++ ++ ++/*****************************************************************************\ ++ * * ++ * High Precision Time * ++ * * ++\*****************************************************************************/ ++ ++#ifdef USE_SCHED_TIME ++ ++#include ++ ++typedef unsigned long hptime_t; ++ ++#define FMT_HPT "lu" ++ ++static inline hptime_t hptime(void) ++{ ++ return frc_clock_ticks32(); ++} ++ ++#define HPTIME_CLK_NS 1000ul ++ ++#else ++ ++typedef unsigned long hptime_t; ++ ++#define FMT_HPT "lu" ++ ++static inline hptime_t hptime(void) ++{ ++ return jiffies; ++} ++ ++#define HPTIME_CLK_NS (1000000000ul/HZ) ++ ++#endif ++ ++static inline unsigned long int since_ns(hptime_t t) ++{ ++ return (unsigned long)((hptime() - t) * HPTIME_CLK_NS); ++} ++ ++#if 0 ++static void hptime_test(void) ++{ ++ hptime_t now; ++ hptime_t later; ++ ++ now = hptime(); ++ msleep(10); ++ later = hptime(); ++ ++ printk(KERN_INFO DRIVER_NAME": 10ms = %"FMT_HPT" clks " ++ "(from %"FMT_HPT" to %"FMT_HPT") = %luns\n", ++ later-now, now, later, ++ (unsigned long)(HPTIME_CLK_NS * (later - now))); ++ ++ now = hptime(); ++ msleep(1000); ++ later = hptime(); ++ ++ printk(KERN_INFO DRIVER_NAME": 1s = %"FMT_HPT" clks " ++ "(from %"FMT_HPT" to %"FMT_HPT") = %luns\n", ++ later-now, now, later, ++ (unsigned long)(HPTIME_CLK_NS * (later - now))); ++} ++#endif ++ ++/*****************************************************************************\ ++ * * ++ * SDHCI core callbacks * ++ * * ++\*****************************************************************************/ ++ ++ ++#ifdef CHECK_DMA_USE ++/*#define CHECK_DMA_REG_USE*/ ++#endif ++ ++#ifdef CHECK_DMA_REG_USE ++/* we don't expect anything to be using these registers during a ++ DMA (except the IRQ status) - so check */ ++static void check_dma_reg_use(struct sdhci_host *host, int reg); ++#else ++#define check_dma_reg_use(host, reg) ++#endif ++ ++ ++static inline u32 sdhci_bcm2708_raw_readl(struct sdhci_host *host, int reg) ++{ ++ return readl(host->ioaddr + reg); ++} ++ ++u32 sdhci_bcm2708_readl(struct sdhci_host *host, int reg) ++{ ++ u32 l = sdhci_bcm2708_raw_readl(host, reg); ++ ++#ifdef LOG_REGISTERS ++ printk(KERN_ERR "%s: readl from 0x%02x, value 0x%08x\n", ++ mmc_hostname(host->mmc), reg, l); ++#endif ++ check_dma_reg_use(host, reg); ++ ++ return l; ++} ++ ++u16 sdhci_bcm2708_readw(struct sdhci_host *host, int reg) ++{ ++ u32 l = sdhci_bcm2708_raw_readl(host, reg & ~3); ++ u32 w = l >> (reg << 3 & 0x18) & 0xffff; ++ ++#ifdef LOG_REGISTERS ++ printk(KERN_ERR "%s: readw from 0x%02x, value 0x%04x\n", ++ mmc_hostname(host->mmc), reg, w); ++#endif ++ check_dma_reg_use(host, reg); ++ ++ return (u16)w; ++} ++ ++u8 sdhci_bcm2708_readb(struct sdhci_host *host, int reg) ++{ ++ u32 l = sdhci_bcm2708_raw_readl(host, reg & ~3); ++ u32 b = l >> (reg << 3 & 0x18) & 0xff; ++ ++#ifdef LOG_REGISTERS ++ printk(KERN_ERR "%s: readb from 0x%02x, value 0x%02x\n", ++ mmc_hostname(host->mmc), reg, b); ++#endif ++ check_dma_reg_use(host, reg); ++ ++ return (u8)b; ++} ++ ++ ++static void sdhci_bcm2708_raw_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ /* The Arasan has a bugette whereby it may lose the content of ++ * successive writes to registers that are within two SD-card clock ++ * cycles of each other (a clock domain crossing problem). ++ * It seems, however, that the data register does not have this problem. ++ * (Which is just as well - otherwise we'd have to nobble the DMA engine ++ * too) ++ */ ++#if 1 ++ if (reg != SDHCI_BUFFER && host->clock != 0) { ++ /* host->clock is the clock freq in Hz */ ++ static hptime_t last_write_hpt; ++ hptime_t now = hptime(); ++ unsigned int ns_2clk = 2000000000/host->clock; ++ ++ if (now == last_write_hpt || now == last_write_hpt+1) { ++ /* we can't guarantee any significant time has ++ * passed - we'll have to wait anyway ! */ ++ udelay((ns_2clk+1000-1)/1000); ++ } else ++ { ++ /* we must have waited at least this many ns: */ ++ unsigned int ns_wait = HPTIME_CLK_NS * ++ (last_write_hpt - now - 1); ++ if (ns_wait < ns_2clk) ++ udelay((ns_2clk-ns_wait+500)/1000); ++ } ++ last_write_hpt = now; ++ } ++ writel(val, host->ioaddr + reg); ++#else ++ void __iomem * regaddr = host->ioaddr + reg; ++ ++ writel(val, regaddr); ++ ++ if (reg != SDHCI_BUFFER && reg != SDHCI_INT_STATUS && host->clock != 0) ++ { ++ int timeout = 100000; ++ while (val != readl(regaddr) && --timeout > 0) ++ continue; ++ ++ if (timeout <= 0) ++ printk(KERN_ERR "%s: writing 0x%X to reg 0x%X " ++ "always gives 0x%X\n", ++ mmc_hostname(host->mmc), ++ val, reg, readl(regaddr)); ++ BUG_ON(timeout <= 0); ++ } ++#endif ++} ++ ++ ++void sdhci_bcm2708_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++#ifdef LOG_REGISTERS ++ printk(KERN_ERR "%s: writel to 0x%02x, value 0x%08x\n", ++ mmc_hostname(host->mmc), reg, val); ++#endif ++ check_dma_reg_use(host, reg); ++ ++ sdhci_bcm2708_raw_writel(host, val, reg); ++} ++ ++void sdhci_bcm2708_writew(struct sdhci_host *host, u16 val, int reg) ++{ ++ static u32 shadow = 0; ++ ++ u32 p = reg == SDHCI_COMMAND ? shadow : ++ sdhci_bcm2708_raw_readl(host, reg & ~3); ++ u32 s = reg << 3 & 0x18; ++ u32 l = val << s; ++ u32 m = 0xffff << s; ++ ++#ifdef LOG_REGISTERS ++ printk(KERN_ERR "%s: writew to 0x%02x, value 0x%04x\n", ++ mmc_hostname(host->mmc), reg, val); ++#endif ++ ++ if (reg == SDHCI_TRANSFER_MODE) ++ shadow = (p & ~m) | l; ++ else { ++ check_dma_reg_use(host, reg); ++ sdhci_bcm2708_raw_writel(host, (p & ~m) | l, reg & ~3); ++ } ++} ++ ++void sdhci_bcm2708_writeb(struct sdhci_host *host, u8 val, int reg) ++{ ++ u32 p = sdhci_bcm2708_raw_readl(host, reg & ~3); ++ u32 s = reg << 3 & 0x18; ++ u32 l = val << s; ++ u32 m = 0xff << s; ++ ++#ifdef LOG_REGISTERS ++ printk(KERN_ERR "%s: writeb to 0x%02x, value 0x%02x\n", ++ mmc_hostname(host->mmc), reg, val); ++#endif ++ ++ check_dma_reg_use(host, reg); ++ sdhci_bcm2708_raw_writel(host, (p & ~m) | l, reg & ~3); ++} ++ ++static unsigned int sdhci_bcm2708_get_max_clock(struct sdhci_host *host) ++{ ++ return 100000000; // this value is in Hz (100MHz/4) ++} ++ ++static unsigned int sdhci_bcm2708_get_timeout_clock(struct sdhci_host *host) ++{ ++ return 100000; // this value is in kHz (100MHz/4) ++} ++ ++/*****************************************************************************\ ++ * * ++ * DMA Operation * ++ * * ++\*****************************************************************************/ ++ ++struct sdhci_bcm2708_priv { ++ int dma_chan; ++ int dma_irq; ++ void __iomem *dma_chan_base; ++ struct bcm2708_dma_cb *cb_base; /* DMA control blocks */ ++ dma_addr_t cb_handle; ++ /* tracking scatter gather progress */ ++ unsigned sg_ix; /* scatter gather list index */ ++ unsigned sg_done; /* bytes in current sg_ix done */ ++ /* power management */ ++ BCM_POWER_HANDLE_T power_handle; ++ unsigned char power_state; /* enable/disable power state */ ++ unsigned char power_mode; /* last set power mode */ ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ unsigned char dma_wanted; /* DMA transfer requested */ ++ unsigned char dma_waits; /* wait states in DMAs */ ++#ifdef CHECK_DMA_USE ++ unsigned char dmas_pending; /* no of unfinished DMAs */ ++ hptime_t when_started; ++ hptime_t when_reset; ++ hptime_t when_stopped; ++#endif ++#endif ++ /* signalling the end of a transfer */ ++ void (*complete)(struct sdhci_host *); ++}; ++ ++#define SDHCI_HOST_PRIV(host) \ ++ (struct sdhci_bcm2708_priv *)((struct sdhci_host *)(host)+1) ++ ++ ++ ++#ifdef CHECK_DMA_REG_USE ++static void check_dma_reg_use(struct sdhci_host *host, int reg) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ if (host_priv->dma_wanted && reg != SDHCI_INT_STATUS) { ++ printk(KERN_INFO"%s: accessing register 0x%x during DMA\n", ++ mmc_hostname(host->mmc), reg); ++ } ++} ++#endif ++ ++ ++ ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ ++static void sdhci_clear_set_irqgen(struct sdhci_host *host, u32 clear, u32 set) ++{ ++ u32 ier; ++ ++ ier = sdhci_bcm2708_raw_readl(host, SDHCI_SIGNAL_ENABLE); ++ ier &= ~clear; ++ ier |= set; ++ /* change which requests generate IRQs - makes no difference to ++ the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */ ++ sdhci_bcm2708_raw_writel(host, ier, SDHCI_SIGNAL_ENABLE); ++} ++ ++static void sdhci_signal_irqs(struct sdhci_host *host, u32 irqs) ++{ ++ sdhci_clear_set_irqgen(host, 0, irqs); ++} ++ ++static void sdhci_unsignal_irqs(struct sdhci_host *host, u32 irqs) ++{ ++ sdhci_clear_set_irqgen(host, irqs, 0); ++} ++ ++ ++ ++static void schci_bcm2708_cb_read(struct sdhci_bcm2708_priv *host, ++ int ix, ++ dma_addr_t dma_addr, unsigned len, ++ int /*bool*/ is_last) ++{ ++ struct bcm2708_dma_cb *cb = &host->cb_base[ix]; ++ unsigned char dmawaits = host->dma_waits; ++ ++ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) | ++ BCM2708_DMA_WAITS(dmawaits) | ++ BCM2708_DMA_S_DREQ | ++ BCM2708_DMA_D_WIDTH | ++ BCM2708_DMA_D_INC; ++ cb->src = DMA_SDHCI_BUFFER; /* DATA register DMA address */ ++ cb->dst = dma_addr; ++ cb->length = len; ++ cb->stride = 0; ++ ++ if (is_last) { ++ cb->info |= BCM2708_DMA_INT_EN; ++ cb->next = 0; ++ } else ++ cb->next = host->cb_handle + ++ (ix+1)*sizeof(struct bcm2708_dma_cb); ++ ++ cb->pad[0] = 0; ++ cb->pad[1] = 0; ++} ++ ++static void schci_bcm2708_cb_write(struct sdhci_bcm2708_priv *host, ++ int ix, ++ dma_addr_t dma_addr, unsigned len, ++ int /*bool*/ is_last) ++{ ++ struct bcm2708_dma_cb *cb = &host->cb_base[ix]; ++ unsigned char dmawaits = host->dma_waits; ++ ++ /* We can make arbitrarily large writes as long as we specify DREQ to ++ pace the delivery of bytes to the Arasan hardware */ ++ cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) | ++ BCM2708_DMA_WAITS(dmawaits) | ++ BCM2708_DMA_D_DREQ | ++ BCM2708_DMA_S_WIDTH | ++ BCM2708_DMA_S_INC; ++ cb->src = dma_addr; ++ cb->dst = DMA_SDHCI_BUFFER; /* DATA register DMA address */ ++ cb->length = len; ++ cb->stride = 0; ++ ++ if (is_last) { ++ cb->info |= BCM2708_DMA_INT_EN; ++ cb->next = 0; ++ } else ++ cb->next = host->cb_handle + ++ (ix+1)*sizeof(struct bcm2708_dma_cb); ++ ++ cb->pad[0] = 0; ++ cb->pad[1] = 0; ++} ++ ++ ++static void schci_bcm2708_dma_go(struct sdhci_host *host) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ void __iomem *dma_chan_base = host_priv->dma_chan_base; ++ ++ BUG_ON(host_priv->dma_wanted); ++#ifdef CHECK_DMA_USE ++ if (host_priv->dma_wanted) ++ printk(KERN_ERR "%s: DMA already in progress - " ++ "now %"FMT_HPT", last started %lu " ++ "reset %lu stopped %lu\n", ++ mmc_hostname(host->mmc), ++ hptime(), since_ns(host_priv->when_started), ++ since_ns(host_priv->when_reset), ++ since_ns(host_priv->when_stopped)); ++ else if (host_priv->dmas_pending > 0) ++ printk(KERN_INFO "%s: note - new DMA when %d reset DMAs " ++ "already in progress - " ++ "now %"FMT_HPT", started %lu reset %lu stopped %lu\n", ++ mmc_hostname(host->mmc), ++ host_priv->dmas_pending, ++ hptime(), since_ns(host_priv->when_started), ++ since_ns(host_priv->when_reset), ++ since_ns(host_priv->when_stopped)); ++ host_priv->dmas_pending += 1; ++ host_priv->when_started = hptime(); ++#endif ++ host_priv->dma_wanted = 1; ++ DBG("PDMA go - base %p handle %08X\n", dma_chan_base, ++ host_priv->cb_handle); ++ bcm_dma_start(dma_chan_base, host_priv->cb_handle); ++} ++ ++ ++static void ++sdhci_platdma_read(struct sdhci_host *host, dma_addr_t dma_addr, size_t len) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ ++ DBG("PDMA to read %d bytes\n", len); ++ host_priv->sg_done += len; ++ schci_bcm2708_cb_read(host_priv, 0, dma_addr, len, 1/*TRUE*/); ++ schci_bcm2708_dma_go(host); ++} ++ ++ ++static void ++sdhci_platdma_write(struct sdhci_host *host, dma_addr_t dma_addr, size_t len) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ ++ DBG("PDMA to write %d bytes\n", len); ++ //BUG_ON(0 != (len & 0x1ff)); ++ ++ host_priv->sg_done += len; ++ schci_bcm2708_cb_write(host_priv, 0, dma_addr, len, 1/*TRUE*/); ++ schci_bcm2708_dma_go(host); ++} ++ ++/*! space is avaiable to receive into or data is available to write ++ Platform DMA exported function ++*/ ++void ++sdhci_bcm2708_platdma_avail(struct sdhci_host *host, unsigned int *ref_intmask, ++ void(*completion_callback)(struct sdhci_host *host)) ++{ ++ struct mmc_data *data = host->data; ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ int sg_ix; ++ size_t bytes; ++ dma_addr_t addr; ++ ++ BUG_ON(NULL == data); ++ BUG_ON(0 == data->blksz); ++ ++ host_priv->complete = completion_callback; ++ ++ sg_ix = host_priv->sg_ix; ++ BUG_ON(sg_ix >= data->sg_len); ++ ++ /* we can DMA blocks larger than blksz - it may hang the DMA ++ channel but we are its only user */ ++ bytes = sg_dma_len(&data->sg[sg_ix]) - host_priv->sg_done; ++ addr = sg_dma_address(&data->sg[sg_ix]) + host_priv->sg_done; ++ ++ if (bytes > 0) { ++ /* We're going to poll for read/write available state until ++ we finish this DMA ++ */ ++ ++ if (data->flags & MMC_DATA_READ) { ++ if (*ref_intmask & SDHCI_INT_DATA_AVAIL) { ++ sdhci_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | ++ SDHCI_INT_SPACE_AVAIL); ++ sdhci_platdma_read(host, addr, bytes); ++ } ++ } else { ++ if (*ref_intmask & SDHCI_INT_SPACE_AVAIL) { ++ sdhci_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | ++ SDHCI_INT_SPACE_AVAIL); ++ sdhci_platdma_write(host, addr, bytes); ++ } ++ } ++ } ++ /* else: ++ we have run out of bytes that need transferring (e.g. we may be in ++ the middle of the last DMA transfer), or ++ it is also possible that we've been called when another IRQ is ++ signalled, even though we've turned off signalling of our own IRQ */ ++ ++ *ref_intmask &= ~SDHCI_INT_DATA_END; ++ /* don't let the main sdhci driver act on this .. we'll deal with it ++ when we respond to the DMA - if one is currently in progress */ ++} ++ ++/* is it possible to DMA the given mmc_data structure? ++ Platform DMA exported function ++*/ ++int /*bool*/ ++sdhci_bcm2708_platdma_dmaable(struct sdhci_host *host, struct mmc_data *data) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ int ok = bcm_sg_suitable_for_dma(data->sg, data->sg_len); ++ ++ if (!ok) ++ DBG("Reverting to PIO - bad cache alignment\n"); ++ ++ else { ++ host_priv->sg_ix = 0; /* first SG index */ ++ host_priv->sg_done = 0; /* no bytes done */ ++ } ++ ++ return ok; ++} ++ ++#include //GRAYG ++/*! the current SD transacton has been abandonned ++ We need to tidy up if we were in the middle of a DMA ++ Platform DMA exported function ++*/ ++void ++sdhci_bcm2708_platdma_reset(struct sdhci_host *host, struct mmc_data *data) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ unsigned long flags; ++ ++ BUG_ON(NULL == host); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ if (host_priv->dma_wanted) { ++ if (NULL == data) { ++ printk(KERN_ERR "%s: ongoing DMA reset - no data!\n", ++ mmc_hostname(host->mmc)); ++ BUG_ON(NULL == data); ++ } else { ++ struct scatterlist *sg; ++ int sg_len; ++ int sg_todo; ++ int rc; ++ unsigned long cs; ++ ++ sg = data->sg; ++ sg_len = data->sg_len; ++ sg_todo = sg_dma_len(&sg[host_priv->sg_ix]); ++ ++ cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS); ++ ++ if (!(BCM2708_DMA_ACTIVE & cs)) ++ printk(KERN_INFO "%s: missed completion of " ++ "cmd %d DMA (%d/%d [%d]/[%d]) - " ++ "ignoring it\n", ++ mmc_hostname(host->mmc), ++ host->last_cmdop, ++ host_priv->sg_done, sg_todo, ++ host_priv->sg_ix+1, sg_len); ++ else ++ printk(KERN_INFO "%s: resetting ongoing cmd %d" ++ "DMA before %d/%d [%d]/[%d] complete\n", ++ mmc_hostname(host->mmc), ++ host->last_cmdop, ++ host_priv->sg_done, sg_todo, ++ host_priv->sg_ix+1, sg_len); ++#ifdef CHECK_DMA_USE ++ printk(KERN_INFO "%s: now %"FMT_HPT" started %lu " ++ "last reset %lu last stopped %lu\n", ++ mmc_hostname(host->mmc), ++ hptime(), since_ns(host_priv->when_started), ++ since_ns(host_priv->when_reset), ++ since_ns(host_priv->when_stopped)); ++ { unsigned long info, debug; ++ void __iomem *base; ++ unsigned long pend0, pend1, pend2; ++ ++ base = host_priv->dma_chan_base; ++ cs = readl(base + BCM2708_DMA_CS); ++ info = readl(base + BCM2708_DMA_INFO); ++ debug = readl(base + BCM2708_DMA_DEBUG); ++ printk(KERN_INFO "%s: DMA%d CS=%08lX TI=%08lX " ++ "DEBUG=%08lX\n", ++ mmc_hostname(host->mmc), ++ host_priv->dma_chan, ++ cs, info, debug); ++ pend0 = readl(__io_address(ARM_IRQ_PEND0)); ++ pend1 = readl(__io_address(ARM_IRQ_PEND1)); ++ pend2 = readl(__io_address(ARM_IRQ_PEND2)); ++ ++ printk(KERN_INFO "%s: PEND0=%08lX " ++ "PEND1=%08lX PEND2=%08lX\n", ++ mmc_hostname(host->mmc), ++ pend0, pend1, pend2); ++ ++ //gintsts = readl(__io_address(GINTSTS)); ++ //gintmsk = readl(__io_address(GINTMSK)); ++ //printk(KERN_INFO "%s: USB GINTSTS=%08lX" ++ // "GINTMSK=%08lX\n", ++ // mmc_hostname(host->mmc), gintsts, gintmsk); ++ } ++#endif ++ rc = bcm_dma_abort(host_priv->dma_chan_base); ++ BUG_ON(rc != 0); ++ } ++ host_priv->dma_wanted = 0; ++#ifdef CHECK_DMA_USE ++ host_priv->when_reset = hptime(); ++#endif ++ } ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++ ++static void sdhci_bcm2708_dma_complete_irq(struct sdhci_host *host, ++ u32 dma_cs) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ struct mmc_data *data; ++ struct scatterlist *sg; ++ int sg_len; ++ int sg_ix; ++ int sg_todo; ++ unsigned long flags; ++ ++ BUG_ON(NULL == host); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ data = host->data; ++ ++#ifdef CHECK_DMA_USE ++ if (host_priv->dmas_pending <= 0) ++ DBG("on completion no DMA in progress - " ++ "now %"FMT_HPT" started %lu reset %lu stopped %lu\n", ++ hptime(), since_ns(host_priv->when_started), ++ since_ns(host_priv->when_reset), ++ since_ns(host_priv->when_stopped)); ++ else if (host_priv->dmas_pending > 1) ++ DBG("still %d DMA in progress after completion - " ++ "now %"FMT_HPT" started %lu reset %lu stopped %lu\n", ++ host_priv->dmas_pending - 1, ++ hptime(), since_ns(host_priv->when_started), ++ since_ns(host_priv->when_reset), ++ since_ns(host_priv->when_stopped)); ++ BUG_ON(host_priv->dmas_pending <= 0); ++ host_priv->dmas_pending -= 1; ++ host_priv->when_stopped = hptime(); ++#endif ++ host_priv->dma_wanted = 0; ++ ++ if (NULL == data) { ++ DBG("PDMA unused completion - status 0x%X\n", dma_cs); ++ spin_unlock_irqrestore(&host->lock, flags); ++ return; ++ } ++ sg = data->sg; ++ sg_len = data->sg_len; ++ sg_todo = sg_dma_len(&sg[host_priv->sg_ix]); ++ ++ DBG("PDMA complete %d/%d [%d]/[%d]..\n", ++ host_priv->sg_done, sg_todo, ++ host_priv->sg_ix+1, sg_len); ++ ++ BUG_ON(host_priv->sg_done > sg_todo); ++ ++ if (host_priv->sg_done >= sg_todo) { ++ host_priv->sg_ix++; ++ host_priv->sg_done = 0; ++ } ++ ++ sg_ix = host_priv->sg_ix; ++ if (sg_ix < sg_len) { ++ u32 irq_mask; ++ /* Set off next DMA if we've got the capacity */ ++ ++ if (data->flags & MMC_DATA_READ) ++ irq_mask = SDHCI_INT_DATA_AVAIL; ++ else ++ irq_mask = SDHCI_INT_SPACE_AVAIL; ++ ++ /* We have to use the interrupt status register on the BCM2708 ++ rather than the SDHCI_PRESENT_STATE register because latency ++ in the glue logic means that the information retrieved from ++ the latter is not always up-to-date w.r.t the DMA engine - ++ it may not indicate that a read or a write is ready yet */ ++ if (sdhci_bcm2708_raw_readl(host, SDHCI_INT_STATUS) & ++ irq_mask) { ++ size_t bytes = sg_dma_len(&sg[sg_ix]) - ++ host_priv->sg_done; ++ dma_addr_t addr = sg_dma_address(&data->sg[sg_ix]) + ++ host_priv->sg_done; ++ ++ /* acknowledge interrupt */ ++ sdhci_bcm2708_raw_writel(host, irq_mask, ++ SDHCI_INT_STATUS); ++ ++ BUG_ON(0 == bytes); ++ ++ if (data->flags & MMC_DATA_READ) ++ sdhci_platdma_read(host, addr, bytes); ++ else ++ sdhci_platdma_write(host, addr, bytes); ++ } else { ++ DBG("PDMA - wait avail\n"); ++ /* may generate an IRQ if already present */ ++ sdhci_signal_irqs(host, SDHCI_INT_DATA_AVAIL | ++ SDHCI_INT_SPACE_AVAIL); ++ } ++ } else { ++#ifdef USE_SYNC_AFTER_DMA ++ /* On the Arasan controller the stop command (which will be ++ scheduled after this completes) does not seem to work ++ properly if we allow it to be issued when we are ++ transferring data to/from the SD card. ++ We get CRC and DEND errors unless we wait for ++ the SD controller to finish reading/writing to the card. */ ++ u32 state_mask; ++ int timeout=1000000; ++ hptime_t now = hptime(); ++ ++ DBG("PDMA over - sync card\n"); ++ if (data->flags & MMC_DATA_READ) ++ state_mask = SDHCI_DOING_READ; ++ else ++ state_mask = SDHCI_DOING_WRITE; ++ ++ while (0 != (sdhci_bcm2708_raw_readl(host, ++ SDHCI_PRESENT_STATE) & ++ state_mask) && --timeout > 0) ++ continue; ++ ++ if (1000000-timeout > 4000) /*ave. is about 3250*/ ++ printk(KERN_INFO "%s: note - long %s sync %luns - " ++ "%d its.\n", ++ mmc_hostname(host->mmc), ++ data->flags & MMC_DATA_READ? "read": "write", ++ since_ns(now), 1000000-timeout); ++ if (timeout <= 0) ++ printk(KERN_ERR"%s: final %s to SD card still " ++ "running\n", ++ mmc_hostname(host->mmc), ++ data->flags & MMC_DATA_READ? "read": "write"); ++#endif ++ if (host_priv->complete) { ++ (*host_priv->complete)(host); ++ DBG("PDMA %s complete\n", ++ data->flags & MMC_DATA_READ?"read":"write"); ++ sdhci_signal_irqs(host, SDHCI_INT_DATA_AVAIL | ++ SDHCI_INT_SPACE_AVAIL); ++ } ++ } ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static irqreturn_t sdhci_bcm2708_dma_irq(int irq, void *dev_id) ++{ ++ irqreturn_t result = IRQ_NONE; ++ struct sdhci_host *host = dev_id; ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ u32 dma_cs; /* control and status register */ ++ unsigned long flags; ++ ++ BUG_ON(NULL == dev_id); ++ BUG_ON(NULL == host_priv->dma_chan_base); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ dma_cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS); ++ ++ if (dma_cs & BCM2708_DMA_ERR) { ++ unsigned long debug; ++ debug = readl(host_priv->dma_chan_base + ++ BCM2708_DMA_DEBUG); ++ printk(KERN_ERR "%s: DMA error - CS %lX DEBUG %lX\n", ++ mmc_hostname(host->mmc), (unsigned long)dma_cs, ++ (unsigned long)debug); ++ /* reset error */ ++ writel(debug, host_priv->dma_chan_base + ++ BCM2708_DMA_DEBUG); ++ } ++ if (dma_cs & BCM2708_DMA_INT) { ++ /* acknowledge interrupt */ ++ writel(BCM2708_DMA_INT, ++ host_priv->dma_chan_base + BCM2708_DMA_CS); ++ ++ dsb(); /* ARM data synchronization (push) operation */ ++ ++ if (!host_priv->dma_wanted) { ++ /* ignore this interrupt - it was reset */ ++ printk(KERN_INFO "%s: DMA IRQ %X ignored - " ++ "results were reset\n", ++ mmc_hostname(host->mmc), dma_cs); ++#ifdef CHECK_DMA_USE ++ printk(KERN_INFO "%s: now %"FMT_HPT ++ " started %lu reset %lu stopped %lu\n", ++ mmc_hostname(host->mmc), hptime(), ++ since_ns(host_priv->when_started), ++ since_ns(host_priv->when_reset), ++ since_ns(host_priv->when_stopped)); ++ host_priv->dmas_pending--; ++#endif ++ } else ++ sdhci_bcm2708_dma_complete_irq(host, dma_cs); ++ ++ result = IRQ_HANDLED; ++ } ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ return result; ++} ++#endif /* CONFIG_MMC_SDHCI_BCM2708_DMA */ ++ ++ ++/***************************************************************************** \ ++ * * ++ * Device Attributes * ++ * * ++\*****************************************************************************/ ++ ++ ++/** ++ * Show the DMA-using status ++ */ ++static ssize_t attr_dma_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); ++ ++ if (host) { ++ int use_dma = (host->flags & SDHCI_USE_PLATDMA? 1:0); ++ return sprintf(buf, "%d\n", use_dma); ++ } else ++ return -EINVAL; ++} ++ ++/** ++ * Set the DMA-using status ++ */ ++static ssize_t attr_dma_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); ++ ++ if (host) { ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ int on = simple_strtol(buf, NULL, 0); ++ if (on) { ++ host->flags |= SDHCI_USE_PLATDMA; ++ printk(KERN_INFO "%s: DMA enabled\n", ++ mmc_hostname(host->mmc)); ++ } else { ++ host->flags &= ~(SDHCI_USE_PLATDMA | SDHCI_REQ_USE_DMA); ++ printk(KERN_INFO "%s: DMA disabled\n", ++ mmc_hostname(host->mmc)); ++ } ++#endif ++ return count; ++ } else ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(use_dma, S_IRUGO | S_IWUGO, attr_dma_show, attr_dma_store); ++ ++ ++/** ++ * Show the DMA wait states used ++ */ ++static ssize_t attr_dmawait_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); ++ ++ if (host) { ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ int dmawait = host_priv->dma_waits; ++ return sprintf(buf, "%d\n", dmawait); ++ } else ++ return -EINVAL; ++} ++ ++/** ++ * Set the DMA wait state used ++ */ ++static ssize_t attr_dmawait_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); ++ ++ if (host) { ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ int dma_waits = simple_strtol(buf, NULL, 0); ++ if (dma_waits >= 0 && dma_waits < 32) ++ host_priv->dma_waits = dma_waits; ++ else ++ printk(KERN_ERR "%s: illegal dma_waits value - %d", ++ mmc_hostname(host->mmc), dma_waits); ++#endif ++ return count; ++ } else ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(dma_wait, S_IRUGO | S_IWUGO, ++ attr_dmawait_show, attr_dmawait_store); ++ ++ ++/** ++ * Show the DMA-using status ++ */ ++static ssize_t attr_status_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); ++ ++ if (host) { ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ int power_state = host_priv->power_state; ++ return sprintf(buf, ++ "present: yes\n" ++ "power: %s\n" ++ "clock: %u Hz\n" ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ "dma: %s (%d waits)\n", ++#else ++ "dma: unconfigured\n", ++#endif ++ power_state == POWER_ON? "on": ++ power_state == POWER_OFF? "off": ++ power_state == POWER_LAZY_OFF? "lazy-off": ++ "", ++ host->clock ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ , (host->flags & SDHCI_USE_PLATDMA)? "on": "off" ++ , host_priv->dma_waits ++#endif ++ ); ++ } else ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(status, S_IRUGO, attr_status_show, NULL); ++ ++/***************************************************************************** \ ++ * * ++ * Power Management * ++ * * ++\*****************************************************************************/ ++ ++ ++#ifdef CONFIG_PM ++static int sdhci_bcm2708_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ struct sdhci_host *host = (struct sdhci_host *) ++ platform_get_drvdata(dev); ++ int ret = 0; ++ ++ if (host->mmc) { ++ ret = mmc_suspend_host(host->mmc); ++ } ++ ++ return ret; ++} ++ ++static int sdhci_bcm2708_resume(struct platform_device *dev) ++{ ++ struct sdhci_host *host = (struct sdhci_host *) ++ platform_get_drvdata(dev); ++ int ret = 0; ++ ++ if (host->mmc) { ++ ret = mmc_resume_host(host->mmc); ++ } ++ ++ return ret; ++} ++#endif ++ ++ ++/* Click forwards one step towards fully on */ ++static int sdhci_bcm2708_enable(struct sdhci_host *host) ++{ ++ int rc; ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ ++ if (host_priv->power_state == POWER_OFF) { ++ /* warning: may schedule - don't call in irq mode */ ++ rc = bcm_power_request(host_priv->power_handle, ++ BCM_POWER_SDCARD); ++ ++ if (rc == 0) { ++ mmc_power_restore_host(host->mmc); ++ host_priv->power_state = POWER_ON; ++ } else if (rc != -EINTR) ++ printk(KERN_ERR "%s: mmc power up request failed - " ++ "rc %d\n", ++ mmc_hostname(host->mmc), rc); ++ } else { ++ host_priv->power_state = POWER_ON; ++ rc = 0; ++ } ++ ++ return rc; ++} ++ ++/* Click backwards one step towards fully off */ ++static int sdhci_bcm2708_disable(struct sdhci_host *host, int lazy) ++{ ++ int rc; ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ ++ if ((host_priv->power_state == POWER_ON) && lazy) { ++ host_priv->power_state = POWER_LAZY_OFF; ++ return BCM2708_SDHCI_SLEEP_TIMEOUT; ++ } ++ ++ /* warning: may schedule - don't call in irq mode */ ++ rc = bcm_power_request(host_priv->power_handle, BCM_POWER_NONE); ++ ++ if (rc == 0) ++ host_priv->power_state = POWER_OFF; ++ else if (rc != -EINTR) ++ printk(KERN_ERR "%s: mmc power down request failed - rc %d\n", ++ mmc_hostname(host->mmc), rc); ++ ++ return rc; ++} ++ ++static int sdhci_bcm2708_set_plat_power(struct sdhci_host *host, ++ int power_mode) ++{ ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ int rc; ++ ++ do { ++ rc = mmc_host_enable(host->mmc); ++ } while (-EINTR == rc); ++ ++ if (rc == 0) do { ++ if (rc == 0 && power_mode != host_priv->power_mode) ++ { ++ switch (power_mode) ++ { ++ case MMC_POWER_OFF: ++ rc = bcm_power_request(host_priv->power_handle, ++ BCM_POWER_NONE); ++ break; ++ ++ case MMC_POWER_UP: ++ rc = bcm_power_request(host_priv->power_handle, ++ BCM_POWER_SDCARD); ++ /* ++ * We need an extra 10ms delay of 10ms before we ++ * can apply clock after applying power ++ */ ++ if (rc == 0) ++ mdelay(10); ++ break; ++ ++ case MMC_POWER_ON: ++ mdelay(10); ++ /* do_send_init_stream = 1; */ ++ break; ++ } ++ ++ if (rc == 0) ++ host_priv->power_mode = power_mode; ++ } ++ } while (-EINTR == rc); ++ ++ if (rc == 0) do { ++ if (rc == 0) { ++ if (power_mode == MMC_POWER_OFF) ++ rc = mmc_host_disable(host->mmc); ++ else ++ rc = mmc_host_lazy_disable(host->mmc); ++ } ++ ++ } while (-EINTR == rc); ++ ++ return rc; ++} ++ ++/*****************************************************************************\ ++ * * ++ * Device quirk functions. Implemented as local ops because the flags * ++ * field is out of space with newer kernels. This implementation can be * ++ * back ported to older kernels as well. * ++\****************************************************************************/ ++static unsigned int sdhci_bcm2708_quirk_extra_ints(struct sdhci_host *host) ++{ ++ return 1; ++} ++ ++static unsigned int sdhci_bcm2708_quirk_spurious_crc(struct sdhci_host *host) ++{ ++ return 1; ++} ++ ++static unsigned int sdhci_bcm2708_quirk_voltage_broken(struct sdhci_host *host) ++{ ++ return 1; ++} ++ ++static unsigned int sdhci_bcm2708_uhs_broken(struct sdhci_host *host) ++{ ++ return 1; ++} ++ ++/***************************************************************************** \ ++ * * ++ * Device ops * ++ * * ++\*****************************************************************************/ ++ ++static struct sdhci_ops sdhci_bcm2708_ops = { ++#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS ++ .read_l = sdhci_bcm2708_readl, ++ .read_w = sdhci_bcm2708_readw, ++ .read_b = sdhci_bcm2708_readb, ++ .write_l = sdhci_bcm2708_writel, ++ .write_w = sdhci_bcm2708_writew, ++ .write_b = sdhci_bcm2708_writeb, ++#else ++#error The BCM2708 SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set ++#endif ++ //.enable_dma = NULL, ++ //.set_clock = NULL, ++ .get_max_clock = sdhci_bcm2708_get_max_clock, ++ //.get_min_clock = NULL, ++ .get_timeout_clock = sdhci_bcm2708_get_timeout_clock, ++ ++ .enable = sdhci_bcm2708_enable, ++ .disable = sdhci_bcm2708_disable, ++ .set_plat_power = sdhci_bcm2708_set_plat_power, ++ ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ // Platform DMA operations ++ .pdma_able = sdhci_bcm2708_platdma_dmaable, ++ .pdma_avail = sdhci_bcm2708_platdma_avail, ++ .pdma_reset = sdhci_bcm2708_platdma_reset, ++#endif ++ .extra_ints = sdhci_bcm2708_quirk_extra_ints, ++ .spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc, ++ .voltage_broken = sdhci_bcm2708_quirk_voltage_broken, ++ .uhs_broken = sdhci_bcm2708_uhs_broken, ++}; ++ ++/*****************************************************************************\ ++ * * ++ * Device probing/removal * ++ * * ++\*****************************************************************************/ ++ ++static int __devinit sdhci_bcm2708_probe(struct platform_device *pdev) ++{ ++ struct sdhci_host *host; ++ struct resource *iomem; ++ struct sdhci_bcm2708_priv *host_priv; ++ int ret; ++ ++ BUG_ON(pdev == NULL); ++ ++ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!iomem) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ if (resource_size(iomem) != 0x100) ++ dev_err(&pdev->dev, "Invalid iomem size. You may " ++ "experience problems.\n"); ++ ++ if (pdev->dev.parent) ++ host = sdhci_alloc_host(pdev->dev.parent, ++ sizeof(struct sdhci_bcm2708_priv)); ++ else ++ host = sdhci_alloc_host(&pdev->dev, ++ sizeof(struct sdhci_bcm2708_priv)); ++ ++ if (IS_ERR(host)) { ++ ret = PTR_ERR(host); ++ goto err; ++ } ++ ++ host->hw_name = "BCM2708_Arasan"; ++ host->ops = &sdhci_bcm2708_ops; ++ host->irq = platform_get_irq(pdev, 0); ++ ++ host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | ++ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ host->flags = SDHCI_USE_PLATDMA; ++#endif ++ ++ if (!request_mem_region(iomem->start, resource_size(iomem), ++ mmc_hostname(host->mmc))) { ++ dev_err(&pdev->dev, "cannot request region\n"); ++ ret = -EBUSY; ++ goto err_request; ++ } ++ ++ host->ioaddr = ioremap(iomem->start, resource_size(iomem)); ++ if (!host->ioaddr) { ++ dev_err(&pdev->dev, "failed to remap registers\n"); ++ ret = -ENOMEM; ++ goto err_remap; ++ } ++ ++ host_priv = SDHCI_HOST_PRIV(host); ++ ++ host_priv->power_state = POWER_ON; ++ ret = bcm_power_open(&host_priv->power_handle); ++ if (ret != 0) ++ goto err_power; ++ ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ host_priv->dma_wanted = 0; ++#ifdef CHECK_DMA_USE ++ host_priv->dmas_pending = 0; ++ host_priv->when_started = 0; ++ host_priv->when_reset = 0; ++ host_priv->when_stopped = 0; ++#endif ++ host_priv->sg_ix = 0; ++ host_priv->sg_done = 0; ++ host_priv->complete = NULL; ++ host_priv->dma_waits = SDHCI_BCM_DMA_WAITS; ++ ++ host_priv->cb_base = dma_alloc_writecombine(&pdev->dev, SZ_4K, ++ &host_priv->cb_handle, ++ GFP_KERNEL); ++ if (!host_priv->cb_base) { ++ dev_err(&pdev->dev, "cannot allocate DMA CBs\n"); ++ ret = -ENOMEM; ++ goto err_alloc_cb; ++ } ++ ++ ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, ++ &host_priv->dma_chan_base, ++ &host_priv->dma_irq); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "couldn't allocate a DMA channel\n"); ++ goto err_add_dma; ++ } ++ host_priv->dma_chan = ret; ++ ++ ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq, ++ IRQF_SHARED, DRIVER_NAME " (dma)", host); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot set DMA IRQ\n"); ++ goto err_add_dma_irq; ++ } ++ DBG("DMA CBs %p handle %08X DMA%d %p DMA IRQ %d\n", ++ host_priv->cb_base, (unsigned)host_priv->cb_handle, ++ host_priv->dma_chan, host_priv->dma_chan_base, ++ host_priv->dma_irq); ++#endif ++ ++ ret = sdhci_add_host(host); ++ if (ret) ++ goto err_add_host; ++ ++ platform_set_drvdata(pdev, host); ++ ret = device_create_file(&pdev->dev, &dev_attr_use_dma); ++ ret = device_create_file(&pdev->dev, &dev_attr_dma_wait); ++ ret = device_create_file(&pdev->dev, &dev_attr_status); ++ ++ printk(KERN_INFO "%s: BCM2708 SDHC host at 0x%08llx DMA %d IRQ %d\n", ++ mmc_hostname(host->mmc), (unsigned long long)iomem->start, ++ host_priv->dma_chan, host_priv->dma_irq); ++ ++ return 0; ++ ++err_add_host: ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ free_irq(host_priv->dma_irq, host); ++err_add_dma_irq: ++ bcm_dma_chan_free(host_priv->dma_chan); ++err_add_dma: ++ dma_free_writecombine(&pdev->dev, SZ_4K, host_priv->cb_base, ++ host_priv->cb_handle); ++err_alloc_cb: ++#endif ++ bcm_power_close(host_priv->power_handle); ++err_power: ++ iounmap(host->ioaddr); ++err_remap: ++ release_mem_region(iomem->start, resource_size(iomem)); ++err_request: ++ sdhci_free_host(host); ++err: ++ dev_err(&pdev->dev, "probe failed, err %d\n", ret); ++ return ret; ++} ++ ++static int __devexit sdhci_bcm2708_remove(struct platform_device *pdev) ++{ ++ struct sdhci_host *host = platform_get_drvdata(pdev); ++ struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); ++ int dead; ++ u32 scratch; ++ ++ dead = 0; ++ scratch = sdhci_bcm2708_readl(host, SDHCI_INT_STATUS); ++ if (scratch == (u32)-1) ++ dead = 1; ++ ++ device_remove_file(&pdev->dev, &dev_attr_status); ++ device_remove_file(&pdev->dev, &dev_attr_dma_wait); ++ device_remove_file(&pdev->dev, &dev_attr_use_dma); ++ ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ free_irq(host_priv->dma_irq, host); ++ dma_free_writecombine(&pdev->dev, SZ_4K, host_priv->cb_base, ++ host_priv->cb_handle); ++#endif ++ bcm_power_close(host_priv->power_handle); ++ sdhci_remove_host(host, dead); ++ iounmap(host->ioaddr); ++ release_mem_region(iomem->start, resource_size(iomem)); ++ sdhci_free_host(host); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver sdhci_bcm2708_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = sdhci_bcm2708_probe, ++ .remove = __devexit_p(sdhci_bcm2708_remove), ++ ++#ifdef CONFIG_PM ++ .suspend = sdhci_bcm2708_suspend, ++ .resume = sdhci_bcm2708_resume, ++#endif ++ ++}; ++ ++/*****************************************************************************\ ++ * * ++ * Driver init/exit * ++ * * ++\*****************************************************************************/ ++ ++static int __init sdhci_drv_init(void) ++{ ++ return platform_driver_register(&sdhci_bcm2708_driver); ++} ++ ++static void __exit sdhci_drv_exit(void) ++{ ++ platform_driver_unregister(&sdhci_bcm2708_driver); ++} ++ ++module_init(sdhci_drv_init); ++module_exit(sdhci_drv_exit); ++ ++MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver"); ++MODULE_AUTHOR("Broadcom "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:"DRIVER_NAME); ++ +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -27,6 +27,7 @@ + + #include + #include ++#include + + #include "sdhci.h" + +@@ -66,6 +67,7 @@ static inline int sdhci_runtime_pm_put(s + } + #endif + ++ + static void sdhci_dumpregs(struct sdhci_host *host) + { + pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", +@@ -150,6 +152,9 @@ static void sdhci_set_card_detection(str + (host->mmc->caps & MMC_CAP_NONREMOVABLE)) + return; + ++ if (host->quirks2 & SDHCI_QUIRK2_OWN_CARD_DETECTION) ++ return; ++ + present = sdhci_readl(host, SDHCI_PRESENT_STATE) & + SDHCI_CARD_PRESENT; + irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT; +@@ -299,7 +304,7 @@ static void sdhci_read_block_pio(struct + u32 uninitialized_var(scratch); + u8 *buf; + +- DBG("PIO reading\n"); ++ DBG("PIO reading %db\n", host->data->blksz); + + blksize = host->data->blksz; + chunk = 0; +@@ -344,7 +349,7 @@ static void sdhci_write_block_pio(struct + u32 scratch; + u8 *buf; + +- DBG("PIO writing\n"); ++ DBG("PIO writing %db\n", host->data->blksz); + + blksize = host->data->blksz; + chunk = 0; +@@ -383,19 +388,28 @@ static void sdhci_write_block_pio(struct + local_irq_restore(flags); + } + +-static void sdhci_transfer_pio(struct sdhci_host *host) ++static void sdhci_transfer_pio(struct sdhci_host *host, u32 intstate) + { + u32 mask; ++ u32 state = 0; ++ u32 intmask; ++ int available; + + BUG_ON(!host->data); + + if (host->blocks == 0) + return; + +- if (host->data->flags & MMC_DATA_READ) ++ if (host->data->flags & MMC_DATA_READ) { + mask = SDHCI_DATA_AVAILABLE; +- else ++ intmask = SDHCI_INT_DATA_AVAIL; ++ } else { + mask = SDHCI_SPACE_AVAILABLE; ++ intmask = SDHCI_INT_SPACE_AVAIL; ++ } ++ ++ /* initially we can see whether we can procede using intstate */ ++ available = (intstate & intmask); + + /* + * Some controllers (JMicron JMB38x) mess up the buffer bits +@@ -406,7 +420,7 @@ static void sdhci_transfer_pio(struct sd + (host->data->blocks == 1)) + mask = ~0; + +- while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { ++ while (available) { + if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) + udelay(100); + +@@ -418,9 +432,11 @@ static void sdhci_transfer_pio(struct sd + host->blocks--; + if (host->blocks == 0) + break; ++ state = sdhci_readl(host, SDHCI_PRESENT_STATE); ++ available = state & mask; + } + +- DBG("PIO transfer complete.\n"); ++ DBG("PIO transfer complete - %d blocks left.\n", host->blocks); + } + + static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) +@@ -693,7 +709,9 @@ static void sdhci_set_transfer_irqs(stru + u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; + u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; + +- if (host->flags & SDHCI_REQ_USE_DMA) ++ /* platform DMA will begin on receipt of PIO irqs */ ++ if ((host->flags & SDHCI_REQ_USE_DMA) && ++ !(host->flags & SDHCI_USE_PLATDMA)) + sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); + else + sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); +@@ -725,44 +743,25 @@ static void sdhci_prepare_data(struct sd + host->data_early = 0; + host->data->bytes_xfered = 0; + +- if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) ++ if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA | SDHCI_USE_PLATDMA)) + host->flags |= SDHCI_REQ_USE_DMA; + + /* + * FIXME: This doesn't account for merging when mapping the + * scatterlist. + */ +- if (host->flags & SDHCI_REQ_USE_DMA) { +- int broken, i; +- struct scatterlist *sg; +- +- broken = 0; +- if (host->flags & SDHCI_USE_ADMA) { +- if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) +- broken = 1; +- } else { +- if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) +- broken = 1; +- } +- +- if (unlikely(broken)) { +- for_each_sg(data->sg, sg, data->sg_len, i) { +- if (sg->length & 0x3) { +- DBG("Reverting to PIO because of " +- "transfer size (%d)\n", +- sg->length); +- host->flags &= ~SDHCI_REQ_USE_DMA; +- break; +- } +- } +- } +- } + + /* + * The assumption here being that alignment is the same after + * translation to device address space. + */ +- if (host->flags & SDHCI_REQ_USE_DMA) { ++ if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_PLATDMA)) == ++ (SDHCI_REQ_USE_DMA | SDHCI_USE_PLATDMA)) { ++ ++ if (! sdhci_platdma_dmaable(host, data)) ++ host->flags &= ~SDHCI_REQ_USE_DMA; ++ ++ } else if (host->flags & SDHCI_REQ_USE_DMA) { + int broken, i; + struct scatterlist *sg; + +@@ -821,7 +820,8 @@ static void sdhci_prepare_data(struct sd + */ + WARN_ON(1); + host->flags &= ~SDHCI_REQ_USE_DMA; +- } else { ++ } else ++ if (!(host->flags & SDHCI_USE_PLATDMA)) { + WARN_ON(sg_cnt != 1); + sdhci_writel(host, sg_dma_address(data->sg), + SDHCI_DMA_ADDRESS); +@@ -837,11 +837,13 @@ static void sdhci_prepare_data(struct sd + if (host->version >= SDHCI_SPEC_200) { + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + ctrl &= ~SDHCI_CTRL_DMA_MASK; +- if ((host->flags & SDHCI_REQ_USE_DMA) && +- (host->flags & SDHCI_USE_ADMA)) +- ctrl |= SDHCI_CTRL_ADMA32; +- else +- ctrl |= SDHCI_CTRL_SDMA; ++ if (! (host->flags & SDHCI_USE_PLATDMA)) { ++ if ((host->flags & SDHCI_REQ_USE_DMA) && ++ (host->flags & SDHCI_USE_ADMA)) ++ ctrl |= SDHCI_CTRL_ADMA32; ++ else ++ ctrl |= SDHCI_CTRL_SDMA; ++ } + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + } + +@@ -893,7 +895,8 @@ static void sdhci_set_transfer_mode(stru + + if (data->flags & MMC_DATA_READ) + mode |= SDHCI_TRNS_READ; +- if (host->flags & SDHCI_REQ_USE_DMA) ++ if ((host->flags & SDHCI_REQ_USE_DMA) && ++ !(host->flags & SDHCI_USE_PLATDMA)) + mode |= SDHCI_TRNS_DMA; + + sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); +@@ -909,13 +912,16 @@ static void sdhci_finish_data(struct sdh + host->data = NULL; + + if (host->flags & SDHCI_REQ_USE_DMA) { +- if (host->flags & SDHCI_USE_ADMA) +- sdhci_adma_table_post(host, data); +- else { ++ /* we may have to abandon an ongoing platform DMA */ ++ if (host->flags & SDHCI_USE_PLATDMA) ++ sdhci_platdma_reset(host, data); ++ ++ if (host->flags & (SDHCI_USE_PLATDMA | SDHCI_USE_SDMA)) { + dma_unmap_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, (data->flags & MMC_DATA_READ) ? + DMA_FROM_DEVICE : DMA_TO_DEVICE); +- } ++ } else if (host->flags & SDHCI_USE_ADMA) ++ sdhci_adma_table_post(host, data); + } + + /* +@@ -985,10 +991,16 @@ static void sdhci_send_command(struct sd + timeout--; + mdelay(1); + } ++ DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask, ++ sdhci_readl(host, SDHCI_INT_STATUS)); + + mod_timer(&host->timer, jiffies + 10 * HZ); + + host->cmd = cmd; ++ if (host->last_cmdop == MMC_APP_CMD) ++ host->last_cmdop = -cmd->opcode; ++ else ++ host->last_cmdop = cmd->opcode; + + sdhci_prepare_data(host, cmd); + +@@ -1234,6 +1246,35 @@ static int sdhci_set_power(struct sdhci_ + return power; + } + ++/* Power on or off the circuitary supporting the register set */ ++static int sdhci_set_plat_power(struct sdhci_host *host, int power_mode) ++{ ++ if (host->ops->set_plat_power) ++ return host->ops->set_plat_power(host, power_mode); ++ else ++ return 0; ++} ++ ++/* Click forwards one step towards fully on */ ++static int sdhci_enable(struct mmc_host *mmc) ++{ ++ struct sdhci_host *host; ++ ++ host = mmc_priv(mmc); ++ ++ return host->ops->enable? host->ops->enable(host): 0; ++} ++ ++/* Click backwards one step towards fully off */ ++static int sdhci_disable(struct mmc_host *mmc, int lazy) ++{ ++ struct sdhci_host *host; ++ ++ host = mmc_priv(mmc); ++ ++ return host->ops->disable? host->ops->disable(host, lazy): 0; ++} ++ + /*****************************************************************************\ + * * + * MMC callbacks * +@@ -1250,6 +1291,8 @@ static void sdhci_request(struct mmc_hos + + sdhci_runtime_pm_get(host); + ++ sdhci_runtime_pm_get(host); ++ + spin_lock_irqsave(&host->lock, flags); + + WARN_ON(host->mrq != NULL); +@@ -1314,6 +1357,7 @@ static void sdhci_do_set_ios(struct sdhc + { + unsigned long flags; + int vdd_bit = -1; ++ int rc; + u8 ctrl; + + spin_lock_irqsave(&host->lock, flags); +@@ -1383,7 +1427,7 @@ static void sdhci_do_set_ios(struct sdhc + else + ctrl &= ~SDHCI_CTRL_HISPD; + +- if (host->version >= SDHCI_SPEC_300) { ++ if (host->version >= SDHCI_SPEC_300 && !(host->ops->uhs_broken)) { + u16 clk, ctrl_2; + unsigned int clock; + +@@ -1474,6 +1518,12 @@ static void sdhci_do_set_ios(struct sdhc + + mmiowb(); + spin_unlock_irqrestore(&host->lock, flags); ++ ++ if (ios->power_mode == MMC_POWER_OFF) { ++ do ++ rc = sdhci_set_plat_power(host, ios->power_mode); ++ while (rc == -EINTR); ++ } + } + + static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +@@ -1934,6 +1984,8 @@ static const struct mmc_host_ops sdhci_o + .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, + .execute_tuning = sdhci_execute_tuning, + .enable_preset_value = sdhci_enable_preset_value, ++ .enable = sdhci_enable, ++ .disable = sdhci_disable, + }; + + /*****************************************************************************\ +@@ -2091,10 +2143,13 @@ static void sdhci_cmd_irq(struct sdhci_h + BUG_ON(intmask == 0); + + if (!host->cmd) { +- pr_err("%s: Got command interrupt 0x%08x even " +- "though no command operation was in progress.\n", +- mmc_hostname(host->mmc), (unsigned)intmask); +- sdhci_dumpregs(host); ++ if (!(host->ops->extra_ints)) { ++ pr_err("%s: Got command interrupt 0x%08x even " ++ "though no command operation was in progress.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ sdhci_dumpregs(host); ++ } else ++ DBG("cmd irq 0x%08x cmd complete\n", (unsigned)intmask); + return; + } + +@@ -2164,6 +2219,19 @@ static void sdhci_show_adma_error(struct + static void sdhci_show_adma_error(struct sdhci_host *host) { } + #endif + ++static void sdhci_data_end(struct sdhci_host *host) ++{ ++ if (host->cmd) { ++ /* ++ * Data managed to finish before the ++ * command completed. Make sure we do ++ * things in the proper order. ++ */ ++ host->data_early = 1; ++ } else ++ sdhci_finish_data(host); ++} ++ + static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) + { + u32 command; +@@ -2192,35 +2260,57 @@ static void sdhci_data_irq(struct sdhci_ + return; + } + } +- +- pr_err("%s: Got data interrupt 0x%08x even " +- "though no data operation was in progress.\n", +- mmc_hostname(host->mmc), (unsigned)intmask); +- sdhci_dumpregs(host); +- +- return; +- } +- +- if (intmask & SDHCI_INT_DATA_TIMEOUT) +- host->data->error = -ETIMEDOUT; +- else if (intmask & SDHCI_INT_DATA_END_BIT) +- host->data->error = -EILSEQ; +- else if ((intmask & SDHCI_INT_DATA_CRC) && +- SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) +- != MMC_BUS_TEST_R) +- host->data->error = -EILSEQ; +- else if (intmask & SDHCI_INT_ADMA_ERROR) { ++ ++ if (!(host->ops->extra_ints)) { ++ pr_err("%s: Got data interrupt 0x%08x even " ++ "though no data operation was in progress.\n", ++ mmc_hostname(host->mmc), (unsigned)intmask); ++ sdhci_dumpregs(host); ++ } else ++ DBG("data irq 0x%08x but no data\n", (unsigned)intmask); ++ ++ return; ++ } ++ ++ if (intmask & SDHCI_INT_DATA_TIMEOUT) ++ host->data->error = -ETIMEDOUT; ++ else if (intmask & SDHCI_INT_DATA_END_BIT) { ++ DBG("end error in cmd %d\n", host->last_cmdop); ++ if (host->ops->spurious_crc_acmd51 && ++ host->last_cmdop == -SD_APP_SEND_SCR) { ++ DBG("ignoring spurious data_end_bit error\n"); ++ intmask = SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END; ++ } else ++ host->data->error = -EILSEQ; ++ } else if ((intmask & SDHCI_INT_DATA_CRC) && ++ SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) ++ != MMC_BUS_TEST_R) { ++ DBG("crc error in cmd %d\n", host->last_cmdop); ++ if (host->ops->spurious_crc_acmd51 && ++ host->last_cmdop == -SD_APP_SEND_SCR) { ++ DBG("ignoring spurious data_crc_bit error\n"); ++ intmask = SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END; ++ } else ++ host->data->error = -EILSEQ; ++ } else if (intmask & SDHCI_INT_ADMA_ERROR) { + pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); +- sdhci_show_adma_error(host); +- host->data->error = -EIO; +- } +- +- if (host->data->error) +- sdhci_finish_data(host); +- else { +- if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) +- sdhci_transfer_pio(host); +- ++ sdhci_show_adma_error(host); ++ host->data->error = -EIO; ++ } ++ ++ if (host->data->error) { ++ DBG("finish request early on error %d\n", host->data->error); ++ sdhci_finish_data(host); ++ } else { ++ if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) { ++ if (host->flags & SDHCI_REQ_USE_DMA) { ++ /* possible only in PLATDMA mode */ ++ sdhci_platdma_avail(host, &intmask, ++ &sdhci_data_end); ++ } else ++ sdhci_transfer_pio(host, intmask); ++ } ++ + /* + * We currently don't do anything fancy with DMA + * boundaries, but as we can't disable the feature +@@ -2249,16 +2339,7 @@ static void sdhci_data_irq(struct sdhci_ + } + + if (intmask & SDHCI_INT_DATA_END) { +- if (host->cmd) { +- /* +- * Data managed to finish before the +- * command completed. Make sure we do +- * things in the proper order. +- */ +- host->data_early = 1; +- } else { +- sdhci_finish_data(host); +- } ++ sdhci_data_end(host); + } + } + } +@@ -2314,6 +2395,22 @@ static irqreturn_t sdhci_irq(int irq, vo + tasklet_schedule(&host->card_tasklet); + } + ++ if (intmask & SDHCI_INT_ERROR_MASK & ~SDHCI_INT_ERROR) ++ DBG("controller reports error 0x%x -" ++ "%s%s%s%s%s%s%s%s%s%s", ++ intmask, ++ intmask & SDHCI_INT_TIMEOUT? " timeout": "", ++ intmask & SDHCI_INT_CRC ? " crc": "", ++ intmask & SDHCI_INT_END_BIT? " endbit": "", ++ intmask & SDHCI_INT_INDEX? " index": "", ++ intmask & SDHCI_INT_DATA_TIMEOUT? " data_timeout": "", ++ intmask & SDHCI_INT_DATA_CRC? " data_crc": "", ++ intmask & SDHCI_INT_DATA_END_BIT? " data_endbit": "", ++ intmask & SDHCI_INT_BUS_POWER? " buspower": "", ++ intmask & SDHCI_INT_ACMD12ERR? " acmd12": "", ++ intmask & SDHCI_INT_ADMA_ERROR? " adma": "" ++ ); ++ + if (intmask & SDHCI_INT_CMD_MASK) { + sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, + SDHCI_INT_STATUS); +@@ -2535,6 +2632,90 @@ EXPORT_SYMBOL_GPL(sdhci_runtime_resume_h + + #endif + ++#ifdef CONFIG_PM_RUNTIME ++ ++static int sdhci_runtime_pm_get(struct sdhci_host *host) ++{ ++ return pm_runtime_get_sync(host->mmc->parent); ++} ++ ++static int sdhci_runtime_pm_put(struct sdhci_host *host) ++{ ++ pm_runtime_mark_last_busy(host->mmc->parent); ++ return pm_runtime_put_autosuspend(host->mmc->parent); ++} ++ ++int sdhci_runtime_suspend_host(struct sdhci_host *host) ++{ ++ unsigned long flags; ++ int ret = 0; ++ ++ /* Disable tuning since we are suspending */ ++ if (host->version >= SDHCI_SPEC_300 && ++ host->tuning_mode == SDHCI_TUNING_MODE_1) { ++ del_timer_sync(&host->tuning_timer); ++ host->flags &= ~SDHCI_NEEDS_RETUNING; ++ } ++ ++ spin_lock_irqsave(&host->lock, flags); ++ sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ synchronize_irq(host->irq); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ host->runtime_suspended = true; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); ++ ++int sdhci_runtime_resume_host(struct sdhci_host *host) ++{ ++ unsigned long flags; ++ int ret = 0, host_flags = host->flags; ++ ++ if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { ++ if (host->ops->enable_dma) ++ host->ops->enable_dma(host); ++ } ++ ++ sdhci_init(host, 0); ++ ++ /* Force clock and power re-program */ ++ host->pwr = 0; ++ host->clock = 0; ++ sdhci_do_set_ios(host, &host->mmc->ios); ++ ++ sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios); ++ if (host_flags & SDHCI_PV_ENABLED) ++ sdhci_do_enable_preset_value(host, true); ++ ++ /* Set the re-tuning expiration flag */ ++ if ((host->version >= SDHCI_SPEC_300) && host->tuning_count && ++ (host->tuning_mode == SDHCI_TUNING_MODE_1)) ++ host->flags |= SDHCI_NEEDS_RETUNING; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ host->runtime_suspended = false; ++ ++ /* Enable SDIO IRQ */ ++ if ((host->flags & SDHCI_SDIO_IRQ_ENABLED)) ++ sdhci_enable_sdio_irq_nolock(host, true); ++ ++ /* Enable Card Detection */ ++ sdhci_enable_card_detection(host); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host); ++ ++#endif ++ + /*****************************************************************************\ + * * + * Device allocation/registration * +@@ -2738,7 +2919,7 @@ int sdhci_add_host(struct sdhci_host *ho + /* Auto-CMD23 stuff only works in ADMA or PIO. */ + if ((host->version >= SDHCI_SPEC_300) && + ((host->flags & SDHCI_USE_ADMA) || +- !(host->flags & SDHCI_USE_SDMA))) { ++ !(host->flags & SDHCI_USE_SDMA) )) { + host->flags |= SDHCI_AUTO_CMD23; + DBG("%s: Auto-CMD23 available\n", mmc_hostname(mmc)); + } else { +@@ -2800,6 +2981,15 @@ int sdhci_add_host(struct sdhci_host *ho + else + mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE; + ++ /* ++ * If Power Off Notify capability is enabled by the host, ++ * set notify to short power off notify timeout value. ++ */ ++ if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY) ++ mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; ++ else ++ mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE; ++ + /* Initial value for re-tuning timer count */ + host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> + SDHCI_RETUNING_TIMER_COUNT_SHIFT; +@@ -2875,6 +3065,9 @@ int sdhci_add_host(struct sdhci_host *ho + mmc->caps |= MMC_CAP_MAX_CURRENT_200; + } + ++ if(host->ops->voltage_broken) ++ ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; ++ + mmc->ocr_avail = ocr_avail; + mmc->ocr_avail_sdio = ocr_avail; + if (host->ocr_avail_sdio) +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -274,6 +274,24 @@ struct sdhci_ops { + void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); + void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); + int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); ++ ++ int (*enable)(struct sdhci_host *mmc); ++ int (*disable)(struct sdhci_host *mmc, int lazy); ++ int (*set_plat_power)(struct sdhci_host *mmc, ++ int power_mode); ++ ++ int (*pdma_able)(struct sdhci_host *host, ++ struct mmc_data *data); ++ void (*pdma_avail)(struct sdhci_host *host, ++ unsigned int *ref_intmask, ++ void(*complete)(struct sdhci_host *)); ++ void (*pdma_reset)(struct sdhci_host *host, ++ struct mmc_data *data); ++ unsigned int (*extra_ints)(struct sdhci_host *host); ++ unsigned int (*spurious_crc_acmd51)(struct sdhci_host *host); ++ unsigned int (*voltage_broken)(struct sdhci_host *host); ++ unsigned int (*uhs_broken)(struct sdhci_host *host); ++ + void (*hw_reset)(struct sdhci_host *host); + }; + +@@ -383,6 +401,34 @@ extern void sdhci_enable_irq_wakeups(str + #ifdef CONFIG_PM_RUNTIME + extern int sdhci_runtime_suspend_host(struct sdhci_host *host); + extern int sdhci_runtime_resume_host(struct sdhci_host *host); ++#endif ++ ++static inline int /*bool*/ ++sdhci_platdma_dmaable(struct sdhci_host *host, struct mmc_data *data) ++{ ++ if (host->ops->pdma_able) ++ return host->ops->pdma_able(host, data); ++ else ++ return 1; ++} ++static inline void ++sdhci_platdma_avail(struct sdhci_host *host, unsigned int *ref_intmask, ++ void(*completion_callback)(struct sdhci_host *)) ++{ ++ if (host->ops->pdma_avail) ++ host->ops->pdma_avail(host, ref_intmask, completion_callback); ++} ++ ++static inline void ++sdhci_platdma_reset(struct sdhci_host *host, struct mmc_data *data) ++{ ++ if (host->ops->pdma_reset) ++ host->ops->pdma_reset(host, data); ++} ++ ++#ifdef CONFIG_PM_RUNTIME ++extern int sdhci_runtime_suspend_host(struct sdhci_host *host); ++extern int sdhci_runtime_resume_host(struct sdhci_host *host); + #endif + + #endif /* __SDHCI_HW_H */ +--- a/include/linux/mmc/sdhci.h ++++ b/include/linux/mmc/sdhci.h +@@ -90,6 +90,8 @@ struct sdhci_host { + + unsigned int quirks2; /* More deviations from spec. */ + ++#define SDHCI_QUIRK2_OWN_CARD_DETECTION (1<<0) ++ + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ + +@@ -120,6 +122,7 @@ struct sdhci_host { + #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ + #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ + #define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */ ++#define SDHCI_USE_PLATDMA (1<<11) /* Host uses 3rd party DMA */ + + unsigned int version; /* SDHCI spec. version */ + +@@ -131,9 +134,9 @@ struct sdhci_host { + u8 pwr; /* Current voltage */ + + bool runtime_suspended; /* Host is runtime suspended */ +- + struct mmc_request *mrq; /* Current request */ + struct mmc_command *cmd; /* Current command */ ++ int last_cmdop; /* Opcode of last cmd sent */ + struct mmc_data *data; /* Current data request */ + unsigned int data_early:1; /* Data finished before cmd */ + -- cgit v1.2.3