Commit de521514 authored by Paul Mackerras's avatar Paul Mackerras

Merge samba.org:/home/paulus/kernel/linux-2.5

into samba.org:/home/paulus/kernel/for-linus-ppc
parents d79fbd73 21fbda93
...@@ -97,14 +97,6 @@ config ARCH_ANAKIN ...@@ -97,14 +97,6 @@ config ARCH_ANAKIN
Bosch DAB module Bosch DAB module
* An audio card ( 4 * 40W, AC97 Codec, I2S) * An audio card ( 4 * 40W, AC97 Codec, I2S)
config ARCH_ARCA5K
bool "Archimedes/A5000"
help
This selects what ARM system you wish to build the kernel for. It
also selects to some extent the CPU type. If you are unsure what
to set this option to, please consult any information supplied with
your system.
config ARCH_CLPS7500 config ARCH_CLPS7500
bool "Cirrus-CL-PS7500FE" bool "Cirrus-CL-PS7500FE"
...@@ -167,8 +159,6 @@ config ARCH_SHARK ...@@ -167,8 +159,6 @@ config ARCH_SHARK
endchoice endchoice
source "arch/arm/mach-arc/Kconfig"
source "arch/arm/mach-clps711x/Kconfig" source "arch/arm/mach-clps711x/Kconfig"
source "arch/arm/mach-epxa10db/Kconfig" source "arch/arm/mach-epxa10db/Kconfig"
...@@ -184,7 +174,7 @@ source "arch/arm/mach-sa1100/Kconfig" ...@@ -184,7 +174,7 @@ source "arch/arm/mach-sa1100/Kconfig"
# Definitions to make life easier # Definitions to make life easier
config ARCH_ACORN config ARCH_ACORN
bool bool
depends on ARCH_ARCA5K || ARCH_RPC depends on ARCH_RPC
default y default y
##################################################################### #####################################################################
...@@ -226,12 +216,6 @@ comment "Processor Type" ...@@ -226,12 +216,6 @@ comment "Processor Type"
# Figure out whether this system uses 26-bit or 32-bit CPUs. # Figure out whether this system uses 26-bit or 32-bit CPUs.
config CPU_32 config CPU_32
bool bool
depends on !ARCH_ARCA5K
default y
config CPU_26
bool
depends on ARCH_ARCA5K
default y default y
# Select CPU types depending on the architecture selected. This selects # Select CPU types depending on the architecture selected. This selects
...@@ -656,7 +640,7 @@ config FPE_NWFPE_XP ...@@ -656,7 +640,7 @@ config FPE_NWFPE_XP
config FPE_FASTFPE config FPE_FASTFPE
bool "FastFPE math emulation (EXPERIMENTAL)" bool "FastFPE math emulation (EXPERIMENTAL)"
depends on !CPU_26 && !CPU_32v3 && EXPERIMENTAL depends on !CPU_32v3 && EXPERIMENTAL
---help--- ---help---
Say Y here to include the FAST floating point emulator in the kernel. Say Y here to include the FAST floating point emulator in the kernel.
This is an experimental much faster emulator which now also has full This is an experimental much faster emulator which now also has full
......
...@@ -30,6 +30,9 @@ AS += -EB ...@@ -30,6 +30,9 @@ AS += -EB
LD += -EB LD += -EB
endif endif
check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
comma = ,
# Select CPU dependent flags. Note that order of declaration is important; # Select CPU dependent flags. Note that order of declaration is important;
# the options further down the list override previous items. # the options further down the list override previous items.
# #
...@@ -40,7 +43,7 @@ apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3 ...@@ -40,7 +43,7 @@ apcs-$(CONFIG_CPU_26) :=-mapcs-26 -mcpu=arm3
# Note that GCC does not numerically define an architecture version # Note that GCC does not numerically define an architecture version
# macro, but instead defines a whole series of macros which makes # macro, but instead defines a whole series of macros which makes
# testing for a specific architecture or later rather impossible. # testing for a specific architecture or later rather impossible.
arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5te arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4 -Wa$(comma)-mxscale)
arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
...@@ -53,7 +56,7 @@ tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi ...@@ -53,7 +56,7 @@ tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110)
# Force -mno-fpu to be passed to the assembler. Some versions of gcc don't # Force -mno-fpu to be passed to the assembler. Some versions of gcc don't
# do this with -msoft-float # do this with -msoft-float
......
...@@ -29,16 +29,16 @@ ...@@ -29,16 +29,16 @@
* GCC 3.0, 3.1: general bad code generation. * GCC 3.0, 3.1: general bad code generation.
* GCC 3.2.0: incorrect function argument offset calculation. * GCC 3.2.0: incorrect function argument offset calculation.
* GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
* (http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=8896) * (http://gcc.gnu.org/PR8896) and incorrect structure
* initialisation in fs/jffs2/erase.c
*/ */
#if __GNUC__ < 2 || \ #if __GNUC__ < 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ < 95) || \ (__GNUC__ == 2 && __GNUC_MINOR__ < 95) || \
(__GNUC__ == 2 && __GNUC_MINOR__ == 95 && __GNUC_PATCHLEVEL__ != 0 && \ (__GNUC__ == 2 && __GNUC_MINOR__ == 95 && __GNUC_PATCHLEVEL__ != 0 && \
__GNUC_PATCHLEVEL__ < 3) || \ __GNUC_PATCHLEVEL__ < 3) || \
(__GNUC__ == 3 && __GNUC_MINOR__ < 2) || \ (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
(__GNUC__ == 3 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ < 1)
#error Your compiler is too buggy; it is known to miscompile kernels. #error Your compiler is too buggy; it is known to miscompile kernels.
#error Known good compilers: 2.95.3, 2.95.4, 2.96, 3.2.2+PR8896 #error Known good compilers: 2.95.3, 2.95.4, 2.96, 3.3
#endif #endif
/* Use marker if you need to separate the values later */ /* Use marker if you need to separate the values later */
......
...@@ -174,6 +174,9 @@ void do_gettimeofday(struct timeval *tv) ...@@ -174,6 +174,9 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -184,21 +187,21 @@ int do_settimeofday(struct timespec *tv) ...@@ -184,21 +187,21 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* done, and then undo it! * done, and then undo it!
*/ */
tv->tv_nsec -= 1000 * (gettimeoffset() + nsec -= gettimeoffset() * NSEC_PER_USEC;
(jiffies - wall_jiffies) * USECS_PER_JIFFY); nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT;
write_sequnlock_irq(&xtime_lock); write_sequnlock_irq(&xtime_lock);
clock_was_set();
return 0; return 0;
} }
......
menu "Archimedes/A5000 Implementations"
# These architectures will be combined. However, until this
# is complete... Note that the ARC will take precedence over
# A5K
comment "Archimedes/A5000 Implementations (select only ONE)"
config ARCH_ARC
bool "Archimedes"
depends on ARCH_ARCA5K
help
The Acorn Archimedes was an personal computer based on an 8K ARM2
processor, released in 1987. It supported 512K of RAM and 2 800K
floppy disks. Picture and more detailed specifications at
<http://www.computingmuseum.com/museum/archi.htm>.
config ARCH_A5K
bool "A5000"
depends on ARCH_ARCA5K
help
Say Y here to to support the Acorn A5000. Linux can support the
internal IDE disk and CD-ROM interface, serial and parallel port,
and the floppy drive. Note that on some A5000s the floppy is
plugged into the wrong socket on the motherboard.
config PAGESIZE_16
bool "2MB physical memory"
depends on ARCH_ARCA5K
help
Say Y here if your Archimedes or A5000 system has only 2MB of
memory, otherwise say N. The resulting kernel will not run on a
machine with 4MB of memory.
endmenu
#
# Makefile for the linux kernel.
#
# Object file lists.
obj-y := arch.o dma.o fault.o irq.o mm.o oldlatches.o \
small_page.o
obj-$(CONFIG_DEBUG_LL) += debug.o
extra-y := head.o
AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR)
/*
* linux/arch/arm/mach-arc/arch.c
*
* Copyright (C) 1998-2001 Russell King
*
* 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.
*
* Architecture specific fixups.
*/
#include <linux/config.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/page.h>
#include <asm/setup.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
extern void arc_init_irq(void);
#ifdef CONFIG_ARCH_ARC
MACHINE_START(ARCHIMEDES, "Acorn-Archimedes")
MAINTAINER("Dave Gilbert")
BOOT_PARAMS(0x0207c000)
INITIRQ(arc_init_irq)
MACHINE_END
#endif
#ifdef CONFIG_ARCH_A5K
MACHINE_START(A5K, "Acorn-A5000")
MAINTAINER("Russell King")
BOOT_PARAMS(0x0207c000)
INITIRQ(arc_init_irq)
MACHINE_END
#endif
/*
* linux/arch/arm/kernel/debug-armo.S
*
* Copyright (C) 1999 Russell King
*
* 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.
*
* 26-bit debugging code
*/
#include <linux/linkage.h>
.macro addruart,rx
mov \rx, #0x03000000
orr \rx, \rx, #0x00010000
orr \rx, \rx, #0x00000fe0
.endm
.macro senduart,rd,rx
strb \rd, [\rx]
.endm
.macro busyuart,rd,rx
1002: ldrb \rd, [\rx, #0x14]
and \rd, \rd, #0x60
teq \rd, #0x60
bne 1002b
.endm
.macro waituart,rd,rx
1001: ldrb \rd, [\rx, #0x18]
tst \rd, #0x10
beq 1001b
.endm
.text
/*
* Useful debugging routines
*/
ENTRY(printhex8)
mov r1, #8
b printhex
ENTRY(printhex4)
mov r1, #4
b printhex
ENTRY(printhex2)
mov r1, #2
printhex: ldr r2, =hexbuf
add r3, r2, r1
mov r1, #0
strb r1, [r3]
1: and r1, r0, #15
mov r0, r0, lsr #4
cmp r1, #10
addlt r1, r1, #'0'
addge r1, r1, #'a' - 10
strb r1, [r3, #-1]!
teq r3, r2
bne 1b
mov r0, r2
b printascii
.ltorg
ENTRY(printascii)
addruart r3
b 2f
1: waituart r2, r3
senduart r1, r3
busyuart r2, r3
teq r1, #'\n'
moveq r1, #'\r'
beq 1b
2: teq r0, #0
ldrneb r1, [r0], #1
teqne r1, #0
bne 1b
mov pc, lr
ENTRY(printch)
addruart r3
mov r1, r0
mov r0, #0
b 1b
.bss
hexbuf: .space 16
/*
* linux/arch/arm/kernel/dma-arc.c
*
* Copyright (C) 1998-1999 Dave Gilbert / Russell King
*
* 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.
*
* DMA functions specific to Archimedes and A5000 architecture
*/
#include <linux/config.h>
#include <linux/init.h>
#include <asm/dma.h>
#include <asm/fiq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/dma.h>
#define DPRINTK(x...) printk(KERN_DEBUG x)
#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE)
static void arc_floppy_data_enable_dma(dmach_t channel, dma_t *dma)
{
DPRINTK("arc_floppy_data_enable_dma\n");
if (dma->using_sg)
BUG();
switch (dma->dma_mode) {
case DMA_MODE_READ: { /* read */
extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end;
extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
unsigned long flags;
DPRINTK("enable_dma fdc1772 data read\n");
save_flags(flags);
clf();
memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
&fdc1772_dma_read_end - &fdc1772_dma_read);
fdc1772_setupdma(dma->buf.length, dma->buf.__address); /* Sets data pointer up */
enable_fiq(FIQ_FLOPPYDATA);
restore_flags(flags);
}
break;
case DMA_MODE_WRITE: { /* write */
extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end;
extern void fdc1772_setupdma(unsigned int count,unsigned int addr);
unsigned long flags;
DPRINTK("enable_dma fdc1772 data write\n");
save_flags(flags);
clf();
memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
&fdc1772_dma_write_end - &fdc1772_dma_write);
fdc1772_setupdma(dma->buf.length, dma->buf.__address); /* Sets data pointer up */
enable_fiq(FIQ_FLOPPYDATA;
restore_flags(flags);
}
break;
default:
printk ("enable_dma: dma%d not initialised\n", channel);
}
}
static int arc_floppy_data_get_dma_residue(dmach_t channel, dma_t *dma)
{
extern unsigned int fdc1772_bytestogo;
/* 10/1/1999 DAG - I presume its the number of bytes left? */
return fdc1772_bytestogo;
}
static void arc_floppy_cmdend_enable_dma(dmach_t channel, dma_t *dma)
{
/* Need to build a branch at the FIQ address */
extern void fdc1772_comendhandler(void);
unsigned long flags;
DPRINTK("arc_floppy_cmdend_enable_dma\n");
/*printk("enable_dma fdc1772 command end FIQ\n");*/
save_flags(flags);
clf();
/* B fdc1772_comendhandler */
*((unsigned int *)0x1c)=0xea000000 |
(((unsigned int)fdc1772_comendhandler-(0x1c+8))/4);
restore_flags(flags);
}
static int arc_floppy_cmdend_get_dma_residue(dmach_t channel, dma_t *dma)
{
/* 10/1/1999 DAG - Presume whether there is an outstanding command? */
extern unsigned int fdc1772_fdc_int_done;
/* Explicit! If the int done is 0 then 1 int to go */
return (fdc1772_fdc_int_done==0)?1:0;
}
static void arc_disable_dma(dmach_t channel, dma_t *dma)
{
disable_fiq(dma->dma_irq);
}
static struct dma_ops arc_floppy_data_dma_ops = {
.type = "FIQDMA",
.enable = arc_floppy_data_enable_dma,
.disable = arc_disable_dma,
.residue = arc_floppy_data_get_dma_residue,
};
static struct dma_ops arc_floppy_cmdend_dma_ops = {
.type = "FIQCMD",
.enable = arc_floppy_cmdend_enable_dma,
.disable = arc_disable_dma,
.residue = arc_floppy_cmdend_get_dma_residue,
};
#endif
#ifdef CONFIG_ARCH_A5K
static struct fiq_handler fh = {
.name = "floppydata"
};
static int a5k_floppy_get_dma_residue(dmach_t channel, dma_t *dma)
{
struct pt_regs regs;
get_fiq_regs(&regs);
return regs.ARM_r9;
}
static void a5k_floppy_enable_dma(dmach_t channel, dma_t *dma)
{
struct pt_regs regs;
void *fiqhandler_start;
unsigned int fiqhandler_length;
extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
unsigned long port);
if (dma->using_sg)
BUG();
if (dma->dma_mode == DMA_MODE_READ) {
extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
fiqhandler_start = &floppy_fiqin_start;
fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
} else {
extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
fiqhandler_start = &floppy_fiqout_start;
fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
}
if (claim_fiq(&fh)) {
printk("floppydma: couldn't claim FIQ.\n");
return;
}
memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
regs.ARM_r9 = dma->buf.length;
regs.ARM_r10 = (unsigned long)dma->buf.__address;
regs.ARM_fp = FLOPPYDMA_BASE;
set_fiq_regs(&regs);
enable_fiq(dma->dma_irq);
}
static void a5k_floppy_disable_dma(dmach_t channel, dma_t *dma)
{
disable_fiq(dma->dma_irq);
release_fiq(&fh);
}
static struct dma_ops a5k_floppy_dma_ops = {
.type = "FIQDMA",
.enable = a5k_floppy_enable_dma,
.disable = a5k_floppy_disable_dma,
.residue = a5k_floppy_get_dma_residue,
};
#endif
/*
* This is virtual DMA - we don't need anything here
*/
static void sound_enable_disable_dma(dmach_t channel, dma_t *dma)
{
}
static struct dma_ops sound_dma_ops = {
.type = "VIRTUAL",
.enable = sound_enable_disable_dma,
.disable = sound_enable_disable_dma,
};
void __init arch_dma_init(dma_t *dma)
{
#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE)
if (machine_is_archimedes()) {
dma[DMA_VIRTUAL_FLOPPY0].dma_irq = FIQ_FLOPPYDATA;
dma[DMA_VIRTUAL_FLOPPY0].d_ops = &arc_floppy_data_dma_ops;
dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 1;
dma[DMA_VIRTUAL_FLOPPY1].d_ops = &arc_floppy_cmdend_dma_ops;
}
#endif
#ifdef CONFIG_ARCH_A5K
if (machine_is_a5k()) {
dma[DMA_VIRTUAL_FLOPPY0].dma_irq = FIQ_FLOPPYDATA;
dma[DMA_VIRTUAL_FLOPPY0].d_ops = &a5k_floppy_dma_ops;
}
#endif
dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops;
}
/*
* linux/arch/arm/mm/fault-armo.c
*
* Copyright (C) 1995 Linus Torvalds
* Modifications for ARM processor (c) 1995-1999 Russell King
*
* 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/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#define FAULT_CODE_LDRSTRPOST 0x80
#define FAULT_CODE_LDRSTRPRE 0x40
#define FAULT_CODE_LDRSTRREG 0x20
#define FAULT_CODE_LDMSTM 0x10
#define FAULT_CODE_LDCSTC 0x08
#define FAULT_CODE_PREFETCH 0x04
#define FAULT_CODE_WRITE 0x02
#define FAULT_CODE_FORCECOW 0x01
#define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
#define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
extern int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs);
extern void show_pte(struct mm_struct *mm, unsigned long addr);
/*
* Handle a data abort. Note that we have to handle a range of addresses
* on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force
* a copy-on-write. However, on the second page, we always force COW.
*/
asmlinkage void
do_DataAbort(unsigned long min_addr, unsigned long max_addr, int mode, struct pt_regs *regs)
{
do_page_fault(min_addr, mode, regs);
if ((min_addr ^ max_addr) >> PAGE_SHIFT)
do_page_fault(max_addr, mode | FAULT_CODE_FORCECOW, regs);
}
asmlinkage int
do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
{
#if 0
if (the memc mapping for this page exists) {
printk ("Page in, but got abort (undefined instruction?)\n");
return 0;
}
#endif
do_page_fault(addr, FAULT_CODE_PREFETCH, regs);
return 1;
}
/*
* linux/arch/arm/kernel/head-armo.S
*
* Copyright (C) 1994-2000 Russell King
*
* 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.
*
* 26-bit kernel startup code
*/
#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/mach-types.h>
.globl swapper_pg_dir
.equ swapper_pg_dir, 0x0207d000
/*
* Entry point.
*/
__INIT
ENTRY(stext)
__entry: cmp pc, #0x02000000
ldrlt pc, LC0 @ if 0x01800000, call at 0x02080000
teq r0, #0 @ Check for old calling method
blne oldparams @ Move page if old
adr r0, LC0
ldmib r0, {r2-r5, sp} @ Setup stack
mov r0, #0
1: cmp r2, r3 @ Clear BSS
strcc r0, [r2], #4
bcc 1b
bl detect_proc_type
str r0, [r4]
bl detect_arch_type
str r0, [r5]
mov fp, #0
b start_kernel
LC0: .word _stext
.word __bss_start @ r2
.word _end @ r3
.word processor_id @ r4
.word __machine_arch_type @ r5
.word init_task_union+8192 @ sp
arm2_id: .long 0x41560200
arm250_id: .long 0x41560250
.align
oldparams: mov r4, #0x02000000
add r3, r4, #0x00080000
add r4, r4, #0x0007c000
1: ldmia r0!, {r5 - r12}
stmia r4!, {r5 - r12}
cmp r4, r3
blt 1b
mov pc, lr
/*
* We need some way to automatically detect the difference between
* these two machines. Unfortunately, it is not possible to detect
* the presence of the SuperIO chip, because that will hang the old
* Archimedes machines solid.
*/
/* DAG: Outdated, these have been combined !!!!!!! */
detect_arch_type:
#if defined(CONFIG_ARCH_ARC)
mov r0, #MACH_TYPE_ARCHIMEDES
#elif defined(CONFIG_ARCH_A5K)
mov r0, #MACH_TYPE_A5K
#endif
mov pc, lr
detect_proc_type:
mov ip, lr
mov r2, #0xea000000 @ Point undef instr to continuation
adr r0, continue - 12
orr r0, r2, r0, lsr #2
mov r1, #0
str r0, [r1, #4]
ldr r0, arm2_id
swp r2, r2, [r1] @ check for swp (ARM2 cant)
ldr r0, arm250_id
mrc 15, 0, r3, c0, c0 @ check for CP#15 (ARM250 cant)
mov r0, r3
continue: mov r2, #0xeb000000 @ Make undef vector loop
sub r2, r2, #2
str r2, [r1, #4]
mov pc, ip
/*
* linux/arch/arm/mach-arc/irq.c
*
* Copyright (C) 1996 Russell King
*
* 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.
*
* Changelog:
* 24-09-1996 RMK Created
* 10-10-1996 RMK Brought up to date with arch-sa110eval
* 22-10-1996 RMK Changed interrupt numbers & uses new inb/outb macros
* 11-01-1998 RMK Added mask_and_ack_irq
* 22-08-1998 RMK Restructured IRQ routines
*/
#include <linux/config.h>
#include <linux/init.h>
#include <asm/mach/irq.h>
#include <asm/hardware/ioc.h>
#include <asm/io.h>
#include <asm/system.h>
extern void init_FIQ(void);
#ifdef CONFIG_ARCH_ARC
#define a_clf() clf()
#define a_stf() stf()
#else
#define a_clf() do { } while (0)
#define a_stf() do { } while (0)
#endif
static void arc_mask_irq_ack_a(unsigned int irq)
{
unsigned int val, mask;
mask = 1 << irq;
a_clf();
val = ioc_readb(IOC_IRQMASKA);
ioc_writeb(val & ~mask, IOC_IRQMASKA);
ioc_writeb(mask, IOC_IRQCLRA);
a_stf();
}
static void arc_mask_irq_a(unsigned int irq)
{
unsigned int val, mask;
mask = 1 << irq;
a_clf();
val = ioc_readb(IOC_IRQMASKA);
ioc_writeb(val & ~mask, IOC_IRQMASKA);
a_stf();
}
static void arc_unmask_irq_a(unsigned int irq)
{
unsigned int val, mask;
mask = 1 << irq;
a_clf();
val = ioc_readb(IOC_IRQMASKA);
ioc_writeb(val | mask, IOC_IRQMASKA);
a_stf();
}
static void arc_mask_irq_b(unsigned int irq)
{
unsigned int val, mask;
mask = 1 << (irq & 7);
val = ioc_readb(IOC_IRQMASKB);
ioc_writeb(val & ~mask, IOC_IRQMASKB);
}
static void arc_unmask_irq_b(unsigned int irq)
{
unsigned int val, mask;
mask = 1 << (irq & 7);
val = ioc_readb(IOC_IRQMASKB);
ioc_writeb(val | mask, IOC_IRQMASKB);
}
static void arc_mask_irq_fiq(unsigned int irq)
{
unsigned int val, mask;
mask = 1 << (irq & 7);
val = ioc_readb(IOC_FIQMASK);
ioc_writeb(val & ~mask, IOC_FIQMASK);
}
static void arc_unmask_irq_fiq(unsigned int irq)
{
unsigned int val, mask;
mask = 1 << (irq & 7);
val = ioc_readb(IOC_FIQMASK);
ioc_writeb(val | mask, IOC_FIQMASK);
}
void __init arc_init_irq(void)
{
int irq;
ioc_writeb(0, IOC_IRQMASKA);
ioc_writeb(0, IOC_IRQMASKB);
ioc_writeb(0, IOC_FIQMASK);
for (irq = 0; irq < NR_IRQS; irq++) {
switch (irq) {
case 0 ... 6:
irq_desc[irq].probe_ok = 1;
irq_desc[irq].valid = 1;
irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
irq_desc[irq].mask = arc_mask_irq_a;
irq_desc[irq].unmask = arc_unmask_irq_a;
break;
case 7:
irq_desc[irq].noautoenable = 1;
irq_desc[irq].valid = 1;
irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
irq_desc[irq].mask = arc_mask_irq_a;
irq_desc[irq].unmask = arc_unmask_irq_a;
break;
case 9 ... 15:
irq_desc[irq].probe_ok = 1;
case 8:
irq_desc[irq].valid = 1;
irq_desc[irq].mask_ack = arc_mask_irq_b;
irq_desc[irq].mask = arc_mask_irq_b;
irq_desc[irq].unmask = arc_unmask_irq_b;
break;
case 64 ... 72:
irq_desc[irq].valid = 1;
irq_desc[irq].mask_ack = arc_mask_irq_fiq;
irq_desc[irq].mask = arc_mask_irq_fiq;
irq_desc[irq].unmask = arc_unmask_irq_fiq;
break;
}
}
irq_desc[IRQ_KEYBOARDTX].noautoenable = 1;
init_FIQ();
}
/*
* linux/arch/arm/mm/mm-armo.c
*
* Copyright (C) 1998-2000 Russell King
*
* 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.
*
* Page table sludge for older ARM processor architectures.
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
#include <asm/arch/memory.h>
#include <asm/mach/map.h>
#define MEMC_TABLE_SIZE (256*sizeof(unsigned long))
kmem_cache_t *pte_cache, *pgd_cache;
int page_nr;
/*
* Allocate a page table. Note that we place the MEMC
* table before the page directory. This means we can
* easily get to both tightly-associated data structures
* with a single pointer.
*/
static inline pgd_t *alloc_pgd_table(int priority)
{
void *pg2k = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
if (pg2k)
pg2k += MEMC_TABLE_SIZE;
return (pgd_t *)pg2k;
}
void free_pgd_slow(pgd_t *pgd)
{
unsigned long tbl = (unsigned long)pgd;
/*
* CHECKME: are we leaking pte tables here???
*/
tbl -= MEMC_TABLE_SIZE;
kmem_cache_free(pgd_cache, (void *)tbl);
}
pgd_t *get_pgd_slow(struct mm_struct *mm)
{
pgd_t *new_pgd, *init_pgd;
pmd_t *new_pmd, *init_pmd;
pte_t *new_pte, *init_pte;
new_pgd = alloc_pgd_table(GFP_KERNEL);
if (!new_pgd)
goto no_pgd;
/*
* This lock is here just to satisfy pmd_alloc and pte_lock
*/
spin_lock(&mm->page_table_lock);
/*
* On ARM, first page must always be allocated since it contains
* the machine vectors.
*/
new_pmd = pmd_alloc(mm, new_pgd, 0);
if (!new_pmd)
goto no_pmd;
new_pte = pte_alloc_map(mm, new_pmd, 0);
if (!new_pte)
goto no_pte;
init_pgd = pgd_offset_k(0);
init_pmd = pmd_offset(init_pgd, 0);
init_pte = pte_offset_map_nested(init_pmd, 0);
set_pte(new_pte, *init_pte);
pte_unmap_nested(init_pte);
pte_unmap(new_pte);
/*
* most of the page table entries are zeroed
* wne the table is created.
*/
memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
spin_unlock(&mm->page_table_lock);
/* update MEMC tables */
cpu_memc_update_all(new_pgd);
return new_pgd;
no_pte:
spin_unlock(&mm->page_table_lock);
pmd_free(new_pmd);
free_pgd_slow(new_pgd);
return NULL;
no_pmd:
spin_unlock(&mm->page_table_lock);
free_pgd_slow(new_pgd);
return NULL;
no_pgd:
return NULL;
}
/*
* No special code is required here.
*/
void setup_mm_for_reboot(char mode)
{
}
/*
* This contains the code to setup the memory map on an ARM2/ARM250/ARM3
* machine. This is both processor & architecture specific, and requires
* some more work to get it to fit into our separate processor and
* architecture structure.
*/
void __init memtable_init(struct meminfo *mi)
{
pte_t *pte;
int i;
page_nr = max_low_pfn;
pte = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t));
pte[0] = pfn_pte((PAGE_OFFSET + 491520) >> PAGE_SHIFT, PAGE_READONLY);
pmd_populate(&init_mm, pmd_offset(swapper_pg_dir, 0), pte);
for (i = 1; i < PTRS_PER_PGD; i++)
pgd_val(swapper_pg_dir[i]) = 0;
}
void __init iotable_init(struct map_desc *io_desc)
{
/* nothing to do */
}
/*
* We never have holes in the memmap
*/
void __init create_memmap_holes(struct meminfo *mi)
{
}
static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
{
memzero(pte, sizeof(pte_t) * PTRS_PER_PTE);
}
static void pgd_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
{
pgd_t *pgd = (pte + MEMC_TABLE_SIZE);
memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
}
void __init pgtable_cache_init(void)
{
pte_cache = kmem_cache_create("pte-cache",
sizeof(pte_t) * PTRS_PER_PTE,
0, 0, pte_cache_ctor, NULL);
if (!pte_cache)
BUG();
pgd_cache = kmem_cache_create("pgd-cache", MEMC_TABLE_SIZE +
sizeof(pgd_t) * PTRS_PER_PGD,
0, 0, pgd_cache_ctor, NULL);
if (!pgd_cache)
BUG();
}
/*
* linux/arch/arm/kernel/oldlatches.c
*
* Copyright (C) David Alan Gilbert 1995/1996,2000
*
* 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.
*
* Support for the latches on the old Archimedes which control the floppy,
* hard disc and printer
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/oldlatches.h>
static unsigned char latch_a_copy;
static unsigned char latch_b_copy;
/* newval=(oldval & ~mask)|newdata */
void oldlatch_aupdate(unsigned char mask,unsigned char newdata)
{
if (machine_is_archimedes()) {
unsigned long flags;
local_save_flags(flags);
latch_a_copy = (latch_a_copy & ~mask) | newdata;
__raw_writeb(latch_a_copy, LATCHA_BASE);
local_restore_flags(flags);
printk("Latch: A = 0x%02x\n", latch_a_copy);
} else
BUG();
}
/* newval=(oldval & ~mask)|newdata */
void oldlatch_bupdate(unsigned char mask,unsigned char newdata)
{
if (machine_is_archimedes()) {
unsigned long flags;
local_save_flags(flags);
latch_b_copy = (latch_b_copy & ~mask) | newdata;
__raw_writeb(latch_b_copy, LATCHB_BASE);
local_restore_flags(flags);
printk("Latch: B = 0x%02x\n", latch_b_copy);
} else
BUG();
}
static int __init oldlatch_init(void)
{
if (machine_is_archimedes()) {
oldlatch_aupdate(0xff, 0xff);
/* Thats no FDC reset...*/
oldlatch_bupdate(0xff, LATCHB_FDCRESET);
}
return 0;
}
__initcall(oldlatch_init);
EXPORT_SYMBOL(oldlatch_aupdate);
EXPORT_SYMBOL(oldlatch_bupdate);
/*
* linux/arch/arm/mm/small_page.c
*
* Copyright (C) 1996 Russell King
*
* 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.
*
* Changelog:
* 26/01/1996 RMK Cleaned up various areas to make little more generic
* 07/02/1999 RMK Support added for 16K and 32K page sizes
* containing 8K blocks
*/
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
#define PEDANTIC
/*
* Requirement:
* We need to be able to allocate naturally aligned memory of finer
* granularity than the page size. This is typically used for the
* second level page tables on 32-bit ARMs.
*
* Theory:
* We "misuse" the Linux memory management system. We use alloc_page
* to allocate a page and then mark it as reserved. The Linux memory
* management system will then ignore the "offset", "next_hash" and
* "pprev_hash" entries in the mem_map for this page.
*
* We then use a bitstring in the "offset" field to mark which segments
* of the page are in use, and manipulate this as required during the
* allocation and freeing of these small pages.
*
* We also maintain a queue of pages being used for this purpose using
* the "next_hash" and "pprev_hash" entries of mem_map;
*/
struct order {
struct list_head queue;
unsigned int mask; /* (1 << shift) - 1 */
unsigned int shift; /* (1 << shift) size of page */
unsigned int block_mask; /* nr_blocks - 1 */
unsigned int all_used; /* (1 << nr_blocks) - 1 */
};
static struct order orders[] = {
#if PAGE_SIZE == 4096
{ LIST_HEAD_INIT(orders[0].queue), 2047, 11, 1, 0x00000003 }
#elif PAGE_SIZE == 32768
{ LIST_HEAD_INIT(orders[0].queue), 2047, 11, 15, 0x0000ffff },
{ LIST_HEAD_INIT(orders[1].queue), 8191, 13, 3, 0x0000000f }
#else
#error unsupported page size
#endif
};
#define USED_MAP(pg) ((pg)->index)
#define TEST_AND_CLEAR_USED(pg,off) (test_and_clear_bit(off, &USED_MAP(pg)))
#define SET_USED(pg,off) (set_bit(off, &USED_MAP(pg)))
static spinlock_t small_page_lock = SPIN_LOCK_UNLOCKED;
static unsigned long __get_small_page(int priority, struct order *order)
{
unsigned long flags;
struct page *page;
int offset;
do {
spin_lock_irqsave(&small_page_lock, flags);
if (list_empty(&order->queue))
goto need_new_page;
page = list_entry(order->queue.next, struct page, list);
again:
#ifdef PEDANTIC
if (USED_MAP(page) & ~order->all_used)
PAGE_BUG(page);
#endif
offset = ffz(USED_MAP(page));
SET_USED(page, offset);
if (USED_MAP(page) == order->all_used)
list_del_init(&page->list);
spin_unlock_irqrestore(&small_page_lock, flags);
return (unsigned long) page_address(page) + (offset << order->shift);
need_new_page:
spin_unlock_irqrestore(&small_page_lock, flags);
page = alloc_page(priority);
spin_lock_irqsave(&small_page_lock, flags);
if (list_empty(&order->queue)) {
if (!page)
goto no_page;
SetPageReserved(page);
USED_MAP(page) = 0;
list_add(&page->list, &order->queue);
goto again;
}
spin_unlock_irqrestore(&small_page_lock, flags);
__free_page(page);
} while (1);
no_page:
spin_unlock_irqrestore(&small_page_lock, flags);
return 0;
}
static void __free_small_page(unsigned long spage, struct order *order)
{
unsigned long flags;
struct page *page;
if (virt_addr_valid(spage)) {
page = virt_to_page(spage);
/*
* The container-page must be marked Reserved
*/
if (!PageReserved(page) || spage & order->mask)
goto non_small;
#ifdef PEDANTIC
if (USED_MAP(page) & ~order->all_used)
PAGE_BUG(page);
#endif
spage = spage >> order->shift;
spage &= order->block_mask;
/*
* the following must be atomic wrt get_page
*/
spin_lock_irqsave(&small_page_lock, flags);
if (USED_MAP(page) == order->all_used)
list_add(&page->list, &order->queue);
if (!TEST_AND_CLEAR_USED(page, spage))
goto already_free;
if (USED_MAP(page) == 0)
goto free_page;
spin_unlock_irqrestore(&small_page_lock, flags);
}
return;
free_page:
/*
* unlink the page from the small page queue and free it
*/
list_del_init(&page->list);
spin_unlock_irqrestore(&small_page_lock, flags);
ClearPageReserved(page);
__free_page(page);
return;
non_small:
printk("Trying to free non-small page from %p\n", __builtin_return_address(0));
return;
already_free:
printk("Trying to free free small page from %p\n", __builtin_return_address(0));
}
unsigned long get_page_8k(int priority)
{
return __get_small_page(priority, orders+1);
}
void free_page_8k(unsigned long spage)
{
__free_small_page(spage, orders+1);
}
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/hardware.h> #include <asm/hardware.h>
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -92,7 +93,7 @@ void pxa_free_dma (int dma_ch) ...@@ -92,7 +93,7 @@ void pxa_free_dma (int dma_ch)
local_irq_restore(flags); local_irq_restore(flags);
} }
static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{ {
int i, dint = DINT; int i, dint = DINT;
...@@ -111,6 +112,7 @@ static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ...@@ -111,6 +112,7 @@ static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
} }
} }
} }
return IRQ_HANDLED;
} }
static int __init pxa_dma_init (void) static int __init pxa_dma_init (void)
......
...@@ -103,7 +103,7 @@ EXPORT_SYMBOL(get_lclk_frequency_10khz); ...@@ -103,7 +103,7 @@ EXPORT_SYMBOL(get_lclk_frequency_10khz);
void pxa_gpio_mode(int gpio_mode) void pxa_gpio_mode(int gpio_mode)
{ {
long flags; unsigned long flags;
int gpio = gpio_mode & GPIO_MD_MASK_NR; int gpio = gpio_mode & GPIO_MD_MASK_NR;
int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8; int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
int gafr; int gafr;
......
...@@ -11,12 +11,6 @@ ...@@ -11,12 +11,6 @@
* modify it under the terms of the GNU General Public License. * modify it under the terms of the GNU General Public License.
*/ */
#include <linux/config.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <asm/hardware.h> #include <asm/hardware.h>
...@@ -81,7 +75,7 @@ int pm_do_suspend(void) ...@@ -81,7 +75,7 @@ int pm_do_suspend(void)
/* /*
* Temporary solution. This won't be necessary once * Temporary solution. This won't be necessary once
* we move pxa support into the serial/* driver * we move pxa support into the serial driver
* Save the FF UART * Save the FF UART
*/ */
SAVE(FFIER); SAVE(FFIER);
...@@ -175,7 +169,7 @@ int pm_do_suspend(void) ...@@ -175,7 +169,7 @@ int pm_do_suspend(void)
/* /*
* Temporary solution. This won't be necessary once * Temporary solution. This won't be necessary once
* we move pxa support into the serial/* driver. * we move pxa support into the serial driver.
* Restore the FF UART. * Restore the FF UART.
*/ */
RESTORE(FFMCR); RESTORE(FFMCR);
...@@ -207,58 +201,3 @@ unsigned long sleep_phys_sp(void *sp) ...@@ -207,58 +201,3 @@ unsigned long sleep_phys_sp(void *sp)
{ {
return virt_to_phys(sp); return virt_to_phys(sp);
} }
#ifdef CONFIG_SYSCTL
/*
* ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
* linux/sysctl.h.
*
* This means our interface here won't survive long - it needs a new
* interface. Quick hack to get this working - use sysctl id 9999.
*/
#warning ACPI broke the kernel, this interface needs to be fixed up.
#define CTL_ACPI 9999
#define ACPI_S1_SLP_TYP 19
/*
* Send us to sleep.
*/
static int sysctl_pm_do_suspend(void)
{
int retval;
retval = pm_send_all(PM_SUSPEND, (void *)3);
if (retval == 0) {
retval = pm_do_suspend();
pm_send_all(PM_RESUME, (void *)0);
}
return retval;
}
static struct ctl_table pm_table[] =
{
{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
{0}
};
static struct ctl_table pm_dir_table[] =
{
{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
{0}
};
/*
* Initialize power interface
*/
static int __init pm_init(void)
{
register_sysctl_table(pm_dir_table, 1);
return 0;
}
__initcall(pm_init);
#endif
...@@ -48,7 +48,7 @@ ENTRY(pxa_cpu_suspend) ...@@ -48,7 +48,7 @@ ENTRY(pxa_cpu_suspend)
str r0, [r1] str r0, [r1]
@ clean data cache @ clean data cache
bl cpu_xscale_cache_clean_invalidate_all bl xscale_flush_kern_cache_all
@ Put the processor to sleep @ Put the processor to sleep
@ (also workaround for sighting 28071) @ (also workaround for sighting 28071)
...@@ -101,7 +101,7 @@ ENTRY(pxa_cpu_suspend) ...@@ -101,7 +101,7 @@ ENTRY(pxa_cpu_suspend)
.data .data
.align 5 .align 5
ENTRY(pxa_cpu_resume) ENTRY(pxa_cpu_resume)
mov r0, #I_BIT | F_BIT | MODE_SVC @ set SVC, irqs off mov r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC @ set SVC, irqs off
msr cpsr_c, r0 msr cpsr_c, r0
ldr r0, sleep_save_sp @ stack phys addr ldr r0, sleep_save_sp @ stack phys addr
......
...@@ -1110,7 +1110,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i ...@@ -1110,7 +1110,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
release_mem_region(card->mem_base, card->mem_len); release_mem_region(card->mem_base, card->mem_len);
failed_req_mem: failed_req_mem:
#endif #endif
iounmap((void *) card->csr_base); iounmap((void *) card->csr_remap);
failed_remap_csr: failed_remap_csr:
release_mem_region(card->csr_base, card->csr_len); release_mem_region(card->csr_base, card->csr_len);
failed_req_csr: failed_req_csr:
......
...@@ -74,6 +74,17 @@ static inline void write_ireg(u_long base, u_int reg, u_int val) ...@@ -74,6 +74,17 @@ static inline void write_ireg(u_long base, u_int reg, u_int val)
" : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
} }
static inline unsigned short read_ireg(u_long base_addr, u_int reg)
{
u_short v;
__asm__(
"str%?h %1, [%2] @ NAT_RAP\n\t"
"str%?h %0, [%2, #8] @ NET_IDP\n\t"
: "=r" (v)
: "r" (reg), "r" (ISAIO_BASE + 0x0464));
return v;
}
#define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1)) #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
#define am_readword(dev,off) __raw_readw(ISAMEM_BASE + ((off) << 1)) #define am_readword(dev,off) __raw_readw(ISAMEM_BASE + ((off) << 1))
...@@ -253,9 +264,27 @@ am79c961_init_for_open(struct net_device *dev) ...@@ -253,9 +264,27 @@ am79c961_init_for_open(struct net_device *dev)
write_rreg (dev->base_addr, BASERXH, 0); write_rreg (dev->base_addr, BASERXH, 0);
write_rreg (dev->base_addr, CSR0, CSR0_STOP); write_rreg (dev->base_addr, CSR0, CSR0_STOP);
write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO); write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT); write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
} }
static void am79c961_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct dev_priv *priv = (struct dev_priv *)dev->priv;
unsigned int lnkstat, carrier;
lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
carrier = netif_carrier_ok(dev);
if (lnkstat && !carrier)
netif_carrier_on(dev);
else if (!lnkstat && carrier)
netif_carrier_off(dev);
mod_timer(&priv->timer, jiffies + 5*HZ);
}
/* /*
* Open/initialize the board. * Open/initialize the board.
*/ */
...@@ -273,6 +302,11 @@ am79c961_open(struct net_device *dev) ...@@ -273,6 +302,11 @@ am79c961_open(struct net_device *dev)
am79c961_init_for_open(dev); am79c961_init_for_open(dev);
netif_carrier_off(dev);
priv->timer.expires = jiffies;
add_timer(&priv->timer);
netif_start_queue(dev); netif_start_queue(dev);
return 0; return 0;
...@@ -287,7 +321,10 @@ am79c961_close(struct net_device *dev) ...@@ -287,7 +321,10 @@ am79c961_close(struct net_device *dev)
struct dev_priv *priv = (struct dev_priv *)dev->priv; struct dev_priv *priv = (struct dev_priv *)dev->priv;
unsigned long flags; unsigned long flags;
del_timer_sync(&priv->timer);
netif_stop_queue(dev); netif_stop_queue(dev);
netif_carrier_off(dev);
spin_lock_irqsave(priv->chip_lock, flags); spin_lock_irqsave(priv->chip_lock, flags);
write_rreg (dev->base_addr, CSR0, CSR0_STOP); write_rreg (dev->base_addr, CSR0, CSR0_STOP);
...@@ -408,19 +445,10 @@ static int ...@@ -408,19 +445,10 @@ static int
am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev) am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
{ {
struct dev_priv *priv = (struct dev_priv *)dev->priv; struct dev_priv *priv = (struct dev_priv *)dev->priv;
unsigned int length = skb->len;
unsigned int hdraddr, bufaddr; unsigned int hdraddr, bufaddr;
unsigned int head; unsigned int head;
unsigned long flags; unsigned long flags;
/* FIXME: I thought the 79c961 could do padding - RMK ??? */
if (length < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN);
if (skb == NULL)
return 0;
length = ETH_ZLEN;
}
head = priv->txhead; head = priv->txhead;
hdraddr = priv->txhdr + (head << 3); hdraddr = priv->txhdr + (head << 3);
bufaddr = priv->txbuffer[head]; bufaddr = priv->txbuffer[head];
...@@ -428,8 +456,8 @@ am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev) ...@@ -428,8 +456,8 @@ am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
if (head >= TX_BUFFERS) if (head >= TX_BUFFERS)
head = 0; head = 0;
am_writebuffer (dev, bufaddr, skb->data, length); am_writebuffer (dev, bufaddr, skb->data, skb->len);
am_writeword (dev, hdraddr + 4, -length); am_writeword (dev, hdraddr + 4, -skb->len);
am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP); am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
priv->txhead = head; priv->txhead = head;
...@@ -518,6 +546,7 @@ static void ...@@ -518,6 +546,7 @@ static void
am79c961_tx(struct net_device *dev, struct dev_priv *priv) am79c961_tx(struct net_device *dev, struct dev_priv *priv)
{ {
do { do {
short len;
u_int hdraddr; u_int hdraddr;
u_int status; u_int status;
...@@ -553,6 +582,8 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv) ...@@ -553,6 +582,8 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv)
continue; continue;
} }
priv->stats.tx_packets ++; priv->stats.tx_packets ++;
len = am_readword (dev, hdraddr + 4);
priv->stats.tx_bytes += -len;
} while (priv->txtail != priv->txhead); } while (priv->txtail != priv->txhead);
netif_wake_queue(dev); netif_wake_queue(dev);
...@@ -563,11 +594,14 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -563,11 +594,14 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *)dev_id; struct net_device *dev = (struct net_device *)dev_id;
struct dev_priv *priv = (struct dev_priv *)dev->priv; struct dev_priv *priv = (struct dev_priv *)dev->priv;
u_int status; u_int status, n = 100;
int handled = 0; int handled = 0;
do {
status = read_rreg(dev->base_addr, CSR0); status = read_rreg(dev->base_addr, CSR0);
write_rreg(dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA)); write_rreg(dev->base_addr, CSR0, status &
(CSR0_IENA|CSR0_TINT|CSR0_RINT|
CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
if (status & CSR0_RINT) { if (status & CSR0_RINT) {
handled = 1; handled = 1;
...@@ -581,6 +615,11 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -581,6 +615,11 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
handled = 1; handled = 1;
priv->stats.rx_dropped ++; priv->stats.rx_dropped ++;
} }
if (status & CSR0_CERR) {
handled = 1;
mod_timer(&priv->timer, jiffies);
} while (--n && status & (CSR0_RINT | CSR0_TINT));
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
...@@ -593,10 +632,10 @@ am79c961_hw_init(struct net_device *dev) ...@@ -593,10 +632,10 @@ am79c961_hw_init(struct net_device *dev)
{ {
struct dev_priv *priv = (struct dev_priv *)dev->priv; struct dev_priv *priv = (struct dev_priv *)dev->priv;
spin_lock_irq(priv->chip_lock); spin_lock_irq(&priv->chip_lock);
write_rreg (dev->base_addr, CSR0, CSR0_STOP); write_rreg (dev->base_addr, CSR0, CSR0_STOP);
write_rreg (dev->base_addr, CSR3, CSR3_MASKALL); write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
spin_unlock_irq(priv->chip_lock); spin_unlock_irq(&priv->chip_lock);
am79c961_ramtest(dev, 0x66); am79c961_ramtest(dev, 0x66);
am79c961_ramtest(dev, 0x99); am79c961_ramtest(dev, 0x99);
...@@ -661,6 +700,11 @@ static int __init am79c961_init(void) ...@@ -661,6 +700,11 @@ static int __init am79c961_init(void)
printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
} }
spin_lock_init(&priv->chip_lock);
init_timer(&priv->timer);
priv->timer.data = (unsigned long)dev;
priv->timer.function = am79c961_timer;
if (am79c961_hw_init(dev)) if (am79c961_hw_init(dev))
goto release; goto release;
......
...@@ -58,6 +58,18 @@ ...@@ -58,6 +58,18 @@
#define CSR3_BABLM 0x4000 #define CSR3_BABLM 0x4000
#define CSR3_MASKALL 0x5F00 #define CSR3_MASKALL 0x5F00
#define CSR4 4
#define CSR4_JABM 0x0001
#define CSR4_JAB 0x0002
#define CSR4_TXSTRTM 0x0004
#define CSR4_TXSTRT 0x0008
#define CSR4_RCVCCOM 0x0010
#define CSR4_RCVCCO 0x0020
#define CSR4_MFCOM 0x0100
#define CSR4_MFCO 0x0200
#define CSR4_ASTRP_RCV 0x0400
#define CSR4_APAD_XMIT 0x0800
#define CTRL1 5 #define CTRL1 5
#define CTRL1_SPND 0x0001 #define CTRL1_SPND 0x0001
...@@ -93,6 +105,8 @@ ...@@ -93,6 +105,8 @@
#define SIZERXR 76 #define SIZERXR 76
#define SIZETXR 78 #define SIZETXR 78
#define CSR_MFC 112
#define RMD_ENP 0x0100 #define RMD_ENP 0x0100
#define RMD_STP 0x0200 #define RMD_STP 0x0200
#define RMD_CRC 0x0800 #define RMD_CRC 0x0800
...@@ -112,6 +126,9 @@ ...@@ -112,6 +126,9 @@
#define TST_UFLO 0x4000 #define TST_UFLO 0x4000
#define TST_BUFF 0x8000 #define TST_BUFF 0x8000
#define ISALED0 0x0004
#define ISALED0_LNKST 0x8000
struct dev_priv { struct dev_priv {
struct net_device_stats stats; struct net_device_stats stats;
unsigned long rxbuffer[RX_BUFFERS]; unsigned long rxbuffer[RX_BUFFERS];
...@@ -123,6 +140,7 @@ struct dev_priv { ...@@ -123,6 +140,7 @@ struct dev_priv {
unsigned long rxhdr; unsigned long rxhdr;
unsigned long txhdr; unsigned long txhdr;
spinlock_t chip_lock; spinlock_t chip_lock;
struct timer_list timer;
}; };
extern int am79c961_probe (struct net_device *dev); extern int am79c961_probe (struct net_device *dev);
......
...@@ -687,7 +687,6 @@ static int ...@@ -687,7 +687,6 @@ static int
ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
{ {
struct ether1_priv *priv = (struct ether1_priv *)dev->priv; struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
int len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr; int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
unsigned long flags; unsigned long flags;
tx_t tx; tx_t tx;
...@@ -705,12 +704,18 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) ...@@ -705,12 +704,18 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
priv->restart = 0; priv->restart = 0;
} }
if (skb->len < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN);
if (skb == NULL)
goto out;
}
/* /*
* insert packet followed by a nop * insert packet followed by a nop
*/ */
txaddr = ether1_txalloc (dev, TX_SIZE); txaddr = ether1_txalloc (dev, TX_SIZE);
tbdaddr = ether1_txalloc (dev, TBD_SIZE); tbdaddr = ether1_txalloc (dev, TBD_SIZE);
dataddr = ether1_txalloc (dev, len); dataddr = ether1_txalloc (dev, skb->len);
nopaddr = ether1_txalloc (dev, NOP_SIZE); nopaddr = ether1_txalloc (dev, NOP_SIZE);
tx.tx_status = 0; tx.tx_status = 0;
...@@ -728,7 +733,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) ...@@ -728,7 +733,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
local_irq_save(flags); local_irq_save(flags);
ether1_writebuffer (dev, &tx, txaddr, TX_SIZE); ether1_writebuffer (dev, &tx, txaddr, TX_SIZE);
ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE); ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
ether1_writebuffer (dev, skb->data, dataddr, len); ether1_writebuffer (dev, skb->data, dataddr, skb->len);
ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE); ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE);
tmp = priv->tx_link; tmp = priv->tx_link;
priv->tx_link = nopaddr; priv->tx_link = nopaddr;
...@@ -750,6 +755,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) ...@@ -750,6 +755,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
if (tst == -1) if (tst == -1)
netif_stop_queue(dev); netif_stop_queue(dev);
out:
return 0; return 0;
} }
......
...@@ -523,8 +523,6 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) ...@@ -523,8 +523,6 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned int ptr, next_ptr; unsigned int ptr, next_ptr;
length = (length + 1) & ~1;
if (priv->broken) { if (priv->broken) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
priv->stats.tx_dropped ++; priv->stats.tx_dropped ++;
...@@ -532,6 +530,13 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) ...@@ -532,6 +530,13 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
return 0; return 0;
} }
length = (length + 1) & ~1;
if (length != skb->len) {
skb = skb_padto(skb, length);
if (skb == NULL)
goto out;
}
next_ptr = (priv->tx_head + 1) & 15; next_ptr = (priv->tx_head + 1) & 15;
local_irq_save(flags); local_irq_save(flags);
...@@ -573,6 +578,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) ...@@ -573,6 +578,7 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
if (priv->tx_tail == next_ptr) if (priv->tx_tail == next_ptr)
netif_stop_queue(dev); netif_stop_queue(dev);
out:
return 0; return 0;
} }
......
...@@ -325,9 +325,7 @@ static int ti113x_override(struct yenta_socket *socket) ...@@ -325,9 +325,7 @@ static int ti113x_override(struct yenta_socket *socket)
static int ti1250_init(struct pcmcia_socket *sock) static int ti1250_init(struct pcmcia_socket *sock)
{ {
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
yenta_init(sock);
ti113x_init(sock); ti113x_init(sock);
ti_set_zv(sock);
ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX); ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX);
ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */ ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */
if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE)) if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE))
......
/*
* linux/include/asm-arm/arch-arc/dma.h
*
* Copyright (C) 1996-1998 Russell King
*
* 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.
*
* Acorn Archimedes/A5000 architecture virtual DMA
* implementation
*
* Modifications:
* 04-04-1998 RMK Merged arc and a5k versions
*/
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
#define MAX_DMA_ADDRESS 0x03000000
#define MAX_DMA_CHANNELS 3
/* ARC */
#define DMA_VIRTUAL_FLOPPY0 0
#define DMA_VIRTUAL_FLOPPY1 1
#define DMA_VIRTUAL_SOUND 2
/* A5K */
#define DMA_FLOPPY DMA_VIRTUAL_FLOPPY0
#endif /* _ASM_ARCH_DMA_H */
/*
* linux/include/asm-arm/arch-arc/hardware.h
*
* Copyright (C) 1996-1999 Russell King.
*
* 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 file contains the hardware definitions of the
* Acorn Archimedes/A5000 machines.
*
* Modifications:
* 04-04-1998 PJB/RMK Merged arc and a5k versions
*/
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
#include <linux/config.h>
#include <asm/arch/memory.h>
/*
* What hardware must be present - these can be tested by the kernel
* source.
*/
#define HAS_IOC
#define HAS_MEMC
#include <asm/hardware/memc.h>
#define HAS_VIDC
/* Hardware addresses of major areas.
* *_START is the physical address
* *_SIZE is the size of the region
* *_BASE is the virtual address
*/
#define IO_START 0x03000000
#define IO_SIZE 0x01000000
#define IO_BASE 0x03000000
/*
* Screen mapping information
*/
#define SCREEN_START 0x02000000
#define SCREEN_END 0x02078000
#define SCREEN_BASE 0x02000000
#define EXPMASK_BASE 0x03360000
#define IOEB_BASE 0x03350000
#define VIDC_BASE 0x03400000
#define LATCHA_BASE 0x03250040
#define LATCHB_BASE 0x03250018
#define IOC_BASE 0x03200000
#define FLOPPYDMA_BASE 0x0302a000
#define PCIO_BASE 0x03010000
#define vidc_writel(val) __raw_writel(val, VIDC_BASE)
#ifndef __ASSEMBLY__
/*
* for use with inb/outb
*/
#ifdef CONFIG_ARCH_A5K
#define IOEB_VID_CTL (IOEB_BASE + 0x48)
#define IOEB_PRESENT (IOEB_BASE + 0x50)
#define IOEB_PSCLR (IOEB_BASE + 0x58)
#define IOEB_MONTYPE (IOEB_BASE + 0x70)
#endif
#define IO_EC_IOC_BASE 0x80090000
#define IO_EC_MEMC_BASE 0x80000000
#ifdef CONFIG_ARCH_ARC
/* A680 hardware */
#define WD1973_BASE 0x03290000
#define WD1973_LATCH 0x03350000
#define Z8530_BASE 0x032b0008
#define SCSI_BASE 0x03100000
#endif
#endif
#define EXPMASK_STATUS (EXPMASK_BASE + 0x00)
#define EXPMASK_ENABLE (EXPMASK_BASE + 0x04)
#endif
/*
* linux/include/asm-arm/arch-arc/ide.h
*
* Copyright (C) 1997,1998 Russell King
*
* 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.
*
* IDE definitions for the Acorn Archimedes/A5000
* architecture
*
* Modifications:
* 04-04-1998 PJB Merged `arc' and `a5k' versions
* 01-07-1998 RMK Added new ide_ioregspec_t
* 29-07-1998 RMK Major re-work of IDE architecture specific code
*/
#include <asm/irq.h>
#include <asm/mach-types.h>
/*
* Set up a hw structure for a specified data port, control port and IRQ.
* This should follow whatever the default interface uses.
*/
static __inline__ void
ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
{
ide_ioreg_t reg = (ide_ioreg_t) data_port;
int i;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
hw->io_ports[i] = reg;
reg += 1;
}
hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
if (irq)
*irq = 0;
}
/*
* This registers the standard ports for this architecture with the IDE
* driver.
*/
static __inline__ void ide_init_default_hwifs(void)
{
if (machine_is_a5k()) {
hw_regs_t hw;
memset(&hw, 0, sizeof(hw));
ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
hw.irq = IRQ_HARDDISK;
ide_register_hw(&hw);
}
}
/*
* linux/include/asm-arm/arch-arc/io.h
*
* Copyright (C) 1997 Russell King
*
* 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.
*
* Modifications:
* 06-Dec-1997 RMK Created.
*/
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
#define IO_SPACE_LIMIT 0xffffffff
/*
* GCC is totally crap at loading/storing data. We try to persuade it
* to do the right thing by using these whereever possible instead of
* the above.
*/
#define __arch_base_getb(b,o) \
({ \
unsigned int v, r = (b); \
__asm__ __volatile__( \
"ldrb %0, [%1, %2]" \
: "=r" (v) \
: "r" (r), "Ir" (o)); \
v; \
})
#define __arch_base_getl(b,o) \
({ \
unsigned int v, r = (b); \
__asm__ __volatile__( \
"ldr %0, [%1, %2]" \
: "=r" (v) \
: "r" (r), "Ir" (o)); \
v; \
})
#define __arch_base_putb(v,b,o) \
({ \
unsigned int r = (b); \
__asm__ __volatile__( \
"strb %0, [%1, %2]" \
: \
: "r" (v), "r" (r), "Ir" (o)); \
})
#define __arch_base_putl(v,b,o) \
({ \
unsigned int r = (b); \
__asm__ __volatile__( \
"str %0, [%1, %2]" \
: \
: "r" (v), "r" (r), "Ir" (o)); \
})
/*
* We use two different types of addressing - PC style addresses, and ARM
* addresses. PC style accesses the PC hardware with the normal PC IO
* addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+
* and are translated to the start of IO. Note that all addresses are
* shifted left!
*/
#define __PORT_PCIO(x) (!((x) & 0x80000000))
/*
* Dynamic IO functions - let the compiler
* optimize the expressions
*/
static inline void __outb (unsigned int value, unsigned int port)
{
unsigned long temp;
__asm__ __volatile__(
"tst %2, #0x80000000\n\t"
"mov %0, %4\n\t"
"addeq %0, %0, %3\n\t"
"strb %1, [%0, %2, lsl #2] @ outb"
: "=&r" (temp)
: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
: "cc");
}
static inline void __outw (unsigned int value, unsigned int port)
{
unsigned long temp;
__asm__ __volatile__(
"tst %2, #0x80000000\n\t"
"mov %0, %4\n\t"
"addeq %0, %0, %3\n\t"
"str %1, [%0, %2, lsl #2] @ outw"
: "=&r" (temp)
: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
: "cc");
}
static inline void __outl (unsigned int value, unsigned int port)
{
unsigned long temp;
__asm__ __volatile__(
"tst %2, #0x80000000\n\t"
"mov %0, %4\n\t"
"addeq %0, %0, %3\n\t"
"str %1, [%0, %2, lsl #2] @ outl"
: "=&r" (temp)
: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
: "cc");
}
#define DECLARE_DYN_IN(sz,fnsuffix,instr) \
static inline unsigned sz __in##fnsuffix (unsigned int port) \
{ \
unsigned long temp, value; \
__asm__ __volatile__( \
"tst %2, #0x80000000\n\t" \
"mov %0, %4\n\t" \
"addeq %0, %0, %3\n\t" \
"ldr" instr " %1, [%0, %2, lsl #2] @ in" #fnsuffix \
: "=&r" (temp), "=r" (value) \
: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
: "cc"); \
return (unsigned sz)value; \
}
static inline unsigned int __ioaddr (unsigned int port) \
{ \
if (__PORT_PCIO(port)) \
return (unsigned int)(PCIO_BASE + (port << 2)); \
else \
return (unsigned int)(IO_BASE + (port << 2)); \
}
#define DECLARE_IO(sz,fnsuffix,instr) \
DECLARE_DYN_IN(sz,fnsuffix,instr)
DECLARE_IO(char,b,"b")
DECLARE_IO(short,w,"")
DECLARE_IO(int,l,"")
#undef DECLARE_IO
#undef DECLARE_DYN_IN
/*
* Constant address IO functions
*
* These have to be macros for the 'J' constraint to work -
* +/-4096 immediate operand.
*/
#define __outbc(value,port) \
({ \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
"strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
"strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \
})
#define __inbc(port) \
({ \
unsigned char result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
"ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
"ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
#define __outwc(value,port) \
({ \
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
"str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
"str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \
})
#define __inwc(port) \
({ \
unsigned short result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
"ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
"ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result & 0xffff; \
})
#define __outlc(value,port) \
({ \
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
"str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
"str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (IO_BASE), "r" ((port) << 2)); \
})
#define __inlc(port) \
({ \
unsigned long result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
"ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
"ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
#define __ioaddrc(port) \
({ \
unsigned long addr; \
if (__PORT_PCIO((port))) \
addr = PCIO_BASE + ((port) << 2); \
else \
addr = IO_BASE + ((port) << 2); \
addr; \
})
#define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p))
#define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p))
#define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p))
#define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
/* the following macro is deprecated */
#define ioaddr(port) __ioaddr((port))
/*
* No ioremap support here.
*/
#define __arch_ioremap(c,s,f) ((void *)(c))
#define __arch_iounmap(c) do { } while (0)
#endif
/*
* linux/include/asm-arm/arch-arc/irqs.h
*
* Copyright (C) 1996 Russell King, Dave Gilbert
*
* 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.
*
* Modifications:
* 04-04-1998 PJB Merged arc and a5k versions
*/
#include <linux/config.h>
#if defined(CONFIG_ARCH_A5K)
#define IRQ_PRINTER 0
#define IRQ_BATLOW 1
#define IRQ_FLOPPYINDEX 2
#define IRQ_FLOPPYDISK 12
#elif defined(CONFIG_ARCH_ARC)
#define IRQ_PRINTERBUSY 0
#define IRQ_SERIALRING 1
#define IRQ_PRINTERACK 2
#define IRQ_FLOPPYCHANGED 12
#endif
#define IRQ_VSYNCPULSE 3
#define IRQ_POWERON 4
#define IRQ_TIMER0 5
#define IRQ_TIMER1 6
#define IRQ_IMMEDIATE 7
#define IRQ_EXPCARDFIQ 8
#define IRQ_SOUNDCHANGE 9
#define IRQ_SERIALPORT 10
#define IRQ_HARDDISK 11
#define IRQ_EXPANSIONCARD 13
#define IRQ_KEYBOARDTX 14
#define IRQ_KEYBOARDRX 15
#if defined(CONFIG_ARCH_A5K)
#define FIQ_SERIALPORT 4
#elif defined(CONFIG_ARCH_ARC)
#define FIQ_FLOPPYIRQ 1
#define FIQ_FD1772 FIQ_FLOPPYIRQ
#endif
#define FIQ_FLOPPYDATA 0
#define FIQ_ECONET 2
#define FIQ_EXPANSIONCARD 6
#define FIQ_FORCE 7
#define IRQ_TIMER IRQ_TIMER0
/*
* This is the offset of the FIQ "IRQ" numbers
*/
#define FIQ_START 64
#define irq_canonicalize(i) (i)
/*
* linux/include/asm-arm/arch-arc/keyboard.h
*
* Copyright (C) 1998-2001 Russell King
*
* 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.
*
* Keyboard driver definitions for Acorn Archimedes/A5000
* architecture
*/
#include <asm/irq.h>
#define NR_SCANCODES 128
extern void a5kkbd_init_hw(void);
#define kbd_disable_irq() disable_irq(IRQ_KEYBOARDRX)
#define kbd_enable_irq() enable_irq(IRQ_KEYBOARDRX)
#define kbd_init_hw() a5kkbd_init_hw()
/*
* linux/include/asm-arm/arch-arc/memory.h
*
* Copyright (C) 1996-1999 Russell King.
*
* 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.
*
* Changelog:
* 22-Nov-1996 RMK Created
* 21-Mar-1999 RMK Renamed to memory.h
* RMK Moved PAGE_OFFSET and TASK_SIZE here
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
/*
* User space: 26MB
*/
#define TASK_SIZE (0x01a00000UL)
#define TASK_SIZE_26 (0x01a00000UL)
/*
* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
/*
* Page offset: 32MB
*/
#define PAGE_OFFSET (0x02000000UL)
#define PHYS_OFFSET (0x02000000UL)
#define __virt_to_phys__is_a_macro
#define __virt_to_phys(vpage) vpage
#define __phys_to_virt__is_a_macro
#define __phys_to_virt(ppage) ppage
/*
* Virtual view <-> DMA view memory address translations
* virt_to_bus: Used to translate the virtual address to an
* address suitable to be passed to set_dma_addr
* bus_to_virt: Used to convert an address for DMA operations
* to an address that the kernel can use.
*/
#define __virt_to_bus__is_a_macro
#define __virt_to_bus(x) (x)
#define __bus_to_virt__is_a_macro
#define __bus_to_virt(x) (x)
#endif
/*
* linux/include/asm-arm/arch-arc/oldlatches.h
*
* Copyright (C) 1996 Russell King, Dave Gilbert
*
* 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.
*
* Modifications:
* 04-04-1998 PJB/RMK Merged arc and a5k versions
*/
#ifndef _ASM_ARCH_OLDLATCH_H
#define _ASM_ARCH_OLDLATCH_H
#define LATCHA_FDSEL0 (1<<0)
#define LATCHA_FDSEL1 (1<<1)
#define LATCHA_FDSEL2 (1<<2)
#define LATCHA_FDSEL3 (1<<3)
#define LATCHA_FDSELALL (0xf)
#define LATCHA_SIDESEL (1<<4)
#define LATCHA_MOTOR (1<<5)
#define LATCHA_INUSE (1<<6)
#define LATCHA_CHANGERST (1<<7)
#define LATCHB_FDCDENSITY (1<<1)
#define LATCHB_FDCRESET (1<<3)
#define LATCHB_PRINTSTROBE (1<<4)
/* newval=(oldval & mask)|newdata */
void oldlatch_bupdate(unsigned char mask,unsigned char newdata);
/* newval=(oldval & mask)|newdata */
void oldlatch_aupdate(unsigned char mask,unsigned char newdata);
#endif
/*
* linux/include/asm-arm/arch-arc/param.h
*/
/*
* linux/include/asm-arm/arch-arc/serial.h
*
* Copyright (C) 1996 Russell King.
*
* 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.
*
* Changelog:
* 15-10-1996 RMK Created
* 04-04-1998 PJB Merged `arc' and `a5k' architectures
*/
#ifndef __ASM_ARCH_SERIAL_H
#define __ASM_ARCH_SERIAL_H
#include <linux/config.h>
/*
* This assumes you have a 1.8432 MHz clock for your UART.
*
* It'd be nice if someone built a serial card with a 24.576 MHz
* clock, since the 16550A is capable of handling a top speed of 1.5
* megabits/second; but this requires the faster clock.
*/
#define BASE_BAUD (1843200 / 16)
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
#define RS_TABLE_SIZE 16
#if defined(CONFIG_ARCH_A5K)
/* UART CLK PORT IRQ FLAGS */
#define STD_SERIAL_PORT_DEFNS \
{ 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \
{ 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */
#else
#define STD_SERIAL_PORT_DEFNS \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS0 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS1 */
#endif
#define EXTRA_SERIAL_PORT_DEFNS \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */
#endif
/*
* linux/include/asm-arm/arch-arc/system.h
*
* Copyright (C) 1996-1999 Russell King and Dave Gilbert
*
* 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.
*/
static inline void arch_idle(void)
{
}
static inline void arch_reset(char mode)
{
/*
* copy branch instruction to reset location and call it
*/
*(unsigned long *)0 = *(unsigned long *)0x03800000;
((void(*)(void))0)();
}
/*
* linux/include/asm-arm/arch-arc/time.h
*
* Copyright (C) 1996-2000 Russell King.
*
* 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.
*
* Changelog:
* 24-Sep-1996 RMK Created
* 10-Oct-1996 RMK Brought up to date with arch-sa110eval
* 04-Dec-1997 RMK Updated for new arch/arm/time.c
*/
extern void ioctime_init(void);
static irqreturn_t
timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
do_timer(regs);
do_set_rtc();
do_profile(regs);
return IRQ_HANDLED;
}
/*
* Set up timer interrupt.
*/
void __init time_init(void)
{
ioctime_init();
timer_irq.handler = timer_interrupt;
setup_irq(IRQ_TIMER, &timer_irq);
}
/*
* linux/include/asm-arm/arch-arc/timex.h
*
* Copyright (C) 1997, 1998 Russell King
*
* 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.
*
* Acorn Archimedes/A5000 architecture timex specifications
*/
/*
* On the RiscPC, the clock ticks at 2MHz.
*/
#define CLOCK_TICK_RATE 2000000
/*
* linux/include/asm-arm/arch-arc/uncompress.h
*
* Copyright (C) 1996 Russell King
*
* 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.
*/
#define VIDMEM ((char *)0x02000000)
int video_num_columns, video_num_lines, video_size_row;
int white, bytes_per_char_h;
extern unsigned long con_charconvtable[256];
struct param_struct {
unsigned long page_size;
unsigned long nr_pages;
unsigned long ramdisk_size;
unsigned long mountrootrdonly;
unsigned long rootdev;
unsigned long video_num_cols;
unsigned long video_num_rows;
unsigned long video_x;
unsigned long video_y;
unsigned long memc_control_reg;
unsigned char sounddefault;
unsigned char adfsdrives;
unsigned char bytes_per_char_h;
unsigned char bytes_per_char_v;
unsigned long unused[256/4-11];
};
static struct param_struct *params = (struct param_struct *)0x0207c000;
/*
* This does not append a newline
*/
static void puts(const char *s)
{
extern void ll_write_char(char *, unsigned long);
int x,y;
unsigned char c;
char *ptr;
x = params->video_x;
y = params->video_y;
while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
if ( c == '\n' ) {
x = 0;
if ( ++y >= video_num_lines ) {
y--;
}
} else {
ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
ll_write_char(ptr, c|(white<<16));
if ( ++x >= video_num_columns ) {
x = 0;
if ( ++y >= video_num_lines ) {
y--;
}
}
}
}
params->video_x = x;
params->video_y = y;
}
static void error(char *x);
/*
* Setup for decompression
*/
static void arch_decomp_setup(void)
{
int i;
video_num_lines = params->video_num_rows;
video_num_columns = params->video_num_cols;
bytes_per_char_h = params->bytes_per_char_h;
video_size_row = video_num_columns * bytes_per_char_h;
if (bytes_per_char_h == 4)
for (i = 0; i < 256; i++)
con_charconvtable[i] =
(i & 128 ? 1 << 0 : 0) |
(i & 64 ? 1 << 4 : 0) |
(i & 32 ? 1 << 8 : 0) |
(i & 16 ? 1 << 12 : 0) |
(i & 8 ? 1 << 16 : 0) |
(i & 4 ? 1 << 20 : 0) |
(i & 2 ? 1 << 24 : 0) |
(i & 1 ? 1 << 28 : 0);
else
for (i = 0; i < 16; i++)
con_charconvtable[i] =
(i & 8 ? 1 << 0 : 0) |
(i & 4 ? 1 << 8 : 0) |
(i & 2 ? 1 << 16 : 0) |
(i & 1 ? 1 << 24 : 0);
white = bytes_per_char_h == 8 ? 0xfc : 7;
if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n");
}
/*
* nothing to do
*/
#define arch_decomp_wdog()
#include <asm-generic/sections.h>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment