Commit ab0af3d4 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-rmk

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents ad49d6ba f05ee516
...@@ -6,7 +6,7 @@ Introduction ...@@ -6,7 +6,7 @@ Introduction
------------ ------------
The S3C2410 supports a low-power suspend mode, where the SDRAM is kept The S3C2410 supports a low-power suspend mode, where the SDRAM is kept
in Self-Refresh mode, and all but the esential peripheral blocks are in Self-Refresh mode, and all but the essential peripheral blocks are
powered down. For more information on how this works, please look powered down. For more information on how this works, please look
at the S3C2410 datasheets from Samsung. at the S3C2410 datasheets from Samsung.
...@@ -41,7 +41,7 @@ Machine Support ...@@ -41,7 +41,7 @@ Machine Support
--------------- ---------------
The machine specific functions must call the s3c2410_pm_init() function The machine specific functions must call the s3c2410_pm_init() function
to say that it's bootloader is capable of resuming. This can be as to say that its bootloader is capable of resuming. This can be as
simple as adding the following to the machine's definition: simple as adding the following to the machine's definition:
INITMACHINE(s3c2410_pm_init) INITMACHINE(s3c2410_pm_init)
...@@ -53,22 +53,22 @@ Machine Support ...@@ -53,22 +53,22 @@ Machine Support
saving the resume address, if your board requires it, then contact saving the resume address, if your board requires it, then contact
the maintainer and discuss what is required. the maintainer and discuss what is required.
Note, the origianal method of adding an late_initcall() is wrong, Note, the original method of adding an late_initcall() is wrong,
and will end up initialising all compiled machine's pm init! and will end up initialising all compiled machines' pm init!
Debugging Debugging
--------- ---------
There are several important things to rember when using PM suspend: There are several important things to remember when using PM suspend:
1) The uart drivers will disable the clocks to the UART blocks when 1) The uart drivers will disable the clocks to the UART blocks when
suspending, which means that use of printascii() or similar direct suspending, which means that use of printascii() or similar direct
access to the UARTs will cause the debug to stop. access to the UARTs will cause the debug to stop.
2) Whilst the pm code itself will attempt to re-enabled the UART clocks, 2) Whilst the pm code itself will attempt to re-enable the UART clocks,
care should be taken that any external clock sources that the UARTs care should be taken that any external clock sources that the UARTs
rely on are still enabled at that point rely on are still enabled at that point.
Configuration Configuration
......
...@@ -343,6 +343,50 @@ config ZBOOT_ROM_BSS ...@@ -343,6 +343,50 @@ config ZBOOT_ROM_BSS
while the decompressor is running. Unless you have special requirements, while the decompressor is running. Unless you have special requirements,
you should not change this value. you should not change this value.
config XIP_KERNEL
bool "Kernel Execute-In-Place from ROM"
depends on !ZBOOT_ROM
help
Execute-In-Place allows the kernel to run from non-volatile storage
directly addressable by the CPU, such as NOR flash. This saves RAM
space since the text section of the kernel is not loaded from flash
to RAM. Read-write sections, such as the data section and stack,
are still copied to RAM. The XIP kernel is not compressed since
it has to run directly from flash, so it will take more space to
store it. The flash address used to link the kernel object files,
and for storing it, is configuration dependent. Therefore, if you
say Y here, you must know the proper physical address where to
store the kernel image depending on your own flash memory usage.
Also note that the make target becomes "make xipImage" rather than
"make zImage" or "make Image". The final kernel binary to put in
ROM memory will be arch/arm/boot/xipImage.
If unsure, say N.
config XIP_PHYS_ADDR
hex "XIP Kernel Physical Location"
depends on XIP_KERNEL
default "0x00080000"
help
This is the physical address in your flash memory the kernel will
be linked for and stored to. This address is dependent on your
own flash usage.
Please note that, if you're using MTD, you must use a flash chip
that is NOT handled by MTD or the flash will be turned into non
data mode for status and query purposes which will instantaneously
crash the kernel.
MTD can however be used with a XIP kernel on the same flash chip
but only if the flash memory supports multiple partitions in
hardware, like with the Intel K3 flash parts, and only if the
kernel is not stored within the firrst hardware partition of the
chip.
In any case, make sure that MTD support is configured out for
the first attempt.
if (ARCH_SA1100 || ARCH_INTEGRATOR) if (ARCH_SA1100 || ARCH_INTEGRATOR)
config CPU_FREQ config CPU_FREQ
......
...@@ -58,14 +58,13 @@ tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) ...@@ -58,14 +58,13 @@ tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110)
tune-$(CONFIG_CPU_V6) :=-mtune=strongarm tune-$(CONFIG_CPU_V6) :=-mtune=strongarm
# Need -Uarm for gcc < 3.x # Need -Uarm for gcc < 3.x
CFLAGS +=-mapcs-32 $(arch-y) $(tune-y) $(call cc-option,-malignment-traps,-mshort-load-bytes) -msoft-float -Uarm CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
AFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -msoft-float CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
CHECKFLAGS += -D__arm__ CHECKFLAGS += -D__arm__
#Default value #Default value
DATAADDR := .
head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
textaddr-y := 0xC0008000 textaddr-y := 0xC0008000
...@@ -109,6 +108,16 @@ export CFLAGS_3c589_cs.o ...@@ -109,6 +108,16 @@ export CFLAGS_3c589_cs.o
endif endif
TEXTADDR := $(textaddr-y) TEXTADDR := $(textaddr-y)
ifeq ($(CONFIG_XIP_KERNEL),y)
DATAADDR := $(TEXTADDR)
xipaddr-$(CONFIG_ARCH_CO285) := 0x5f000000
xipaddr-y ?= 0xbf000000
# Replace phys addr with virt addr while keeping offset from base.
TEXTADDR := $(shell echo $(CONFIG_XIP_PHYS_ADDR) $(xipaddr-y) | \
awk --non-decimal-data '/[:xdigit:]/ \
{ printf("0x%x\n", and($$1, 0x000fffff) + $$2) }' )
endif
ifeq ($(incdir-y),) ifeq ($(incdir-y),)
incdir-y := $(machine-y) incdir-y := $(machine-y)
endif endif
...@@ -119,7 +128,7 @@ else ...@@ -119,7 +128,7 @@ else
MACHINE := MACHINE :=
endif endif
export TEXTADDR GZFLAGS export TEXTADDR DATAADDR GZFLAGS
# Do we have FASTFPE? # Do we have FASTFPE?
FASTFPE :=arch/arm/fastfpe FASTFPE :=arch/arm/fastfpe
...@@ -141,7 +150,11 @@ drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ ...@@ -141,7 +150,11 @@ drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/
libs-y += arch/arm/lib/ libs-y += arch/arm/lib/
# Default target when executing plain make # Default target when executing plain make
ifeq ($(CONFIG_XIP_KERNEL),y)
all: xipImage
else
all: zImage all: zImage
endif
boot := arch/arm/boot boot := arch/arm/boot
...@@ -168,7 +181,7 @@ maketools: include/asm-arm/constants.h include/linux/version.h FORCE ...@@ -168,7 +181,7 @@ maketools: include/asm-arm/constants.h include/linux/version.h FORCE
# Convert bzImage to zImage # Convert bzImage to zImage
bzImage: zImage bzImage: zImage
zImage Image bootpImage uImage: vmlinux zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
zinstall install: vmlinux zinstall install: vmlinux
...@@ -194,6 +207,7 @@ include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s ...@@ -194,6 +207,7 @@ include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
define archhelp define archhelp
echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
echo '* xipImage - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)'
echo ' bootpImage - Combined zImage and initial RAM disk' echo ' bootpImage - Combined zImage and initial RAM disk'
echo ' (supply initrd image via make variable INITRD=<path>)' echo ' (supply initrd image via make variable INITRD=<path>)'
echo ' install - Install uncompressed kernel' echo ' install - Install uncompressed kernel'
......
...@@ -24,7 +24,24 @@ INITRD_PHYS := $(initrd_phys-y) ...@@ -24,7 +24,24 @@ INITRD_PHYS := $(initrd_phys-y)
export ZRELADDR INITRD_PHYS PARAMS_PHYS export ZRELADDR INITRD_PHYS PARAMS_PHYS
targets := Image zImage bootpImage uImage targets := Image zImage xipImage bootpImage uImage
ifeq ($(CONFIG_XIP_KERNEL),y)
$(obj)/xipImage: vmlinux FORCE
$(call if_changed,objcopy)
@echo ' Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
$(obj)/Image $(obj)/zImage: FORCE
@echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@echo 'Only the xipImage target is available in this case'
@false
else
$(obj)/xipImage: FORCE
@echo 'Kernel not configured for XIP (CONFIG_XIP_KERNEL!=y)'
@false
$(obj)/Image: vmlinux FORCE $(obj)/Image: vmlinux FORCE
$(call if_changed,objcopy) $(call if_changed,objcopy)
...@@ -37,6 +54,8 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE ...@@ -37,6 +54,8 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy) $(call if_changed,objcopy)
@echo ' Kernel: $@ is ready' @echo ' Kernel: $@ is ready'
endif
quiet_cmd_uimage = UIMAGE $@ quiet_cmd_uimage = UIMAGE $@
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
-C none -a $(ZRELADDR) -e $(ZRELADDR) \ -C none -a $(ZRELADDR) -e $(ZRELADDR) \
......
...@@ -147,15 +147,23 @@ static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) ...@@ -147,15 +147,23 @@ static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
return ops->set_time(tm); return ops->set_time(tm);
} }
static inline void rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
{ {
int ret = -EINVAL;
if (ops->read_alarm) {
memset(alrm, 0, sizeof(struct rtc_wkalrm)); memset(alrm, 0, sizeof(struct rtc_wkalrm));
ops->read_alarm(alrm); ops->read_alarm(alrm);
ret = 0;
}
return ret;
} }
static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
{ {
return ops->set_alarm(alrm); int ret = -EINVAL;
if (ops->set_alarm)
ret = ops->set_alarm(alrm);
return ret;
} }
void rtc_update(unsigned long num, unsigned long events) void rtc_update(unsigned long num, unsigned long events)
...@@ -233,11 +241,13 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -233,11 +241,13 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct rtc_ops *ops = file->private_data; struct rtc_ops *ops = file->private_data;
struct rtc_time tm; struct rtc_time tm;
struct rtc_wkalrm alrm; struct rtc_wkalrm alrm;
int ret; int ret = -EINVAL;
switch (cmd) { switch (cmd) {
case RTC_ALM_READ: case RTC_ALM_READ:
rtc_read_alarm(ops, &alrm); ret = rtc_read_alarm(ops, &alrm);
if (ret)
break;
ret = copy_to_user((void *)arg, &alrm.time, sizeof(tm)); ret = copy_to_user((void *)arg, &alrm.time, sizeof(tm));
if (ret) if (ret)
ret = -EFAULT; ret = -EFAULT;
...@@ -245,6 +255,10 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -245,6 +255,10 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case RTC_ALM_SET: case RTC_ALM_SET:
ret = copy_from_user(&alrm.time, (void *)arg, sizeof(tm)); ret = copy_from_user(&alrm.time, (void *)arg, sizeof(tm));
if (ret) {
ret = -EFAULT;
break;
}
alrm.enabled = 0; alrm.enabled = 0;
alrm.pending = 0; alrm.pending = 0;
alrm.time.tm_mday = -1; alrm.time.tm_mday = -1;
...@@ -253,10 +267,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -253,10 +267,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
alrm.time.tm_wday = -1; alrm.time.tm_wday = -1;
alrm.time.tm_yday = -1; alrm.time.tm_yday = -1;
alrm.time.tm_isdst = -1; alrm.time.tm_isdst = -1;
if (ret == 0)
ret = rtc_set_alarm(ops, &alrm); ret = rtc_set_alarm(ops, &alrm);
else
ret = -EFAULT;
break; break;
case RTC_RD_TIME: case RTC_RD_TIME:
...@@ -278,8 +289,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -278,8 +289,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ret = -EFAULT; ret = -EFAULT;
break; break;
#ifndef rtc_epoch
case RTC_EPOCH_SET: case RTC_EPOCH_SET:
#ifndef rtc_epoch
/* /*
* There were no RTC clocks before 1900. * There were no RTC clocks before 1900.
*/ */
...@@ -293,8 +304,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -293,8 +304,8 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
} }
rtc_epoch = arg; rtc_epoch = arg;
ret = 0; ret = 0;
break;
#endif #endif
break;
case RTC_EPOCH_READ: case RTC_EPOCH_READ:
ret = put_user(rtc_epoch, (unsigned long *)arg); ret = put_user(rtc_epoch, (unsigned long *)arg);
...@@ -302,21 +313,26 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -302,21 +313,26 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case RTC_WKALM_SET: case RTC_WKALM_SET:
ret = copy_from_user(&alrm, (void *)arg, sizeof(alrm)); ret = copy_from_user(&alrm, (void *)arg, sizeof(alrm));
if (ret == 0) if (ret) {
ret = rtc_set_alarm(ops, &alrm);
else
ret = -EFAULT; ret = -EFAULT;
break; break;
}
ret = rtc_set_alarm(ops, &alrm);
break;
case RTC_WKALM_RD: case RTC_WKALM_RD:
rtc_read_alarm(ops, &alrm); ret = rtc_read_alarm(ops, &alrm);
if (ret)
break;
ret = copy_to_user((void *)arg, &alrm, sizeof(alrm)); ret = copy_to_user((void *)arg, &alrm, sizeof(alrm));
if (ret) if (ret)
ret = -EFAULT; ret = -EFAULT;
break; break;
default: default:
if (ops->ioctl)
ret = ops->ioctl(cmd, arg); ret = ops->ioctl(cmd, arg);
break;
} }
return ret; return ret;
} }
...@@ -406,7 +422,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo ...@@ -406,7 +422,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
rtc_epoch); rtc_epoch);
rtc_read_alarm(ops, &alrm); if (rtc_read_alarm(ops, &alrm) == 0) {
p += sprintf(p, "alrm_time\t: "); p += sprintf(p, "alrm_time\t: ");
if ((unsigned int)alrm.time.tm_hour <= 24) if ((unsigned int)alrm.time.tm_hour <= 24)
p += sprintf(p, "%02d:", alrm.time.tm_hour); p += sprintf(p, "%02d:", alrm.time.tm_hour);
...@@ -434,8 +450,11 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo ...@@ -434,8 +450,11 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
p += sprintf(p, "%02d\n", alrm.time.tm_mday); p += sprintf(p, "%02d\n", alrm.time.tm_mday);
else else
p += sprintf(p, "**\n"); p += sprintf(p, "**\n");
p += sprintf(p, "alrm_wakeup\t: %s\n", alrm.enabled ? "yes" : "no"); p += sprintf(p, "alrm_wakeup\t: %s\n",
p += sprintf(p, "alrm_pending\t: %s\n", alrm.pending ? "yes" : "no"); alrm.enabled ? "yes" : "no");
p += sprintf(p, "alrm_pending\t: %s\n",
alrm.pending ? "yes" : "no");
}
if (ops->proc) if (ops->proc)
p += ops->proc(p); p += ops->proc(p);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the linux kernel. # Makefile for the linux kernel.
# #
AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
# Object file lists. # Object file lists.
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/memory.h>
/* /*
* Make sure that the compiler and target are compatible. * Make sure that the compiler and target are compatible.
...@@ -72,6 +73,7 @@ int main(void) ...@@ -72,6 +73,7 @@ int main(void)
DEFINE(VM_EXEC, VM_EXEC); DEFINE(VM_EXEC, VM_EXEC);
BLANK(); BLANK();
DEFINE(PAGE_SZ, PAGE_SIZE); DEFINE(PAGE_SZ, PAGE_SIZE);
DEFINE(VIRT_OFFSET, PAGE_OFFSET);
BLANK(); BLANK();
DEFINE(SYS_ERROR0, 0x9f0000); DEFINE(SYS_ERROR0, 0x9f0000);
BLANK(); BLANK();
......
...@@ -19,17 +19,16 @@ ...@@ -19,17 +19,16 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/constants.h> #include <asm/constants.h>
#ifndef CONFIG_XIP_KERNEL
/* /*
* We place the page tables 16K below TEXTADDR. Therefore, we must make sure * We place the page tables 16K below TEXTADDR. Therefore, we must make sure
* that TEXTADDR is correctly set. Currently, we expect the least significant * that TEXTADDR is correctly set. Currently, we expect the least significant
* 16 bits to be 0x8000, but we could probably relax this restriction to * 16 bits to be 0x8000, but we could probably relax this restriction to
* TEXTADDR > PAGE_OFFSET + 0x4000 * TEXTADDR >= PAGE_OFFSET + 0x4000
* *
* Note that swapper_pg_dir is the virtual address of the page tables, and * Note that swapper_pg_dir is the virtual address of the page tables, and
* pgtbl gives us a position-independent reference to these tables. We can * pgtbl gives us a position-independent reference to these tables. We can
* do this because stext == TEXTADDR * do this because stext == TEXTADDR
*
* swapper_pg_dir, pgtbl and krnladr are all closely related.
*/ */
#if (TEXTADDR & 0xffff) != 0x8000 #if (TEXTADDR & 0xffff) != 0x8000
#error TEXTADDR must start at 0xXXXX8000 #error TEXTADDR must start at 0xXXXX8000
...@@ -38,19 +37,35 @@ ...@@ -38,19 +37,35 @@
.globl swapper_pg_dir .globl swapper_pg_dir
.equ swapper_pg_dir, TEXTADDR - 0x4000 .equ swapper_pg_dir, TEXTADDR - 0x4000
.macro pgtbl, reg .macro pgtbl, rd, phys
adr \reg, stext adr \rd, stext
sub \reg, \reg, #0x4000 sub \rd, \rd, #0x4000
.endm .endm
#else
/* /*
* Since the page table is closely related to the kernel start address, we * XIP Kernel:
* can convert the page table base address to the base address of the section *
* containing both. * We place the page tables 16K below DATAADDR. Therefore, we must make sure
* that DATAADDR is correctly set. Currently, we expect the least significant
* 16 bits to be 0x8000, but we could probably relax this restriction to
* DATAADDR >= PAGE_OFFSET + 0x4000
*
* Note that pgtbl is meant to return the physical address of swapper_pg_dir.
* We can't make it relative to the kernel position in this case since
* the kernel can physically be anywhere.
*/ */
.macro krnladr, rd, pgtable #if (DATAADDR & 0xffff) != 0x8000
bic \rd, \pgtable, #0x000ff000 #error DATAADDR must start at 0xXXXX8000
#endif
.globl swapper_pg_dir
.equ swapper_pg_dir, DATAADDR - 0x4000
.macro pgtbl, rd, phys
ldr \rd, =((DATAADDR - 0x4000) - VIRT_OFFSET)
add \rd, \rd, \phys
.endm .endm
#endif
/* /*
* Kernel startup entry point. * Kernel startup entry point.
...@@ -99,6 +114,8 @@ ENTRY(stext) ...@@ -99,6 +114,8 @@ ENTRY(stext)
.type __switch_data, %object .type __switch_data, %object
__switch_data: __switch_data:
.long __mmap_switched .long __mmap_switched
.long __data_loc @ r2
.long __data_start @ r3
.long __bss_start @ r4 .long __bss_start @ r4
.long _end @ r5 .long _end @ r5
.long processor_id @ r6 .long processor_id @ r6
...@@ -136,12 +153,20 @@ __turn_mmu_on: ...@@ -136,12 +153,20 @@ __turn_mmu_on:
*/ */
.align 5 .align 5
__mmap_switched: __mmap_switched:
adr r3, __switch_data + 4 adr r2, __switch_data + 4
ldmia r3, {r4, r5, r6, r7, r8, sp} ldmia r2, {r2, r3, r4, r5, r6, r7, r8, sp}
cmp r2, r3 @ Copy data segment if needed
1: cmpne r3, r4
ldrne fp, [r2], #4
strne fp, [r3], #4
bne 1b
mov fp, #0 @ Clear BSS (and zero fp) mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r4, r5 1: cmp r4, r5
strcc fp, [r4],#4 strcc fp, [r4],#4
bcc 1b bcc 1b
str r9, [r6] @ Save processor ID str r9, [r6] @ Save processor ID
str r1, [r7] @ Save machine type str r1, [r7] @ Save machine type
bic r2, r0, #2 @ Clear 'A' bit bic r2, r0, #2 @ Clear 'A' bit
...@@ -156,16 +181,13 @@ __mmap_switched: ...@@ -156,16 +181,13 @@ __mmap_switched:
* amount which are required to get the kernel running, which * amount which are required to get the kernel running, which
* generally means mapping in the kernel code. * generally means mapping in the kernel code.
* *
* We only map in 4MB of RAM, which should be sufficient in
* all cases.
*
* r5 = physical address of start of RAM * r5 = physical address of start of RAM
* r6 = physical IO address * r6 = physical IO address
* r7 = byte offset into page tables for IO * r7 = byte offset into page tables for IO
* r8 = page table flags * r8 = page table flags
*/ */
__create_page_tables: __create_page_tables:
pgtbl r4 @ page table address pgtbl r4, r5 @ page table address
/* /*
* Clear the 16K level 1 swapper page table * Clear the 16K level 1 swapper page table
...@@ -183,28 +205,50 @@ __create_page_tables: ...@@ -183,28 +205,50 @@ __create_page_tables:
/* /*
* Create identity mapping for first MB of kernel to * Create identity mapping for first MB of kernel to
* cater for the MMU enable. This identity mapping * cater for the MMU enable. This identity mapping
* will be removed by paging_init() * will be removed by paging_init(). We use our current program
* counter to determine corresponding section base address.
*/ */
krnladr r2, r4 @ start of kernel mov r2, pc, lsr #20 @ start of kernel section
add r3, r8, r2 @ flags + kernel base add r3, r8, r2, lsl #20 @ flags + kernel base
str r3, [r4, r2, lsr #18] @ identity mapping str r3, [r4, r2, lsl #2] @ identity mapping
/* /*
* Now setup the pagetables for our kernel direct * Now setup the pagetables for our kernel direct
* mapped region. We round TEXTADDR down to the * mapped region. We round TEXTADDR down to the
* nearest megabyte boundary. * nearest megabyte boundary. It is assumed that
* the kernel fits within 4 contigous 1MB sections.
*/ */
add r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel add r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel
bic r2, r3, #0x00f00000 str r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]!
str r2, [r0] @ PAGE_OFFSET + 0MB
add r0, r0, #(TEXTADDR & 0x00f00000) >> 18
str r3, [r0], #4 @ KERNEL + 0MB
add r3, r3, #1 << 20 add r3, r3, #1 << 20
str r3, [r0], #4 @ KERNEL + 1MB str r3, [r0, #4]! @ KERNEL + 1MB
add r3, r3, #1 << 20 add r3, r3, #1 << 20
str r3, [r0], #4 @ KERNEL + 2MB str r3, [r0, #4]! @ KERNEL + 2MB
add r3, r3, #1 << 20 add r3, r3, #1 << 20
str r3, [r0], #4 @ KERNEL + 3MB str r3, [r0, #4] @ KERNEL + 3MB
/*
* Then map first 1MB of ram in case it contains our boot params.
*/
add r0, r4, #VIRT_OFFSET >> 18
add r2, r5, r8
str r2, [r0]
#ifdef CONFIG_XIP_KERNEL
/*
* Map some ram to cover our .data and .bss areas.
* Mapping 3MB should be plenty.
*/
sub r3, r4, r5
mov r3, r3, lsr #20
add r0, r0, r3, lsl #2
add r2, r2, r3, lsl #20
str r2, [r0], #4
add r2, r2, #(1 << 20)
str r2, [r0], #4
add r2, r2, #(1 << 20)
str r2, [r0]
#endif
bic r8, r8, #0x0c @ turn off cacheable bic r8, r8, #0x0c @ turn off cacheable
@ and bufferable bits @ and bufferable bits
...@@ -255,6 +299,7 @@ __create_page_tables: ...@@ -255,6 +299,7 @@ __create_page_tables:
str r3, [r0] str r3, [r0]
#endif #endif
mov pc, lr mov pc, lr
.ltorg
......
...@@ -376,7 +376,6 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) ...@@ -376,7 +376,6 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
do { do {
struct irqaction *action; struct irqaction *action;
int ret;
action = desc->action; action = desc->action;
if (!action) if (!action)
...@@ -387,9 +386,7 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) ...@@ -387,9 +386,7 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
desc->chip->unmask(irq); desc->chip->unmask(irq);
} }
ret = __do_irq(irq, action, regs); __do_irq(irq, action, regs);
if (ret != IRQ_HANDLED)
report_bad_irq(irq, regs, desc, ret);
} while (desc->pending && !desc->disable_depth); } while (desc->pending && !desc->disable_depth);
desc->running = 0; desc->running = 0;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* *
* Module allocation method suggested by Andi Kleen. * Module allocation method suggested by Andi Kleen.
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/elf.h> #include <linux/elf.h>
...@@ -19,6 +20,18 @@ ...@@ -19,6 +20,18 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#ifdef CONFIG_XIP_KERNEL
/*
* The XIP kernel text is mapped in the module area for modules and
* some other stuff to work without any indirect relocations.
* MODULE_START is redefined here and not in asm/memory.h to avoid
* recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.
*/
extern void _etext;
#undef MODULE_START
#define MODULE_START (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK)
#endif
void *module_alloc(unsigned long size) void *module_alloc(unsigned long size)
{ {
struct vm_struct *area; struct vm_struct *area;
......
...@@ -59,7 +59,7 @@ extern void convert_to_tag_list(struct tag *tags); ...@@ -59,7 +59,7 @@ extern void convert_to_tag_list(struct tag *tags);
extern void squash_mem_tags(struct tag *tag); extern void squash_mem_tags(struct tag *tag);
extern void reboot_setup(char *str); extern void reboot_setup(char *str);
extern int root_mountflags; extern int root_mountflags;
extern int _stext, _text, _etext, _edata, _end; extern void _stext, _text, _etext, __data_start, _edata, _end;
unsigned int processor_id; unsigned int processor_id;
unsigned int __machine_arch_type; unsigned int __machine_arch_type;
...@@ -113,7 +113,7 @@ static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', ' ...@@ -113,7 +113,7 @@ static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '
*/ */
static struct resource mem_res[] = { static struct resource mem_res[] = {
{ "Video RAM", 0, 0, IORESOURCE_MEM }, { "Video RAM", 0, 0, IORESOURCE_MEM },
{ "Kernel code", 0, 0, IORESOURCE_MEM }, { "Kernel text", 0, 0, IORESOURCE_MEM },
{ "Kernel data", 0, 0, IORESOURCE_MEM } { "Kernel data", 0, 0, IORESOURCE_MEM }
}; };
...@@ -447,10 +447,10 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) ...@@ -447,10 +447,10 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
struct resource *res; struct resource *res;
int i; int i;
kernel_code.start = __virt_to_phys(init_mm.start_code); kernel_code.start = virt_to_phys(&_text);
kernel_code.end = __virt_to_phys(init_mm.end_code - 1); kernel_code.end = virt_to_phys(&_etext - 1);
kernel_data.start = __virt_to_phys(init_mm.end_code); kernel_data.start = virt_to_phys(&__data_start);
kernel_data.end = __virt_to_phys(init_mm.brk - 1); kernel_data.end = virt_to_phys(&_end - 1);
for (i = 0; i < mi->nr_banks; i++) { for (i = 0; i < mi->nr_banks; i++) {
unsigned long virt_start, virt_end; unsigned long virt_start, virt_end;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
#include <asm-generic/vmlinux.lds.h> #include <asm-generic/vmlinux.lds.h>
#include <linux/config.h>
OUTPUT_ARCH(arm) OUTPUT_ARCH(arm)
ENTRY(stext) ENTRY(stext)
...@@ -17,7 +18,6 @@ SECTIONS ...@@ -17,7 +18,6 @@ SECTIONS
. = TEXTADDR; . = TEXTADDR;
.init : { /* Init code and data */ .init : { /* Init code and data */
_stext = .; _stext = .;
__init_begin = .;
_sinittext = .; _sinittext = .;
*(.init.text) *(.init.text)
_einittext = .; _einittext = .;
...@@ -30,7 +30,6 @@ SECTIONS ...@@ -30,7 +30,6 @@ SECTIONS
__tagtable_begin = .; __tagtable_begin = .;
*(.taglist) *(.taglist)
__tagtable_end = .; __tagtable_end = .;
*(.init.data)
. = ALIGN(16); . = ALIGN(16);
__setup_start = .; __setup_start = .;
*(.init.setup) *(.init.setup)
...@@ -57,8 +56,12 @@ SECTIONS ...@@ -57,8 +56,12 @@ SECTIONS
__initramfs_start = .; __initramfs_start = .;
usr/built-in.o(.init.ramfs) usr/built-in.o(.init.ramfs)
__initramfs_end = .; __initramfs_end = .;
#ifndef CONFIG_XIP_KERNEL
__init_begin = _stext;
*(.init.data)
. = ALIGN(4096); . = ALIGN(4096);
__init_end = .; __init_end = .;
#endif
} }
/DISCARD/ : { /* Exit code and data */ /DISCARD/ : { /* Exit code and data */
...@@ -79,8 +82,6 @@ SECTIONS ...@@ -79,8 +82,6 @@ SECTIONS
*(.glue_7) *(.glue_7)
*(.glue_7t) *(.glue_7t)
*(.got) /* Global offset table */ *(.got) /* Global offset table */
_etext = .; /* End of text section */
} }
. = ALIGN(16); . = ALIGN(16);
...@@ -92,15 +93,33 @@ SECTIONS ...@@ -92,15 +93,33 @@ SECTIONS
RODATA RODATA
_etext = .; /* End of text and rodata section */
#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
. = DATAADDR;
#else
. = ALIGN(8192); . = ALIGN(8192);
__data_loc = .;
#endif
.data : AT(__data_loc) {
__data_start = .; /* address in memory */
.data : {
/* /*
* first, the init task union, aligned * first, the init task union, aligned
* to an 8192 byte boundary. * to an 8192 byte boundary.
*/ */
*(.init.task) *(.init.task)
#ifdef CONFIG_XIP_KERNEL
. = ALIGN(4096);
__init_begin = .;
*(.init.data)
. = ALIGN(4096);
__init_end = .;
#endif
. = ALIGN(4096); . = ALIGN(4096);
__nosave_begin = .; __nosave_begin = .;
*(.data.nosave) *(.data.nosave)
...@@ -126,7 +145,7 @@ SECTIONS ...@@ -126,7 +145,7 @@ SECTIONS
__bss_start = .; /* BSS */ __bss_start = .; /* BSS */
*(.bss) *(.bss)
*(COMMON) *(COMMON)
_end = . ; _end = .;
} }
/* Stabs debugging sections. */ /* Stabs debugging sections. */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }
......
...@@ -10,7 +10,7 @@ obj-m := ...@@ -10,7 +10,7 @@ obj-m :=
obj-n := obj-n :=
obj- := obj- :=
obj-$(CONFIG_ARCH_IOP321) += iop321-setup.o iop321-irq.o iop321-pci.o iop321-mm.o iop321-time.o obj-$(CONFIG_ARCH_IOP321) += iop321-setup.o iop321-irq.o iop321-pci.o iop321-time.o
obj-$(CONFIG_ARCH_IOP331) += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o obj-$(CONFIG_ARCH_IOP331) += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o
......
/*
* linux/arch/arm/mach-iop3xx/mm.c
*
* Low level memory initialization for IOP321 based systems
*
* Author: Rory Bolt <rorybolt@pacbell.net>
* Copyright (C) 2002 Rory Bolt
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/mm.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/mach/map.h>
#include <asm/mach-types.h>
/*
* Standard IO mapping for all IOP321 based systems
*/
static struct map_desc iop321_std_desc[] __initdata = {
/* virtual physical length type */
/* mem mapped registers */
{ IOP321_VIRT_MEM_BASE, IOP321_PHY_MEM_BASE, 0x00002000, MT_DEVICE },
/* PCI IO space */
{ 0xfe000000, 0x90000000, 0x00020000, MT_DEVICE }
};
void __init iop321_map_io(void)
{
iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
}
...@@ -9,11 +9,21 @@ ...@@ -9,11 +9,21 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
*/ */
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_core.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/mach/map.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/memory.h> #include <asm/memory.h>
...@@ -21,6 +31,52 @@ ...@@ -21,6 +31,52 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#define IOP321_UART_XTAL 1843200
/*
* Standard IO mapping for all IOP321 based systems
*/
static struct map_desc iop321_std_desc[] __initdata = {
/* virtual physical length type */
/* mem mapped registers */
{ IOP321_VIRT_MEM_BASE, IOP321_PHY_MEM_BASE, 0x00002000, MT_DEVICE },
/* PCI IO space */
{ 0xfe000000, 0x90000000, 0x00020000, MT_DEVICE }
};
#ifdef CONFIG_ARCH_IQ80321
#define UARTBASE IQ80321_UART
#define IRQ_UART IRQ_IQ80321_UART
#endif
#ifdef CONFIG_ARCH_IQ31244
#define UARTBASE IQ31244_UART
#define IRQ_UART IRQ_IQ31244_UART
#endif
static struct uart_port iop321_serial_ports[] = {
{
.membase = (char*)(UARTBASE),
.mapbase = (UARTBASE),
.irq = IRQ_UART,
.flags = UPF_SKIP_TEST,
.iotype = UPIO_MEM,
.regshift = 0,
.uartclk = IOP321_UART_XTAL,
.line = 0,
.type = PORT_16550A,
.fifosize = 16
}
};
void __init iop321_map_io(void)
{
iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
early_serial_setup(&iop321_serial_ports[0]);
}
#ifdef CONFIG_ARCH_IQ80321 #ifdef CONFIG_ARCH_IQ80321
extern void iq80321_map_io(void); extern void iq80321_map_io(void);
extern struct sys_timer iop321_timer; extern struct sys_timer iop321_timer;
...@@ -33,29 +89,22 @@ extern struct sys_timer iop321_timer; ...@@ -33,29 +89,22 @@ extern struct sys_timer iop321_timer;
extern void iop321_init_time(void); extern void iop321_init_time(void);
#endif #endif
static void __init
fixup_iop321(struct machine_desc *desc, struct tag *tags,
char **cmdline, struct meminfo *mi)
{
}
#if defined(CONFIG_ARCH_IQ80321) #if defined(CONFIG_ARCH_IQ80321)
MACHINE_START(IQ80321, "Intel IQ80321") MACHINE_START(IQ80321, "Intel IQ80321")
MAINTAINER("Intel Corporation") MAINTAINER("Intel Corporation")
BOOT_MEM(PHYS_OFFSET, IQ80321_UART, 0xfe800000) BOOT_MEM(PHYS_OFFSET, IQ80321_UART, IQ80321_UART)
FIXUP(fixup_iop321)
MAPIO(iq80321_map_io) MAPIO(iq80321_map_io)
INITIRQ(iop321_init_irq) INITIRQ(iop321_init_irq)
.timer = &iop331_timer, .timer = &iop321_timer,
BOOT_PARAMS(0xa0000100) BOOT_PARAMS(0xa0000100)
MACHINE_END MACHINE_END
#elif defined(CONFIG_ARCH_IQ31244) #elif defined(CONFIG_ARCH_IQ31244)
MACHINE_START(IQ31244, "Intel IQ31244") MACHINE_START(IQ31244, "Intel IQ31244")
MAINTAINER("Intel Corp.") MAINTAINER("Intel Corp.")
BOOT_MEM(PHYS_OFFSET, IQ31244_UART, IQ31244_UART) BOOT_MEM(PHYS_OFFSET, IQ31244_UART, IQ31244_UART)
MAPIO(iq31244_map_io) MAPIO(iq31244_map_io)
INITIRQ(iop321_init_irq) INITIRQ(iop321_init_irq)
.timer = &iop331_timer, .timer = &iop321_timer,
BOOT_PARAMS(0xa0000100) BOOT_PARAMS(0xa0000100)
MACHINE_END MACHINE_END
#else #else
......
...@@ -29,11 +29,9 @@ ...@@ -29,11 +29,9 @@
#define IOP321_TIME_SYNC 0 #define IOP321_TIME_SYNC 0
static unsigned long iop321_latch;
static inline unsigned long get_elapsed(void) static inline unsigned long get_elapsed(void)
{ {
return iop321_latch - *IOP321_TU_TCR0; return LATCH - *IOP321_TU_TCR0;
} }
static unsigned long iop321_gettimeoffset(void) static unsigned long iop321_gettimeoffset(void)
...@@ -55,14 +53,14 @@ static unsigned long iop321_gettimeoffset(void) ...@@ -55,14 +53,14 @@ static unsigned long iop321_gettimeoffset(void)
asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2)); asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
if(tisr1 & 1) if(tisr1 & 1)
elapsed += iop321_latch; elapsed += LATCH;
else if (tisr2 & 1) else if (tisr2 & 1)
elapsed = iop321_latch + get_elapsed(); elapsed = LATCH + get_elapsed();
/* /*
* Now convert them to usec. * Now convert them to usec.
*/ */
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / iop321_latch; usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
return usec; return usec;
} }
...@@ -71,35 +69,16 @@ static irqreturn_t ...@@ -71,35 +69,16 @@ static irqreturn_t
iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
u32 tisr; u32 tisr;
#ifdef IOP321_TIME_SYNC
u32 passed;
#define TM_THRESH (iop321_latch*2)
#endif
asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr)); write_seqlock(&xtime_lock);
asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
tisr |= 1; tisr |= 1;
asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr)); asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
#ifdef IOP321_TIME_SYNC timer_tick(regs);
passed = 0xffffffff - *IOP321_TU_TCR1;
write_sequnlock(&xtime_lock);
do
{
do_timer(regs);
if(passed < TM_THRESH)
break;
if(passed > iop321_latch)
passed -= iop321_latch;
else
passed = 0;
} while(1);
asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
#else
do_timer(regs);
#endif
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -114,25 +93,14 @@ static void __init iop321_timer_init(void) ...@@ -114,25 +93,14 @@ static void __init iop321_timer_init(void)
{ {
u32 timer_ctl; u32 timer_ctl;
iop321_latch = (CLOCK_TICK_RATE + HZ / 2) / HZ;
setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq); setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD | timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
IOP321_TMR_RATIO_1_1; IOP321_TMR_RATIO_1_1;
asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (iop321_latch)); asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl)); asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
#ifdef IOP321_TIME_SYNC
/* Setup second timer */
/* setup counter */
timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED |
IOP321_TMR_RATIO_1_1;
asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
/* setup control */
asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
#endif
} }
struct sys_timer iop321_timer = { struct sys_timer iop321_timer = {
......
...@@ -27,13 +27,9 @@ ...@@ -27,13 +27,9 @@
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
#undef IOP331_TIME_SYNC
static unsigned long iop331_latch;
static inline unsigned long get_elapsed(void) static inline unsigned long get_elapsed(void)
{ {
return iop331_latch - *IOP331_TU_TCR0; return LATCH - *IOP331_TU_TCR0;
} }
static unsigned long iop331_gettimeoffset(void) static unsigned long iop331_gettimeoffset(void)
...@@ -55,14 +51,14 @@ static unsigned long iop331_gettimeoffset(void) ...@@ -55,14 +51,14 @@ static unsigned long iop331_gettimeoffset(void)
asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2)); asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
if(tisr1 & 1) if(tisr1 & 1)
elapsed += iop331_latch; elapsed += LATCH;
else if (tisr2 & 1) else if (tisr2 & 1)
elapsed = iop331_latch + get_elapsed(); elapsed = LATCH + get_elapsed();
/* /*
* Now convert them to usec. * Now convert them to usec.
*/ */
usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / iop331_latch; usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
return usec; return usec;
} }
...@@ -71,36 +67,16 @@ static irqreturn_t ...@@ -71,36 +67,16 @@ static irqreturn_t
iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
u32 tisr; u32 tisr;
#ifdef IOP331_TIME_SYNC
u32 passed;
#define TM_THRESH (iop331_latch*2)
#endif
asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr)); write_seqlock(&xtime_lock);
asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
tisr |= 1; tisr |= 1;
asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr)); asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
#ifdef IOP331_TIME_SYNC timer_tick(regs);
passed = 0xffffffff - *IOP331_TU_TCR1;
do
{
do_timer(regs);
if(passed < TM_THRESH)
break;
if(passed > iop331_latch)
passed -= iop331_latch;
else
passed = 0;
} while(1);
asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
#else
do_timer(regs);
#endif
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -114,25 +90,15 @@ static void __init iop331_timer_init(void) ...@@ -114,25 +90,15 @@ static void __init iop331_timer_init(void)
{ {
u32 timer_ctl; u32 timer_ctl;
iop331_latch = (CLOCK_TICK_RATE + HZ / 2) / HZ;
setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq); setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq);
timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD | timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD |
IOP331_TMR_RATIO_1_1; IOP331_TMR_RATIO_1_1;
asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (iop331_latch)); asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl)); asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl));
#ifdef IOP331_TIME_SYNC
/* Setup second timer */
/* setup counter */
timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED |
IOP331_TMR_RATIO_1_1;
asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
/* setup control */
asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
#endif
} }
struct sys_timer iop331_timer = { struct sys_timer iop331_timer = {
......
...@@ -59,16 +59,6 @@ extern void arm920_flush_kern_cache_all(void); ...@@ -59,16 +59,6 @@ extern void arm920_flush_kern_cache_all(void);
#define PFX "s3c24xx-pm: " #define PFX "s3c24xx-pm: "
/* sleep save info */
struct sleep_save {
unsigned long reg;
unsigned long val;
};
#define SAVE_ITEM(x) \
{ .reg = (x) }
static struct sleep_save core_save[] = { static struct sleep_save core_save[] = {
SAVE_ITEM(S3C2410_LOCKTIME), SAVE_ITEM(S3C2410_LOCKTIME),
SAVE_ITEM(S3C2410_CLKCON), SAVE_ITEM(S3C2410_CLKCON),
...@@ -81,21 +71,32 @@ static struct sleep_save core_save[] = { ...@@ -81,21 +71,32 @@ static struct sleep_save core_save[] = {
* wrong here, as we modify the refresh and both pll settings. * wrong here, as we modify the refresh and both pll settings.
*/ */
SAVE_ITEM(S3C2410_REFRESH), SAVE_ITEM(S3C2410_BWSCON),
SAVE_ITEM(S3C2410_BANKCON0),
SAVE_ITEM(S3C2410_BANKCON1),
SAVE_ITEM(S3C2410_BANKCON2),
SAVE_ITEM(S3C2410_BANKCON3),
SAVE_ITEM(S3C2410_BANKCON4),
SAVE_ITEM(S3C2410_BANKCON5),
SAVE_ITEM(S3C2410_CLKDIVN),
SAVE_ITEM(S3C2410_MPLLCON), SAVE_ITEM(S3C2410_MPLLCON),
SAVE_ITEM(S3C2410_UPLLCON), SAVE_ITEM(S3C2410_UPLLCON),
SAVE_ITEM(S3C2410_CLKDIVN),
SAVE_ITEM(S3C2410_CLKSLOW), SAVE_ITEM(S3C2410_CLKSLOW),
SAVE_ITEM(S3C2410_REFRESH),
}; };
/* this lot should be really saved by the IRQ code */ /* this lot should be really saved by the IRQ code */
static struct sleep_save irq_save[] = { static struct sleep_save irq_save[] = {
SAVE_ITEM(S3C2410_EINTMASK), SAVE_ITEM(S3C2410_EXTINT0),
SAVE_ITEM(S3C2410_INTMSK), SAVE_ITEM(S3C2410_EXTINT1),
SAVE_ITEM(S3C2410_EXTINT2),
SAVE_ITEM(S3C2410_EINFLT0), SAVE_ITEM(S3C2410_EINFLT0),
SAVE_ITEM(S3C2410_EINFLT1), SAVE_ITEM(S3C2410_EINFLT1),
SAVE_ITEM(S3C2410_EINFLT2), SAVE_ITEM(S3C2410_EINFLT2),
SAVE_ITEM(S3C2410_EINFLT3) SAVE_ITEM(S3C2410_EINFLT3),
SAVE_ITEM(S3C2410_EINTMASK),
SAVE_ITEM(S3C2410_INTMSK)
}; };
static struct sleep_save gpio_save[] = { static struct sleep_save gpio_save[] = {
...@@ -129,6 +130,8 @@ static struct sleep_save gpio_save[] = { ...@@ -129,6 +130,8 @@ static struct sleep_save gpio_save[] = {
SAVE_ITEM(S3C2410_GPHCON), SAVE_ITEM(S3C2410_GPHCON),
SAVE_ITEM(S3C2410_GPHDAT), SAVE_ITEM(S3C2410_GPHDAT),
SAVE_ITEM(S3C2410_GPHUP), SAVE_ITEM(S3C2410_GPHUP),
SAVE_ITEM(S3C2410_DCLKCON),
}; };
#ifdef CONFIG_S3C2410_PM_DEBUG #ifdef CONFIG_S3C2410_PM_DEBUG
...@@ -384,7 +387,7 @@ static struct sleep_save uart_save[] = {}; ...@@ -384,7 +387,7 @@ static struct sleep_save uart_save[] = {};
/* helper functions to save and restore register state */ /* helper functions to save and restore register state */
static void s3c2410_pm_do_save(struct sleep_save *ptr, int count) void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
{ {
for (; count > 0; count--, ptr++) { for (; count > 0; count--, ptr++) {
ptr->val = __raw_readl(ptr->reg); ptr->val = __raw_readl(ptr->reg);
...@@ -400,7 +403,7 @@ static void s3c2410_pm_do_save(struct sleep_save *ptr, int count) ...@@ -400,7 +403,7 @@ static void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
* restore the UARTs state yet * restore the UARTs state yet
*/ */
static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count) void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
{ {
for (; count > 0; count--, ptr++) { for (; count > 0; count--, ptr++) {
printk(KERN_DEBUG "restore %08lx (restore %08lx, was %08x)\n", printk(KERN_DEBUG "restore %08lx (restore %08lx, was %08x)\n",
...@@ -410,6 +413,21 @@ static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count) ...@@ -410,6 +413,21 @@ static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
} }
} }
/* s3c2410_pm_do_restore_core
*
* similar to s3c2410_pm_do_restore_core
*
* WARNING: Do not put any debug in here that may effect memory or use
* peripherals, as things may be changing!
*/
static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
__raw_writel(ptr->val, ptr->reg);
}
}
/* s3c2410_pm_show_resume_irqs /* s3c2410_pm_show_resume_irqs
* *
* print any IRQs asserted at resume time (ie, we woke from) * print any IRQs asserted at resume time (ie, we woke from)
...@@ -578,7 +596,7 @@ static int s3c2410_pm_enter(suspend_state_t state) ...@@ -578,7 +596,7 @@ static int s3c2410_pm_enter(suspend_state_t state)
/* restore the system state */ /* restore the system state */
s3c2410_pm_do_restore(core_save, ARRAY_SIZE(core_save)); s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
......
...@@ -34,3 +34,16 @@ extern void s3c2410_cpu_suspend(unsigned long *saveblk); ...@@ -34,3 +34,16 @@ extern void s3c2410_cpu_suspend(unsigned long *saveblk);
extern void s3c2410_cpu_resume(void); extern void s3c2410_cpu_resume(void);
extern unsigned long s3c2410_sleep_save_phys; extern unsigned long s3c2410_sleep_save_phys;
/* sleep save info */
struct sleep_save {
unsigned long reg;
unsigned long val;
};
#define SAVE_ITEM(x) \
{ .reg = (x) }
extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
...@@ -11,15 +11,14 @@ ...@@ -11,15 +11,14 @@
* *
* Modifications: * Modifications:
* 29-Aug-2004 BJD Start of drive-strength control * 29-Aug-2004 BJD Start of drive-strength control
* 09-Nov-2004 BJD Added symbol export
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h> #include <linux/module.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -55,3 +54,5 @@ int s3c2440_set_dsc(unsigned int pin, unsigned int value) ...@@ -55,3 +54,5 @@ int s3c2440_set_dsc(unsigned int pin, unsigned int value)
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
} }
EXPORT_SYMBOL(s3c2440_set_dsc);
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* 24-Aug-2004 BJD Start of s3c2440 support * 24-Aug-2004 BJD Start of s3c2440 support
* 12-Oct-2004 BJD Moved clock info out to clock.c * 12-Oct-2004 BJD Moved clock info out to clock.c
* 01-Nov-2004 BJD Fixed clock build code * 01-Nov-2004 BJD Fixed clock build code
* 09-Nov-2004 BJD Added sysdev for power management
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -22,6 +23,7 @@ ...@@ -22,6 +23,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/sysdev.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -34,10 +36,15 @@ ...@@ -34,10 +36,15 @@
#include <asm/arch/regs-clock.h> #include <asm/arch/regs-clock.h>
#include <asm/arch/regs-serial.h> #include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-gpioj.h>
#include <asm/arch/regs-dsc.h>
#include "s3c2440.h" #include "s3c2440.h"
#include "clock.h" #include "clock.h"
#include "devs.h"
#include "cpu.h" #include "cpu.h"
#include "pm.h"
int s3c2440_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */ int s3c2440_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */
...@@ -136,6 +143,43 @@ static struct clk s3c2440_clk_ac97 = { ...@@ -136,6 +143,43 @@ static struct clk s3c2440_clk_ac97 = {
.ctrlbit = S3C2440_CLKCON_CAMERA .ctrlbit = S3C2440_CLKCON_CAMERA
}; };
#ifdef CONFIG_PM
struct sleep_save s3c2440_sleep[] = {
SAVE_ITEM(S3C2440_DSC0),
SAVE_ITEM(S3C2440_DSC1),
SAVE_ITEM(S3C2440_GPJDAT),
SAVE_ITEM(S3C2440_GPJCON),
SAVE_ITEM(S3C2440_GPJUP)
};
static int s3c2440_suspend(struct sys_device *dev, u32 state)
{
s3c2410_pm_do_save(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
return 0;
}
static int s3c2440_resume(struct sys_device *dev)
{
s3c2410_pm_do_restore(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
return 0;
}
#else
#define s3c2440_suspend NULL
#define s3c2440_resume NULL
#endif
static struct sysdev_class s3c2440_sysclass = {
set_kset_name("s3c2440-core"),
.suspend = s3c2440_suspend,
.resume = s3c2440_resume
};
static struct sys_device s3c2440_sysdev = {
.cls = &s3c2440_sysclass,
};
void __init s3c2440_map_io(struct map_desc *mach_desc, int size) void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
{ {
unsigned long clkdiv; unsigned long clkdiv;
...@@ -202,15 +246,22 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size) ...@@ -202,15 +246,22 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
clk_disable(&s3c2440_clk_cam); clk_disable(&s3c2440_clk_cam);
} }
int __init s3c2440_init(void) int __init s3c2440_init(void)
{ {
int ret; int ret;
printk("S3C2440: Initialising architecture\n"); printk("S3C2440: Initialising architecture\n");
ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices)); ret = sysdev_class_register(&s3c2440_sysclass);
if (ret == 0)
ret = sysdev_register(&s3c2440_sysdev);
if (ret != 0)
printk(KERN_ERR "failed to register sysdev for s3c2440\n");
if (ret != 0)
ret = platform_add_devices(uart_devices,
ARRAY_SIZE(uart_devices));
return ret; return ret;
} }
...@@ -9,16 +9,17 @@ ...@@ -9,16 +9,17 @@
* 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
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mm.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
...@@ -29,6 +30,7 @@ ...@@ -29,6 +30,7 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/mach/serial_sa1100.h> #include <asm/mach/serial_sa1100.h>
#include <asm/arch/assabet.h> #include <asm/arch/assabet.h>
...@@ -92,6 +94,68 @@ static void assabet_lcd_power(int on) ...@@ -92,6 +94,68 @@ static void assabet_lcd_power(int on)
ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
} }
#ifdef ASSABET_REV_4
/*
* Phase 4 Assabet has two 28F160B3 flash parts in bank 0:
*/
static struct mtd_partition assabet_partitions[] = {
{
.name = "bootloader",
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "bootloader params",
.size = 0x00020000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "jffs",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
#else
/*
* Phase 5 Assabet has two 28F128J3A flash parts in bank 0:
*/
static struct mtd_partition assabet_partitions[] = {
{
.name = "bootloader",
.size = 0x00040000,
.offset = 0,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "bootloader params",
.size = 0x00040000,
.offset = MTDPART_OFS_APPEND,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "jffs",
.size = MTDPART_SIZ_FULL,
.offset = MTDPART_OFS_APPEND,
}
};
#endif
static struct flash_platform_data assabet_flash_data = {
.map_name = "cfi_probe",
.parts = assabet_partitions,
.nr_parts = ARRAY_SIZE(assabet_partitions),
};
static struct resource assabet_flash_resources[] = {
{
.start = SA1100_CS0_PHYS,
.end = SA1100_CS0_PHYS + SZ_32M - 1,
.flags = IORESOURCE_MEM,
}, {
.start = SA1100_CS1_PHYS,
.end = SA1100_CS1_PHYS + SZ_32M - 1,
.flags = IORESOURCE_MEM,
}
};
static void __init assabet_init(void) static void __init assabet_init(void)
{ {
/* /*
...@@ -136,6 +200,9 @@ static void __init assabet_init(void) ...@@ -136,6 +200,9 @@ static void __init assabet_init(void)
"hasn't been configured in the kernel\n" ); "hasn't been configured in the kernel\n" );
#endif #endif
} }
sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources,
ARRAY_SIZE(assabet_flash_resources));
} }
/* /*
...@@ -325,5 +392,5 @@ MACHINE_START(ASSABET, "Intel-Assabet") ...@@ -325,5 +392,5 @@ MACHINE_START(ASSABET, "Intel-Assabet")
MAPIO(assabet_map_io) MAPIO(assabet_map_io)
INITIRQ(sa1100_init_irq) INITIRQ(sa1100_init_irq)
.timer = &sa1100_timer, .timer = &sa1100_timer,
INIT_MACHINE(assabet_init) .init_machine = assabet_init,
MACHINE_END MACHINE_END
...@@ -270,6 +270,19 @@ static struct platform_device sa11x0pcmcia_device = { ...@@ -270,6 +270,19 @@ static struct platform_device sa11x0pcmcia_device = {
.id = -1, .id = -1,
}; };
static struct platform_device sa11x0mtd_device = {
.name = "flash",
.id = -1,
};
void sa11x0_set_flash_data(struct flash_platform_data *flash,
struct resource *res, int nr)
{
sa11x0mtd_device.dev.platform_data = flash;
sa11x0mtd_device.resource = res;
sa11x0mtd_device.num_resources = nr;
}
static struct platform_device *sa11x0_devices[] __initdata = { static struct platform_device *sa11x0_devices[] __initdata = {
&sa11x0udc_device, &sa11x0udc_device,
&sa11x0uart1_device, &sa11x0uart1_device,
...@@ -278,6 +291,7 @@ static struct platform_device *sa11x0_devices[] __initdata = { ...@@ -278,6 +291,7 @@ static struct platform_device *sa11x0_devices[] __initdata = {
&sa11x0ssp_device, &sa11x0ssp_device,
&sa11x0pcmcia_device, &sa11x0pcmcia_device,
&sa11x0fb_device, &sa11x0fb_device,
&sa11x0mtd_device,
}; };
static int __init sa1100_init(void) static int __init sa1100_init(void)
......
...@@ -27,3 +27,9 @@ extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); ...@@ -27,3 +27,9 @@ extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
extern unsigned int sa11x0_getspeed(unsigned int cpu); extern unsigned int sa11x0_getspeed(unsigned int cpu);
extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx); extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
struct flash_platform_data;
struct resource;
extern void sa11x0_set_flash_data(struct flash_platform_data *flash,
struct resource *res, int nr);
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern char _stext, _text, _etext, _end, __init_begin, __init_end; extern void _stext, _text, _etext, __data_start, _end, __init_begin, __init_end;
extern unsigned long phys_initrd_start; extern unsigned long phys_initrd_start;
extern unsigned long phys_initrd_size; extern unsigned long phys_initrd_size;
...@@ -282,7 +282,11 @@ static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot ...@@ -282,7 +282,11 @@ static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot
* Register the kernel text and data with bootmem. * Register the kernel text and data with bootmem.
* Note that this can only be in node 0. * Note that this can only be in node 0.
*/ */
#ifdef CONFIG_XIP_KERNEL
reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
#else
reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext); reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
#endif
/* /*
* Reserve the page tables. These are already in use, * Reserve the page tables. These are already in use,
...@@ -540,7 +544,7 @@ void __init mem_init(void) ...@@ -540,7 +544,7 @@ void __init mem_init(void)
int i, node; int i, node;
codepages = &_etext - &_text; codepages = &_etext - &_text;
datapages = &_end - &_etext; datapages = &_end - &__data_start;
initpages = &__init_end - &__init_begin; initpages = &__init_end - &__init_begin;
#ifndef CONFIG_DISCONTIGMEM #ifndef CONFIG_DISCONTIGMEM
......
...@@ -326,6 +326,10 @@ static struct mem_types mem_types[] __initdata = { ...@@ -326,6 +326,10 @@ static struct mem_types mem_types[] __initdata = {
[MT_MEMORY] = { [MT_MEMORY] = {
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
.domain = DOMAIN_KERNEL, .domain = DOMAIN_KERNEL,
},
[MT_ROM] = {
.prot_sect = PMD_TYPE_SECT,
.domain = DOMAIN_KERNEL,
} }
}; };
...@@ -359,6 +363,7 @@ static void __init build_mem_type_table(void) ...@@ -359,6 +363,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_MINICLEAN].prot_sect |= PMD_BIT4; mem_types[MT_MINICLEAN].prot_sect |= PMD_BIT4;
mem_types[MT_VECTORS].prot_l1 |= PMD_BIT4; mem_types[MT_VECTORS].prot_l1 |= PMD_BIT4;
mem_types[MT_MEMORY].prot_sect |= PMD_BIT4; mem_types[MT_MEMORY].prot_sect |= PMD_BIT4;
mem_types[MT_ROM].prot_sect |= PMD_BIT4;
} }
/* /*
...@@ -370,6 +375,7 @@ static void __init build_mem_type_table(void) ...@@ -370,6 +375,7 @@ static void __init build_mem_type_table(void)
* kernel memory mapping. * kernel memory mapping.
*/ */
mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4;
mem_types[MT_ROM].prot_sect &= ~PMD_BIT4;
/* /*
* Mark cache clean areas read only from SVC mode * Mark cache clean areas read only from SVC mode
* and no access from userspace. * and no access from userspace.
...@@ -389,6 +395,7 @@ static void __init build_mem_type_table(void) ...@@ -389,6 +395,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_VECTORS].prot_l1 |= ecc_mask;
mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
mem_types[MT_ROM].prot_sect |= cp->pmd;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]); unsigned long v = pgprot_val(protection_map[i]);
...@@ -426,14 +433,14 @@ static void __init create_mapping(struct map_desc *md) ...@@ -426,14 +433,14 @@ static void __init create_mapping(struct map_desc *md)
pgprot_t prot_pte; pgprot_t prot_pte;
long off; long off;
if (md->virtual != vectors_base() && md->virtual < PAGE_OFFSET) { if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
printk(KERN_WARNING "BUG: not creating mapping for " printk(KERN_WARNING "BUG: not creating mapping for "
"0x%08lx at 0x%08lx in user region\n", "0x%08lx at 0x%08lx in user region\n",
md->physical, md->virtual); md->physical, md->virtual);
return; return;
} }
if (md->type == MT_DEVICE && if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx " printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx "
"overlaps vmalloc space\n", "overlaps vmalloc space\n",
...@@ -508,6 +515,8 @@ void setup_mm_for_reboot(char mode) ...@@ -508,6 +515,8 @@ void setup_mm_for_reboot(char mode)
} }
} }
extern void _stext, _etext;
/* /*
* Setup initial mappings. We use the page we allocated for zero page to hold * Setup initial mappings. We use the page we allocated for zero page to hold
* the mappings, which will get overwritten by the vectors in traps_init(). * the mappings, which will get overwritten by the vectors in traps_init().
...@@ -523,6 +532,14 @@ void __init memtable_init(struct meminfo *mi) ...@@ -523,6 +532,14 @@ void __init memtable_init(struct meminfo *mi)
init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE); init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE);
#ifdef CONFIG_XIP_KERNEL
p->physical = CONFIG_XIP_PHYS_ADDR & PMD_MASK;
p->virtual = (unsigned long)&_stext & PMD_MASK;
p->length = ((unsigned long)&_etext - p->virtual + ~PMD_MASK) & PMD_MASK;
p->type = MT_ROM;
p ++;
#endif
for (i = 0; i < mi->nr_banks; i++) { for (i = 0; i < mi->nr_banks; i++) {
if (mi->bank[i].size == 0) if (mi->bank[i].size == 0)
continue; continue;
......
/*
* include/asm-arm/arch-iop3xx/serial.h
*/
#include <linux/config.h>
/*
* This assumes you have a 1.8432 MHz clock for your UART.
*
* It'd be nice if someone built a serial card with a 24.576 MHz
* clock, since the 16550A is capable of handling a top speed of 1.5
* megabits/second; but this requires the faster clock.
*/
#define BASE_BAUD ( 1843200 / 16 )
/* Standard COM flags */
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
#ifdef CONFIG_ARCH_IQ80321
#define IRQ_UART1 IRQ_IQ80321_UART
#define RS_TABLE_SIZE 1
#define STD_SERIAL_PORT_DEFNS \
/* UART CLK PORT IRQ FLAGS */ \
{ 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS }, /* ttyS0 */
#endif // CONFIG_ARCH_IQ80321
#ifdef CONFIG_ARCH_IQ31244
#define IRQ_UART1 IRQ_IQ31244_UART
#define RS_TABLE_SIZE 1
#define STD_SERIAL_PORT_DEFNS \
/* UART CLK PORT IRQ FLAGS */ \
{ 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS }, /* ttyS0 */
#endif // CONFIG_ARCH_IQ31244
#ifdef CONFIG_ARCH_IQ80331
#undef BASE_BAUD
#define BASE_BAUD ( 33334000 / 16 )
#define IRQ_UART0 IRQ_IQ80331_UART0
#define IRQ_UART1 IRQ_IQ80331_UART1
#define RS_TABLE_SIZE 2
#define STD_SERIAL_PORT_DEFNS \
{ \
/*type: PORT_XSCALE,*/ \
/*xmit_fifo_size: 32,*/ \
baud_base: BASE_BAUD, \
irq: IRQ_UART0, \
flags: STD_COM_FLAGS, \
iomem_base: IQ80331_UART0_VIRT, \
io_type: SERIAL_IO_MEM, \
iomem_reg_shift: 2 \
}, /* ttyS0 */ \
{ \
/*type: PORT_XSCALE,*/ \
/*xmit_fifo_size: 32,*/ \
baud_base: BASE_BAUD, \
irq: IRQ_UART1, \
flags: STD_COM_FLAGS, \
iomem_base: IQ80331_UART1_VIRT, \
io_type: SERIAL_IO_MEM, \
iomem_reg_shift: 2 \
} /* ttyS1 */
#endif // CONFIG_ARCH_IQ80331
#define EXTRA_SERIAL_PORT_DEFNS
...@@ -20,15 +20,15 @@ ...@@ -20,15 +20,15 @@
#ifdef CONFIG_CPU_S3C2440 #ifdef CONFIG_CPU_S3C2440
#define S3C2440_DSC0 S3C2410_GPIOREG(0xc0) #define S3C2440_DSC0 S3C2410_GPIOREG(0xc4)
#define S3C2440_DSC1 S3C2410_GPIOREG(0xc4) #define S3C2440_DSC1 S3C2410_GPIOREG(0xc8)
#define S3C2440_SELECT_DSC0 (0) #define S3C2440_SELECT_DSC0 (0)
#define S3C2440_SELECT_DSC1 (1<<31) #define S3C2440_SELECT_DSC1 (1<<31)
#define S3C2440_DSC_GETSHIFT(x) ((x) & 31) #define S3C2440_DSC_GETSHIFT(x) ((x) & 31)
#define S3C2440_DSC0_ENABLE (1<<31) #define S3C2440_DSC0_DISABLE (1<<31)
#define S3C2440_DSC0_ADDR (S3C2440_SELECT_DSC0 | 8) #define S3C2440_DSC0_ADDR (S3C2440_SELECT_DSC0 | 8)
#define S3C2440_DSC0_ADDR_12mA (0<<8) #define S3C2440_DSC0_ADDR_12mA (0<<8)
...@@ -69,19 +69,19 @@ ...@@ -69,19 +69,19 @@
#define S3C2440_DSC0_DATA0_6mA (3<<0) #define S3C2440_DSC0_DATA0_6mA (3<<0)
#define S3C2440_DSC0_DATA0_MASK (3<<0) #define S3C2440_DSC0_DATA0_MASK (3<<0)
#define S3C2440_DSC1_SCK0 (S3C2440_SELECT_DSC1 | 28) #define S3C2440_DSC1_SCK1 (S3C2440_SELECT_DSC1 | 28)
#define S3C2440_DSC1_SCK0_12mA (0<<28) #define S3C2440_DSC1_SCK1_12mA (0<<28)
#define S3C2440_DSC1_SCK0_10mA (1<<28) #define S3C2440_DSC1_SCK1_10mA (1<<28)
#define S3C2440_DSC1_SCK0_8mA (2<<28) #define S3C2440_DSC1_SCK1_8mA (2<<28)
#define S3C2440_DSC1_SCK0_6mA (3<<28) #define S3C2440_DSC1_SCK1_6mA (3<<28)
#define S3C2440_DSC1_SCK0_MASK (3<<28) #define S3C2440_DSC1_SCK1_MASK (3<<28)
#define S3C2440_DSC1_SCK1 (S3C2440_SELECT_DSC1 | 26) #define S3C2440_DSC1_SCK0 (S3C2440_SELECT_DSC1 | 26)
#define S3C2440_DSC1_SCK1_12mA (0<<26) #define S3C2440_DSC1_SCK0_12mA (0<<26)
#define S3C2440_DSC1_SCK1_10mA (1<<26) #define S3C2440_DSC1_SCK0_10mA (1<<26)
#define S3C2440_DSC1_SCK1_8mA (2<<26) #define S3C2440_DSC1_SCK0_8mA (2<<26)
#define S3C2440_DSC1_SCK1_6mA (3<<26) #define S3C2440_DSC1_SCK0_6mA (3<<26)
#define S3C2440_DSC1_SCK1_MASK (3<<26) #define S3C2440_DSC1_SCK0_MASK (3<<26)
#define S3C2440_DSC1_SCKE (S3C2440_SELECT_DSC1 | 24) #define S3C2440_DSC1_SCKE (S3C2440_SELECT_DSC1 | 24)
#define S3C2440_DSC1_SCKE_10mA (0<<24) #define S3C2440_DSC1_SCKE_10mA (0<<24)
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* *
* Changelog: * Changelog:
* 03-Oct-2004 BJD Initial include for Linux * 03-Oct-2004 BJD Initial include for Linux
* 08-Nov-2004 BJD Added S3C2440 filter register
*/ */
#ifndef __ASM_ARCH_REGS_IIC_H #ifndef __ASM_ARCH_REGS_IIC_H
...@@ -24,6 +25,7 @@ ...@@ -24,6 +25,7 @@
#define S3C2410_IICSTAT S3C2410_IICREG(0x04) #define S3C2410_IICSTAT S3C2410_IICREG(0x04)
#define S3C2410_IICADD S3C2410_IICREG(0x08) #define S3C2410_IICADD S3C2410_IICREG(0x08)
#define S3C2410_IICDS S3C2410_IICREG(0x0C) #define S3C2410_IICDS S3C2410_IICREG(0x0C)
#define S3C2440_IICLC S3C2410_IICREG(0x10)
#define S3C2410_IICCON_ACKEN (1<<7) #define S3C2410_IICCON_ACKEN (1<<7)
#define S3C2410_IICCON_TXDIV_16 (0<<6) #define S3C2410_IICCON_TXDIV_16 (0<<6)
...@@ -47,4 +49,12 @@ ...@@ -47,4 +49,12 @@
#define S3C2410_IICSTAT_ADDR0 (1<<1) #define S3C2410_IICSTAT_ADDR0 (1<<1)
#define S3C2410_IICSTAT_LASTBIT (1<<0) #define S3C2410_IICSTAT_LASTBIT (1<<0)
#define S3C2410_IICLC_SDA_DELAY0 (0 << 0)
#define S3C2410_IICLC_SDA_DELAY5 (1 << 0)
#define S3C2410_IICLC_SDA_DELAY10 (2 << 0)
#define S3C2410_IICLC_SDA_DELAY15 (3 << 0)
#define S3C2410_IICLC_SDA_DELAY_MASK (3 << 0)
#define S3C2410_IICLC_FILTER_ON (1<<2)
#endif /* __ASM_ARCH_REGS_IIC_H */ #endif /* __ASM_ARCH_REGS_IIC_H */
...@@ -2,18 +2,33 @@ ...@@ -2,18 +2,33 @@
* linux/include/asm-arm/mach/flash.h * linux/include/asm-arm/mach/flash.h
* *
* Copyright (C) 2003 Russell King, All Rights Reserved. * Copyright (C) 2003 Russell King, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/ */
#ifndef ASMARM_MACH_FLASH_H #ifndef ASMARM_MACH_FLASH_H
#define ASMAMR_MACH_FLASH_H #define ASMARM_MACH_FLASH_H
struct mtd_partition; struct mtd_partition;
/*
* map_name: the map probe function name
* width: width of mapped device
* init: method called at driver/device initialisation
* exit: method called at driver/device removal
* set_vpp: method called to enable or disable VPP
* parts: optional array of mtd_partitions for static partitioning
* nr_parts: number of mtd_partitions for static partitoning
*/
struct flash_platform_data { struct flash_platform_data {
const char *map_name; const char *map_name;
int width; unsigned int width;
int (*init)(void); int (*init)(void);
void (*exit)(void); void (*exit)(void);
void (*set_vpp)(int on); void (*set_vpp)(int on);
struct mtd_partition *parts;
unsigned int nr_parts;
}; };
#endif #endif
...@@ -23,6 +23,7 @@ struct meminfo; ...@@ -23,6 +23,7 @@ struct meminfo;
#define MT_MINICLEAN 2 #define MT_MINICLEAN 2
#define MT_VECTORS 3 #define MT_VECTORS 3
#define MT_MEMORY 4 #define MT_MEMORY 4
#define MT_ROM 5
extern void create_memmap_holes(struct meminfo *); extern void create_memmap_holes(struct meminfo *);
extern void memtable_init(struct meminfo *); extern void memtable_init(struct meminfo *);
......
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