From be6f72aa718d9d7ed053298b85a9dca1d5c338d5 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 9 Nov 2004 10:01:11 +0000 Subject: [ARM PATCH] 2215/1: S3C2410 - i2c registers for s3c2440a Patch from Ben Dooks Added S3C2440_IICLC register definitions Signed-off-by: Ben Dooks Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/regs-iic.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include') diff --git a/include/asm-arm/arch-s3c2410/regs-iic.h b/include/asm-arm/arch-s3c2410/regs-iic.h index 381ab4baf208..fed3288e2046 100644 --- a/include/asm-arm/arch-s3c2410/regs-iic.h +++ b/include/asm-arm/arch-s3c2410/regs-iic.h @@ -11,6 +11,7 @@ * * Changelog: * 03-Oct-2004 BJD Initial include for Linux + * 08-Nov-2004 BJD Added S3C2440 filter register */ #ifndef __ASM_ARCH_REGS_IIC_H @@ -24,6 +25,7 @@ #define S3C2410_IICSTAT S3C2410_IICREG(0x04) #define S3C2410_IICADD S3C2410_IICREG(0x08) #define S3C2410_IICDS S3C2410_IICREG(0x0C) +#define S3C2440_IICLC S3C2410_IICREG(0x10) #define S3C2410_IICCON_ACKEN (1<<7) #define S3C2410_IICCON_TXDIV_16 (0<<6) @@ -47,4 +49,12 @@ #define S3C2410_IICSTAT_ADDR0 (1<<1) #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 */ -- cgit v1.2.3 From 738ddd43a0b596f25e227836400da5336615ee14 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Nov 2004 23:33:40 +0000 Subject: [ARM] Add static partitioning information to flash_platform_data. --- include/asm-arm/mach/flash.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-arm/mach/flash.h b/include/asm-arm/mach/flash.h index f7b86a1be96d..a92887d4b2cb 100644 --- a/include/asm-arm/mach/flash.h +++ b/include/asm-arm/mach/flash.h @@ -2,18 +2,33 @@ * linux/include/asm-arm/mach/flash.h * * 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 -#define ASMAMR_MACH_FLASH_H +#define ASMARM_MACH_FLASH_H 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 { const char *map_name; - int width; + unsigned int width; int (*init)(void); void (*exit)(void); void (*set_vpp)(int on); + struct mtd_partition *parts; + unsigned int nr_parts; }; #endif -- cgit v1.2.3 From 5bffe1b1ac1ead8c9b07bcba90aee11c9e9e20d1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 10 Nov 2004 00:13:49 +0000 Subject: [ARM PATCH] 2220/1: S3C2410 - regs-dsc.h fixes Patch from Ben Dooks The following fixes are included: - fix the addresses of S3C2440_DSCx (off by 4) - SCK0/SCK1 definitions the wrong way around - renable ENABLE to DISABLE Signed-off-by: Ben Dooks Signed-off-by: Russell King --- include/asm-arm/arch-s3c2410/regs-dsc.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/asm-arm/arch-s3c2410/regs-dsc.h b/include/asm-arm/arch-s3c2410/regs-dsc.h index 0da1ec7b7675..a023b0434efe 100644 --- a/include/asm-arm/arch-s3c2410/regs-dsc.h +++ b/include/asm-arm/arch-s3c2410/regs-dsc.h @@ -20,15 +20,15 @@ #ifdef CONFIG_CPU_S3C2440 -#define S3C2440_DSC0 S3C2410_GPIOREG(0xc0) -#define S3C2440_DSC1 S3C2410_GPIOREG(0xc4) +#define S3C2440_DSC0 S3C2410_GPIOREG(0xc4) +#define S3C2440_DSC1 S3C2410_GPIOREG(0xc8) #define S3C2440_SELECT_DSC0 (0) #define S3C2440_SELECT_DSC1 (1<<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_12mA (0<<8) @@ -69,19 +69,19 @@ #define S3C2440_DSC0_DATA0_6mA (3<<0) #define S3C2440_DSC0_DATA0_MASK (3<<0) -#define S3C2440_DSC1_SCK0 (S3C2440_SELECT_DSC1 | 28) -#define S3C2440_DSC1_SCK0_12mA (0<<28) -#define S3C2440_DSC1_SCK0_10mA (1<<28) -#define S3C2440_DSC1_SCK0_8mA (2<<28) -#define S3C2440_DSC1_SCK0_6mA (3<<28) -#define S3C2440_DSC1_SCK0_MASK (3<<28) - -#define S3C2440_DSC1_SCK1 (S3C2440_SELECT_DSC1 | 26) -#define S3C2440_DSC1_SCK1_12mA (0<<26) -#define S3C2440_DSC1_SCK1_10mA (1<<26) -#define S3C2440_DSC1_SCK1_8mA (2<<26) -#define S3C2440_DSC1_SCK1_6mA (3<<26) -#define S3C2440_DSC1_SCK1_MASK (3<<26) +#define S3C2440_DSC1_SCK1 (S3C2440_SELECT_DSC1 | 28) +#define S3C2440_DSC1_SCK1_12mA (0<<28) +#define S3C2440_DSC1_SCK1_10mA (1<<28) +#define S3C2440_DSC1_SCK1_8mA (2<<28) +#define S3C2440_DSC1_SCK1_6mA (3<<28) +#define S3C2440_DSC1_SCK1_MASK (3<<28) + +#define S3C2440_DSC1_SCK0 (S3C2440_SELECT_DSC1 | 26) +#define S3C2440_DSC1_SCK0_12mA (0<<26) +#define S3C2440_DSC1_SCK0_10mA (1<<26) +#define S3C2440_DSC1_SCK0_8mA (2<<26) +#define S3C2440_DSC1_SCK0_6mA (3<<26) +#define S3C2440_DSC1_SCK0_MASK (3<<26) #define S3C2440_DSC1_SCKE (S3C2440_SELECT_DSC1 | 24) #define S3C2440_DSC1_SCKE_10mA (0<<24) -- cgit v1.2.3 From e9edaa3d5c5bfd7d8d24cfa621350a6ada3918f6 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 10 Nov 2004 00:47:09 +0000 Subject: [ARM PATCH] 2223/1: convert serial UART to platform device on iop3xx Patch from Dave Jiang Converting IOP321 UART to platform device Remove asm/arch/serial.h dependency Signed-off-by: Dave Jiang Signed-off-by: Russell King --- arch/arm/mach-iop3xx/Makefile | 2 +- arch/arm/mach-iop3xx/iop321-mm.c | 43 -------------------- arch/arm/mach-iop3xx/iop321-setup.c | 67 ++++++++++++++++++++++++++----- include/asm-arm/arch-iop3xx/serial.h | 76 ------------------------------------ 4 files changed, 59 insertions(+), 129 deletions(-) delete mode 100644 arch/arm/mach-iop3xx/iop321-mm.c delete mode 100644 include/asm-arm/arch-iop3xx/serial.h (limited to 'include') diff --git a/arch/arm/mach-iop3xx/Makefile b/arch/arm/mach-iop3xx/Makefile index dcbffb66d8de..e633dd9f4b26 100644 --- a/arch/arm/mach-iop3xx/Makefile +++ b/arch/arm/mach-iop3xx/Makefile @@ -10,7 +10,7 @@ obj-m := obj-n := 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 diff --git a/arch/arm/mach-iop3xx/iop321-mm.c b/arch/arm/mach-iop3xx/iop321-mm.c deleted file mode 100644 index 818a54872c7a..000000000000 --- a/arch/arm/mach-iop3xx/iop321-mm.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * linux/arch/arm/mach-iop3xx/mm.c - * - * Low level memory initialization for IOP321 based systems - * - * Author: Rory Bolt - * 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 -#include - -#include -#include -#include - -#include -#include - - -/* - * 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)); -} diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c index b21899af763b..12e4a787b836 100644 --- a/arch/arm/mach-iop3xx/iop321-setup.c +++ b/arch/arm/mach-iop3xx/iop321-setup.c @@ -9,11 +9,21 @@ * published by the Free Software Foundation. * */ +#include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -21,6 +31,52 @@ #include #include +#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 extern void iq80321_map_io(void); extern struct sys_timer iop321_timer; @@ -33,24 +89,17 @@ extern struct sys_timer iop321_timer; extern void iop321_init_time(void); #endif -static void __init -fixup_iop321(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -} - #if defined(CONFIG_ARCH_IQ80321) MACHINE_START(IQ80321, "Intel IQ80321") MAINTAINER("Intel Corporation") - BOOT_MEM(PHYS_OFFSET, IQ80321_UART, 0xfe800000) - FIXUP(fixup_iop321) + BOOT_MEM(PHYS_OFFSET, IQ80321_UART, IQ80321_UART) MAPIO(iq80321_map_io) INITIRQ(iop321_init_irq) .timer = &iop321_timer, BOOT_PARAMS(0xa0000100) MACHINE_END #elif defined(CONFIG_ARCH_IQ31244) - MACHINE_START(IQ31244, "Intel IQ31244") +MACHINE_START(IQ31244, "Intel IQ31244") MAINTAINER("Intel Corp.") BOOT_MEM(PHYS_OFFSET, IQ31244_UART, IQ31244_UART) MAPIO(iq31244_map_io) diff --git a/include/asm-arm/arch-iop3xx/serial.h b/include/asm-arm/arch-iop3xx/serial.h deleted file mode 100644 index 61192f98c066..000000000000 --- a/include/asm-arm/arch-iop3xx/serial.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * include/asm-arm/arch-iop3xx/serial.h - */ -#include - -/* - * 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 - -- cgit v1.2.3 From 457450ab3b946006299131970d8e1296db494a1e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 10 Nov 2004 14:37:18 +0000 Subject: [ARM PATCH] 2154/2: XIP kernel for ARM Patch from Nicolas Pitre This patch allows for the kernel to be configured for XIP. A lot of people are using semi hacked up XIP patches already so it is a good idea to have a generic and clean implementation supporting all ARM targets. The patch isn't too intrusive. It involves: - modifying the kernel entry code to map separate .text and .data sections in the initial page table, as well as relocating .data to ram when needed - modifying the linker script to account for the different VMA and LMA for .data, as well as making sure that .init.data gets relocated to ram - adding the final kernel mapping with a new MT_ROM mem type - distinguishing between XIP and non-XIP for bootmem and memory resource declaration - and adding proper target handling to Makefiles. While at it, this also cleans up the kernel boot code a bit so the kernel can now be compiled for any address in ram, removing the need for a relation between kernel address and start of ram. Also throws in some more comments. And finally the _text, _etext, _end and similar variables are now declared extern void instead of extern char, or even extern int. That allows for operations on their address directly without any cast, and trying to reference them by mistake would yield an error which is a good thing. Tested both configurations: XIP and non XIP, the later producing a kernel for execution from ram just as before. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig | 44 +++++++++++++++++ arch/arm/Makefile | 20 ++++++-- arch/arm/boot/Makefile | 21 ++++++++- arch/arm/kernel/Makefile | 2 +- arch/arm/kernel/asm-offsets.c | 2 + arch/arm/kernel/head.S | 107 ++++++++++++++++++++++++++++++------------ arch/arm/kernel/setup.c | 12 ++--- arch/arm/kernel/vmlinux.lds.S | 31 +++++++++--- arch/arm/mm/init.c | 8 +++- arch/arm/mm/mm-armv.c | 19 +++++++- include/asm-arm/mach/map.h | 1 + 11 files changed, 215 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dd96dde542bc..6da1af1b5425 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -343,6 +343,50 @@ config ZBOOT_ROM_BSS while the decompressor is running. Unless you have special requirements, 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) config CPU_FREQ diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 9e6900c890ad..56ebbcca7fa1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -65,8 +65,6 @@ AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float CHECKFLAGS += -D__arm__ #Default value -DATAADDR := . - head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o textaddr-y := 0xC0008000 @@ -110,6 +108,15 @@ export CFLAGS_3c589_cs.o endif TEXTADDR := $(textaddr-y) +ifeq ($(CONFIG_XIP_KERNEL),y) + DATAADDR := $(TEXTADDR) + # Replace phys addr with virt addr while keeping offset from base. + xipaddr-y ?= 0xe8000000 + 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),) incdir-y := $(machine-y) endif @@ -120,7 +127,7 @@ else MACHINE := endif -export TEXTADDR GZFLAGS +export TEXTADDR DATAADDR GZFLAGS # Do we have FASTFPE? FASTFPE :=arch/arm/fastfpe @@ -142,7 +149,11 @@ drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ libs-y += arch/arm/lib/ # Default target when executing plain make +ifeq ($(CONFIG_XIP_KERNEL),y) +all: xipImage +else all: zImage +endif boot := arch/arm/boot @@ -169,7 +180,7 @@ maketools: include/asm-arm/constants.h include/linux/version.h FORCE # Convert bzImage to zImage bzImage: zImage -zImage Image bootpImage uImage: vmlinux +zImage Image xipImage bootpImage uImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ zinstall install: vmlinux @@ -195,6 +206,7 @@ include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s define archhelp echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' 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 ' (supply initrd image via make variable INITRD=)' echo ' install - Install uncompressed kernel' diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index d17494a822c3..937a353bc37c 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -24,7 +24,24 @@ INITRD_PHYS := $(initrd_phys-y) 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 $(call if_changed,objcopy) @@ -37,6 +54,8 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) @echo ' Kernel: $@ is ready' +endif + quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ -C none -a $(ZRELADDR) -e $(ZRELADDR) \ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 936dee40e5e7..7c56c5589e3f 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) +AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) # Object file lists. diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 3f22b6356cd8..93525fdf2ff8 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -14,6 +14,7 @@ #include #include #include +#include /* * Make sure that the compiler and target are compatible. @@ -72,6 +73,7 @@ int main(void) DEFINE(VM_EXEC, VM_EXEC); BLANK(); DEFINE(PAGE_SZ, PAGE_SIZE); + DEFINE(VIRT_OFFSET, PAGE_OFFSET); BLANK(); DEFINE(SYS_ERROR0, 0x9f0000); BLANK(); diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 6958a8b3faeb..933ab867a19d 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -19,17 +19,16 @@ #include #include +#ifndef CONFIG_XIP_KERNEL /* * We place the page tables 16K below TEXTADDR. Therefore, we must make sure * that TEXTADDR is correctly set. Currently, we expect the least significant * 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 * pgtbl gives us a position-independent reference to these tables. We can * do this because stext == TEXTADDR - * - * swapper_pg_dir, pgtbl and krnladr are all closely related. */ #if (TEXTADDR & 0xffff) != 0x8000 #error TEXTADDR must start at 0xXXXX8000 @@ -38,19 +37,35 @@ .globl swapper_pg_dir .equ swapper_pg_dir, TEXTADDR - 0x4000 - .macro pgtbl, reg - adr \reg, stext - sub \reg, \reg, #0x4000 + .macro pgtbl, rd, phys + adr \rd, stext + sub \rd, \rd, #0x4000 .endm - +#else /* - * Since the page table is closely related to the kernel start address, we - * can convert the page table base address to the base address of the section - * containing both. + * XIP Kernel: + * + * 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 - bic \rd, \pgtable, #0x000ff000 +#if (DATAADDR & 0xffff) != 0x8000 +#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 +#endif /* * Kernel startup entry point. @@ -99,6 +114,8 @@ ENTRY(stext) .type __switch_data, %object __switch_data: .long __mmap_switched + .long __data_loc @ r2 + .long __data_start @ r3 .long __bss_start @ r4 .long _end @ r5 .long processor_id @ r6 @@ -136,12 +153,20 @@ __turn_mmu_on: */ .align 5 __mmap_switched: - adr r3, __switch_data + 4 - ldmia r3, {r4, r5, r6, r7, r8, sp} + adr r2, __switch_data + 4 + 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) 1: cmp r4, r5 strcc fp, [r4],#4 bcc 1b + str r9, [r6] @ Save processor ID str r1, [r7] @ Save machine type bic r2, r0, #2 @ Clear 'A' bit @@ -156,16 +181,13 @@ __mmap_switched: * amount which are required to get the kernel running, which * 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 * r6 = physical IO address * r7 = byte offset into page tables for IO * r8 = page table flags */ __create_page_tables: - pgtbl r4 @ page table address + pgtbl r4, r5 @ page table address /* * Clear the 16K level 1 swapper page table @@ -183,28 +205,50 @@ __create_page_tables: /* * Create identity mapping for first MB of kernel to * 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 - add r3, r8, r2 @ flags + kernel base - str r3, [r4, r2, lsr #18] @ identity mapping + mov r2, pc, lsr #20 @ start of kernel section + add r3, r8, r2, lsl #20 @ flags + kernel base + str r3, [r4, r2, lsl #2] @ identity mapping /* * Now setup the pagetables for our kernel direct * 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 - bic r2, r3, #0x00f00000 - str r2, [r0] @ PAGE_OFFSET + 0MB - add r0, r0, #(TEXTADDR & 0x00f00000) >> 18 - str r3, [r0], #4 @ KERNEL + 0MB + add r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel + str r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]! add r3, r3, #1 << 20 - str r3, [r0], #4 @ KERNEL + 1MB + str r3, [r0, #4]! @ KERNEL + 1MB add r3, r3, #1 << 20 - str r3, [r0], #4 @ KERNEL + 2MB + str r3, [r0, #4]! @ KERNEL + 2MB 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 @ and bufferable bits @@ -255,6 +299,7 @@ __create_page_tables: str r3, [r0] #endif mov pc, lr + .ltorg diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 35ca99adb33d..21d0a197a00a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -59,7 +59,7 @@ extern void convert_to_tag_list(struct tag *tags); extern void squash_mem_tags(struct tag *tag); extern void reboot_setup(char *str); 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 __machine_arch_type; @@ -113,7 +113,7 @@ static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', ' */ static struct resource mem_res[] = { { "Video RAM", 0, 0, IORESOURCE_MEM }, - { "Kernel code", 0, 0, IORESOURCE_MEM }, + { "Kernel text", 0, 0, IORESOURCE_MEM }, { "Kernel data", 0, 0, IORESOURCE_MEM } }; @@ -447,10 +447,10 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) struct resource *res; int i; - kernel_code.start = __virt_to_phys(init_mm.start_code); - kernel_code.end = __virt_to_phys(init_mm.end_code - 1); - kernel_data.start = __virt_to_phys(init_mm.end_code); - kernel_data.end = __virt_to_phys(init_mm.brk - 1); + kernel_code.start = virt_to_phys(&_text); + kernel_code.end = virt_to_phys(&_etext - 1); + kernel_data.start = virt_to_phys(&__data_start); + kernel_data.end = virt_to_phys(&_end - 1); for (i = 0; i < mi->nr_banks; i++) { unsigned long virt_start, virt_end; diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 1131500de2ad..0a400eab75f6 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -4,6 +4,7 @@ */ #include +#include OUTPUT_ARCH(arm) ENTRY(stext) @@ -17,7 +18,6 @@ SECTIONS . = TEXTADDR; .init : { /* Init code and data */ _stext = .; - __init_begin = .; _sinittext = .; *(.init.text) _einittext = .; @@ -30,7 +30,6 @@ SECTIONS __tagtable_begin = .; *(.taglist) __tagtable_end = .; - *(.init.data) . = ALIGN(16); __setup_start = .; *(.init.setup) @@ -57,8 +56,12 @@ SECTIONS __initramfs_start = .; usr/built-in.o(.init.ramfs) __initramfs_end = .; +#ifndef CONFIG_XIP_KERNEL + __init_begin = _stext; + *(.init.data) . = ALIGN(4096); __init_end = .; +#endif } /DISCARD/ : { /* Exit code and data */ @@ -79,8 +82,6 @@ SECTIONS *(.glue_7) *(.glue_7t) *(.got) /* Global offset table */ - - _etext = .; /* End of text section */ } . = ALIGN(16); @@ -92,15 +93,33 @@ SECTIONS RODATA + _etext = .; /* End of text and rodata section */ + +#ifdef CONFIG_XIP_KERNEL + __data_loc = ALIGN(4); /* location in binary */ + . = DATAADDR; +#else . = ALIGN(8192); + __data_loc = .; +#endif + + .data : AT(__data_loc) { + __data_start = .; /* address in memory */ - .data : { /* * first, the init task union, aligned * to an 8192 byte boundary. */ *(.init.task) +#ifdef CONFIG_XIP_KERNEL + . = ALIGN(4096); + __init_begin = .; + *(.init.data) + . = ALIGN(4096); + __init_end = .; +#endif + . = ALIGN(4096); __nosave_begin = .; *(.data.nosave) @@ -126,7 +145,7 @@ SECTIONS __bss_start = .; /* BSS */ *(.bss) *(COMMON) - _end = . ; + _end = .; } /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index d7b4441ace2d..51f3be19ec41 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -30,7 +30,7 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 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_size; @@ -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. * 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); +#endif /* * Reserve the page tables. These are already in use, @@ -540,7 +544,7 @@ void __init mem_init(void) int i, node; codepages = &_etext - &_text; - datapages = &_end - &_etext; + datapages = &_end - &__data_start; initpages = &__init_end - &__init_begin; #ifndef CONFIG_DISCONTIGMEM diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 50c2c0f8d717..77529a36653e 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -326,6 +326,10 @@ static struct mem_types mem_types[] __initdata = { [MT_MEMORY] = { .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .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) mem_types[MT_MINICLEAN].prot_sect |= PMD_BIT4; mem_types[MT_VECTORS].prot_l1 |= 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) * kernel memory mapping. */ 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 * and no access from userspace. @@ -389,6 +395,7 @@ static void __init build_mem_type_table(void) mem_types[MT_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; + mem_types[MT_ROM].prot_sect |= cp->pmd; for (i = 0; i < 16; i++) { unsigned long v = pgprot_val(protection_map[i]); @@ -433,7 +440,7 @@ static void __init create_mapping(struct map_desc *md) return; } - if (md->type == MT_DEVICE && + if ((md->type == MT_DEVICE || md->type == MT_ROM) && md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx " "overlaps vmalloc space\n", @@ -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 * the mappings, which will get overwritten by the vectors in traps_init(). @@ -534,6 +543,14 @@ void __init memtable_init(struct meminfo *mi) p ++; } +#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 + #ifdef FLUSH_BASE p->physical = FLUSH_BASE_PHYS; p->virtual = FLUSH_BASE; diff --git a/include/asm-arm/mach/map.h b/include/asm-arm/mach/map.h index 284df8bb76d1..2a75545a2d04 100644 --- a/include/asm-arm/mach/map.h +++ b/include/asm-arm/mach/map.h @@ -23,6 +23,7 @@ struct meminfo; #define MT_MINICLEAN 2 #define MT_VECTORS 3 #define MT_MEMORY 4 +#define MT_ROM 5 extern void create_memmap_holes(struct meminfo *); extern void memtable_init(struct meminfo *); -- cgit v1.2.3