Commit c662921a authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 007427b9 bf3abfa9
This diff is collapsed.
This diff is collapsed.
...@@ -286,3 +286,5 @@ EXPORT_SYMBOL(set_dma_page); ...@@ -286,3 +286,5 @@ EXPORT_SYMBOL(set_dma_page);
EXPORT_SYMBOL(get_dma_residue); EXPORT_SYMBOL(get_dma_residue);
EXPORT_SYMBOL(set_dma_sg); EXPORT_SYMBOL(set_dma_sg);
EXPORT_SYMBOL(set_dma_speed); EXPORT_SYMBOL(set_dma_speed);
EXPORT_SYMBOL(dma_spin_lock);
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/config.h> #include <linux/config.h>
#include "entry-header.S" #include "entry-header.S"
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/glue.h>
#ifdef IOC_BASE #ifdef IOC_BASE
...@@ -681,12 +682,12 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE ...@@ -681,12 +682,12 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE
/* /*
* This routine must not corrupt r9 * This routine must not corrupt r9
*/ */
#ifdef MULTI_CPU #ifdef MULTI_ABORT
ldr r4, .LCprocfns @ pass r0, r3 to ldr r4, .LCprocfns @ pass r0, r3 to
mov lr, pc @ processor code mov lr, pc @ processor code
ldr pc, [r4] @ call processor specific code ldr pc, [r4] @ call processor specific code
#else #else
bl cpu_data_abort bl CPU_ABORT_HANDLER
#endif #endif
msr cpsr_c, r9 msr cpsr_c, r9
mov r2, sp mov r2, sp
...@@ -799,7 +800,7 @@ __pabt_svc: sub sp, sp, #S_FRAME_SIZE ...@@ -799,7 +800,7 @@ __pabt_svc: sub sp, sp, #S_FRAME_SIZE
.LCirq: .word __temp_irq .LCirq: .word __temp_irq
.LCund: .word __temp_und .LCund: .word __temp_und
.LCabt: .word __temp_abt .LCabt: .word __temp_abt
#ifdef MULTI_CPU #ifdef MULTI_ABORT
.LCprocfns: .word SYMBOL_NAME(processor) .LCprocfns: .word SYMBOL_NAME(processor)
#endif #endif
.LCfp: .word SYMBOL_NAME(fp_enter) .LCfp: .word SYMBOL_NAME(fp_enter)
...@@ -823,12 +824,12 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go ...@@ -823,12 +824,12 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
alignment_trap r7, r7, __temp_abt alignment_trap r7, r7, __temp_abt
zero_fp zero_fp
mov r0, r2 @ remove once everyones in sync mov r0, r2 @ remove once everyones in sync
#ifdef MULTI_CPU #ifdef MULTI_ABORT
ldr r4, .LCprocfns @ pass r0, r3 to ldr r4, .LCprocfns @ pass r0, r3 to
mov lr, pc @ processor code mov lr, pc @ processor code
ldr pc, [r4] @ call processor specific code ldr pc, [r4] @ call processor specific code
#else #else
bl cpu_data_abort bl CPU_ABORT_HANDLER
#endif #endif
set_cpsr_c r2, #MODE_SVC @ Enable interrupts set_cpsr_c r2, #MODE_SVC @ Enable interrupts
mov r2, sp mov r2, sp
......
...@@ -76,6 +76,9 @@ struct processor processor; ...@@ -76,6 +76,9 @@ struct processor processor;
#ifdef MULTI_TLB #ifdef MULTI_TLB
struct cpu_tlb_fns cpu_tlb; struct cpu_tlb_fns cpu_tlb;
#endif #endif
#ifdef MULTI_USER
struct cpu_user_fns cpu_user;
#endif
unsigned char aux_device_present; unsigned char aux_device_present;
char elf_platform[ELF_PLATFORM_SIZE]; char elf_platform[ELF_PLATFORM_SIZE];
...@@ -248,6 +251,9 @@ static void __init setup_processor(void) ...@@ -248,6 +251,9 @@ static void __init setup_processor(void)
#ifdef MULTI_TLB #ifdef MULTI_TLB
cpu_tlb = *list->tlb; cpu_tlb = *list->tlb;
#endif #endif
#ifdef MULTI_USER
cpu_user = *list->user;
#endif
printk("Processor: %s %s revision %d\n", printk("Processor: %s %s revision %d\n",
proc_info.manufacturer, proc_info.cpu_name, proc_info.manufacturer, proc_info.cpu_name,
......
...@@ -113,7 +113,6 @@ static int __init integrator_map_irq(struct pci_dev *dev, u8 slot, u8 pin) ...@@ -113,7 +113,6 @@ static int __init integrator_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
extern void pci_v3_init(void *); extern void pci_v3_init(void *);
struct hw_pci integrator_pci __initdata = { struct hw_pci integrator_pci __initdata = {
mem_offset: 0x40000000,
swizzle: integrator_swizzle, swizzle: integrator_swizzle,
map_irq: integrator_map_irq, map_irq: integrator_map_irq,
setup: pci_v3_setup, setup: pci_v3_setup,
......
...@@ -435,7 +435,7 @@ static int __init pci_v3_setup_resources(struct resource **resource) ...@@ -435,7 +435,7 @@ static int __init pci_v3_setup_resources(struct resource **resource)
resource[1] = &non_mem; resource[1] = &non_mem;
resource[2] = &pre_mem; resource[2] = &pre_mem;
return 0; return 1;
} }
/* /*
...@@ -529,8 +529,10 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys) ...@@ -529,8 +529,10 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
{ {
int ret = 0; int ret = 0;
if (nr == 0) if (nr == 0) {
sys->mem_offset = 0x40000000;
ret = pci_v3_setup_resources(sys->resource); ret = pci_v3_setup_resources(sys->resource);
}
return ret; return ret;
} }
...@@ -634,7 +636,6 @@ void __init pci_v3_preinit(void) ...@@ -634,7 +636,6 @@ void __init pci_v3_preinit(void)
void __init pci_v3_postinit(void) void __init pci_v3_postinit(void)
{ {
unsigned int pci_cmd; unsigned int pci_cmd;
int ret;
pci_cmd = PCI_COMMAND_MEMORY | pci_cmd = PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
......
...@@ -47,23 +47,44 @@ static u_long iq80310_read_timer (void) ...@@ -47,23 +47,44 @@ static u_long iq80310_read_timer (void)
u_long b0, b1, b2, b3, val; u_long b0, b1, b2, b3, val;
b0 = *la0; b1 = *la1; b2 = *la2; b3 = *la3; b0 = *la0; b1 = *la1; b2 = *la2; b3 = *la3;
b0 = (((b0 & 0x20) >> 1) | (b0 & 0x1f)); b0 = (((b0 & 0x40) >> 1) | (b0 & 0x1f));
b1 = (((b1 & 0x20) >> 1) | (b1 & 0x1f)); b1 = (((b1 & 0x40) >> 1) | (b1 & 0x1f));
b2 = (((b2 & 0x20) >> 1) | (b2 & 0x1f)); b2 = (((b2 & 0x40) >> 1) | (b2 & 0x1f));
b3 = (b3 & 0x0f); b3 = (b3 & 0x0f);
val = ((b0 << 0) | (b1 << 6) | (b2 << 12) | (b3 << 18)); val = ((b0 << 0) | (b1 << 6) | (b2 << 12) | (b3 << 18));
return val; return val;
} }
/* IRQs are disabled before entering here from do_gettimeofday() */ /*
* IRQs are disabled before entering here from do_gettimeofday().
* Note that the counter may wrap. When it does, 'elapsed' will
* be small, but we will have a pending interrupt.
*/
static unsigned long iq80310_gettimeoffset (void) static unsigned long iq80310_gettimeoffset (void)
{ {
unsigned long elapsed, usec; unsigned long elapsed, usec, tmp1;
unsigned int stat1, stat2;
/* We need elapsed timer ticks since last interrupt */ stat1 = *(volatile u8 *)IQ80310_INT_STAT;
elapsed = iq80310_read_timer(); elapsed = iq80310_read_timer();
stat2 = *(volatile u8 *)IQ80310_INT_STAT;
/*
* If an interrupt was pending before we read the timer,
* we've already wrapped. Factor this into the time.
* If an interrupt was pending after we read the timer,
* it may have wrapped between checking the interrupt
* status and reading the timer. Re-read the timer to
* be sure its value is after the wrap.
*/
if (stat1 & 1)
elapsed += LATCH;
else if (stat2 & 1)
elapsed = LATCH + iq80310_read_timer();
/* Now convert them to usec */ /*
* Now convert them to usec.
*/
usec = (unsigned long)(elapsed*tick)/LATCH; usec = (unsigned long)(elapsed*tick)/LATCH;
return usec; return usec;
...@@ -92,9 +113,7 @@ static void iq80310_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -92,9 +113,7 @@ static void iq80310_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* *
* -DS * -DS
*/ */
irq_exit(smp_processor_id(), irq);
do_timer(regs); do_timer(regs);
irq_enter(smp_processor_id(), irq);
} }
extern unsigned long (*gettimeoffset)(void); extern unsigned long (*gettimeoffset)(void);
...@@ -116,4 +135,3 @@ void __init time_init(void) ...@@ -116,4 +135,3 @@ void __init time_init(void)
*timer_en |= 2; *timer_en |= 2;
*timer_en |= 1; *timer_en |= 1;
} }
...@@ -14,69 +14,105 @@ obj-y := generic.o irq.o dma.o ...@@ -14,69 +14,105 @@ obj-y := generic.o irq.o dma.o
obj-m := obj-m :=
obj-n := obj-n :=
obj- := obj- :=
led-y := leds.o
export-objs := assabet.o dma.o flexanet.o freebird.o generic.o h3600.o \ export-objs := dma.o generic.o irq.o pcipool.o sa1111.o sa1111-pcibuf.o \
huw_webpanel.o irq.o pcipool.o sa1111.o sa1111-pcibuf.o \ usb_ctl.o usb_recv.o usb_send.o pm.o
yopy.o usb_ctl.o usb_recv.o usb_send.o
# This needs to be cleaned up. We probably need to have SA1100 # This needs to be cleaned up. We probably need to have SA1100
# and SA1110 config symbols. # and SA1110 config symbols.
# #
# We link the CPU support next, so that RAM timings can be tuned. # We link the CPU support next, so that RAM timings can be tuned.
ifeq ($(CONFIG_CPU_FREQ),y) ifeq ($(CONFIG_CPU_FREQ),y)
obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o
obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o
endif endif
# Next, the SA1111 stuff. # Next, the SA1111 stuff.
obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_SA1111) += sa1111.o
obj-$(CONFIG_USB_OHCI_SA1111) += sa1111-pcibuf.o pcipool.o obj-$(CONFIG_USB_OHCI_SA1111) += sa1111-pcibuf.o pcipool.o
# Specific board support # Specific board support
obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o
obj-$(CONFIG_SA1100_ASSABET) += assabet.o led-$(CONFIG_SA1100_ADSBITSY) += leds-adsbitsy.o
obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o
obj-$(CONFIG_SA1100_BRUTUS) += brutus.o obj-$(CONFIG_SA1100_ASSABET) += assabet.o
obj-$(CONFIG_SA1100_CERF) += cerf.o export-objs += assabet.o
obj-$(CONFIG_SA1100_EMPEG) += empeg.o led-$(CONFIG_SA1100_ASSABET) += leds-assabet.o
obj-$(CONFIG_SA1100_FLEXANET) += flexanet.o obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o
obj-$(CONFIG_SA1100_FREEBIRD) += freebird.o
obj-$(CONFIG_SA1100_GRAPHICSCLIENT) += graphicsclient.o obj-$(CONFIG_SA1100_BADGE4) += badge4.o
obj-$(CONFIG_SA1100_GRAPHICSMASTER) += graphicsmaster.o export-objs += badge4.o
obj-$(CONFIG_SA1100_H3600) += h3600.o
obj-$(CONFIG_SA1100_HUW_WEBPANEL) += huw_webpanel.o obj-$(CONFIG_SA1100_BRUTUS) += brutus.o
obj-$(CONFIG_SA1100_ITSY) += itsy.o led-$(CONFIG_SA1100_BRUTUS) += leds-brutus.o
obj-$(CONFIG_SA1100_JORNADA720) += jornada720.o
obj-$(CONFIG_SA1100_LART) += lart.o obj-$(CONFIG_SA1100_CERF) += cerf.o
obj-$(CONFIG_SA1100_NANOENGINE) += nanoengine.o led-$(CONFIG_SA1100_CERF) += leds-cerf.o
obj-$(CONFIG_SA1100_OMNIMETER) += omnimeter.o
obj-$(CONFIG_SA1100_PANGOLIN) += pangolin.o obj-$(CONFIG_SA1100_EMPEG) += empeg.o
obj-$(CONFIG_SA1100_PFS168) += pfs168.o
obj-$(CONFIG_SA1100_PLEB) += pleb.o obj-$(CONFIG_SA1100_FLEXANET) += flexanet.o
obj-$(CONFIG_SA1100_SHANNON) += shannon.o export-objs += flexanet.o
obj-$(CONFIG_SA1100_SHERMAN) += sherman.o led-$(CONFIG_SA1100_FLEXANET) += leds-flexanet.o
obj-$(CONFIG_SA1100_PT_SYSTEM3) += system3.o
obj-$(CONFIG_SA1100_SIMPAD) += simpad.o obj-$(CONFIG_SA1100_FREEBIRD) += freebird.o
obj-$(CONFIG_SA1100_VICTOR) += victor.o export-objs += freebird.o
obj-$(CONFIG_SA1100_XP860) += xp860.o
obj-$(CONFIG_SA1100_YOPY) += yopy.o obj-$(CONFIG_SA1100_GRAPHICSCLIENT) += graphicsclient.o
led-$(CONFIG_SA1100_GRAPHICSCLIENT) += leds-graphicsclient.o
obj-$(CONFIG_SA1100_GRAPHICSMASTER) += graphicsmaster.o
led-$(CONFIG_SA1100_GRAPHICSMASTER) += leds-graphicsmaster.o
obj-$(CONFIG_SA1100_H3600) += h3600.o
export-objs += h3600.o
obj-$(CONFIG_SA1100_HUW_WEBPANEL) += huw_webpanel.o
export-objs += huw_webpanel.o
obj-$(CONFIG_SA1100_ITSY) += itsy.o
obj-$(CONFIG_SA1100_JORNADA720) += jornada720.o
obj-$(CONFIG_SA1100_LART) += lart.o
led-$(CONFIG_SA1100_LART) += leds-lart.o
obj-$(CONFIG_SA1100_NANOENGINE) += nanoengine.o
obj-$(CONFIG_SA1100_OMNIMETER) += omnimeter.o
obj-$(CONFIG_SA1100_PANGOLIN) += pangolin.o
obj-$(CONFIG_SA1100_PFS168) += pfs168.o
led-$(CONFIG_SA1100_PFS168) += leds-pfs168.o
obj-$(CONFIG_SA1100_PLEB) += pleb.o
obj-$(CONFIG_SA1100_PT_SYSTEM3) += system3.o
led-$(CONFIG_SA1100_PT_SYSTEM3) += leds-system3.o
obj-$(CONFIG_SA1100_SHANNON) += shannon.o
obj-$(CONFIG_SA1100_SHERMAN) += sherman.o
obj-$(CONFIG_SA1100_SIMPAD) += simpad.o
led-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o
obj-$(CONFIG_SA1100_STORK) += stork.o
export-objs += stork.o
obj-$(CONFIG_SA1100_VICTOR) += victor.o
obj-$(CONFIG_SA1100_XP860) += xp860.o
obj-$(CONFIG_SA1100_YOPY) += yopy.o
export-objs += yopy.o
# LEDs support # LEDs support
leds-y := leds.o obj-$(CONFIG_LEDS) += $(led-y)
leds-$(CONFIG_SA1100_ADSBITSY) += leds-adsbitsy.o
leds-$(CONFIG_SA1100_ASSABET) += leds-assabet.o
leds-$(CONFIG_SA1100_BRUTUS) += leds-brutus.o
leds-$(CONFIG_SA1100_CERF) += leds-cerf.o
leds-$(CONFIG_SA1100_FLEXANET) += leds-flexanet.o
leds-$(CONFIG_SA1100_GRAPHICSCLIENT) += leds-graphicsclient.o
leds-$(CONFIG_SA1100_GRAPHICSMASTER) += leds-graphicsmaster.o
leds-$(CONFIG_SA1100_LART) += leds-lart.o
leds-$(CONFIG_SA1100_PFS168) += leds-pfs168.o
leds-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o
leds-$(CONFIG_SA1100_PT_SYSTEM3) += leds-system3.o
obj-$(CONFIG_LEDS) += $(leds-y)
# SA1110 USB client support # SA1110 USB client support
list-multi += sa1100usb_core.o list-multi += sa1100usb_core.o
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (C) 2001 Russell King * Copyright (C) 2001 Russell King
* *
* $Id: cpu-sa1110.c,v 1.6 2001/10/22 11:53:47 rmk Exp $ * $Id: cpu-sa1110.c,v 1.8 2002/01/09 17:13:27 rmk Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -69,13 +69,23 @@ static struct sdram_params tc59sm716_cl3_params __initdata = { ...@@ -69,13 +69,23 @@ static struct sdram_params tc59sm716_cl3_params __initdata = {
}; };
static struct sdram_params samsung_k4s641632d_tc75 __initdata = { static struct sdram_params samsung_k4s641632d_tc75 __initdata = {
rows: 14, rows: 14,
tck: 9, tck: 9,
trcd: 27, trcd: 27,
trp: 20, trp: 20,
twr: 9, twr: 9,
refresh: 64000, refresh: 64000,
cas_latency: 3, cas_latency: 3,
};
static struct sdram_params samsung_km416s4030ct __initdata = {
rows: 13,
tck: 8,
trcd: 24, /* 3 CLKs */
trp: 24, /* 3 CLKs */
twr: 16, /* Trdl: 2 CLKs */
refresh: 64000,
cas_latency: 3,
}; };
static struct sdram_params sdram_params; static struct sdram_params sdram_params;
...@@ -273,6 +283,8 @@ static int __init sa1110_clk_init(void) ...@@ -273,6 +283,8 @@ static int __init sa1110_clk_init(void)
if (machine_is_pt_system3()) if (machine_is_pt_system3())
sdram = &samsung_k4s641632d_tc75; sdram = &samsung_k4s641632d_tc75;
if (machine_is_h3100())
sdram = &samsung_km416s4030ct;
if (sdram) { if (sdram) {
printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d" printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
* in the platform specific files. * in the platform specific files.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/cpufreq.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/memory.h> #include <asm/memory.h>
...@@ -210,3 +212,5 @@ static int __init pm_init(void) ...@@ -210,3 +212,5 @@ static int __init pm_init(void)
__initcall(pm_init); __initcall(pm_init);
#endif #endif
EXPORT_SYMBOL(pm_do_suspend);
...@@ -99,10 +99,9 @@ extern void convert_to_tag_list(struct param_struct *params, int mem_init); ...@@ -99,10 +99,9 @@ extern void convert_to_tag_list(struct param_struct *params, int mem_init);
*/ */
static struct map_desc system3_io_desc[] __initdata = { static struct map_desc system3_io_desc[] __initdata = {
/* virtual physical length domain r w c b */ /* virtual physical length domain r w c b */
{ 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */ { 0xf3000000, PT_CPLD_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
{ 0xf3000000, PT_CPLD_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */ { 0xf4000000, PT_SA1111_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
{ 0xf4000000, PT_SA1111_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC LAST_DESC
}; };
......
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
/* /*
* Function: armv4_early_abort * Function: v4_early_abort
* *
* Params : r2 = address of aborted instruction * Params : r2 = address of aborted instruction
* : r3 = saved SPSR * : r3 = saved SPSR
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* picture. Unfortunately, this does happen. We live with it. * picture. Unfortunately, this does happen. We live with it.
*/ */
.align 5 .align 5
ENTRY(armv4_early_abort) ENTRY(v4_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r0, c6, c0, 0 @ get FAR
ldr r3, [r2] @ read aborted ARM instruction ldr r3, [r2] @ read aborted ARM instruction
......
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
/* /*
* Function: armv4t_early_abort * Function: v4t_early_abort
* *
* Params : r2 = address of aborted instruction * Params : r2 = address of aborted instruction
* : r3 = saved SPSR * : r3 = saved SPSR
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* picture. Unfortunately, this does happen. We live with it. * picture. Unfortunately, this does happen. We live with it.
*/ */
.align 5 .align 5
ENTRY(armv4t_early_abort) ENTRY(v4t_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r0, c6, c0, 0 @ get FAR
tst r3, #PSR_T_BIT tst r3, #PSR_T_BIT
......
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
/* /*
* Function: armv5ej_early_abort * Function: v5ej_early_abort
* *
* Params : r2 = address of aborted instruction * Params : r2 = address of aborted instruction
* : r3 = saved SPSR * : r3 = saved SPSR
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* picture. Unfortunately, this does happen. We live with it. * picture. Unfortunately, this does happen. We live with it.
*/ */
.align 5 .align 5
ENTRY(armv5ej_early_abort) ENTRY(v5ej_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r0, c6, c0, 0 @ get FAR
tst r3, #PSR_J_BIT tst r3, #PSR_J_BIT
......
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
/* /*
* Function: armv4t_late_abort * Function: v4t_late_abort
* *
* Params : r2 = address of aborted instruction * Params : r2 = address of aborted instruction
* : r3 = saved SPSR * : r3 = saved SPSR
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* abort here if the I-TLB and D-TLB aren't seeing the same * abort here if the I-TLB and D-TLB aren't seeing the same
* picture. Unfortunately, this does happen. We live with it. * picture. Unfortunately, this does happen. We live with it.
*/ */
ENTRY(armv4t_late_abort) ENTRY(v4t_late_abort)
tst r3, #PSR_T_BIT @ check for thumb mode tst r3, #PSR_T_BIT @ check for thumb mode
mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r0, c6, c0, 0 @ get FAR
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* *
* FIXME: do we need to handle cache stuff... * FIXME: do we need to handle cache stuff...
*/ */
ENTRY(armv3_copy_user_page) ENTRY(v3_copy_user_page)
stmfd sp!, {r4, lr} @ 2 stmfd sp!, {r4, lr} @ 2
mov r2, #PAGE_SZ/64 @ 1 mov r2, #PAGE_SZ/64 @ 1
ldmia r1!, {r3, r4, ip, lr} @ 4+1 ldmia r1!, {r3, r4, ip, lr} @ 4+1
...@@ -42,7 +42,7 @@ ENTRY(armv3_copy_user_page) ...@@ -42,7 +42,7 @@ ENTRY(armv3_copy_user_page)
* *
* FIXME: do we need to handle cache stuff... * FIXME: do we need to handle cache stuff...
*/ */
ENTRY(armv3_clear_user_page) ENTRY(v3_clear_user_page)
str lr, [sp, #-4]! str lr, [sp, #-4]!
mov r1, #PAGE_SZ/64 @ 1 mov r1, #PAGE_SZ/64 @ 1
mov r2, #0 @ 1 mov r2, #0 @ 1
...@@ -57,3 +57,8 @@ ENTRY(armv3_clear_user_page) ...@@ -57,3 +57,8 @@ ENTRY(armv3_clear_user_page)
bne 1b @ 1 bne 1b @ 1
ldr pc, [sp], #4 ldr pc, [sp], #4
.section ".text.init", #alloc, #execinstr
ENTRY(v3_user_fns)
.long v3_clear_user_page
.long v3_copy_user_page
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* instruction. If your processor does not supply this, you have to write your * instruction. If your processor does not supply this, you have to write your
* own copy_user_page that does the right thing. * own copy_user_page that does the right thing.
*/ */
ENTRY(armv4_copy_user_page) ENTRY(v4_copy_user_page)
stmfd sp!, {r4, lr} @ 2 stmfd sp!, {r4, lr} @ 2
mov r2, #PAGE_SZ/64 @ 1 mov r2, #PAGE_SZ/64 @ 1
ldmia r1!, {r3, r4, ip, lr} @ 4 ldmia r1!, {r3, r4, ip, lr} @ 4
...@@ -51,7 +51,7 @@ ENTRY(armv4_copy_user_page) ...@@ -51,7 +51,7 @@ ENTRY(armv4_copy_user_page)
* *
* Same story as above. * Same story as above.
*/ */
ENTRY(armv4_clear_user_page) ENTRY(v4_clear_user_page)
str lr, [sp, #-4]! str lr, [sp, #-4]!
mov r1, #PAGE_SZ/64 @ 1 mov r1, #PAGE_SZ/64 @ 1
mov r2, #0 @ 1 mov r2, #0 @ 1
...@@ -68,3 +68,10 @@ ENTRY(armv4_clear_user_page) ...@@ -68,3 +68,10 @@ ENTRY(armv4_clear_user_page)
bne 1b @ 1 bne 1b @ 1
mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB
ldr pc, [sp], #4 ldr pc, [sp], #4
.section ".text.init", #alloc, #execinstr
ENTRY(v4_user_fns)
.long v4_clear_user_page
.long v4_copy_user_page
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* instruction. If your processor does not supply this, you have to write your * instruction. If your processor does not supply this, you have to write your
* own copy_user_page that does the right thing. * own copy_user_page that does the right thing.
*/ */
ENTRY(armv4_mc_copy_user_page) ENTRY(v4_mc_copy_user_page)
stmfd sp!, {r4, lr} @ 2 stmfd sp!, {r4, lr} @ 2
mov r4, r0 mov r4, r0
mov r0, r1 mov r0, r1
...@@ -53,7 +53,7 @@ ENTRY(armv4_mc_copy_user_page) ...@@ -53,7 +53,7 @@ ENTRY(armv4_mc_copy_user_page)
* *
* Same story as above. * Same story as above.
*/ */
ENTRY(armv4_mc_clear_user_page) ENTRY(v4_mc_clear_user_page)
str lr, [sp, #-4]! str lr, [sp, #-4]!
mov r1, #PAGE_SZ/64 @ 1 mov r1, #PAGE_SZ/64 @ 1
mov r2, #0 @ 1 mov r2, #0 @ 1
...@@ -69,3 +69,10 @@ ENTRY(armv4_mc_clear_user_page) ...@@ -69,3 +69,10 @@ ENTRY(armv4_mc_clear_user_page)
subs r1, r1, #1 @ 1 subs r1, r1, #1 @ 1
bne 1b @ 1 bne 1b @ 1
ldr pc, [sp], #4 ldr pc, [sp], #4
.section ".text.init", #alloc, #execinstr
ENTRY(v4_mc_user_fns)
.long v4_mc_clear_user_page
.long v4_mc_copy_user_page
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* page. We rely on the mini-cache being smaller than one page, so we'll * page. We rely on the mini-cache being smaller than one page, so we'll
* cycle through the complete cache anyway. * cycle through the complete cache anyway.
*/ */
ENTRY(armv5te_copy_user_page) ENTRY(v5te_mc_copy_user_page)
stmfd sp!, {r4, r5, lr} stmfd sp!, {r4, r5, lr}
mov r5, r0 mov r5, r0
mov r0, r1 mov r0, r1
...@@ -62,7 +62,7 @@ ENTRY(armv5te_copy_user_page) ...@@ -62,7 +62,7 @@ ENTRY(armv5te_copy_user_page)
* r0 = destination * r0 = destination
* r1 = virtual user address of ultimate destination page * r1 = virtual user address of ultimate destination page
*/ */
ENTRY(armv5te_clear_user_page) ENTRY(v5te_mc_clear_user_page)
str lr, [sp, #-4]! str lr, [sp, #-4]!
mov r1, #PAGE_SZ/32 mov r1, #PAGE_SZ/32
mov r2, #0 mov r2, #0
...@@ -77,3 +77,9 @@ ENTRY(armv5te_clear_user_page) ...@@ -77,3 +77,9 @@ ENTRY(armv5te_clear_user_page)
subs r1, r1, #1 subs r1, r1, #1
bne 1b bne 1b
ldr pc, [sp], #4 ldr pc, [sp], #4
.section ".text.init", #alloc, #execinstr
ENTRY(v5te_mc_user_fns)
.long v5te_mc_clear_user_page
.long v5te_mc_copy_user_page
...@@ -181,7 +181,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address) ...@@ -181,7 +181,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
static void static void
make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page) make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page)
{ {
struct vm_area_struct *mpnt; struct list_head *l;
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT; unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
int aliases = 0; int aliases = 0;
...@@ -191,10 +191,12 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page) ...@@ -191,10 +191,12 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page)
* space, then we need to handle them specially to maintain * space, then we need to handle them specially to maintain
* cache coherency. * cache coherency.
*/ */
for (mpnt = page->mapping->i_mmap_shared; mpnt; list_for_each(l, &page->mapping->i_mmap_shared) {
mpnt = mpnt->vm_next_share) { struct vm_area_struct *mpnt;
unsigned long off; unsigned long off;
mpnt = list_entry(l, struct vm_area_struct, shared);
/* /*
* If this VMA is not in our MM, we can ignore it. * If this VMA is not in our MM, we can ignore it.
* Note that we intentionally don't mask out the VMA * Note that we intentionally don't mask out the VMA
......
/* /*
* linux/arch/arm/mm/init.c * linux/arch/arm/mm/init.c
* *
* Copyright (C) 1995-2000 Russell King * Copyright (C) 1995-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#define TABLE_OFFSET 0 #define TABLE_OFFSET 0
#endif #endif
#define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *)) #define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(pte_t))
static unsigned long totalram_pages; static unsigned long totalram_pages;
extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
...@@ -319,7 +319,7 @@ static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot ...@@ -319,7 +319,7 @@ static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot
* and can only be in node 0. * and can only be in node 0.
*/ */
reserve_bootmem_node(pgdat, __pa(swapper_pg_dir), reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
PTRS_PER_PGD * sizeof(void *)); PTRS_PER_PGD * sizeof(pgd_t));
#endif #endif
/* /*
* And don't forget to reserve the allocator bitmap, * And don't forget to reserve the allocator bitmap,
......
/* /*
* linux/arch/arm/mm/mm-armv.c * linux/arch/arm/mm/mm-armv.c
* *
* Copyright (C) 1998-2000 Russell King * Copyright (C) 1998-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -82,9 +82,6 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) ...@@ -82,9 +82,6 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
init_pgd = pgd_offset_k(0); init_pgd = pgd_offset_k(0);
if (vectors_base() == 0) { if (vectors_base() == 0) {
init_pmd = pmd_offset(init_pgd, 0);
init_pte = pte_offset(init_pmd, 0);
/* /*
* This lock is here just to satisfy pmd_alloc and pte_lock * This lock is here just to satisfy pmd_alloc and pte_lock
*/ */
...@@ -172,11 +169,14 @@ void free_pgd_slow(pgd_t *pgd) ...@@ -172,11 +169,14 @@ void free_pgd_slow(pgd_t *pgd)
static inline void static inline void
alloc_init_section(unsigned long virt, unsigned long phys, int prot) alloc_init_section(unsigned long virt, unsigned long phys, int prot)
{ {
pmd_t pmd; pmd_t *pmdp, pmd;
pmd_val(pmd) = phys | prot; pmdp = pmd_offset(pgd_offset_k(virt), virt);
if (virt & (1 << PMD_SHIFT))
pmdp++;
set_pmd(pmd_offset(pgd_offset_k(virt), virt), pmd); pmd_val(pmd) = phys | prot;
set_pmd(pmdp, pmd);
} }
/* /*
...@@ -189,18 +189,19 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot) ...@@ -189,18 +189,19 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot)
static inline void static inline void
alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot) alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot)
{ {
pmd_t *pmdp; pmd_t *pmdp, pmd;
pte_t *ptep; pte_t *ptep;
pmdp = pmd_offset(pgd_offset_k(virt), virt); pmdp = pmd_offset(pgd_offset_k(virt), virt);
if (pmd_none(*pmdp)) { if (pmd_none(*pmdp)) {
pte_t *ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
sizeof(pte_t)); sizeof(pte_t));
ptep += PTRS_PER_PTE; pmd_val(pmd) = __pa(ptep) | PMD_TYPE_TABLE | PMD_DOMAIN(domain);
set_pmd(pmdp, pmd);
set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain))); pmd_val(pmd) += 256 * sizeof(pte_t);
set_pmd(pmdp + 1, pmd);
} }
ptep = pte_offset_kernel(pmdp, virt); ptep = pte_offset_kernel(pmdp, virt);
...@@ -266,11 +267,11 @@ static void __init create_mapping(struct map_desc *md) ...@@ -266,11 +267,11 @@ static void __init create_mapping(struct map_desc *md)
length -= PAGE_SIZE; length -= PAGE_SIZE;
} }
while (length >= PGDIR_SIZE) { while (length >= (PGDIR_SIZE / 2)) {
alloc_init_section(virt, virt + off, prot_sect); alloc_init_section(virt, virt + off, prot_sect);
virt += PGDIR_SIZE; virt += (PGDIR_SIZE / 2);
length -= PGDIR_SIZE; length -= (PGDIR_SIZE / 2);
} }
while (length >= PAGE_SIZE) { while (length >= PAGE_SIZE) {
...@@ -463,41 +464,3 @@ void __init create_memmap_holes(struct meminfo *mi) ...@@ -463,41 +464,3 @@ void __init create_memmap_holes(struct meminfo *mi)
for (node = 0; node < numnodes; node++) for (node = 0; node < numnodes; node++)
free_unused_memmap_node(node, mi); free_unused_memmap_node(node, mi);
} }
/*
* PTE table allocation cache.
*
* This is a move away from our custom 2K page allocator. We now use the
* slab cache to keep track of these objects.
*
* With this, it is questionable as to whether the PGT cache gains us
* anything. We may be better off dropping the PTE stuff from our PGT
* cache implementation.
*/
kmem_cache_t *pte_cache;
/*
* The constructor gets called for each object within the cache when the
* cache page is created. Note that if slab tries to misalign the blocks,
* we BUG() loudly.
*/
static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
{
unsigned long block = (unsigned long)pte;
if (block & 2047)
BUG();
memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
cpu_cache_clean_invalidate_range(block, block +
PTRS_PER_PTE * sizeof(pte_t), 0);
}
void __init pgtable_cache_init(void)
{
pte_cache = kmem_cache_create("pte-cache",
2 * PTRS_PER_PTE * sizeof(pte_t), 0, 0,
pte_cache_ctor, NULL);
if (!pte_cache)
BUG();
}
...@@ -499,7 +499,9 @@ ENTRY(cpu_arm1020_set_pmd) ...@@ -499,7 +499,9 @@ ENTRY(cpu_arm1020_set_pmd)
*/ */
.align 5 .align 5
ENTRY(cpu_arm1020_set_pte) ENTRY(cpu_arm1020_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
...@@ -608,7 +610,7 @@ __arm1020_setup: ...@@ -608,7 +610,7 @@ __arm1020_setup:
*/ */
.type arm1020_processor_functions, #object .type arm1020_processor_functions, #object
arm1020_processor_functions: arm1020_processor_functions:
.word armv4t_early_abort .word v4t_early_abort
.word cpu_arm1020_check_bugs .word cpu_arm1020_check_bugs
.word cpu_arm1020_proc_init .word cpu_arm1020_proc_init
.word cpu_arm1020_proc_fin .word cpu_arm1020_proc_fin
...@@ -635,10 +637,6 @@ arm1020_processor_functions: ...@@ -635,10 +637,6 @@ arm1020_processor_functions:
.word cpu_arm1020_set_pmd .word cpu_arm1020_set_pmd
.word cpu_arm1020_set_pte .word cpu_arm1020_set_pte
/* misc */
.word armv4_clear_user_page
.word armv4_copy_user_page
.size arm1020_processor_functions, . - arm1020_processor_functions .size arm1020_processor_functions, . - arm1020_processor_functions
.type cpu_arm1020_info, #object .type cpu_arm1020_info, #object
...@@ -672,4 +670,5 @@ __arm1020_proc_info: ...@@ -672,4 +670,5 @@ __arm1020_proc_info:
.long cpu_arm1020_info .long cpu_arm1020_info
.long arm1020_processor_functions .long arm1020_processor_functions
.long v4wbi_tlb_fns .long v4wbi_tlb_fns
.long v4_user_fns
.size __arm1020_proc_info, . - __arm1020_proc_info .size __arm1020_proc_info, . - __arm1020_proc_info
...@@ -342,6 +342,7 @@ arm3_elf_name: .asciz "v2" ...@@ -342,6 +342,7 @@ arm3_elf_name: .asciz "v2"
.long cpu_arm2_info .long cpu_arm2_info
.long SYMBOL_NAME(arm2_processor_functions) .long SYMBOL_NAME(arm2_processor_functions)
.long 0 .long 0
.long 0
.long 0x41560250 .long 0x41560250
.long 0xfffffff0 .long 0xfffffff0
...@@ -353,6 +354,7 @@ arm3_elf_name: .asciz "v2" ...@@ -353,6 +354,7 @@ arm3_elf_name: .asciz "v2"
.long cpu_arm250_info .long cpu_arm250_info
.long SYMBOL_NAME(arm250_processor_functions) .long SYMBOL_NAME(arm250_processor_functions)
.long 0 .long 0
.long 0
.long 0x41560300 .long 0x41560300
.long 0xfffffff0 .long 0xfffffff0
...@@ -364,3 +366,5 @@ arm3_elf_name: .asciz "v2" ...@@ -364,3 +366,5 @@ arm3_elf_name: .asciz "v2"
.long cpu_arm3_info .long cpu_arm3_info
.long SYMBOL_NAME(arm3_processor_functions) .long SYMBOL_NAME(arm3_processor_functions)
.long 0 .long 0
.long 0
...@@ -274,7 +274,9 @@ ENTRY(cpu_arm7_set_pmd) ...@@ -274,7 +274,9 @@ ENTRY(cpu_arm7_set_pmd)
.align 5 .align 5
ENTRY(cpu_arm6_set_pte) ENTRY(cpu_arm6_set_pte)
ENTRY(cpu_arm7_set_pte) ENTRY(cpu_arm7_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
...@@ -373,10 +375,6 @@ ENTRY(arm6_processor_functions) ...@@ -373,10 +375,6 @@ ENTRY(arm6_processor_functions)
.word cpu_arm6_set_pmd .word cpu_arm6_set_pmd
.word cpu_arm6_set_pte .word cpu_arm6_set_pte
/* other */
.word armv3_clear_user_page
.word armv3_copy_user_page
.size arm6_processor_functions, . - arm6_processor_functions .size arm6_processor_functions, . - arm6_processor_functions
/* /*
...@@ -412,10 +410,6 @@ ENTRY(arm7_processor_functions) ...@@ -412,10 +410,6 @@ ENTRY(arm7_processor_functions)
.word cpu_arm7_set_pmd .word cpu_arm7_set_pmd
.word cpu_arm7_set_pte .word cpu_arm7_set_pte
/* other */
.word armv3_clear_user_page
.word armv3_copy_user_page
.size arm7_processor_functions, . - arm7_processor_functions .size arm7_processor_functions, . - arm7_processor_functions
.type cpu_arm6_info, #object .type cpu_arm6_info, #object
...@@ -465,6 +459,7 @@ __arm6_proc_info: ...@@ -465,6 +459,7 @@ __arm6_proc_info:
.long cpu_arm6_info .long cpu_arm6_info
.long arm6_processor_functions .long arm6_processor_functions
.long v3_tlb_fns .long v3_tlb_fns
.long v3_user_fns
.size __arm6_proc_info, . - __arm6_proc_info .size __arm6_proc_info, . - __arm6_proc_info
.type __arm610_proc_info, #object .type __arm610_proc_info, #object
...@@ -479,6 +474,7 @@ __arm610_proc_info: ...@@ -479,6 +474,7 @@ __arm610_proc_info:
.long cpu_arm610_info .long cpu_arm610_info
.long arm6_processor_functions .long arm6_processor_functions
.long v3_tlb_fns .long v3_tlb_fns
.long v3_user_fns
.size __arm610_proc_info, . - __arm610_proc_info .size __arm610_proc_info, . - __arm610_proc_info
.type __arm7_proc_info, #object .type __arm7_proc_info, #object
...@@ -493,6 +489,7 @@ __arm7_proc_info: ...@@ -493,6 +489,7 @@ __arm7_proc_info:
.long cpu_arm7_info .long cpu_arm7_info
.long arm7_processor_functions .long arm7_processor_functions
.long v3_tlb_fns .long v3_tlb_fns
.long v3_user_fns
.size __arm7_proc_info, . - __arm7_proc_info .size __arm7_proc_info, . - __arm7_proc_info
.type __arm710_proc_info, #object .type __arm710_proc_info, #object
...@@ -507,4 +504,5 @@ __arm710_proc_info: ...@@ -507,4 +504,5 @@ __arm710_proc_info:
.long cpu_arm710_info .long cpu_arm710_info
.long arm7_processor_functions .long arm7_processor_functions
.long v3_tlb_fns .long v3_tlb_fns
.long v3_user_fns
.size __arm710_proc_info, . - __arm710_proc_info .size __arm710_proc_info, . - __arm710_proc_info
...@@ -136,7 +136,9 @@ ENTRY(cpu_arm720_set_pmd) ...@@ -136,7 +136,9 @@ ENTRY(cpu_arm720_set_pmd)
*/ */
.align 5 .align 5
ENTRY(cpu_arm720_set_pte) ENTRY(cpu_arm720_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
...@@ -199,7 +201,7 @@ __arm720_setup: mov r0, #0 ...@@ -199,7 +201,7 @@ __arm720_setup: mov r0, #0
*/ */
.type arm720_processor_functions, #object .type arm720_processor_functions, #object
ENTRY(arm720_processor_functions) ENTRY(arm720_processor_functions)
.word armv4t_late_abort .word v4t_late_abort
.word cpu_arm720_check_bugs .word cpu_arm720_check_bugs
.word cpu_arm720_proc_init .word cpu_arm720_proc_init
.word cpu_arm720_proc_fin .word cpu_arm720_proc_fin
...@@ -226,10 +228,6 @@ ENTRY(arm720_processor_functions) ...@@ -226,10 +228,6 @@ ENTRY(arm720_processor_functions)
.word cpu_arm720_set_pmd .word cpu_arm720_set_pmd
.word cpu_arm720_set_pte .word cpu_arm720_set_pte
/* misc */
.word armv4_clear_user_page
.word armv4_copy_user_page
.size arm720_processor_functions, . - arm720_processor_functions .size arm720_processor_functions, . - arm720_processor_functions
.type cpu_arm720_info, #object .type cpu_arm720_info, #object
...@@ -265,4 +263,5 @@ __arm720_proc_info: ...@@ -265,4 +263,5 @@ __arm720_proc_info:
.long cpu_arm720_info @ info .long cpu_arm720_info @ info
.long arm720_processor_functions .long arm720_processor_functions
.long v4_tlb_fns .long v4_tlb_fns
.long v4_user_fns
.size __arm720_proc_info, . - __arm720_proc_info .size __arm720_proc_info, . - __arm720_proc_info
...@@ -420,7 +420,9 @@ ENTRY(cpu_arm920_set_pmd) ...@@ -420,7 +420,9 @@ ENTRY(cpu_arm920_set_pmd)
*/ */
.align 5 .align 5
ENTRY(cpu_arm920_set_pte) ENTRY(cpu_arm920_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
...@@ -511,7 +513,7 @@ __arm920_setup: ...@@ -511,7 +513,7 @@ __arm920_setup:
*/ */
.type arm920_processor_functions, #object .type arm920_processor_functions, #object
arm920_processor_functions: arm920_processor_functions:
.word armv4t_early_abort .word v4t_early_abort
.word cpu_arm920_check_bugs .word cpu_arm920_check_bugs
.word cpu_arm920_proc_init .word cpu_arm920_proc_init
.word cpu_arm920_proc_fin .word cpu_arm920_proc_fin
...@@ -538,10 +540,6 @@ arm920_processor_functions: ...@@ -538,10 +540,6 @@ arm920_processor_functions:
.word cpu_arm920_set_pmd .word cpu_arm920_set_pmd
.word cpu_arm920_set_pte .word cpu_arm920_set_pte
/* misc */
.word armv4_clear_user_page
.word armv4_copy_user_page
.size arm920_processor_functions, . - arm920_processor_functions .size arm920_processor_functions, . - arm920_processor_functions
.type cpu_arm920_info, #object .type cpu_arm920_info, #object
...@@ -575,4 +573,5 @@ __arm920_proc_info: ...@@ -575,4 +573,5 @@ __arm920_proc_info:
.long cpu_arm920_info .long cpu_arm920_info
.long arm920_processor_functions .long arm920_processor_functions
.long v4wbi_tlb_fns .long v4wbi_tlb_fns
.long v4_user_fns
.size __arm920_proc_info, . - __arm920_proc_info .size __arm920_proc_info, . - __arm920_proc_info
...@@ -421,7 +421,9 @@ ENTRY(cpu_arm922_set_pmd) ...@@ -421,7 +421,9 @@ ENTRY(cpu_arm922_set_pmd)
*/ */
.align 5 .align 5
ENTRY(cpu_arm922_set_pte) ENTRY(cpu_arm922_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
...@@ -512,7 +514,7 @@ __arm922_setup: ...@@ -512,7 +514,7 @@ __arm922_setup:
*/ */
.type arm922_processor_functions, #object .type arm922_processor_functions, #object
arm922_processor_functions: arm922_processor_functions:
.word armv4t_early_abort .word v4t_early_abort
.word cpu_arm922_check_bugs .word cpu_arm922_check_bugs
.word cpu_arm922_proc_init .word cpu_arm922_proc_init
.word cpu_arm922_proc_fin .word cpu_arm922_proc_fin
...@@ -539,10 +541,6 @@ arm922_processor_functions: ...@@ -539,10 +541,6 @@ arm922_processor_functions:
.word cpu_arm922_set_pmd .word cpu_arm922_set_pmd
.word cpu_arm922_set_pte .word cpu_arm922_set_pte
/* misc */
.word armv4_clear_user_page
.word armv4_copy_user_page
.size arm922_processor_functions, . - arm922_processor_functions .size arm922_processor_functions, . - arm922_processor_functions
.type cpu_arm922_info, #object .type cpu_arm922_info, #object
...@@ -576,4 +574,5 @@ __arm922_proc_info: ...@@ -576,4 +574,5 @@ __arm922_proc_info:
.long cpu_arm922_info .long cpu_arm922_info
.long arm922_processor_functions .long arm922_processor_functions
.long v4wbi_tlb_fns .long v4wbi_tlb_fns
.long v4_user_fns
.size __arm922_proc_info, . - __arm922_proc_info .size __arm922_proc_info, . - __arm922_proc_info
...@@ -443,7 +443,9 @@ ENTRY(cpu_arm926_set_pmd) ...@@ -443,7 +443,9 @@ ENTRY(cpu_arm926_set_pmd)
*/ */
.align 5 .align 5
ENTRY(cpu_arm926_set_pte) ENTRY(cpu_arm926_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
...@@ -549,7 +551,7 @@ __arm926_setup: ...@@ -549,7 +551,7 @@ __arm926_setup:
*/ */
.type arm926_processor_functions, #object .type arm926_processor_functions, #object
arm926_processor_functions: arm926_processor_functions:
.word armv5ej_early_abort .word v5ej_early_abort
.word cpu_arm926_check_bugs .word cpu_arm926_check_bugs
.word cpu_arm926_proc_init .word cpu_arm926_proc_init
.word cpu_arm926_proc_fin .word cpu_arm926_proc_fin
...@@ -576,10 +578,6 @@ arm926_processor_functions: ...@@ -576,10 +578,6 @@ arm926_processor_functions:
.word cpu_arm926_set_pmd .word cpu_arm926_set_pmd
.word cpu_arm926_set_pte .word cpu_arm926_set_pte
/* misc */
.word armv4_clear_user_page
.word armv4_copy_user_page
.size arm926_processor_functions, . - arm926_processor_functions .size arm926_processor_functions, . - arm926_processor_functions
.type cpu_arm926_info, #object .type cpu_arm926_info, #object
...@@ -613,4 +611,5 @@ __arm926_proc_info: ...@@ -613,4 +611,5 @@ __arm926_proc_info:
.long cpu_arm926_info .long cpu_arm926_info
.long arm926_processor_functions .long arm926_processor_functions
.long v4wbi_tlb_fns .long v4wbi_tlb_fns
.long v4_user_fns
.size __arm926_proc_info, . - __arm926_proc_info .size __arm926_proc_info, . - __arm926_proc_info
/* /*
* linux/arch/arm/mm/proc-sa110.S * linux/arch/arm/mm/proc-sa110.S
* *
* Copyright (C) 1997-2000 Russell King * Copyright (C) 1997-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -468,7 +468,9 @@ ENTRY(cpu_sa1100_set_pmd) ...@@ -468,7 +468,9 @@ ENTRY(cpu_sa1100_set_pmd)
.align 5 .align 5
ENTRY(cpu_sa110_set_pte) ENTRY(cpu_sa110_set_pte)
ENTRY(cpu_sa1100_set_pte) ENTRY(cpu_sa1100_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
...@@ -538,7 +540,7 @@ __setup_common: ...@@ -538,7 +540,7 @@ __setup_common:
.type sa110_processor_functions, #object .type sa110_processor_functions, #object
ENTRY(sa110_processor_functions) ENTRY(sa110_processor_functions)
.word armv4_early_abort .word v4_early_abort
.word cpu_sa110_check_bugs .word cpu_sa110_check_bugs
.word cpu_sa110_proc_init .word cpu_sa110_proc_init
.word cpu_sa110_proc_fin .word cpu_sa110_proc_fin
...@@ -565,10 +567,6 @@ ENTRY(sa110_processor_functions) ...@@ -565,10 +567,6 @@ ENTRY(sa110_processor_functions)
.word cpu_sa110_set_pmd .word cpu_sa110_set_pmd
.word cpu_sa110_set_pte .word cpu_sa110_set_pte
/* misc */
.word armv4_clear_user_page
.word armv4_copy_user_page
.size sa110_processor_functions, . - sa110_processor_functions .size sa110_processor_functions, . - sa110_processor_functions
.type cpu_sa110_info, #object .type cpu_sa110_info, #object
...@@ -610,10 +608,6 @@ ENTRY(sa1100_processor_functions) ...@@ -610,10 +608,6 @@ ENTRY(sa1100_processor_functions)
.word cpu_sa1100_set_pmd .word cpu_sa1100_set_pmd
.word cpu_sa1100_set_pte .word cpu_sa1100_set_pte
/* misc */
.word armv4_mc_clear_user_page
.word armv4_mc_copy_user_page
.size sa1100_processor_functions, . - sa1100_processor_functions .size sa1100_processor_functions, . - sa1100_processor_functions
cpu_sa1100_info: cpu_sa1100_info:
...@@ -651,6 +645,7 @@ __sa110_proc_info: ...@@ -651,6 +645,7 @@ __sa110_proc_info:
.long cpu_sa110_info .long cpu_sa110_info
.long sa110_processor_functions .long sa110_processor_functions
.long v4wb_tlb_fns .long v4wb_tlb_fns
.long v4_user_fns
.size __sa110_proc_info, . - __sa110_proc_info .size __sa110_proc_info, . - __sa110_proc_info
.type __sa1100_proc_info,#object .type __sa1100_proc_info,#object
...@@ -665,6 +660,7 @@ __sa1100_proc_info: ...@@ -665,6 +660,7 @@ __sa1100_proc_info:
.long cpu_sa1100_info .long cpu_sa1100_info
.long sa1100_processor_functions .long sa1100_processor_functions
.long v4wb_tlb_fns .long v4wb_tlb_fns
.long v4_mc_user_fns
.size __sa1100_proc_info, . - __sa1100_proc_info .size __sa1100_proc_info, . - __sa1100_proc_info
.type __sa1110_proc_info,#object .type __sa1110_proc_info,#object
...@@ -679,4 +675,5 @@ __sa1110_proc_info: ...@@ -679,4 +675,5 @@ __sa1110_proc_info:
.long cpu_sa1110_info .long cpu_sa1110_info
.long sa1100_processor_functions .long sa1100_processor_functions
.long v4wb_tlb_fns .long v4wb_tlb_fns
.long v4_mc_user_fns
.size __sa1110_proc_info, . - __sa1110_proc_info .size __sa1110_proc_info, . - __sa1110_proc_info
...@@ -602,7 +602,9 @@ ENTRY(cpu_xscale_set_pmd) ...@@ -602,7 +602,9 @@ ENTRY(cpu_xscale_set_pmd)
*/ */
.align 5 .align 5
ENTRY(cpu_xscale_set_pte) ENTRY(cpu_xscale_set_pte)
str r1, [r0], #-1024 @ linux version tst r0, #2048
streq r0, [r0, -r0] @ BUG_ON
str r1, [r0], #-2048 @ linux version
bic r2, r1, #0xff0 bic r2, r1, #0xff0
orr r2, r2, #PTE_TYPE_EXT @ extended page orr r2, r2, #PTE_TYPE_EXT @ extended page
...@@ -695,7 +697,7 @@ __xscale_setup: ...@@ -695,7 +697,7 @@ __xscale_setup:
.type xscale_processor_functions, #object .type xscale_processor_functions, #object
ENTRY(xscale_processor_functions) ENTRY(xscale_processor_functions)
.word armv4t_early_abort .word v4t_early_abort
.word cpu_xscale_check_bugs .word cpu_xscale_check_bugs
.word cpu_xscale_proc_init .word cpu_xscale_proc_init
.word cpu_xscale_proc_fin .word cpu_xscale_proc_fin
...@@ -722,10 +724,6 @@ ENTRY(xscale_processor_functions) ...@@ -722,10 +724,6 @@ ENTRY(xscale_processor_functions)
.word cpu_xscale_set_pmd .word cpu_xscale_set_pmd
.word cpu_xscale_set_pte .word cpu_xscale_set_pte
/* misc */
.word armv5te_clear_user_page
.word armv5te_copy_user_page
.size xscale_processor_functions, . - xscale_processor_functions .size xscale_processor_functions, . - xscale_processor_functions
.type cpu_80200_info, #object .type cpu_80200_info, #object
...@@ -765,6 +763,7 @@ __80200_proc_info: ...@@ -765,6 +763,7 @@ __80200_proc_info:
.long cpu_80200_info .long cpu_80200_info
.long xscale_processor_functions .long xscale_processor_functions
.long v4wbi_tlb_fns .long v4wbi_tlb_fns
.long v5te_mc_user_fns
.size __80200_proc_info, . - __80200_proc_info .size __80200_proc_info, . - __80200_proc_info
.type __pxa250_proc_info,#object .type __pxa250_proc_info,#object
...@@ -779,6 +778,7 @@ __pxa250_proc_info: ...@@ -779,6 +778,7 @@ __pxa250_proc_info:
.long cpu_pxa250_info .long cpu_pxa250_info
.long xscale_processor_functions .long xscale_processor_functions
.long v4wbi_tlb_fns .long v4wbi_tlb_fns
.long v5te_mc_user_fns
.size __cotulla_proc_info, . - __cotulla_proc_info .size __cotulla_proc_info, . - __cotulla_proc_info
.size __pxa250_proc_info, . - __pxa250_proc_info .size __pxa250_proc_info, . - __pxa250_proc_info
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/time.h>
#include <linux/miscdevice.h>
#include <linux/rtc.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
...@@ -21,15 +24,19 @@ ...@@ -21,15 +24,19 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/hardware/ioc.h> #include <asm/hardware/ioc.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h>
#include "pcf8583.h" #include "pcf8583.h"
extern unsigned long
mktime(unsigned int year, unsigned int mon, unsigned int day,
unsigned int hour, unsigned int min, unsigned int sec);
extern int (*set_rtc)(void); extern int (*set_rtc)(void);
static struct i2c_client *rtc_client; static struct i2c_client *rtc_client;
static const unsigned char days_in_mon[] =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static unsigned int rtc_epoch = 1900;
#define CMOS_CHECKSUM (63)
#define CMOS_YEAR (64 + 128)
static inline int rtc_command(int cmd, void *data) static inline int rtc_command(int cmd, void *data)
{ {
...@@ -44,12 +51,10 @@ static inline int rtc_command(int cmd, void *data) ...@@ -44,12 +51,10 @@ static inline int rtc_command(int cmd, void *data)
/* /*
* Read the current RTC time and date, and update xtime. * Read the current RTC time and date, and update xtime.
*/ */
static void get_rtc_time(void) static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year)
{ {
unsigned char ctrl; unsigned char ctrl, yr[2];
unsigned char year; struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr };
struct rtc_tm rtctm;
struct mem rtcmem = { 0xc0, 1, &year };
/* /*
* Ensure that the RTC is running. * Ensure that the RTC is running.
...@@ -73,22 +78,53 @@ static void get_rtc_time(void) ...@@ -73,22 +78,53 @@ static void get_rtc_time(void)
if (rtc_command(MEM_READ, &rtcmem)) if (rtc_command(MEM_READ, &rtcmem))
return; return;
if (rtc_command(RTC_GETDATETIME, &rtctm)) if (rtc_command(RTC_GETDATETIME, rtctm))
return; return;
if (year < 70) *year = yr[1] * 100 + yr[0];
year += 100; }
static int set_rtc_time(struct rtc_tm *rtctm, unsigned int year)
{
unsigned char yr[2], leap, chk;
struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr };
struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
int ret;
leap = (!(year % 4) && (year % 100)) || !(year % 400);
if (rtctm->mon > 12 || rtctm->mday == 0)
return -EINVAL;
if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap)))
return -EINVAL;
if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60)
return -EINVAL;
xtime.tv_usec = rtctm.cs * 10000; ret = rtc_command(RTC_SETDATETIME, rtctm);
xtime.tv_sec = mktime(1900 + year, rtctm.mon, rtctm.mday, if (ret == 0) {
rtctm.hours, rtctm.mins, rtctm.secs); rtc_command(MEM_READ, &cmos_check);
rtc_command(MEM_READ, &cmos_year);
chk -= yr[1] + yr[0];
yr[1] = year / 100;
yr[0] = year % 100;
chk += yr[1] + yr[0];
rtc_command(MEM_WRITE, &cmos_year);
rtc_command(MEM_WRITE, &cmos_check);
}
return ret;
} }
/* /*
* Set the RTC time only. Note that * Set the RTC time only. Note that
* we do not touch the date. * we do not touch the date.
*/ */
static int set_rtc_time(void) static int k_set_rtc_time(void)
{ {
struct rtc_tm new_rtctm, old_rtctm; struct rtc_tm new_rtctm, old_rtctm;
unsigned long nowtime = xtime.tv_sec; unsigned long nowtime = xtime.tv_sec;
...@@ -110,13 +146,70 @@ static int set_rtc_time(void) ...@@ -110,13 +146,70 @@ static int set_rtc_time(void)
* [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00, * [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00,
* rtc gets set to 1/1/2000 00:01:00 ] * rtc gets set to 1/1/2000 00:01:00 ]
*/ */
if ((old_rtctm.hours == 23 && old_rtctm.mins == 59) || if ((old_rtctm.hours == 23 && old_rtctm.mins == 59) ||
(new_rtctm.hours == 23 && new_rtctm.mins == 59)) (new_rtctm.hours == 23 && new_rtctm.mins == 59))
return 1; return 1;
return rtc_command(RTC_SETTIME, &new_rtctm); return rtc_command(RTC_SETTIME, &new_rtctm);
} }
static int rtc_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned int year;
struct rtc_time rtctm;
struct rtc_tm rtc_raw;
switch (cmd) {
case RTC_ALM_READ:
case RTC_ALM_SET:
break;
case RTC_RD_TIME:
get_rtc_time(&rtc_raw, &year);
rtctm.tm_sec = rtc_raw.secs;
rtctm.tm_min = rtc_raw.mins;
rtctm.tm_hour = rtc_raw.hours;
rtctm.tm_mday = rtc_raw.mday;
rtctm.tm_mon = rtc_raw.mon - 1; /* month starts at 0 */
rtctm.tm_year = year - 1900; /* starts at 1900 */
return copy_to_user((void *)arg, &rtctm, sizeof(rtctm))
? -EFAULT : 0;
case RTC_SET_TIME:
if (!capable(CAP_SYS_TIME))
return -EACCES;
if (copy_from_user(&rtctm, (void *)arg, sizeof(rtctm)))
return -EFAULT;
rtc_raw.secs = rtctm.tm_sec;
rtc_raw.mins = rtctm.tm_min;
rtc_raw.hours = rtctm.tm_hour;
rtc_raw.mday = rtctm.tm_mday;
rtc_raw.mon = rtctm.tm_mon + 1;
rtc_raw.year_off = 2;
year = rtctm.tm_year + 1900;
return set_rtc_time(&rtc_raw, year);
break;
case RTC_EPOCH_READ:
return put_user(rtc_epoch, (unsigned long *)arg);
}
return -EINVAL;
}
static struct file_operations rtc_fops = {
ioctl: rtc_ioctl,
};
static struct miscdevice rtc_dev = {
minor: RTC_MINOR,
name: "rtc",
fops: &rtc_fops,
};
/* IOC / IOMD i2c driver */
#define FORCE_ONES 0xdc #define FORCE_ONES 0xdc
#define SCL 0x02 #define SCL 0x02
...@@ -184,9 +277,16 @@ static int ioc_client_reg(struct i2c_client *client) ...@@ -184,9 +277,16 @@ static int ioc_client_reg(struct i2c_client *client)
{ {
if (client->id == I2C_DRIVERID_PCF8583 && if (client->id == I2C_DRIVERID_PCF8583 &&
client->addr == 0x50) { client->addr == 0x50) {
struct rtc_tm rtctm;
unsigned int year;
rtc_client = client; rtc_client = client;
get_rtc_time(); get_rtc_time(&rtctm, &year);
set_rtc = set_rtc_time;
xtime.tv_usec = rtctm.cs * 10000;
xtime.tv_sec = mktime(year, rtctm.mon, rtctm.mday,
rtctm.hours, rtctm.mins, rtctm.secs);
set_rtc = k_set_rtc_time;
} }
return 0; return 0;
...@@ -212,9 +312,16 @@ static struct i2c_adapter ioc_ops = { ...@@ -212,9 +312,16 @@ static struct i2c_adapter ioc_ops = {
static int __init i2c_ioc_init(void) static int __init i2c_ioc_init(void)
{ {
int ret;
force_ones = FORCE_ONES | SCL | SDA; force_ones = FORCE_ONES | SCL | SDA;
return i2c_bit_add_bus(&ioc_ops); ret = i2c_bit_add_bus(&ioc_ops);
if (ret >= 0)
misc_register(&rtc_dev);
return ret;
} }
__initcall(i2c_ioc_init); __initcall(i2c_ioc_init);
...@@ -20,7 +20,4 @@ ...@@ -20,7 +20,4 @@
#define MY_PORT_ADDRESS(port,cardaddr) \ #define MY_PORT_ADDRESS(port,cardaddr) \
((cardaddr) + 0x200 - (port) * 0x100) ((cardaddr) + 0x200 - (port) * 0x100)
#define INIT serial_card_atomwide_init
#define EXIT serial_card_atomwide_exit
#include "serial-card.c" #include "serial-card.c"
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/ecard.h> #include <asm/ecard.h>
...@@ -38,95 +39,84 @@ ...@@ -38,95 +39,84 @@
#define NUM_SERIALS MY_NUMPORTS * MAX_ECARDS #define NUM_SERIALS MY_NUMPORTS * MAX_ECARDS
#endif #endif
#ifdef MODULE static int serial_ports[NUM_SERIALS];
static int __serial_ports[NUM_SERIALS]; static int serial_pcount;
static int __serial_pcount; static int serial_addr[NUM_SERIALS];
static int __serial_addr[NUM_SERIALS];
static struct expansion_card *expcard[MAX_ECARDS]; static struct expansion_card *expcard[MAX_ECARDS];
#define ADD_ECARD(ec,card) expcard[(card)] = (ec)
#define ADD_PORT(port,addr) \
do { \
__serial_ports[__serial_pcount] = (port); \
__serial_addr[__serial_pcount] = (addr); \
__serial_pcount += 1; \
} while (0)
#else
#define ADD_ECARD(ec,card)
#define ADD_PORT(port,addr)
#endif
static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } }; static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } };
static inline int serial_register_onedev (unsigned long port, int irq) static inline int serial_register_onedev (unsigned long port, int irq)
{ {
struct serial_struct req; struct serial_struct req;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.baud_base = MY_BAUD_BASE; req.baud_base = MY_BAUD_BASE;
req.irq = irq; req.irq = irq;
req.port = port; req.port = port;
req.flags = 0; req.flags = 0;
return register_serial(&req); return register_serial(&req);
} }
static int __init INIT (void) static int __init serial_card_init(void)
{ {
int card = 0; int card = 0;
ecard_startfind (); ecard_startfind ();
do { do {
struct expansion_card *ec; struct expansion_card *ec;
unsigned long cardaddr; unsigned long cardaddr;
int port; int port;
ec = ecard_find (0, serial_cids); ec = ecard_find (0, serial_cids);
if (!ec) if (!ec)
break; break;
cardaddr = MY_BASE_ADDRESS(ec); cardaddr = MY_BASE_ADDRESS(ec);
for (port = 0; port < MY_NUMPORTS; port ++) { for (port = 0; port < MY_NUMPORTS; port ++) {
unsigned long address; unsigned long address;
int line; int line;
address = MY_PORT_ADDRESS(port, cardaddr); address = MY_PORT_ADDRESS(port, cardaddr);
line = serial_register_onedev (address, ec->irq); line = serial_register_onedev (address, ec->irq);
if (line < 0) if (line < 0)
break; break;
ADD_PORT(line, address); serial_ports[serial_pcount] = line;
} serial_addr[serial_pcount] = address;
serial_pcount += 1;
if (port) { }
ecard_claim (ec);
ADD_ECARD(ec, card); if (port) {
} else ecard_claim (ec);
break; expcard[card] = ec;
} while (++card < MAX_ECARDS); } else
return card ? 0 : -ENODEV; break;
} while (++card < MAX_ECARDS);
return card ? 0 : -ENODEV;
} }
static void __exit EXIT (void) static void __exit serial_card_exit(void)
{ {
#ifdef MODULE int i;
int i;
for (i = 0; i < __serial_pcount; i++) { for (i = 0; i < serial_pcount; i++) {
unregister_serial(__serial_ports[i]); unregister_serial(serial_ports[i]);
release_region(__serial_addr[i], 8); release_region(serial_addr[i], 8);
} }
for (i = 0; i < MAX_ECARDS; i++) for (i = 0; i < MAX_ECARDS; i++)
if (expcard[i]) if (expcard[i])
ecard_release (expcard[i]); ecard_release (expcard[i]);
#endif
} }
EXPORT_NO_SYMBOLS; EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Russell King");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(INIT); module_init(serial_card_init);
module_exit(EXIT); module_exit(serial_card_exit);
...@@ -18,7 +18,4 @@ ...@@ -18,7 +18,4 @@
#define MY_PORT_ADDRESS(port,cardaddress) \ #define MY_PORT_ADDRESS(port,cardaddress) \
((cardaddress) + (port) * 8) ((cardaddress) + (port) * 8)
#define INIT serial_card_dualsp_init
#define EXIT serial_card_dualsp_exit
#include "serial-card.c" #include "serial-card.c"
...@@ -718,7 +718,7 @@ dropping:{ ...@@ -718,7 +718,7 @@ dropping:{
/* /*
* Don't print this message too many times... * Don't print this message too many times...
*/ */
if (jiffies - last_warned > 30 * HZ) { if (time_after(jiffies, last_warned + 10 * HZ)) {
last_warned = jiffies; last_warned = jiffies;
printk("%s: memory squeeze, dropping packet.\n", dev->name); printk("%s: memory squeeze, dropping packet.\n", dev->name);
} }
......
/* /*
* linux/drivers/acorn/net/etherh.c * linux/drivers/acorn/net/etherh.c
* *
* Copyright (C) 2000 Russell King * Copyright (C) 2000-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
* 12-10-1999 CK/TEW EtherM driver first release * 12-10-1999 CK/TEW EtherM driver first release
* 21-12-2000 TTC EtherH/EtherM integration * 21-12-2000 TTC EtherH/EtherM integration
* 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver. * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver.
* 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -64,13 +65,18 @@ static const card_ids __init etherh_cids[] = { ...@@ -64,13 +65,18 @@ static const card_ids __init etherh_cids[] = {
{ 0xffff, 0xffff } { 0xffff, 0xffff }
}; };
struct etherh_priv {
unsigned int id;
unsigned int ctrl_port;
unsigned int ctrl;
};
MODULE_AUTHOR("Russell King"); MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("EtherH/EtherM driver"); MODULE_DESCRIPTION("EtherH/EtherM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static char version[] __initdata = static char version[] __initdata =
"EtherH/EtherM Driver (c) 2000 Russell King v1.08\n"; "EtherH/EtherM Driver (c) 2002 Russell King v1.09\n";
#define ETHERH500_DATAPORT 0x200 /* MEMC */ #define ETHERH500_DATAPORT 0x200 /* MEMC */
#define ETHERH500_NS8390 0x000 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */
...@@ -97,18 +103,61 @@ static char version[] __initdata = ...@@ -97,18 +103,61 @@ static char version[] __initdata =
#define ETHERM_TX_START_PAGE 64 #define ETHERM_TX_START_PAGE 64
#define ETHERM_STOP_PAGE 127 #define ETHERM_STOP_PAGE 127
/* --------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------ */
static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask)
{
eh->ctrl |= mask;
outb(eh->ctrl, eh->ctrl_port);
}
static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask)
{
eh->ctrl &= ~mask;
outb(eh->ctrl, eh->ctrl_port);
}
static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
{
return inb(eh->ctrl_port);
}
static void etherh_irq_enable(ecard_t *ec, int irqnr)
{
struct etherh_priv *eh = ec->irq_data;
etherh_set_ctrl(eh, ETHERH_CP_IE);
}
static void etherh_irq_disable(ecard_t *ec, int irqnr)
{
struct etherh_priv *eh = ec->irq_data;
etherh_clr_ctrl(eh, ETHERH_CP_IE);
}
static expansioncard_ops_t etherh_ops = {
irqenable: etherh_irq_enable,
irqdisable: etherh_irq_disable,
};
static void static void
etherh_setif(struct net_device *dev) etherh_setif(struct net_device *dev)
{ {
struct ei_device *ei_local = (struct ei_device *) dev->priv; struct ei_device *ei_local = (struct ei_device *) dev->priv;
struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
unsigned long addr, flags; unsigned long addr, flags;
save_flags_cli(flags); local_irq_save(flags);
/* set the interface type */ /* set the interface type */
switch (dev->mem_end) { switch (eh->id) {
case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A: case PROD_I3_ETHERLAN600A:
addr = dev->base_addr + EN0_RCNTHI; addr = dev->base_addr + EN0_RCNTHI;
...@@ -124,14 +173,13 @@ etherh_setif(struct net_device *dev) ...@@ -124,14 +173,13 @@ etherh_setif(struct net_device *dev)
break; break;
case PROD_I3_ETHERLAN500: case PROD_I3_ETHERLAN500:
addr = dev->rmem_start;
switch (dev->if_port) { switch (dev->if_port) {
case IF_PORT_10BASE2: case IF_PORT_10BASE2:
outb(inb(addr) & ~ETHERH_CP_IF, addr); etherh_clr_ctrl(eh, ETHERH_CP_IF);
break; break;
case IF_PORT_10BASET: case IF_PORT_10BASET:
outb(inb(addr) | ETHERH_CP_IF, addr); etherh_set_ctrl(eh, ETHERH_CP_IF);
break; break;
} }
break; break;
...@@ -140,16 +188,17 @@ etherh_setif(struct net_device *dev) ...@@ -140,16 +188,17 @@ etherh_setif(struct net_device *dev)
break; break;
} }
restore_flags(flags); local_irq_restore(flags);
} }
static int static int
etherh_getifstat(struct net_device *dev) etherh_getifstat(struct net_device *dev)
{ {
struct ei_device *ei_local = (struct ei_device *) dev->priv; struct ei_device *ei_local = (struct ei_device *) dev->priv;
struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
int stat = 0; int stat = 0;
switch (dev->mem_end) { switch (eh->id) {
case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A: case PROD_I3_ETHERLAN600A:
switch (dev->if_port) { switch (dev->if_port) {
...@@ -168,7 +217,7 @@ etherh_getifstat(struct net_device *dev) ...@@ -168,7 +217,7 @@ etherh_getifstat(struct net_device *dev)
stat = 1; stat = 1;
break; break;
case IF_PORT_10BASET: case IF_PORT_10BASET:
stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT; stat = etherh_get_stat(eh) & ETHERH_CP_HEARTBEAT;
break; break;
} }
break; break;
...@@ -251,7 +300,13 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ...@@ -251,7 +300,13 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
return; return;
} }
ei_local->dmaing |= 1; /*
* Make sure we have a round number of bytes if we're in word mode.
*/
if (count & 1 && ei_local->word16)
count++;
ei_local->dmaing = 1;
addr = dev->base_addr; addr = dev->base_addr;
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
...@@ -291,7 +346,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ...@@ -291,7 +346,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
} }
outb (ENISR_RDC, addr + EN0_ISR); outb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing &= ~1; ei_local->dmaing = 0;
} }
/* /*
...@@ -311,7 +366,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ...@@ -311,7 +366,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
return; return;
} }
ei_local->dmaing |= 1; ei_local->dmaing = 1;
addr = dev->base_addr; addr = dev->base_addr;
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
...@@ -332,7 +387,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ...@@ -332,7 +387,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
insb (dma_addr, buf, count); insb (dma_addr, buf, count);
outb (ENISR_RDC, addr + EN0_ISR); outb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing &= ~1; ei_local->dmaing = 0;
} }
/* /*
...@@ -351,7 +406,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p ...@@ -351,7 +406,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
return; return;
} }
ei_local->dmaing |= 1; ei_local->dmaing = 1;
addr = dev->base_addr; addr = dev->base_addr;
dma_addr = dev->mem_start; dma_addr = dev->mem_start;
...@@ -369,7 +424,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p ...@@ -369,7 +424,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
insb (dma_addr, hdr, sizeof (*hdr)); insb (dma_addr, hdr, sizeof (*hdr));
outb (ENISR_RDC, addr + EN0_ISR); outb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing &= ~1; ei_local->dmaing = 0;
} }
/* /*
...@@ -427,23 +482,6 @@ etherh_close(struct net_device *dev) ...@@ -427,23 +482,6 @@ etherh_close(struct net_device *dev)
return 0; return 0;
} }
static void etherh_irq_enable(ecard_t *ec, int irqnr)
{
unsigned int ctrl_addr = (unsigned int)ec->irq_data;
outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr);
}
static void etherh_irq_disable(ecard_t *ec, int irqnr)
{
unsigned int ctrl_addr = (unsigned int)ec->irq_data;
outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr);
}
static expansioncard_ops_t etherh_ops = {
irqenable: etherh_irq_enable,
irqdisable: etherh_irq_disable,
};
/* /*
* Initialisation * Initialisation
*/ */
...@@ -506,6 +544,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -506,6 +544,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
{ {
struct ei_device *ei_local; struct ei_device *ei_local;
struct net_device *dev; struct net_device *dev;
struct etherh_priv *eh;
const char *dev_type; const char *dev_type;
int i, size; int i, size;
...@@ -517,6 +556,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -517,6 +556,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (!dev) if (!dev)
goto out; goto out;
eh = kmalloc(sizeof(struct etherh_priv), GFP_KERNEL);
if (!eh)
goto out_nopriv;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
dev->open = etherh_open; dev->open = etherh_open;
...@@ -524,8 +567,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -524,8 +567,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
dev->set_config = etherh_set_config; dev->set_config = etherh_set_config;
dev->irq = ec->irq; dev->irq = ec->irq;
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
dev->mem_end = ec->cid.product; dev->rmem_start = (unsigned long)eh;
/*
* IRQ and control port handling
*/
ec->ops = &etherh_ops; ec->ops = &etherh_ops;
ec->irq_data = eh;
eh->ctrl = 0;
eh->id = ec->cid.product;
switch (ec->cid.product) { switch (ec->cid.product) {
case PROD_ANT_ETHERM: case PROD_ANT_ETHERM:
...@@ -533,7 +583,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -533,7 +583,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
goto free; goto free;
dev->base_addr += ETHERM_NS8390; dev->base_addr += ETHERM_NS8390;
dev->mem_start = dev->base_addr + ETHERM_DATAPORT; dev->mem_start = dev->base_addr + ETHERM_DATAPORT;
ec->irq_data = (void *)(dev->base_addr + ETHERM_CTRLPORT); eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT;
break; break;
case PROD_I3_ETHERLAN500: case PROD_I3_ETHERLAN500:
...@@ -541,8 +591,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -541,8 +591,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
goto free; goto free;
dev->base_addr += ETHERH500_NS8390; dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
dev->rmem_start = (unsigned long) eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
ec->irq_data = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST)
+ ETHERH500_CTRLPORT; + ETHERH500_CTRLPORT;
break; break;
...@@ -551,8 +600,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -551,8 +600,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (etherh_addr(dev->dev_addr, ec)) if (etherh_addr(dev->dev_addr, ec))
goto free; goto free;
dev->base_addr += ETHERH600_NS8390; dev->base_addr += ETHERH600_NS8390;
dev->mem_start = dev->base_addr + ETHERH600_DATAPORT; dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
ec->irq_data = (void *)(dev->base_addr + ETHERH600_CTRLPORT); eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT;
break; break;
default: default:
...@@ -571,6 +620,12 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -571,6 +620,12 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (ethdev_init(dev)) if (ethdev_init(dev))
goto release; goto release;
/*
* If we're in the NIC slot, make sure the IRQ is enabled
*/
if (dev->irq == 11)
etherh_set_ctrl(eh, ETHERH_CP_IE);
/* /*
* Unfortunately, ethdev_init eventually calls * Unfortunately, ethdev_init eventually calls
* ether_setup, which re-writes dev->flags. * ether_setup, which re-writes dev->flags.
...@@ -636,6 +691,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec) ...@@ -636,6 +691,8 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
release: release:
release_region(dev->base_addr, 16); release_region(dev->base_addr, 16);
free: free:
kfree(eh);
out_nopriv:
unregister_netdev(dev); unregister_netdev(dev);
kfree(dev); kfree(dev);
out: out:
...@@ -696,6 +753,7 @@ static void __exit etherh_exit(void) ...@@ -696,6 +753,7 @@ static void __exit etherh_exit(void)
} }
if (e_card[i]) { if (e_card[i]) {
e_card[i]->ops = NULL; e_card[i]->ops = NULL;
kfree(e_card[i]->irq_data);
ecard_release(e_card[i]); ecard_release(e_card[i]);
e_card[i] = NULL; e_card[i] = NULL;
} }
......
...@@ -2583,10 +2583,10 @@ int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -2583,10 +2583,10 @@ int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
done(SCpnt); done(SCpnt);
return 0; return 0;
} }
save_flags_cli(flags); local_irq_save(flags);
if (host->scsi.phase == PHASE_IDLE) if (host->scsi.phase == PHASE_IDLE)
acornscsi_kick(host); acornscsi_kick(host);
restore_flags(flags); local_irq_restore(flags);
} }
return 0; return 0;
} }
......
...@@ -2137,7 +2137,7 @@ int fas216_command(Scsi_Cmnd *SCpnt) ...@@ -2137,7 +2137,7 @@ int fas216_command(Scsi_Cmnd *SCpnt)
* However, we must re-enable interrupts, or else we'll be * However, we must re-enable interrupts, or else we'll be
* waiting forever. * waiting forever.
*/ */
spin_unlock_irq(&io_request_lock); spin_unlock_irq(info->host->host_lock);
while (!info->internal_done) { while (!info->internal_done) {
/* /*
...@@ -2149,13 +2149,13 @@ int fas216_command(Scsi_Cmnd *SCpnt) ...@@ -2149,13 +2149,13 @@ int fas216_command(Scsi_Cmnd *SCpnt)
* to be some time (eg, disconnected). * to be some time (eg, disconnected).
*/ */
if (inb(REG_STAT(info)) & STAT_INT) { if (inb(REG_STAT(info)) & STAT_INT) {
spin_lock_irq(&io_request_lock); spin_lock_irq(info->host->host_lock);
fas216_intr(info->host); fas216_intr(info->host);
spin_unlock_irq(&io_request_lock); spin_unlock_irq(info->host->host_lock);
} }
} }
spin_lock_irq(&io_request_lock); spin_lock_irq(info->host->host_lock);
return SCpnt->result; return SCpnt->result;
} }
...@@ -2459,13 +2459,13 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) ...@@ -2459,13 +2459,13 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
/* /*
* Ugly ugly ugly! * Ugly ugly ugly!
* We need to release the io_request_lock and enable * We need to release the host_lock and enable
* IRQs if we sleep, but we must relock and disable * IRQs if we sleep, but we must relock and disable
* IRQs after the sleep. * IRQs after the sleep.
*/ */
spin_unlock_irq(&io_request_lock); spin_unlock_irq(info->host->host_lock);
scsi_sleep(25*HZ/100); scsi_sleep(25*HZ/100);
spin_lock_irq(&io_request_lock); spin_lock_irq(info->host->host_lock);
/* /*
* Release the SCSI reset. * Release the SCSI reset.
...@@ -2628,9 +2628,9 @@ int fas216_init(struct Scsi_Host *instance) ...@@ -2628,9 +2628,9 @@ int fas216_init(struct Scsi_Host *instance)
/* /*
* scsi standard says wait 250ms * scsi standard says wait 250ms
*/ */
spin_unlock_irq(&io_request_lock); spin_unlock_irq(info->host->host_lock);
scsi_sleep(25*HZ/100); scsi_sleep(25*HZ/100);
spin_lock_irq(&io_request_lock); spin_lock_irq(info->host->host_lock);
outb(info->scsi.cfg[0], REG_CNTL1(info)); outb(info->scsi.cfg[0], REG_CNTL1(info));
inb(REG_INST(info)); inb(REG_INST(info));
......
...@@ -82,6 +82,68 @@ static struct pcmcia_low_level *pcmcia_low_level; ...@@ -82,6 +82,68 @@ static struct pcmcia_low_level *pcmcia_low_level;
static struct timer_list poll_timer; static struct timer_list poll_timer;
static struct tq_struct sa1100_pcmcia_task; static struct tq_struct sa1100_pcmcia_task;
/*
* sa1100_pcmcia_default_mecr_timing
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
* Calculate MECR clock wait states for given CPU clock
* speed and command wait state. This function can be over-
* written by a board specific version.
*
* The default is to simply calculate the BS values as specified in
* the INTEL SA1100 development manual
* "Expansion Memory (PCMCIA) Configuration Register (MECR)"
* that's section 10.2.5 in _my_ version of the manuial ;)
*/
static int sa1100_pcmcia_default_mecr_timing(unsigned int sock, unsigned int cpu_speed,
unsigned int cmd_time )
{
return sa1100_pcmcia_mecr_bs( cmd_time, cpu_speed );
}
/* sa1100_pcmcia_set_mecr()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
* set MECR value for socket <sock> based on this sockets
* io, mem and attribute space access speed.
* Call board specific BS value calculation to allow boards
* to tweak the BS values.
*/
static int sa1100_pcmcia_set_mecr( int sock )
{
struct sa1100_pcmcia_socket *skt;
u32 mecr;
int clock;
long flags;
unsigned int bs;
if ( sock<0 || sock>SA1100_PCMCIA_MAX_SOCK )
return -1;
skt = PCMCIA_SOCKET( sock );
local_irq_save(flags);
clock = cpufreq_get(0);
bs = pcmcia_low_level->socket_get_timing( sock, clock, skt->speed_io);
mecr = MECR;
MECR_FAST_SET(mecr, sock, 0);
MECR_BSIO_SET(mecr, sock, bs );
MECR_BSA_SET(mecr, sock, bs );
MECR_BSM_SET(mecr, sock, bs );
MECR = mecr;
local_irq_restore(flags);
DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
__FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
sock, MECR_BSIO_GET(mecr, sock));
return 0;
}
/* /*
* sa1100_pcmcia_state_to_config * sa1100_pcmcia_state_to_config
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...@@ -586,26 +648,10 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) ...@@ -586,26 +648,10 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
} }
if (map->flags & MAP_ACTIVE) { if (map->flags & MAP_ACTIVE) {
unsigned int clock, speed = map->speed; if ( map->speed == 0)
unsigned long mecr; map->speed = SA1100_PCMCIA_IO_ACCESS;
if (speed == 0) sa1100_pcmcia_set_mecr( sock );
speed = SA1100_PCMCIA_IO_ACCESS;
clock = cpufreq_get(0);
mecr = MECR;
MECR_BSIO_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
skt->speed_io = speed;
DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
__FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
sock, MECR_BSIO_GET(mecr, sock));
MECR = mecr;
} }
if (map->stop == 1) if (map->stop == 1)
...@@ -683,39 +729,19 @@ sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) ...@@ -683,39 +729,19 @@ sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
} }
if (map->flags & MAP_ACTIVE) { if (map->flags & MAP_ACTIVE) {
unsigned int clock, speed = map->speed; /*
unsigned long mecr; * When clients issue RequestMap, the access speed is not always
* properly configured. Choose some sensible defaults.
/* */
* When clients issue RequestMap, the access speed is not always if (map->speed == 0) {
* properly configured. Choose some sensible defaults. if (skt->cs_state.Vcc == 33)
*/ map->speed = SA1100_PCMCIA_3V_MEM_ACCESS;
if (speed == 0) { else
if (skt->cs_state.Vcc == 33) map->speed = SA1100_PCMCIA_5V_MEM_ACCESS;
speed = SA1100_PCMCIA_3V_MEM_ACCESS; }
else
speed = SA1100_PCMCIA_5V_MEM_ACCESS; sa1100_pcmcia_set_mecr( sock );
}
clock = cpufreq_get(0);
/* Fixme: MECR is not pre-empt safe. */
mecr = MECR;
if (map->flags & MAP_ATTRIB) {
MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
skt->speed_attr = speed;
} else {
MECR_BSM_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
skt->speed_mem = speed;
}
DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
__FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
sock, MECR_BSIO_GET(mecr, sock));
MECR = mecr;
} }
start = (map->flags & MAP_ATTRIB) ? skt->phys_attr : skt->phys_mem; start = (map->flags & MAP_ATTRIB) ? skt->phys_attr : skt->phys_mem;
...@@ -857,20 +883,10 @@ static struct pccard_operations sa1100_pcmcia_operations = { ...@@ -857,20 +883,10 @@ static struct pccard_operations sa1100_pcmcia_operations = {
static void sa1100_pcmcia_update_mecr(unsigned int clock) static void sa1100_pcmcia_update_mecr(unsigned int clock)
{ {
unsigned int sock; unsigned int sock;
unsigned long mecr = MECR;
for(sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock){
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
MECR_BSIO_SET(mecr, sock, for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) {
sa1100_pcmcia_mecr_bs(skt->speed_io, clock)); sa1100_pcmcia_set_mecr( sock );
MECR_BSA_SET(mecr, sock,
sa1100_pcmcia_mecr_bs(skt->speed_attr, clock));
MECR_BSM_SET(mecr, sock,
sa1100_pcmcia_mecr_bs(skt->speed_mem, clock));
} }
MECR = mecr;
} }
/* sa1100_pcmcia_notifier() /* sa1100_pcmcia_notifier()
...@@ -929,8 +945,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops) ...@@ -929,8 +945,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
struct pcmcia_init pcmcia_init; struct pcmcia_init pcmcia_init;
struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK]; struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
struct pcmcia_state_array state_array; struct pcmcia_state_array state_array;
unsigned int i, clock; unsigned int i;
unsigned long mecr;
int ret; int ret;
/* /*
...@@ -941,6 +956,13 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops) ...@@ -941,6 +956,13 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
pcmcia_low_level = ops; pcmcia_low_level = ops;
/*
* set default MECR calculation if the board specific
* code did not specify one...
*/
if (!pcmcia_low_level->socket_get_timing)
pcmcia_low_level->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
pcmcia_init.handler = sa1100_pcmcia_interrupt; pcmcia_init.handler = sa1100_pcmcia_interrupt;
ret = ops->init(&pcmcia_init); ret = ops->init(&pcmcia_init);
if (ret < 0) { if (ret < 0) {
...@@ -967,10 +989,6 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops) ...@@ -967,10 +989,6 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
* We initialize the MECR to default values here, because we are * We initialize the MECR to default values here, because we are
* not guaranteed to see a SetIOMap operation at runtime. * not guaranteed to see a SetIOMap operation at runtime.
*/ */
mecr = 0;
clock = cpufreq_get(0);
for (i = 0; i < sa1100_pcmcia_socket_count; i++) { for (i = 0; i < sa1100_pcmcia_socket_count; i++) {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
struct pcmcia_irq_info irq_info; struct pcmcia_irq_info irq_info;
...@@ -1000,13 +1018,9 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops) ...@@ -1000,13 +1018,9 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
goto out_err; goto out_err;
} }
MECR_FAST_SET(mecr, i, 0); sa1100_pcmcia_set_mecr( i );
MECR_BSIO_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_io, clock));
MECR_BSA_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_attr, clock));
MECR_BSM_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_mem, clock));
} }
MECR = mecr;
/* Only advertise as many sockets as we can detect */ /* Only advertise as many sockets as we can detect */
ret = register_ss_entry(sa1100_pcmcia_socket_count, ret = register_ss_entry(sa1100_pcmcia_socket_count,
......
...@@ -69,6 +69,12 @@ struct pcmcia_low_level { ...@@ -69,6 +69,12 @@ struct pcmcia_low_level {
* Disable card status IRQs and PCMCIA bus on suspend. * Disable card status IRQs and PCMCIA bus on suspend.
*/ */
int (*socket_suspend)(int sock); int (*socket_suspend)(int sock);
/*
* Calculate MECR timing clock wait states
*/
int (*socket_get_timing)(unsigned int sock, unsigned int cpu_speed,
unsigned int cmd_time );
}; };
extern int sa1100_register_pcmcia(struct pcmcia_low_level *); extern int sa1100_register_pcmcia(struct pcmcia_low_level *);
......
...@@ -17,29 +17,34 @@ ...@@ -17,29 +17,34 @@
* will stop our MCLK signal (which provides the clock for the glue * will stop our MCLK signal (which provides the clock for the glue
* logic, and therefore the timer interrupt). * logic, and therefore the timer interrupt).
* *
* Instead, we spin, waiting for either hlt_counter or need_resched() * Instead, we spin, polling the IRQ_STAT register for the occurrence
* to be set. If we have been spinning for 2cs, then we drop the * of any interrupt with core clock down to the memory clock.
* core clock down to the memory clock.
*/ */
static void arch_idle(void) static void arch_idle(void)
{ {
unsigned long start_idle; const char *irq_stat = (char *)0xff000000;
long flags;
start_idle = jiffies; if (!hlt_counter)
return;
do { do {
if (need_resched() || hlt_counter) /* disable interrupts */
goto slow_out; cli();
} while (time_before(jiffies, start_idle + HZ/50)); /* check need_resched here to avoid races */
if (need_resched()) {
cpu_do_idle(IDLE_CLOCK_SLOW); sti();
return;
while (!need_resched() && !hlt_counter) { }
/* do nothing slowly */ /* disable clock switching */
} asm volatile ("mcr%? p15, 0, ip, c15, c2, 2");
/* wait for an interrupt to occur */
cpu_do_idle(IDLE_CLOCK_FAST); while (!*irq_stat);
slow_out: /* enable clock switching */
asm volatile ("mcr%? p15, 0, ip, c15, c1, 2");
/* allow the interrupt to happen */
sti();
} while (!need_resched());
} }
#define arch_reset(mode) cpu_reset(0x80000000) #define arch_reset(mode) cpu_reset(0x80000000)
......
...@@ -107,18 +107,12 @@ extern struct processor { ...@@ -107,18 +107,12 @@ extern struct processor {
*/ */
void (*set_pte)(pte_t *ptep, pte_t pte); void (*set_pte)(pte_t *ptep, pte_t pte);
} pgtable; } pgtable;
struct { /* other */
void (*clear_user_page)(void *page, unsigned long u_addr);
void (*copy_user_page)(void *to, void *from, unsigned long u_addr);
} misc;
} processor; } processor;
extern const struct processor arm6_processor_functions; extern const struct processor arm6_processor_functions;
extern const struct processor arm7_processor_functions; extern const struct processor arm7_processor_functions;
extern const struct processor sa110_processor_functions; extern const struct processor sa110_processor_functions;
#define cpu_data_abort(pc) processor._data_abort(pc)
#define cpu_check_bugs() processor._check_bugs() #define cpu_check_bugs() processor._check_bugs()
#define cpu_proc_init() processor._proc_init() #define cpu_proc_init() processor._proc_init()
#define cpu_proc_fin() processor._proc_fin() #define cpu_proc_fin() processor._proc_fin()
...@@ -141,9 +135,6 @@ extern const struct processor sa110_processor_functions; ...@@ -141,9 +135,6 @@ extern const struct processor sa110_processor_functions;
#define cpu_set_pmd(pmdp, pmd) processor.pgtable.set_pmd(pmdp, pmd) #define cpu_set_pmd(pmdp, pmd) processor.pgtable.set_pmd(pmdp, pmd)
#define cpu_set_pte(ptep, pte) processor.pgtable.set_pte(ptep, pte) #define cpu_set_pte(ptep, pte) processor.pgtable.set_pte(ptep, pte)
#define cpu_copy_user_page(to,from,uaddr) processor.misc.copy_user_page(to,from,uaddr)
#define cpu_clear_user_page(page,uaddr) processor.misc.clear_user_page(page,uaddr)
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd))) #define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
#define cpu_get_pgd() \ #define cpu_get_pgd() \
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* function pointers for this lot. Otherwise, we can optimise the * function pointers for this lot. Otherwise, we can optimise the
* table away. * table away.
*/ */
#define cpu_data_abort __cpu_fn(CPU_ABRT,_abort)
#define cpu_check_bugs __cpu_fn(CPU_NAME,_check_bugs) #define cpu_check_bugs __cpu_fn(CPU_NAME,_check_bugs)
#define cpu_proc_init __cpu_fn(CPU_NAME,_proc_init) #define cpu_proc_init __cpu_fn(CPU_NAME,_proc_init)
#define cpu_proc_fin __cpu_fn(CPU_NAME,_proc_fin) #define cpu_proc_fin __cpu_fn(CPU_NAME,_proc_fin)
...@@ -40,8 +39,6 @@ ...@@ -40,8 +39,6 @@
#define cpu_set_pgd __cpu_fn(CPU_NAME,_set_pgd) #define cpu_set_pgd __cpu_fn(CPU_NAME,_set_pgd)
#define cpu_set_pmd __cpu_fn(CPU_NAME,_set_pmd) #define cpu_set_pmd __cpu_fn(CPU_NAME,_set_pmd)
#define cpu_set_pte __cpu_fn(CPU_NAME,_set_pte) #define cpu_set_pte __cpu_fn(CPU_NAME,_set_pte)
#define cpu_copy_user_page __cpu_fn(MMU_ARCH,_copy_user_page)
#define cpu_clear_user_page __cpu_fn(MMU_ARCH,_clear_user_page)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -74,9 +71,6 @@ extern void cpu_set_pgd(unsigned long pgd_phys); ...@@ -74,9 +71,6 @@ extern void cpu_set_pgd(unsigned long pgd_phys);
extern void cpu_set_pmd(pmd_t *pmdp, pmd_t pmd); extern void cpu_set_pmd(pmd_t *pmdp, pmd_t pmd);
extern void cpu_set_pte(pte_t *ptep, pte_t pte); extern void cpu_set_pte(pte_t *ptep, pte_t pte);
extern void cpu_copy_user_page(void *to, void *from, unsigned long u_addr);
extern void cpu_clear_user_page(void *page, unsigned long u_addr);
extern volatile void cpu_reset(unsigned long addr); extern volatile void cpu_reset(unsigned long addr);
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd))) #define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
......
...@@ -24,14 +24,21 @@ ...@@ -24,14 +24,21 @@
#endif #endif
#define __glue(name,fn) ____glue(name,fn) #define __glue(name,fn) ____glue(name,fn)
/*
* Select MMU TLB handling.
*/
/* /*
* ARMv3 MMU * MMU TLB Model
* =============
*
* We have the following to choose from:
* v3 - ARMv3
* v4 - ARMv4 without write buffer
* v4wb - ARMv4 with write buffer without I TLB flush entry instruction
* v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
*/ */
#undef _TLB #undef _TLB
#undef MULTI_TLB
#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
# ifdef _TLB # ifdef _TLB
# define MULTI_TLB 1 # define MULTI_TLB 1
...@@ -40,9 +47,6 @@ ...@@ -40,9 +47,6 @@
# endif # endif
#endif #endif
/*
* ARMv4 MMU without write buffer
*/
#if defined(CONFIG_CPU_ARM720T) #if defined(CONFIG_CPU_ARM720T)
# ifdef _TLB # ifdef _TLB
# define MULTI_TLB 1 # define MULTI_TLB 1
...@@ -51,9 +55,6 @@ ...@@ -51,9 +55,6 @@
# endif # endif
#endif #endif
/*
* ARMv4 MMU with write buffer, with invalidate I TLB entry instruction
*/
#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ #if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \ defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \
defined(CONFIG_CPU_XSCALE) defined(CONFIG_CPU_XSCALE)
...@@ -64,9 +65,6 @@ ...@@ -64,9 +65,6 @@
# endif # endif
#endif #endif
/*
* ARMv4 MMU with write buffer, without invalidate I TLB entry instruction
*/
#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) #if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
# ifdef _TLB # ifdef _TLB
# define MULTI_TLB 1 # define MULTI_TLB 1
...@@ -75,4 +73,134 @@ ...@@ -75,4 +73,134 @@
# endif # endif
#endif #endif
#ifndef _TLB
#error Unknown TLB model
#endif
/*
* Data Abort Model
* ================
*
* We have the following to choose from:
* arm6 - ARM6 style
* arm7 - ARM7 style
* v4_early - ARMv4 without Thumb early abort handler
* v4t_late - ARMv4 with Thumb late abort handler
* v4t_early - ARMv4 with Thumb early abort handler
* v5ej_early - ARMv5 with Thumb and Java early abort handler
*/
#undef CPU_ABORT_HANDLER
#undef MULTI_ABORT
#if defined(CONFIG_CPU_ARM610)
# ifdef CPU_ABORT_HANDLER
# define MULTI_ABORT 1
# else
# define CPU_ABORT_HANDLER cpu_arm6_data_abort
# endif
#endif
#if defined(CONFIG_CPU_ARM710)
# ifdef CPU_ABORT_HANDLER
# define MULTI_ABORT 1
# else
# define CPU_ABORT_HANDLER cpu_arm7_data_abort
# endif
#endif
#if defined(CONFIG_CPU_ARM720T)
# ifdef CPU_ABORT_HANDLER
# define MULTI_ABORT 1
# else
# define CPU_ABORT_HANDLER v4t_late_abort
# endif
#endif
#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
# ifdef CPU_ABORT_HANDLER
# define MULTI_ABORT 1
# else
# define CPU_ABORT_HANDLER v4_early_abort
# endif
#endif
#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
defined(CONFIG_CPU_ARM1020) || defined(CONFIG_CPU_XSCALE)
# ifdef CPU_ABORT_HANDLER
# define MULTI_ABORT 1
# else
# define CPU_ABORT_HANDLER v4t_early_abort
# endif
#endif
#if defined(CONFIG_CPU_ARM926T)
# ifdef CPU_ABORT_HANDLER
# define MULTI_ABORT 1
# else
# define CPU_ABORT_HANDLER v5ej_early_abort
# endif
#endif
#ifndef CPU_ABORT_HANDLER
#error Unknown data abort handler type
#endif
/*
* User Space Model
* ================
*
* This section selects the correct set of functions for dealing with
* page-based copying and clearing for user space for the particular
* processor(s) we're building for.
*
* We have the following to choose from:
* v3 - ARMv3
* v4 - ARMv4 without minicache
* v4_mc - ARMv4 with minicache
* v5te_mc - ARMv5TE with minicache
*/
#undef _USER
#undef MULTI_USER
#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
# ifdef _USER
# define MULTI_USER 1
# else
# define _USER v3
# endif
#endif
#if defined(CONFIG_CPU_ARM720T) || defined(CONFIG_CPU_ARM920T) || \
defined(CONFIG_CPU_ARM922T) || defined(CONFIG_CPU_ARM926T) || \
defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_ARM1020)
# ifdef _USER
# define MULTI_USER 1
# else
# define _USER v4
# endif
#endif
#if defined(CONFIG_CPU_SA1100)
# ifdef _USER
# define MULTI_USER 1
# else
# define _USER v4_mc
# endif
#endif
#if defined(CONFIG_CPU_XSCALE)
# ifdef _USER
# define MULTI_USER 1
# else
# define _USER v5te_mc
# endif
#endif
#ifndef _USER
#error Unknown user operations model
#endif
#endif #endif
...@@ -19,12 +19,6 @@ struct hw_pci { ...@@ -19,12 +19,6 @@ struct hw_pci {
/* Setup bus resources */ /* Setup bus resources */
void (*setup_resources)(struct resource **); void (*setup_resources)(struct resource **);
/*
* This is the offset of PCI memory base registers
* to physical memory.
*/
unsigned long mem_offset;
/* IRQ swizzle */ /* IRQ swizzle */
u8 (*swizzle)(struct pci_dev *dev, u8 *pin); u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
......
#ifndef _ASMARM_PAGE_H #ifndef _ASMARM_PAGE_H
#define _ASMARM_PAGE_H #define _ASMARM_PAGE_H
#include <asm/proc/page.h> #include <linux/config.h>
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#define STRICT_MM_TYPECHECKS #include <asm/glue.h>
#define clear_page(page) memzero((void *)(page), PAGE_SIZE) struct cpu_user_fns {
extern void copy_page(void *to, void *from); void (*cpu_clear_user_page)(void *p, unsigned long user);
void (*cpu_copy_user_page)(void *to, const void *from,
unsigned long user);
};
#ifdef MULTI_USER
extern struct cpu_user_fns cpu_user;
#define __cpu_clear_user_page cpu_user.cpu_clear_user_page
#define __cpu_copy_user_page cpu_user.cpu_copy_user_page
#else
#define __cpu_clear_user_page __glue(_USER,_clear_user_page)
#define __cpu_copy_user_page __glue(_USER,_copy_user_page)
extern void __cpu_clear_user_page(void *p, unsigned long user);
extern void __cpu_copy_user_page(void *to, const void *from,
unsigned long user);
#endif
#define clear_user_page(addr,vaddr) \ #define clear_user_page(addr,vaddr) \
do { \ do { \
preempt_disable(); \ preempt_disable(); \
cpu_clear_user_page(addr, vaddr); \ __cpu_clear_user_page(addr, vaddr); \
preempt_enable(); \ preempt_enable(); \
} while (0) } while (0)
#define copy_user_page(to,from,vaddr) \ #define copy_user_page(to,from,vaddr) \
do { \ do { \
preempt_disable(); \ preempt_disable(); \
cpu_copy_user_page(to, from, vaddr); \ __cpu_copy_user_page(to, from, vaddr); \
preempt_enable(); \ preempt_enable(); \
} while (0) } while (0)
#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
extern void copy_page(void *to, void *from);
#undef STRICT_MM_TYPECHECKS
#ifdef STRICT_MM_TYPECHECKS #ifdef STRICT_MM_TYPECHECKS
/* /*
* These are used to make use of C type-checking.. * These are used to make use of C type-checking..
*/ */
typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t; typedef struct { unsigned long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte) #define pte_val(x) ((x).pte)
#define pmd_val(x) ((x).pmd) #define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot) #define pgprot_val(x) ((x).pgprot)
#define __pte(x) ((pte_t) { (x) } ) #define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } ) #define __pmd(x) ((pmd_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } )
#else #else
...@@ -53,25 +71,29 @@ typedef struct { unsigned long pgprot; } pgprot_t; ...@@ -53,25 +71,29 @@ typedef struct { unsigned long pgprot; } pgprot_t;
*/ */
typedef unsigned long pte_t; typedef unsigned long pte_t;
typedef unsigned long pmd_t; typedef unsigned long pmd_t;
typedef unsigned long pgd_t;
typedef unsigned long pgprot_t; typedef unsigned long pgprot_t;
#define pte_val(x) (x) #define pte_val(x) (x)
#define pmd_val(x) (x) #define pmd_val(x) (x)
#define pgd_val(x) (x)
#define pgprot_val(x) (x) #define pgprot_val(x) (x)
#define __pte(x) (x) #define __pte(x) (x)
#define __pmd(x) (x) #define __pmd(x) (x)
#define __pgd(x) (x)
#define __pgprot(x) (x) #define __pgprot(x) (x)
#endif #endif /* STRICT_MM_TYPECHECKS */
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
#include <asm/proc/page.h>
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
/* to align the pointer to the (next) page boundary */ /* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
#ifdef __KERNEL__
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef CONFIG_DEBUG_BUGVERBOSE #ifdef CONFIG_DEBUG_BUGVERBOSE
...@@ -105,7 +127,6 @@ static inline int get_order(unsigned long size) ...@@ -105,7 +127,6 @@ static inline int get_order(unsigned long size)
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#include <linux/config.h>
#include <asm/arch/memory.h> #include <asm/arch/memory.h>
#define __pa(x) __virt_to_phys((unsigned long)(x)) #define __pa(x) __virt_to_phys((unsigned long)(x))
...@@ -120,6 +141,6 @@ static inline int get_order(unsigned long size) ...@@ -120,6 +141,6 @@ static inline int get_order(unsigned long size)
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#endif #endif /* __KERNEL__ */
#endif #endif
/* /*
* linux/include/asm-arm/pgtable.h * linux/include/asm-arm/pgtable.h
* *
* Copyright (C) 2000-2001 Russell King * Copyright (C) 2000-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -19,7 +19,11 @@ ...@@ -19,7 +19,11 @@
* PGDIR_SHIFT determines what a third-level page table entry can map * PGDIR_SHIFT determines what a third-level page table entry can map
*/ */
#define PMD_SHIFT 20 #define PMD_SHIFT 20
#ifdef CONFIG_CPU_32
#define PGDIR_SHIFT 21
#else
#define PGDIR_SHIFT 20 #define PGDIR_SHIFT 20
#endif
#define LIBRARY_TEXT_START 0x0c000000 #define LIBRARY_TEXT_START 0x0c000000
...@@ -93,7 +97,6 @@ extern struct page *empty_zero_page; ...@@ -93,7 +97,6 @@ extern struct page *empty_zero_page;
#define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_present(pmd) (pmd_val(pmd)) #define pmd_present(pmd) (pmd_val(pmd))
#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
/* /*
* Permanent address of a page. We never have highmem, so this is trivial. * Permanent address of a page. We never have highmem, so this is trivial.
...@@ -106,18 +109,10 @@ extern struct page *empty_zero_page; ...@@ -106,18 +109,10 @@ extern struct page *empty_zero_page;
*/ */
static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
{ {
pte_t pte; return __pte(physpage | pgprot_val(pgprot));
pte_val(pte) = physpage | pgprot_val(pgprot);
return pte;
} }
#define mk_pte(page,pgprot) \ #define mk_pte(page,pgprot) mk_pte_phys(__pa(page_address(page)), pgprot)
({ \
pte_t __pte; \
pte_val(__pte) = __pa(page_address(page)) + \
pgprot_val(pgprot); \
__pte; \
})
/* /*
* The "pgd_xxx()" functions here are trivial for a folded two-level * The "pgd_xxx()" functions here are trivial for a folded two-level
...@@ -127,7 +122,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) ...@@ -127,7 +122,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
#define pgd_none(pgd) (0) #define pgd_none(pgd) (0)
#define pgd_bad(pgd) (0) #define pgd_bad(pgd) (0)
#define pgd_present(pgd) (1) #define pgd_present(pgd) (1)
#define pgd_clear(pgdp) #define pgd_clear(pgdp) do { } while (0)
#define page_pte_prot(page,prot) mk_pte(page, prot) #define page_pte_prot(page,prot) mk_pte(page, prot)
#define page_pte(page) mk_pte(page, __pgprot(0)) #define page_pte(page) mk_pte(page, __pgprot(0))
...@@ -147,15 +142,6 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) ...@@ -147,15 +142,6 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
/* Find an entry in the third-level page table.. */ /* Find an entry in the third-level page table.. */
#define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
#define pmd_page(dir) ((struct page *)__pmd_page(dir))
#define __pte_offset(dir, addr) ((pte_t *)__pmd_page(*(dir)) + __pte_index(addr))
#define pte_offset_kernel __pte_offset
#define pte_offset_map __pte_offset
#define pte_offset_map_nested __pte_offset
#define pte_unmap(pte) do { } while (0)
#define pte_unmap_nested(pte) do { } while (0)
#include <asm/proc/pgtable.h> #include <asm/proc/pgtable.h>
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
...@@ -182,8 +168,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; ...@@ -182,8 +168,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#include <asm-generic/pgtable.h> #include <asm-generic/pgtable.h>
extern void pgtable_cache_init(void);
/* /*
* remap a physical address `phys' of size `size' with page protection `prot' * remap a physical address `phys' of size `size' with page protection `prot'
* into virtual address `from' * into virtual address `from'
......
/* /*
* linux/include/asm-arm/proc-armo/page.h * linux/include/asm-arm/proc-armo/page.h
* *
* Copyright (C) 1995, 1996 Russell King * Copyright (C) 1995-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -21,4 +21,20 @@ ...@@ -21,4 +21,20 @@
#define EXEC_PAGESIZE 32768 #define EXEC_PAGESIZE 32768
#ifndef __ASSEMBLY__
#ifdef STRICT_MM_TYPECHECKS
typedef struct { unsigned long pgd; } pgd_t;
#define pgd_val(x) ((x).pgd)
#else
typedef unsigned long pgd_t;
#define pgd_val(x) (x)
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ASM_PROC_PAGE_H */ #endif /* __ASM_PROC_PAGE_H */
/* /*
* linux/include/asm-arm/proc-armo/pgalloc.h * linux/include/asm-arm/proc-armo/pgalloc.h
* *
* Copyright (C) 2001 Russell King * Copyright (C) 2001-2002 Russell King
* *
* Page table allocation/freeing primitives for 26-bit ARM processors. * Page table allocation/freeing primitives for 26-bit ARM processors.
*/ */
/* unfortunately, this includes linux/mm.h and the rest of the universe. */
#include <linux/slab.h> #include <linux/slab.h>
extern kmem_cache_t *pte_cache; extern kmem_cache_t *pte_cache;
/* static inline pte_t *
* Allocate one PTE table. pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
*
* Note that we keep the processor copy of the PTE entries separate
* from the Linux copy. The processor copies are offset by -PTRS_PER_PTE
* words from the Linux copy.
*/
static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{ {
return kmem_cache_alloc(pte_cache, GFP_KERNEL); return kmem_cache_alloc(pte_cache, GFP_KERNEL);
} }
/* static inline void pte_free_kernel(pte_t *pte)
* Free one PTE table.
*/
static inline void pte_free_slow(pte_t *pte)
{ {
if (pte) if (pte)
kmem_cache_free(pte_cache, pte); kmem_cache_free(pte_cache, pte);
...@@ -39,9 +29,16 @@ static inline void pte_free_slow(pte_t *pte) ...@@ -39,9 +29,16 @@ static inline void pte_free_slow(pte_t *pte)
* If 'mm' is the init tasks mm, then we are doing a vmalloc, and we * If 'mm' is the init tasks mm, then we are doing a vmalloc, and we
* need to set stuff up correctly for it. * need to set stuff up correctly for it.
*/ */
#define pmd_populate(mm,pmdp,pte) \ static inline void
do { \ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
set_pmd(pmdp, __mk_pmd(pte, _PAGE_TABLE)); \ {
} while (0) set_pmd(pmdp, __mk_pmd(ptep, _PAGE_TABLE));
}
/*
* We use the old 2.5.5-rmk1 hack for this.
* This is not truely correct, but should be functional.
*/
#define pte_alloc_one(mm,addr) ((struct page *)pte_alloc_one_kernel(mm,addr))
#define pte_free(pte) pte_free_kernel((pte_t *)pte)
#define pmd_populate(mm,pmdp,ptep) pmd_populate_kernel(mm,pmdp,(pte_t *)ptep)
/* /*
* linux/include/asm-arm/proc-armo/pgtable.h * linux/include/asm-arm/proc-armo/pgtable.h
* *
* Copyright (C) 1995-2001 Russell King * Copyright (C) 1995-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define pmd_bad(pmd) ((pmd_val(pmd) & 0xfc000002)) #define pmd_bad(pmd) ((pmd_val(pmd) & 0xfc000002))
#define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd)) #define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd))
#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot) static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
{ {
...@@ -48,6 +49,12 @@ static inline unsigned long pmd_page(pmd_t pmd) ...@@ -48,6 +49,12 @@ static inline unsigned long pmd_page(pmd_t pmd)
return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE); return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE);
} }
#define pte_offset_kernel(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
#define pte_offset_map(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
#define pte_offset_map_nested(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
#define pte_unmap(pte) do { } while (0)
#define pte_unmap_nested(pte) do { } while (0)
#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
#define _PAGE_PRESENT 0x01 #define _PAGE_PRESENT 0x01
...@@ -89,11 +96,11 @@ static inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= ~_PAGE_NOT_USE ...@@ -89,11 +96,11 @@ static inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= ~_PAGE_NOT_USE
static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) &= ~_PAGE_CLEAN; return pte; } static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) &= ~_PAGE_CLEAN; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) &= ~_PAGE_OLD; return pte; } static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) &= ~_PAGE_OLD; return pte; }
#define pte_alloc_kernel pte_alloc
/* /*
* We don't store cache state bits in the page table here. * We don't store cache state bits in the page table here.
*/ */
#define pgprot_noncached(prot) (prot) #define pgprot_noncached(prot) (prot)
extern void pgtable_cache_init(void);
#endif /* __ASM_PROC_PGTABLE_H */ #endif /* __ASM_PROC_PGTABLE_H */
/* /*
* linux/include/asm-arm/proc-armv/cache.h * linux/include/asm-arm/proc-armv/cache.h
* *
* Copyright (C) 1999-2001 Russell King * Copyright (C) 1999-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -134,7 +134,8 @@ static __inline__ void flush_page_to_ram(struct page *page) ...@@ -134,7 +134,8 @@ static __inline__ void flush_page_to_ram(struct page *page)
#define clean_dcache_range(_s,_e) cpu_dcache_clean_range((_s),(_e)) #define clean_dcache_range(_s,_e) cpu_dcache_clean_range((_s),(_e))
#define flush_dcache_range(_s,_e) cpu_cache_clean_invalidate_range((_s),(_e),0) #define flush_dcache_range(_s,_e) cpu_cache_clean_invalidate_range((_s),(_e),0)
#define mapping_mapped(map) ((map)->i_mmap || (map)->i_mmap_shared) #define mapping_mapped(map) (!list_empty(&(map)->i_mmap) || \
!list_empty(&(map)->i_mmap_shared))
/* /*
* flush_dcache_page is used when the kernel has written to the page * flush_dcache_page is used when the kernel has written to the page
...@@ -204,7 +205,7 @@ static inline void flush_icache_page(struct vm_area_struct *vma, struct page *pa ...@@ -204,7 +205,7 @@ static inline void flush_icache_page(struct vm_area_struct *vma, struct page *pa
* TLB Management * TLB Management
* ============== * ==============
* *
* The arch/arm/mm/tlb-*.S files implement this methods. * The arch/arm/mm/tlb-*.S files implement these methods.
* *
* The TLB specific code is expected to perform whatever tests it * The TLB specific code is expected to perform whatever tests it
* needs to determine if it should invalidate the TLB for each * needs to determine if it should invalidate the TLB for each
......
/* /*
* linux/include/asm-arm/proc-armv/page.h * linux/include/asm-arm/proc-armv/page.h
* *
* Copyright (C) 1995, 1996 Russell King * Copyright (C) 1995-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -15,4 +15,23 @@ ...@@ -15,4 +15,23 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef __ASSEMBLY__
#ifdef STRICT_MM_TYPECHECKS
typedef struct {
unsigned long pgd0;
unsigned long pgd1;
} pgd_t;
#define pgd_val(x) ((x).pgd0)
#else
typedef unsigned long pgd_t[2];
#define pgd_val(x) ((x)[0])
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ASM_PROC_PAGE_H */ #endif /* __ASM_PROC_PAGE_H */
/* /*
* linux/include/asm-arm/proc-armv/pgalloc.h * linux/include/asm-arm/proc-armv/pgalloc.h
* *
* Copyright (C) 2001 Russell King * Copyright (C) 2001-2002 Russell King
* *
* Page table allocation/freeing primitives for 32-bit ARM processors. * Page table allocation/freeing primitives for 32-bit ARM processors.
*/ */
#include "pgtable.h"
/* unfortunately, this includes linux/mm.h and the rest of the universe. */
#include <linux/slab.h>
extern kmem_cache_t *pte_cache;
/* /*
* Allocate one PTE table. * Allocate one PTE table.
* *
* Note that we keep the processor copy of the PTE entries separate * This actually allocates two hardware PTE tables, but we wrap this up
* from the Linux copy. The processor copies are offset by -PTRS_PER_PTE * into one table thus:
* words from the Linux copy. *
* +------------+
* | h/w pt 0 |
* +------------+
* | h/w pt 1 |
* +------------+
* | Linux pt 0 |
* +------------+
* | Linux pt 1 |
* +------------+
*/ */
static inline pte_t * static inline pte_t *
pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
{ {
int count = 0;
pte_t *pte; pte_t *pte;
pte = kmem_cache_alloc(pte_cache, GFP_KERNEL); do {
if (pte) pte = (pte_t *)__get_free_page(GFP_KERNEL);
if (!pte) {
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ);
}
} while (!pte && (count++ < 10));
if (pte) {
clear_page(pte);
clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE);
pte += PTRS_PER_PTE; pte += PTRS_PER_PTE;
}
return pte; return pte;
} }
static inline struct page * static inline struct page *
pte_alloc_one(struct mm_struct *mm, unsigned long addr) pte_alloc_one(struct mm_struct *mm, unsigned long addr)
{ {
pte_t *pte; struct page *pte;
int count = 0;
pte = kmem_cache_alloc(pte_cache, GFP_KERNEL); do {
if (pte) pte = alloc_pages(GFP_KERNEL, 0);
pte += PTRS_PER_PTE; if (!pte) {
return (struct page *)pte; current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ);
}
} while (!pte && (count++ < 10));
if (pte) {
void *page = page_address(pte);
clear_page(page);
clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE);
}
return pte;
} }
/* /*
...@@ -47,34 +76,49 @@ static inline void pte_free_kernel(pte_t *pte) ...@@ -47,34 +76,49 @@ static inline void pte_free_kernel(pte_t *pte)
{ {
if (pte) { if (pte) {
pte -= PTRS_PER_PTE; pte -= PTRS_PER_PTE;
kmem_cache_free(pte_cache, pte); free_page((unsigned long)pte);
} }
} }
static inline void pte_free(struct page *pte) static inline void pte_free(struct page *pte)
{ {
pte_t *_pte = (pte_t *)pte; __free_page(pte);
if (pte) {
_pte -= PTRS_PER_PTE;
kmem_cache_free(pte_cache, _pte);
}
} }
/* /*
* Populate the pmdp entry with a pointer to the pte. This pmd is part * Populate the pmdp entry with a pointer to the pte. This pmd is part
* of the mm address space. * of the mm address space.
* *
* If 'mm' is the init tasks mm, then we are doing a vmalloc, and we * Ensure that we always set both PMD entries.
* need to set stuff up correctly for it.
*/ */
#define pmd_populate_kernel(mm,pmdp,pte) \ static inline void
do { \ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
BUG_ON(mm != &init_mm); \ {
set_pmd(pmdp, __mk_pmd(pte, _PAGE_KERNEL_TABLE));\ unsigned long pte_ptr = (unsigned long)ptep;
} while (0) pmd_t pmd;
#define pmd_populate(mm,pmdp,pte) \ BUG_ON(mm != &init_mm);
do { \
BUG_ON(mm == &init_mm); \ /*
set_pmd(pmdp, __mk_pmd(pte, _PAGE_USER_TABLE)); \ * The pmd must be loaded with the physical
} while (0) * address of the PTE table
*/
pte_ptr -= PTRS_PER_PTE * sizeof(void *);
pmd_val(pmd) = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
set_pmd(pmdp, pmd);
pmd_val(pmd) += 256 * sizeof(pte_t);
set_pmd(pmdp + 1, pmd);
}
static inline void
pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
{
pmd_t pmd;
BUG_ON(mm == &init_mm);
pmd_val(pmd) = __pa(page_address(ptep)) | _PAGE_USER_TABLE;
set_pmd(pmdp, pmd);
pmd_val(pmd) += 256 * sizeof(pte_t);
set_pmd(pmdp + 1, pmd);
}
/* /*
* linux/include/asm-arm/proc-armv/pgtable.h * linux/include/asm-arm/proc-armv/pgtable.h
* *
* Copyright (C) 1995-2001 Russell King * Copyright (C) 1995-2002 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -16,12 +16,17 @@ ...@@ -16,12 +16,17 @@
#define __ASM_PROC_PGTABLE_H #define __ASM_PROC_PGTABLE_H
/* /*
* entries per page directory level: they are two-level, so * We pull a couple of tricks here:
* we don't really have any PMD directory. * 1. We wrap the PMD into the PGD.
* 2. We lie about the size of the PTE and PGD.
* Even though we have 256 PTE entries and 4096 PGD entries, we tell
* Linux that we actually have 512 PTE entries and 2048 PGD entries.
* Each "Linux" PGD entry is made up of two hardware PGD entries, and
* each PTE table is actually two hardware PTE tables.
*/ */
#define PTRS_PER_PTE 256 #define PTRS_PER_PTE 512
#define PTRS_PER_PMD 1 #define PTRS_PER_PMD 1
#define PTRS_PER_PGD 4096 #define PTRS_PER_PGD 2048
/* /*
* Hardware page table definitions. * Hardware page table definitions.
...@@ -109,33 +114,30 @@ ...@@ -109,33 +114,30 @@
#define pmd_bad(pmd) (pmd_val(pmd) & 2) #define pmd_bad(pmd) (pmd_val(pmd) & 2)
#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp, pmd) #define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp, pmd)
static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot) static inline void pmd_clear(pmd_t *pmdp)
{ {
unsigned long pte_ptr = (unsigned long)ptep; set_pmd(pmdp, __pmd(0));
pmd_t pmd; set_pmd(pmdp + 1, __pmd(0));
pte_ptr -= PTRS_PER_PTE * sizeof(void *);
/*
* The pmd must be loaded with the physical
* address of the PTE table
*/
pmd_val(pmd) = __virt_to_phys(pte_ptr) | prot;
return pmd;
} }
static inline unsigned long __pmd_page(pmd_t pmd) static inline pte_t *pmd_page_kernel(pmd_t pmd)
{ {
unsigned long ptr; unsigned long ptr;
ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1); ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
ptr += PTRS_PER_PTE * sizeof(void *); ptr += PTRS_PER_PTE * sizeof(void *);
return __phys_to_virt(ptr); return __va(ptr);
} }
#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
#define pte_offset_kernel(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
#define pte_offset_map(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
#define pte_offset_map_nested(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
#define pte_unmap(pte) do { } while (0)
#define pte_unmap_nested(pte) do { } while (0)
#define set_pte(ptep, pte) cpu_set_pte(ptep,pte) #define set_pte(ptep, pte) cpu_set_pte(ptep,pte)
/* /*
...@@ -183,6 +185,8 @@ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); ...@@ -183,6 +185,8 @@ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG);
*/ */
#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE)) #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
#define pgtable_cache_init() do { } while (0)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __ASM_PROC_PGTABLE_H */ #endif /* __ASM_PROC_PGTABLE_H */
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
/* /*
* CPU_NAME - the prefix for CPU related functions * CPU_NAME - the prefix for CPU related functions
* CPU_ABRT - the prefix for the CPU abort decoding function
* MMU_ARCH - the prefix for copy_user_page/clear_user_page
*/ */
#ifdef CONFIG_CPU_32 #ifdef CONFIG_CPU_32
...@@ -40,8 +38,6 @@ ...@@ -40,8 +38,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_arm6 # define CPU_NAME cpu_arm6
# define CPU_ABRT cpu_arm6
# define MMU_ARCH armv3
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_ARM710 # ifdef CONFIG_CPU_ARM710
...@@ -50,8 +46,6 @@ ...@@ -50,8 +46,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_arm7 # define CPU_NAME cpu_arm7
# define CPU_ABRT cpu_arm7
# define MMU_ARCH armv3
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_ARM720T # ifdef CONFIG_CPU_ARM720T
...@@ -60,8 +54,6 @@ ...@@ -60,8 +54,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_arm720 # define CPU_NAME cpu_arm720
# define CPU_ABRT armv4t_late
# define MMU_ARCH armv4
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_ARM920T # ifdef CONFIG_CPU_ARM920T
...@@ -70,8 +62,6 @@ ...@@ -70,8 +62,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_arm920 # define CPU_NAME cpu_arm920
# define CPU_ABRT armv4t_early
# define MMU_ARCH armv4
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_ARM922T # ifdef CONFIG_CPU_ARM922T
...@@ -80,8 +70,6 @@ ...@@ -80,8 +70,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_arm922 # define CPU_NAME cpu_arm922
# define CPU_ABRT armv4t_early
# define MMU_ARCH armv4
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_ARM926T # ifdef CONFIG_CPU_ARM926T
...@@ -90,8 +78,6 @@ ...@@ -90,8 +78,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_arm926 # define CPU_NAME cpu_arm926
# define CPU_ABRT armv5ej_early
# define MMU_ARCH armv4
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_SA110 # ifdef CONFIG_CPU_SA110
...@@ -100,8 +86,6 @@ ...@@ -100,8 +86,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_sa110 # define CPU_NAME cpu_sa110
# define CPU_ABRT armv4_early
# define MMU_ARCH armv4
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_SA1100 # ifdef CONFIG_CPU_SA1100
...@@ -110,8 +94,6 @@ ...@@ -110,8 +94,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_sa1100 # define CPU_NAME cpu_sa1100
# define CPU_ABRT armv4_early
# define MMU_ARCH armv4_mc
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_ARM1020 # ifdef CONFIG_CPU_ARM1020
...@@ -120,8 +102,6 @@ ...@@ -120,8 +102,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_arm1020 # define CPU_NAME cpu_arm1020
# define CPU_ABRT armv4t_early
# define MMU_ARCH armv4
# endif # endif
# endif # endif
# ifdef CONFIG_CPU_XSCALE # ifdef CONFIG_CPU_XSCALE
...@@ -130,8 +110,6 @@ ...@@ -130,8 +110,6 @@
# define MULTI_CPU # define MULTI_CPU
# else # else
# define CPU_NAME cpu_xscale # define CPU_NAME cpu_xscale
# define CPU_ABRT armv4t_early
# define MMU_ARCH armv5te
# endif # endif
# endif # endif
#endif #endif
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/proc-fns.h> #include <asm/proc-fns.h>
struct cpu_tlb_fns; struct cpu_tlb_fns;
struct cpu_user_fns;
struct processor; struct processor;
struct proc_info_item { struct proc_info_item {
...@@ -32,21 +33,22 @@ struct proc_info_item { ...@@ -32,21 +33,22 @@ struct proc_info_item {
* arch/arm/mm/proc-*.S and arch/arm/kernel/head-armv.S * arch/arm/mm/proc-*.S and arch/arm/kernel/head-armv.S
*/ */
struct proc_info_list { struct proc_info_list {
unsigned int cpu_val; unsigned int cpu_val;
unsigned int cpu_mask; unsigned int cpu_mask;
unsigned long __cpu_mmu_flags; /* used by head-armv.S */ unsigned long __cpu_mmu_flags; /* used by head-armv.S */
unsigned long __cpu_flush; /* used by head-armv.S */ unsigned long __cpu_flush; /* used by head-armv.S */
const char *arch_name; const char *arch_name;
const char *elf_name; const char *elf_name;
unsigned int elf_hwcap; unsigned int elf_hwcap;
struct proc_info_item *info; struct proc_info_item *info;
struct processor *proc; struct processor *proc;
struct cpu_tlb_fns *tlb; struct cpu_tlb_fns *tlb;
struct cpu_user_fns *user;
}; };
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#define PROC_INFO_SZ 40 #define PROC_INFO_SZ 44
#define HWCAP_SWP 1 #define HWCAP_SWP 1
#define HWCAP_HALF 2 #define HWCAP_HALF 2
......
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