提交 91b90475 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-arm

......@@ -67,10 +67,6 @@ config GENERIC_BUST_SPINLOCK
config GENERIC_ISA_DMA
bool
config GENERIC_IOMAP
bool
default y
config FIQ
bool
......@@ -202,6 +198,11 @@ config ARCH_H720X
help
This enables support for systems based on the Hynix HMS720x
config ARCH_AAEC2000
bool "Agilent AAEC-2000 based"
help
This enables support for systems based on the Agilent AAEC-2000
endchoice
source "arch/arm/mach-clps711x/Kconfig"
......@@ -234,6 +235,8 @@ source "arch/arm/mach-h720x/Kconfig"
source "arch/arm/mach-versatile/Kconfig"
source "arch/arm/mach-aaec2000/Kconfig"
# Definitions to make life easier
config ARCH_ACORN
bool
......@@ -277,7 +280,7 @@ config ISA_DMA_API
default y
config PCI
bool "PCI support" if ARCH_INTEGRATOR_AP
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside
......
......@@ -97,6 +97,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_IMX) := imx
machine-$(CONFIG_ARCH_H720X) := h720x
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
......
......@@ -30,6 +30,8 @@
#include <linux/dmapool.h>
#include <linux/list.h>
#include <asm/cacheflush.h>
#undef DEBUG
#undef STATS
......@@ -302,12 +304,24 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
DO_STATS ( device_info->bounce_count++ );
if ((dir == DMA_FROM_DEVICE) ||
(dir == DMA_BIDIRECTIONAL)) {
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
unsigned long ptr;
dev_dbg(dev,
"%s: copy back safe %p to unsafe %p size %d\n",
__func__, buf->safe, buf->ptr, size);
memcpy(buf->ptr, buf->safe, size);
/*
* DMA buffers must have the same cache properties
* as if they were really used for DMA - which means
* data must be written back to RAM. Note that
* we don't use dmac_flush_range() here for the
* bidirectional case because we know the cache
* lines will be coherent with the data written.
*/
ptr = (unsigned long)buf->ptr;
dmac_clean_range(ptr, ptr + size);
}
free_safe_buffer(device_info, buf);
}
......
......@@ -22,7 +22,7 @@
* them early in the boot process, then pass them to the appropriate drivers.
* Not all devices use all paramaters but the format is common to all.
*/
#ifdef ARCH_SA1100
#ifdef CONFIG_ARCH_SA1100
#define PARAM_BASE 0xe8ffc000
#else
#define PARAM_BASE 0xa0000a00
......
......@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
......
......@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
......
......@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
......
......@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
......
......@@ -50,7 +50,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
......
......@@ -6,7 +6,7 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
# Object file lists.
obj-y := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o \
obj-y := compat.o dma.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
time.o traps.o
......
/*
* linux/arch/arm/kernel/arch.c
*
* Architecture specific fixups.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/types.h>
#include <asm/elf.h>
#include <asm/page.h>
#include <asm/setup.h>
#include <asm/mach/arch.h>
unsigned int vram_size;
#ifdef CONFIG_ARCH_ACORN
unsigned int memc_ctrl_reg;
unsigned int number_mfm_drives;
static int __init parse_tag_acorn(const struct tag *tag)
{
memc_ctrl_reg = tag->u.acorn.memc_control_reg;
number_mfm_drives = tag->u.acorn.adfsdrives;
switch (tag->u.acorn.vram_pages) {
case 512:
vram_size += PAGE_SIZE * 256;
case 256:
vram_size += PAGE_SIZE * 256;
default:
break;
}
#if 0
if (vram_size) {
desc->video_start = 0x02000000;
desc->video_end = 0x02000000 + vram_size;
}
#endif
return 0;
}
__tagtable(ATAG_ACORN, parse_tag_acorn);
#endif
......@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
DItype
__ashldi3 (DItype u, word_type b)
s64 __ashldi3(s64 u, int b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.low = 0;
w.s.high = (USItype)uu.s.low << -bm;
}
else
{
USItype carries = (USItype)uu.s.low >> bm;
w.s.low = (USItype)uu.s.low << b;
w.s.high = ((USItype)uu.s.high << b) | carries;
}
return w.ll;
DIunion w;
int bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
if (bm <= 0) {
w.s.low = 0;
w.s.high = (u32) uu.s.low << -bm;
} else {
u32 carries = (u32) uu.s.low >> bm;
w.s.low = (u32) uu.s.low << b;
w.s.high = ((u32) uu.s.high << b) | carries;
}
return w.ll;
}
......@@ -31,31 +31,27 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
DItype
__ashrdi3 (DItype u, word_type b)
s64 __ashrdi3(s64 u, int b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
/* w.s.high = 1..1 or 0..0 */
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
w.s.low = uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
return w.ll;
DIunion w;
int bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
if (bm <= 0) {
/* w.s.high = 1..1 or 0..0 */
w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
w.s.low = uu.s.high >> -bm;
} else {
u32 carries = (u32) uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((u32) uu.s.low >> b) | carries;
}
return w.ll;
}
/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
/* I Molton 29/07/01 */
#define BITS_PER_UNIT 8
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#include <linux/types.h>
typedef unsigned int UQItype __attribute__ ((mode (QI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
#define BITS_PER_UNIT 8
#define SI_TYPE_SIZE (sizeof(s32) * BITS_PER_UNIT)
#ifdef __ARMEB__
struct DIstruct {SItype high, low;};
struct DIstruct {
s32 high, low;
};
#else
struct DIstruct {SItype low, high;};
struct DIstruct {
s32 low, high;
};
#endif
typedef union
{
struct DIstruct s;
DItype ll;
typedef union {
struct DIstruct s;
s64 ll;
} DIunion;
......@@ -26,18 +26,18 @@
#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 __ll_lowpart(t) ((u32) (t) % __ll_B)
#define __ll_highpart(t) ((u32) (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
multiplies two u32 integers MULTIPLER and MULTIPLICAND,
and generates a two-part u32 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.
2) __umulsidi3(a,b) multiplies two u32 integers A and B,
and returns a u64 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
......@@ -77,23 +77,23 @@
#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)))
: "=r" ((u32) (sh)), \
"=&r" ((u32) (sl)) \
: "%r" ((u32) (ah)), \
"rI" ((u32) (bh)), \
"%r" ((u32) (al)), \
"rI" ((u32) (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)))
: "=r" ((u32) (sh)), \
"=&r" ((u32) (sl)) \
: "r" ((u32) (ah)), \
"rI" ((u32) (bh)), \
"r" ((u32) (al)), \
"rI" ((u32) (bl)))
#define umul_ppmm(xh, xl, a, b) \
{register USItype __t0, __t1, __t2; \
{register u32 __t0, __t1, __t2; \
__asm__ ("%@ Inlined umul_ppmm \n\
mov %2, %5, lsr #16 \n\
mov %0, %6, lsr #16 \n\
......@@ -107,14 +107,14 @@
addcs %0, %0, #65536 \n\
adds %1, %1, %3, lsl #16 \n\
adc %0, %0, %3, lsr #16" \
: "=&r" ((USItype) (xh)), \
"=r" ((USItype) (xl)), \
: "=&r" ((u32) (xh)), \
"=r" ((u32) (xl)), \
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
: "r" ((USItype) (a)), \
"r" ((USItype) (b)));}
: "r" ((u32) (a)), \
"r" ((u32) (b)));}
#define UMUL_TIME 20
#define UDIV_TIME 100
#endif /* __arm__ */
#endif /* __arm__ */
#define __umulsidi3(u, v) \
({DIunion __w; \
......@@ -123,14 +123,14 @@
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
do { \
USItype __d1, __d0, __q1, __q0; \
USItype __r1, __r0, __m; \
u32 __d1, __d0, __q1, __q0; \
u32 __r1, __r0, __m; \
__d1 = __ll_highpart (d); \
__d0 = __ll_lowpart (d); \
\
__r1 = (n1) % __d1; \
__q1 = (n1) / __d1; \
__m = (USItype) __q1 * __d0; \
__m = (u32) __q1 * __d0; \
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
if (__r1 < __m) \
{ \
......@@ -143,7 +143,7 @@
\
__r0 = __r1 % __d1; \
__q0 = __r1 / __d1; \
__m = (USItype) __q0 * __d0; \
__m = (u32) __q0 * __d0; \
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
if (__r0 < __m) \
{ \
......@@ -154,7 +154,7 @@
} \
__r0 -= __m; \
\
(q) = (USItype) __q1 * __ll_B | __q0; \
(q) = (u32) __q1 * __ll_B | __q0; \
(r) = __r0; \
} while (0)
......@@ -163,14 +163,14 @@
#define count_leading_zeros(count, x) \
do { \
USItype __xr = (x); \
USItype __a; \
u32 __xr = (x); \
u32 __a; \
\
if (SI_TYPE_SIZE <= 32) \
{ \
__a = __xr < ((USItype)1<<2*__BITS4) \
? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
: (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
__a = __xr < ((u32)1<<2*__BITS4) \
? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4) \
: (__xr < ((u32)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
} \
else \
{ \
......
......@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
DItype
__lshrdi3 (DItype u, word_type b)
s64 __lshrdi3(s64 u, int b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.high = 0;
w.s.low = (USItype)uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = (USItype)uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
return w.ll;
DIunion w;
int bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof(s32) * BITS_PER_UNIT) - b;
if (bm <= 0) {
w.s.high = 0;
w.s.low = (u32) uu.s.high >> -bm;
} else {
u32 carries = (u32) uu.s.high << bm;
w.s.high = (u32) uu.s.high >> b;
w.s.low = ((u32) uu.s.low >> b) | carries;
}
return w.ll;
}
......@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
#define umul_ppmm(xh, xl, a, b) \
{register USItype __t0, __t1, __t2; \
{register u32 __t0, __t1, __t2; \
__asm__ ("%@ Inlined umul_ppmm \n\
mov %2, %5, lsr #16 \n\
mov %0, %6, lsr #16 \n\
......@@ -46,32 +46,27 @@ Boston, MA 02111-1307, USA. */
addcs %0, %0, #65536 \n\
adds %1, %1, %3, lsl #16 \n\
adc %0, %0, %3, lsr #16" \
: "=&r" ((USItype) (xh)), \
"=r" ((USItype) (xl)), \
: "=&r" ((u32) (xh)), \
"=r" ((u32) (xl)), \
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
: "r" ((USItype) (a)), \
"r" ((USItype) (b)));}
: "r" ((u32) (a)), \
"r" ((u32) (b)));}
#define __umulsidi3(u, v) \
({DIunion __w; \
umul_ppmm (__w.s.high, __w.s.low, u, v); \
__w.ll; })
DItype
__muldi3 (DItype u, DItype v)
s64 __muldi3(s64 u, s64 v)
{
DIunion w;
DIunion uu, vv;
DIunion w;
DIunion uu, vv;
uu.ll = u,
vv.ll = v;
uu.ll = u, vv.ll = v;
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ (USItype) uu.s.high * (USItype) vv.s.low);
w.ll = __umulsidi3(uu.s.low, vv.s.low);
w.s.high += ((u32) uu.s.low * (u32) vv.s.high
+ (u32) uu.s.high * (u32) vv.s.low);
return w.ll;
return w.ll;
}
......@@ -31,21 +31,19 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
word_type
__ucmpdi2 (DItype a, DItype b)
int __ucmpdi2(s64 a, s64 b)
{
DIunion au, bu;
au.ll = a, bu.ll = b;
if ((USItype) au.s.high < (USItype) bu.s.high)
return 0;
else if ((USItype) au.s.high > (USItype) bu.s.high)
return 2;
if ((USItype) au.s.low < (USItype) bu.s.low)
return 0;
else if ((USItype) au.s.low > (USItype) bu.s.low)
return 2;
return 1;
DIunion au, bu;
au.ll = a, bu.ll = b;
if ((u32) au.s.high < (u32) bu.s.high)
return 0;
else if ((u32) au.s.high > (u32) bu.s.high)
return 2;
if ((u32) au.s.low < (u32) bu.s.low)
return 0;
else if ((u32) au.s.low > (u32) bu.s.low)
return 2;
return 1;
}
......@@ -32,211 +32,191 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
#include "longlong.h"
static const UQItype __clz_tab[] =
{
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
static const u8 __clz_tab[] = {
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
};
UDItype
__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
{
DIunion ww;
DIunion nn, dd;
DIunion rr;
USItype d0, d1, n0, n1, n2;
USItype q0, q1;
USItype 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 (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 >> (SI_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 SI_TYPE_SIZE are undefined.) */
n1 -= d0;
q1 = 1;
}
else
{
/* Normalize. */
b = SI_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;
}
}
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
{
USItype m1, m0;
/* Normalize. */
b = SI_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;
DIunion ww;
DIunion nn, dd;
DIunion rr;
u32 d0, d1, n0, n1, n2;
u32 q0, q1;
u32 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 (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 >> (SI_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 SI_TYPE_SIZE are undefined.) */
n1 -= d0;
q1 = 1;
} else {
/* Normalize. */
b = SI_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;
}
} 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 {
u32 m1, m0;
/* Normalize. */
b = SI_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;
}
UDItype
__udivdi3 (UDItype n, UDItype d)
u64 __udivdi3(u64 n, u64 d)
{
return __udivmoddi4 (n, d, (UDItype *) 0);
return __udivmoddi4(n, d, (u64 *) 0);
}
UDItype
__umoddi3 (UDItype u, UDItype v)
u64 __umoddi3(u64 u, u64 v)
{
UDItype w;
u64 w;
(void) __udivmoddi4 (u ,v, &w);
(void)__udivmoddi4(u, v, &w);
return w;
return w;
}
if ARCH_AAEC2000
menu "Agilent AAEC-2000 Implementations"
config MACH_AAED2000
bool "Agilent AAED-2000 Development Platform"
select CPU_ARM920T
endmenu
endif
#
# Makefile for the linux kernel.
#
# Common support (must be linked before board specific support)
obj-y += core.o
# Specific board support
obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
/*
* linux/arch/arm/mach-aaec2000/aaed2000.c
*
* Support for the Agilent AAED-2000 Development Platform.
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/major.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/memory.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include "core.h"
static void __init aaed2000_init_irq(void)
{
aaec2000_init_irq();
}
static void __init aaed2000_map_io(void)
{
aaec2000_map_io();
}
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
MAINTAINER("Nicolas Bellido Y Ortega")
BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE)
MAPIO(aaed2000_map_io)
INITIRQ(aaed2000_init_irq)
.timer = &aaec2000_timer,
MACHINE_END
/*
* linux/arch/arm/mach-aaec2000/core.c
*
* Code common to all AAEC-2000 machines
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/signal.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
/*
* Common I/O mapping:
*
* Static virtual address mappings are as follow:
*
* 0xf8000000-0xf8001ffff: Devices connected to APB bus
* 0xf8002000-0xf8003ffff: Devices connected to AHB bus
*
* Below 0xe8000000 is reserved for vm allocation.
*
* The machine specific code must provide the extra mapping beside the
* default mapping provided here.
*/
static struct map_desc standard_io_desc[] __initdata = {
/* virtual physical length type */
{ VIO_APB_BASE, PIO_APB_BASE, IO_APB_LENGTH, MT_DEVICE },
{ VIO_AHB_BASE, PIO_AHB_BASE, IO_AHB_LENGTH, MT_DEVICE }
};
void __init aaec2000_map_io(void)
{
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
}
/*
* Interrupt handling routines
*/
static void aaec2000_int_ack(unsigned int irq)
{
IRQ_INTSR = 1 << irq;
}
static void aaec2000_int_mask(unsigned int irq)
{
IRQ_INTENC |= (1 << irq);
}
static void aaec2000_int_unmask(unsigned int irq)
{
IRQ_INTENS |= (1 << irq);
}
static struct irqchip aaec2000_irq_chip = {
.ack = aaec2000_int_ack,
.mask = aaec2000_int_mask,
.unmask = aaec2000_int_unmask,
};
void __init aaec2000_init_irq(void)
{
unsigned int i;
for (i = 0; i < NR_IRQS; i++) {
set_irq_handler(i, do_level_IRQ);
set_irq_chip(i, &aaec2000_irq_chip);
set_irq_flags(i, IRQF_VALID);
}
/* Disable all interrupts */
IRQ_INTENC = 0xffffffff;
/* Clear any pending interrupts */
IRQ_INTSR = IRQ_INTSR;
}
/*
* Time keeping
*/
/* IRQs are disabled before entering here from do_gettimeofday() */
static unsigned long aaec2000_gettimeoffset(void)
{
unsigned long ticks_to_match, elapsed, usec;
/* Get ticks before next timer match */
ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
/* We need elapsed ticks since last match */
elapsed = LATCH - ticks_to_match;
/* Now, convert them to usec */
usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
return usec;
}
/* We enter here with IRQs enabled */
static irqreturn_t
aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/* TODO: Check timer accuracy */
write_seqlock(&xtime_lock);
timer_tick(regs);
TIMER1_CLEAR = 1;
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static struct irqaction aaec2000_timer_irq = {
.name = "AAEC-2000 Timer Tick",
.flags = SA_INTERRUPT,
.handler = aaec2000_timer_interrupt
};
static void __init aaec2000_timer_init(void)
{
/* Disable timer 1 */
TIMER1_CTRL = 0;
/* We have somehow to generate a 100Hz clock.
* We then use the 508KHz timer in periodic mode.
*/
TIMER1_LOAD = LATCH;
TIMER1_CLEAR = 1; /* Clear interrupt */
setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
TIMER1_CTRL = TIMER_CTRL_ENABLE |
TIMER_CTRL_PERIODIC |
TIMER_CTRL_CLKSEL_508K;
}
struct sys_timer aaec2000_timer = {
.init = aaec2000_timer_init,
.offset = aaec2000_gettimeoffset,
};
/*
* linux/arch/arm/mach-aaec2000/core.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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 sys_timer;
extern struct sys_timer aaec2000_timer;
extern void __init aaec2000_map_io(void);
extern void __init aaec2000_init_irq(void);
......@@ -227,7 +227,6 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* primary CPU
*/
if (hard_smp_processor_id() == 0) {
nmi_tick();
timer_tick(regs);
#ifdef CONFIG_SMP
smp_send_timer();
......
......@@ -162,12 +162,13 @@ void __init ixp2000_map_io(void)
static unsigned ticks_per_jiffy;
static unsigned ticks_per_usec;
static unsigned next_jiffy_time;
static volatile unsigned long *missing_jiffy_timer_csr;
unsigned long ixp2000_gettimeoffset (void)
{
unsigned long offset;
offset = next_jiffy_time - *IXP2000_T4_CSR;
offset = next_jiffy_time - *missing_jiffy_timer_csr;
return offset / ticks_per_usec;
}
......@@ -179,7 +180,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* clear timer 1 */
ixp2000_reg_write(IXP2000_T1_CLR, 1);
while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
timer_tick(regs);
next_jiffy_time -= ticks_per_jiffy;
}
......@@ -197,20 +198,37 @@ static struct irqaction ixp2000_timer_irq = {
void __init ixp2000_init_time(unsigned long tick_rate)
{
ixp2000_reg_write(IXP2000_T1_CLR, 0);
ixp2000_reg_write(IXP2000_T4_CLR, 0);
ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
ticks_per_usec = tick_rate / 1000000;
/*
* We use timer 1 as our timer interrupt.
*/
ixp2000_reg_write(IXP2000_T1_CLR, 0);
ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
/*
* We use T4 as a monotonic counter to track missed jiffies
* We use a second timer as a monotonic counter for tracking
* missed jiffies. The IXP2000 has four timers, but if we're
* on an A-step IXP2800, timer 2 and 3 don't work, so on those
* chips we use timer 4. Timer 4 is the only timer that can
* be used for the watchdog, so we use timer 2 if we're on a
* non-buggy chip.
*/
ixp2000_reg_write(IXP2000_T4_CLD, -1);
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
ixp2000_reg_write(IXP2000_T4_CLR, 0);
ixp2000_reg_write(IXP2000_T4_CLD, -1);
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
missing_jiffy_timer_csr = IXP2000_T4_CSR;
} else {
ixp2000_reg_write(IXP2000_T2_CLR, 0);
ixp2000_reg_write(IXP2000_T2_CLD, -1);
ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
missing_jiffy_timer_csr = IXP2000_T2_CSR;
}
next_jiffy_time = 0xffffffff;
/* register for interrupt */
......
......@@ -5,3 +5,4 @@
obj-y := core.o clock.o
obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o
obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o
obj-$(CONFIG_PCI) += pci.o
......@@ -196,11 +196,15 @@ static struct map_desc versatile_io_desc[] __initdata = {
#ifdef CONFIG_DEBUG_LL
{ IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE },
#endif
#ifdef FIXME
{ PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
{ PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
{ PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE },
{ PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE },
#ifdef CONFIG_PCI
{ IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
{ VERSATILE_PCI_VIRT_BASE, VERSATILE_PCI_BASE, VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
{ VERSATILE_PCI_CFG_VIRT_BASE, VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
#if 0
{ VERSATILE_PCI_VIRT_MEM_BASE0, VERSATILE_PCI_MEM_BASE0, SZ_16M, MT_DEVICE },
{ VERSATILE_PCI_VIRT_MEM_BASE1, VERSATILE_PCI_MEM_BASE1, SZ_16M, MT_DEVICE },
{ VERSATILE_PCI_VIRT_MEM_BASE2, VERSATILE_PCI_MEM_BASE2, SZ_16M, MT_DEVICE },
#endif
#endif
};
......
/*
* linux/arch/arm/mach-versatile/pci.c
*
* (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved.
* You can redistribute and/or modify this software under the terms of version 2
* of the GNU General Public License as published by the Free Software Foundation.
* THIS SOFTWARE IS PROVIDED "AS IS" 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.
* Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software.
*
* ARM Versatile PCI driver.
*
* 14/04/2005 Initial version, colin.king@philips.com
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
/*
* these spaces are mapped using the following base registers:
*
* Usage Local Bus Memory Base/Map registers used
*
* Mem 50000000 - 5FFFFFFF LB_BASE0/LB_MAP0, non prefetch
* Mem 60000000 - 6FFFFFFF LB_BASE1/LB_MAP1, prefetch
* IO 44000000 - 4FFFFFFF LB_BASE2/LB_MAP2, IO
* Cfg 42000000 - 42FFFFFF PCI config
*
*/
#define SYS_PCICTL IO_ADDRESS(VERSATILE_SYS_PCICTL)
#define PCI_IMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
#define PCI_IMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
#define PCI_IMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
#define PCI_SMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
#define PCI_SMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
#define PCI_SMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
#define PCI_SELFID IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
#define DEVICE_ID_OFFSET 0x00
#define CSR_OFFSET 0x04
#define CLASS_ID_OFFSET 0x08
#define VP_PCI_DEVICE_ID 0x030010ee
#define VP_PCI_CLASS_ID 0x0b400000
static unsigned long pci_slot_ignore = 0;
static int __init versatile_pci_slot_ignore(char *str)
{
int retval;
int slot;
while ((retval = get_option(&str,&slot))) {
if ((slot < 0) || (slot > 31)) {
printk("Illegal slot value: %d\n",slot);
} else {
pci_slot_ignore |= (1 << slot);
}
}
return 1;
}
__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
static unsigned long __pci_addr(struct pci_bus *bus,
unsigned int devfn, int offset)
{
unsigned int busnr = bus->number;
/*
* Trap out illegal values
*/
if (offset > 255)
BUG();
if (busnr > 255)
BUG();
if (devfn > 255)
BUG();
return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
(PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
}
static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
unsigned long addr = __pci_addr(bus, devfn, where);
u32 v;
int slot = PCI_SLOT(devfn);
if (pci_slot_ignore & (1 << slot)) {
/* Ignore this slot */
switch (size) {
case 1:
v = 0xff;
break;
case 2:
v = 0xffff;
break;
default:
v = 0xffffffff;
}
} else {
switch (size) {
case 1:
addr &= ~3;
v = __raw_readb(addr);
break;
case 2:
v = __raw_readl(addr & ~3);
if (addr & 2) v >>= 16;
v &= 0xffff;
break;
default:
addr &= ~3;
v = __raw_readl(addr);
break;
}
}
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
unsigned long addr = __pci_addr(bus, devfn, where);
int slot = PCI_SLOT(devfn);
if (pci_slot_ignore & (1 << slot)) {
return PCIBIOS_SUCCESSFUL;
}
switch (size) {
case 1:
__raw_writeb((u8)val, addr);
break;
case 2:
__raw_writew((u16)val, addr);
break;
case 4:
__raw_writel(val, addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops pci_versatile_ops = {
.read = versatile_read_config,
.write = versatile_write_config,
};
static struct resource io_mem = {
.name = "PCI I/O space",
.start = VERSATILE_PCI_MEM_BASE0,
.end = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
.flags = IORESOURCE_IO,
};
static struct resource non_mem = {
.name = "PCI non-prefetchable",
.start = VERSATILE_PCI_MEM_BASE1,
.end = VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1,
.flags = IORESOURCE_MEM,
};
static struct resource pre_mem = {
.name = "PCI prefetchable",
.start = VERSATILE_PCI_MEM_BASE2,
.end = VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1,
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
};
static int __init pci_versatile_setup_resources(struct resource **resource)
{
int ret = 0;
ret = request_resource(&iomem_resource, &io_mem);
if (ret) {
printk(KERN_ERR "PCI: unable to allocate I/O "
"memory region (%d)\n", ret);
goto out;
}
ret = request_resource(&iomem_resource, &non_mem);
if (ret) {
printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
"memory region (%d)\n", ret);
goto release_io_mem;
}
ret = request_resource(&iomem_resource, &pre_mem);
if (ret) {
printk(KERN_ERR "PCI: unable to allocate prefetchable "
"memory region (%d)\n", ret);
goto release_non_mem;
}
/*
* bus->resource[0] is the IO resource for this bus
* bus->resource[1] is the mem resource for this bus
* bus->resource[2] is the prefetch mem resource for this bus
*/
resource[0] = &io_mem;
resource[1] = &non_mem;
resource[2] = &pre_mem;
goto out;
release_non_mem:
release_resource(&non_mem);
release_io_mem:
release_resource(&io_mem);
out:
return ret;
}
int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
{
int ret = 0;
int i;
int myslot = -1;
unsigned long val;
if (nr == 0) {
sys->mem_offset = 0;
ret = pci_versatile_setup_resources(sys->resource);
if (ret < 0) {
printk("pci_versatile_setup: resources... oops?\n");
goto out;
}
} else {
printk("pci_versatile_setup: resources... nr == 0??\n");
goto out;
}
__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0);
__raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1);
__raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2);
__raw_writel(1, SYS_PCICTL);
val = __raw_readl(SYS_PCICTL);
if (!(val & 1)) {
printk("Not plugged into PCI backplane!\n");
ret = -EIO;
goto out;
}
/*
* We need to discover the PCI core first to configure itself
* before the main PCI probing is performed
*/
for (i=0; i<32; i++) {
if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) &&
(__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) {
myslot = i;
__raw_writel(myslot, PCI_SELFID);
val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
val |= (1<<2);
__raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
break;
}
}
if (myslot == -1) {
printk("Cannot find PCI core!\n");
ret = -EIO;
} else {
printk("PCI core found (slot %d)\n",myslot);
/* Do not to map Versatile FPGA PCI device
into memory space as we are short of
mappable memory */
pci_slot_ignore |= (1 << myslot);
ret = 1;
}
out:
return ret;
}
struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
{
return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys);
}
/*
* V3_LB_BASE? - local bus address
* V3_LB_MAP? - pci bus address
*/
void __init pci_versatile_preinit(void)
{
}
void __init pci_versatile_postinit(void)
{
}
/*
* map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this.
*/
static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int irq;
int devslot = PCI_SLOT(dev->devfn);
/* slot, pin, irq
24 1 27
25 1 28 untested
26 1 29
27 1 30 untested
*/
irq = 27 + ((slot + pin + 2) % 3); /* Fudged */
printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
return irq;
}
static struct hw_pci versatile_pci __initdata = {
.swizzle = NULL,
.map_irq = versatile_map_irq,
.nr_controllers = 1,
.setup = pci_versatile_setup,
.scan = pci_versatile_scan_bus,
.preinit = pci_versatile_preinit,
.postinit = pci_versatile_postinit,
};
static int __init versatile_pci_init(void)
{
pci_common_init(&versatile_pci);
return 0;
}
subsys_initcall(versatile_pci_init);
......@@ -62,7 +62,7 @@ config CPU_ARM720T
# ARM920T
config CPU_ARM920T
bool "Support ARM920T processor" if !ARCH_S3C2410
depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
default y if ARCH_S3C2410
select CPU_32v4
select CPU_ABRT_EV4T
......
......@@ -30,8 +30,6 @@
static DEFINE_SPINLOCK(v6_lock);
#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
/*
* Copy the user page. No aliasing to deal with so we can just
* attack the kernel's existing mapping of these pages.
......@@ -55,7 +53,7 @@ void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
*/
void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
{
unsigned int offset = DCACHE_COLOUR(vaddr);
unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long from, to;
/*
......@@ -95,7 +93,7 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
*/
void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
{
unsigned int offset = DCACHE_COLOUR(vaddr);
unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long to = to_address + (offset << PAGE_SHIFT);
/*
......
......@@ -77,9 +77,8 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
}
static void
make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
{
struct address_space *mapping = page_mapping(page);
struct mm_struct *mm = vma->vm_mm;
struct vm_area_struct *mpnt;
struct prio_tree_iter iter;
......@@ -87,9 +86,6 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
pgoff_t pgoff;
int aliases = 0;
if (!mapping)
return;
pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
/*
......@@ -115,9 +111,11 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
if (aliases)
adjust_pte(vma, addr);
else
flush_cache_page(vma, addr, page_to_pfn(page));
flush_cache_page(vma, addr, pfn);
}
void __flush_dcache_page(struct address_space *mapping, struct page *page);
/*
* Take care of architecture specific things when placing a new PTE into
* a page table, or changing an existing PTE. Basically, there are two
......@@ -134,29 +132,22 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
{
unsigned long pfn = pte_pfn(pte);
struct address_space *mapping;
struct page *page;
if (!pfn_valid(pfn))
return;
page = pfn_to_page(pfn);
if (page_mapping(page)) {
mapping = page_mapping(page);
if (mapping) {
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
if (dirty) {
/*
* This is our first userspace mapping of this page.
* Ensure that the physical page is coherent with
* the kernel mapping.
*
* FIXME: only need to do this on VIVT and aliasing
* VIPT cache architectures. We can do that
* by choosing whether to set this bit...
*/
__cpuc_flush_dcache_page(page_address(page));
}
if (dirty)
__flush_dcache_page(mapping, page);
if (cache_is_vivt())
make_coherent(vma, addr, page, dirty);
make_coherent(mapping, vma, addr, pfn);
}
}
......
......@@ -37,13 +37,8 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
#define flush_pfn_alias(pfn,vaddr) do { } while (0)
#endif
static void __flush_dcache_page(struct address_space *mapping, struct page *page)
void __flush_dcache_page(struct address_space *mapping, struct page *page)
{
struct mm_struct *mm = current->active_mm;
struct vm_area_struct *mpnt;
struct prio_tree_iter iter;
pgoff_t pgoff;
/*
* Writeback any data associated with the kernel mapping of this
* page. This ensures that data in the physical page is mutually
......@@ -52,24 +47,21 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
__cpuc_flush_dcache_page(page_address(page));
/*
* If there's no mapping pointer here, then this page isn't
* visible to userspace yet, so there are no cache lines
* associated with any other aliases.
*/
if (!mapping)
return;
/*
* This is a page cache page. If we have a VIPT cache, we
* only need to do one flush - which would be at the relevant
* If this is a page cache page, and we have an aliasing VIPT cache,
* we only need to do one flush - which would be at the relevant
* userspace colour, which is congruent with page->index.
*/
if (cache_is_vipt()) {
if (cache_is_vipt_aliasing())
flush_pfn_alias(page_to_pfn(page),
page->index << PAGE_CACHE_SHIFT);
return;
}
if (mapping && cache_is_vipt_aliasing())
flush_pfn_alias(page_to_pfn(page),
page->index << PAGE_CACHE_SHIFT);
}
static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
{
struct mm_struct *mm = current->active_mm;
struct vm_area_struct *mpnt;
struct prio_tree_iter iter;
pgoff_t pgoff;
/*
* There are possible user space mappings of this page:
......@@ -116,12 +108,12 @@ void flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);
if (cache_is_vipt_nonaliasing())
return;
if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
else
else {
__flush_dcache_page(mapping, page);
if (mapping && cache_is_vivt())
__flush_dcache_aliases(mapping, page);
}
}
EXPORT_SYMBOL(flush_dcache_page);
......@@ -170,3 +170,50 @@ void __iounmap(void __iomem *addr)
vfree((void *) (PAGE_MASK & (unsigned long) addr));
}
EXPORT_SYMBOL(__iounmap);
#ifdef __io
void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
return __io(port);
}
EXPORT_SYMBOL(ioport_map);
void ioport_unmap(void __iomem *addr)
{
}
EXPORT_SYMBOL(ioport_unmap);
#endif
#ifdef CONFIG_PCI
#include <linux/pci.h>
#include <linux/ioport.h>
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
unsigned long start = pci_resource_start(dev, bar);
unsigned long len = pci_resource_len(dev, bar);
unsigned long flags = pci_resource_flags(dev, bar);
if (!len || !start)
return NULL;
if (maxlen && len > maxlen)
len = maxlen;
if (flags & IORESOURCE_IO)
return ioport_map(start, len);
if (flags & IORESOURCE_MEM) {
if (flags & IORESOURCE_CACHEABLE)
return ioremap(start, len);
return ioremap_nocache(start, len);
}
return NULL;
}
EXPORT_SYMBOL(pci_iomap);
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
{
if ((unsigned long)addr >= VMALLOC_START &&
(unsigned long)addr < VMALLOC_END)
iounmap(addr);
}
EXPORT_SYMBOL(pci_iounmap);
#endif
......@@ -192,7 +192,12 @@ static struct miscdevice ixp2000_wdt_miscdev =
static int __init ixp2000_wdt_init(void)
{
wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;;
if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
return -EIO;
}
wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
return misc_register(&ixp2000_wdt_miscdev);
}
......
/*
* linux/include/asm-arm/arch-aaec2000/aaec2000.h
*
* AAEC-2000 registers definition
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_AAEC2000_H
#define __ASM_ARCH_AAEC2000_H
#ifndef __ASM_ARCH_HARDWARE_H
#error You must include hardware.h not this file
#endif /* __ASM_ARCH_HARDWARE_H */
/* Interrupt controller */
#define IRQ_BASE __REG(0x80000500)
#define IRQ_INTSR __REG(0x80000500) /* Int Status Register */
#define IRQ_INTRSR __REG(0x80000504) /* Int Raw (unmasked) Status */
#define IRQ_INTENS __REG(0x80000508) /* Int Enable Set */
#define IRQ_INTENC __REG(0x8000050c) /* Int Enable Clear */
/* UART 1 */
#define UART1_BASE __REG(0x80000600)
#define UART1_DR __REG(0x80000600) /* Data/FIFO Register */
#define UART1_LCR __REG(0x80000604) /* Link Control Register */
#define UART1_BRCR __REG(0x80000608) /* Baud Rate Control Register */
#define UART1_CR __REG(0x8000060c) /* Control Register */
#define UART1_SR __REG(0x80000610) /* Status Register */
#define UART1_INT __REG(0x80000614) /* Interrupt Status Register */
#define UART1_INTM __REG(0x80000618) /* Interrupt Mask Register */
#define UART1_INTRES __REG(0x8000061c) /* Int Result (masked status) Register */
/* UART 2 */
#define UART2_BASE __REG(0x80000700)
#define UART2_DR __REG(0x80000700) /* Data/FIFO Register */
#define UART2_LCR __REG(0x80000704) /* Link Control Register */
#define UART2_BRCR __REG(0x80000708) /* Baud Rate Control Register */
#define UART2_CR __REG(0x8000070c) /* Control Register */
#define UART2_SR __REG(0x80000710) /* Status Register */
#define UART2_INT __REG(0x80000714) /* Interrupt Status Register */
#define UART2_INTM __REG(0x80000718) /* Interrupt Mask Register */
#define UART2_INTRES __REG(0x8000071c) /* Int Result (masked status) Register */
/* UART 3 */
#define UART3_BASE __REG(0x80000800)
#define UART3_DR __REG(0x80000800) /* Data/FIFO Register */
#define UART3_LCR __REG(0x80000804) /* Link Control Register */
#define UART3_BRCR __REG(0x80000808) /* Baud Rate Control Register */
#define UART3_CR __REG(0x8000080c) /* Control Register */
#define UART3_SR __REG(0x80000810) /* Status Register */
#define UART3_INT __REG(0x80000814) /* Interrupt Status Register */
#define UART3_INTM __REG(0x80000818) /* Interrupt Mask Register */
#define UART3_INTRES __REG(0x8000081c) /* Int Result (masked status) Register */
/* These are used in some places */
#define _UART1_BASE __PREG(UART1_BASE)
#define _UART2_BASE __PREG(UART2_BASE)
#define _UART3_BASE __PREG(UART3_BASE)
/* UART Registers Offsets */
#define UART_DR 0x00
#define UART_LCR 0x04
#define UART_BRCR 0x08
#define UART_CR 0x0c
#define UART_SR 0x10
#define UART_INT 0x14
#define UART_INTM 0x18
#define UART_INTRES 0x1c
/* UART_LCR Bitmask */
#define UART_LCR_BRK (1 << 0) /* Send Break */
#define UART_LCR_PEN (1 << 1) /* Parity Enable */
#define UART_LCR_EP (1 << 2) /* Even/Odd Parity */
#define UART_LCR_S2 (1 << 3) /* One/Two Stop bits */
#define UART_LCR_FIFO (1 << 4) /* FIFO Enable */
#define UART_LCR_WL5 (0 << 5) /* Word Length - 5 bits */
#define UART_LCR_WL6 (1 << 5) /* Word Length - 6 bits */
#define UART_LCR_WL7 (1 << 6) /* Word Length - 7 bits */
#define UART_LCR_WL8 (1 << 7) /* Word Length - 8 bits */
/* UART_CR Bitmask */
#define UART_CR_EN (1 << 0) /* UART Enable */
#define UART_CR_SIR (1 << 1) /* IrDA SIR Enable */
#define UART_CR_SIRLP (1 << 2) /* Low Power IrDA Enable */
#define UART_CR_RXP (1 << 3) /* Receive Pin Polarity */
#define UART_CR_TXP (1 << 4) /* Transmit Pin Polarity */
#define UART_CR_MXP (1 << 5) /* Modem Pin Polarity */
#define UART_CR_LOOP (1 << 6) /* Loopback Mode */
/* UART_SR Bitmask */
#define UART_SR_CTS (1 << 0) /* Clear To Send Status */
#define UART_SR_DSR (1 << 1) /* Data Set Ready Status */
#define UART_SR_DCD (1 << 2) /* Data Carrier Detect Status */
#define UART_SR_TxBSY (1 << 3) /* Transmitter Busy Status */
#define UART_SR_RxFE (1 << 4) /* Receive FIFO Empty Status */
#define UART_SR_TxFF (1 << 5) /* Transmit FIFO Full Status */
#define UART_SR_RxFF (1 << 6) /* Receive FIFO Full Status */
#define UART_SR_TxFE (1 << 7) /* Transmit FIFO Empty Status */
/* UART_INT Bitmask */
#define UART_INT_RIS (1 << 0) /* Rx Interrupt */
#define UART_INT_TIS (1 << 1) /* Tx Interrupt */
#define UART_INT_MIS (1 << 2) /* Modem Interrupt */
#define UART_INT_RTIS (1 << 3) /* Receive Timeout Interrupt */
/* Timer 1 */
#define TIMER1_BASE __REG(0x80000c00)
#define TIMER1_LOAD __REG(0x80000c00) /* Timer 1 Load Register */
#define TIMER1_VAL __REG(0x80000c04) /* Timer 1 Value Register */
#define TIMER1_CTRL __REG(0x80000c08) /* Timer 1 Control Register */
#define TIMER1_CLEAR __REG(0x80000c0c) /* Timer 1 Clear Register */
/* Timer 2 */
#define TIMER2_BASE __REG(0x80000d00)
#define TIMER2_LOAD __REG(0x80000d00) /* Timer 2 Load Register */
#define TIMER2_VAL __REG(0x80000d04) /* Timer 2 Value Register */
#define TIMER2_CTRL __REG(0x80000d08) /* Timer 2 Control Register */
#define TIMER2_CLEAR __REG(0x80000d0c) /* Timer 2 Clear Register */
/* Timer 3 */
#define TIMER3_BASE __REG(0x80000e00)
#define TIMER3_LOAD __REG(0x80000e00) /* Timer 3 Load Register */
#define TIMER3_VAL __REG(0x80000e04) /* Timer 3 Value Register */
#define TIMER3_CTRL __REG(0x80000e08) /* Timer 3 Control Register */
#define TIMER3_CLEAR __REG(0x80000e0c) /* Timer 3 Clear Register */
/* Timer Control register bits */
#define TIMER_CTRL_ENABLE (1 << 7) /* Enable (Start° Timer */
#define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic Running Mode */
#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
#define TIMER_CTRL_CLKSEL_508K (1 << 3) /* 508KHz Clock select (Timer 1, 2) */
#define TIMER_CTRL_CLKSEL_2K (0 << 3) /* 2KHz Clock Select (Timer 1, 2)*/
/* Power and State Control */
#define POWER_BASE __REG(0x80000400)
#define POWER_PWRSR __REG(0x80000400) /* Power Status Register */
#define POWER_PWRCNT __REG(0x80000404) /* Power/Clock control */
#define POWER_HALT __REG(0x80000408) /* Power Idle Mode */
#define POWER_STDBY __REG(0x8000040c) /* Power Standby Mode */
#define POWER_BLEOI __REG(0x80000410) /* Battery Low End of Interrupt */
#define POWER_MCEOI __REG(0x80000414) /* Media Changed EoI */
#define POWER_TEOI __REG(0x80000418) /* Tick EoI */
#define POWER_STFCLR __REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
#define POWER_CLKSET __REG(0x80000420) /* Clock Speed Control */
#endif /* __ARM_ARCH_AAEC2000_H */
/* linux/include/asm-arm/arch-aaec2000/debug-macro.S
*
* Debugging macro include header
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
moveq \rx, #0x80000000 @ physical
movne \rx, #io_p2v(0x80000000) @ virtual
orr \rx, \rx, #0x00000800
.endm
.macro senduart,rd,rx
str \rd, [\rx, #0]
.endm
.macro busyuart,rd,rx
1002: ldr \rd, [\rx, #0x10]
tst \rd, #(1 << 7)
beq 1002b
.endm
.macro waituart,rd,rx
#if 0
1001: ldr \rd, [\rx, #0x10]
tst \rd, #(1 << 5)
beq 1001b
#endif
.endm
/*
* linux/include/asm-arm/arch-aaec2000/dma.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
#define MAX_DMA_ADDRESS 0xffffffff
#define MAX_DMA_CHANNELS 0
#endif
/*
* linux/include/asm-arm/arch-aaec2000/entry-macro.S
*
* Low-level IRQ helper for aaec-2000 based platforms
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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 disable_fiq
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xf8000000
add r4, r4, #0x00000500
mov \base, r4
ldr \irqstat, [\base, #0]
cmp \irqstat, #0
bne 1001f
ldr \irqnr, =NR_IRQS+1
b 1003f
1001: mov \irqnr, #0
1002: ands \tmp, \irqstat, #1
mov \irqstat, \irqstat, LSR #1
add \irqnr, \irqnr, #1
beq 1002b
sub \irqnr, \irqnr, #1
1003:
.endm
/*
* linux/include/asm-arm/arch-aaec2000/hardware.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
#include <linux/config.h>
/* The kernel is loaded at physical address 0xf8000000.
* We map the IO space a bit after
*/
#define PIO_APB_BASE 0x80000000
#define VIO_APB_BASE 0xf8000000
#define IO_APB_LENGTH 0x2000
#define PIO_AHB_BASE 0x80002000
#define VIO_AHB_BASE 0xf8002000
#define IO_AHB_LENGTH 0x2000
#define VIO_BASE VIO_APB_BASE
#define PIO_BASE PIO_APB_BASE
#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
#ifndef __ASSEMBLY__
#include <asm/types.h>
/* FIXME: Is it needed to optimize this a la pxa ?? */
#define __REG(x) (*((volatile u32 *)io_p2v(x)))
#define __PREG(x) (io_v2p((u32)&(x)))
#else /* __ASSEMBLY__ */
#define __REG(x) io_p2v(x)
#define __PREG(x) io_v2p(x)
#endif
#include "aaec2000.h"
#endif /* __ASM_ARCH_HARDWARE_H */
/*
* linux/include/asm-arm/arch-aaec2000/io.h
*
* Copied from asm/arch/sa1100/io.h
*/
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
#define IO_SPACE_LIMIT 0xffffffff
/*
* We don't actually have real ISA nor PCI buses, but there is so many
* drivers out there that might just work if we fake them...
*/
#define __io(a) ((void __iomem *)(a))
#define __mem_pci(a) (a)
#define __mem_isa(a) (a)
#endif
/*
* linux/include/asm-arm/arch-aaec2000/irqs.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H
#define INT_GPIOF0_FIQ 0 /* External GPIO Port F O Fast Interrupt Input */
#define INT_BL_FIQ 1 /* Battery Low Fast Interrupt */
#define INT_WE_FIQ 2 /* Watchdog Expired Fast Interrupt */
#define INT_MV_FIQ 3 /* Media Changed Interrupt */
#define INT_SC 4 /* Sound Codec Interrupt */
#define INT_GPIO1 5 /* GPIO Port F Configurable Int 1 */
#define INT_GPIO2 6 /* GPIO Port F Configurable Int 2 */
#define INT_GPIO3 7 /* GPIO Port F Configurable Int 3 */
#define INT_TMR1_OFL 8 /* Timer 1 Overflow Interrupt */
#define INT_TMR2_OFL 9 /* Timer 2 Overflow Interrupt */
#define INT_RTC_CM 10 /* RTC Compare Match Interrupt */
#define INT_TICK 11 /* 64Hz Tick Interrupt */
#define INT_UART1 12 /* UART1 Interrupt */
#define INT_UART2 13 /* UART2 & Modem State Changed Interrupt */
#define INT_LCD 14 /* LCD Interrupt */
#define INT_SSI 15 /* SSI End of Transfer Interrupt */
#define INT_UART3 16 /* UART3 Interrupt */
#define INT_SCI 17 /* SCI Interrupt */
#define INT_AAC 18 /* Advanced Audio Codec Interrupt */
#define INT_MMC 19 /* MMC Interrupt */
#define INT_USB 20 /* USB Interrupt */
#define INT_DMA 21 /* DMA Interrupt */
#define INT_TMR3_UOFL 22 /* Timer 3 Underflow Interrupt */
#define INT_GPIO4 23 /* GPIO Port F Configurable Int 4 */
#define INT_GPIO5 24 /* GPIO Port F Configurable Int 4 */
#define INT_GPIO6 25 /* GPIO Port F Configurable Int 4 */
#define INT_GPIO7 26 /* GPIO Port F Configurable Int 4 */
#define INT_BMI 27 /* BMI Interrupt */
#define NR_IRQS (INT_BMI + 1)
#endif /* __ASM_ARCH_IRQS_H */
/*
* linux/include/asm-arm/arch-aaec2000/memory.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
#include <linux/config.h>
#define PHYS_OFFSET (0xf0000000UL)
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
#ifdef CONFIG_DISCONTIGMEM
/*
* The nodes are the followings:
*
* node 0: 0xf000.0000 - 0xf3ff.ffff
* node 1: 0xf400.0000 - 0xf7ff.ffff
* node 2: 0xf800.0000 - 0xfbff.ffff
* node 3: 0xfc00.0000 - 0xffff.ffff
*/
/*
* Given a kernel address, find the home node of the underlying memory.
*/
#define KVADDR_TO_NID(addr) \
(((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
/*
* Given a page frame number, convert it to a node id.
*/
#define PFN_TO_NID(pfn) \
(((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
/*
* Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
* and return the mem_map of that node.
*/
#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
/*
* Given a page frame number, find the owning node of the memory
* and return the mem_map of that node.
*/
#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
/*
* Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
* and returns the index corresponding to the appropriate page in the
* node's mem_map.
*/
#define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
#define NODE_MAX_MEM_SHIFT 26
#define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT)
#else
#define PFN_TO_NID(addr) (0)
#endif /* CONFIG_DISCONTIGMEM */
#endif /* __ASM_ARCH_MEMORY_H */
/*
* linux/include/asm-arm/arch-aaec2000/param.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_PARAM_H
#define __ASM_ARCH_PARAM_H
#endif /* __ASM_ARCH_PARAM_H */
/*
* linux/include/asm-arm/arch-aaed2000/system.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
static inline void arch_idle(void)
{
cpu_do_idle();
}
static inline void arch_reset(char mode)
{
cpu_reset(0);
}
#endif /* __ASM_ARCH_SYSTEM_H */
/*
* linux/include/asm-arm/arch-aaec2000/timex.h
*
* AAEC-2000 Architecture timex specification
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_TIMEX_H
#define __ASM_ARCH_TIMEX_H
#define CLOCK_TICK_RATE 508000
#endif /* __ASM_ARCH_TIMEX_H */
/*
* linux/include/asm-arm/arch-aaec2000/uncompress.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_UNCOMPRESS_H
#define __ASM_ARCH_UNCOMPRESS_H
#include "hardware.h"
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
static void putstr( const char *s )
{
unsigned long serial_port;
do {
serial_port = _UART3_BASE;
if (UART(UART_CR) & UART_CR_EN) break;
serial_port = _UART1_BASE;
if (UART(UART_CR) & UART_CR_EN) break;
serial_port = _UART2_BASE;
if (UART(UART_CR) & UART_CR_EN) break;
return;
} while (0);
for (; *s; s++) {
/* wait for space in the UART's transmitter */
while ((UART(UART_SR) & UART_SR_TxFF));
/* send the character out. */
UART(UART_DR) = *s;
/* if a LF, also do CR... */
if (*s == 10) {
while ((UART(UART_SR) & UART_SR_TxFF));
UART(UART_DR) = 13;
}
}
}
#define arch_decomp_setup()
#define arch_decomp_wdog()
#endif /* __ASM_ARCH_UNCOMPRESS_H */
/*
* linux/include/asm-arm/arch-aaec2000/vmalloc.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H
#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
#endif /* __ASM_ARCH_VMALLOC_H */
......@@ -363,6 +363,7 @@
#define IXP2000_MIN_REV_MASK 0x0000000F
#define IXP2000_PROD_ID_MASK 0xFFFFFFFF
#define IXP2000_PRODUCT_ID GLOBAL_REG(0x00)
#define IXP2000_MISC_CONTROL GLOBAL_REG(0x04)
#define IXP2000_MSF_CLK_CNTRL GLOBAL_REG(0x08)
#define IXP2000_RESET0 GLOBAL_REG(0x0c)
......
......@@ -25,19 +25,26 @@
#include <asm/sizes.h>
#include <asm/arch/platform.h>
// FIXME = PCI settings need to be fixed!!!!!
/*
* Similar to above, but for PCI addresses (memory, IO, Config and the
* V3 chip itself). WARNING: this has to mirror definitions in platform.h
* PCI space virtual addresses
*/
#define PCI_MEMORY_VADDR 0xe8000000
#define PCI_CONFIG_VADDR 0xec000000
#define PCI_V3_VADDR 0xed000000
#define PCI_IO_VADDR 0xee000000
#define VERSATILE_PCI_VIRT_BASE 0xe8000000
#define VERSATILE_PCI_CFG_VIRT_BASE 0xe9000000
#if 0
#define VERSATILE_PCI_VIRT_MEM_BASE0 0xf4000000
#define VERSATILE_PCI_VIRT_MEM_BASE1 0xf5000000
#define VERSATILE_PCI_VIRT_MEM_BASE2 0xf6000000
#define PCIO_BASE VERSATILE_PCI_VIRT_MEM_BASE0
#define PCIMEM_BASE VERSATILE_PCI_VIRT_MEM_BASE1
#endif
/* CIK guesswork */
#define PCIBIOS_MIN_IO 0x44000000
#define PCIBIOS_MIN_MEM 0x50000000
#define PCIO_BASE PCI_IO_VADDR
#define PCIMEM_BASE PCI_MEMORY_VADDR
#define pcibios_assign_all_busses() 1
/* macro to get at IO space when running virtually */
#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
......
......@@ -20,7 +20,7 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
#define IO_SPACE_LIMIT 0xffff
#define IO_SPACE_LIMIT 0xffffffff
#define __io(a) ((void __iomem *)(a))
#define __mem_pci(a) (a)
......
......@@ -76,7 +76,7 @@
#define VERSATILE_SYS_NVFLAGSSET_OFFSET 0x38
#define VERSATILE_SYS_NVFLAGSCLR_OFFSET 0x3C
#define VERSATILE_SYS_RESETCTL_OFFSET 0x40
#define VERSATILE_SYS_PICCTL_OFFSET 0x44
#define VERSATILE_SYS_PCICTL_OFFSET 0x44
#define VERSATILE_SYS_MCI_OFFSET 0x48
#define VERSATILE_SYS_FLASH_OFFSET 0x4C
#define VERSATILE_SYS_CLCD_OFFSET 0x50
......@@ -114,7 +114,7 @@
#define VERSATILE_SYS_NVFLAGSSET (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET)
#define VERSATILE_SYS_NVFLAGSCLR (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET)
#define VERSATILE_SYS_RESETCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET)
#define VERSATILE_SYS_PICCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_PICCTL_OFFSET)
#define VERSATILE_SYS_PCICTL (VERSATILE_SYS_BASE + VERSATILE_SYS_PCICTL_OFFSET)
#define VERSATILE_SYS_MCI (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET)
#define VERSATILE_SYS_FLASH (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET)
#define VERSATILE_SYS_CLCD (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET)
......@@ -225,7 +225,20 @@
#define VERSATILE_SSMC_BASE 0x20000000 /* SSMC */
#define VERSATILE_IB2_BASE 0x24000000 /* IB2 module */
#define VERSATILE_MBX_BASE 0x40000000 /* MBX */
/* PCI space */
#define VERSATILE_PCI_BASE 0x41000000 /* PCI Interface */
#define VERSATILE_PCI_CFG_BASE 0x42000000
#define VERSATILE_PCI_MEM_BASE0 0x44000000
#define VERSATILE_PCI_MEM_BASE1 0x50000000
#define VERSATILE_PCI_MEM_BASE2 0x60000000
/* Sizes of above maps */
#define VERSATILE_PCI_BASE_SIZE 0x01000000
#define VERSATILE_PCI_CFG_BASE_SIZE 0x02000000
#define VERSATILE_PCI_MEM_BASE0_SIZE 0x0c000000 /* 32Mb */
#define VERSATILE_PCI_MEM_BASE1_SIZE 0x10000000 /* 256Mb */
#define VERSATILE_PCI_MEM_BASE2_SIZE 0x10000000 /* 256Mb */
#define VERSATILE_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */
#define VERSATILE_LT_BASE 0x80000000 /* Logic Tile expansion */
......
......@@ -16,6 +16,9 @@
#include <asm/mman.h>
#include <asm/glue.h>
#include <asm/shmparam.h>
#define CACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
/*
* Cache Model
......
......@@ -272,6 +272,33 @@ extern void __iounmap(void __iomem *addr);
#define iounmap(cookie) __arch_iounmap(cookie)
#endif
/*
* io{read,write}{8,16,32} macros
*/
#define ioread8(p) ({ unsigned int __v = __raw_readb(p); __v; })
#define ioread16(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })
#define ioread32(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })
#define iowrite8(v,p) __raw_writeb(v, p)
#define iowrite16(v,p) __raw_writew(cpu_to_le16(v), p)
#define iowrite32(v,p) __raw_writel(cpu_to_le32(v), p)
#define ioread8_rep(p,d,c) __raw_readsb(p,d,c)
#define ioread16_rep(p,d,c) __raw_readsw(p,d,c)
#define ioread32_rep(p,d,c) __raw_readsl(p,d,c)
#define iowrite8_rep(p,s,c) __raw_writesb(p,s,c)
#define iowrite16_rep(p,s,c) __raw_writesw(p,s,c)
#define iowrite32_rep(p,s,c) __raw_writesl(p,s,c)
extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
extern void ioport_unmap(void __iomem *addr);
struct pci_dev;
extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen);
extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
/*
* can the hardware map this into one segment or not, given no other
* constraints.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册