Main bcm2708 linux port

Signed-off-by: popcornmix <popcornmix@gmail.com>
This commit is contained in:
popcornmix
2012-01-17 19:20:11 +00:00
parent c2eaacd305
commit d5ef856b46
59 changed files with 10481 additions and 176 deletions

View File

@@ -896,6 +896,19 @@ 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
help
This enables support for Broadcom BCM2708 boards.
config ARCH_VT8500
bool "VIA/WonderMedia 85xx"
select CPU_ARM926T
@@ -1042,6 +1055,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

View File

@@ -196,6 +196,7 @@ machine-$(CONFIG_MACH_SPEAR310) := spear3xx
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.

View File

@@ -121,11 +121,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 FORCE
$(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

View File

@@ -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;
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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);
@@ -134,6 +136,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 */

View File

@@ -13,7 +13,8 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
testchangebit.o testclearbit.o testsetbit.o \
ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
ucmpdi2.o lib1funcs.o div64.o \
io-readsb.o io-writesb.o io-readsl.o io-writesl.o
io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
divdi3.o
mmu-y := clear_user.o copy_page.o getuser.o putuser.o

338
arch/arm/lib/divdi3.c Normal file
View File

@@ -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;
}

View File

@@ -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:

151
arch/arm/lib/longlong.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,3 @@
zreladdr-y := 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000

View File

@@ -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 <linux/init.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
#include <linux/syscore_ops.h>
#else
#include <linux/sysdev.h>
#endif
#include <linux/interrupt.h>
#include <asm/mach/irq.h>
#include <mach/hardware.h>
#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;
}

View File

@@ -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

View File

@@ -0,0 +1,658 @@
/*
* 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 <linux/init.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
#include <linux/platform_device.h>
#include <linux/sysdev.h>
#include <linux/interrupt.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/clockchips.h>
#include <linux/cnt32_to_63.h>
#include <linux/io.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
#include <linux/clkdev.h>
#else
#include <asm/clkdev.h>
#endif
#include <asm/system.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
#include <mach/timex.h>
#include <mach/dma.h>
#include <mach/vcio.h>
#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 <linux/leds.h>
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

View File

@@ -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 <linux/amba/bus.h>
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

View File

@@ -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 <linux/spinlock.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <mach/platform.h>
#include <mach/gpio.h>
#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<<gpio_field_offset, gpio->base + GPIOSET(gpio_bank));
else
writel(1<<gpio_field_offset, gpio->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<<gpio_field_offset);
else
gpioren &= ~(1<<gpio_field_offset);
if (trigger & (IRQ_TYPE_EDGE_FALLING))
gpiofen |= (1<<gpio_field_offset);
else
gpiofen &= ~(1<<gpio_field_offset);
if (trigger & (IRQ_TYPE_LEVEL_HIGH))
gpiohen |= (1<<gpio_field_offset);
else
gpiohen &= ~(1<<gpio_field_offset);
if (trigger & (IRQ_TYPE_LEVEL_LOW))
gpiolen |= (1<<gpio_field_offset);
else
gpiolen &= ~(1<<gpio_field_offset);
writel(gpioren, chip->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");

View File

@@ -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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/string.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <asm/clkdev.h>
#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);

View File

@@ -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;
};

397
arch/arm/mach-bcm2708/dma.c Normal file
View File

@@ -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 <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <mach/dma.h>
#include <mach/irqs.h>
/*****************************************************************************\
* *
* 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 <grayg@broadcom.com>");
MODULE_DESCRIPTION("DMA channel manager driver");
MODULE_LICENSE("GPL");
MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM");

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 <asm/hardware/debug-pl01x.S>

View File

@@ -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<<BCM_DMA_FEATURE_FAST_ORD)
#define BCM_DMA_FEATURE_COUNT 1
/* return channel no or -ve error */
extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,
void __iomem **out_dma_base, int *out_dma_irq);
extern int bcm_dma_chan_free(int channel);
#endif /* _MACH_BCM2708_DMA_H */

View File

@@ -0,0 +1,69 @@
/*
* arch/arm/mach-bcm2708/include/mach/entry-macro.S
*
* Low-level IRQ helper macros for BCM2708 platforms
*
* 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 <mach/hardware.h>
.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

View File

@@ -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

View File

@@ -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 <asm-generic/gpio.h>
#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

View File

@@ -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 <asm/sizes.h>
#include <mach/platform.h>
#endif

View File

@@ -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

View File

@@ -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 <mach/platform.h>
/*
* 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_ */

View File

@@ -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 <mach/platform.h>
/*
* 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)

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 <linux/types.h>
#include <mach/arm_power.h>
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

View File

@@ -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 <linux/io.h>
#include <mach/hardware.h>
#include <mach/platform.h>
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

View File

@@ -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)

View File

@@ -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 <linux/io.h>
#include <mach/hardware.h>
#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()

View File

@@ -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 <linux/ioctl.h>
#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 */

View File

@@ -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

View File

@@ -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)

View File

@@ -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 <linux/module.h>
#include <linux/semaphore.h>
#include <linux/bug.h>
#include <mach/power.h>
#include <mach/vcio.h>
#include <mach/arm_power.h>
#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");

View File

@@ -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 <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#ifdef CONFIG_ARCH_KONA
#include <chal/chal_ipc.h>
#elif CONFIG_ARCH_BCM2708
#else
#include <csp/chal_ipc.h>
#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 <mach/io_map.h>
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 <mach/csp/mm_io.h>
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");

View File

@@ -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 <linux/module.h>
#include <linux/console.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <mach/vcio.h>
#include <mach/platform.h>
#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");

View File

@@ -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

View File

@@ -855,9 +855,11 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
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;

View File

@@ -70,10 +70,19 @@ ENTRY(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)

View File

@@ -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"

View File

@@ -13,6 +13,7 @@ obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
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
@@ -36,6 +37,7 @@ tmio_mmc_core-$(subst m,y,$(CONFIG_MMC_SDHI)) += tmio_mmc_dma.o
obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o
obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
obj-$(CONFIG_MMC_BCM2708) += bcm2708_mci.o
obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o
obj-$(CONFIG_MMC_DW) += dw_mmc.o
obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o

View File

@@ -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 <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/highmem.h>
#include <linux/log2.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/sizes.h>
//#include <asm/mach/mmc.h>
#include <mach/gpio.h>
#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");

View File

@@ -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);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -274,6 +274,24 @@ struct sdhci_ops {
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);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
@@ -379,4 +397,32 @@ extern int sdhci_resume_host(struct sdhci_host *host);
extern void sdhci_enable_irq_wakeups(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 */

View File

@@ -12,6 +12,7 @@
#include <linux/leds.h>
#include <linux/sched.h>
#include <linux/fault-inject.h>
#include <linux/mmc/core.h>
#include <linux/mmc/pm.h>
@@ -108,6 +109,9 @@ struct mmc_host_ops {
* It is optional for the host to implement pre_req and post_req in
* order to support double buffering of requests (prepare one
* request while another request is active).
* pre_req() must always be followed by a post_req().
* To undo a call made to pre_req(), call post_req() with
* a nonzero err condition.
*/
void (*post_req)(struct mmc_host *host, struct mmc_request *req,
int err);
@@ -147,6 +151,7 @@ struct mmc_host_ops {
int (*execute_tuning)(struct mmc_host *host);
void (*enable_preset_value)(struct mmc_host *host, bool enable);
int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
void (*hw_reset)(struct mmc_host *host);
};
struct mmc_card;
@@ -229,8 +234,20 @@ struct mmc_host {
#define MMC_CAP_MAX_CURRENT_600 (1 << 28) /* Host max current limit is 600mA */
#define MMC_CAP_MAX_CURRENT_800 (1 << 29) /* Host max current limit is 800mA */
#define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */
#define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */
unsigned int caps2; /* More host capabilities */
#define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */
#define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */
#define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */
#define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */
mmc_pm_flag_t pm_caps; /* supported pm features */
unsigned int power_notify_type;
#define MMC_HOST_PW_NOTIFY_NONE 0
#define MMC_HOST_PW_NOTIFY_SHORT 1
#define MMC_HOST_PW_NOTIFY_LONG 2
#ifdef CONFIG_MMC_CLKGATE
int clk_requests; /* internal reference counter */
@@ -302,6 +319,10 @@ struct mmc_host {
struct mmc_async_req *areq; /* active async req */
#ifdef CONFIG_FAIL_MMC_REQUEST
struct fault_attr fail_mmc_request;
#endif
unsigned long private[0] ____cacheline_aligned;
};
@@ -330,6 +351,8 @@ extern int mmc_power_restore_host(struct mmc_host *host);
extern void mmc_detect_change(struct mmc_host *, unsigned long delay);
extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
extern int mmc_cache_ctrl(struct mmc_host *, u8);
static inline void mmc_signal_sdio_irq(struct mmc_host *host)
{
host->ops->enable_sdio_irq(host, 0);
@@ -394,4 +417,10 @@ static inline int mmc_host_cmd23(struct mmc_host *host)
{
return host->caps & MMC_CAP_CMD23;
}
static inline int mmc_boot_partition_access(struct mmc_host *host)
{
return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC);
}
#endif /* LINUX_MMC_HOST_H */

View File

@@ -88,6 +88,10 @@ struct sdhci_host {
/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1<<31)
unsigned int quirks2; /* More deviations from spec. */
#define SDHCI_QUIRK2_OWN_CARD_DETECTION (1<<0)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
@@ -115,6 +119,9 @@ struct sdhci_host {
#define SDHCI_NEEDS_RETUNING (1<<5) /* Host needs retuning */
#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */
#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */
#define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */
#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */
#define SDHCI_USE_PLATDMA (1<<10) /* Host uses 3rd party DMA */
unsigned int version; /* SDHCI spec. version */
@@ -125,8 +132,11 @@ struct sdhci_host {
unsigned int clock; /* Current clock (MHz) */
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 */