mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 18:09:56 +00:00
Main bcm2708 linux port
Signed-off-by: popcornmix <popcornmix@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
338
arch/arm/boot/compressed/divdi3.c
Normal file
338
arch/arm/boot/compressed/divdi3.c
Normal 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;
|
||||
}
|
||||
151
arch/arm/boot/compressed/longlong.h
Normal file
151
arch/arm/boot/compressed/longlong.h
Normal 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
|
||||
1558
arch/arm/configs/bcmrpi_cutdown_defconfig
Normal file
1558
arch/arm/configs/bcmrpi_cutdown_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
@@ -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
338
arch/arm/lib/divdi3.c
Normal 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;
|
||||
}
|
||||
@@ -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
151
arch/arm/lib/longlong.h
Normal 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
|
||||
25
arch/arm/mach-bcm2708/Kconfig
Normal file
25
arch/arm/mach-bcm2708/Kconfig
Normal 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
|
||||
8
arch/arm/mach-bcm2708/Makefile
Normal file
8
arch/arm/mach-bcm2708/Makefile
Normal 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
|
||||
|
||||
3
arch/arm/mach-bcm2708/Makefile.boot
Normal file
3
arch/arm/mach-bcm2708/Makefile.boot
Normal file
@@ -0,0 +1,3 @@
|
||||
zreladdr-y := 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
||||
399
arch/arm/mach-bcm2708/armctrl.c
Normal file
399
arch/arm/mach-bcm2708/armctrl.c
Normal 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;
|
||||
}
|
||||
27
arch/arm/mach-bcm2708/armctrl.h
Normal file
27
arch/arm/mach-bcm2708/armctrl.h
Normal 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
|
||||
658
arch/arm/mach-bcm2708/bcm2708.c
Normal file
658
arch/arm/mach-bcm2708/bcm2708.c
Normal 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
|
||||
51
arch/arm/mach-bcm2708/bcm2708.h
Normal file
51
arch/arm/mach-bcm2708/bcm2708.h
Normal 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
|
||||
323
arch/arm/mach-bcm2708/bcm2708_gpio.c
Normal file
323
arch/arm/mach-bcm2708/bcm2708_gpio.c
Normal 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");
|
||||
|
||||
61
arch/arm/mach-bcm2708/clock.c
Normal file
61
arch/arm/mach-bcm2708/clock.c
Normal 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);
|
||||
24
arch/arm/mach-bcm2708/clock.h
Normal file
24
arch/arm/mach-bcm2708/clock.h
Normal 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
397
arch/arm/mach-bcm2708/dma.c
Normal 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");
|
||||
419
arch/arm/mach-bcm2708/include/mach/arm_control.h
Normal file
419
arch/arm/mach-bcm2708/include/mach/arm_control.h
Normal 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
|
||||
60
arch/arm/mach-bcm2708/include/mach/arm_power.h
Normal file
60
arch/arm/mach-bcm2708/include/mach/arm_power.h
Normal 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
|
||||
7
arch/arm/mach-bcm2708/include/mach/clkdev.h
Normal file
7
arch/arm/mach-bcm2708/include/mach/clkdev.h
Normal 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
|
||||
24
arch/arm/mach-bcm2708/include/mach/debug-macro.S
Normal file
24
arch/arm/mach-bcm2708/include/mach/debug-macro.S
Normal 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>
|
||||
84
arch/arm/mach-bcm2708/include/mach/dma.h
Normal file
84
arch/arm/mach-bcm2708/include/mach/dma.h
Normal 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 */
|
||||
69
arch/arm/mach-bcm2708/include/mach/entry-macro.S
Normal file
69
arch/arm/mach-bcm2708/include/mach/entry-macro.S
Normal 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
|
||||
38
arch/arm/mach-bcm2708/include/mach/frc.h
Normal file
38
arch/arm/mach-bcm2708/include/mach/frc.h
Normal 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
|
||||
48
arch/arm/mach-bcm2708/include/mach/gpio.h
Normal file
48
arch/arm/mach-bcm2708/include/mach/gpio.h
Normal 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
|
||||
28
arch/arm/mach-bcm2708/include/mach/hardware.h
Normal file
28
arch/arm/mach-bcm2708/include/mach/hardware.h
Normal 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
|
||||
28
arch/arm/mach-bcm2708/include/mach/io.h
Normal file
28
arch/arm/mach-bcm2708/include/mach/io.h
Normal 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
|
||||
190
arch/arm/mach-bcm2708/include/mach/irqs.h
Normal file
190
arch/arm/mach-bcm2708/include/mach/irqs.h
Normal 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_ */
|
||||
185
arch/arm/mach-bcm2708/include/mach/irqs.h.orig
Normal file
185
arch/arm/mach-bcm2708/include/mach/irqs.h.orig
Normal 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)
|
||||
59
arch/arm/mach-bcm2708/include/mach/memory.h
Normal file
59
arch/arm/mach-bcm2708/include/mach/memory.h
Normal 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
|
||||
210
arch/arm/mach-bcm2708/include/mach/platform.h
Normal file
210
arch/arm/mach-bcm2708/include/mach/platform.h
Normal 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 */
|
||||
210
arch/arm/mach-bcm2708/include/mach/platform.h.orig
Normal file
210
arch/arm/mach-bcm2708/include/mach/platform.h.orig
Normal 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 */
|
||||
26
arch/arm/mach-bcm2708/include/mach/power.h
Normal file
26
arch/arm/mach-bcm2708/include/mach/power.h
Normal 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
|
||||
53
arch/arm/mach-bcm2708/include/mach/system.h
Normal file
53
arch/arm/mach-bcm2708/include/mach/system.h
Normal 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
|
||||
23
arch/arm/mach-bcm2708/include/mach/timex.h
Normal file
23
arch/arm/mach-bcm2708/include/mach/timex.h
Normal 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)
|
||||
49
arch/arm/mach-bcm2708/include/mach/uncompress.h
Normal file
49
arch/arm/mach-bcm2708/include/mach/uncompress.h
Normal 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()
|
||||
34
arch/arm/mach-bcm2708/include/mach/vc_mem.h
Normal file
34
arch/arm/mach-bcm2708/include/mach/vc_mem.h
Normal 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 */
|
||||
|
||||
42
arch/arm/mach-bcm2708/include/mach/vcio.h
Normal file
42
arch/arm/mach-bcm2708/include/mach/vcio.h
Normal 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
|
||||
20
arch/arm/mach-bcm2708/include/mach/vmalloc.h
Normal file
20
arch/arm/mach-bcm2708/include/mach/vmalloc.h
Normal 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)
|
||||
193
arch/arm/mach-bcm2708/power.c
Normal file
193
arch/arm/mach-bcm2708/power.c
Normal 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");
|
||||
467
arch/arm/mach-bcm2708/vc_mem.c
Normal file
467
arch/arm/mach-bcm2708/vc_mem.c
Normal 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");
|
||||
309
arch/arm/mach-bcm2708/vcio.c
Normal file
309
arch/arm/mach-bcm2708/vcio.c
Normal 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");
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
889
drivers/mmc/host/bcm2708_mci.c
Normal file
889
drivers/mmc/host/bcm2708_mci.c
Normal 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");
|
||||
101
drivers/mmc/host/bcm2708_mci.h
Normal file
101
drivers/mmc/host/bcm2708_mci.h
Normal 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);
|
||||
}
|
||||
1461
drivers/mmc/host/sdhci-bcm2708.c
Normal file
1461
drivers/mmc/host/sdhci-bcm2708.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user