diff options
277 files changed, 12016 insertions, 1563 deletions
diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt index 9d58c7c5edd..eb0fae18ffb 100644 --- a/Documentation/arm/memory.txt +++ b/Documentation/arm/memory.txt @@ -59,7 +59,11 @@ PAGE_OFFSET	high_memory-1	Kernel direct-mapped RAM region.  				This maps the platforms RAM, and typically  				maps all platform RAM in a 1:1 relationship. -TASK_SIZE	PAGE_OFFSET-1	Kernel module space +PKMAP_BASE	PAGE_OFFSET-1	Permanent kernel mappings +				One way of mapping HIGHMEM pages into kernel +				space. + +MODULES_VADDR	MODULES_END-1	Kernel module space  				Kernel modules inserted via insmod are  				placed here using dynamic mappings. diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt index da42ab414c4..74a8b6fefa2 100644 --- a/Documentation/cachetlb.txt +++ b/Documentation/cachetlb.txt @@ -88,12 +88,12 @@ changes occur:  	This is used primarily during fault processing.  5) void update_mmu_cache(struct vm_area_struct *vma, -			 unsigned long address, pte_t pte) +			 unsigned long address, pte_t *ptep)  	At the end of every page fault, this routine is invoked to  	tell the architecture specific code that a translation -	described by "pte" now exists at virtual address "address" -	for address space "vma->vm_mm", in the software page tables. +	now exists at virtual address "address" for address space +	"vma->vm_mm", in the software page tables.  	A port may use this information in any way it so chooses.  	For example, it could use this event to pre-load TLB diff --git a/arch/alpha/include/asm/pgtable.h b/arch/alpha/include/asm/pgtable.h index 3f0c59f6d8a..71a24329414 100644 --- a/arch/alpha/include/asm/pgtable.h +++ b/arch/alpha/include/asm/pgtable.h @@ -329,7 +329,7 @@ extern pgd_t swapper_pg_dir[1024];   * tables contain all the necessary information.   */  extern inline void update_mmu_cache(struct vm_area_struct * vma, -	unsigned long address, pte_t pte) +	unsigned long address, pte_t *ptep)  {  } diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fb2a51b0ec1..e4a765438ee 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -12,6 +12,7 @@ config ARM  	select HAVE_IDE  	select RTC_LIB  	select SYS_SUPPORTS_APM_EMULATION +	select GENERIC_ATOMIC64 if (!CPU_32v6K)  	select HAVE_OPROFILE  	select HAVE_ARCH_KGDB  	select HAVE_KPROBES if (!XIP_KERNEL) @@ -20,6 +21,8 @@ config ARM  	select HAVE_GENERIC_DMA_COHERENT  	select HAVE_KERNEL_GZIP  	select HAVE_KERNEL_LZO +	select HAVE_PERF_EVENTS +	select PERF_USE_VMALLOC  	help  	  The ARM series is a line of low-power-consumption RISC chip designs  	  licensed by ARM Ltd and targeted at embedded applications and @@ -52,6 +55,9 @@ config HAVE_TCM  	bool  	select GENERIC_ALLOCATOR +config HAVE_PROC_CPU +	bool +  config NO_IOPORT  	bool @@ -161,6 +167,11 @@ config ARCH_MTD_XIP  config GENERIC_HARDIRQS_NO__DO_IRQ  	def_bool y +config ARM_L1_CACHE_SHIFT_6 +	bool +	help +	  Setting ARM L1 cache line size to 64 Bytes. +  if OPROFILE  config OPROFILE_ARMV6 @@ -550,6 +561,15 @@ config ARCH_W90X900  	  <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/  		ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller> +config ARCH_NUC93X +	bool "Nuvoton NUC93X CPU" +	select CPU_ARM926T +	select HAVE_CLK +	select COMMON_CLKDEV +	help +	  Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a +	  low-power and high performance MPEG-4/JPEG multimedia controller chip. +  config ARCH_PNX4008  	bool "Philips Nexperia PNX4008 Mobile"  	select CPU_ARM926T @@ -639,6 +659,7 @@ config ARCH_S5PC1XX  	select GENERIC_GPIO  	select HAVE_CLK  	select CPU_V7 +	select ARM_L1_CACHE_SHIFT_6  	help  	  Samsung S5PC1XX series based systems @@ -785,6 +806,8 @@ source "arch/arm/plat-nomadik/Kconfig"  source "arch/arm/mach-ns9xxx/Kconfig" +source "arch/arm/mach-nuc93x/Kconfig" +  source "arch/arm/plat-omap/Kconfig"  source "arch/arm/mach-omap1/Kconfig" @@ -867,6 +890,11 @@ config XSCALE_PMU  	depends on CPU_XSCALE && !XSCALE_PMU_TIMER  	default y +config CPU_HAS_PMU +	depends on CPU_V6 || CPU_V7 || XSCALE_PMU +	default y +	bool +  if !MMU  source "arch/arm/Kconfig-nommu"  endif @@ -921,6 +949,19 @@ config ARM_ERRATA_460075  	  ACTLR register. Note that setting specific bits in the ACTLR register  	  may not be available in non-secure mode. +config PL310_ERRATA_588369 +	bool "Clean & Invalidate maintenance operations do not invalidate clean lines" +	depends on CACHE_L2X0 && ARCH_OMAP4 +	help +	   The PL310 L2 cache controller implements three types of Clean & +	   Invalidate maintenance operations: by Physical Address +	   (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC). +	   They are architecturally defined to behave as the execution of a +	   clean operation followed immediately by an invalidate operation, +	   both performing to the same memory location. This functionality +	   is not correctly implemented in PL310 as clean lines are not +	   invalidated as a result of these operations. Note that this errata +	   uses Texas Instrument's secure monitor api.  endmenu  source "arch/arm/common/Kconfig" @@ -1171,6 +1212,14 @@ config HIGHPTE  	depends on HIGHMEM  	depends on !OUTER_CACHE +config HW_PERF_EVENTS +	bool "Enable hardware performance counter support for perf events" +	depends on PERF_EVENTS && CPU_HAS_PMU && (CPU_V6 || CPU_V7) +	default y +	help +	  Enable hardware performance counter support for perf events. If +	  disabled, perf events will use software events only. +  source "mm/Kconfig"  config LEDS @@ -1230,6 +1279,7 @@ config ALIGNMENT_TRAP  	bool  	depends on CPU_CP15_MMU  	default y if !ARCH_EBSA110 +	select HAVE_PROC_CPU if PROC_FS  	help  	  ARM processors cannot fetch/store information which is not  	  naturally aligned on the bus, i.e., a 4 byte fetch must start at an diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 9e758257274..52a820d4277 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -171,6 +171,7 @@ machine-$(CONFIG_ARCH_U300)		:= u300  machine-$(CONFIG_ARCH_U8500)		:= ux500  machine-$(CONFIG_ARCH_VERSATILE)	:= versatile  machine-$(CONFIG_ARCH_W90X900)		:= w90x900 +machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x  machine-$(CONFIG_FOOTBRIDGE)		:= footbridge  # Platform directory name.  This list is sorted alphanumerically diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 2d4d88ba73b..97c89e7de7d 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -5,7 +5,7 @@  #  HEAD	= head.o -OBJS	= misc.o +OBJS	= misc.o decompress.o  FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c  # @@ -106,10 +106,6 @@ lib1funcs = $(obj)/lib1funcs.o  $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE  	$(call cmd,shipped) -# Don't allow any static data in misc.o, which -# would otherwise mess up our GOT table -CFLAGS_misc.o := -Dstatic= -  $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \  	 	$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE  	$(call if_changed,ld) diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c new file mode 100644 index 00000000000..0da382f3315 --- /dev/null +++ b/arch/arm/boot/compressed/decompress.c @@ -0,0 +1,45 @@ +#define _LINUX_STRING_H_ + +#include <linux/compiler.h>	/* for inline */ +#include <linux/types.h>	/* for size_t */ +#include <linux/stddef.h>	/* for NULL */ +#include <linux/linkage.h> +#include <asm/string.h> + +extern unsigned long free_mem_ptr; +extern unsigned long free_mem_end_ptr; +extern void error(char *); + +#define STATIC static + +#define ARCH_HAS_DECOMP_WDOG + +/* Diagnostic functions */ +#ifdef DEBUG +#  define Assert(cond,msg) {if(!(cond)) error(msg);} +#  define Trace(x) fprintf x +#  define Tracev(x) {if (verbose) fprintf x ;} +#  define Tracevv(x) {if (verbose>1) fprintf x ;} +#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +#  define Assert(cond,msg) +#  define Trace(x) +#  define Tracev(x) +#  define Tracevv(x) +#  define Tracec(c,x) +#  define Tracecv(c,x) +#endif + +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif + +#ifdef CONFIG_KERNEL_LZO +#include "../../../../lib/decompress_unlzo.c" +#endif + +void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) +{ +	decompress(input, len, NULL, NULL, output, NULL, error); +} diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 4fddc509e78..99b75aa1c2e 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -22,13 +22,13 @@  #if defined(CONFIG_DEBUG_ICEDCC)  #ifdef CONFIG_CPU_V6 -		.macro	loadsp, rb +		.macro	loadsp, rb, tmp  		.endm  		.macro	writeb, ch, rb  		mcr	p14, 0, \ch, c0, c5, 0  		.endm  #elif defined(CONFIG_CPU_V7) -		.macro	loadsp, rb +		.macro	loadsp, rb, tmp  		.endm  		.macro	writeb, ch, rb  wait:		mrc	p14, 0, pc, c0, c1, 0 @@ -36,13 +36,13 @@ wait:		mrc	p14, 0, pc, c0, c1, 0  		mcr	p14, 0, \ch, c0, c5, 0  		.endm  #elif defined(CONFIG_CPU_XSCALE) -		.macro	loadsp, rb +		.macro	loadsp, rb, tmp  		.endm  		.macro	writeb, ch, rb  		mcr	p14, 0, \ch, c8, c0, 0  		.endm  #else -		.macro	loadsp, rb +		.macro	loadsp, rb, tmp  		.endm  		.macro	writeb, ch, rb  		mcr	p14, 0, \ch, c1, c0, 0 @@ -58,7 +58,7 @@ wait:		mrc	p14, 0, pc, c0, c1, 0  		.endm  #if defined(CONFIG_ARCH_SA1100) -		.macro	loadsp, rb +		.macro	loadsp, rb, tmp  		mov	\rb, #0x80000000	@ physical base address  #ifdef CONFIG_DEBUG_LL_SER3  		add	\rb, \rb, #0x00050000	@ Ser3 @@ -67,13 +67,13 @@ wait:		mrc	p14, 0, pc, c0, c1, 0  #endif  		.endm  #elif defined(CONFIG_ARCH_S3C2410) -		.macro loadsp, rb +		.macro loadsp, rb, tmp  		mov	\rb, #0x50000000  		add	\rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT  		.endm  #else -		.macro	loadsp,	rb -		addruart \rb +		.macro	loadsp,	rb, tmp +		addruart \rb, \tmp  		.endm  #endif  #endif @@ -1025,7 +1025,7 @@ phex:		adr	r3, phexbuf  		strb	r2, [r3, r1]  		b	1b -puts:		loadsp	r3 +puts:		loadsp	r3, r1  1:		ldrb	r2, [r0], #1  		teq	r2, #0  		moveq	pc, lr @@ -1042,7 +1042,7 @@ puts:		loadsp	r3  putc:  		mov	r2, r0  		mov	r0, #0 -		loadsp	r3 +		loadsp	r3, r1  		b	2b  memdump:	mov	r12, r0 diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 56a0d116d27..d32bc71c1f7 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -23,8 +23,8 @@ unsigned int __machine_arch_type;  #include <linux/compiler.h>	/* for inline */  #include <linux/types.h>	/* for size_t */  #include <linux/stddef.h>	/* for NULL */ -#include <asm/string.h>  #include <linux/linkage.h> +#include <asm/string.h>  #include <asm/unaligned.h> @@ -117,57 +117,7 @@ static void putstr(const char *ptr)  #endif -#define __ptr_t void * - -#define memzero(s,n) __memzero(s,n) - -/* - * Optimised C version of memzero for the ARM. - */ -void __memzero (__ptr_t s, size_t n) -{ -	union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; -	int i; - -	u.vp = s; - -	for (i = n >> 5; i > 0; i--) { -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -	} - -	if (n & 1 << 4) { -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -		*u.ulp++ = 0; -	} - -	if (n & 1 << 3) { -		*u.ulp++ = 0; -		*u.ulp++ = 0; -	} - -	if (n & 1 << 2) -		*u.ulp++ = 0; - -	if (n & 1 << 1) { -		*u.ucp++ = 0; -		*u.ucp++ = 0; -	} - -	if (n & 1) -		*u.ucp++ = 0; -} - -static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, -			    size_t __n) +void *memcpy(void *__dest, __const void *__src, size_t __n)  {  	int i = 0;  	unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; @@ -204,59 +154,20 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,  /*   * gzip delarations   */ -#define STATIC static - -/* Diagnostic functions */ -#ifdef DEBUG -#  define Assert(cond,msg) {if(!(cond)) error(msg);} -#  define Trace(x) fprintf x -#  define Tracev(x) {if (verbose) fprintf x ;} -#  define Tracevv(x) {if (verbose>1) fprintf x ;} -#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -#  define Assert(cond,msg) -#  define Trace(x) -#  define Tracev(x) -#  define Tracevv(x) -#  define Tracec(c,x) -#  define Tracecv(c,x) -#endif - -static void error(char *m); -  extern char input_data[];  extern char input_data_end[]; -static unsigned char *output_data; -static unsigned long output_ptr; - -static void error(char *m); - -static void putstr(const char *); +unsigned char *output_data; +unsigned long output_ptr; -static unsigned long free_mem_ptr; -static unsigned long free_mem_end_ptr; - -#ifdef STANDALONE_DEBUG -#define NO_INFLATE_MALLOC -#endif - -#define ARCH_HAS_DECOMP_WDOG - -#ifdef CONFIG_KERNEL_GZIP -#include "../../../../lib/decompress_inflate.c" -#endif - -#ifdef CONFIG_KERNEL_LZO -#include "../../../../lib/decompress_unlzo.c" -#endif +unsigned long free_mem_ptr; +unsigned long free_mem_end_ptr;  #ifndef arch_error  #define arch_error(x)  #endif -static void error(char *x) +void error(char *x)  {  	arch_error(x); @@ -272,6 +183,8 @@ asmlinkage void __div0(void)  	error("Attempting division by 0!");  } +extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); +  #ifndef STANDALONE_DEBUG  unsigned long @@ -292,8 +205,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,  	output_ptr = get_unaligned_le32(tmp);  	putstr("Uncompressing Linux..."); -	decompress(input_data, input_data_end - input_data, -			NULL, NULL, output_data, NULL, error); +	do_decompress(input_data, input_data_end - input_data, +			output_data, error);  	putstr(" done, booting the kernel.\n");  	return output_ptr;  } diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index a5924b9b88b..7ca9ecff652 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -14,6 +14,13 @@ SECTIONS    /DISCARD/ : {      *(.ARM.exidx*)      *(.ARM.extab*) +    /* +     * Discard any r/w data - this produces a link error if we have any, +     * which is required for PIC decompression.  Local data generates +     * GOTOFF relocations, which prevents it being relocated independently +     * of the text/got segments. +     */ +    *(.data)    }    . = TEXT_START; @@ -40,7 +47,6 @@ SECTIONS    .got			: { *(.got) }    _got_end = .;    .got.plt		: { *(.got.plt) } -  .data			: { *(.data) }    _edata = .;    . = BSS_START; diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index cc32c1e54a5..cc0a932bbea 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -277,7 +277,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,  		 * We don't need to sync the DMA buffer since  		 * it was allocated via the coherent allocators.  		 */ -		dma_cache_maint(ptr, size, dir); +		__dma_single_cpu_to_dev(ptr, size, dir);  	}  	return dma_addr; @@ -315,6 +315,8 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,  			__cpuc_flush_dcache_area(ptr, size);  		}  		free_safe_buffer(dev->archdata.dmabounce, buf); +	} else { +		__dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir);  	}  } diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index f232941de8a..1cf999ade4b 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -18,6 +18,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ +  #include <linux/init.h>  #include <linux/list.h>  #include <linux/io.h> @@ -28,48 +29,6 @@  #include <asm/mach/irq.h>  #include <asm/hardware/vic.h> -static void vic_ack_irq(unsigned int irq) -{ -	void __iomem *base = get_irq_chip_data(irq); -	irq &= 31; -	writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); -	/* moreover, clear the soft-triggered, in case it was the reason */ -	writel(1 << irq, base + VIC_INT_SOFT_CLEAR); -} - -static void vic_mask_irq(unsigned int irq) -{ -	void __iomem *base = get_irq_chip_data(irq); -	irq &= 31; -	writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); -} - -static void vic_unmask_irq(unsigned int irq) -{ -	void __iomem *base = get_irq_chip_data(irq); -	irq &= 31; -	writel(1 << irq, base + VIC_INT_ENABLE); -} - -/** - * vic_init2 - common initialisation code - * @base: Base of the VIC. - * - * Common initialisation code for registeration - * and resume. -*/ -static void vic_init2(void __iomem *base) -{ -	int i; - -	for (i = 0; i < 16; i++) { -		void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); -		writel(VIC_VECT_CNTL_ENABLE | i, reg); -	} - -	writel(32, base + VIC_PL190_DEF_VECT_ADDR); -} -  #if defined(CONFIG_PM)  /**   * struct vic_device - VIC PM device @@ -99,13 +58,34 @@ struct vic_device {  /* we cannot allocate memory when VICs are initially registered */  static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; +static int vic_id; +  static inline struct vic_device *to_vic(struct sys_device *sys)  {  	return container_of(sys, struct vic_device, sysdev);  } +#endif /* CONFIG_PM */ -static int vic_id; +/** + * vic_init2 - common initialisation code + * @base: Base of the VIC. + * + * Common initialisation code for registeration + * and resume. +*/ +static void vic_init2(void __iomem *base) +{ +	int i; + +	for (i = 0; i < 16; i++) { +		void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); +		writel(VIC_VECT_CNTL_ENABLE | i, reg); +	} + +	writel(32, base + VIC_PL190_DEF_VECT_ADDR); +} +#if defined(CONFIG_PM)  static int vic_class_resume(struct sys_device *dev)  {  	struct vic_device *vic = to_vic(dev); @@ -159,31 +139,6 @@ struct sysdev_class vic_class = {  };  /** - * vic_pm_register - Register a VIC for later power management control - * @base: The base address of the VIC. - * @irq: The base IRQ for the VIC. - * @resume_sources: bitmask of interrupts allowed for resume sources. - * - * Register the VIC with the system device tree so that it can be notified - * of suspend and resume requests and ensure that the correct actions are - * taken to re-instate the settings on resume. - */ -static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources) -{ -	struct vic_device *v; - -	if (vic_id >= ARRAY_SIZE(vic_devices)) -		printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); -	else { -		v = &vic_devices[vic_id]; -		v->base = base; -		v->resume_sources = resume_sources; -		v->irq = irq; -		vic_id++; -	} -} - -/**   * vic_pm_init - initicall to register VIC pm   *   * This is called via late_initcall() to register @@ -219,9 +174,60 @@ static int __init vic_pm_init(void)  	return 0;  } -  late_initcall(vic_pm_init); +/** + * vic_pm_register - Register a VIC for later power management control + * @base: The base address of the VIC. + * @irq: The base IRQ for the VIC. + * @resume_sources: bitmask of interrupts allowed for resume sources. + * + * Register the VIC with the system device tree so that it can be notified + * of suspend and resume requests and ensure that the correct actions are + * taken to re-instate the settings on resume. + */ +static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources) +{ +	struct vic_device *v; + +	if (vic_id >= ARRAY_SIZE(vic_devices)) +		printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); +	else { +		v = &vic_devices[vic_id]; +		v->base = base; +		v->resume_sources = resume_sources; +		v->irq = irq; +		vic_id++; +	} +} +#else +static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { } +#endif /* CONFIG_PM */ + +static void vic_ack_irq(unsigned int irq) +{ +	void __iomem *base = get_irq_chip_data(irq); +	irq &= 31; +	writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); +	/* moreover, clear the soft-triggered, in case it was the reason */ +	writel(1 << irq, base + VIC_INT_SOFT_CLEAR); +} + +static void vic_mask_irq(unsigned int irq) +{ +	void __iomem *base = get_irq_chip_data(irq); +	irq &= 31; +	writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); +} + +static void vic_unmask_irq(unsigned int irq) +{ +	void __iomem *base = get_irq_chip_data(irq); +	irq &= 31; +	writel(1 << irq, base + VIC_INT_ENABLE); +} + +#if defined(CONFIG_PM)  static struct vic_device *vic_from_irq(unsigned int irq)  {          struct vic_device *v = vic_devices; @@ -255,10 +261,7 @@ static int vic_set_wake(unsigned int irq, unsigned int on)  	return 0;  } -  #else -static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { } -  #define vic_set_wake NULL  #endif /* CONFIG_PM */ @@ -270,9 +273,62 @@ static struct irq_chip vic_chip = {  	.set_wake = vic_set_wake,  }; -/* The PL190 cell from ARM has been modified by ST, so handle both here */ -static void vik_init_st(void __iomem *base, unsigned int irq_start, -			 u32 vic_sources); +/* + * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. + * The original cell has 32 interrupts, while the modified one has 64, + * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case + * the probe function is called twice, with base set to offset 000 + *  and 020 within the page. We call this "second block". + */ +static void __init vic_init_st(void __iomem *base, unsigned int irq_start, +				u32 vic_sources) +{ +	unsigned int i; +	int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; + +	/* Disable all interrupts initially. */ + +	writel(0, base + VIC_INT_SELECT); +	writel(0, base + VIC_INT_ENABLE); +	writel(~0, base + VIC_INT_ENABLE_CLEAR); +	writel(0, base + VIC_IRQ_STATUS); +	writel(0, base + VIC_ITCR); +	writel(~0, base + VIC_INT_SOFT_CLEAR); + +	/* +	 * Make sure we clear all existing interrupts. The vector registers +	 * in this cell are after the second block of general registers, +	 * so we can address them using standard offsets, but only from +	 * the second base address, which is 0x20 in the page +	 */ +	if (vic_2nd_block) { +		writel(0, base + VIC_PL190_VECT_ADDR); +		for (i = 0; i < 19; i++) { +			unsigned int value; + +			value = readl(base + VIC_PL190_VECT_ADDR); +			writel(value, base + VIC_PL190_VECT_ADDR); +		} +		/* ST has 16 vectors as well, but we don't enable them by now */ +		for (i = 0; i < 16; i++) { +			void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); +			writel(0, reg); +		} + +		writel(32, base + VIC_PL190_DEF_VECT_ADDR); +	} + +	for (i = 0; i < 32; i++) { +		if (vic_sources & (1 << i)) { +			unsigned int irq = irq_start + i; + +			set_irq_chip(irq, &vic_chip); +			set_irq_chip_data(irq, base); +			set_irq_handler(irq, handle_level_irq); +			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); +		} +	} +}  /**   * vic_init - initialise a vectored interrupt controller @@ -299,7 +355,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,  	switch(vendor) {  	case AMBA_VENDOR_ST: -		vik_init_st(base, irq_start, vic_sources); +		vic_init_st(base, irq_start, vic_sources);  		return;  	default:  		printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); @@ -343,60 +399,3 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,  	vic_pm_register(base, irq_start, resume_sources);  } - -/* - * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. - * The original cell has 32 interrupts, while the modified one has 64, - * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case - * the probe function is called twice, with base set to offset 000 - *  and 020 within the page. We call this "second block". - */ -static void __init vik_init_st(void __iomem *base, unsigned int irq_start, -				u32 vic_sources) -{ -	unsigned int i; -	int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; - -	/* Disable all interrupts initially. */ - -	writel(0, base + VIC_INT_SELECT); -	writel(0, base + VIC_INT_ENABLE); -	writel(~0, base + VIC_INT_ENABLE_CLEAR); -	writel(0, base + VIC_IRQ_STATUS); -	writel(0, base + VIC_ITCR); -	writel(~0, base + VIC_INT_SOFT_CLEAR); - -	/* -	 * Make sure we clear all existing interrupts. The vector registers -	 * in this cell are after the second block of general registers, -	 * so we can address them using standard offsets, but only from -	 * the second base address, which is 0x20 in the page -	 */ -	if (vic_2nd_block) { -		writel(0, base + VIC_PL190_VECT_ADDR); -		for (i = 0; i < 19; i++) { -			unsigned int value; - -			value = readl(base + VIC_PL190_VECT_ADDR); -			writel(value, base + VIC_PL190_VECT_ADDR); -		} -		/* ST has 16 vectors as well, but we don't enable them by now */ -		for (i = 0; i < 16; i++) { -			void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); -			writel(0, reg); -		} - -		writel(32, base + VIC_PL190_DEF_VECT_ADDR); -	} - -	for (i = 0; i < 32; i++) { -		if (vic_sources & (1 << i)) { -			unsigned int irq = irq_start + i; - -			set_irq_chip(irq, &vic_chip); -			set_irq_chip_data(irq, base); -			set_irq_handler(irq, handle_level_irq); -			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); -		} -	} -} diff --git a/arch/arm/configs/at572d940hfek_defconfig b/arch/arm/configs/at572d940hfek_defconfig new file mode 100644 index 00000000000..76d724b8041 --- /dev/null +++ b/arch/arm/configs/at572d940hfek_defconfig @@ -0,0 +1,1640 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.28-rc7 +# Fri Dec  5 10:58:47 2008 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="-AT572D940HF" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +# CONFIG_TASK_DELAY_ACCT is not set +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_NS is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_DEVICE is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +# CONFIG_USER_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_RESOURCE_COUNTERS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_MARKERS=y +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +CONFIG_KPROBES=y +CONFIG_KRETPROBES=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +CONFIG_BLK_DEV_IO_TRACE=y +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set + +# +# Boot options +# + +# +# Power management +# + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +# CONFIG_ARCH_AT91SAM9G20 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_ARCH_AT572D940HF=y +CONFIG_AT91_PMC_UNIT=y + +# +# AT572D940HF Board Type +# +CONFIG_MACH_AT572D940HFEB=y + +# +# AT91 Board Options +# +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set +# CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16 is not set +CONFIG_NUM_SERIAL=3 + +# +# AT91 Feature Selections +# +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +CONFIG_AT91_TIMER_HZ=100 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +# CONFIG_OUTER_CACHE is not set + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +# CONFIG_AEABI is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="mem=48M console=ttyS0 initrd=0x21100000,3145728 root=/dev/ram0 rw ip=172.16.1.181" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +CONFIG_FPE_NWFPE_XP=y +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +CONFIG_NET_TCPPROBE=m +# CONFIG_HAMRADIO is not set +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m + +# +# CAN Device Drivers +# +CONFIG_CAN_VCAN=m +CONFIG_CAN_DEBUG_DEVICES=y +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_MAC80211 is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +# CONFIG_IEEE80211_CRYPT_CCMP is not set +# CONFIG_IEEE80211_CRYPT_TKIP is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_CONNECTOR=m +CONFIG_MTD=m +CONFIG_MTD_DEBUG=y +CONFIG_MTD_DEBUG_VERBOSE=1 +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m +CONFIG_SSFDC=m +CONFIG_MTD_OOPS=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0x4000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +CONFIG_MTD_PLATRAM=m + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_DATAFLASH=m +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DATAFLASH_OTP is not set +CONFIG_MTD_M25P80=m +CONFIG_M25PXX_USE_FAST_READ=y +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +# CONFIG_MTD_NAND_ATMEL is not set +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +CONFIG_MTD_ALAUDA=m +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +CONFIG_MTD_UBI_GLUEBI=y + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +CONFIG_ATMEL_TCLIB=y +CONFIG_ATMEL_TCB_CLKSRC=y +CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0 +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_ICS932S401 is not set +CONFIG_ATMEL_SSC=m +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=m +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_MACVLAN=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_ICPLUS_PHY=m +# CONFIG_REALTEK_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=m +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_MACB=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_SMC911X is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +CONFIG_WLAN_PRE80211=y +CONFIG_STRIP=m +CONFIG_WLAN_80211=y +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_USB_ZD1201=m +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_IWLWIFI_LEDS is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_DM9601=m +# CONFIG_USB_NET_SMSC95XX is not set +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +CONFIG_INPUT_POLLDEV=m + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVBUG=m + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_GPIO=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_APPLETOUCH=m +# CONFIG_MOUSE_BCM5974 is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOUSE_GPIO=m +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +CONFIG_SPECIALIX=m +CONFIG_RIO=m +# CONFIG_RIO_OLDPCI is not set +CONFIG_STALDRV=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m +CONFIG_HW_RANDOM=y +CONFIG_NVRAM=m +CONFIG_R3964=m +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=256 +CONFIG_TCG_TPM=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_I2C=m +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +CONFIG_DS1682=m +# CONFIG_AT24 is not set +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +CONFIG_SENSORS_TSL2550=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_ATMEL=y +CONFIG_SPI_BITBANG=m + +# +# SPI Protocol Masters +# +CONFIG_SPI_AT25=m +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +# CONFIG_SND_PCM_OSS_PLUGINS is not set +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +# CONFIG_SND_AT73C213 is not set +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +# CONFIG_SND_SOC is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=m +# CONFIG_HID_DEBUG is not set +CONFIG_HIDRAW=y + +# +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BRIGHT=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DELL=m +CONFIG_HID_EZKEY=m +CONFIG_HID_GYRATION=m +CONFIG_HID_LOGITECH=m +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_PANTHERLORD=m +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_DYNAMIC_MINORS=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# + +# +# see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_KARMA=y +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +CONFIG_USB_LIBUSUAL=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP2101 is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_OTI6858 is not set +CONFIG_USB_SERIAL_SPCP8X5=m +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +CONFIG_USB_TEST=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=m +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=m +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +CONFIG_USB_MIDI_GADGET=m +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=m +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_AT91=y +CONFIG_MMC_SPI=m +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=m +# CONFIG_LEDS_PCA955X is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=m +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +CONFIG_RTC_DRV_DS1305=y +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_AT91SAM9 is not set +# CONFIG_DMADEVICES is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_JBD_DEBUG=y +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_CHECK=y +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=m +CONFIG_GENERIC_ACL=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +# CONFIG_UBIFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +# CONFIG_SUNRPC_REGISTER_V4 is not set +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +CONFIG_LDM_DEBUG=y +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m +CONFIG_DLM=m +# CONFIG_DLM_DEBUG is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y + +# +# Tracers +# +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +CONFIG_SECURITYFS=y +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_GF128MUL=m +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=m +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m +CONFIG_LZO_COMPRESS=m +CONFIG_LZO_DECOMPRESS=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/omap_4430sdp_defconfig b/arch/arm/configs/omap_4430sdp_defconfig index 3de640ac294..c48d7b89386 100644 --- a/arch/arm/configs/omap_4430sdp_defconfig +++ b/arch/arm/configs/omap_4430sdp_defconfig @@ -242,10 +242,13 @@ CONFIG_CPU_CP15_MMU=y  # CONFIG_CPU_DCACHE_DISABLE is not set  # CONFIG_CPU_BPREDICT_DISABLE is not set  CONFIG_HAS_TLS_REG=y +CONFIG_OUTER_CACHE=y +CONFIG_CACHE_L2X0=y  CONFIG_ARM_L1_CACHE_SHIFT=5  # CONFIG_ARM_ERRATA_430973 is not set  # CONFIG_ARM_ERRATA_458693 is not set  # CONFIG_ARM_ERRATA_460075 is not set +CONFIG_PL310_ERRATA_588369=y  CONFIG_ARM_GIC=y  # diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index d0daeab2234..e8ddec2cb15 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -235,6 +235,234 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)  #define smp_mb__before_atomic_inc()	smp_mb()  #define smp_mb__after_atomic_inc()	smp_mb() +#ifndef CONFIG_GENERIC_ATOMIC64 +typedef struct { +	u64 __aligned(8) counter; +} atomic64_t; + +#define ATOMIC64_INIT(i) { (i) } + +static inline u64 atomic64_read(atomic64_t *v) +{ +	u64 result; + +	__asm__ __volatile__("@ atomic64_read\n" +"	ldrexd	%0, %H0, [%1]" +	: "=&r" (result) +	: "r" (&v->counter) +	); + +	return result; +} + +static inline void atomic64_set(atomic64_t *v, u64 i) +{ +	u64 tmp; + +	__asm__ __volatile__("@ atomic64_set\n" +"1:	ldrexd	%0, %H0, [%1]\n" +"	strexd	%0, %2, %H2, [%1]\n" +"	teq	%0, #0\n" +"	bne	1b" +	: "=&r" (tmp) +	: "r" (&v->counter), "r" (i) +	: "cc"); +} + +static inline void atomic64_add(u64 i, atomic64_t *v) +{ +	u64 result; +	unsigned long tmp; + +	__asm__ __volatile__("@ atomic64_add\n" +"1:	ldrexd	%0, %H0, [%2]\n" +"	adds	%0, %0, %3\n" +"	adc	%H0, %H0, %H3\n" +"	strexd	%1, %0, %H0, [%2]\n" +"	teq	%1, #0\n" +"	bne	1b" +	: "=&r" (result), "=&r" (tmp) +	: "r" (&v->counter), "r" (i) +	: "cc"); +} + +static inline u64 atomic64_add_return(u64 i, atomic64_t *v) +{ +	u64 result; +	unsigned long tmp; + +	smp_mb(); + +	__asm__ __volatile__("@ atomic64_add_return\n" +"1:	ldrexd	%0, %H0, [%2]\n" +"	adds	%0, %0, %3\n" +"	adc	%H0, %H0, %H3\n" +"	strexd	%1, %0, %H0, [%2]\n" +"	teq	%1, #0\n" +"	bne	1b" +	: "=&r" (result), "=&r" (tmp) +	: "r" (&v->counter), "r" (i) +	: "cc"); + +	smp_mb(); + +	return result; +} + +static inline void atomic64_sub(u64 i, atomic64_t *v) +{ +	u64 result; +	unsigned long tmp; + +	__asm__ __volatile__("@ atomic64_sub\n" +"1:	ldrexd	%0, %H0, [%2]\n" +"	subs	%0, %0, %3\n" +"	sbc	%H0, %H0, %H3\n" +"	strexd	%1, %0, %H0, [%2]\n" +"	teq	%1, #0\n" +"	bne	1b" +	: "=&r" (result), "=&r" (tmp) +	: "r" (&v->counter), "r" (i) +	: "cc"); +} + +static inline u64 atomic64_sub_return(u64 i, atomic64_t *v) +{ +	u64 result; +	unsigned long tmp; + +	smp_mb(); + +	__asm__ __volatile__("@ atomic64_sub_return\n" +"1:	ldrexd	%0, %H0, [%2]\n" +"	subs	%0, %0, %3\n" +"	sbc	%H0, %H0, %H3\n" +"	strexd	%1, %0, %H0, [%2]\n" +"	teq	%1, #0\n" +"	bne	1b" +	: "=&r" (result), "=&r" (tmp) +	: "r" (&v->counter), "r" (i) +	: "cc"); + +	smp_mb(); + +	return result; +} + +static inline u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old, u64 new) +{ +	u64 oldval; +	unsigned long res; + +	smp_mb(); + +	do { +		__asm__ __volatile__("@ atomic64_cmpxchg\n" +		"ldrexd		%1, %H1, [%2]\n" +		"mov		%0, #0\n" +		"teq		%1, %3\n" +		"teqeq		%H1, %H3\n" +		"strexdeq	%0, %4, %H4, [%2]" +		: "=&r" (res), "=&r" (oldval) +		: "r" (&ptr->counter), "r" (old), "r" (new) +		: "cc"); +	} while (res); + +	smp_mb(); + +	return oldval; +} + +static inline u64 atomic64_xchg(atomic64_t *ptr, u64 new) +{ +	u64 result; +	unsigned long tmp; + +	smp_mb(); + +	__asm__ __volatile__("@ atomic64_xchg\n" +"1:	ldrexd	%0, %H0, [%2]\n" +"	strexd	%1, %3, %H3, [%2]\n" +"	teq	%1, #0\n" +"	bne	1b" +	: "=&r" (result), "=&r" (tmp) +	: "r" (&ptr->counter), "r" (new) +	: "cc"); + +	smp_mb(); + +	return result; +} + +static inline u64 atomic64_dec_if_positive(atomic64_t *v) +{ +	u64 result; +	unsigned long tmp; + +	smp_mb(); + +	__asm__ __volatile__("@ atomic64_dec_if_positive\n" +"1:	ldrexd	%0, %H0, [%2]\n" +"	subs	%0, %0, #1\n" +"	sbc	%H0, %H0, #0\n" +"	teq	%H0, #0\n" +"	bmi	2f\n" +"	strexd	%1, %0, %H0, [%2]\n" +"	teq	%1, #0\n" +"	bne	1b\n" +"2:" +	: "=&r" (result), "=&r" (tmp) +	: "r" (&v->counter) +	: "cc"); + +	smp_mb(); + +	return result; +} + +static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u) +{ +	u64 val; +	unsigned long tmp; +	int ret = 1; + +	smp_mb(); + +	__asm__ __volatile__("@ atomic64_add_unless\n" +"1:	ldrexd	%0, %H0, [%3]\n" +"	teq	%0, %4\n" +"	teqeq	%H0, %H4\n" +"	moveq	%1, #0\n" +"	beq	2f\n" +"	adds	%0, %0, %5\n" +"	adc	%H0, %H0, %H5\n" +"	strexd	%2, %0, %H0, [%3]\n" +"	teq	%2, #0\n" +"	bne	1b\n" +"2:" +	: "=&r" (val), "=&r" (ret), "=&r" (tmp) +	: "r" (&v->counter), "r" (u), "r" (a) +	: "cc"); + +	if (ret) +		smp_mb(); + +	return ret; +} + +#define atomic64_add_negative(a, v)	(atomic64_add_return((a), (v)) < 0) +#define atomic64_inc(v)			atomic64_add(1LL, (v)) +#define atomic64_inc_return(v)		atomic64_add_return(1LL, (v)) +#define atomic64_inc_and_test(v)	(atomic64_inc_return(v) == 0) +#define atomic64_sub_and_test(a, v)	(atomic64_sub_return((a), (v)) == 0) +#define atomic64_dec(v)			atomic64_sub(1LL, (v)) +#define atomic64_dec_return(v)		atomic64_sub_return(1LL, (v)) +#define atomic64_dec_and_test(v)	(atomic64_dec_return((v)) == 0) +#define atomic64_inc_not_zero(v)	atomic64_add_unless((v), 1LL, 0LL) + +#else /* !CONFIG_GENERIC_ATOMIC64 */ +#include <asm-generic/atomic64.h> +#endif  #include <asm-generic/atomic-long.h>  #endif  #endif diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index c77d2fa1f6e..8148a009273 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -196,21 +196,6 @@   *	DMA Cache Coherency   *	===================   * - *	dma_inv_range(start, end) - * - *		Invalidate (discard) the specified virtual address range. - *		May not write back any entries.  If 'start' or 'end' - *		are not cache line aligned, those lines must be written - *		back. - *		- start  - virtual start address - *		- end    - virtual end address - * - *	dma_clean_range(start, end) - * - *		Clean (write back) the specified virtual address range. - *		- start  - virtual start address - *		- end    - virtual end address - *   *	dma_flush_range(start, end)   *   *		Clean and invalidate the specified virtual address range. @@ -227,8 +212,9 @@ struct cpu_cache_fns {  	void (*coherent_user_range)(unsigned long, unsigned long);  	void (*flush_kern_dcache_area)(void *, size_t); -	void (*dma_inv_range)(const void *, const void *); -	void (*dma_clean_range)(const void *, const void *); +	void (*dma_map_area)(const void *, size_t, int); +	void (*dma_unmap_area)(const void *, size_t, int); +  	void (*dma_flush_range)(const void *, const void *);  }; @@ -258,8 +244,8 @@ extern struct cpu_cache_fns cpu_cache;   * is visible to DMA, or data written by DMA to system memory is   * visible to the CPU.   */ -#define dmac_inv_range			cpu_cache.dma_inv_range -#define dmac_clean_range		cpu_cache.dma_clean_range +#define dmac_map_area			cpu_cache.dma_map_area +#define dmac_unmap_area		cpu_cache.dma_unmap_area  #define dmac_flush_range		cpu_cache.dma_flush_range  #else @@ -284,12 +270,12 @@ extern void __cpuc_flush_dcache_area(void *, size_t);   * is visible to DMA, or data written by DMA to system memory is   * visible to the CPU.   */ -#define dmac_inv_range			__glue(_CACHE,_dma_inv_range) -#define dmac_clean_range		__glue(_CACHE,_dma_clean_range) +#define dmac_map_area			__glue(_CACHE,_dma_map_area) +#define dmac_unmap_area		__glue(_CACHE,_dma_unmap_area)  #define dmac_flush_range		__glue(_CACHE,_dma_flush_range) -extern void dmac_inv_range(const void *, const void *); -extern void dmac_clean_range(const void *, const void *); +extern void dmac_map_area(const void *, size_t, int); +extern void dmac_unmap_area(const void *, size_t, int);  extern void dmac_flush_range(const void *, const void *);  #endif @@ -330,12 +316,8 @@ static inline void outer_flush_range(unsigned long start, unsigned long end)   * processes address space.  Really, we want to allow our "user   * space" model to handle this.   */ -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ -	do {							\ -		memcpy(dst, src, len);				\ -		flush_ptrace_access(vma, page, vaddr, dst, len, 1);\ -	} while (0) - +extern void copy_to_user_page(struct vm_area_struct *, struct page *, +	unsigned long, void *, const void *, unsigned long);  #define copy_from_user_page(vma, page, vaddr, dst, src, len) \  	do {							\  		memcpy(dst, src, len);				\ @@ -369,17 +351,6 @@ vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig  	}  } -static inline void -vivt_flush_ptrace_access(struct vm_area_struct *vma, struct page *page, -			 unsigned long uaddr, void *kaddr, -			 unsigned long len, int write) -{ -	if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) { -		unsigned long addr = (unsigned long)kaddr; -		__cpuc_coherent_kern_range(addr, addr + len); -	} -} -  #ifndef CONFIG_CPU_CACHE_VIPT  #define flush_cache_mm(mm) \  		vivt_flush_cache_mm(mm) @@ -387,15 +358,10 @@ vivt_flush_ptrace_access(struct vm_area_struct *vma, struct page *page,  		vivt_flush_cache_range(vma,start,end)  #define flush_cache_page(vma,addr,pfn) \  		vivt_flush_cache_page(vma,addr,pfn) -#define flush_ptrace_access(vma,page,ua,ka,len,write) \ -		vivt_flush_ptrace_access(vma,page,ua,ka,len,write)  #else  extern void flush_cache_mm(struct mm_struct *mm);  extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);  extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); -extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, -				unsigned long uaddr, void *kaddr, -				unsigned long len, int write);  #endif  #define flush_cache_dup_mm(mm) flush_cache_mm(mm) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index a96300bf83f..256ee1c9f51 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -57,18 +57,58 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)  #endif  /* - * DMA-consistent mapping functions.  These allocate/free a region of - * uncached, unwrite-buffered mapped memory space for use with DMA - * devices.  This is the "generic" version.  The PCI specific version - * is in pci.h + * The DMA API is built upon the notion of "buffer ownership".  A buffer + * is either exclusively owned by the CPU (and therefore may be accessed + * by it) or exclusively owned by the DMA device.  These helper functions + * represent the transitions between these two ownership states.   * - * Note: Drivers should NOT use this function directly, as it will break - * platforms with CONFIG_DMABOUNCE. - * Use the driver DMA support - see dma-mapping.h (dma_sync_*) + * Note, however, that on later ARMs, this notion does not work due to + * speculative prefetches.  We model our approach on the assumption that + * the CPU does do speculative prefetches, which means we clean caches + * before transfers and delay cache invalidation until transfer completion. + * + * Private support functions: these are not part of the API and are + * liable to change.  Drivers must not use these.   */ -extern void dma_cache_maint(const void *kaddr, size_t size, int rw); -extern void dma_cache_maint_page(struct page *page, unsigned long offset, -				 size_t size, int rw); +static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size, +	enum dma_data_direction dir) +{ +	extern void ___dma_single_cpu_to_dev(const void *, size_t, +		enum dma_data_direction); + +	if (!arch_is_coherent()) +		___dma_single_cpu_to_dev(kaddr, size, dir); +} + +static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size, +	enum dma_data_direction dir) +{ +	extern void ___dma_single_dev_to_cpu(const void *, size_t, +		enum dma_data_direction); + +	if (!arch_is_coherent()) +		___dma_single_dev_to_cpu(kaddr, size, dir); +} + +static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off, +	size_t size, enum dma_data_direction dir) +{ +	extern void ___dma_page_cpu_to_dev(struct page *, unsigned long, +		size_t, enum dma_data_direction); + +	if (!arch_is_coherent()) +		___dma_page_cpu_to_dev(page, off, size, dir); +} + +static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off, +	size_t size, enum dma_data_direction dir) +{ +	extern void ___dma_page_dev_to_cpu(struct page *, unsigned long, +		size_t, enum dma_data_direction); + +	if (!arch_is_coherent()) +		___dma_page_dev_to_cpu(page, off, size, dir); +}  /*   * Return whether the given device DMA address mask can be supported @@ -304,8 +344,7 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,  {  	BUG_ON(!valid_dma_direction(dir)); -	if (!arch_is_coherent()) -		dma_cache_maint(cpu_addr, size, dir); +	__dma_single_cpu_to_dev(cpu_addr, size, dir);  	return virt_to_dma(dev, cpu_addr);  } @@ -329,8 +368,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,  {  	BUG_ON(!valid_dma_direction(dir)); -	if (!arch_is_coherent()) -		dma_cache_maint_page(page, offset, size, dir); +	__dma_page_cpu_to_dev(page, offset, size, dir);  	return page_to_dma(dev, page) + offset;  } @@ -352,7 +390,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,  static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,  		size_t size, enum dma_data_direction dir)  { -	/* nothing to do */ +	__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);  }  /** @@ -372,7 +410,8 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,  static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,  		size_t size, enum dma_data_direction dir)  { -	/* nothing to do */ +	__dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK, +		size, dir);  }  #endif /* CONFIG_DMABOUNCE */ @@ -400,7 +439,10 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,  {  	BUG_ON(!valid_dma_direction(dir)); -	dmabounce_sync_for_cpu(dev, handle, offset, size, dir); +	if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir)) +		return; + +	__dma_single_dev_to_cpu(dma_to_virt(dev, handle) + offset, size, dir);  }  static inline void dma_sync_single_range_for_device(struct device *dev, @@ -412,8 +454,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev,  	if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))  		return; -	if (!arch_is_coherent()) -		dma_cache_maint(dma_to_virt(dev, handle) + offset, size, dir); +	__dma_single_cpu_to_dev(dma_to_virt(dev, handle) + offset, size, dir);  }  static inline void dma_sync_single_for_cpu(struct device *dev, diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index d2a59cfc30c..c980156f326 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -69,9 +69,16 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);  /*   * __arm_ioremap takes CPU physical address.   * __arm_ioremap_pfn takes a Page Frame Number and an offset into that page + * The _caller variety takes a __builtin_return_address(0) value for + * /proc/vmalloc to use - and should only be used in non-inline functions.   */ -extern void __iomem * __arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); -extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int); +extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long, +	size_t, unsigned int, void *); +extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int, +	void *); + +extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); +extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);  extern void __iounmap(volatile void __iomem *addr);  /* diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h index b2cc1fcd040..8bffc3ff3ac 100644 --- a/arch/arm/include/asm/mach/time.h +++ b/arch/arm/include/asm/mach/time.h @@ -46,12 +46,4 @@ struct sys_timer {  extern struct sys_timer *system_timer;  extern void timer_tick(void); -/* - * Kernel time keeping support. - */ -struct timespec; -extern int (*set_rtc)(void); -extern void save_time_delta(struct timespec *delta, struct timespec *rtc); -extern void restore_time_delta(struct timespec *delta, struct timespec *rtc); -  #endif diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 5421d82a257..4312ee5e3d0 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -76,6 +76,17 @@   */  #define IOREMAP_MAX_ORDER	24 +/* + * Size of DMA-consistent memory region.  Must be multiple of 2M, + * between 2MB and 14MB inclusive. + */ +#ifndef CONSISTENT_DMA_SIZE +#define CONSISTENT_DMA_SIZE 	SZ_2M +#endif + +#define CONSISTENT_END		(0xffe00000UL) +#define CONSISTENT_BASE		(CONSISTENT_END - CONSISTENT_DMA_SIZE) +  #else /* CONFIG_MMU */  /* @@ -93,11 +104,11 @@  #endif  #ifndef PHYS_OFFSET -#define PHYS_OFFSET 		(CONFIG_DRAM_BASE) +#define PHYS_OFFSET 		UL(CONFIG_DRAM_BASE)  #endif  #ifndef END_MEM -#define END_MEM     		(CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE) +#define END_MEM     		(UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)  #endif  #ifndef PAGE_OFFSET @@ -113,14 +124,6 @@  #endif /* !CONFIG_MMU */  /* - * Size of DMA-consistent memory region.  Must be multiple of 2M, - * between 2MB and 14MB inclusive. - */ -#ifndef CONSISTENT_DMA_SIZE -#define CONSISTENT_DMA_SIZE SZ_2M -#endif - -/*   * Physical vs virtual RAM address space conversion.  These are   * private definitions which should NOT be used outside memory.h   * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead. diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index b561584d04a..68870c77667 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -6,6 +6,7 @@  typedef struct {  #ifdef CONFIG_CPU_HAS_ASID  	unsigned int id; +	spinlock_t id_lock;  #endif  	unsigned int kvm_seq;  } mm_context_t; diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h index de6cefb329d..a0b3cac0547 100644 --- a/arch/arm/include/asm/mmu_context.h +++ b/arch/arm/include/asm/mmu_context.h @@ -43,12 +43,23 @@ void __check_kvm_seq(struct mm_struct *mm);  #define ASID_FIRST_VERSION	(1 << ASID_BITS)  extern unsigned int cpu_last_asid; +#ifdef CONFIG_SMP +DECLARE_PER_CPU(struct mm_struct *, current_mm); +#endif  void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);  void __new_context(struct mm_struct *mm);  static inline void check_context(struct mm_struct *mm)  { +	/* +	 * This code is executed with interrupts enabled. Therefore, +	 * mm->context.id cannot be updated to the latest ASID version +	 * on a different CPU (and condition below not triggered) +	 * without first getting an IPI to reset the context. The +	 * alternative is to take a read_lock on mm->context.id_lock +	 * (after changing its type to rwlock_t). +	 */  	if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS))  		__new_context(mm); @@ -108,6 +119,10 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,  		__flush_icache_all();  #endif  	if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) { +#ifdef CONFIG_SMP +		struct mm_struct **crt_mm = &per_cpu(current_mm, cpu); +		*crt_mm = next; +#endif  		check_context(next);  		cpu_switch_mm(next->pgd, next);  		if (cache_is_vivt()) diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index 3a32af4cce3..a485ac3c869 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -117,11 +117,12 @@  #endif  struct page; +struct vm_area_struct;  struct cpu_user_fns {  	void (*cpu_clear_user_highpage)(struct page *page, unsigned long vaddr);  	void (*cpu_copy_user_highpage)(struct page *to, struct page *from, -			unsigned long vaddr); +			unsigned long vaddr, struct vm_area_struct *vma);  };  #ifdef MULTI_USER @@ -137,7 +138,7 @@ extern struct cpu_user_fns cpu_user;  extern void __cpu_clear_user_highpage(struct page *page, unsigned long vaddr);  extern void __cpu_copy_user_highpage(struct page *to, struct page *from, -			unsigned long vaddr); +			unsigned long vaddr, struct vm_area_struct *vma);  #endif  #define clear_user_highpage(page,vaddr)		\ @@ -145,7 +146,7 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,  #define __HAVE_ARCH_COPY_USER_HIGHPAGE  #define copy_user_highpage(to,from,vaddr,vma)	\ -	__cpu_copy_user_highpage(to, from, vaddr) +	__cpu_copy_user_highpage(to, from, vaddr, vma)  #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)  extern void copy_page(void *to, const void *from); diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h new file mode 100644 index 00000000000..49e3049aba3 --- /dev/null +++ b/arch/arm/include/asm/perf_event.h @@ -0,0 +1,31 @@ +/* + *  linux/arch/arm/include/asm/perf_event.h + * + *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles + * + * 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 __ARM_PERF_EVENT_H__ +#define __ARM_PERF_EVENT_H__ + +/* + * NOP: on *most* (read: all supported) ARM platforms, the performance + * counter interrupts are regular interrupts and not an NMI. This + * means that when we receive the interrupt we can call + * perf_event_do_pending() that handles all of the work with + * interrupts enabled. + */ +static inline void +set_perf_event_pending(void) +{ +} + +/* ARM performance counters start from 1 (in the cp15 accesses) so use the + * same indexes here for consistency. */ +#define PERF_EVENT_INDEX_OFFSET 1 + +#endif /* __ARM_PERF_EVENT_H__ */ diff --git a/arch/arm/include/asm/pgtable-nommu.h b/arch/arm/include/asm/pgtable-nommu.h index b011f2e939a..013cfcdc483 100644 --- a/arch/arm/include/asm/pgtable-nommu.h +++ b/arch/arm/include/asm/pgtable-nommu.h @@ -86,8 +86,8 @@ extern unsigned int kobjsize(const void *objp);   * All 32bit addresses are effectively valid for vmalloc...   * Sort of meaningless for non-VM targets.   */ -#define	VMALLOC_START	0 -#define	VMALLOC_END	0xffffffff +#define	VMALLOC_START	0UL +#define	VMALLOC_END	0xffffffffUL  #define FIRST_USER_ADDRESS      (0) diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h new file mode 100644 index 00000000000..2829b9f981a --- /dev/null +++ b/arch/arm/include/asm/pmu.h @@ -0,0 +1,75 @@ +/* + *  linux/arch/arm/include/asm/pmu.h + * + *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles + * + * 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 __ARM_PMU_H__ +#define __ARM_PMU_H__ + +#ifdef CONFIG_CPU_HAS_PMU + +struct pmu_irqs { +	const int   *irqs; +	int	    num_irqs; +}; + +/** + * reserve_pmu() - reserve the hardware performance counters + * + * Reserve the hardware performance counters in the system for exclusive use. + * The 'struct pmu_irqs' for the system is returned on success, ERR_PTR() + * encoded error on failure. + */ +extern const struct pmu_irqs * +reserve_pmu(void); + +/** + * release_pmu() - Relinquish control of the performance counters + * + * Release the performance counters and allow someone else to use them. + * Callers must have disabled the counters and released IRQs before calling + * this. The 'struct pmu_irqs' returned from reserve_pmu() must be passed as + * a cookie. + */ +extern int +release_pmu(const struct pmu_irqs *irqs); + +/** + * init_pmu() - Initialise the PMU. + * + * Initialise the system ready for PMU enabling. This should typically set the + * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do + * the actual hardware initialisation. + */ +extern int +init_pmu(void); + +#else /* CONFIG_CPU_HAS_PMU */ + +static inline const struct pmu_irqs * +reserve_pmu(void) +{ +	return ERR_PTR(-ENODEV); +} + +static inline int +release_pmu(const struct pmu_irqs *irqs) +{ +	return -ENODEV; +} + +static inline int +init_pmu(void) +{ +	return -ENODEV; +} + +#endif /* CONFIG_CPU_HAS_PMU */ + +#endif /* __ARM_PMU_H__ */ diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index 5ccce0a9b03..f392fb4437a 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -223,18 +223,6 @@ extern struct meminfo meminfo;  #define bank_phys_end(bank)	((bank)->start + (bank)->size)  #define bank_phys_size(bank)	(bank)->size -/* - * Early command line parameters. - */ -struct early_params { -	const char *arg; -	void (*fn)(char **p); -}; - -#define __early_param(name,fn)					\ -static struct early_params __early_##fn __used			\ -__attribute__((__section__(".early_param.init"))) = { name, fn } -  #endif  /*  __KERNEL__  */  #endif diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index 59303e20084..e6215305544 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h @@ -13,4 +13,9 @@ static inline int tlb_ops_need_broadcast(void)  	return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;  } +static inline int cache_ops_need_broadcast(void) +{ +	return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1; +} +  #endif diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index c91c64cab92..17eb355707d 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -5,6 +5,22 @@  #error SMP not supported on pre-ARMv6 CPUs  #endif +static inline void dsb_sev(void) +{ +#if __LINUX_ARM_ARCH__ >= 7 +	__asm__ __volatile__ ( +		"dsb\n" +		"sev" +	); +#elif defined(CONFIG_CPU_32v6K) +	__asm__ __volatile__ ( +		"mcr p15, 0, %0, c7, c10, 4\n" +		"sev" +		: : "r" (0) +	); +#endif +} +  /*   * ARMv6 Spin-locking.   * @@ -69,13 +85,11 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)  	__asm__ __volatile__(  "	str	%1, [%0]\n" -#ifdef CONFIG_CPU_32v6K -"	mcr	p15, 0, %1, c7, c10, 4\n" /* DSB */ -"	sev" -#endif  	:  	: "r" (&lock->lock), "r" (0)  	: "cc"); + +	dsb_sev();  }  /* @@ -132,13 +146,11 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)  	__asm__ __volatile__(  	"str	%1, [%0]\n" -#ifdef CONFIG_CPU_32v6K -"	mcr	p15, 0, %1, c7, c10, 4\n" /* DSB */ -"	sev\n" -#endif  	:  	: "r" (&rw->lock), "r" (0)  	: "cc"); + +	dsb_sev();  }  /* write_can_lock - would write_trylock() succeed? */ @@ -188,14 +200,12 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)  "	strex	%1, %0, [%2]\n"  "	teq	%1, #0\n"  "	bne	1b" -#ifdef CONFIG_CPU_32v6K -"\n	cmp	%0, #0\n" -"	mcreq   p15, 0, %0, c7, c10, 4\n" -"	seveq" -#endif  	: "=&r" (tmp), "=&r" (tmp2)  	: "r" (&rw->lock)  	: "cc"); + +	if (tmp == 0) +		dsb_sev();  }  static inline int arch_read_trylock(arch_rwlock_t *rw) diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 058e7e90881..ca88e6a8470 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -73,8 +73,7 @@ extern unsigned int mem_fclk_21285;  struct pt_regs; -void die(const char *msg, struct pt_regs *regs, int err) -		__attribute__((noreturn)); +void die(const char *msg, struct pt_regs *regs, int err);  struct siginfo;  void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 2dfb7d7a66e..b74970ec02c 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -115,7 +115,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);  extern void iwmmxt_task_release(struct thread_info *);  extern void iwmmxt_task_switch(struct thread_info *); -extern void vfp_sync_state(struct thread_info *thread); +extern void vfp_sync_hwstate(struct thread_info *); +extern void vfp_flush_hwstate(struct thread_info *);  #endif diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index c2f1605de35..e085e2c545e 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -529,7 +529,8 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);   * cache entries for the kernels virtual memory range are written   * back to the page.   */ -extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte); +extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, +	pte_t *ptep);  #endif diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index dd00f747e2a..26d302c28e1 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -17,6 +17,7 @@ obj-y		:= compat.o elf.o entry-armv.o entry-common.o irq.o \  		   process.o ptrace.o return_address.o setup.o signal.o \  		   sys_arm.o stacktrace.o time.o traps.o +obj-$(CONFIG_LEDS)		+= leds.o  obj-$(CONFIG_OC_ETM)		+= etm.o  obj-$(CONFIG_ISA_DMA_API)	+= dma.o @@ -46,6 +47,8 @@ obj-$(CONFIG_CPU_XSCALE)	+= xscale-cp0.o  obj-$(CONFIG_CPU_XSC3)		+= xscale-cp0.o  obj-$(CONFIG_CPU_MOHAWK)	+= xscale-cp0.o  obj-$(CONFIG_IWMMXT)		+= iwmmxt.o +obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o +obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o  AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt  ifneq ($(CONFIG_ARCH_EBSA110),y) diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 4a881258bb1..883511522fc 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -12,6 +12,7 @@   */  #include <linux/sched.h>  #include <linux/mm.h> +#include <linux/dma-mapping.h>  #include <asm/mach/arch.h>  #include <asm/thread_info.h>  #include <asm/memory.h> @@ -112,5 +113,9 @@ int main(void)  #ifdef MULTI_PABORT    DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));  #endif +  BLANK(); +  DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL); +  DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE); +  DEFINE(DMA_FROM_DEVICE,	DMA_FROM_DEVICE);    return 0;   } diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index 5c91addcaeb..a38b4879441 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -24,7 +24,7 @@  #if defined(CONFIG_CPU_V6) -		.macro	addruart, rx +		.macro	addruart, rx, tmp  		.endm  		.macro	senduart, rd, rx @@ -51,7 +51,7 @@  #elif defined(CONFIG_CPU_V7) -		.macro	addruart, rx +		.macro	addruart, rx, tmp  		.endm  		.macro	senduart, rd, rx @@ -71,7 +71,7 @@ wait:		mrc	p14, 0, pc, c0, c1, 0  #elif defined(CONFIG_CPU_XSCALE) -		.macro	addruart, rx +		.macro	addruart, rx, tmp  		.endm  		.macro	senduart, rd, rx @@ -98,7 +98,7 @@ wait:		mrc	p14, 0, pc, c0, c1, 0  #else -		.macro	addruart, rx +		.macro	addruart, rx, tmp  		.endm  		.macro	senduart, rd, rx @@ -164,7 +164,7 @@ ENDPROC(printhex2)  		.ltorg  ENTRY(printascii) -		addruart r3 +		addruart r3, r1  		b	2f  1:		waituart r2, r3  		senduart r1, r3 @@ -180,7 +180,7 @@ ENTRY(printascii)  ENDPROC(printascii)  ENTRY(printch) -		addruart r3 +		addruart r3, r1  		mov	r1, r0  		mov	r0, #0  		b	1b diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c new file mode 100644 index 00000000000..31a316c1777 --- /dev/null +++ b/arch/arm/kernel/leds.c @@ -0,0 +1,115 @@ +/* + * LED support code, ripped out of arch/arm/kernel/time.c + * + *  Copyright (C) 1994-2001 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sysdev.h> + +#include <asm/leds.h> + +static void dummy_leds_event(led_event_t evt) +{ +} + +void (*leds_event)(led_event_t) = dummy_leds_event; + +struct leds_evt_name { +	const char	name[8]; +	int		on; +	int		off; +}; + +static const struct leds_evt_name evt_names[] = { +	{ "amber", led_amber_on, led_amber_off }, +	{ "blue",  led_blue_on,  led_blue_off  }, +	{ "green", led_green_on, led_green_off }, +	{ "red",   led_red_on,   led_red_off   }, +}; + +static ssize_t leds_store(struct sys_device *dev, +			struct sysdev_attribute *attr, +			const char *buf, size_t size) +{ +	int ret = -EINVAL, len = strcspn(buf, " "); + +	if (len > 0 && buf[len] == '\0') +		len--; + +	if (strncmp(buf, "claim", len) == 0) { +		leds_event(led_claim); +		ret = size; +	} else if (strncmp(buf, "release", len) == 0) { +		leds_event(led_release); +		ret = size; +	} else { +		int i; + +		for (i = 0; i < ARRAY_SIZE(evt_names); i++) { +			if (strlen(evt_names[i].name) != len || +			    strncmp(buf, evt_names[i].name, len) != 0) +				continue; +			if (strncmp(buf+len, " on", 3) == 0) { +				leds_event(evt_names[i].on); +				ret = size; +			} else if (strncmp(buf+len, " off", 4) == 0) { +				leds_event(evt_names[i].off); +				ret = size; +			} +			break; +		} +	} +	return ret; +} + +static SYSDEV_ATTR(event, 0200, NULL, leds_store); + +static int leds_suspend(struct sys_device *dev, pm_message_t state) +{ +	leds_event(led_stop); +	return 0; +} + +static int leds_resume(struct sys_device *dev) +{ +	leds_event(led_start); +	return 0; +} + +static int leds_shutdown(struct sys_device *dev) +{ +	leds_event(led_halted); +	return 0; +} + +static struct sysdev_class leds_sysclass = { +	.name		= "leds", +	.shutdown	= leds_shutdown, +	.suspend	= leds_suspend, +	.resume		= leds_resume, +}; + +static struct sys_device leds_device = { +	.id		= 0, +	.cls		= &leds_sysclass, +}; + +static int __init leds_init(void) +{ +	int ret; +	ret = sysdev_class_register(&leds_sysclass); +	if (ret == 0) +		ret = sysdev_register(&leds_device); +	if (ret == 0) +		ret = sysdev_create_file(&leds_device, &attr_event); +	return ret; +} + +device_initcall(leds_init); + +EXPORT_SYMBOL(leds_event); diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c new file mode 100644 index 00000000000..c54ceb3d1f9 --- /dev/null +++ b/arch/arm/kernel/perf_event.c @@ -0,0 +1,2276 @@ +#undef DEBUG + +/* + * ARM performance counter support. + * + * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles + * + * ARMv7 support: Jean Pihet <jpihet@mvista.com> + * 2010 (c) MontaVista Software, LLC. + * + * This code is based on the sparc64 perf event code, which is in turn based + * on the x86 code. Callchain code is based on the ARM OProfile backtrace + * code. + */ +#define pr_fmt(fmt) "hw perfevents: " fmt + +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/perf_event.h> +#include <linux/spinlock.h> +#include <linux/uaccess.h> + +#include <asm/cputype.h> +#include <asm/irq.h> +#include <asm/irq_regs.h> +#include <asm/pmu.h> +#include <asm/stacktrace.h> + +static const struct pmu_irqs *pmu_irqs; + +/* + * Hardware lock to serialize accesses to PMU registers. Needed for the + * read/modify/write sequences. + */ +DEFINE_SPINLOCK(pmu_lock); + +/* + * ARMv6 supports a maximum of 3 events, starting from index 1. If we add + * another platform that supports more, we need to increase this to be the + * largest of all platforms. + * + * ARMv7 supports up to 32 events: + *  cycle counter CCNT + 31 events counters CNT0..30. + *  Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters. + */ +#define ARMPMU_MAX_HWEVENTS		33 + +/* The events for a given CPU. */ +struct cpu_hw_events { +	/* +	 * The events that are active on the CPU for the given index. Index 0 +	 * is reserved. +	 */ +	struct perf_event	*events[ARMPMU_MAX_HWEVENTS]; + +	/* +	 * A 1 bit for an index indicates that the counter is being used for +	 * an event. A 0 means that the counter can be used. +	 */ +	unsigned long		used_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)]; + +	/* +	 * A 1 bit for an index indicates that the counter is actively being +	 * used. +	 */ +	unsigned long		active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)]; +}; +DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); + +struct arm_pmu { +	char		*name; +	irqreturn_t	(*handle_irq)(int irq_num, void *dev); +	void		(*enable)(struct hw_perf_event *evt, int idx); +	void		(*disable)(struct hw_perf_event *evt, int idx); +	int		(*event_map)(int evt); +	u64		(*raw_event)(u64); +	int		(*get_event_idx)(struct cpu_hw_events *cpuc, +					 struct hw_perf_event *hwc); +	u32		(*read_counter)(int idx); +	void		(*write_counter)(int idx, u32 val); +	void		(*start)(void); +	void		(*stop)(void); +	int		num_events; +	u64		max_period; +}; + +/* Set at runtime when we know what CPU type we are. */ +static const struct arm_pmu *armpmu; + +#define HW_OP_UNSUPPORTED		0xFFFF + +#define C(_x) \ +	PERF_COUNT_HW_CACHE_##_x + +#define CACHE_OP_UNSUPPORTED		0xFFFF + +static unsigned armpmu_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] +				     [PERF_COUNT_HW_CACHE_OP_MAX] +				     [PERF_COUNT_HW_CACHE_RESULT_MAX]; + +static int +armpmu_map_cache_event(u64 config) +{ +	unsigned int cache_type, cache_op, cache_result, ret; + +	cache_type = (config >>  0) & 0xff; +	if (cache_type >= PERF_COUNT_HW_CACHE_MAX) +		return -EINVAL; + +	cache_op = (config >>  8) & 0xff; +	if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) +		return -EINVAL; + +	cache_result = (config >> 16) & 0xff; +	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) +		return -EINVAL; + +	ret = (int)armpmu_perf_cache_map[cache_type][cache_op][cache_result]; + +	if (ret == CACHE_OP_UNSUPPORTED) +		return -ENOENT; + +	return ret; +} + +static int +armpmu_event_set_period(struct perf_event *event, +			struct hw_perf_event *hwc, +			int idx) +{ +	s64 left = atomic64_read(&hwc->period_left); +	s64 period = hwc->sample_period; +	int ret = 0; + +	if (unlikely(left <= -period)) { +		left = period; +		atomic64_set(&hwc->period_left, left); +		hwc->last_period = period; +		ret = 1; +	} + +	if (unlikely(left <= 0)) { +		left += period; +		atomic64_set(&hwc->period_left, left); +		hwc->last_period = period; +		ret = 1; +	} + +	if (left > (s64)armpmu->max_period) +		left = armpmu->max_period; + +	atomic64_set(&hwc->prev_count, (u64)-left); + +	armpmu->write_counter(idx, (u64)(-left) & 0xffffffff); + +	perf_event_update_userpage(event); + +	return ret; +} + +static u64 +armpmu_event_update(struct perf_event *event, +		    struct hw_perf_event *hwc, +		    int idx) +{ +	int shift = 64 - 32; +	s64 prev_raw_count, new_raw_count; +	s64 delta; + +again: +	prev_raw_count = atomic64_read(&hwc->prev_count); +	new_raw_count = armpmu->read_counter(idx); + +	if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count, +			     new_raw_count) != prev_raw_count) +		goto again; + +	delta = (new_raw_count << shift) - (prev_raw_count << shift); +	delta >>= shift; + +	atomic64_add(delta, &event->count); +	atomic64_sub(delta, &hwc->period_left); + +	return new_raw_count; +} + +static void +armpmu_disable(struct perf_event *event) +{ +	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); +	struct hw_perf_event *hwc = &event->hw; +	int idx = hwc->idx; + +	WARN_ON(idx < 0); + +	clear_bit(idx, cpuc->active_mask); +	armpmu->disable(hwc, idx); + +	barrier(); + +	armpmu_event_update(event, hwc, idx); +	cpuc->events[idx] = NULL; +	clear_bit(idx, cpuc->used_mask); + +	perf_event_update_userpage(event); +} + +static void +armpmu_read(struct perf_event *event) +{ +	struct hw_perf_event *hwc = &event->hw; + +	/* Don't read disabled counters! */ +	if (hwc->idx < 0) +		return; + +	armpmu_event_update(event, hwc, hwc->idx); +} + +static void +armpmu_unthrottle(struct perf_event *event) +{ +	struct hw_perf_event *hwc = &event->hw; + +	/* +	 * Set the period again. Some counters can't be stopped, so when we +	 * were throttled we simply disabled the IRQ source and the counter +	 * may have been left counting. If we don't do this step then we may +	 * get an interrupt too soon or *way* too late if the overflow has +	 * happened since disabling. +	 */ +	armpmu_event_set_period(event, hwc, hwc->idx); +	armpmu->enable(hwc, hwc->idx); +} + +static int +armpmu_enable(struct perf_event *event) +{ +	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); +	struct hw_perf_event *hwc = &event->hw; +	int idx; +	int err = 0; + +	/* If we don't have a space for the counter then finish early. */ +	idx = armpmu->get_event_idx(cpuc, hwc); +	if (idx < 0) { +		err = idx; +		goto out; +	} + +	/* +	 * If there is an event in the counter we are going to use then make +	 * sure it is disabled. +	 */ +	event->hw.idx = idx; +	armpmu->disable(hwc, idx); +	cpuc->events[idx] = event; +	set_bit(idx, cpuc->active_mask); + +	/* Set the period for the event. */ +	armpmu_event_set_period(event, hwc, idx); + +	/* Enable the event. */ +	armpmu->enable(hwc, idx); + +	/* Propagate our changes to the userspace mapping. */ +	perf_event_update_userpage(event); + +out: +	return err; +} + +static struct pmu pmu = { +	.enable	    = armpmu_enable, +	.disable    = armpmu_disable, +	.unthrottle = armpmu_unthrottle, +	.read	    = armpmu_read, +}; + +static int +validate_event(struct cpu_hw_events *cpuc, +	       struct perf_event *event) +{ +	struct hw_perf_event fake_event = event->hw; + +	if (event->pmu && event->pmu != &pmu) +		return 0; + +	return armpmu->get_event_idx(cpuc, &fake_event) >= 0; +} + +static int +validate_group(struct perf_event *event) +{ +	struct perf_event *sibling, *leader = event->group_leader; +	struct cpu_hw_events fake_pmu; + +	memset(&fake_pmu, 0, sizeof(fake_pmu)); + +	if (!validate_event(&fake_pmu, leader)) +		return -ENOSPC; + +	list_for_each_entry(sibling, &leader->sibling_list, group_entry) { +		if (!validate_event(&fake_pmu, sibling)) +			return -ENOSPC; +	} + +	if (!validate_event(&fake_pmu, event)) +		return -ENOSPC; + +	return 0; +} + +static int +armpmu_reserve_hardware(void) +{ +	int i; +	int err; + +	pmu_irqs = reserve_pmu(); +	if (IS_ERR(pmu_irqs)) { +		pr_warning("unable to reserve pmu\n"); +		return PTR_ERR(pmu_irqs); +	} + +	init_pmu(); + +	if (pmu_irqs->num_irqs < 1) { +		pr_err("no irqs for PMUs defined\n"); +		return -ENODEV; +	} + +	for (i = 0; i < pmu_irqs->num_irqs; ++i) { +		err = request_irq(pmu_irqs->irqs[i], armpmu->handle_irq, +				  IRQF_DISABLED, "armpmu", NULL); +		if (err) { +			pr_warning("unable to request IRQ%d for ARM " +				   "perf counters\n", pmu_irqs->irqs[i]); +			break; +		} +	} + +	if (err) { +		for (i = i - 1; i >= 0; --i) +			free_irq(pmu_irqs->irqs[i], NULL); +		release_pmu(pmu_irqs); +		pmu_irqs = NULL; +	} + +	return err; +} + +static void +armpmu_release_hardware(void) +{ +	int i; + +	for (i = pmu_irqs->num_irqs - 1; i >= 0; --i) +		free_irq(pmu_irqs->irqs[i], NULL); +	armpmu->stop(); + +	release_pmu(pmu_irqs); +	pmu_irqs = NULL; +} + +static atomic_t active_events = ATOMIC_INIT(0); +static DEFINE_MUTEX(pmu_reserve_mutex); + +static void +hw_perf_event_destroy(struct perf_event *event) +{ +	if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) { +		armpmu_release_hardware(); +		mutex_unlock(&pmu_reserve_mutex); +	} +} + +static int +__hw_perf_event_init(struct perf_event *event) +{ +	struct hw_perf_event *hwc = &event->hw; +	int mapping, err; + +	/* Decode the generic type into an ARM event identifier. */ +	if (PERF_TYPE_HARDWARE == event->attr.type) { +		mapping = armpmu->event_map(event->attr.config); +	} else if (PERF_TYPE_HW_CACHE == event->attr.type) { +		mapping = armpmu_map_cache_event(event->attr.config); +	} else if (PERF_TYPE_RAW == event->attr.type) { +		mapping = armpmu->raw_event(event->attr.config); +	} else { +		pr_debug("event type %x not supported\n", event->attr.type); +		return -EOPNOTSUPP; +	} + +	if (mapping < 0) { +		pr_debug("event %x:%llx not supported\n", event->attr.type, +			 event->attr.config); +		return mapping; +	} + +	/* +	 * Check whether we need to exclude the counter from certain modes. +	 * The ARM performance counters are on all of the time so if someone +	 * has asked us for some excludes then we have to fail. +	 */ +	if (event->attr.exclude_kernel || event->attr.exclude_user || +	    event->attr.exclude_hv || event->attr.exclude_idle) { +		pr_debug("ARM performance counters do not support " +			 "mode exclusion\n"); +		return -EPERM; +	} + +	/* +	 * We don't assign an index until we actually place the event onto +	 * hardware. Use -1 to signify that we haven't decided where to put it +	 * yet. For SMP systems, each core has it's own PMU so we can't do any +	 * clever allocation or constraints checking at this point. +	 */ +	hwc->idx = -1; + +	/* +	 * Store the event encoding into the config_base field. config and +	 * event_base are unused as the only 2 things we need to know are +	 * the event mapping and the counter to use. The counter to use is +	 * also the indx and the config_base is the event type. +	 */ +	hwc->config_base	    = (unsigned long)mapping; +	hwc->config		    = 0; +	hwc->event_base		    = 0; + +	if (!hwc->sample_period) { +		hwc->sample_period  = armpmu->max_period; +		hwc->last_period    = hwc->sample_period; +		atomic64_set(&hwc->period_left, hwc->sample_period); +	} + +	err = 0; +	if (event->group_leader != event) { +		err = validate_group(event); +		if (err) +			return -EINVAL; +	} + +	return err; +} + +const struct pmu * +hw_perf_event_init(struct perf_event *event) +{ +	int err = 0; + +	if (!armpmu) +		return ERR_PTR(-ENODEV); + +	event->destroy = hw_perf_event_destroy; + +	if (!atomic_inc_not_zero(&active_events)) { +		if (atomic_read(&active_events) > perf_max_events) { +			atomic_dec(&active_events); +			return ERR_PTR(-ENOSPC); +		} + +		mutex_lock(&pmu_reserve_mutex); +		if (atomic_read(&active_events) == 0) { +			err = armpmu_reserve_hardware(); +		} + +		if (!err) +			atomic_inc(&active_events); +		mutex_unlock(&pmu_reserve_mutex); +	} + +	if (err) +		return ERR_PTR(err); + +	err = __hw_perf_event_init(event); +	if (err) +		hw_perf_event_destroy(event); + +	return err ? ERR_PTR(err) : &pmu; +} + +void +hw_perf_enable(void) +{ +	/* Enable all of the perf events on hardware. */ +	int idx; +	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + +	if (!armpmu) +		return; + +	for (idx = 0; idx <= armpmu->num_events; ++idx) { +		struct perf_event *event = cpuc->events[idx]; + +		if (!event) +			continue; + +		armpmu->enable(&event->hw, idx); +	} + +	armpmu->start(); +} + +void +hw_perf_disable(void) +{ +	if (armpmu) +		armpmu->stop(); +} + +/* + * ARMv6 Performance counter handling code. + * + * ARMv6 has 2 configurable performance counters and a single cycle counter. + * They all share a single reset bit but can be written to zero so we can use + * that for a reset. + * + * The counters can't be individually enabled or disabled so when we remove + * one event and replace it with another we could get spurious counts from the + * wrong event. However, we can take advantage of the fact that the + * performance counters can export events to the event bus, and the event bus + * itself can be monitored. This requires that we *don't* export the events to + * the event bus. The procedure for disabling a configurable counter is: + *	- change the counter to count the ETMEXTOUT[0] signal (0x20). This + *	  effectively stops the counter from counting. + *	- disable the counter's interrupt generation (each counter has it's + *	  own interrupt enable bit). + * Once stopped, the counter value can be written as 0 to reset. + * + * To enable a counter: + *	- enable the counter's interrupt generation. + *	- set the new event type. + * + * Note: the dedicated cycle counter only counts cycles and can't be + * enabled/disabled independently of the others. When we want to disable the + * cycle counter, we have to just disable the interrupt reporting and start + * ignoring that counter. When re-enabling, we have to reset the value and + * enable the interrupt. + */ + +enum armv6_perf_types { +	ARMV6_PERFCTR_ICACHE_MISS	    = 0x0, +	ARMV6_PERFCTR_IBUF_STALL	    = 0x1, +	ARMV6_PERFCTR_DDEP_STALL	    = 0x2, +	ARMV6_PERFCTR_ITLB_MISS		    = 0x3, +	ARMV6_PERFCTR_DTLB_MISS		    = 0x4, +	ARMV6_PERFCTR_BR_EXEC		    = 0x5, +	ARMV6_PERFCTR_BR_MISPREDICT	    = 0x6, +	ARMV6_PERFCTR_INSTR_EXEC	    = 0x7, +	ARMV6_PERFCTR_DCACHE_HIT	    = 0x9, +	ARMV6_PERFCTR_DCACHE_ACCESS	    = 0xA, +	ARMV6_PERFCTR_DCACHE_MISS	    = 0xB, +	ARMV6_PERFCTR_DCACHE_WBACK	    = 0xC, +	ARMV6_PERFCTR_SW_PC_CHANGE	    = 0xD, +	ARMV6_PERFCTR_MAIN_TLB_MISS	    = 0xF, +	ARMV6_PERFCTR_EXPL_D_ACCESS	    = 0x10, +	ARMV6_PERFCTR_LSU_FULL_STALL	    = 0x11, +	ARMV6_PERFCTR_WBUF_DRAINED	    = 0x12, +	ARMV6_PERFCTR_CPU_CYCLES	    = 0xFF, +	ARMV6_PERFCTR_NOP		    = 0x20, +}; + +enum armv6_counters { +	ARMV6_CYCLE_COUNTER = 1, +	ARMV6_COUNTER0, +	ARMV6_COUNTER1, +}; + +/* + * The hardware events that we support. We do support cache operations but + * we have harvard caches and no way to combine instruction and data + * accesses/misses in hardware. + */ +static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = { +	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV6_PERFCTR_CPU_CYCLES, +	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV6_PERFCTR_INSTR_EXEC, +	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED, +	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED, +	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC, +	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV6_PERFCTR_BR_MISPREDICT, +	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED, +}; + +static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] +					  [PERF_COUNT_HW_CACHE_OP_MAX] +					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = { +	[C(L1D)] = { +		/* +		 * The performance counters don't differentiate between read +		 * and write accesses/misses so this isn't strictly correct, +		 * but it's the best we can do. Writes and reads get +		 * combined. +		 */ +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= ARMV6_PERFCTR_DCACHE_ACCESS, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DCACHE_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(L1I)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(LL)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(DTLB)] = { +		/* +		 * The ARM performance counters can count micro DTLB misses, +		 * micro ITLB misses and main TLB misses. There isn't an event +		 * for TLB misses, so use the micro misses here and if users +		 * want the main TLB misses they can use a raw counter. +		 */ +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_DTLB_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(ITLB)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ITLB_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(BPU)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +}; + +enum armv6mpcore_perf_types { +	ARMV6MPCORE_PERFCTR_ICACHE_MISS	    = 0x0, +	ARMV6MPCORE_PERFCTR_IBUF_STALL	    = 0x1, +	ARMV6MPCORE_PERFCTR_DDEP_STALL	    = 0x2, +	ARMV6MPCORE_PERFCTR_ITLB_MISS	    = 0x3, +	ARMV6MPCORE_PERFCTR_DTLB_MISS	    = 0x4, +	ARMV6MPCORE_PERFCTR_BR_EXEC	    = 0x5, +	ARMV6MPCORE_PERFCTR_BR_NOTPREDICT   = 0x6, +	ARMV6MPCORE_PERFCTR_BR_MISPREDICT   = 0x7, +	ARMV6MPCORE_PERFCTR_INSTR_EXEC	    = 0x8, +	ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS = 0xA, +	ARMV6MPCORE_PERFCTR_DCACHE_RDMISS   = 0xB, +	ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS = 0xC, +	ARMV6MPCORE_PERFCTR_DCACHE_WRMISS   = 0xD, +	ARMV6MPCORE_PERFCTR_DCACHE_EVICTION = 0xE, +	ARMV6MPCORE_PERFCTR_SW_PC_CHANGE    = 0xF, +	ARMV6MPCORE_PERFCTR_MAIN_TLB_MISS   = 0x10, +	ARMV6MPCORE_PERFCTR_EXPL_MEM_ACCESS = 0x11, +	ARMV6MPCORE_PERFCTR_LSU_FULL_STALL  = 0x12, +	ARMV6MPCORE_PERFCTR_WBUF_DRAINED    = 0x13, +	ARMV6MPCORE_PERFCTR_CPU_CYCLES	    = 0xFF, +}; + +/* + * The hardware events that we support. We do support cache operations but + * we have harvard caches and no way to combine instruction and data + * accesses/misses in hardware. + */ +static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = { +	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV6MPCORE_PERFCTR_CPU_CYCLES, +	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV6MPCORE_PERFCTR_INSTR_EXEC, +	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED, +	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED, +	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC, +	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV6MPCORE_PERFCTR_BR_MISPREDICT, +	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED, +}; + +static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] +					[PERF_COUNT_HW_CACHE_OP_MAX] +					[PERF_COUNT_HW_CACHE_RESULT_MAX] = { +	[C(L1D)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]  = +				ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS, +			[C(RESULT_MISS)]    = +				ARMV6MPCORE_PERFCTR_DCACHE_RDMISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]  = +				ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS, +			[C(RESULT_MISS)]    = +				ARMV6MPCORE_PERFCTR_DCACHE_WRMISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(L1I)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(LL)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(DTLB)] = { +		/* +		 * The ARM performance counters can count micro DTLB misses, +		 * micro ITLB misses and main TLB misses. There isn't an event +		 * for TLB misses, so use the micro misses here and if users +		 * want the main TLB misses they can use a raw counter. +		 */ +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_DTLB_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(ITLB)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ITLB_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(BPU)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED, +		}, +	}, +}; + +static inline unsigned long +armv6_pmcr_read(void) +{ +	u32 val; +	asm volatile("mrc   p15, 0, %0, c15, c12, 0" : "=r"(val)); +	return val; +} + +static inline void +armv6_pmcr_write(unsigned long val) +{ +	asm volatile("mcr   p15, 0, %0, c15, c12, 0" : : "r"(val)); +} + +#define ARMV6_PMCR_ENABLE		(1 << 0) +#define ARMV6_PMCR_CTR01_RESET		(1 << 1) +#define ARMV6_PMCR_CCOUNT_RESET		(1 << 2) +#define ARMV6_PMCR_CCOUNT_DIV		(1 << 3) +#define ARMV6_PMCR_COUNT0_IEN		(1 << 4) +#define ARMV6_PMCR_COUNT1_IEN		(1 << 5) +#define ARMV6_PMCR_CCOUNT_IEN		(1 << 6) +#define ARMV6_PMCR_COUNT0_OVERFLOW	(1 << 8) +#define ARMV6_PMCR_COUNT1_OVERFLOW	(1 << 9) +#define ARMV6_PMCR_CCOUNT_OVERFLOW	(1 << 10) +#define ARMV6_PMCR_EVT_COUNT0_SHIFT	20 +#define ARMV6_PMCR_EVT_COUNT0_MASK	(0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT) +#define ARMV6_PMCR_EVT_COUNT1_SHIFT	12 +#define ARMV6_PMCR_EVT_COUNT1_MASK	(0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT) + +#define ARMV6_PMCR_OVERFLOWED_MASK \ +	(ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \ +	 ARMV6_PMCR_CCOUNT_OVERFLOW) + +static inline int +armv6_pmcr_has_overflowed(unsigned long pmcr) +{ +	return (pmcr & ARMV6_PMCR_OVERFLOWED_MASK); +} + +static inline int +armv6_pmcr_counter_has_overflowed(unsigned long pmcr, +				  enum armv6_counters counter) +{ +	int ret = 0; + +	if (ARMV6_CYCLE_COUNTER == counter) +		ret = pmcr & ARMV6_PMCR_CCOUNT_OVERFLOW; +	else if (ARMV6_COUNTER0 == counter) +		ret = pmcr & ARMV6_PMCR_COUNT0_OVERFLOW; +	else if (ARMV6_COUNTER1 == counter) +		ret = pmcr & ARMV6_PMCR_COUNT1_OVERFLOW; +	else +		WARN_ONCE(1, "invalid counter number (%d)\n", counter); + +	return ret; +} + +static inline u32 +armv6pmu_read_counter(int counter) +{ +	unsigned long value = 0; + +	if (ARMV6_CYCLE_COUNTER == counter) +		asm volatile("mrc   p15, 0, %0, c15, c12, 1" : "=r"(value)); +	else if (ARMV6_COUNTER0 == counter) +		asm volatile("mrc   p15, 0, %0, c15, c12, 2" : "=r"(value)); +	else if (ARMV6_COUNTER1 == counter) +		asm volatile("mrc   p15, 0, %0, c15, c12, 3" : "=r"(value)); +	else +		WARN_ONCE(1, "invalid counter number (%d)\n", counter); + +	return value; +} + +static inline void +armv6pmu_write_counter(int counter, +		       u32 value) +{ +	if (ARMV6_CYCLE_COUNTER == counter) +		asm volatile("mcr   p15, 0, %0, c15, c12, 1" : : "r"(value)); +	else if (ARMV6_COUNTER0 == counter) +		asm volatile("mcr   p15, 0, %0, c15, c12, 2" : : "r"(value)); +	else if (ARMV6_COUNTER1 == counter) +		asm volatile("mcr   p15, 0, %0, c15, c12, 3" : : "r"(value)); +	else +		WARN_ONCE(1, "invalid counter number (%d)\n", counter); +} + +void +armv6pmu_enable_event(struct hw_perf_event *hwc, +		      int idx) +{ +	unsigned long val, mask, evt, flags; + +	if (ARMV6_CYCLE_COUNTER == idx) { +		mask	= 0; +		evt	= ARMV6_PMCR_CCOUNT_IEN; +	} else if (ARMV6_COUNTER0 == idx) { +		mask	= ARMV6_PMCR_EVT_COUNT0_MASK; +		evt	= (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) | +			  ARMV6_PMCR_COUNT0_IEN; +	} else if (ARMV6_COUNTER1 == idx) { +		mask	= ARMV6_PMCR_EVT_COUNT1_MASK; +		evt	= (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) | +			  ARMV6_PMCR_COUNT1_IEN; +	} else { +		WARN_ONCE(1, "invalid counter number (%d)\n", idx); +		return; +	} + +	/* +	 * Mask out the current event and set the counter to count the event +	 * that we're interested in. +	 */ +	spin_lock_irqsave(&pmu_lock, flags); +	val = armv6_pmcr_read(); +	val &= ~mask; +	val |= evt; +	armv6_pmcr_write(val); +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static irqreturn_t +armv6pmu_handle_irq(int irq_num, +		    void *dev) +{ +	unsigned long pmcr = armv6_pmcr_read(); +	struct perf_sample_data data; +	struct cpu_hw_events *cpuc; +	struct pt_regs *regs; +	int idx; + +	if (!armv6_pmcr_has_overflowed(pmcr)) +		return IRQ_NONE; + +	regs = get_irq_regs(); + +	/* +	 * The interrupts are cleared by writing the overflow flags back to +	 * the control register. All of the other bits don't have any effect +	 * if they are rewritten, so write the whole value back. +	 */ +	armv6_pmcr_write(pmcr); + +	data.addr = 0; + +	cpuc = &__get_cpu_var(cpu_hw_events); +	for (idx = 0; idx <= armpmu->num_events; ++idx) { +		struct perf_event *event = cpuc->events[idx]; +		struct hw_perf_event *hwc; + +		if (!test_bit(idx, cpuc->active_mask)) +			continue; + +		/* +		 * We have a single interrupt for all counters. Check that +		 * each counter has overflowed before we process it. +		 */ +		if (!armv6_pmcr_counter_has_overflowed(pmcr, idx)) +			continue; + +		hwc = &event->hw; +		armpmu_event_update(event, hwc, idx); +		data.period = event->hw.last_period; +		if (!armpmu_event_set_period(event, hwc, idx)) +			continue; + +		if (perf_event_overflow(event, 0, &data, regs)) +			armpmu->disable(hwc, idx); +	} + +	/* +	 * Handle the pending perf events. +	 * +	 * Note: this call *must* be run with interrupts enabled. For +	 * platforms that can have the PMU interrupts raised as a PMI, this +	 * will not work. +	 */ +	perf_event_do_pending(); + +	return IRQ_HANDLED; +} + +static void +armv6pmu_start(void) +{ +	unsigned long flags, val; + +	spin_lock_irqsave(&pmu_lock, flags); +	val = armv6_pmcr_read(); +	val |= ARMV6_PMCR_ENABLE; +	armv6_pmcr_write(val); +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +void +armv6pmu_stop(void) +{ +	unsigned long flags, val; + +	spin_lock_irqsave(&pmu_lock, flags); +	val = armv6_pmcr_read(); +	val &= ~ARMV6_PMCR_ENABLE; +	armv6_pmcr_write(val); +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static inline int +armv6pmu_event_map(int config) +{ +	int mapping = armv6_perf_map[config]; +	if (HW_OP_UNSUPPORTED == mapping) +		mapping = -EOPNOTSUPP; +	return mapping; +} + +static inline int +armv6mpcore_pmu_event_map(int config) +{ +	int mapping = armv6mpcore_perf_map[config]; +	if (HW_OP_UNSUPPORTED == mapping) +		mapping = -EOPNOTSUPP; +	return mapping; +} + +static u64 +armv6pmu_raw_event(u64 config) +{ +	return config & 0xff; +} + +static int +armv6pmu_get_event_idx(struct cpu_hw_events *cpuc, +		       struct hw_perf_event *event) +{ +	/* Always place a cycle counter into the cycle counter. */ +	if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) { +		if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask)) +			return -EAGAIN; + +		return ARMV6_CYCLE_COUNTER; +	} else { +		/* +		 * For anything other than a cycle counter, try and use +		 * counter0 and counter1. +		 */ +		if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) { +			return ARMV6_COUNTER1; +		} + +		if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) { +			return ARMV6_COUNTER0; +		} + +		/* The counters are all in use. */ +		return -EAGAIN; +	} +} + +static void +armv6pmu_disable_event(struct hw_perf_event *hwc, +		       int idx) +{ +	unsigned long val, mask, evt, flags; + +	if (ARMV6_CYCLE_COUNTER == idx) { +		mask	= ARMV6_PMCR_CCOUNT_IEN; +		evt	= 0; +	} else if (ARMV6_COUNTER0 == idx) { +		mask	= ARMV6_PMCR_COUNT0_IEN | ARMV6_PMCR_EVT_COUNT0_MASK; +		evt	= ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT0_SHIFT; +	} else if (ARMV6_COUNTER1 == idx) { +		mask	= ARMV6_PMCR_COUNT1_IEN | ARMV6_PMCR_EVT_COUNT1_MASK; +		evt	= ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT1_SHIFT; +	} else { +		WARN_ONCE(1, "invalid counter number (%d)\n", idx); +		return; +	} + +	/* +	 * Mask out the current event and set the counter to count the number +	 * of ETM bus signal assertion cycles. The external reporting should +	 * be disabled and so this should never increment. +	 */ +	spin_lock_irqsave(&pmu_lock, flags); +	val = armv6_pmcr_read(); +	val &= ~mask; +	val |= evt; +	armv6_pmcr_write(val); +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static void +armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc, +			      int idx) +{ +	unsigned long val, mask, flags, evt = 0; + +	if (ARMV6_CYCLE_COUNTER == idx) { +		mask	= ARMV6_PMCR_CCOUNT_IEN; +	} else if (ARMV6_COUNTER0 == idx) { +		mask	= ARMV6_PMCR_COUNT0_IEN; +	} else if (ARMV6_COUNTER1 == idx) { +		mask	= ARMV6_PMCR_COUNT1_IEN; +	} else { +		WARN_ONCE(1, "invalid counter number (%d)\n", idx); +		return; +	} + +	/* +	 * Unlike UP ARMv6, we don't have a way of stopping the counters. We +	 * simply disable the interrupt reporting. +	 */ +	spin_lock_irqsave(&pmu_lock, flags); +	val = armv6_pmcr_read(); +	val &= ~mask; +	val |= evt; +	armv6_pmcr_write(val); +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static const struct arm_pmu armv6pmu = { +	.name			= "v6", +	.handle_irq		= armv6pmu_handle_irq, +	.enable			= armv6pmu_enable_event, +	.disable		= armv6pmu_disable_event, +	.event_map		= armv6pmu_event_map, +	.raw_event		= armv6pmu_raw_event, +	.read_counter		= armv6pmu_read_counter, +	.write_counter		= armv6pmu_write_counter, +	.get_event_idx		= armv6pmu_get_event_idx, +	.start			= armv6pmu_start, +	.stop			= armv6pmu_stop, +	.num_events		= 3, +	.max_period		= (1LLU << 32) - 1, +}; + +/* + * ARMv6mpcore is almost identical to single core ARMv6 with the exception + * that some of the events have different enumerations and that there is no + * *hack* to stop the programmable counters. To stop the counters we simply + * disable the interrupt reporting and update the event. When unthrottling we + * reset the period and enable the interrupt reporting. + */ +static const struct arm_pmu armv6mpcore_pmu = { +	.name			= "v6mpcore", +	.handle_irq		= armv6pmu_handle_irq, +	.enable			= armv6pmu_enable_event, +	.disable		= armv6mpcore_pmu_disable_event, +	.event_map		= armv6mpcore_pmu_event_map, +	.raw_event		= armv6pmu_raw_event, +	.read_counter		= armv6pmu_read_counter, +	.write_counter		= armv6pmu_write_counter, +	.get_event_idx		= armv6pmu_get_event_idx, +	.start			= armv6pmu_start, +	.stop			= armv6pmu_stop, +	.num_events		= 3, +	.max_period		= (1LLU << 32) - 1, +}; + +/* + * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code. + * + * Copied from ARMv6 code, with the low level code inspired + *  by the ARMv7 Oprofile code. + * + * Cortex-A8 has up to 4 configurable performance counters and + *  a single cycle counter. + * Cortex-A9 has up to 31 configurable performance counters and + *  a single cycle counter. + * + * All counters can be enabled/disabled and IRQ masked separately. The cycle + *  counter and all 4 performance counters together can be reset separately. + */ + +#define ARMV7_PMU_CORTEX_A8_NAME		"ARMv7 Cortex-A8" + +#define ARMV7_PMU_CORTEX_A9_NAME		"ARMv7 Cortex-A9" + +/* Common ARMv7 event types */ +enum armv7_perf_types { +	ARMV7_PERFCTR_PMNC_SW_INCR		= 0x00, +	ARMV7_PERFCTR_IFETCH_MISS		= 0x01, +	ARMV7_PERFCTR_ITLB_MISS			= 0x02, +	ARMV7_PERFCTR_DCACHE_REFILL		= 0x03, +	ARMV7_PERFCTR_DCACHE_ACCESS		= 0x04, +	ARMV7_PERFCTR_DTLB_REFILL		= 0x05, +	ARMV7_PERFCTR_DREAD			= 0x06, +	ARMV7_PERFCTR_DWRITE			= 0x07, + +	ARMV7_PERFCTR_EXC_TAKEN			= 0x09, +	ARMV7_PERFCTR_EXC_EXECUTED		= 0x0A, +	ARMV7_PERFCTR_CID_WRITE			= 0x0B, +	/* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS. +	 * It counts: +	 *  - all branch instructions, +	 *  - instructions that explicitly write the PC, +	 *  - exception generating instructions. +	 */ +	ARMV7_PERFCTR_PC_WRITE			= 0x0C, +	ARMV7_PERFCTR_PC_IMM_BRANCH		= 0x0D, +	ARMV7_PERFCTR_UNALIGNED_ACCESS		= 0x0F, +	ARMV7_PERFCTR_PC_BRANCH_MIS_PRED	= 0x10, +	ARMV7_PERFCTR_CLOCK_CYCLES		= 0x11, + +	ARMV7_PERFCTR_PC_BRANCH_MIS_USED	= 0x12, + +	ARMV7_PERFCTR_CPU_CYCLES		= 0xFF +}; + +/* ARMv7 Cortex-A8 specific event types */ +enum armv7_a8_perf_types { +	ARMV7_PERFCTR_INSTR_EXECUTED		= 0x08, + +	ARMV7_PERFCTR_PC_PROC_RETURN		= 0x0E, + +	ARMV7_PERFCTR_WRITE_BUFFER_FULL		= 0x40, +	ARMV7_PERFCTR_L2_STORE_MERGED		= 0x41, +	ARMV7_PERFCTR_L2_STORE_BUFF		= 0x42, +	ARMV7_PERFCTR_L2_ACCESS			= 0x43, +	ARMV7_PERFCTR_L2_CACH_MISS		= 0x44, +	ARMV7_PERFCTR_AXI_READ_CYCLES		= 0x45, +	ARMV7_PERFCTR_AXI_WRITE_CYCLES		= 0x46, +	ARMV7_PERFCTR_MEMORY_REPLAY		= 0x47, +	ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY	= 0x48, +	ARMV7_PERFCTR_L1_DATA_MISS		= 0x49, +	ARMV7_PERFCTR_L1_INST_MISS		= 0x4A, +	ARMV7_PERFCTR_L1_DATA_COLORING		= 0x4B, +	ARMV7_PERFCTR_L1_NEON_DATA		= 0x4C, +	ARMV7_PERFCTR_L1_NEON_CACH_DATA		= 0x4D, +	ARMV7_PERFCTR_L2_NEON			= 0x4E, +	ARMV7_PERFCTR_L2_NEON_HIT		= 0x4F, +	ARMV7_PERFCTR_L1_INST			= 0x50, +	ARMV7_PERFCTR_PC_RETURN_MIS_PRED	= 0x51, +	ARMV7_PERFCTR_PC_BRANCH_FAILED		= 0x52, +	ARMV7_PERFCTR_PC_BRANCH_TAKEN		= 0x53, +	ARMV7_PERFCTR_PC_BRANCH_EXECUTED	= 0x54, +	ARMV7_PERFCTR_OP_EXECUTED		= 0x55, +	ARMV7_PERFCTR_CYCLES_INST_STALL		= 0x56, +	ARMV7_PERFCTR_CYCLES_INST		= 0x57, +	ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL	= 0x58, +	ARMV7_PERFCTR_CYCLES_NEON_INST_STALL	= 0x59, +	ARMV7_PERFCTR_NEON_CYCLES		= 0x5A, + +	ARMV7_PERFCTR_PMU0_EVENTS		= 0x70, +	ARMV7_PERFCTR_PMU1_EVENTS		= 0x71, +	ARMV7_PERFCTR_PMU_EVENTS		= 0x72, +}; + +/* ARMv7 Cortex-A9 specific event types */ +enum armv7_a9_perf_types { +	ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC	= 0x40, +	ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC	= 0x41, +	ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC	= 0x42, + +	ARMV7_PERFCTR_COHERENT_LINE_MISS	= 0x50, +	ARMV7_PERFCTR_COHERENT_LINE_HIT		= 0x51, + +	ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES	= 0x60, +	ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES	= 0x61, +	ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES	= 0x62, +	ARMV7_PERFCTR_STREX_EXECUTED_PASSED	= 0x63, +	ARMV7_PERFCTR_STREX_EXECUTED_FAILED	= 0x64, +	ARMV7_PERFCTR_DATA_EVICTION		= 0x65, +	ARMV7_PERFCTR_ISSUE_STAGE_NO_INST	= 0x66, +	ARMV7_PERFCTR_ISSUE_STAGE_EMPTY		= 0x67, +	ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE	= 0x68, + +	ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS	= 0x6E, + +	ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST	= 0x70, +	ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST	= 0x71, +	ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST	= 0x72, +	ARMV7_PERFCTR_FP_EXECUTED_INST		= 0x73, +	ARMV7_PERFCTR_NEON_EXECUTED_INST	= 0x74, + +	ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES	= 0x80, +	ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES	= 0x81, +	ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES	= 0x82, +	ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES	= 0x83, +	ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES	= 0x84, +	ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES 	= 0x85, +	ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES	= 0x86, + +	ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES	= 0x8A, +	ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES	= 0x8B, + +	ARMV7_PERFCTR_ISB_INST			= 0x90, +	ARMV7_PERFCTR_DSB_INST			= 0x91, +	ARMV7_PERFCTR_DMB_INST			= 0x92, +	ARMV7_PERFCTR_EXT_INTERRUPTS		= 0x93, + +	ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED	= 0xA0, +	ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED	= 0xA1, +	ARMV7_PERFCTR_PLE_FIFO_FLUSH		= 0xA2, +	ARMV7_PERFCTR_PLE_RQST_COMPLETED	= 0xA3, +	ARMV7_PERFCTR_PLE_FIFO_OVERFLOW		= 0xA4, +	ARMV7_PERFCTR_PLE_RQST_PROG		= 0xA5 +}; + +/* + * Cortex-A8 HW events mapping + * + * The hardware events that we support. We do support cache operations but + * we have harvard caches and no way to combine instruction and data + * accesses/misses in hardware. + */ +static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = { +	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES, +	[PERF_COUNT_HW_INSTRUCTIONS]	    = ARMV7_PERFCTR_INSTR_EXECUTED, +	[PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED, +	[PERF_COUNT_HW_CACHE_MISSES]	    = HW_OP_UNSUPPORTED, +	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, +	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, +	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES, +}; + +static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] +					  [PERF_COUNT_HW_CACHE_OP_MAX] +					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = { +	[C(L1D)] = { +		/* +		 * The performance counters don't differentiate between read +		 * and write accesses/misses so this isn't strictly correct, +		 * but it's the best we can do. Writes and reads get +		 * combined. +		 */ +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(L1I)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_INST, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_INST_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_INST, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_INST_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(LL)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_ACCESS, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACH_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L2_ACCESS, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L2_CACH_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(DTLB)] = { +		/* +		 * Only ITLB misses and DTLB refills are supported. +		 * If users want the DTLB refills misses a raw counter +		 * must be used. +		 */ +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(ITLB)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(BPU)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE, +			[C(RESULT_MISS)] +					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE, +			[C(RESULT_MISS)] +					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +}; + +/* + * Cortex-A9 HW events mapping + */ +static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = { +	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES, +	[PERF_COUNT_HW_INSTRUCTIONS]	    = +					ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE, +	[PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT, +	[PERF_COUNT_HW_CACHE_MISSES]	    = ARMV7_PERFCTR_COHERENT_LINE_MISS, +	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, +	[PERF_COUNT_HW_BRANCH_MISSES]	    = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, +	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES, +}; + +static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] +					  [PERF_COUNT_HW_CACHE_OP_MAX] +					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = { +	[C(L1D)] = { +		/* +		 * The performance counters don't differentiate between read +		 * and write accesses/misses so this isn't strictly correct, +		 * but it's the best we can do. Writes and reads get +		 * combined. +		 */ +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_DCACHE_ACCESS, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DCACHE_REFILL, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(L1I)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_IFETCH_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(LL)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(DTLB)] = { +		/* +		 * Only ITLB misses and DTLB refills are supported. +		 * If users want the DTLB refills misses a raw counter +		 * must be used. +		 */ +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_DTLB_REFILL, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(ITLB)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= ARMV7_PERFCTR_ITLB_MISS, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +	[C(BPU)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE, +			[C(RESULT_MISS)] +					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_PC_WRITE, +			[C(RESULT_MISS)] +					= ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	}, +}; + +/* + * Perf Events counters + */ +enum armv7_counters { +	ARMV7_CYCLE_COUNTER 		= 1,	/* Cycle counter */ +	ARMV7_COUNTER0			= 2,	/* First event counter */ +}; + +/* + * The cycle counter is ARMV7_CYCLE_COUNTER. + * The first event counter is ARMV7_COUNTER0. + * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1). + */ +#define	ARMV7_COUNTER_LAST	(ARMV7_COUNTER0 + armpmu->num_events - 1) + +/* + * ARMv7 low level PMNC access + */ + +/* + * Per-CPU PMNC: config reg + */ +#define ARMV7_PMNC_E		(1 << 0) /* Enable all counters */ +#define ARMV7_PMNC_P		(1 << 1) /* Reset all counters */ +#define ARMV7_PMNC_C		(1 << 2) /* Cycle counter reset */ +#define ARMV7_PMNC_D		(1 << 3) /* CCNT counts every 64th cpu cycle */ +#define ARMV7_PMNC_X		(1 << 4) /* Export to ETM */ +#define ARMV7_PMNC_DP		(1 << 5) /* Disable CCNT if non-invasive debug*/ +#define	ARMV7_PMNC_N_SHIFT	11	 /* Number of counters supported */ +#define	ARMV7_PMNC_N_MASK	0x1f +#define	ARMV7_PMNC_MASK		0x3f	 /* Mask for writable bits */ + +/* + * Available counters + */ +#define ARMV7_CNT0 		0	/* First event counter */ +#define ARMV7_CCNT 		31	/* Cycle counter */ + +/* Perf Event to low level counters mapping */ +#define ARMV7_EVENT_CNT_TO_CNTx	(ARMV7_COUNTER0 - ARMV7_CNT0) + +/* + * CNTENS: counters enable reg + */ +#define ARMV7_CNTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) +#define ARMV7_CNTENS_C		(1 << ARMV7_CCNT) + +/* + * CNTENC: counters disable reg + */ +#define ARMV7_CNTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) +#define ARMV7_CNTENC_C		(1 << ARMV7_CCNT) + +/* + * INTENS: counters overflow interrupt enable reg + */ +#define ARMV7_INTENS_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) +#define ARMV7_INTENS_C		(1 << ARMV7_CCNT) + +/* + * INTENC: counters overflow interrupt disable reg + */ +#define ARMV7_INTENC_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) +#define ARMV7_INTENC_C		(1 << ARMV7_CCNT) + +/* + * EVTSEL: Event selection reg + */ +#define	ARMV7_EVTSEL_MASK	0x7f		/* Mask for writable bits */ + +/* + * SELECT: Counter selection reg + */ +#define	ARMV7_SELECT_MASK	0x1f		/* Mask for writable bits */ + +/* + * FLAG: counters overflow flag status reg + */ +#define ARMV7_FLAG_P(idx)	(1 << (idx - ARMV7_EVENT_CNT_TO_CNTx)) +#define ARMV7_FLAG_C		(1 << ARMV7_CCNT) +#define	ARMV7_FLAG_MASK		0xffffffff	/* Mask for writable bits */ +#define	ARMV7_OVERFLOWED_MASK	ARMV7_FLAG_MASK + +static inline unsigned long armv7_pmnc_read(void) +{ +	u32 val; +	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val)); +	return val; +} + +static inline void armv7_pmnc_write(unsigned long val) +{ +	val &= ARMV7_PMNC_MASK; +	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val)); +} + +static inline int armv7_pmnc_has_overflowed(unsigned long pmnc) +{ +	return pmnc & ARMV7_OVERFLOWED_MASK; +} + +static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc, +					enum armv7_counters counter) +{ +	int ret; + +	if (counter == ARMV7_CYCLE_COUNTER) +		ret = pmnc & ARMV7_FLAG_C; +	else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST)) +		ret = pmnc & ARMV7_FLAG_P(counter); +	else +		pr_err("CPU%u checking wrong counter %d overflow status\n", +			smp_processor_id(), counter); + +	return ret; +} + +static inline int armv7_pmnc_select_counter(unsigned int idx) +{ +	u32 val; + +	if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) { +		pr_err("CPU%u selecting wrong PMNC counter" +			" %d\n", smp_processor_id(), idx); +		return -1; +	} + +	val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK; +	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); + +	return idx; +} + +static inline u32 armv7pmu_read_counter(int idx) +{ +	unsigned long value = 0; + +	if (idx == ARMV7_CYCLE_COUNTER) +		asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value)); +	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) { +		if (armv7_pmnc_select_counter(idx) == idx) +			asm volatile("mrc p15, 0, %0, c9, c13, 2" +				     : "=r" (value)); +	} else +		pr_err("CPU%u reading wrong counter %d\n", +			smp_processor_id(), idx); + +	return value; +} + +static inline void armv7pmu_write_counter(int idx, u32 value) +{ +	if (idx == ARMV7_CYCLE_COUNTER) +		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value)); +	else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) { +		if (armv7_pmnc_select_counter(idx) == idx) +			asm volatile("mcr p15, 0, %0, c9, c13, 2" +				     : : "r" (value)); +	} else +		pr_err("CPU%u writing wrong counter %d\n", +			smp_processor_id(), idx); +} + +static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val) +{ +	if (armv7_pmnc_select_counter(idx) == idx) { +		val &= ARMV7_EVTSEL_MASK; +		asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); +	} +} + +static inline u32 armv7_pmnc_enable_counter(unsigned int idx) +{ +	u32 val; + +	if ((idx != ARMV7_CYCLE_COUNTER) && +	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { +		pr_err("CPU%u enabling wrong PMNC counter" +			" %d\n", smp_processor_id(), idx); +		return -1; +	} + +	if (idx == ARMV7_CYCLE_COUNTER) +		val = ARMV7_CNTENS_C; +	else +		val = ARMV7_CNTENS_P(idx); + +	asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); + +	return idx; +} + +static inline u32 armv7_pmnc_disable_counter(unsigned int idx) +{ +	u32 val; + + +	if ((idx != ARMV7_CYCLE_COUNTER) && +	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { +		pr_err("CPU%u disabling wrong PMNC counter" +			" %d\n", smp_processor_id(), idx); +		return -1; +	} + +	if (idx == ARMV7_CYCLE_COUNTER) +		val = ARMV7_CNTENC_C; +	else +		val = ARMV7_CNTENC_P(idx); + +	asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); + +	return idx; +} + +static inline u32 armv7_pmnc_enable_intens(unsigned int idx) +{ +	u32 val; + +	if ((idx != ARMV7_CYCLE_COUNTER) && +	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { +		pr_err("CPU%u enabling wrong PMNC counter" +			" interrupt enable %d\n", smp_processor_id(), idx); +		return -1; +	} + +	if (idx == ARMV7_CYCLE_COUNTER) +		val = ARMV7_INTENS_C; +	else +		val = ARMV7_INTENS_P(idx); + +	asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val)); + +	return idx; +} + +static inline u32 armv7_pmnc_disable_intens(unsigned int idx) +{ +	u32 val; + +	if ((idx != ARMV7_CYCLE_COUNTER) && +	    ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) { +		pr_err("CPU%u disabling wrong PMNC counter" +			" interrupt enable %d\n", smp_processor_id(), idx); +		return -1; +	} + +	if (idx == ARMV7_CYCLE_COUNTER) +		val = ARMV7_INTENC_C; +	else +		val = ARMV7_INTENC_P(idx); + +	asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val)); + +	return idx; +} + +static inline u32 armv7_pmnc_getreset_flags(void) +{ +	u32 val; + +	/* Read */ +	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); + +	/* Write to clear flags */ +	val &= ARMV7_FLAG_MASK; +	asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val)); + +	return val; +} + +#ifdef DEBUG +static void armv7_pmnc_dump_regs(void) +{ +	u32 val; +	unsigned int cnt; + +	printk(KERN_INFO "PMNC registers dump:\n"); + +	asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); +	printk(KERN_INFO "PMNC  =0x%08x\n", val); + +	asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val)); +	printk(KERN_INFO "CNTENS=0x%08x\n", val); + +	asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val)); +	printk(KERN_INFO "INTENS=0x%08x\n", val); + +	asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); +	printk(KERN_INFO "FLAGS =0x%08x\n", val); + +	asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val)); +	printk(KERN_INFO "SELECT=0x%08x\n", val); + +	asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); +	printk(KERN_INFO "CCNT  =0x%08x\n", val); + +	for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) { +		armv7_pmnc_select_counter(cnt); +		asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); +		printk(KERN_INFO "CNT[%d] count =0x%08x\n", +			cnt-ARMV7_EVENT_CNT_TO_CNTx, val); +		asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val)); +		printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n", +			cnt-ARMV7_EVENT_CNT_TO_CNTx, val); +	} +} +#endif + +void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) +{ +	unsigned long flags; + +	/* +	 * Enable counter and interrupt, and set the counter to count +	 * the event that we're interested in. +	 */ +	spin_lock_irqsave(&pmu_lock, flags); + +	/* +	 * Disable counter +	 */ +	armv7_pmnc_disable_counter(idx); + +	/* +	 * Set event (if destined for PMNx counters) +	 * We don't need to set the event if it's a cycle count +	 */ +	if (idx != ARMV7_CYCLE_COUNTER) +		armv7_pmnc_write_evtsel(idx, hwc->config_base); + +	/* +	 * Enable interrupt for this counter +	 */ +	armv7_pmnc_enable_intens(idx); + +	/* +	 * Enable counter +	 */ +	armv7_pmnc_enable_counter(idx); + +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) +{ +	unsigned long flags; + +	/* +	 * Disable counter and interrupt +	 */ +	spin_lock_irqsave(&pmu_lock, flags); + +	/* +	 * Disable counter +	 */ +	armv7_pmnc_disable_counter(idx); + +	/* +	 * Disable interrupt for this counter +	 */ +	armv7_pmnc_disable_intens(idx); + +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) +{ +	unsigned long pmnc; +	struct perf_sample_data data; +	struct cpu_hw_events *cpuc; +	struct pt_regs *regs; +	int idx; + +	/* +	 * Get and reset the IRQ flags +	 */ +	pmnc = armv7_pmnc_getreset_flags(); + +	/* +	 * Did an overflow occur? +	 */ +	if (!armv7_pmnc_has_overflowed(pmnc)) +		return IRQ_NONE; + +	/* +	 * Handle the counter(s) overflow(s) +	 */ +	regs = get_irq_regs(); + +	data.addr = 0; + +	cpuc = &__get_cpu_var(cpu_hw_events); +	for (idx = 0; idx <= armpmu->num_events; ++idx) { +		struct perf_event *event = cpuc->events[idx]; +		struct hw_perf_event *hwc; + +		if (!test_bit(idx, cpuc->active_mask)) +			continue; + +		/* +		 * We have a single interrupt for all counters. Check that +		 * each counter has overflowed before we process it. +		 */ +		if (!armv7_pmnc_counter_has_overflowed(pmnc, idx)) +			continue; + +		hwc = &event->hw; +		armpmu_event_update(event, hwc, idx); +		data.period = event->hw.last_period; +		if (!armpmu_event_set_period(event, hwc, idx)) +			continue; + +		if (perf_event_overflow(event, 0, &data, regs)) +			armpmu->disable(hwc, idx); +	} + +	/* +	 * Handle the pending perf events. +	 * +	 * Note: this call *must* be run with interrupts enabled. For +	 * platforms that can have the PMU interrupts raised as a PMI, this +	 * will not work. +	 */ +	perf_event_do_pending(); + +	return IRQ_HANDLED; +} + +static void armv7pmu_start(void) +{ +	unsigned long flags; + +	spin_lock_irqsave(&pmu_lock, flags); +	/* Enable all counters */ +	armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E); +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static void armv7pmu_stop(void) +{ +	unsigned long flags; + +	spin_lock_irqsave(&pmu_lock, flags); +	/* Disable all counters */ +	armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E); +	spin_unlock_irqrestore(&pmu_lock, flags); +} + +static inline int armv7_a8_pmu_event_map(int config) +{ +	int mapping = armv7_a8_perf_map[config]; +	if (HW_OP_UNSUPPORTED == mapping) +		mapping = -EOPNOTSUPP; +	return mapping; +} + +static inline int armv7_a9_pmu_event_map(int config) +{ +	int mapping = armv7_a9_perf_map[config]; +	if (HW_OP_UNSUPPORTED == mapping) +		mapping = -EOPNOTSUPP; +	return mapping; +} + +static u64 armv7pmu_raw_event(u64 config) +{ +	return config & 0xff; +} + +static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc, +				  struct hw_perf_event *event) +{ +	int idx; + +	/* Always place a cycle counter into the cycle counter. */ +	if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) { +		if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask)) +			return -EAGAIN; + +		return ARMV7_CYCLE_COUNTER; +	} else { +		/* +		 * For anything other than a cycle counter, try and use +		 * the events counters +		 */ +		for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) { +			if (!test_and_set_bit(idx, cpuc->used_mask)) +				return idx; +		} + +		/* The counters are all in use. */ +		return -EAGAIN; +	} +} + +static struct arm_pmu armv7pmu = { +	.handle_irq		= armv7pmu_handle_irq, +	.enable			= armv7pmu_enable_event, +	.disable		= armv7pmu_disable_event, +	.raw_event		= armv7pmu_raw_event, +	.read_counter		= armv7pmu_read_counter, +	.write_counter		= armv7pmu_write_counter, +	.get_event_idx		= armv7pmu_get_event_idx, +	.start			= armv7pmu_start, +	.stop			= armv7pmu_stop, +	.max_period		= (1LLU << 32) - 1, +}; + +static u32 __init armv7_reset_read_pmnc(void) +{ +	u32 nb_cnt; + +	/* Initialize & Reset PMNC: C and P bits */ +	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C); + +	/* Read the nb of CNTx counters supported from PMNC */ +	nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK; + +	/* Add the CPU cycles counter and return */ +	return nb_cnt + 1; +} + +static int __init +init_hw_perf_events(void) +{ +	unsigned long cpuid = read_cpuid_id(); +	unsigned long implementor = (cpuid & 0xFF000000) >> 24; +	unsigned long part_number = (cpuid & 0xFFF0); + +	/* We only support ARM CPUs implemented by ARM at the moment. */ +	if (0x41 == implementor) { +		switch (part_number) { +		case 0xB360:	/* ARM1136 */ +		case 0xB560:	/* ARM1156 */ +		case 0xB760:	/* ARM1176 */ +			armpmu = &armv6pmu; +			memcpy(armpmu_perf_cache_map, armv6_perf_cache_map, +					sizeof(armv6_perf_cache_map)); +			perf_max_events	= armv6pmu.num_events; +			break; +		case 0xB020:	/* ARM11mpcore */ +			armpmu = &armv6mpcore_pmu; +			memcpy(armpmu_perf_cache_map, +			       armv6mpcore_perf_cache_map, +			       sizeof(armv6mpcore_perf_cache_map)); +			perf_max_events = armv6mpcore_pmu.num_events; +			break; +		case 0xC080:	/* Cortex-A8 */ +			armv7pmu.name = ARMV7_PMU_CORTEX_A8_NAME; +			memcpy(armpmu_perf_cache_map, armv7_a8_perf_cache_map, +				sizeof(armv7_a8_perf_cache_map)); +			armv7pmu.event_map = armv7_a8_pmu_event_map; +			armpmu = &armv7pmu; + +			/* Reset PMNC and read the nb of CNTx counters +			    supported */ +			armv7pmu.num_events = armv7_reset_read_pmnc(); +			perf_max_events = armv7pmu.num_events; +			break; +		case 0xC090:	/* Cortex-A9 */ +			armv7pmu.name = ARMV7_PMU_CORTEX_A9_NAME; +			memcpy(armpmu_perf_cache_map, armv7_a9_perf_cache_map, +				sizeof(armv7_a9_perf_cache_map)); +			armv7pmu.event_map = armv7_a9_pmu_event_map; +			armpmu = &armv7pmu; + +			/* Reset PMNC and read the nb of CNTx counters +			    supported */ +			armv7pmu.num_events = armv7_reset_read_pmnc(); +			perf_max_events = armv7pmu.num_events; +			break; +		default: +			pr_info("no hardware support available\n"); +			perf_max_events = -1; +		} +	} + +	if (armpmu) +		pr_info("enabled with %s PMU driver, %d counters available\n", +			armpmu->name, armpmu->num_events); + +	return 0; +} +arch_initcall(init_hw_perf_events); + +/* + * Callchain handling code. + */ +static inline void +callchain_store(struct perf_callchain_entry *entry, +		u64 ip) +{ +	if (entry->nr < PERF_MAX_STACK_DEPTH) +		entry->ip[entry->nr++] = ip; +} + +/* + * The registers we're interested in are at the end of the variable + * length saved register structure. The fp points at the end of this + * structure so the address of this struct is: + * (struct frame_tail *)(xxx->fp)-1 + * + * This code has been adapted from the ARM OProfile support. + */ +struct frame_tail { +	struct frame_tail   *fp; +	unsigned long	    sp; +	unsigned long	    lr; +} __attribute__((packed)); + +/* + * Get the return address for a single stackframe and return a pointer to the + * next frame tail. + */ +static struct frame_tail * +user_backtrace(struct frame_tail *tail, +	       struct perf_callchain_entry *entry) +{ +	struct frame_tail buftail; + +	/* Also check accessibility of one struct frame_tail beyond */ +	if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) +		return NULL; +	if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail))) +		return NULL; + +	callchain_store(entry, buftail.lr); + +	/* +	 * Frame pointers should strictly progress back up the stack +	 * (towards higher addresses). +	 */ +	if (tail >= buftail.fp) +		return NULL; + +	return buftail.fp - 1; +} + +static void +perf_callchain_user(struct pt_regs *regs, +		    struct perf_callchain_entry *entry) +{ +	struct frame_tail *tail; + +	callchain_store(entry, PERF_CONTEXT_USER); + +	if (!user_mode(regs)) +		regs = task_pt_regs(current); + +	tail = (struct frame_tail *)regs->ARM_fp - 1; + +	while (tail && !((unsigned long)tail & 0x3)) +		tail = user_backtrace(tail, entry); +} + +/* + * Gets called by walk_stackframe() for every stackframe. This will be called + * whist unwinding the stackframe and is like a subroutine return so we use + * the PC. + */ +static int +callchain_trace(struct stackframe *fr, +		void *data) +{ +	struct perf_callchain_entry *entry = data; +	callchain_store(entry, fr->pc); +	return 0; +} + +static void +perf_callchain_kernel(struct pt_regs *regs, +		      struct perf_callchain_entry *entry) +{ +	struct stackframe fr; + +	callchain_store(entry, PERF_CONTEXT_KERNEL); +	fr.fp = regs->ARM_fp; +	fr.sp = regs->ARM_sp; +	fr.lr = regs->ARM_lr; +	fr.pc = regs->ARM_pc; +	walk_stackframe(&fr, callchain_trace, entry); +} + +static void +perf_do_callchain(struct pt_regs *regs, +		  struct perf_callchain_entry *entry) +{ +	int is_user; + +	if (!regs) +		return; + +	is_user = user_mode(regs); + +	if (!current || !current->pid) +		return; + +	if (is_user && current->state != TASK_RUNNING) +		return; + +	if (!is_user) +		perf_callchain_kernel(regs, entry); + +	if (current->mm) +		perf_callchain_user(regs, entry); +} + +static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); + +struct perf_callchain_entry * +perf_callchain(struct pt_regs *regs) +{ +	struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry); + +	entry->nr = 0; +	perf_do_callchain(regs, entry); +	return entry; +} diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c new file mode 100644 index 00000000000..a124312e343 --- /dev/null +++ b/arch/arm/kernel/pmu.c @@ -0,0 +1,103 @@ +/* + *  linux/arch/arm/kernel/pmu.c + * + *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/cpumask.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include <asm/pmu.h> + +/* + * Define the IRQs for the system. We could use something like a platform + * device but that seems fairly heavyweight for this. Also, the performance + * counters can't be removed or hotplugged. + * + * Ordering is important: init_pmu() will use the ordering to set the affinity + * to the corresponding core. e.g. the first interrupt will go to cpu 0, the + * second goes to cpu 1 etc. + */ +static const int irqs[] = { +#if defined(CONFIG_ARCH_OMAP2) +	3, +#elif defined(CONFIG_ARCH_BCMRING) +	IRQ_PMUIRQ, +#elif defined(CONFIG_MACH_REALVIEW_EB) +	IRQ_EB11MP_PMU_CPU0, +	IRQ_EB11MP_PMU_CPU1, +	IRQ_EB11MP_PMU_CPU2, +	IRQ_EB11MP_PMU_CPU3, +#elif defined(CONFIG_ARCH_OMAP3) +	INT_34XX_BENCH_MPU_EMUL, +#elif defined(CONFIG_ARCH_IOP32X) +	IRQ_IOP32X_CORE_PMU, +#elif defined(CONFIG_ARCH_IOP33X) +	IRQ_IOP33X_CORE_PMU, +#elif defined(CONFIG_ARCH_PXA) +	IRQ_PMU, +#endif +}; + +static const struct pmu_irqs pmu_irqs = { +	.irqs	    = irqs, +	.num_irqs   = ARRAY_SIZE(irqs), +}; + +static volatile long pmu_lock; + +const struct pmu_irqs * +reserve_pmu(void) +{ +	return test_and_set_bit_lock(0, &pmu_lock) ? ERR_PTR(-EBUSY) : +		&pmu_irqs; +} +EXPORT_SYMBOL_GPL(reserve_pmu); + +int +release_pmu(const struct pmu_irqs *irqs) +{ +	if (WARN_ON(irqs != &pmu_irqs)) +		return -EINVAL; +	clear_bit_unlock(0, &pmu_lock); +	return 0; +} +EXPORT_SYMBOL_GPL(release_pmu); + +static int +set_irq_affinity(int irq, +		 unsigned int cpu) +{ +#ifdef CONFIG_SMP +	int err = irq_set_affinity(irq, cpumask_of(cpu)); +	if (err) +		pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", +			   irq, cpu); +	return err; +#else +	return 0; +#endif +} + +int +init_pmu(void) +{ +	int i, err = 0; + +	for (i = 0; i < pmu_irqs.num_irqs; ++i) { +		err = set_irq_affinity(pmu_irqs.irqs[i], i); +		if (err) +			break; +	} + +	return err; +} +EXPORT_SYMBOL_GPL(init_pmu); diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index a2ea3854cb3..08f899fb76a 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = {  	.fn		= break_trap,  }; +static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr) +{ +	unsigned int instr2; +	void __user *pc; + +	/* Check the second half of the instruction.  */ +	pc = (void __user *)(instruction_pointer(regs) + 2); + +	if (processor_mode(regs) == SVC_MODE) { +		instr2 = *(u16 *) pc; +	} else { +		get_user(instr2, (u16 __user *)pc); +	} + +	if (instr2 == 0xa000) { +		ptrace_break(current, regs); +		return 0; +	} else { +		return 1; +	} +} + +static struct undef_hook thumb2_break_hook = { +	.instr_mask	= 0xffff, +	.instr_val	= 0xf7f0, +	.cpsr_mask	= PSR_T_BIT, +	.cpsr_val	= PSR_T_BIT, +	.fn		= thumb2_break_trap, +}; +  static int __init ptrace_break_init(void)  {  	register_undef_hook(&arm_break_hook);  	register_undef_hook(&thumb_break_hook); +	register_undef_hook(&thumb2_break_hook);  	return 0;  } @@ -669,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)  	union vfp_state *vfp = &thread->vfpstate;  	struct user_vfp __user *ufp = data; -	vfp_sync_state(thread); +	vfp_sync_hwstate(thread);  	/* copy the floating point registers */  	if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, @@ -692,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)  	union vfp_state *vfp = &thread->vfpstate;  	struct user_vfp __user *ufp = data; -	vfp_sync_state(thread); +	vfp_sync_hwstate(thread);  	/* copy the floating point registers */  	if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, @@ -703,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)  	if (get_user(vfp->hard.fpscr, &ufp->fpscr))  		return -EFAULT; +	vfp_flush_hwstate(thread); +  	return 0;  }  #endif @@ -712,26 +745,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)  	int ret;  	switch (request) { -		/* -		 * read word at location "addr" in the child process. -		 */ -		case PTRACE_PEEKTEXT: -		case PTRACE_PEEKDATA: -			ret = generic_ptrace_peekdata(child, addr, data); -			break; -  		case PTRACE_PEEKUSR:  			ret = ptrace_read_user(child, addr, (unsigned long __user *)data);  			break; -		/* -		 * write the word at location addr. -		 */ -		case PTRACE_POKETEXT: -		case PTRACE_POKEDATA: -			ret = generic_ptrace_pokedata(child, addr, data); -			break; -  		case PTRACE_POKEUSR:  			ret = ptrace_write_user(child, addr, data);  			break; diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index c6c57b640b6..baf5959d639 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -24,6 +24,7 @@  #include <linux/interrupt.h>  #include <linux/smp.h>  #include <linux/fs.h> +#include <linux/proc_fs.h>  #include <asm/unified.h>  #include <asm/cpu.h> @@ -117,7 +118,7 @@ EXPORT_SYMBOL(elf_platform);  static const char *cpu_name;  static const char *machine_name; -static char __initdata command_line[COMMAND_LINE_SIZE]; +static char __initdata cmd_line[COMMAND_LINE_SIZE];  static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;  static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; @@ -417,10 +418,11 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)   * Pick out the memory size.  We look for mem=size@start,   * where start and size are "size[KkMm]"   */ -static void __init early_mem(char **p) +static int __init early_mem(char *p)  {  	static int usermem __initdata = 0;  	unsigned long size, start; +	char *endp;  	/*  	 * If the user specifies memory size, we @@ -433,52 +435,15 @@ static void __init early_mem(char **p)  	}  	start = PHYS_OFFSET; -	size  = memparse(*p, p); -	if (**p == '@') -		start = memparse(*p + 1, p); +	size  = memparse(p, &endp); +	if (*endp == '@') +		start = memparse(endp + 1, NULL);  	arm_add_memory(start, size); -} -__early_param("mem=", early_mem); - -/* - * Initial parsing of the command line. - */ -static void __init parse_cmdline(char **cmdline_p, char *from) -{ -	char c = ' ', *to = command_line; -	int len = 0; - -	for (;;) { -		if (c == ' ') { -			extern struct early_params __early_begin, __early_end; -			struct early_params *p; -			for (p = &__early_begin; p < &__early_end; p++) { -				int arglen = strlen(p->arg); - -				if (memcmp(from, p->arg, arglen) == 0) { -					if (to != command_line) -						to -= 1; -					from += arglen; -					p->fn(&from); - -					while (*from != ' ' && *from != '\0') -						from++; -					break; -				} -			} -		} -		c = *from++; -		if (!c) -			break; -		if (COMMAND_LINE_SIZE <= ++len) -			break; -		*to++ = c; -	} -	*to = '\0'; -	*cmdline_p = command_line; +	return 0;  } +early_param("mem", early_mem);  static void __init  setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) @@ -739,9 +704,15 @@ void __init setup_arch(char **cmdline_p)  	init_mm.end_data   = (unsigned long) _edata;  	init_mm.brk	   = (unsigned long) _end; -	memcpy(boot_command_line, from, COMMAND_LINE_SIZE); -	boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; -	parse_cmdline(cmdline_p, from); +	/* parse_early_param needs a boot_command_line */ +	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); + +	/* populate cmd_line too for later use, preserving boot_command_line */ +	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); +	*cmdline_p = cmd_line; + +	parse_early_param(); +  	paging_init(mdesc);  	request_standard_resources(&meminfo, mdesc); @@ -782,9 +753,21 @@ static int __init topology_init(void)  	return 0;  } -  subsys_initcall(topology_init); +#ifdef CONFIG_HAVE_PROC_CPU +static int __init proc_cpu_init(void) +{ +	struct proc_dir_entry *res; + +	res = proc_mkdir("cpu", NULL); +	if (!res) +		return -ENOMEM; +	return 0; +} +fs_initcall(proc_cpu_init); +#endif +  static const char *hwcap_str[] = {  	"swp",  	"half", diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index d38cdf2c827..28753805d2d 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -10,11 +10,6 @@   *   *  This file contains the ARM-specific time handling details:   *  reading the RTC at bootup, etc... - * - *  1994-07-02  Alan Modra - *              fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime - *  1998-12-20  Updated NTP code according to technical memorandum Jan '96 - *              "A Kernel Model for Precision Timekeeping" by Dave Mills   */  #include <linux/module.h>  #include <linux/kernel.h> @@ -77,11 +72,6 @@ unsigned long profile_pc(struct pt_regs *regs)  EXPORT_SYMBOL(profile_pc);  #endif -/* - * hook for setting the RTC's idea of the current time. - */ -int (*set_rtc)(void); -  #ifndef CONFIG_GENERIC_TIME  static unsigned long dummy_gettimeoffset(void)  { @@ -89,140 +79,6 @@ static unsigned long dummy_gettimeoffset(void)  }  #endif -static unsigned long next_rtc_update; - -/* - * If we have an externally synchronized linux clock, then update - * CMOS clock accordingly every ~11 minutes.  set_rtc() has to be - * called as close as possible to 500 ms before the new second - * starts. - */ -static inline void do_set_rtc(void) -{ -	if (!ntp_synced() || set_rtc == NULL) -		return; - -	if (next_rtc_update && -	    time_before((unsigned long)xtime.tv_sec, next_rtc_update)) -		return; - -	if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) && -	    xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1)) -		return; - -	if (set_rtc()) -		/* -		 * rtc update failed.  Try again in 60s -		 */ -		next_rtc_update = xtime.tv_sec + 60; -	else -		next_rtc_update = xtime.tv_sec + 660; -} - -#ifdef CONFIG_LEDS - -static void dummy_leds_event(led_event_t evt) -{ -} - -void (*leds_event)(led_event_t) = dummy_leds_event; - -struct leds_evt_name { -	const char	name[8]; -	int		on; -	int		off; -}; - -static const struct leds_evt_name evt_names[] = { -	{ "amber", led_amber_on, led_amber_off }, -	{ "blue",  led_blue_on,  led_blue_off  }, -	{ "green", led_green_on, led_green_off }, -	{ "red",   led_red_on,   led_red_off   }, -}; - -static ssize_t leds_store(struct sys_device *dev, -			struct sysdev_attribute *attr, -			const char *buf, size_t size) -{ -	int ret = -EINVAL, len = strcspn(buf, " "); - -	if (len > 0 && buf[len] == '\0') -		len--; - -	if (strncmp(buf, "claim", len) == 0) { -		leds_event(led_claim); -		ret = size; -	} else if (strncmp(buf, "release", len) == 0) { -		leds_event(led_release); -		ret = size; -	} else { -		int i; - -		for (i = 0; i < ARRAY_SIZE(evt_names); i++) { -			if (strlen(evt_names[i].name) != len || -			    strncmp(buf, evt_names[i].name, len) != 0) -				continue; -			if (strncmp(buf+len, " on", 3) == 0) { -				leds_event(evt_names[i].on); -				ret = size; -			} else if (strncmp(buf+len, " off", 4) == 0) { -				leds_event(evt_names[i].off); -				ret = size; -			} -			break; -		} -	} -	return ret; -} - -static SYSDEV_ATTR(event, 0200, NULL, leds_store); - -static int leds_suspend(struct sys_device *dev, pm_message_t state) -{ -	leds_event(led_stop); -	return 0; -} - -static int leds_resume(struct sys_device *dev) -{ -	leds_event(led_start); -	return 0; -} - -static int leds_shutdown(struct sys_device *dev) -{ -	leds_event(led_halted); -	return 0; -} - -static struct sysdev_class leds_sysclass = { -	.name		= "leds", -	.shutdown	= leds_shutdown, -	.suspend	= leds_suspend, -	.resume		= leds_resume, -}; - -static struct sys_device leds_device = { -	.id		= 0, -	.cls		= &leds_sysclass, -}; - -static int __init leds_init(void) -{ -	int ret; -	ret = sysdev_class_register(&leds_sysclass); -	if (ret == 0) -		ret = sysdev_register(&leds_device); -	if (ret == 0) -		ret = sysdev_create_file(&leds_device, &attr_event); -	return ret; -} - -device_initcall(leds_init); - -EXPORT_SYMBOL(leds_event); -#endif -  #ifdef CONFIG_LEDS_TIMER  static inline void do_leds(void)  { @@ -295,39 +151,6 @@ int do_settimeofday(struct timespec *tv)  EXPORT_SYMBOL(do_settimeofday);  #endif /* !CONFIG_GENERIC_TIME */ -/** - * save_time_delta - Save the offset between system time and RTC time - * @delta: pointer to timespec to store delta - * @rtc: pointer to timespec for current RTC time - * - * Return a delta between the system time and the RTC time, such - * that system time can be restored later with restore_time_delta() - */ -void save_time_delta(struct timespec *delta, struct timespec *rtc) -{ -	set_normalized_timespec(delta, -				xtime.tv_sec - rtc->tv_sec, -				xtime.tv_nsec - rtc->tv_nsec); -} -EXPORT_SYMBOL(save_time_delta); - -/** - * restore_time_delta - Restore the current system time - * @delta: delta returned by save_time_delta() - * @rtc: pointer to timespec for current RTC time - */ -void restore_time_delta(struct timespec *delta, struct timespec *rtc) -{ -	struct timespec ts; - -	set_normalized_timespec(&ts, -				delta->tv_sec + rtc->tv_sec, -				delta->tv_nsec + rtc->tv_nsec); - -	do_settimeofday(&ts); -} -EXPORT_SYMBOL(restore_time_delta); -  #ifndef CONFIG_GENERIC_CLOCKEVENTS  /*   * Kernel system timer support. @@ -336,7 +159,6 @@ void timer_tick(void)  {  	profile_tick(CPU_PROFILING);  	do_leds(); -	do_set_rtc();  	write_seqlock(&xtime_lock);  	do_timer(1);  	write_sequnlock(&xtime_lock); diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3f361a783f4..1621e5327b2 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -12,15 +12,17 @@   *  'linux/arch/arm/lib/traps.S'.  Mostly a debugging aid, but will probably   *  kill the offending process.   */ -#include <linux/module.h>  #include <linux/signal.h> -#include <linux/spinlock.h>  #include <linux/personality.h>  #include <linux/kallsyms.h> -#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/uaccess.h>  #include <linux/hardirq.h> +#include <linux/kdebug.h> +#include <linux/module.h> +#include <linux/kexec.h> +#include <linux/delay.h>  #include <linux/init.h> -#include <linux/uaccess.h>  #include <asm/atomic.h>  #include <asm/cacheflush.h> @@ -224,14 +226,21 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)  #define S_SMP ""  #endif -static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) +static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)  {  	struct task_struct *tsk = thread->task;  	static int die_counter; +	int ret;  	printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",  	       str, err, ++die_counter);  	sysfs_printk_last_file(); + +	/* trap and error numbers are mostly meaningless on ARM */ +	ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); +	if (ret == NOTIFY_STOP) +		return ret; +  	print_modules();  	__show_regs(regs);  	printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", @@ -243,6 +252,8 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p  		dump_backtrace(regs, tsk);  		dump_instr(KERN_EMERG, regs);  	} + +	return ret;  }  DEFINE_SPINLOCK(die_lock); @@ -250,16 +261,21 @@ DEFINE_SPINLOCK(die_lock);  /*   * This function is protected against re-entrancy.   */ -NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) +void die(const char *str, struct pt_regs *regs, int err)  {  	struct thread_info *thread = current_thread_info(); +	int ret;  	oops_enter();  	spin_lock_irq(&die_lock);  	console_verbose();  	bust_spinlocks(1); -	__die(str, err, thread, regs); +	ret = __die(str, err, thread, regs); + +	if (regs && kexec_should_crash(thread->task)) +		crash_kexec(regs); +  	bust_spinlocks(0);  	add_taint(TAINT_DIE);  	spin_unlock_irq(&die_lock); @@ -267,11 +283,10 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)  	if (in_interrupt())  		panic("Fatal exception in interrupt"); -  	if (panic_on_oops)  		panic("Fatal exception"); - -	do_exit(SIGSEGV); +	if (ret != NOTIFY_STOP) +		do_exit(SIGSEGV);  }  void arm_notify_die(const char *str, struct pt_regs *regs, diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 4957e13ef55..b16c07914b5 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -43,10 +43,6 @@ SECTIONS  		INIT_SETUP(16) -		__early_begin = .; -			*(.early_param.init) -		__early_end = .; -  		INIT_CALLS  		CON_INITCALL  		SECURITY_INITCALL diff --git a/arch/arm/mach-aaec2000/include/mach/debug-macro.S b/arch/arm/mach-aaec2000/include/mach/debug-macro.S index 0b6351d7c38..a9cac368bfe 100644 --- a/arch/arm/mach-aaec2000/include/mach/debug-macro.S +++ b/arch/arm/mach-aaec2000/include/mach/debug-macro.S @@ -10,7 +10,7 @@   */  #include "hardware.h" -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x80000000		@ physical diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 0b2ee953f16..2db43a5ddd9 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -89,6 +89,12 @@ config ARCH_AT91CAP9  	select GENERIC_CLOCKEVENTS  	select HAVE_FB_ATMEL +config ARCH_AT572D940HF +	bool "AT572D940HF" +	select CPU_ARM926T +	select GENERIC_TIME +	select GENERIC_CLOCKEVENTS +  config ARCH_AT91X40  	bool "AT91x40" @@ -390,6 +396,23 @@ endif  # ---------------------------------------------------------- +if ARCH_AT572D940HF + +comment "AT572D940HF Board Type" + +config MACH_AT572D940HFEB +	bool "AT572D940HF-EK" +	depends on ARCH_AT572D940HF +	select HAVE_AT91_DATAFLASH_CARD +	select HAVE_NAND_ATMEL_BUSWIDTH_16 +	help +	  Select this if you are using Atmel's AT572D940HF-EK evaluation kit. +	  <http://www.atmel.com/products/diopsis/default.asp> + +endif + +# ---------------------------------------------------------- +  if ARCH_AT91X40  comment "AT91X40 Board Type" diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 709fbad4a3e..027dd570dcc 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_AT91SAM9RL)	+= at91sam9rl.o at91sam926x_time.o at91sam9rl_devi  obj-$(CONFIG_ARCH_AT91SAM9G20)	+= at91sam9260.o at91sam926x_time.o at91sam9260_devices.o  sam9_smc.o   obj-$(CONFIG_ARCH_AT91SAM9G45)	+= at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o  obj-$(CONFIG_ARCH_AT91CAP9)	+= at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT572D940HF)  += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o  obj-$(CONFIG_ARCH_AT91X40)	+= at91x40.o at91x40_time.o  # AT91RM9200 board-specific support @@ -69,6 +70,9 @@ obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o  # AT91CAP9 board-specific support  obj-$(CONFIG_MACH_AT91CAP9ADK)	+= board-cap9adk.o +# AT572D940HF board-specific support +obj-$(CONFIG_MACH_AT572D940HFEB) += board-at572d940hf_ek.o +  # AT91X40 board-specific support  obj-$(CONFIG_MACH_AT91EB01)	+= board-eb01.o diff --git a/arch/arm/mach-at91/at572d940hf.c b/arch/arm/mach-at91/at572d940hf.c new file mode 100644 index 00000000000..a6b9c68c003 --- /dev/null +++ b/arch/arm/mach-at91/at572d940hf.c @@ -0,0 +1,377 @@ +/* + * arch/arm/mach-at91/at572d940hf.c + * + * Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2008 Atmel + * + * Copyright (C) 2005 SAN People + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include <linux/module.h> + +#include <asm/mach/irq.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <mach/at572d940hf.h> +#include <mach/at91_pmc.h> +#include <mach/at91_rstc.h> + +#include "generic.h" +#include "clock.h" + +static struct map_desc at572d940hf_io_desc[] __initdata = { +	{ +		.virtual	= AT91_VA_BASE_SYS, +		.pfn		= __phys_to_pfn(AT91_BASE_SYS), +		.length		= SZ_16K, +		.type		= MT_DEVICE, +	}, { +		.virtual	= AT91_IO_VIRT_BASE - AT572D940HF_SRAM_SIZE, +		.pfn		= __phys_to_pfn(AT572D940HF_SRAM_BASE), +		.length		= AT572D940HF_SRAM_SIZE, +		.type		= MT_DEVICE, +	}, +}; + +/* -------------------------------------------------------------------- + *  Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { +	.name		= "pioA_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_PIOA, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { +	.name		= "pioB_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_PIOB, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { +	.name		= "pioC_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_PIOC, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk macb_clk = { +	.name		= "macb_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_EMAC, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { +	.name		= "usart0_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_US0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { +	.name		= "usart1_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_US1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { +	.name		= "usart2_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_US2, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { +	.name		= "mci_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_MCI, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { +	.name		= "udc_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_UDP, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk twi0_clk = { +	.name		= "twi0_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_TWI0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { +	.name		= "spi0_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_SPI0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { +	.name		= "spi1_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_SPI1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc0_clk = { +	.name		= "ssc0_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_SSC0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc1_clk = { +	.name		= "ssc1_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_SSC1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc2_clk = { +	.name		= "ssc2_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_SSC2, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk tc0_clk = { +	.name		= "tc0_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_TC0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk tc1_clk = { +	.name		= "tc1_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_TC1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk tc2_clk = { +	.name		= "tc2_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_TC2, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { +	.name		= "ohci_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_UHP, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc3_clk = { +	.name		= "ssc3_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_SSC3, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk twi1_clk = { +	.name		= "twi1_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_TWI1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk can0_clk = { +	.name		= "can0_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_CAN0, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk can1_clk = { +	.name		= "can1_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_CAN1, +	.type		= CLK_TYPE_PERIPHERAL, +}; +static struct clk mAgicV_clk = { +	.name		= "mAgicV_clk", +	.pmc_mask	= 1 << AT572D940HF_ID_MSIRQ0, +	.type		= CLK_TYPE_PERIPHERAL, +}; + + +static struct clk *periph_clocks[] __initdata = { +	&pioA_clk, +	&pioB_clk, +	&pioC_clk, +	&macb_clk, +	&usart0_clk, +	&usart1_clk, +	&usart2_clk, +	&mmc_clk, +	&udc_clk, +	&twi0_clk, +	&spi0_clk, +	&spi1_clk, +	&ssc0_clk, +	&ssc1_clk, +	&ssc2_clk, +	&tc0_clk, +	&tc1_clk, +	&tc2_clk, +	&ohci_clk, +	&ssc3_clk, +	&twi1_clk, +	&can0_clk, +	&can1_clk, +	&mAgicV_clk, +	/* irq0 .. irq2 */ +}; + +/* + * The five programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { +	.name		= "pck0", +	.pmc_mask	= AT91_PMC_PCK0, +	.type		= CLK_TYPE_PROGRAMMABLE, +	.id		= 0, +}; +static struct clk pck1 = { +	.name		= "pck1", +	.pmc_mask	= AT91_PMC_PCK1, +	.type		= CLK_TYPE_PROGRAMMABLE, +	.id		= 1, +}; +static struct clk pck2 = { +	.name		= "pck2", +	.pmc_mask	= AT91_PMC_PCK2, +	.type		= CLK_TYPE_PROGRAMMABLE, +	.id		= 2, +}; +static struct clk pck3 = { +	.name		= "pck3", +	.pmc_mask	= AT91_PMC_PCK3, +	.type		= CLK_TYPE_PROGRAMMABLE, +	.id		= 3, +}; + +static struct clk mAgicV_mem_clk = { +	.name		= "mAgicV_mem_clk", +	.pmc_mask	= AT91_PMC_PCK4, +	.type		= CLK_TYPE_PROGRAMMABLE, +	.id		= 4, +}; + +/* HClocks */ +static struct clk hck0 = { +	.name		= "hck0", +	.pmc_mask	= AT91_PMC_HCK0, +	.type		= CLK_TYPE_SYSTEM, +	.id		= 0, +}; +static struct clk hck1 = { +	.name		= "hck1", +	.pmc_mask	= AT91_PMC_HCK1, +	.type		= CLK_TYPE_SYSTEM, +	.id		= 1, +}; + +static void __init at572d940hf_register_clocks(void) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) +		clk_register(periph_clocks[i]); + +	clk_register(&pck0); +	clk_register(&pck1); +	clk_register(&pck2); +	clk_register(&pck3); +	clk_register(&mAgicV_mem_clk); + +	clk_register(&hck0); +	clk_register(&hck1); +} + +/* -------------------------------------------------------------------- + *  GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at572d940hf_gpio[] = { +	{ +		.id		= AT572D940HF_ID_PIOA, +		.offset		= AT91_PIOA, +		.clock		= &pioA_clk, +	}, { +		.id		= AT572D940HF_ID_PIOB, +		.offset		= AT91_PIOB, +		.clock		= &pioB_clk, +	}, { +		.id		= AT572D940HF_ID_PIOC, +		.offset		= AT91_PIOC, +		.clock		= &pioC_clk, +	} +}; + +static void at572d940hf_reset(void) +{ +	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); +} + + +/* -------------------------------------------------------------------- + *  AT572D940HF processor initialization + * -------------------------------------------------------------------- */ + +void __init at572d940hf_initialize(unsigned long main_clock) +{ +	/* Map peripherals */ +	iotable_init(at572d940hf_io_desc, ARRAY_SIZE(at572d940hf_io_desc)); + +	at91_arch_reset = at572d940hf_reset; +	at91_extern_irq = (1 << AT572D940HF_ID_IRQ0) | (1 << AT572D940HF_ID_IRQ1) +			| (1 << AT572D940HF_ID_IRQ2); + +	/* Init clock subsystem */ +	at91_clock_init(main_clock); + +	/* Register the processor-specific clocks */ +	at572d940hf_register_clocks(); + +	/* Register GPIO subsystem */ +	at91_gpio_init(at572d940hf_gpio, 3); +} + +/* -------------------------------------------------------------------- + *  Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at572d940hf_default_irq_priority[NR_AIC_IRQS] __initdata = { +	7,	/* Advanced Interrupt Controller */ +	7,	/* System Peripherals */ +	0,	/* Parallel IO Controller A */ +	0,	/* Parallel IO Controller B */ +	0,	/* Parallel IO Controller C */ +	3,	/* Ethernet */ +	6,	/* USART 0 */ +	6,	/* USART 1 */ +	6,	/* USART 2 */ +	0,	/* Multimedia Card Interface */ +	4,	/* USB Device Port */ +	0,	/* Two-Wire Interface 0 */ +	6,	/* Serial Peripheral Interface 0 */ +	6,	/* Serial Peripheral Interface 1 */ +	5,	/* Serial Synchronous Controller 0 */ +	5,	/* Serial Synchronous Controller 1 */ +	5,	/* Serial Synchronous Controller 2 */ +	0,	/* Timer Counter 0 */ +	0,	/* Timer Counter 1 */ +	0,	/* Timer Counter 2 */ +	3,	/* USB Host port */ +	3,	/* Serial Synchronous Controller 3 */ +	0,	/* Two-Wire Interface 1 */ +	0,	/* CAN Controller 0 */ +	0,	/* CAN Controller 1 */ +	0,	/* mAgicV HALT line */ +	0,	/* mAgicV SIRQ0 line */ +	0,	/* mAgicV exception line */ +	0,	/* mAgicV end of DMA line */ +	0,	/* Advanced Interrupt Controller */ +	0,	/* Advanced Interrupt Controller */ +	0,	/* Advanced Interrupt Controller */ +}; + +void __init at572d940hf_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ +	if (!priority) +		priority = at572d940hf_default_irq_priority; + +	/* Initialize the AIC interrupt controller */ +	at91_aic_init(priority); + +	/* Enable GPIO interrupts */ +	at91_gpio_irq_setup(); +} + diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c new file mode 100644 index 00000000000..0fc20a24078 --- /dev/null +++ b/arch/arm/mach-at91/at572d940hf_devices.c @@ -0,0 +1,970 @@ +/* + * arch/arm/mach-at91/at572d940hf_devices.c + * + * Copyright (C) 2008 Atmel Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> + * Copyright (C) 2005 David Brownell + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> + +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at572d940hf.h> +#include <mach/at572d940hf_matrix.h> +#include <mach/at91sam9_smc.h> + +#include "generic.h" +#include "sam9_smc.h" + + +/* -------------------------------------------------------------------- + *  USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = DMA_BIT_MASK(32); +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { +	[0] = { +		.start	= AT572D940HF_UHP_BASE, +		.end	= AT572D940HF_UHP_BASE + SZ_1M - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_UHP, +		.end	= AT572D940HF_ID_UHP, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_usbh_device = { +	.name		= "at91_ohci", +	.id		= -1, +	.dev		= { +				.dma_mask		= &ohci_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +				.platform_data		= &usbh_data, +	}, +	.resource	= usbh_resources, +	.num_resources	= ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ +	if (!data) +		return; + +	usbh_data = *data; +	platform_device_register(&at572d940hf_usbh_device); + +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + *  USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_UDP, +		.end	= AT572D940HF_BASE_UDP + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_UDP, +		.end	= AT572D940HF_ID_UDP, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_udc_device = { +	.name		= "at91_udc", +	.id		= -1, +	.dev		= { +				.platform_data		= &udc_data, +	}, +	.resource	= udc_resources, +	.num_resources	= ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ +	if (!data) +		return; + +	if (data->vbus_pin) { +		at91_set_gpio_input(data->vbus_pin, 0); +		at91_set_deglitch(data->vbus_pin, 1); +	} + +	/* Pullup pin is handled internally */ + +	udc_data = *data; +	platform_device_register(&at572d940hf_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + *  Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) +static u64 eth_dmamask = DMA_BIT_MASK(32); +static struct at91_eth_data eth_data; + +static struct resource eth_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_EMAC, +		.end	= AT572D940HF_BASE_EMAC + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_EMAC, +		.end	= AT572D940HF_ID_EMAC, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_eth_device = { +	.name		= "macb", +	.id		= -1, +	.dev		= { +			.dma_mask		= ð_dmamask, +			.coherent_dma_mask	= DMA_BIT_MASK(32), +			.platform_data		= ð_data, +	}, +	.resource	= eth_resources, +	.num_resources	= ARRAY_SIZE(eth_resources), +}; + +void __init at91_add_device_eth(struct at91_eth_data *data) +{ +	if (!data) +		return; + +	if (data->phy_irq_pin) { +		at91_set_gpio_input(data->phy_irq_pin, 0); +		at91_set_deglitch(data->phy_irq_pin, 1); +	} + +	/* Only RMII is supported */ +	data->is_rmii = 1; + +	/* Pins used for RMII */ +	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ETXCK_EREFCK */ +	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ERXDV */ +	at91_set_A_periph(AT91_PIN_PA18, 0);	/* ERX0 */ +	at91_set_A_periph(AT91_PIN_PA19, 0);	/* ERX1 */ +	at91_set_A_periph(AT91_PIN_PA20, 0);	/* ERXER */ +	at91_set_A_periph(AT91_PIN_PA23, 0);	/* ETXEN */ +	at91_set_A_periph(AT91_PIN_PA21, 0);	/* ETX0 */ +	at91_set_A_periph(AT91_PIN_PA22, 0);	/* ETX1 */ +	at91_set_A_periph(AT91_PIN_PA13, 0);	/* EMDIO */ +	at91_set_A_periph(AT91_PIN_PA14, 0);	/* EMDC */ + +	eth_data = *data; +	platform_device_register(&at572d940hf_eth_device); +} +#else +void __init at91_add_device_eth(struct at91_eth_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + *  MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = DMA_BIT_MASK(32); +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_MCI, +		.end	= AT572D940HF_BASE_MCI + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_MCI, +		.end	= AT572D940HF_ID_MCI, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_mmc_device = { +	.name		= "at91_mci", +	.id		= -1, +	.dev		= { +				.dma_mask		= &mmc_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +				.platform_data		= &mmc_data, +	}, +	.resource	= mmc_resources, +	.num_resources	= ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) +{ +	if (!data) +		return; + +	/* input/irq */ +	if (data->det_pin) { +		at91_set_gpio_input(data->det_pin, 1); +		at91_set_deglitch(data->det_pin, 1); +	} +	if (data->wp_pin) +		at91_set_gpio_input(data->wp_pin, 1); +	if (data->vcc_pin) +		at91_set_gpio_output(data->vcc_pin, 0); + +	/* CLK */ +	at91_set_A_periph(AT91_PIN_PC22, 0); + +	/* CMD */ +	at91_set_A_periph(AT91_PIN_PC23, 1); + +	/* DAT0, maybe DAT1..DAT3 */ +	at91_set_A_periph(AT91_PIN_PC24, 1); +	if (data->wire4) { +		at91_set_A_periph(AT91_PIN_PC25, 1); +		at91_set_A_periph(AT91_PIN_PC26, 1); +		at91_set_A_periph(AT91_PIN_PC27, 1); +	} + +	mmc_data = *data; +	platform_device_register(&at572d940hf_mmc_device); +} +#else +void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + *  NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE) +static struct atmel_nand_data nand_data; + +#define NAND_BASE	AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { +	{ +		.start	= NAND_BASE, +		.end	= NAND_BASE + SZ_256M - 1, +		.flags	= IORESOURCE_MEM, +	} +}; + +static struct platform_device at572d940hf_nand_device = { +	.name		= "atmel_nand", +	.id		= -1, +	.dev		= { +				.platform_data	= &nand_data, +	}, +	.resource	= nand_resources, +	.num_resources	= ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct atmel_nand_data *data) +{ +	unsigned long csa; + +	if (!data) +		return; + +	csa = at91_sys_read(AT91_MATRIX_EBICSA); +	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA); + +	/* enable pin */ +	if (data->enable_pin) +		at91_set_gpio_output(data->enable_pin, 1); + +	/* ready/busy pin */ +	if (data->rdy_pin) +		at91_set_gpio_input(data->rdy_pin, 1); + +	/* card detect pin */ +	if (data->det_pin) +		at91_set_gpio_input(data->det_pin, 1); + +	at91_set_A_periph(AT91_PIN_PB28, 0);		/* A[22] */ +	at91_set_B_periph(AT91_PIN_PA28, 0);		/* NANDOE */ +	at91_set_B_periph(AT91_PIN_PA29, 0);		/* NANDWE */ + +	nand_data = *data; +	platform_device_register(&at572d940hf_nand_device); +} + +#else +void __init at91_add_device_nand(struct atmel_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + *  TWI (i2c) + * -------------------------------------------------------------------- */ + +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ + +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { +	.sda_pin		= AT91_PIN_PC7, +	.sda_is_open_drain	= 1, +	.scl_pin		= AT91_PIN_PC8, +	.scl_is_open_drain	= 1, +	.udelay			= 2,		/* ~100 kHz */ +}; + +static struct platform_device at572d940hf_twi_device { +	.name			= "i2c-gpio", +	.id			= -1, +	.dev.platform_data	= &pdata, +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ +	at91_set_GPIO_periph(AT91_PIN_PC7, 1);		/* TWD (SDA) */ +	at91_set_multi_drive(AT91_PIN_PC7, 1); + +	at91_set_GPIO_periph(AT91_PIN_PA8, 1);		/* TWCK (SCL) */ +	at91_set_multi_drive(AT91_PIN_PC8, 1); + +	i2c_register_board_info(0, devices, nr_devices); +	platform_device_register(&at572d940hf_twi_device); +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi0_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_TWI0, +		.end	= AT572D940HF_BASE_TWI0 + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_TWI0, +		.end	= AT572D940HF_ID_TWI0, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_twi0_device = { +	.name		= "at91_i2c", +	.id		= 0, +	.resource	= twi0_resources, +	.num_resources	= ARRAY_SIZE(twi0_resources), +}; + +static struct resource twi1_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_TWI1, +		.end	= AT572D940HF_BASE_TWI1 + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_TWI1, +		.end	= AT572D940HF_ID_TWI1, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_twi1_device = { +	.name		= "at91_i2c", +	.id		= 1, +	.resource	= twi1_resources, +	.num_resources	= ARRAY_SIZE(twi1_resources), +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ +	/* pins used for TWI0 interface */ +	at91_set_A_periph(AT91_PIN_PC7, 0);		/* TWD */ +	at91_set_multi_drive(AT91_PIN_PC7, 1); + +	at91_set_A_periph(AT91_PIN_PC8, 0);		/* TWCK */ +	at91_set_multi_drive(AT91_PIN_PC8, 1); + +	/* pins used for TWI1 interface */ +	at91_set_A_periph(AT91_PIN_PC20, 0);		/* TWD */ +	at91_set_multi_drive(AT91_PIN_PC20, 1); + +	at91_set_A_periph(AT91_PIN_PC21, 0);		/* TWCK */ +	at91_set_multi_drive(AT91_PIN_PC21, 1); + +	i2c_register_board_info(0, devices, nr_devices); +	platform_device_register(&at572d940hf_twi0_device); +	platform_device_register(&at572d940hf_twi1_device); +} +#else +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + *  SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = DMA_BIT_MASK(32); + +static struct resource spi0_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_SPI0, +		.end	= AT572D940HF_BASE_SPI0 + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_SPI0, +		.end	= AT572D940HF_ID_SPI0, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_spi0_device = { +	.name		= "atmel_spi", +	.id		= 0, +	.dev		= { +				.dma_mask		= &spi_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +	}, +	.resource	= spi0_resources, +	.num_resources	= ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +static struct resource spi1_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_SPI1, +		.end	= AT572D940HF_BASE_SPI1 + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_SPI1, +		.end	= AT572D940HF_ID_SPI1, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_spi1_device = { +	.name		= "atmel_spi", +	.id		= 1, +	.dev		= { +				.dma_mask		= &spi_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +	}, +	.resource	= spi1_resources, +	.num_resources	= ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PC3, AT91_PIN_PC4, AT91_PIN_PC5, AT91_PIN_PC6 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ +	int i; +	unsigned long cs_pin; +	short enable_spi0 = 0; +	short enable_spi1 = 0; + +	/* Choose SPI chip-selects */ +	for (i = 0; i < nr_devices; i++) { +		if (devices[i].controller_data) +			cs_pin = (unsigned long) devices[i].controller_data; +		else if (devices[i].bus_num == 0) +			cs_pin = spi0_standard_cs[devices[i].chip_select]; +		else +			cs_pin = spi1_standard_cs[devices[i].chip_select]; + +		if (devices[i].bus_num == 0) +			enable_spi0 = 1; +		else +			enable_spi1 = 1; + +		/* enable chip-select pin */ +		at91_set_gpio_output(cs_pin, 1); + +		/* pass chip-select pin to driver */ +		devices[i].controller_data = (void *) cs_pin; +	} + +	spi_register_board_info(devices, nr_devices); + +	/* Configure SPI bus(es) */ +	if (enable_spi0) { +		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */ +		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */ +		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI0_SPCK */ + +		at91_clock_associate("spi0_clk", &at572d940hf_spi0_device.dev, "spi_clk"); +		platform_device_register(&at572d940hf_spi0_device); +	} +	if (enable_spi1) { +		at91_set_A_periph(AT91_PIN_PC0, 0);	/* SPI1_MISO */ +		at91_set_A_periph(AT91_PIN_PC1, 0);	/* SPI1_MOSI */ +		at91_set_A_periph(AT91_PIN_PC2, 0);	/* SPI1_SPCK */ + +		at91_clock_associate("spi1_clk", &at572d940hf_spi1_device.dev, "spi_clk"); +		platform_device_register(&at572d940hf_spi1_device); +	} +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + *  Timer/Counter blocks + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_ATMEL_TCLIB + +static struct resource tcb_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_TCB, +		.end	= AT572D940HF_BASE_TCB + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_TC0, +		.end	= AT572D940HF_ID_TC0, +		.flags	= IORESOURCE_IRQ, +	}, +	[2] = { +		.start	= AT572D940HF_ID_TC1, +		.end	= AT572D940HF_ID_TC1, +		.flags	= IORESOURCE_IRQ, +	}, +	[3] = { +		.start	= AT572D940HF_ID_TC2, +		.end	= AT572D940HF_ID_TC2, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct platform_device at572d940hf_tcb_device = { +	.name		= "atmel_tcb", +	.id		= 0, +	.resource	= tcb_resources, +	.num_resources	= ARRAY_SIZE(tcb_resources), +}; + +static void __init at91_add_device_tc(void) +{ +	/* this chip has a separate clock and irq for each TC channel */ +	at91_clock_associate("tc0_clk", &at572d940hf_tcb_device.dev, "t0_clk"); +	at91_clock_associate("tc1_clk", &at572d940hf_tcb_device.dev, "t1_clk"); +	at91_clock_associate("tc2_clk", &at572d940hf_tcb_device.dev, "t2_clk"); +	platform_device_register(&at572d940hf_tcb_device); +} +#else +static void __init at91_add_device_tc(void) { } +#endif + + +/* -------------------------------------------------------------------- + *  RTT + * -------------------------------------------------------------------- */ + +static struct resource rtt_resources[] = { +	{ +		.start	= AT91_BASE_SYS + AT91_RTT, +		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1, +		.flags	= IORESOURCE_MEM, +	} +}; + +static struct platform_device at572d940hf_rtt_device = { +	.name		= "at91_rtt", +	.id		= 0, +	.resource	= rtt_resources, +	.num_resources	= ARRAY_SIZE(rtt_resources), +}; + +static void __init at91_add_device_rtt(void) +{ +	platform_device_register(&at572d940hf_rtt_device); +} + + +/* -------------------------------------------------------------------- + *  Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) +static struct platform_device at572d940hf_wdt_device = { +	.name		= "at91_wdt", +	.id		= -1, +	.num_resources	= 0, +}; + +static void __init at91_add_device_watchdog(void) +{ +	platform_device_register(&at572d940hf_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} +#endif + + +/* -------------------------------------------------------------------- + *  UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { +	[0] = { +		.start	= AT91_VA_BASE_SYS + AT91_DBGU, +		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT91_ID_SYS, +		.end	= AT91_ID_SYS, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct atmel_uart_data dbgu_data = { +	.use_dma_tx	= 0, +	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */ +	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static u64 dbgu_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_dbgu_device = { +	.name		= "atmel_usart", +	.id		= 0, +	.dev		= { +				.dma_mask		= &dbgu_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +				.platform_data		= &dbgu_data, +	}, +	.resource	= dbgu_resources, +	.num_resources	= ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ +	at91_set_A_periph(AT91_PIN_PC31, 1);		/* DTXD */ +	at91_set_A_periph(AT91_PIN_PC30, 0);		/* DRXD */ +} + +static struct resource uart0_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_US0, +		.end	= AT572D940HF_BASE_US0 + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_US0, +		.end	= AT572D940HF_ID_US0, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct atmel_uart_data uart0_data = { +	.use_dma_tx	= 1, +	.use_dma_rx	= 1, +}; + +static u64 uart0_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_uart0_device = { +	.name		= "atmel_usart", +	.id		= 1, +	.dev		= { +				.dma_mask		= &uart0_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +				.platform_data		= &uart0_data, +	}, +	.resource	= uart0_resources, +	.num_resources	= ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(unsigned pins) +{ +	at91_set_A_periph(AT91_PIN_PA8, 1);		/* TXD0 */ +	at91_set_A_periph(AT91_PIN_PA7, 0);		/* RXD0 */ + +	if (pins & ATMEL_UART_RTS) +		at91_set_A_periph(AT91_PIN_PA10, 0);	/* RTS0 */ +	if (pins & ATMEL_UART_CTS) +		at91_set_A_periph(AT91_PIN_PA9, 0);	/* CTS0 */ +} + +static struct resource uart1_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_US1, +		.end	= AT572D940HF_BASE_US1 + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_US1, +		.end	= AT572D940HF_ID_US1, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct atmel_uart_data uart1_data = { +	.use_dma_tx	= 1, +	.use_dma_rx	= 1, +}; + +static u64 uart1_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_uart1_device = { +	.name		= "atmel_usart", +	.id		= 2, +	.dev		= { +				.dma_mask		= &uart1_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +				.platform_data		= &uart1_data, +	}, +	.resource	= uart1_resources, +	.num_resources	= ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(unsigned pins) +{ +	at91_set_A_periph(AT91_PIN_PC10, 1);		/* TXD1 */ +	at91_set_A_periph(AT91_PIN_PC9 , 0);		/* RXD1 */ + +	if (pins & ATMEL_UART_RTS) +		at91_set_A_periph(AT91_PIN_PC12, 0);	/* RTS1 */ +	if (pins & ATMEL_UART_CTS) +		at91_set_A_periph(AT91_PIN_PC11, 0);	/* CTS1 */ +} + +static struct resource uart2_resources[] = { +	[0] = { +		.start	= AT572D940HF_BASE_US2, +		.end	= AT572D940HF_BASE_US2 + SZ_16K - 1, +		.flags	= IORESOURCE_MEM, +	}, +	[1] = { +		.start	= AT572D940HF_ID_US2, +		.end	= AT572D940HF_ID_US2, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct atmel_uart_data uart2_data = { +	.use_dma_tx	= 1, +	.use_dma_rx	= 1, +}; + +static u64 uart2_dmamask = DMA_BIT_MASK(32); + +static struct platform_device at572d940hf_uart2_device = { +	.name		= "atmel_usart", +	.id		= 3, +	.dev		= { +				.dma_mask		= &uart2_dmamask, +				.coherent_dma_mask	= DMA_BIT_MASK(32), +				.platform_data		= &uart2_data, +	}, +	.resource	= uart2_resources, +	.num_resources	= ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(unsigned pins) +{ +	at91_set_A_periph(AT91_PIN_PC15, 1);		/* TXD2 */ +	at91_set_A_periph(AT91_PIN_PC14, 0);		/* RXD2 */ + +	if (pins & ATMEL_UART_RTS) +		at91_set_A_periph(AT91_PIN_PC17, 0);	/* RTS2 */ +	if (pins & ATMEL_UART_CTS) +		at91_set_A_periph(AT91_PIN_PC16, 0);	/* CTS2 */ +} + +static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */ +struct platform_device *atmel_default_console_device;	/* the serial console device */ + +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) +{ +	struct platform_device *pdev; + +	switch (id) { +		case 0:		/* DBGU */ +			pdev = &at572d940hf_dbgu_device; +			configure_dbgu_pins(); +			at91_clock_associate("mck", &pdev->dev, "usart"); +			break; +		case AT572D940HF_ID_US0: +			pdev = &at572d940hf_uart0_device; +			configure_usart0_pins(pins); +			at91_clock_associate("usart0_clk", &pdev->dev, "usart"); +			break; +		case AT572D940HF_ID_US1: +			pdev = &at572d940hf_uart1_device; +			configure_usart1_pins(pins); +			at91_clock_associate("usart1_clk", &pdev->dev, "usart"); +			break; +		case AT572D940HF_ID_US2: +			pdev = &at572d940hf_uart2_device; +			configure_usart2_pins(pins); +			at91_clock_associate("usart2_clk", &pdev->dev, "usart"); +			break; +		default: +			return; +	} +	pdev->id = portnr;		/* update to mapped ID */ + +	if (portnr < ATMEL_MAX_UART) +		at91_uarts[portnr] = pdev; +} + +void __init at91_set_serial_console(unsigned portnr) +{ +	if (portnr < ATMEL_MAX_UART) +		atmel_default_console_device = at91_uarts[portnr]; +} + +void __init at91_add_device_serial(void) +{ +	int i; + +	for (i = 0; i < ATMEL_MAX_UART; i++) { +		if (at91_uarts[i]) +			platform_device_register(at91_uarts[i]); +	} + +	if (!atmel_default_console_device) +		printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +#else +void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {} +void __init at91_set_serial_console(unsigned portnr) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- + *  mAgic + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_MAGICV +static struct resource mAgic_resources[] = { +	{ +		.start = AT91_MAGIC_PM_BASE, +		.end   = AT91_MAGIC_PM_BASE + AT91_MAGIC_PM_SIZE - 1, +		.flags = IORESOURCE_MEM, +	}, +	{ +		.start = AT91_MAGIC_DM_I_BASE, +		.end   = AT91_MAGIC_DM_I_BASE + AT91_MAGIC_DM_I_SIZE - 1, +		.flags = IORESOURCE_MEM, +	}, +	{ +		.start = AT91_MAGIC_DM_F_BASE, +		.end   = AT91_MAGIC_DM_F_BASE + AT91_MAGIC_DM_F_SIZE - 1, +		.flags = IORESOURCE_MEM, +	}, +	{ +		.start = AT91_MAGIC_DM_DB_BASE, +		.end   = AT91_MAGIC_DM_DB_BASE + AT91_MAGIC_DM_DB_SIZE - 1, +		.flags = IORESOURCE_MEM, +	}, +	{ +		.start = AT91_MAGIC_REGS_BASE, +		.end   = AT91_MAGIC_REGS_BASE + AT91_MAGIC_REGS_SIZE - 1, +		.flags = IORESOURCE_MEM, +	}, +	{ +		.start = AT91_MAGIC_EXTPAGE_BASE, +		.end   = AT91_MAGIC_EXTPAGE_BASE + AT91_MAGIC_EXTPAGE_SIZE - 1, +		.flags = IORESOURCE_MEM, +	}, +	{ +		.start  = AT572D940HF_ID_MSIRQ0, +		.end    = AT572D940HF_ID_MSIRQ0, +		.flags  = IORESOURCE_IRQ, +	}, +	{ +		.start  = AT572D940HF_ID_MHALT, +		.end    = AT572D940HF_ID_MHALT, +		.flags  = IORESOURCE_IRQ, +	}, +	{ +		.start  = AT572D940HF_ID_MEXC, +		.end    = AT572D940HF_ID_MEXC, +		.flags  = IORESOURCE_IRQ, +	}, +	{ +		.start  = AT572D940HF_ID_MEDMA, +		.end    = AT572D940HF_ID_MEDMA, +		.flags  = IORESOURCE_IRQ, +	}, +}; + +static struct platform_device mAgic_device = { +	.name           = "mAgic", +	.id             = -1, +	.num_resources  = ARRAY_SIZE(mAgic_resources), +	.resource       = mAgic_resources, +}; + +void __init at91_add_device_mAgic(void) +{ +	platform_device_register(&mAgic_device); +} +#else +void __init at91_add_device_mAgic(void) {} +#endif + + +/* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ +	at91_add_device_rtt(); +	at91_add_device_watchdog(); +	at91_add_device_tc(); +	return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c new file mode 100644 index 00000000000..5daff277f53 --- /dev/null +++ b/arch/arm/mach-at91/board-at572d940hf_ek.c @@ -0,0 +1,328 @@ +/* + * linux/arch/arm/mach-at91/board-at572d940hf_ek.c + * + * Copyright (C) 2008 Atmel Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2005 SAN People + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/spi/ds1305.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> + +#include <mach/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/board.h> +#include <mach/gpio.h> +#include <mach/at91sam9_smc.h> + +#include "sam9_smc.h" +#include "generic.h" + + +static void __init eb_map_io(void) +{ +	/* Initialize processor: 12.500 MHz crystal */ +	at572d940hf_initialize(12000000); + +	/* DBGU on ttyS0. (Rx & Tx only) */ +	at91_register_uart(0, 0, 0); + +	/* USART0 on ttyS1. (Rx & Tx only) */ +	at91_register_uart(AT572D940HF_ID_US0, 1, 0); + +	/* USART1 on ttyS2. (Rx & Tx only) */ +	at91_register_uart(AT572D940HF_ID_US1, 2, 0); + +	/* USART2 on ttyS3. (Tx & Rx only */ +	at91_register_uart(AT572D940HF_ID_US2, 3, 0); + +	/* set serial console to ttyS0 (ie, DBGU) */ +	at91_set_serial_console(0); +} + +static void __init eb_init_irq(void) +{ +	at572d940hf_init_interrupts(NULL); +} + + +/* + * USB Host Port + */ +static struct at91_usbh_data __initdata eb_usbh_data = { +	.ports		= 2, +}; + + +/* + * USB Device Port + */ +static struct at91_udc_data __initdata eb_udc_data = { +	.vbus_pin	= 0,		/* no VBUS detection,UDC always on */ +	.pullup_pin	= 0,		/* pull-up driven by UDC */ +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata eb_mmc_data = { +	.wire4		= 1, +/*	.det_pin	= ... not connected */ +/*	.wp_pin		= ... not connected */ +/*	.vcc_pin	= ... not connected */ +}; + + +/* + * MACB Ethernet device + */ +static struct at91_eth_data __initdata eb_eth_data = { +	.phy_irq_pin	= AT91_PIN_PB25, +	.is_rmii	= 1, +}; + +/* + * NOR flash + */ + +static struct mtd_partition eb_nor_partitions[] = { +	{ +		.name		= "Raw Environment", +		.offset		= 0, +		.size		= SZ_4M, +		.mask_flags	= 0, +	}, +	{ +		.name		= "OS FS", +		.offset		= MTDPART_OFS_APPEND, +		.size		= 3 * SZ_1M, +		.mask_flags	= 0, +	}, +	{ +		.name		= "APP FS", +		.offset		= MTDPART_OFS_APPEND, +		.size		= MTDPART_SIZ_FULL, +		.mask_flags	= 0, +	}, +}; + +static void nor_flash_set_vpp(struct map_info* mi, int i) { +}; + +static struct physmap_flash_data nor_flash_data = { +	.width		= 4, +	.parts		= eb_nor_partitions, +	.nr_parts	= ARRAY_SIZE(eb_nor_partitions), +	.set_vpp	= nor_flash_set_vpp, +}; + +static struct resource nor_flash_resources[] = { +	{ +		.start	= AT91_CHIPSELECT_0, +		.end	= AT91_CHIPSELECT_0 + SZ_16M - 1, +		.flags	= IORESOURCE_MEM, +	}, +}; + +static struct platform_device nor_flash = { +	.name		= "physmap-flash", +	.id		= 0, +	.dev		= { +				.platform_data = &nor_flash_data, +			}, +	.resource	= nor_flash_resources, +	.num_resources	= ARRAY_SIZE(nor_flash_resources), +}; + +static struct sam9_smc_config __initdata eb_nor_smc_config = { +	.ncs_read_setup		= 1, +	.nrd_setup		= 1, +	.ncs_write_setup	= 1, +	.nwe_setup		= 1, + +	.ncs_read_pulse		= 7, +	.nrd_pulse		= 7, +	.ncs_write_pulse	= 7, +	.nwe_pulse		= 7, + +	.read_cycle		= 9, +	.write_cycle		= 9, + +	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_32, +	.tdf_cycles		= 1, +}; + +static void __init eb_add_device_nor(void) +{ +	/* configure chip-select 0 (NOR) */ +	sam9_smc_configure(0, &eb_nor_smc_config); +	platform_device_register(&nor_flash); +} + +/* + * NAND flash + */ +static struct mtd_partition __initdata eb_nand_partition[] = { +	{ +		.name	= "Partition 1", +		.offset	= 0, +		.size	= SZ_16M, +	}, +	{ +		.name	= "Partition 2", +		.offset = MTDPART_OFS_NXTBLK, +		.size	= MTDPART_SIZ_FULL, +	} +}; + +static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) +{ +	*num_partitions = ARRAY_SIZE(eb_nand_partition); +	return eb_nand_partition; +} + +static struct atmel_nand_data __initdata eb_nand_data = { +	.ale		= 22, +	.cle		= 21, +/*	.det_pin	= ... not connected */ +/*	.rdy_pin	= AT91_PIN_PC16, */ +	.enable_pin	= AT91_PIN_PA15, +	.partition_info	= nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) +	.bus_width_16	= 1, +#else +	.bus_width_16	= 0, +#endif +}; + +static struct sam9_smc_config __initdata eb_nand_smc_config = { +	.ncs_read_setup		= 0, +	.nrd_setup		= 0, +	.ncs_write_setup	= 1, +	.nwe_setup		= 1, + +	.ncs_read_pulse		= 3, +	.nrd_pulse		= 3, +	.ncs_write_pulse	= 3, +	.nwe_pulse		= 3, + +	.read_cycle		= 5, +	.write_cycle		= 5, + +	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, +	.tdf_cycles		= 12, +}; + +static void __init eb_add_device_nand(void) +{ +	/* setup bus-width (8 or 16) */ +	if (eb_nand_data.bus_width_16) +		eb_nand_smc_config.mode |= AT91_SMC_DBW_16; +	else +		eb_nand_smc_config.mode |= AT91_SMC_DBW_8; + +	/* configure chip-select 3 (NAND) */ +	sam9_smc_configure(3, &eb_nand_smc_config); + +	at91_add_device_nand(&eb_nand_data); +} + + +/* + * SPI devices + */ +static struct resource rtc_resources[] = { +	[0] = { +		.start	= AT572D940HF_ID_IRQ1, +		.end	= AT572D940HF_ID_IRQ1, +		.flags	= IORESOURCE_IRQ, +	}, +}; + +static struct ds1305_platform_data ds1306_data = { +	.is_ds1306	= true, +	.en_1hz		= false, +}; + +static struct spi_board_info eb_spi_devices[] = { +	{	/* RTC Dallas DS1306 */ +		.modalias	= "rtc-ds1305", +		.chip_select	= 3, +		.mode		= SPI_CS_HIGH | SPI_CPOL | SPI_CPHA, +		.max_speed_hz	= 500000, +		.bus_num	= 0, +		.irq		= AT572D940HF_ID_IRQ1, +		.platform_data	= (void *) &ds1306_data, +	}, +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) +	{	/* Dataflash card */ +		.modalias	= "mtd_dataflash", +		.chip_select	= 0, +		.max_speed_hz	= 15 * 1000 * 1000, +		.bus_num	= 0, +	}, +#endif +}; + +static void __init eb_board_init(void) +{ +	/* Serial */ +	at91_add_device_serial(); +	/* USB Host */ +	at91_add_device_usbh(&eb_usbh_data); +	/* USB Device */ +	at91_add_device_udc(&eb_udc_data); +	/* I2C */ +	at91_add_device_i2c(NULL, 0); +	/* NOR */ +	eb_add_device_nor(); +	/* NAND */ +	eb_add_device_nand(); +	/* SPI */ +	at91_add_device_spi(eb_spi_devices, ARRAY_SIZE(eb_spi_devices)); +	/* MMC */ +	at91_add_device_mmc(0, &eb_mmc_data); +	/* Ethernet */ +	at91_add_device_eth(&eb_eth_data); +	/* mAgic */ +	at91_add_device_mAgic(); +} + +MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB") +	/* Maintainer: Atmel <costa.antonior@gmail.com> */ +	.phys_io	= AT91_BASE_SYS, +	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc, +	.boot_params	= AT91_SDRAM_BASE + 0x100, +	.timer		= &at91sam926x_timer, +	.map_io		= eb_map_io, +	.init_irq	= eb_init_irq, +	.init_machine	= eb_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index c042dcf4725..7f7da439341 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -29,6 +29,7 @@  #include <mach/cpu.h>  #include "clock.h" +#include "generic.h"  /* @@ -628,7 +629,7 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)  		at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);  	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() ||  		   cpu_is_at91sam9263() || cpu_is_at91sam9g20() || -		   cpu_is_at91sam9g10()) { +		   cpu_is_at91sam9g10() || cpu_is_at572d940hf()) {  		uhpck.pmc_mask = AT91SAM926x_PMC_UHP;  		udpck.pmc_mask = AT91SAM926x_PMC_UDP;  	} else if (cpu_is_at91cap9()) { @@ -711,12 +712,13 @@ int __init at91_clock_init(unsigned long main_clock)  	/*  	 * USB HS clock init  	 */ -	if (cpu_has_utmi()) +	if (cpu_has_utmi()) {  		/*  		 * multiplier is hard-wired to 40  		 * (obtain the USB High Speed 480 MHz when input is 12 MHz)  		 */  		utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz; +	}  	/*  	 * USB FS clock init @@ -746,7 +748,7 @@ int __init at91_clock_init(unsigned long main_clock)  		mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ?  			freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8));	/* mdiv */  	} else { -		mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8));      /* mdiv */ +		mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8));		/* mdiv */  	}  	/* Register the PMC's standard clocks */ diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h index 1ba3b95ff35..6cf4b78e175 100644 --- a/arch/arm/mach-at91/clock.h +++ b/arch/arm/mach-at91/clock.h @@ -22,7 +22,7 @@ struct clk {  	struct clk	*parent;  	u32		pmc_mask;  	void		(*mode)(struct clk *, int); -	unsigned	id:2;		/* PCK0..3, or 32k/main/a/b */ +	unsigned	id:3;		/* PCK0..4, or 32k/main/a/b */  	unsigned	type;		/* clock type */  	u16		users;  }; diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 88e413b3848..65c3dc5ba0d 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -17,6 +17,7 @@ extern void __init at91sam9rl_initialize(unsigned long main_clock);  extern void __init at91sam9g45_initialize(unsigned long main_clock);  extern void __init at91x40_initialize(unsigned long main_clock);  extern void __init at91cap9_initialize(unsigned long main_clock); +extern void __init at572d940hf_initialize(unsigned long main_clock);   /* Interrupts */  extern void __init at91rm9200_init_interrupts(unsigned int priority[]); @@ -27,6 +28,7 @@ extern void __init at91sam9rl_init_interrupts(unsigned int priority[]);  extern void __init at91sam9g45_init_interrupts(unsigned int priority[]);  extern void __init at91x40_init_interrupts(unsigned int priority[]);  extern void __init at91cap9_init_interrupts(unsigned int priority[]); +extern void __init at572d940hf_init_interrupts(unsigned int priority[]);  extern void __init at91_aic_init(unsigned int priority[]);   /* Timer */ diff --git a/arch/arm/mach-at91/include/mach/at572d940hf.h b/arch/arm/mach-at91/include/mach/at572d940hf.h new file mode 100644 index 00000000000..2d9b0af9c4d --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at572d940hf.h @@ -0,0 +1,123 @@ +/* + * include/mach/at572d940hf.h + * + * Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2008 Atmel + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#ifndef AT572D940HF_H +#define AT572D940HF_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ		0	/* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS		1	/* System Peripherals */ +#define AT572D940HF_ID_PIOA	2	/* Parallel IO Controller A */ +#define AT572D940HF_ID_PIOB	3	/* Parallel IO Controller B */ +#define AT572D940HF_ID_PIOC	4	/* Parallel IO Controller C */ +#define AT572D940HF_ID_EMAC	5	/* MACB ethernet controller */ +#define AT572D940HF_ID_US0	6	/* USART 0 */ +#define AT572D940HF_ID_US1	7	/* USART 1 */ +#define AT572D940HF_ID_US2	8	/* USART 2 */ +#define AT572D940HF_ID_MCI	9	/* Multimedia Card Interface */ +#define AT572D940HF_ID_UDP	10	/* USB Device Port */ +#define AT572D940HF_ID_TWI0	11	/* Two-Wire Interface 0 */ +#define AT572D940HF_ID_SPI0	12	/* Serial Peripheral Interface 0 */ +#define AT572D940HF_ID_SPI1	13	/* Serial Peripheral Interface 1 */ +#define AT572D940HF_ID_SSC0	14	/* Serial Synchronous Controller 0 */ +#define AT572D940HF_ID_SSC1	15	/* Serial Synchronous Controller 1 */ +#define AT572D940HF_ID_SSC2	16	/* Serial Synchronous Controller 2 */ +#define AT572D940HF_ID_TC0	17	/* Timer Counter 0 */ +#define AT572D940HF_ID_TC1	18	/* Timer Counter 1 */ +#define AT572D940HF_ID_TC2	19	/* Timer Counter 2 */ +#define AT572D940HF_ID_UHP	20	/* USB Host port */ +#define AT572D940HF_ID_SSC3	21	/* Serial Synchronous Controller 3 */ +#define AT572D940HF_ID_TWI1	22	/* Two-Wire Interface 1 */ +#define AT572D940HF_ID_CAN0	23	/* CAN Controller 0 */ +#define AT572D940HF_ID_CAN1	24	/* CAN Controller 1 */ +#define AT572D940HF_ID_MHALT	25	/* mAgicV HALT line */ +#define AT572D940HF_ID_MSIRQ0	26	/* mAgicV SIRQ0 line */ +#define AT572D940HF_ID_MEXC	27	/* mAgicV exception line */ +#define AT572D940HF_ID_MEDMA	28	/* mAgicV end of DMA line */ +#define AT572D940HF_ID_IRQ0	29	/* External Interrupt Source (IRQ0) */ +#define AT572D940HF_ID_IRQ1	30	/* External Interrupt Source (IRQ1) */ +#define AT572D940HF_ID_IRQ2	31	/* External Interrupt Source (IRQ2) */ + + +/* + * User Peripheral physical base addresses. + */ +#define AT572D940HF_BASE_TCB	0xfffa0000 +#define AT572D940HF_BASE_TC0	0xfffa0000 +#define AT572D940HF_BASE_TC1	0xfffa0040 +#define AT572D940HF_BASE_TC2	0xfffa0080 +#define AT572D940HF_BASE_UDP	0xfffa4000 +#define AT572D940HF_BASE_MCI	0xfffa8000 +#define AT572D940HF_BASE_TWI0	0xfffac000 +#define AT572D940HF_BASE_US0	0xfffb0000 +#define AT572D940HF_BASE_US1	0xfffb4000 +#define AT572D940HF_BASE_US2	0xfffb8000 +#define AT572D940HF_BASE_SSC0	0xfffbc000 +#define AT572D940HF_BASE_SSC1	0xfffc0000 +#define AT572D940HF_BASE_SSC2	0xfffc4000 +#define AT572D940HF_BASE_SPI0	0xfffc8000 +#define AT572D940HF_BASE_SPI1	0xfffcc000 +#define AT572D940HF_BASE_SSC3	0xfffd0000 +#define AT572D940HF_BASE_TWI1	0xfffd4000 +#define AT572D940HF_BASE_EMAC	0xfffd8000 +#define AT572D940HF_BASE_CAN0	0xfffdc000 +#define AT572D940HF_BASE_CAN1	0xfffe0000 +#define AT91_BASE_SYS		0xffffea00 + + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_SDRAMC	(0xffffea00 - AT91_BASE_SYS) +#define AT91_SMC	(0xffffec00 - AT91_BASE_SYS) +#define AT91_MATRIX	(0xffffee00 - AT91_BASE_SYS) +#define AT91_AIC	(0xfffff000 - AT91_BASE_SYS) +#define AT91_DBGU	(0xfffff200 - AT91_BASE_SYS) +#define AT91_PIOA	(0xfffff400 - AT91_BASE_SYS) +#define AT91_PIOB	(0xfffff600 - AT91_BASE_SYS) +#define AT91_PIOC	(0xfffff800 - AT91_BASE_SYS) +#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS) +#define AT91_RTT	(0xfffffd20 - AT91_BASE_SYS) +#define AT91_PIT	(0xfffffd30 - AT91_BASE_SYS) +#define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS) + +#define AT91_USART0	AT572D940HF_ID_US0 +#define AT91_USART1	AT572D940HF_ID_US1 +#define AT91_USART2	AT572D940HF_ID_US2 + + +/* + * Internal Memory. + */ +#define AT572D940HF_SRAM_BASE	0x00300000	/* Internal SRAM base address */ +#define AT572D940HF_SRAM_SIZE	(48 * SZ_1K)	/* Internal SRAM size (48Kb) */ + +#define AT572D940HF_ROM_BASE	0x00400000	/* Internal ROM base address */ +#define AT572D940HF_ROM_SIZE	SZ_32K		/* Internal ROM size (32Kb) */ + +#define AT572D940HF_UHP_BASE	0x00500000	/* USB Host controller */ + + +#endif diff --git a/arch/arm/mach-at91/include/mach/at572d940hf_matrix.h b/arch/arm/mach-at91/include/mach/at572d940hf_matrix.h new file mode 100644 index 00000000000..b6751df0948 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at572d940hf_matrix.h @@ -0,0 +1,123 @@ +/* + * include/mach//at572d940hf_matrix.h + * + * Antonio R. Costa <costa.antonior@gmail.com> + * Copyright (C) 2008 Atmel + * + * Copyright (C) 2005 SAN People + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef AT572D940HF_MATRIX_H +#define AT572D940HF_MATRIX_H + +#define AT91_MATRIX_MCFG0	(AT91_MATRIX + 0x00)	/* Master Configuration Register 0 */ +#define AT91_MATRIX_MCFG1	(AT91_MATRIX + 0x04)	/* Master Configuration Register 1 */ +#define AT91_MATRIX_MCFG2	(AT91_MATRIX + 0x08)	/* Master Configuration Register 2 */ +#define AT91_MATRIX_MCFG3	(AT91_MATRIX + 0x0C)	/* Master Configuration Register 3 */ +#define AT91_MATRIX_MCFG4	(AT91_MATRIX + 0x10)	/* Master Configuration Register 4 */ +#define AT91_MATRIX_MCFG5	(AT91_MATRIX + 0x14)	/* Master Configuration Register 5 */ + +#define		AT91_MATRIX_ULBT	(7 << 0)	/* Undefined Length Burst Type */ +#define			AT91_MATRIX_ULBT_INFINITE	(0 << 0) +#define			AT91_MATRIX_ULBT_SINGLE		(1 << 0) +#define			AT91_MATRIX_ULBT_FOUR		(2 << 0) +#define			AT91_MATRIX_ULBT_EIGHT		(3 << 0) +#define			AT91_MATRIX_ULBT_SIXTEEN	(4 << 0) + +#define AT91_MATRIX_SCFG0	(AT91_MATRIX + 0x40)	/* Slave Configuration Register 0 */ +#define AT91_MATRIX_SCFG1	(AT91_MATRIX + 0x44)	/* Slave Configuration Register 1 */ +#define AT91_MATRIX_SCFG2	(AT91_MATRIX + 0x48)	/* Slave Configuration Register 2 */ +#define AT91_MATRIX_SCFG3	(AT91_MATRIX + 0x4C)	/* Slave Configuration Register 3 */ +#define AT91_MATRIX_SCFG4	(AT91_MATRIX + 0x50)	/* Slave Configuration Register 4 */ +#define		AT91_MATRIX_SLOT_CYCLE		(0xff << 0)	/* Maximum Number of Allowed Cycles for a Burst */ +#define		AT91_MATRIX_DEFMSTR_TYPE	(3    << 16)	/* Default Master Type */ +#define			AT91_MATRIX_DEFMSTR_TYPE_NONE	(0 << 16) +#define			AT91_MATRIX_DEFMSTR_TYPE_LAST	(1 << 16) +#define			AT91_MATRIX_DEFMSTR_TYPE_FIXED	(2 << 16) +#define		AT91_MATRIX_FIXED_DEFMSTR	(0x7  << 18)	/* Fixed Index of Default Master */ +#define		AT91_MATRIX_ARBT		(3    << 24)	/* Arbitration Type */ +#define			AT91_MATRIX_ARBT_ROUND_ROBIN	(0 << 24) +#define			AT91_MATRIX_ARBT_FIXED_PRIORITY	(1 << 24) + +#define AT91_MATRIX_PRAS0	(AT91_MATRIX + 0x80)	/* Priority Register A for Slave 0 */ +#define AT91_MATRIX_PRAS1	(AT91_MATRIX + 0x88)	/* Priority Register A for Slave 1 */ +#define AT91_MATRIX_PRAS2	(AT91_MATRIX + 0x90)	/* Priority Register A for Slave 2 */ +#define AT91_MATRIX_PRAS3	(AT91_MATRIX + 0x98)	/* Priority Register A for Slave 3 */ +#define AT91_MATRIX_PRAS4	(AT91_MATRIX + 0xA0)	/* Priority Register A for Slave 4 */ + +#define		AT91_MATRIX_M0PR		(3 << 0)	/* Master 0 Priority */ +#define		AT91_MATRIX_M1PR		(3 << 4)	/* Master 1 Priority */ +#define		AT91_MATRIX_M2PR		(3 << 8)	/* Master 2 Priority */ +#define		AT91_MATRIX_M3PR		(3 << 12)	/* Master 3 Priority */ +#define		AT91_MATRIX_M4PR		(3 << 16)	/* Master 4 Priority */ +#define		AT91_MATRIX_M5PR		(3 << 20)	/* Master 5 Priority */ +#define		AT91_MATRIX_M6PR		(3 << 24)	/* Master 6 Priority */ + +#define AT91_MATRIX_MRCR	(AT91_MATRIX + 0x100)	/* Master Remap Control Register */ +#define		AT91_MATRIX_RCB0		(1 << 0)	/* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ +#define		AT91_MATRIX_RCB1		(1 << 1)	/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ + +#define AT91_MATRIX_SFR0	(AT91_MATRIX + 0x110)	/* Special Function Register 0 */ +#define AT91_MATRIX_SFR1	(AT91_MATRIX + 0x114)	/* Special Function Register 1 */ +#define AT91_MATRIX_SFR2	(AT91_MATRIX + 0x118)	/* Special Function Register 2 */ +#define AT91_MATRIX_SFR3	(AT91_MATRIX + 0x11C)	/* Special Function Register 3 */ +#define AT91_MATRIX_SFR4	(AT91_MATRIX + 0x120)	/* Special Function Register 4 */ +#define AT91_MATRIX_SFR5	(AT91_MATRIX + 0x124)	/* Special Function Register 5 */ +#define AT91_MATRIX_SFR6	(AT91_MATRIX + 0x128)	/* Special Function Register 6 */ +#define AT91_MATRIX_SFR7	(AT91_MATRIX + 0x12C)	/* Special Function Register 7 */ +#define AT91_MATRIX_SFR8	(AT91_MATRIX + 0x130)	/* Special Function Register 8 */ +#define AT91_MATRIX_SFR9	(AT91_MATRIX + 0x134)	/* Special Function Register 9 */ +#define AT91_MATRIX_SFR10	(AT91_MATRIX + 0x138)	/* Special Function Register 10 */ +#define AT91_MATRIX_SFR11	(AT91_MATRIX + 0x13C)	/* Special Function Register 11 */ +#define AT91_MATRIX_SFR12	(AT91_MATRIX + 0x140)	/* Special Function Register 12 */ +#define AT91_MATRIX_SFR13	(AT91_MATRIX + 0x144)	/* Special Function Register 13 */ +#define AT91_MATRIX_SFR14	(AT91_MATRIX + 0x148)	/* Special Function Register 14 */ +#define AT91_MATRIX_SFR15	(AT91_MATRIX + 0x14C)	/* Special Function Register 15 */ + + +/* + * The following registers / bits are not defined in the Datasheet (Revision A) + */ + +#define AT91_MATRIX_TCR		(AT91_MATRIX + 0x100)	/* TCM Configuration Register */ +#define		AT91_MATRIX_ITCM_SIZE		(0xf << 0)	/* Size of ITCM enabled memory block */ +#define			AT91_MATRIX_ITCM_0		(0 << 0) +#define			AT91_MATRIX_ITCM_16		(5 << 0) +#define			AT91_MATRIX_ITCM_32		(6 << 0) +#define			AT91_MATRIX_ITCM_64		(7 << 0) +#define		AT91_MATRIX_DTCM_SIZE		(0xf << 4)	/* Size of DTCM enabled memory block */ +#define			AT91_MATRIX_DTCM_0		(0 << 4) +#define			AT91_MATRIX_DTCM_16		(5 << 4) +#define			AT91_MATRIX_DTCM_32		(6 << 4) +#define			AT91_MATRIX_DTCM_64		(7 << 4) + +#define AT91_MATRIX_EBICSA	(AT91_MATRIX + 0x11C)	/* EBI Chip Select Assignment Register */ +#define		AT91_MATRIX_CS1A		(1 << 1)	/* Chip Select 1 Assignment */ +#define			AT91_MATRIX_CS1A_SMC		(0 << 1) +#define			AT91_MATRIX_CS1A_SDRAMC		(1 << 1) +#define		AT91_MATRIX_CS3A		(1 << 3)	/* Chip Select 3 Assignment */ +#define			AT91_MATRIX_CS3A_SMC		(0 << 3) +#define			AT91_MATRIX_CS3A_SMC_SMARTMEDIA	(1 << 3) +#define		AT91_MATRIX_CS4A		(1 << 4)	/* Chip Select 4 Assignment */ +#define			AT91_MATRIX_CS4A_SMC		(0 << 4) +#define			AT91_MATRIX_CS4A_SMC_CF1	(1 << 4) +#define		AT91_MATRIX_CS5A		(1 << 5)	/* Chip Select 5 Assignment */ +#define			AT91_MATRIX_CS5A_SMC		(0 << 5) +#define			AT91_MATRIX_CS5A_SMC_CF2	(1 << 5) +#define		AT91_MATRIX_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */ + +#endif diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h index 64589eaaaee..e46f93e34aa 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc.h @@ -32,6 +32,7 @@  #define		AT91_PMC_PCK1		(1 <<  9)		/* Programmable Clock 1 */  #define		AT91_PMC_PCK2		(1 << 10)		/* Programmable Clock 2 */  #define		AT91_PMC_PCK3		(1 << 11)		/* Programmable Clock 3 */ +#define		AT91_PMC_PCK4		(1 << 12)		/* Programmable Clock 4 [AT572D940HF only] */  #define		AT91_PMC_HCK0		(1 << 16)		/* AHB Clock (USB host) [AT91SAM9261 only] */  #define		AT91_PMC_HCK1		(1 << 17)		/* AHB Clock (LCD) [AT91SAM9261 only] */ diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index bb6f6a7ba5e..ceaec6c16eb 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -87,7 +87,7 @@ struct at91_eth_data {  extern void __init at91_add_device_eth(struct at91_eth_data *data);  #if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91CAP9) \ -	|| defined(CONFIG_ARCH_AT91SAM9G45) +	|| defined(CONFIG_ARCH_AT91SAM9G45) || defined(CONFIG_ARCH_AT572D940HF)  #define eth_platform_data	at91_eth_data  #endif @@ -205,6 +205,9 @@ extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);  extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);  extern void __init at91_pwm_leds(struct gpio_led *leds, int nr); + /* AT572D940HF DSP */ +extern void __init at91_add_device_mAgic(void); +  /* FIXME: this needs a better location, but gets stuff building again */  extern int at91_suspend_entering_slow_clock(void); diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index c22df30ed5e..5a0650101d4 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -33,6 +33,8 @@  #define ARCH_ID_AT91SAM9XE256	0x329a93a0  #define ARCH_ID_AT91SAM9XE512	0x329aa3a0 +#define ARCH_ID_AT572D940HF	0x0e0303e0 +  #define ARCH_ID_AT91M40800	0x14080044  #define ARCH_ID_AT91R40807	0x44080746  #define ARCH_ID_AT91M40807	0x14080745 @@ -141,6 +143,12 @@ static inline unsigned long at91cap9_rev_identify(void)  #define cpu_is_at91cap9_revC()	(0)  #endif +#ifdef CONFIG_ARCH_AT572D940HF +#define cpu_is_at572d940hf() (at91_cpu_identify() == ARCH_ID_AT572D940HF) +#else +#define cpu_is_at572d940hf() (0) +#endif +  /*   * Since this is ARM, we will never run on any AVR32 CPU. But these   * definitions may reduce clutter in common drivers. diff --git a/arch/arm/mach-at91/include/mach/debug-macro.S b/arch/arm/mach-at91/include/mach/debug-macro.S index 29052ba66ad..9e750a1c1b5 100644 --- a/arch/arm/mach-at91/include/mach/debug-macro.S +++ b/arch/arm/mach-at91/include/mach/debug-macro.S @@ -14,7 +14,7 @@  #include <mach/hardware.h>  #include <mach/at91_dbgu.h> -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1						@ MMU enabled?  	ldreq	\rx, =(AT91_BASE_SYS + AT91_DBGU)		@ System peripherals (phys address) diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h index a0df8b022df..3d64a75e3ed 100644 --- a/arch/arm/mach-at91/include/mach/hardware.h +++ b/arch/arm/mach-at91/include/mach/hardware.h @@ -32,6 +32,8 @@  #include <mach/at91cap9.h>  #elif defined(CONFIG_ARCH_AT91X40)  #include <mach/at91x40.h> +#elif defined(CONFIG_ARCH_AT572D940HF) +#include <mach/at572d940hf.h>  #else  #error "Unsupported AT91 processor"  #endif diff --git a/arch/arm/mach-at91/include/mach/timex.h b/arch/arm/mach-at91/include/mach/timex.h index 31ac2d97f14..05a6e8af80c 100644 --- a/arch/arm/mach-at91/include/mach/timex.h +++ b/arch/arm/mach-at91/include/mach/timex.h @@ -82,6 +82,11 @@  #define AT91X40_MASTER_CLOCK	40000000  #define CLOCK_TICK_RATE		(AT91X40_MASTER_CLOCK) +#elif defined(CONFIG_ARCH_AT572D940HF) + +#define AT572D940HF_MASTER_CLOCK	80000000 +#define CLOCK_TICK_RATE		(AT572D940HF_MASTER_CLOCK/16) +  #endif  #endif diff --git a/arch/arm/mach-clps711x/include/mach/debug-macro.S b/arch/arm/mach-clps711x/include/mach/debug-macro.S index 64baf9f8740..fedd8076a68 100644 --- a/arch/arm/mach-clps711x/include/mach/debug-macro.S +++ b/arch/arm/mach-clps711x/include/mach/debug-macro.S @@ -13,7 +13,7 @@  #include <asm/hardware/clps7111.h> -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #CLPS7111_PHYS_BASE diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S b/arch/arm/mach-davinci/include/mach/debug-macro.S index 17ab5236da6..3cd93a801d9 100644 --- a/arch/arm/mach-davinci/include/mach/debug-macro.S +++ b/arch/arm/mach-davinci/include/mach/debug-macro.S @@ -19,7 +19,7 @@  #include <linux/serial_reg.h>  #define UART_SHIFT	2 -		.macro addruart, rx +		.macro addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x01000000	@ physical base address diff --git a/arch/arm/mach-davinci/include/mach/hardware.h b/arch/arm/mach-davinci/include/mach/hardware.h index 41c89386e39..c45ba1f62a1 100644 --- a/arch/arm/mach-davinci/include/mach/hardware.h +++ b/arch/arm/mach-davinci/include/mach/hardware.h @@ -27,7 +27,7 @@  /*   * I/O mapping   */ -#define IO_PHYS				0x01c00000 +#define IO_PHYS				0x01c00000UL  #define IO_OFFSET			0xfd000000 /* Virtual IO = 0xfec00000 */  #define IO_SIZE				0x00400000  #define IO_VIRT				(IO_PHYS + IO_OFFSET) diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c index 49912b48b1b..a1c0b6b99ed 100644 --- a/arch/arm/mach-davinci/io.c +++ b/arch/arm/mach-davinci/io.c @@ -24,7 +24,7 @@ void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type)  	if (BETWEEN(p, IO_PHYS, IO_SIZE))  		return XLATE(p, IO_PHYS, IO_VIRT); -	return __arm_ioremap(p, size, type); +	return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));  }  EXPORT_SYMBOL(davinci_ioremap); diff --git a/arch/arm/mach-dove/include/mach/debug-macro.S b/arch/arm/mach-dove/include/mach/debug-macro.S index 9b89ec7d304..1521d13f1d1 100644 --- a/arch/arm/mach-dove/include/mach/debug-macro.S +++ b/arch/arm/mach-dove/include/mach/debug-macro.S @@ -8,7 +8,7 @@  #include <mach/bridge-regs.h> -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1					@ MMU enabled?  	ldreq	\rx, =DOVE_SB_REGS_PHYS_BASE diff --git a/arch/arm/mach-dove/include/mach/vmalloc.h b/arch/arm/mach-dove/include/mach/vmalloc.h index 8b2c974755c..a28792cf761 100644 --- a/arch/arm/mach-dove/include/mach/vmalloc.h +++ b/arch/arm/mach-dove/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-dove/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfd800000 +#define VMALLOC_END	0xfd800000UL diff --git a/arch/arm/mach-ebsa110/include/mach/debug-macro.S b/arch/arm/mach-ebsa110/include/mach/debug-macro.S index 1dde8227f3a..ebbd89f0e6c 100644 --- a/arch/arm/mach-ebsa110/include/mach/debug-macro.S +++ b/arch/arm/mach-ebsa110/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  **/ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mov	\rx, #0xf0000000  		orr	\rx, \rx, #0x00000be0  		.endm diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig index 9167c3d2a5e..3a08b18f643 100644 --- a/arch/arm/mach-ep93xx/Kconfig +++ b/arch/arm/mach-ep93xx/Kconfig @@ -161,6 +161,20 @@ config MACH_MICRO9S  	  Say 'Y' here if you want your kernel to support the  	  Contec Micro9-Slim board. +config MACH_SIM_ONE +        bool "Support Simplemachines Sim.One board" +        depends on EP93XX_SDCE0_PHYS_OFFSET +        help +          Say 'Y' here if you want your kernel to support the +          Simplemachines Sim.One board. + +config MACH_SNAPPER_CL15 +	bool "Support Bluewater Systems Snapper CL15 Module" +	depends on EP93XX_SDCE0_PHYS_OFFSET +	help +	  Say 'Y' here if you want your kernel to support the Bluewater +	  Systems Snapper CL15 Module. +  config MACH_TS72XX  	bool "Support Technologic Systems TS-72xx SBC"  	depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index eae6199a989..33ee2c863d1 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -10,4 +10,6 @@ obj-$(CONFIG_MACH_ADSSPHERE)	+= adssphere.o  obj-$(CONFIG_MACH_EDB93XX)	+= edb93xx.o  obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o  obj-$(CONFIG_MACH_MICRO9)	+= micro9.o +obj-$(CONFIG_MACH_SIM_ONE)	+= simone.o +obj-$(CONFIG_MACH_SNAPPER_CL15)	+= snappercl15.o  obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index bb3c6219644..5f80092b6ac 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -10,6 +10,8 @@   * your option) any later version.   */ +#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt +  #include <linux/kernel.h>  #include <linux/clk.h>  #include <linux/err.h> @@ -446,30 +448,34 @@ static int __init ep93xx_clock_init(void)  {  	u32 value; -	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1); -	if (!(value & 0x00800000)) {			/* PLL1 bypassed?  */ +	/* Determine the bootloader configured pll1 rate */ +	value = __raw_readl(EP93XX_SYSCON_CLKSET1); +	if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))  		clk_pll1.rate = clk_xtali.rate; -	} else { +	else  		clk_pll1.rate = calc_pll_rate(value); -	} + +	/* Initialize the pll1 derived clocks */  	clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];  	clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];  	clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];  	ep93xx_dma_clock_init(); -	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2); -	if (!(value & 0x00080000)) {			/* PLL2 bypassed?  */ +	/* Determine the bootloader configured pll2 rate */ +	value = __raw_readl(EP93XX_SYSCON_CLKSET2); +	if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))  		clk_pll2.rate = clk_xtali.rate; -	} else if (value & 0x00040000) {		/* PLL2 enabled?  */ +	else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)  		clk_pll2.rate = calc_pll_rate(value); -	} else { +	else  		clk_pll2.rate = 0; -	} + +	/* Initialize the pll2 derived clocks */  	clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1); -	printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n", +	pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",  		clk_pll1.rate / 1000000, clk_pll2.rate / 1000000); -	printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", +	pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",  		clk_f.rate / 1000000, clk_h.rate / 1000000,  		clk_p.rate / 1000000); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 1f0d66561bb..90fb591cbff 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -14,12 +14,15 @@   * your option) any later version.   */ +#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt +  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/platform_device.h>  #include <linux/interrupt.h>  #include <linux/dma-mapping.h>  #include <linux/timex.h> +#include <linux/irq.h>  #include <linux/io.h>  #include <linux/gpio.h>  #include <linux/leds.h> @@ -35,7 +38,6 @@  #include <asm/mach/map.h>  #include <asm/mach/time.h> -#include <asm/mach/irq.h>  #include <asm/hardware/vic.h> @@ -82,13 +84,40 @@ void __init ep93xx_map_io(void)   * to use this timer for something else.  We also use timer 4 for keeping   * track of lost jiffies.   */ -static unsigned int last_jiffy_time; +#define EP93XX_TIMER_REG(x)		(EP93XX_TIMER_BASE + (x)) +#define EP93XX_TIMER1_LOAD		EP93XX_TIMER_REG(0x00) +#define EP93XX_TIMER1_VALUE		EP93XX_TIMER_REG(0x04) +#define EP93XX_TIMER1_CONTROL		EP93XX_TIMER_REG(0x08) +#define EP93XX_TIMER123_CONTROL_ENABLE	(1 << 7) +#define EP93XX_TIMER123_CONTROL_MODE	(1 << 6) +#define EP93XX_TIMER123_CONTROL_CLKSEL	(1 << 3) +#define EP93XX_TIMER1_CLEAR		EP93XX_TIMER_REG(0x0c) +#define EP93XX_TIMER2_LOAD		EP93XX_TIMER_REG(0x20) +#define EP93XX_TIMER2_VALUE		EP93XX_TIMER_REG(0x24) +#define EP93XX_TIMER2_CONTROL		EP93XX_TIMER_REG(0x28) +#define EP93XX_TIMER2_CLEAR		EP93XX_TIMER_REG(0x2c) +#define EP93XX_TIMER4_VALUE_LOW		EP93XX_TIMER_REG(0x60) +#define EP93XX_TIMER4_VALUE_HIGH	EP93XX_TIMER_REG(0x64) +#define EP93XX_TIMER4_VALUE_HIGH_ENABLE	(1 << 8) +#define EP93XX_TIMER3_LOAD		EP93XX_TIMER_REG(0x80) +#define EP93XX_TIMER3_VALUE		EP93XX_TIMER_REG(0x84) +#define EP93XX_TIMER3_CONTROL		EP93XX_TIMER_REG(0x88) +#define EP93XX_TIMER3_CLEAR		EP93XX_TIMER_REG(0x8c) + +#define EP93XX_TIMER123_CLOCK		508469 +#define EP93XX_TIMER4_CLOCK		983040 +#define TIMER1_RELOAD			((EP93XX_TIMER123_CLOCK / HZ) - 1)  #define TIMER4_TICKS_PER_JIFFY		DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ) +static unsigned int last_jiffy_time; +  static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)  { +	/* Writing any value clears the timer interrupt */  	__raw_writel(1, EP93XX_TIMER1_CLEAR); + +	/* Recover lost jiffies */  	while ((signed long)  		(__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)  						>= TIMER4_TICKS_PER_JIFFY) { @@ -107,13 +136,18 @@ static struct irqaction ep93xx_timer_irq = {  static void __init ep93xx_timer_init(void)  { +	u32 tmode = EP93XX_TIMER123_CONTROL_MODE | +		    EP93XX_TIMER123_CONTROL_CLKSEL; +  	/* Enable periodic HZ timer.  */ -	__raw_writel(0x48, EP93XX_TIMER1_CONTROL); -	__raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD); -	__raw_writel(0xc8, EP93XX_TIMER1_CONTROL); +	__raw_writel(tmode, EP93XX_TIMER1_CONTROL); +	__raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD); +	__raw_writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE, +			EP93XX_TIMER1_CONTROL);  	/* Enable lost jiffy timer.  */ -	__raw_writel(0x100, EP93XX_TIMER4_VALUE_HIGH); +	__raw_writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE, +			EP93XX_TIMER4_VALUE_HIGH);  	setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);  } @@ -135,237 +169,16 @@ struct sys_timer ep93xx_timer = {  /************************************************************************* - * GPIO handling for EP93xx - *************************************************************************/ -static unsigned char gpio_int_unmasked[3]; -static unsigned char gpio_int_enabled[3]; -static unsigned char gpio_int_type1[3]; -static unsigned char gpio_int_type2[3]; -static unsigned char gpio_int_debounce[3]; - -/* Port ordering is: A B F */ -static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c }; -static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 }; -static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 }; -static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x58 }; -static const u8 int_debounce_register_offset[3]	= { 0xa8, 0xc4, 0x64 }; - -void ep93xx_gpio_update_int_params(unsigned port) -{ -	BUG_ON(port > 2); - -	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); - -	__raw_writeb(gpio_int_type2[port], -		EP93XX_GPIO_REG(int_type2_register_offset[port])); - -	__raw_writeb(gpio_int_type1[port], -		EP93XX_GPIO_REG(int_type1_register_offset[port])); - -	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], -		EP93XX_GPIO_REG(int_en_register_offset[port])); -} - -void ep93xx_gpio_int_mask(unsigned line) -{ -	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); -} - -void ep93xx_gpio_int_debounce(unsigned int irq, int enable) -{ -	int line = irq_to_gpio(irq); -	int port = line >> 3; -	int port_mask = 1 << (line & 7); - -	if (enable) -		gpio_int_debounce[port] |= port_mask; -	else -		gpio_int_debounce[port] &= ~port_mask; - -	__raw_writeb(gpio_int_debounce[port], -		EP93XX_GPIO_REG(int_debounce_register_offset[port])); -} -EXPORT_SYMBOL(ep93xx_gpio_int_debounce); - -/*************************************************************************   * EP93xx IRQ handling   *************************************************************************/ -static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) -{ -	unsigned char status; -	int i; - -	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); -	for (i = 0; i < 8; i++) { -		if (status & (1 << i)) { -			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; -			generic_handle_irq(gpio_irq); -		} -	} - -	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); -	for (i = 0; i < 8; i++) { -		if (status & (1 << i)) { -			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; -			generic_handle_irq(gpio_irq); -		} -	} -} - -static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) -{ -	/* -	 * map discontiguous hw irq range to continous sw irq range: -	 * -	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) -	 */ -	int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ -	int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; - -	generic_handle_irq(gpio_irq); -} - -static void ep93xx_gpio_irq_ack(unsigned int irq) -{ -	int line = irq_to_gpio(irq); -	int port = line >> 3; -	int port_mask = 1 << (line & 7); - -	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { -		gpio_int_type2[port] ^= port_mask; /* switch edge direction */ -		ep93xx_gpio_update_int_params(port); -	} - -	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); -} - -static void ep93xx_gpio_irq_mask_ack(unsigned int irq) -{ -	int line = irq_to_gpio(irq); -	int port = line >> 3; -	int port_mask = 1 << (line & 7); - -	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) -		gpio_int_type2[port] ^= port_mask; /* switch edge direction */ - -	gpio_int_unmasked[port] &= ~port_mask; -	ep93xx_gpio_update_int_params(port); - -	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); -} - -static void ep93xx_gpio_irq_mask(unsigned int irq) -{ -	int line = irq_to_gpio(irq); -	int port = line >> 3; - -	gpio_int_unmasked[port] &= ~(1 << (line & 7)); -	ep93xx_gpio_update_int_params(port); -} - -static void ep93xx_gpio_irq_unmask(unsigned int irq) -{ -	int line = irq_to_gpio(irq); -	int port = line >> 3; - -	gpio_int_unmasked[port] |= 1 << (line & 7); -	ep93xx_gpio_update_int_params(port); -} - - -/* - * gpio_int_type1 controls whether the interrupt is level (0) or - * edge (1) triggered, while gpio_int_type2 controls whether it - * triggers on low/falling (0) or high/rising (1). - */ -static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) -{ -	struct irq_desc *desc = irq_desc + irq; -	const int gpio = irq_to_gpio(irq); -	const int port = gpio >> 3; -	const int port_mask = 1 << (gpio & 7); - -	gpio_direction_input(gpio); - -	switch (type) { -	case IRQ_TYPE_EDGE_RISING: -		gpio_int_type1[port] |= port_mask; -		gpio_int_type2[port] |= port_mask; -		desc->handle_irq = handle_edge_irq; -		break; -	case IRQ_TYPE_EDGE_FALLING: -		gpio_int_type1[port] |= port_mask; -		gpio_int_type2[port] &= ~port_mask; -		desc->handle_irq = handle_edge_irq; -		break; -	case IRQ_TYPE_LEVEL_HIGH: -		gpio_int_type1[port] &= ~port_mask; -		gpio_int_type2[port] |= port_mask; -		desc->handle_irq = handle_level_irq; -		break; -	case IRQ_TYPE_LEVEL_LOW: -		gpio_int_type1[port] &= ~port_mask; -		gpio_int_type2[port] &= ~port_mask; -		desc->handle_irq = handle_level_irq; -		break; -	case IRQ_TYPE_EDGE_BOTH: -		gpio_int_type1[port] |= port_mask; -		/* set initial polarity based on current input level */ -		if (gpio_get_value(gpio)) -			gpio_int_type2[port] &= ~port_mask; /* falling */ -		else -			gpio_int_type2[port] |= port_mask; /* rising */ -		desc->handle_irq = handle_edge_irq; -		break; -	default: -		pr_err("ep93xx: failed to set irq type %d for gpio %d\n", -		       type, gpio); -		return -EINVAL; -	} - -	gpio_int_enabled[port] |= port_mask; - -	desc->status &= ~IRQ_TYPE_SENSE_MASK; -	desc->status |= type & IRQ_TYPE_SENSE_MASK; - -	ep93xx_gpio_update_int_params(port); - -	return 0; -} - -static struct irq_chip ep93xx_gpio_irq_chip = { -	.name		= "GPIO", -	.ack		= ep93xx_gpio_irq_ack, -	.mask_ack	= ep93xx_gpio_irq_mask_ack, -	.mask		= ep93xx_gpio_irq_mask, -	.unmask		= ep93xx_gpio_irq_unmask, -	.set_type	= ep93xx_gpio_irq_type, -}; - +extern void ep93xx_gpio_init_irq(void);  void __init ep93xx_init_irq(void)  { -	int gpio_irq; -  	vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);  	vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); -	for (gpio_irq = gpio_to_irq(0); -	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { -		set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip); -		set_irq_handler(gpio_irq, handle_level_irq); -		set_irq_flags(gpio_irq, IRQF_VALID); -	} - -	set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler); -	set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler); +	ep93xx_gpio_init_irq();  } @@ -572,9 +385,9 @@ void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,  	 * CMOS driver.  	 */  	if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT) -		pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n"); +		pr_warning("sda != EEDAT, open drain has no effect\n");  	if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK) -		pr_warning("ep93xx: scl != EECLK, open drain has no effect\n"); +		pr_warning("scl != EECLK, open drain has no effect\n");  	__raw_writel((data->sda_is_open_drain << 1) |  		     (data->scl_is_open_drain << 0), diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c index dbcac9c40a2..8904ca4e2e2 100644 --- a/arch/arm/mach-ep93xx/dma-m2p.c +++ b/arch/arm/mach-ep93xx/dma-m2p.c @@ -28,6 +28,8 @@   * with this implementation.   */ +#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt +  #include <linux/kernel.h>  #include <linux/clk.h>  #include <linux/err.h> @@ -173,7 +175,7 @@ static irqreturn_t m2p_irq(int irq, void *dev_id)  	switch (m2p_channel_state(ch)) {  	case STATE_IDLE: -		pr_crit("m2p_irq: dma interrupt without a dma buffer\n"); +		pr_crit("dma interrupt without a dma buffer\n");  		BUG();  		break; @@ -197,7 +199,7 @@ static irqreturn_t m2p_irq(int irq, void *dev_id)  		break;  	case STATE_NEXT: -		pr_crit("m2p_irq: dma interrupt while next\n"); +		pr_crit("dma interrupt while next\n");  		BUG();  		break;  	} diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index a4a7be30800..d22d67ac8b9 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -118,12 +118,33 @@ static void __init edb93xx_register_i2c(void)  	}  } + +/************************************************************************* + * EDB93xx pwm + *************************************************************************/ +static void __init edb93xx_register_pwm(void) +{ +	if (machine_is_edb9301() || +	    machine_is_edb9302() || machine_is_edb9302a()) { +		/* EP9301 and EP9302 only have pwm.1 (EGPIO14) */ +		ep93xx_register_pwm(0, 1); +	} else if (machine_is_edb9307() || machine_is_edb9307a()) { +		/* EP9307 only has pwm.0 (PWMOUT) */ +		ep93xx_register_pwm(1, 0); +	} else { +		/* EP9312 and EP9315 have both */ +		ep93xx_register_pwm(1, 1); +	} +} + +  static void __init edb93xx_init_machine(void)  {  	ep93xx_init_devices();  	edb93xx_register_flash();  	ep93xx_register_eth(&edb93xx_eth_data, 1);  	edb93xx_register_i2c(); +	edb93xx_register_pwm();  } diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c index 1ea8871e03a..cc377ae8c42 100644 --- a/arch/arm/mach-ep93xx/gpio.c +++ b/arch/arm/mach-ep93xx/gpio.c @@ -13,6 +13,8 @@   *  published by the Free Software Foundation.   */ +#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt +  #include <linux/init.h>  #include <linux/module.h>  #include <linux/seq_file.h> @@ -22,6 +24,235 @@  #include <mach/hardware.h> +/************************************************************************* + * GPIO handling for EP93xx + *************************************************************************/ +static unsigned char gpio_int_unmasked[3]; +static unsigned char gpio_int_enabled[3]; +static unsigned char gpio_int_type1[3]; +static unsigned char gpio_int_type2[3]; +static unsigned char gpio_int_debounce[3]; + +/* Port ordering is: A B F */ +static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c }; +static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 }; +static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 }; +static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x58 }; +static const u8 int_debounce_register_offset[3]	= { 0xa8, 0xc4, 0x64 }; + +void ep93xx_gpio_update_int_params(unsigned port) +{ +	BUG_ON(port > 2); + +	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); + +	__raw_writeb(gpio_int_type2[port], +		EP93XX_GPIO_REG(int_type2_register_offset[port])); + +	__raw_writeb(gpio_int_type1[port], +		EP93XX_GPIO_REG(int_type1_register_offset[port])); + +	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], +		EP93XX_GPIO_REG(int_en_register_offset[port])); +} + +void ep93xx_gpio_int_mask(unsigned line) +{ +	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); +} + +void ep93xx_gpio_int_debounce(unsigned int irq, int enable) +{ +	int line = irq_to_gpio(irq); +	int port = line >> 3; +	int port_mask = 1 << (line & 7); + +	if (enable) +		gpio_int_debounce[port] |= port_mask; +	else +		gpio_int_debounce[port] &= ~port_mask; + +	__raw_writeb(gpio_int_debounce[port], +		EP93XX_GPIO_REG(int_debounce_register_offset[port])); +} +EXPORT_SYMBOL(ep93xx_gpio_int_debounce); + +static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) +{ +	unsigned char status; +	int i; + +	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); +	for (i = 0; i < 8; i++) { +		if (status & (1 << i)) { +			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; +			generic_handle_irq(gpio_irq); +		} +	} + +	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); +	for (i = 0; i < 8; i++) { +		if (status & (1 << i)) { +			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; +			generic_handle_irq(gpio_irq); +		} +	} +} + +static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) +{ +	/* +	 * map discontiguous hw irq range to continous sw irq range: +	 * +	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) +	 */ +	int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ +	int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; + +	generic_handle_irq(gpio_irq); +} + +static void ep93xx_gpio_irq_ack(unsigned int irq) +{ +	int line = irq_to_gpio(irq); +	int port = line >> 3; +	int port_mask = 1 << (line & 7); + +	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { +		gpio_int_type2[port] ^= port_mask; /* switch edge direction */ +		ep93xx_gpio_update_int_params(port); +	} + +	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); +} + +static void ep93xx_gpio_irq_mask_ack(unsigned int irq) +{ +	int line = irq_to_gpio(irq); +	int port = line >> 3; +	int port_mask = 1 << (line & 7); + +	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) +		gpio_int_type2[port] ^= port_mask; /* switch edge direction */ + +	gpio_int_unmasked[port] &= ~port_mask; +	ep93xx_gpio_update_int_params(port); + +	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); +} + +static void ep93xx_gpio_irq_mask(unsigned int irq) +{ +	int line = irq_to_gpio(irq); +	int port = line >> 3; + +	gpio_int_unmasked[port] &= ~(1 << (line & 7)); +	ep93xx_gpio_update_int_params(port); +} + +static void ep93xx_gpio_irq_unmask(unsigned int irq) +{ +	int line = irq_to_gpio(irq); +	int port = line >> 3; + +	gpio_int_unmasked[port] |= 1 << (line & 7); +	ep93xx_gpio_update_int_params(port); +} + +/* + * gpio_int_type1 controls whether the interrupt is level (0) or + * edge (1) triggered, while gpio_int_type2 controls whether it + * triggers on low/falling (0) or high/rising (1). + */ +static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) +{ +	struct irq_desc *desc = irq_desc + irq; +	const int gpio = irq_to_gpio(irq); +	const int port = gpio >> 3; +	const int port_mask = 1 << (gpio & 7); + +	gpio_direction_input(gpio); + +	switch (type) { +	case IRQ_TYPE_EDGE_RISING: +		gpio_int_type1[port] |= port_mask; +		gpio_int_type2[port] |= port_mask; +		desc->handle_irq = handle_edge_irq; +		break; +	case IRQ_TYPE_EDGE_FALLING: +		gpio_int_type1[port] |= port_mask; +		gpio_int_type2[port] &= ~port_mask; +		desc->handle_irq = handle_edge_irq; +		break; +	case IRQ_TYPE_LEVEL_HIGH: +		gpio_int_type1[port] &= ~port_mask; +		gpio_int_type2[port] |= port_mask; +		desc->handle_irq = handle_level_irq; +		break; +	case IRQ_TYPE_LEVEL_LOW: +		gpio_int_type1[port] &= ~port_mask; +		gpio_int_type2[port] &= ~port_mask; +		desc->handle_irq = handle_level_irq; +		break; +	case IRQ_TYPE_EDGE_BOTH: +		gpio_int_type1[port] |= port_mask; +		/* set initial polarity based on current input level */ +		if (gpio_get_value(gpio)) +			gpio_int_type2[port] &= ~port_mask; /* falling */ +		else +			gpio_int_type2[port] |= port_mask; /* rising */ +		desc->handle_irq = handle_edge_irq; +		break; +	default: +		pr_err("failed to set irq type %d for gpio %d\n", type, gpio); +		return -EINVAL; +	} + +	gpio_int_enabled[port] |= port_mask; + +	desc->status &= ~IRQ_TYPE_SENSE_MASK; +	desc->status |= type & IRQ_TYPE_SENSE_MASK; + +	ep93xx_gpio_update_int_params(port); + +	return 0; +} + +static struct irq_chip ep93xx_gpio_irq_chip = { +	.name		= "GPIO", +	.ack		= ep93xx_gpio_irq_ack, +	.mask_ack	= ep93xx_gpio_irq_mask_ack, +	.mask		= ep93xx_gpio_irq_mask, +	.unmask		= ep93xx_gpio_irq_unmask, +	.set_type	= ep93xx_gpio_irq_type, +}; + +void __init ep93xx_gpio_init_irq(void) +{ +	int gpio_irq; + +	for (gpio_irq = gpio_to_irq(0); +	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { +		set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip); +		set_irq_handler(gpio_irq, handle_level_irq); +		set_irq_flags(gpio_irq, IRQF_VALID); +	} + +	set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler); +	set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler); +} + + +/************************************************************************* + * gpiolib interface for EP93xx on-chip GPIOs + *************************************************************************/  struct ep93xx_gpio_chip {  	struct gpio_chip	chip; @@ -31,10 +262,6 @@ struct ep93xx_gpio_chip {  #define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip) -/* From core.c */ -extern void ep93xx_gpio_int_mask(unsigned line); -extern void ep93xx_gpio_update_int_params(unsigned port); -  static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)  {  	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); diff --git a/arch/arm/mach-ep93xx/include/mach/debug-macro.S b/arch/arm/mach-ep93xx/include/mach/debug-macro.S index 802858bc809..5cd22444e22 100644 --- a/arch/arm/mach-ep93xx/include/mach/debug-macro.S +++ b/arch/arm/mach-ep93xx/include/mach/debug-macro.S @@ -11,7 +11,7 @@   */  #include <mach/ep93xx-regs.h> -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1				@ MMU enabled?  		ldreq	\rx, =EP93XX_APB_PHYS_BASE	@ Physical base diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index d55194a4c09..93e2ecc79ce 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -92,21 +92,6 @@  /* APB peripherals */  #define EP93XX_TIMER_BASE		EP93XX_APB_IOMEM(0x00010000) -#define EP93XX_TIMER_REG(x)		(EP93XX_TIMER_BASE + (x)) -#define EP93XX_TIMER1_LOAD		EP93XX_TIMER_REG(0x00) -#define EP93XX_TIMER1_VALUE		EP93XX_TIMER_REG(0x04) -#define EP93XX_TIMER1_CONTROL		EP93XX_TIMER_REG(0x08) -#define EP93XX_TIMER1_CLEAR		EP93XX_TIMER_REG(0x0c) -#define EP93XX_TIMER2_LOAD		EP93XX_TIMER_REG(0x20) -#define EP93XX_TIMER2_VALUE		EP93XX_TIMER_REG(0x24) -#define EP93XX_TIMER2_CONTROL		EP93XX_TIMER_REG(0x28) -#define EP93XX_TIMER2_CLEAR		EP93XX_TIMER_REG(0x2c) -#define EP93XX_TIMER4_VALUE_LOW		EP93XX_TIMER_REG(0x60) -#define EP93XX_TIMER4_VALUE_HIGH	EP93XX_TIMER_REG(0x64) -#define EP93XX_TIMER3_LOAD		EP93XX_TIMER_REG(0x80) -#define EP93XX_TIMER3_VALUE		EP93XX_TIMER_REG(0x84) -#define EP93XX_TIMER3_CONTROL		EP93XX_TIMER_REG(0x88) -#define EP93XX_TIMER3_CLEAR		EP93XX_TIMER_REG(0x8c)  #define EP93XX_I2S_BASE			EP93XX_APB_IOMEM(0x00020000) @@ -167,8 +152,11 @@  #define EP93XX_SYSCON_PWRCNT_DMA_M2P1	(1<<16)  #define EP93XX_SYSCON_HALT		EP93XX_SYSCON_REG(0x08)  #define EP93XX_SYSCON_STANDBY		EP93XX_SYSCON_REG(0x0c) -#define EP93XX_SYSCON_CLOCK_SET1	EP93XX_SYSCON_REG(0x20) -#define EP93XX_SYSCON_CLOCK_SET2	EP93XX_SYSCON_REG(0x24) +#define EP93XX_SYSCON_CLKSET1		EP93XX_SYSCON_REG(0x20) +#define EP93XX_SYSCON_CLKSET1_NBYP1	(1<<23) +#define EP93XX_SYSCON_CLKSET2		EP93XX_SYSCON_REG(0x24) +#define EP93XX_SYSCON_CLKSET2_NBYP2	(1<<19) +#define EP93XX_SYSCON_CLKSET2_PLL2_EN	(1<<18)  #define EP93XX_SYSCON_DEVCFG		EP93XX_SYSCON_REG(0x80)  #define EP93XX_SYSCON_DEVCFG_SWRST	(1<<31)  #define EP93XX_SYSCON_DEVCFG_D1ONG	(1<<30) diff --git a/arch/arm/mach-ep93xx/include/mach/vmalloc.h b/arch/arm/mach-ep93xx/include/mach/vmalloc.h index aed21cd3fe2..1b3f25d03d3 100644 --- a/arch/arm/mach-ep93xx/include/mach/vmalloc.h +++ b/arch/arm/mach-ep93xx/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-ep93xx/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfe800000 +#define VMALLOC_END	0xfe800000UL diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c new file mode 100644 index 00000000000..cd93990f1b9 --- /dev/null +++ b/arch/arm/mach-ep93xx/simone.c @@ -0,0 +1,97 @@ +/* + * arch/arm/mach-ep93xx/simone.c + * Simplemachines Sim.One support. + * + * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com> + * + * Based on the 2.6.24.7 support: + *   Copyright (C) 2009 Simplemachines + *   MMC support by Peter Ivanov <ivanovp@gmail.com>, 2007 + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/physmap.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/i2c-gpio.h> + +#include <mach/hardware.h> +#include <mach/fb.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data simone_flash_data = { +	.width		= 2, +}; + +static struct resource simone_flash_resource = { +	.start		= EP93XX_CS6_PHYS_BASE, +	.end		= EP93XX_CS6_PHYS_BASE + SZ_8M - 1, +	.flags		= IORESOURCE_MEM, +}; + +static struct platform_device simone_flash = { +	.name		= "physmap-flash", +	.id		= 0, +	.num_resources	= 1, +	.resource	= &simone_flash_resource, +	.dev = { +		.platform_data	= &simone_flash_data, +	}, +}; + +static struct ep93xx_eth_data simone_eth_data = { +	.phy_id		= 1, +}; + +static struct ep93xxfb_mach_info simone_fb_info = { +	.num_modes	= EP93XXFB_USE_MODEDB, +	.bpp		= 16, +	.flags		= EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, +}; + +static struct i2c_gpio_platform_data simone_i2c_gpio_data = { +	.sda_pin		= EP93XX_GPIO_LINE_EEDAT, +	.sda_is_open_drain	= 0, +	.scl_pin		= EP93XX_GPIO_LINE_EECLK, +	.scl_is_open_drain	= 0, +	.udelay			= 0, +	.timeout		= 0, +}; + +static struct i2c_board_info __initdata simone_i2c_board_info[] = { +	{ +		I2C_BOARD_INFO("ds1337", 0x68), +	}, +}; + +static void __init simone_init_machine(void) +{ +	ep93xx_init_devices(); + +	platform_device_register(&simone_flash); +	ep93xx_register_eth(&simone_eth_data, 1); +	ep93xx_register_fb(&simone_fb_info); +	ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, +			    ARRAY_SIZE(simone_i2c_board_info)); +} + +MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") +/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */ +	.phys_io	= EP93XX_APB_PHYS_BASE, +	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, +	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100, +	.map_io		= ep93xx_map_io, +	.init_irq	= ep93xx_init_irq, +	.timer		= &ep93xx_timer, +	.init_machine	= simone_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c new file mode 100644 index 00000000000..51134b0382c --- /dev/null +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -0,0 +1,172 @@ +/* + * arch/arm/mach-ep93xx/snappercl15.c + * Bluewater Systems Snapper CL15 system module + * + * Copyright (C) 2009 Bluewater Systems Ltd + * Author: Ryan Mallon <ryan@bluewatersys.com> + * + * NAND code adapted from driver by: + *   Andre Renaud <andre@bluewatersys.com> + *   James R. McKaskill + * + * 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/platform_device.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/i2c-gpio.h> +#include <linux/fb.h> + +#include <linux/mtd/partitions.h> +#include <linux/mtd/nand.h> + +#include <mach/hardware.h> +#include <mach/fb.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +#define SNAPPERCL15_NAND_BASE	(EP93XX_CS7_PHYS_BASE + SZ_16M) + +#define SNAPPERCL15_NAND_WPN	(1 << 8)  /* Write protect (active low) */ +#define SNAPPERCL15_NAND_ALE	(1 << 9)  /* Address latch */ +#define SNAPPERCL15_NAND_CLE	(1 << 10) /* Command latch */ +#define SNAPPERCL15_NAND_CEN	(1 << 11) /* Chip enable (active low) */ +#define SNAPPERCL15_NAND_RDY	(1 << 14) /* Device ready */ + +#define NAND_CTRL_ADDR(chip) 	(chip->IO_ADDR_W + 0x40) + +static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +				      unsigned int ctrl) +{ +	struct nand_chip *chip = mtd->priv; +	static u16 nand_state = SNAPPERCL15_NAND_WPN; +	u16 set; + +	if (ctrl & NAND_CTRL_CHANGE) { +		set = SNAPPERCL15_NAND_CEN | SNAPPERCL15_NAND_WPN; + +		if (ctrl & NAND_NCE) +			set &= ~SNAPPERCL15_NAND_CEN; +		if (ctrl & NAND_CLE) +			set |= SNAPPERCL15_NAND_CLE; +		if (ctrl & NAND_ALE) +			set |= SNAPPERCL15_NAND_ALE; + +		nand_state &= ~(SNAPPERCL15_NAND_CEN | +				SNAPPERCL15_NAND_CLE | +				SNAPPERCL15_NAND_ALE); +		nand_state |= set; +		__raw_writew(nand_state, NAND_CTRL_ADDR(chip)); +	} + +	if (cmd != NAND_CMD_NONE) +		__raw_writew((cmd & 0xff) | nand_state, chip->IO_ADDR_W); +} + +static int snappercl15_nand_dev_ready(struct mtd_info *mtd) +{ +	struct nand_chip *chip = mtd->priv; + +	return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY); +} + +static const char *snappercl15_nand_part_probes[] = {"cmdlinepart", NULL}; + +static struct mtd_partition snappercl15_nand_parts[] = { +	{ +		.name		= "Kernel", +		.offset		= 0, +		.size		= SZ_2M, +	}, +	{ +		.name		= "Filesystem", +		.offset		= MTDPART_OFS_APPEND, +		.size		= MTDPART_SIZ_FULL, +	}, +}; + +static struct platform_nand_data snappercl15_nand_data = { +	.chip = { +		.nr_chips		= 1, +		.part_probe_types	= snappercl15_nand_part_probes, +		.partitions		= snappercl15_nand_parts, +		.nr_partitions		= ARRAY_SIZE(snappercl15_nand_parts), +		.options		= NAND_NO_AUTOINCR, +		.chip_delay		= 25, +	}, +	.ctrl = { +		.dev_ready		= snappercl15_nand_dev_ready, +		.cmd_ctrl		= snappercl15_nand_cmd_ctrl, +	}, +}; + +static struct resource snappercl15_nand_resource[] = { +	{ +		.start		= SNAPPERCL15_NAND_BASE, +		.end		= SNAPPERCL15_NAND_BASE + SZ_4K - 1, +		.flags		= IORESOURCE_MEM, +	}, +}; + +static struct platform_device snappercl15_nand_device = { +	.name			= "gen_nand", +	.id			= -1, +	.dev.platform_data	= &snappercl15_nand_data, +	.resource		= snappercl15_nand_resource, +	.num_resources		= ARRAY_SIZE(snappercl15_nand_resource), +}; + +static struct ep93xx_eth_data snappercl15_eth_data = { +	.phy_id			= 1, +}; + +static struct i2c_gpio_platform_data snappercl15_i2c_gpio_data = { +	.sda_pin		= EP93XX_GPIO_LINE_EEDAT, +	.sda_is_open_drain	= 0, +	.scl_pin		= EP93XX_GPIO_LINE_EECLK, +	.scl_is_open_drain	= 0, +	.udelay			= 0, +	.timeout		= 0, +}; + +static struct i2c_board_info __initdata snappercl15_i2c_data[] = { +	{ +		/* Audio codec */ +		I2C_BOARD_INFO("tlv320aic23", 0x1a), +	}, +}; + +static struct ep93xxfb_mach_info snappercl15_fb_info = { +	.num_modes		= EP93XXFB_USE_MODEDB, +	.bpp			= 16, +}; + +static void __init snappercl15_init_machine(void) +{ +	ep93xx_init_devices(); +	ep93xx_register_eth(&snappercl15_eth_data, 1); +	ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data, +			    ARRAY_SIZE(snappercl15_i2c_data)); +	ep93xx_register_fb(&snappercl15_fb_info); +	platform_device_register(&snappercl15_nand_device); +} + +MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15") +	/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */ +	.phys_io	= EP93XX_APB_PHYS_BASE, +	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, +	.boot_params	= EP93XX_SDCE0_PHYS_BASE + 0x100, +	.map_io		= ep93xx_map_io, +	.init_irq	= ep93xx_init_irq, +	.timer 		= &ep93xx_timer, +	.init_machine	= snappercl15_init_machine, +MACHINE_END diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index 41febc796b1..e3bc3f6f6b1 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c @@ -32,12 +32,13 @@ unsigned int mem_fclk_21285 = 50000000;  EXPORT_SYMBOL(mem_fclk_21285); -static void __init early_fclk(char **arg) +static int __init early_fclk(char *arg)  { -	mem_fclk_21285 = simple_strtoul(*arg, arg, 0); +	mem_fclk_21285 = simple_strtoul(arg, NULL, 0); +	return 0;  } -__early_param("mem_fclk_21285=", early_fclk); +early_param("mem_fclk_21285", early_fclk);  static int __init parse_tag_memclk(const struct tag *tag)  { diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S index 4329b812357..60dda1318f2 100644 --- a/arch/arm/mach-footbridge/include/mach/debug-macro.S +++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S @@ -15,7 +15,7 @@  #ifndef CONFIG_DEBUG_DC21285_PORT  	/* For NetWinder debugging */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x7c000000	@ physical @@ -32,7 +32,7 @@  		.equ	dc21285_high, ARMCSR_BASE & 0xff000000  		.equ	dc21285_low,  ARMCSR_BASE & 0x00ffffff -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x42000000 diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S index d04a6eaeae1..ad477047069 100644 --- a/arch/arm/mach-gemini/include/mach/debug-macro.S +++ b/arch/arm/mach-gemini/include/mach/debug-macro.S @@ -11,7 +11,7 @@   */  #include <mach/hardware.h> -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1					@ MMU enabled?  	ldreq	\rx, =GEMINI_UART_BASE			@ physical diff --git a/arch/arm/mach-gemini/include/mach/vmalloc.h b/arch/arm/mach-gemini/include/mach/vmalloc.h index 83e536d9436..45371eb86fc 100644 --- a/arch/arm/mach-gemini/include/mach/vmalloc.h +++ b/arch/arm/mach-gemini/include/mach/vmalloc.h @@ -7,4 +7,4 @@   * (at your option) any later version.   */ -#define VMALLOC_END	0xF0000000 +#define VMALLOC_END	0xf0000000UL diff --git a/arch/arm/mach-h720x/include/mach/debug-macro.S b/arch/arm/mach-h720x/include/mach/debug-macro.S index 6294a1344dd..a9ee8f0d48b 100644 --- a/arch/arm/mach-h720x/include/mach/debug-macro.S +++ b/arch/arm/mach-h720x/include/mach/debug-macro.S @@ -14,7 +14,7 @@  		.equ    io_virt, IO_BASE  		.equ    io_phys, IO_START -		.macro  addruart,rx +		.macro  addruart, rx, tmp  		mrc     p15, 0, \rx, c1, c0  		tst     \rx, #1  	       @ MMU enabled?  		moveq   \rx, #io_phys	       @ physical base address diff --git a/arch/arm/mach-integrator/include/mach/debug-macro.S b/arch/arm/mach-integrator/include/mach/debug-macro.S index d347d659ea3..87a6888ae01 100644 --- a/arch/arm/mach-integrator/include/mach/debug-macro.S +++ b/arch/arm/mach-integrator/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x16000000	@ physical base address diff --git a/arch/arm/mach-iop13xx/include/mach/debug-macro.S b/arch/arm/mach-iop13xx/include/mach/debug-macro.S index 9037d2e8557..c9d6ba46963 100644 --- a/arch/arm/mach-iop13xx/include/mach/debug-macro.S +++ b/arch/arm/mach-iop13xx/include/mach/debug-macro.S @@ -11,7 +11,7 @@   * published by the Free Software Foundation.   */ -	.macro	addruart, rx +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1			@ mmu enabled?  	moveq	\rx, #0xff000000	@ physical diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c index 52958099781..48642e66c56 100644 --- a/arch/arm/mach-iop13xx/io.c +++ b/arch/arm/mach-iop13xx/io.c @@ -61,9 +61,9 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,  			         (cookie - IOP13XX_PCIE_LOWER_MEM_RA));  		break;  	case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA: -		retval = __arm_ioremap(IOP13XX_PBI_LOWER_MEM_PA + +		retval = __arm_ioremap_caller(IOP13XX_PBI_LOWER_MEM_PA +  				       (cookie - IOP13XX_PBI_LOWER_MEM_RA), -				       size, mtype); +				       size, mtype, __builtin_return_address(0));  		break;  	case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:  		retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie); @@ -75,7 +75,8 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,  		retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);  		break;  	default: -		retval = __arm_ioremap(cookie, size, mtype); +		retval = __arm_ioremap_caller(cookie, size, mtype, +				__builtin_return_address(0));  	}  	return retval; diff --git a/arch/arm/mach-iop32x/include/mach/debug-macro.S b/arch/arm/mach-iop32x/include/mach/debug-macro.S index 58b01664ffb..736afe1edd1 100644 --- a/arch/arm/mach-iop32x/include/mach/debug-macro.S +++ b/arch/arm/mach-iop32x/include/mach/debug-macro.S @@ -11,7 +11,7 @@   * published by the Free Software Foundation.   */ -		.macro	addruart, rx +		.macro	addruart, rx, tmp  		mov	\rx, #0xfe000000	@ physical as well as virtual  		orr	\rx, \rx, #0x00800000	@ location of the UART  		.endm diff --git a/arch/arm/mach-iop32x/include/mach/vmalloc.h b/arch/arm/mach-iop32x/include/mach/vmalloc.h index 85ceb09d85f..c4862d48e58 100644 --- a/arch/arm/mach-iop32x/include/mach/vmalloc.h +++ b/arch/arm/mach-iop32x/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-iop32x/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfe000000 +#define VMALLOC_END	0xfe000000UL diff --git a/arch/arm/mach-iop33x/include/mach/debug-macro.S b/arch/arm/mach-iop33x/include/mach/debug-macro.S index a60c9ef05cc..addb2da7842 100644 --- a/arch/arm/mach-iop33x/include/mach/debug-macro.S +++ b/arch/arm/mach-iop33x/include/mach/debug-macro.S @@ -11,7 +11,7 @@   * published by the Free Software Foundation.   */ -		.macro	addruart, rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ mmu enabled?  		moveq	\rx, #0xff000000	@ physical diff --git a/arch/arm/mach-iop33x/include/mach/vmalloc.h b/arch/arm/mach-iop33x/include/mach/vmalloc.h index f9f99dea9bc..48331dc2370 100644 --- a/arch/arm/mach-iop33x/include/mach/vmalloc.h +++ b/arch/arm/mach-iop33x/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-iop33x/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfe000000 +#define VMALLOC_END	0xfe000000UL diff --git a/arch/arm/mach-ixp2000/include/mach/debug-macro.S b/arch/arm/mach-ixp2000/include/mach/debug-macro.S index 904ff56d224..6a827681680 100644 --- a/arch/arm/mach-ixp2000/include/mach/debug-macro.S +++ b/arch/arm/mach-ixp2000/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro  addruart,rx +		.macro  addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0xc0000000	@ Physical base diff --git a/arch/arm/mach-ixp2000/include/mach/vmalloc.h b/arch/arm/mach-ixp2000/include/mach/vmalloc.h index d195e35aed3..61c8dae24f9 100644 --- a/arch/arm/mach-ixp2000/include/mach/vmalloc.h +++ b/arch/arm/mach-ixp2000/include/mach/vmalloc.h @@ -17,4 +17,4 @@   * The vmalloc() routines leaves a hole of 4kB between each vmalloced   * area for the same reason. ;)   */ -#define VMALLOC_END	    0xfb000000 +#define VMALLOC_END	    0xfb000000UL diff --git a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S index 905db318872..a82e375465e 100644 --- a/arch/arm/mach-ixp23xx/include/mach/debug-macro.S +++ b/arch/arm/mach-ixp23xx/include/mach/debug-macro.S @@ -12,7 +12,7 @@   */  #include <mach/ixp23xx.h> -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1				@ mmu enabled?  		ldreq	\rx, =IXP23XX_PERIPHERAL_PHYS 	@ physical diff --git a/arch/arm/mach-ixp23xx/include/mach/vmalloc.h b/arch/arm/mach-ixp23xx/include/mach/vmalloc.h index dd519f678d1..896c56a1c00 100644 --- a/arch/arm/mach-ixp23xx/include/mach/vmalloc.h +++ b/arch/arm/mach-ixp23xx/include/mach/vmalloc.h @@ -7,4 +7,4 @@   * specific static I/O.   */ -#define VMALLOC_END	(0xec000000) +#define VMALLOC_END	(0xec000000UL) diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 3bbf40f6d96..71728d36d50 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -427,6 +427,17 @@ static void __init ixp4xx_clocksource_init(void)  }  /* + * sched_clock() + */ +unsigned long long sched_clock(void) +{ +	cycle_t cyc = ixp4xx_get_cycles(NULL); +	struct clocksource *cs = &clocksource_ixp4xx; + +	return clocksource_cyc2ns(cyc, cs->mult, cs->shift); +} + +/*   * clockevents   */  static int ixp4xx_set_next_event(unsigned long evt, diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S index 7c6a6912acd..893873eb2a0 100644 --- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S +++ b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S @@ -10,7 +10,7 @@   * published by the Free Software Foundation.  */ -                .macro  addruart,rx +                .macro  addruart, rx, tmp                  mrc     p15, 0, \rx, c1, c0                  tst     \rx, #1                 @ MMU enabled?                  moveq   \rx, #0xc8000000 diff --git a/arch/arm/mach-ixp4xx/include/mach/vmalloc.h b/arch/arm/mach-ixp4xx/include/mach/vmalloc.h index 7b3580b53ad..9bcd64d5985 100644 --- a/arch/arm/mach-ixp4xx/include/mach/vmalloc.h +++ b/arch/arm/mach-ixp4xx/include/mach/vmalloc.h @@ -1,5 +1,5 @@  /*   * arch/arm/mach-ixp4xx/include/mach/vmalloc.h   */ -#define VMALLOC_END       (0xFF000000) +#define VMALLOC_END       (0xff000000UL) diff --git a/arch/arm/mach-kirkwood/include/mach/debug-macro.S b/arch/arm/mach-kirkwood/include/mach/debug-macro.S index a4a55c199d7..d0606774dea 100644 --- a/arch/arm/mach-kirkwood/include/mach/debug-macro.S +++ b/arch/arm/mach-kirkwood/include/mach/debug-macro.S @@ -8,7 +8,7 @@  #include <mach/bridge-regs.h> -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1					@ MMU enabled?  	ldreq	\rx, =KIRKWOOD_REGS_PHYS_BASE diff --git a/arch/arm/mach-kirkwood/include/mach/vmalloc.h b/arch/arm/mach-kirkwood/include/mach/vmalloc.h index 8f48260dcda..bf162ca3d2c 100644 --- a/arch/arm/mach-kirkwood/include/mach/vmalloc.h +++ b/arch/arm/mach-kirkwood/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-kirkwood/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfe800000 +#define VMALLOC_END	0xfe800000UL diff --git a/arch/arm/mach-ks8695/include/mach/debug-macro.S b/arch/arm/mach-ks8695/include/mach/debug-macro.S index 3782c355949..cf2095da237 100644 --- a/arch/arm/mach-ks8695/include/mach/debug-macro.S +++ b/arch/arm/mach-ks8695/include/mach/debug-macro.S @@ -14,7 +14,7 @@  #include <mach/hardware.h>  #include <mach/regs-uart.h> -	.macro	addruart, rx +	.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1				@ MMU enabled?  		ldreq	\rx, =KS8695_UART_PA		@ physical base address diff --git a/arch/arm/mach-l7200/include/mach/debug-macro.S b/arch/arm/mach-l7200/include/mach/debug-macro.S index 34eed2a63e6..b69ed344c7c 100644 --- a/arch/arm/mach-l7200/include/mach/debug-macro.S +++ b/arch/arm/mach-l7200/include/mach/debug-macro.S @@ -14,7 +14,7 @@  		.equ	io_virt, IO_BASE  		.equ	io_phys, IO_START -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #io_phys		@ physical base address diff --git a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S b/arch/arm/mach-lh7a40x/include/mach/debug-macro.S index 85141ed5383..c0dcbbba22b 100644 --- a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S +++ b/arch/arm/mach-lh7a40x/include/mach/debug-macro.S @@ -14,7 +14,7 @@  	@ It is not known if this will be appropriate for every 40x  	@ board. -		.macro  addruart,rx +		.macro  addruart, rx, tmp  		mrc     p15, 0, \rx, c1, c0  		tst     \rx, #1                 @ MMU enabled?  		mov     \rx, #0x00000700        @ offset from base diff --git a/arch/arm/mach-lh7a40x/include/mach/vmalloc.h b/arch/arm/mach-lh7a40x/include/mach/vmalloc.h index 3fbd49490bb..d62da7358b1 100644 --- a/arch/arm/mach-lh7a40x/include/mach/vmalloc.h +++ b/arch/arm/mach-lh7a40x/include/mach/vmalloc.h @@ -7,4 +7,4 @@   *  version 2 as published by the Free Software Foundation.   *   */ -#define VMALLOC_END       (0xe8000000) +#define VMALLOC_END       (0xe8000000UL) diff --git a/arch/arm/mach-loki/include/mach/debug-macro.S b/arch/arm/mach-loki/include/mach/debug-macro.S index a8c20bd2f95..3136c913a92 100644 --- a/arch/arm/mach-loki/include/mach/debug-macro.S +++ b/arch/arm/mach-loki/include/mach/debug-macro.S @@ -8,7 +8,7 @@  #include <mach/loki.h> -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1					@ MMU enabled?  	ldreq	\rx, =LOKI_REGS_PHYS_BASE diff --git a/arch/arm/mach-loki/include/mach/vmalloc.h b/arch/arm/mach-loki/include/mach/vmalloc.h index 8dc3bfcbf9f..5dcbd865443 100644 --- a/arch/arm/mach-loki/include/mach/vmalloc.h +++ b/arch/arm/mach-loki/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-loki/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfe800000 +#define VMALLOC_END	0xfe800000UL diff --git a/arch/arm/mach-mmp/include/mach/debug-macro.S b/arch/arm/mach-mmp/include/mach/debug-macro.S index a850f87de51..76deff238e1 100644 --- a/arch/arm/mach-mmp/include/mach/debug-macro.S +++ b/arch/arm/mach-mmp/include/mach/debug-macro.S @@ -11,7 +11,7 @@  #include <mach/addr-map.h> -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1				@ MMU enabled?  		ldreq	\rx, =APB_PHYS_BASE		@ physical diff --git a/arch/arm/mach-mmp/include/mach/vmalloc.h b/arch/arm/mach-mmp/include/mach/vmalloc.h index b60ccaf9fee..1d0bac003ad 100644 --- a/arch/arm/mach-mmp/include/mach/vmalloc.h +++ b/arch/arm/mach-mmp/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * linux/arch/arm/mach-mmp/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfe000000 +#define VMALLOC_END	0xfe000000UL diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S index d48747ebcd3..528750f307e 100644 --- a/arch/arm/mach-msm/include/mach/debug-macro.S +++ b/arch/arm/mach-msm/include/mach/debug-macro.S @@ -20,7 +20,7 @@  #include <mach/msm_iomap.h>  #ifdef CONFIG_MSM_DEBUG_UART -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	@ see if the MMU is enabled and select appropriate base address  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1 @@ -40,7 +40,7 @@  	beq	1001b  	.endm  #else -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	.endm  	.macro	senduart,rd,rx diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c index 1c5e7dac086..05f96b780aa 100644 --- a/arch/arm/mach-msm/io.c +++ b/arch/arm/mach-msm/io.c @@ -76,5 +76,6 @@ __msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)  			mtype = MT_DEVICE_NONSHARED;  	} -	return __arm_ioremap(phys_addr, size, mtype); +	return __arm_ioremap_caller(phys_addr, size, mtype, +		__builtin_return_address(0));  } diff --git a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S index a06442fbd34..cd81689c462 100644 --- a/arch/arm/mach-mv78xx0/include/mach/debug-macro.S +++ b/arch/arm/mach-mv78xx0/include/mach/debug-macro.S @@ -8,7 +8,7 @@  #include <mach/mv78xx0.h> -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1					@ MMU enabled?  	ldreq	\rx, =MV78XX0_REGS_PHYS_BASE diff --git a/arch/arm/mach-mv78xx0/include/mach/vmalloc.h b/arch/arm/mach-mv78xx0/include/mach/vmalloc.h index 1c4954386a8..ba26fe98e64 100644 --- a/arch/arm/mach-mv78xx0/include/mach/vmalloc.h +++ b/arch/arm/mach-mv78xx0/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-mv78xx0/include/mach/vmalloc.h   */ -#define VMALLOC_END	0xfe000000 +#define VMALLOC_END	0xfe000000UL diff --git a/arch/arm/mach-netx/include/mach/debug-macro.S b/arch/arm/mach-netx/include/mach/debug-macro.S index 11b9d5b4639..e96339e71d8 100644 --- a/arch/arm/mach-netx/include/mach/debug-macro.S +++ b/arch/arm/mach-netx/include/mach/debug-macro.S @@ -13,7 +13,7 @@  #include "hardware.h" -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x00100000		@ physical diff --git a/arch/arm/mach-nomadik/include/mach/debug-macro.S b/arch/arm/mach-nomadik/include/mach/debug-macro.S index e876990e156..4f92acfba95 100644 --- a/arch/arm/mach-nomadik/include/mach/debug-macro.S +++ b/arch/arm/mach-nomadik/include/mach/debug-macro.S @@ -10,7 +10,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x10000000	@ physical base address diff --git a/arch/arm/mach-nomadik/include/mach/vmalloc.h b/arch/arm/mach-nomadik/include/mach/vmalloc.h index be12e31ea52..f83d574d944 100644 --- a/arch/arm/mach-nomadik/include/mach/vmalloc.h +++ b/arch/arm/mach-nomadik/include/mach/vmalloc.h @@ -1,2 +1,2 @@ -#define VMALLOC_END       0xe8000000 +#define VMALLOC_END       0xe8000000UL diff --git a/arch/arm/mach-ns9xxx/include/mach/debug-macro.S b/arch/arm/mach-ns9xxx/include/mach/debug-macro.S index c9530fba00a..0859336a8e6 100644 --- a/arch/arm/mach-ns9xxx/include/mach/debug-macro.S +++ b/arch/arm/mach-ns9xxx/include/mach/debug-macro.S @@ -11,7 +11,7 @@  #include <mach/regs-board-a9m9750dev.h> -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1  		ldreq	\rx, =NS9XXX_CSxSTAT_PHYS(0) diff --git a/arch/arm/mach-ns9xxx/include/mach/vmalloc.h b/arch/arm/mach-ns9xxx/include/mach/vmalloc.h index fe964d3bcc4..c8651974c4b 100644 --- a/arch/arm/mach-ns9xxx/include/mach/vmalloc.h +++ b/arch/arm/mach-ns9xxx/include/mach/vmalloc.h @@ -11,6 +11,6 @@  #ifndef __ASM_ARCH_VMALLOC_H  #define __ASM_ARCH_VMALLOC_H -#define VMALLOC_END     (0xf0000000) +#define VMALLOC_END     (0xf0000000UL)  #endif /* ifndef __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-nuc93x/Kconfig b/arch/arm/mach-nuc93x/Kconfig new file mode 100644 index 00000000000..2bc40a280fa --- /dev/null +++ b/arch/arm/mach-nuc93x/Kconfig @@ -0,0 +1,19 @@ +if ARCH_NUC93X + +config CPU_NUC932 +	bool +	help +	  Support for NUC932 of Nuvoton NUC93X CPUs. + +menu "NUC932 Machines" + +config MACH_NUC932EVB +	bool "Nuvoton NUC932 Evaluation Board" +	default y +	select CPU_NUC932 +	help +	   Say Y here if you are using the Nuvoton NUC932EVB + +endmenu + +endif diff --git a/arch/arm/mach-nuc93x/Makefile b/arch/arm/mach-nuc93x/Makefile new file mode 100644 index 00000000000..440e2dec6c8 --- /dev/null +++ b/arch/arm/mach-nuc93x/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y				:= irq.o time.o dev.o cpu.o clock.o +# NUC932 CPU support files + +obj-$(CONFIG_CPU_NUC932)	+= nuc932.o + +# machine support + +obj-$(CONFIG_MACH_NUC932EVB)	+= mach-nuc932evb.o diff --git a/arch/arm/mach-nuc93x/Makefile.boot b/arch/arm/mach-nuc93x/Makefile.boot new file mode 100644 index 00000000000..a057b546b6e --- /dev/null +++ b/arch/arm/mach-nuc93x/Makefile.boot @@ -0,0 +1,3 @@ +zreladdr-y	:= 0x00008000 +params_phys-y	:= 0x00000100 + diff --git a/arch/arm/mach-nuc93x/clock.c b/arch/arm/mach-nuc93x/clock.c new file mode 100644 index 00000000000..0521efbc48c --- /dev/null +++ b/arch/arm/mach-nuc93x/clock.c @@ -0,0 +1,83 @@ +/* + * linux/arch/arm/mach-nuc93x/clock.c + * + * Copyright (c) 2008 Nuvoton technology corporation + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/clk.h> +#include <linux/spinlock.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <mach/hardware.h> + +#include "clock.h" + +static DEFINE_SPINLOCK(clocks_lock); + +int clk_enable(struct clk *clk) +{ +	unsigned long flags; + +	spin_lock_irqsave(&clocks_lock, flags); +	if (clk->enabled++ == 0) +		(clk->enable)(clk, 1); +	spin_unlock_irqrestore(&clocks_lock, flags); + +	return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +	unsigned long flags; + +	WARN_ON(clk->enabled == 0); + +	spin_lock_irqsave(&clocks_lock, flags); +	if (--clk->enabled == 0) +		(clk->enable)(clk, 0); +	spin_unlock_irqrestore(&clocks_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ +	return 27000000; +} +EXPORT_SYMBOL(clk_get_rate); + +void nuc93x_clk_enable(struct clk *clk, int enable) +{ +	unsigned int clocks = clk->cken; +	unsigned long clken; + +	clken = __raw_readl(NUC93X_VA_CLKPWR); + +	if (enable) +		clken |= clocks; +	else +		clken &= ~clocks; + +	__raw_writel(clken, NUC93X_VA_CLKPWR); +} + +void clks_register(struct clk_lookup *clks, size_t num) +{ +	int i; + +	for (i = 0; i < num; i++) +		clkdev_add(&clks[i]); +} diff --git a/arch/arm/mach-nuc93x/clock.h b/arch/arm/mach-nuc93x/clock.h new file mode 100644 index 00000000000..18e51be4816 --- /dev/null +++ b/arch/arm/mach-nuc93x/clock.h @@ -0,0 +1,36 @@ +/* + * linux/arch/arm/mach-nuc93x/clock.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + */ + +#include <asm/clkdev.h> + +void nuc93x_clk_enable(struct clk *clk, int enable); +void clks_register(struct clk_lookup *clks, size_t num); + +struct clk { +	unsigned long		cken; +	unsigned int		enabled; +	void			(*enable)(struct clk *, int enable); +}; + +#define DEFINE_CLK(_name, _ctrlbit)			\ +struct clk clk_##_name = {				\ +		.enable	= nuc93x_clk_enable,		\ +		.cken	= (1 << _ctrlbit),		\ +	} + +#define DEF_CLKLOOK(_clk, _devname, _conname)		\ +	{						\ +		.clk		= _clk,			\ +		.dev_id		= _devname,		\ +		.con_id		= _conname,		\ +	} + diff --git a/arch/arm/mach-nuc93x/cpu.c b/arch/arm/mach-nuc93x/cpu.c new file mode 100644 index 00000000000..f6ff5d87354 --- /dev/null +++ b/arch/arm/mach-nuc93x/cpu.c @@ -0,0 +1,135 @@ +/* + * linux/arch/arm/mach-nuc93x/cpu.c + * + * Copyright (c) 2009 Nuvoton corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * NUC93x series cpu common support + * + * 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;version 2 of the License. + * + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/serial_8250.h> +#include <linux/delay.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/irq.h> + +#include <mach/hardware.h> +#include <mach/regs-serial.h> +#include <mach/regs-clock.h> +#include <mach/regs-ebi.h> + +#include "cpu.h" +#include "clock.h" + +/* Initial IO mappings */ + +static struct map_desc nuc93x_iodesc[] __initdata = { +	IODESC_ENT(IRQ), +	IODESC_ENT(GCR), +	IODESC_ENT(UART), +	IODESC_ENT(TIMER), +	IODESC_ENT(EBI), +}; + +/* Initial nuc932 clock declarations. */ +static DEFINE_CLK(audio, 2); +static DEFINE_CLK(sd, 3); +static DEFINE_CLK(jpg, 4); +static DEFINE_CLK(video, 5); +static DEFINE_CLK(vpost, 6); +static DEFINE_CLK(2d, 7); +static DEFINE_CLK(gpu, 8); +static DEFINE_CLK(gdma, 9); +static DEFINE_CLK(adc, 10); +static DEFINE_CLK(uart, 11); +static DEFINE_CLK(spi, 12); +static DEFINE_CLK(pwm, 13); +static DEFINE_CLK(timer, 14); +static DEFINE_CLK(wdt, 15); +static DEFINE_CLK(ac97, 16); +static DEFINE_CLK(i2s, 16); +static DEFINE_CLK(usbck, 17); +static DEFINE_CLK(usb48, 18); +static DEFINE_CLK(usbh, 19); +static DEFINE_CLK(i2c, 20); +static DEFINE_CLK(ext, 0); + +static struct clk_lookup nuc932_clkregs[] = { +       DEF_CLKLOOK(&clk_audio, "nuc932-audio", NULL), +       DEF_CLKLOOK(&clk_sd, "nuc932-sd", NULL), +       DEF_CLKLOOK(&clk_jpg, "nuc932-jpg", "NULL"), +       DEF_CLKLOOK(&clk_video, "nuc932-video", "NULL"), +       DEF_CLKLOOK(&clk_vpost, "nuc932-vpost", NULL), +       DEF_CLKLOOK(&clk_2d, "nuc932-2d", NULL), +       DEF_CLKLOOK(&clk_gpu, "nuc932-gpu", NULL), +       DEF_CLKLOOK(&clk_gdma, "nuc932-gdma", "NULL"), +       DEF_CLKLOOK(&clk_adc, "nuc932-adc", NULL), +       DEF_CLKLOOK(&clk_uart, NULL, "uart"), +       DEF_CLKLOOK(&clk_spi, "nuc932-spi", NULL), +       DEF_CLKLOOK(&clk_pwm, "nuc932-pwm", NULL), +       DEF_CLKLOOK(&clk_timer, NULL, "timer"), +       DEF_CLKLOOK(&clk_wdt, "nuc932-wdt", NULL), +       DEF_CLKLOOK(&clk_ac97, "nuc932-ac97", NULL), +       DEF_CLKLOOK(&clk_i2s, "nuc932-i2s", NULL), +       DEF_CLKLOOK(&clk_usbck, "nuc932-usbck", NULL), +       DEF_CLKLOOK(&clk_usb48, "nuc932-usb48", NULL), +       DEF_CLKLOOK(&clk_usbh, "nuc932-usbh", NULL), +       DEF_CLKLOOK(&clk_i2c, "nuc932-i2c", NULL), +       DEF_CLKLOOK(&clk_ext, NULL, "ext"), +}; + +/* Initial serial platform data */ + +struct plat_serial8250_port nuc93x_uart_data[] = { +	NUC93X_8250PORT(UART0), +	{}, +}; + +struct platform_device nuc93x_serial_device = { +	.name			= "serial8250", +	.id			= PLAT8250_DEV_PLATFORM, +	.dev			= { +		.platform_data	= nuc93x_uart_data, +	}, +}; + +/*Init NUC93x evb io*/ + +void __init nuc93x_map_io(struct map_desc *mach_desc, int mach_size) +{ +	unsigned long idcode = 0x0; + +	iotable_init(mach_desc, mach_size); +	iotable_init(nuc93x_iodesc, ARRAY_SIZE(nuc93x_iodesc)); + +	idcode = __raw_readl(NUC93XPDID); +	if (idcode == NUC932_CPUID) +		printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode); +	else +		printk(KERN_ERR "CPU type detect error!\n"); + +} + +/*Init NUC93x clock*/ + +void __init nuc93x_init_clocks(void) +{ +	clks_register(nuc932_clkregs, ARRAY_SIZE(nuc932_clkregs)); +} + diff --git a/arch/arm/mach-nuc93x/cpu.h b/arch/arm/mach-nuc93x/cpu.h new file mode 100644 index 00000000000..9def28197bc --- /dev/null +++ b/arch/arm/mach-nuc93x/cpu.h @@ -0,0 +1,48 @@ +/* + * arch/arm/mach-nuc93x/cpu.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Header file for NUC93X CPU support + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define IODESC_ENT(y)					\ +{							\ +	.virtual = (unsigned long)NUC93X_VA_##y,	\ +	.pfn     = __phys_to_pfn(NUC93X_PA_##y),	\ +	.length  = NUC93X_SZ_##y,			\ +	.type    = MT_DEVICE,				\ +} + +#define NUC93X_8250PORT(name)					\ +{								\ +	.membase	= name##_BA,				\ +	.mapbase	= name##_PA,				\ +	.irq		= IRQ_##name,				\ +	.uartclk	= 57139200,				\ +	.regshift	= 2,					\ +	.iotype		= UPIO_MEM,				\ +	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\ +} + +/*Cpu identifier register*/ + +#define NUC93XPDID	NUC93X_VA_GCR +#define NUC932_CPUID	0x29550091 + +/* extern file from cpu.c */ + +extern void nuc93x_clock_source(struct device *dev, unsigned char *src); +extern void nuc93x_init_clocks(void); +extern void nuc93x_map_io(struct map_desc *mach_desc, int mach_size); +extern void nuc93x_board_init(struct platform_device **device, int size); +extern struct platform_device nuc93x_serial_device; + diff --git a/arch/arm/mach-nuc93x/dev.c b/arch/arm/mach-nuc93x/dev.c new file mode 100644 index 00000000000..a962ae9578d --- /dev/null +++ b/arch/arm/mach-nuc93x/dev.c @@ -0,0 +1,42 @@ +/* + * linux/arch/arm/mach-nuc93x/dev.c + * + * Copyright (C) 2009 Nuvoton corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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;version 2 of the License. + * + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/mach-types.h> + +#include "cpu.h" + +/*Here should be your evb resourse,such as LCD*/ + +static struct platform_device *nuc93x_public_dev[] __initdata = { +	&nuc93x_serial_device, +}; + +/* Provide adding specific CPU platform devices API */ + +void __init nuc93x_board_init(struct platform_device **device, int size) +{ +	platform_add_devices(device, size); +	platform_add_devices(nuc93x_public_dev, ARRAY_SIZE(nuc93x_public_dev)); +} + diff --git a/arch/arm/mach-nuc93x/include/mach/clkdev.h b/arch/arm/mach-nuc93x/include/mach/clkdev.h new file mode 100644 index 00000000000..04b37a89801 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-nuc93x/include/mach/entry-macro.S b/arch/arm/mach-nuc93x/include/mach/entry-macro.S new file mode 100644 index 00000000000..1352cbda379 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/entry-macro.S @@ -0,0 +1,32 @@ +/* + * arch/arm/mach-nuc93x/include/mach/entry-macro.S + * + * This file is licensed under  the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + */ + +#include <mach/hardware.h> +#include <mach/regs-irq.h> + +	.macro  get_irqnr_preamble, base, tmp +	.endm + +	.macro  arch_ret_to_user, tmp1, tmp2 +	.endm + +	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp + +		mov	\base, #AIC_BA + +		ldr	\irqnr, [ \base, #AIC_IPER] +		ldr	\irqnr, [ \base, #AIC_ISNR] +		cmp	\irqnr, #0 + +	.endm + +	/* currently don't need an disable_fiq macro */ + +	.macro	disable_fiq +	.endm diff --git a/arch/arm/mach-nuc93x/include/mach/hardware.h b/arch/arm/mach-nuc93x/include/mach/hardware.h new file mode 100644 index 00000000000..fb5c6fcb142 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/hardware.h @@ -0,0 +1,22 @@ +/* + * arch/arm/mach-nuc93x/include/mach/hardware.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + * + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include <asm/sizes.h> +#include <mach/map.h> + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/io.h b/arch/arm/mach-nuc93x/include/mach/io.h new file mode 100644 index 00000000000..72e5051c753 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/io.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-nuc93x/include/mach/io.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + * + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT	0xffffffff + +/* + * 1:1 mapping for ioremapped regions. + */ + +#define __mem_pci(a)	(a) +#define __io(a)		__typesafe_io(a) + +#endif diff --git a/arch/arm/mach-nuc93x/include/mach/irqs.h b/arch/arm/mach-nuc93x/include/mach/irqs.h new file mode 100644 index 00000000000..7c4aa71edb4 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/irqs.h @@ -0,0 +1,59 @@ +/* + * arch/arm/mach-nuc93x/include/mach/irqs.h + * + * Copyright (c) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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;version 2 of the License. + * + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#define NUC93X_IRQ(x)	(x) + +/* Main cpu interrupts */ + +#define IRQ_WDT		NUC93X_IRQ(1) +#define IRQ_IRQ0	NUC93X_IRQ(2) +#define IRQ_IRQ1	NUC93X_IRQ(3) +#define IRQ_IRQ2	NUC93X_IRQ(4) +#define IRQ_IRQ3	NUC93X_IRQ(5) +#define IRQ_USBH	NUC93X_IRQ(6) +#define IRQ_APU		NUC93X_IRQ(7) +#define IRQ_VPOST	NUC93X_IRQ(8) +#define IRQ_ADC		NUC93X_IRQ(9) +#define IRQ_UART0	NUC93X_IRQ(10) +#define IRQ_TIMER0	NUC93X_IRQ(11) +#define IRQ_GPU0	NUC93X_IRQ(12) +#define IRQ_GPU1	NUC93X_IRQ(13) +#define IRQ_GPU2	NUC93X_IRQ(14) +#define IRQ_GPU3	NUC93X_IRQ(15) +#define IRQ_GPU4	NUC93X_IRQ(16) +#define IRQ_VIN		NUC93X_IRQ(17) +#define IRQ_USBD	NUC93X_IRQ(18) +#define IRQ_VRAMLD	NUC93X_IRQ(19) +#define IRQ_GDMA0	NUC93X_IRQ(20) +#define IRQ_GDMA1	NUC93X_IRQ(21) +#define IRQ_SDIO	NUC93X_IRQ(22) +#define IRQ_FMI		NUC93X_IRQ(22) +#define IRQ_JPEG	NUC93X_IRQ(23) +#define IRQ_SPI0	NUC93X_IRQ(24) +#define IRQ_SPI1	NUC93X_IRQ(25) +#define IRQ_RTC		NUC93X_IRQ(26) +#define IRQ_PWM0	NUC93X_IRQ(27) +#define IRQ_PWM1	NUC93X_IRQ(28) +#define IRQ_PWM2	NUC93X_IRQ(29) +#define IRQ_PWM3	NUC93X_IRQ(30) +#define IRQ_I2SAC97	NUC93X_IRQ(31) +#define IRQ_CAP0	IRQ_PWM0 +#define IRQ_CAP1	IRQ_PWM1 +#define IRQ_CAP2	IRQ_PWM2 +#define IRQ_CAP3	IRQ_PWM3 +#define NR_IRQS		(IRQ_I2SAC97 + 1) + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/map.h b/arch/arm/mach-nuc93x/include/mach/map.h new file mode 100644 index 00000000000..fd0b5e89f0e --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/map.h @@ -0,0 +1,139 @@ +/* + * arch/arm/mach-nuc93x/include/mach/map.h + * + * Copyright (c) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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;version 2 of the License. + * + */ + +#ifndef __ASM_ARCH_MAP_H +#define __ASM_ARCH_MAP_H + +#define MAP_OFFSET	(0xfff00000) +#define CLK_OFFSET	(0x10) + +#ifndef __ASSEMBLY__ +#define NUC93X_ADDR(x)	((void __iomem *)(0xF0000000 + ((x)&(~MAP_OFFSET)))) +#else +#define NUC93X_ADDR(x)	(0xF0000000 + ((x)&(~MAP_OFFSET))) +#endif + + /* +  * nuc932 hardware register definition +  */ + +#define NUC93X_PA_IRQ		(0xFFF83000) +#define NUC93X_PA_GCR		(0xFFF00000) +#define NUC93X_PA_EBI		(0xFFF01000) +#define NUC93X_PA_UART		(0xFFF80000) +#define NUC93X_PA_TIMER		(0xFFF81000) +#define NUC93X_PA_GPIO		(0xFFF84000) +#define NUC93X_PA_GDMA		(0xFFF03000) +#define NUC93X_PA_USBHOST	(0xFFF0d000) +#define NUC93X_PA_I2C		(0xFFF89000) +#define NUC93X_PA_LCD		(0xFFF06000) +#define NUC93X_PA_GE		(0xFFF05000) +#define NUC93X_PA_ADC		(0xFFF85000) +#define NUC93X_PA_RTC		(0xFFF87000) +#define NUC93X_PA_PWM		(0xFFF82000) +#define NUC93X_PA_ACTL		(0xFFF0a000) +#define NUC93X_PA_USBDEV	(0xFFF0C000) +#define NUC93X_PA_JEPEG		(0xFFF0e000) +#define NUC93X_PA_CACHE_T	(0xFFF60000) +#define NUC93X_PA_VRAM		(0xFFF0b000) +#define NUC93X_PA_DMAC		(0xFFF09000) +#define NUC93X_PA_I2SM		(0xFFF08000) +#define NUC93X_PA_CACHE		(0xFFF02000) +#define NUC93X_PA_GPU		(0xFFF04000) +#define NUC93X_PA_VIDEOIN	(0xFFF07000) +#define NUC93X_PA_SPI0		(0xFFF86000) +#define NUC93X_PA_SPI1		(0xFFF88000) + + /* +  * nuc932 virtual address mapping. +  * interrupt controller is the first thing we put in, to make +  * the assembly code for the irq detection easier +  */ + +#define NUC93X_VA_IRQ		NUC93X_ADDR(0x00000000) +#define NUC93X_SZ_IRQ		SZ_4K + +#define NUC93X_VA_GCR		NUC93X_ADDR(NUC93X_PA_IRQ) +#define NUC93X_VA_CLKPWR	(NUC93X_VA_GCR+CLK_OFFSET) +#define NUC93X_SZ_GCR		SZ_4K + +/* EBI management */ + +#define NUC93X_VA_EBI		NUC93X_ADDR(NUC93X_PA_EBI) +#define NUC93X_SZ_EBI		SZ_4K + +/* UARTs */ + +#define NUC93X_VA_UART		NUC93X_ADDR(NUC93X_PA_UART) +#define NUC93X_SZ_UART		SZ_4K + +/* Timers */ + +#define NUC93X_VA_TIMER	NUC93X_ADDR(NUC93X_PA_TIMER) +#define NUC93X_SZ_TIMER	SZ_4K + +/* GPIO ports */ + +#define NUC93X_VA_GPIO		NUC93X_ADDR(NUC93X_PA_GPIO) +#define NUC93X_SZ_GPIO		SZ_4K + +/* GDMA control */ + +#define NUC93X_VA_GDMA		NUC93X_ADDR(NUC93X_PA_GDMA) +#define NUC93X_SZ_GDMA		SZ_4K + +/* I2C hardware controller */ + +#define NUC93X_VA_I2C		NUC93X_ADDR(NUC93X_PA_I2C) +#define NUC93X_SZ_I2C		SZ_4K + +/* LCD controller*/ + +#define NUC93X_VA_LCD		NUC93X_ADDR(NUC93X_PA_LCD) +#define NUC93X_SZ_LCD		SZ_4K + +/* 2D controller*/ + +#define NUC93X_VA_GE		NUC93X_ADDR(NUC93X_PA_GE) +#define NUC93X_SZ_GE		SZ_4K + +/* ADC */ + +#define NUC93X_VA_ADC		NUC93X_ADDR(NUC93X_PA_ADC) +#define NUC93X_SZ_ADC		SZ_4K + +/* RTC */ + +#define NUC93X_VA_RTC		NUC93X_ADDR(NUC93X_PA_RTC) +#define NUC93X_SZ_RTC		SZ_4K + +/* Pulse Width Modulation(PWM) Registers */ + +#define NUC93X_VA_PWM		NUC93X_ADDR(NUC93X_PA_PWM) +#define NUC93X_SZ_PWM		SZ_4K + +/* Audio Controller controller */ + +#define NUC93X_VA_ACTL		NUC93X_ADDR(NUC93X_PA_ACTL) +#define NUC93X_SZ_ACTL		SZ_4K + +/* USB Device port */ + +#define NUC93X_VA_USBDEV	NUC93X_ADDR(NUC93X_PA_USBDEV) +#define NUC93X_SZ_USBDEV	SZ_4K + +/* USB host controller*/ +#define NUC93X_VA_USBHOST	NUC93X_ADDR(NUC93X_PA_USBHOST) +#define NUC93X_SZ_USBHOST	SZ_4K + +#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/memory.h b/arch/arm/mach-nuc93x/include/mach/memory.h new file mode 100644 index 00000000000..323ab0db3f7 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/memory.h @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-nuc93x/include/mach/memory.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + * + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET	UL(0x00000000) + +#endif diff --git a/arch/arm/mach-nuc93x/include/mach/regs-clock.h b/arch/arm/mach-nuc93x/include/mach/regs-clock.h new file mode 100644 index 00000000000..5cb2954fbec --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/regs-clock.h @@ -0,0 +1,53 @@ +/* + * arch/arm/mach-nuc93x/include/mach/regs-clock.h + * + * Copyright (c) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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;version 2 of the License. + * + */ + +#ifndef __ASM_ARCH_REGS_CLOCK_H +#define __ASM_ARCH_REGS_CLOCK_H + +/* Clock Control Registers  */ +#define CLK_BA		NUC93X_VA_CLKPWR +#define REG_CLKEN	(CLK_BA + 0x00) +#define REG_CLKSEL	(CLK_BA + 0x04) +#define REG_CLKDIV	(CLK_BA + 0x08) +#define REG_PLLCON0	(CLK_BA + 0x0C) +#define REG_PLLCON1	(CLK_BA + 0x10) +#define REG_PMCON	(CLK_BA + 0x14) +#define REG_IRQWAKECON	(CLK_BA + 0x18) +#define REG_IRQWAKEFLAG	(CLK_BA + 0x1C) +#define REG_IPSRST	(CLK_BA + 0x20) +#define REG_CLKEN1	(CLK_BA + 0x24) +#define REG_CLKDIV1	(CLK_BA + 0x28) + +/* Define PLL freq setting */ +#define PLL_DISABLE		0x12B63 +#define	PLL_66MHZ		0x2B63 +#define	PLL_100MHZ		0x4F64 +#define PLL_120MHZ		0x4F63 +#define	PLL_166MHZ		0x4124 +#define	PLL_200MHZ		0x4F24 + +/* Define AHB:CPUFREQ ratio */ +#define	AHB_CPUCLK_1_1		0x00 +#define	AHB_CPUCLK_1_2		0x01 +#define	AHB_CPUCLK_1_4		0x02 +#define	AHB_CPUCLK_1_8		0x03 + +/* Define APB:AHB ratio */ +#define APB_AHB_1_2		0x01 +#define APB_AHB_1_4		0x02 +#define APB_AHB_1_8		0x03 + +/* Define clock skew */ +#define DEFAULTSKEW		0x48 + +#endif /*  __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/regs-ebi.h b/arch/arm/mach-nuc93x/include/mach/regs-ebi.h new file mode 100644 index 00000000000..3c72550e28e --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/regs-ebi.h @@ -0,0 +1,33 @@ +/* + * arch/arm/mach-nuc93x/include/mach/regs-ebi.h + * + * Copyright (c) 2009 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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;version 2 of the License. + * + */ + +#ifndef __ASM_ARCH_REGS_EBI_H +#define __ASM_ARCH_REGS_EBI_H + +/* EBI Control Registers */ + +#define EBI_BA		NUC93X_VA_EBI +#define REG_EBICON	(EBI_BA + 0x00) +#define REG_ROMCON	(EBI_BA + 0x04) +#define REG_SDCONF0	(EBI_BA + 0x08) +#define REG_SDCONF1	(EBI_BA + 0x0C) +#define REG_SDTIME0	(EBI_BA + 0x10) +#define REG_SDTIME1	(EBI_BA + 0x14) +#define REG_EXT0CON	(EBI_BA + 0x18) +#define REG_EXT1CON	(EBI_BA + 0x1C) +#define REG_EXT2CON	(EBI_BA + 0x20) +#define REG_EXT3CON	(EBI_BA + 0x24) +#define REG_EXT4CON	(EBI_BA + 0x28) +#define REG_CKSKEW	(EBI_BA + 0x2C) + +#endif /*  __ASM_ARCH_REGS_EBI_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/regs-irq.h b/arch/arm/mach-nuc93x/include/mach/regs-irq.h new file mode 100644 index 00000000000..23021592de5 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/regs-irq.h @@ -0,0 +1,42 @@ +/* + * arch/arm/mach-nuc93x/include/mach/regs-irq.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + * + */ + +#ifndef ___ASM_ARCH_REGS_IRQ_H +#define ___ASM_ARCH_REGS_IRQ_H + +/* Advance Interrupt Controller (AIC) Registers */ + +#define AIC_BA    		NUC93X_VA_IRQ + +#define REG_AIC_IRQSC		(AIC_BA+0x80) +#define REG_AIC_GEN		(AIC_BA+0x84) +#define REG_AIC_GASR		(AIC_BA+0x88) +#define REG_AIC_GSCR		(AIC_BA+0x8C) +#define REG_AIC_IRSR		(AIC_BA+0x100) +#define REG_AIC_IASR		(AIC_BA+0x104) +#define REG_AIC_ISR		(AIC_BA+0x108) +#define REG_AIC_IPER		(AIC_BA+0x10C) +#define REG_AIC_ISNR		(AIC_BA+0x110) +#define REG_AIC_IMR		(AIC_BA+0x114) +#define REG_AIC_OISR		(AIC_BA+0x118) +#define REG_AIC_MECR		(AIC_BA+0x120) +#define REG_AIC_MDCR		(AIC_BA+0x124) +#define REG_AIC_SSCR		(AIC_BA+0x128) +#define REG_AIC_SCCR		(AIC_BA+0x12C) +#define REG_AIC_EOSCR		(AIC_BA+0x130) +#define AIC_IPER		(0x10C) +#define AIC_ISNR		(0x110) + +#endif /* ___ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/regs-serial.h b/arch/arm/mach-nuc93x/include/mach/regs-serial.h new file mode 100644 index 00000000000..767a047a8bc --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/regs-serial.h @@ -0,0 +1,52 @@ +/* + * arch/arm/mach-nuc93x/include/mach/regs-serial.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + * + */ + +#ifndef __ASM_ARM_REGS_SERIAL_H +#define __ASM_ARM_REGS_SERIAL_H + +#define UART0_BA	NUC93X_VA_UART +#define UART1_BA	(NUC93X_VA_UART+0x100) + +#define UART0_PA	NUC93X_PA_UART +#define UART1_PA	(NUC93X_PA_UART+0x100) + + +#ifndef __ASSEMBLY__ + +struct nuc93x_uart_clksrc { +	const char	*name; +	unsigned int	divisor; +	unsigned int	min_baud; +	unsigned int	max_baud; +}; + +struct nuc93x_uartcfg { +	unsigned char	hwport; +	unsigned char	unused; +	unsigned short	flags; +	unsigned long	uart_flags; + +	unsigned long	ucon; +	unsigned long	ulcon; +	unsigned long	ufcon; + +	struct nuc93x_uart_clksrc *clocks; +	unsigned int	clocks_size; +}; + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_ARM_REGS_SERIAL_H */ + diff --git a/arch/arm/mach-nuc93x/include/mach/regs-timer.h b/arch/arm/mach-nuc93x/include/mach/regs-timer.h new file mode 100644 index 00000000000..394be9614d3 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/regs-timer.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-nuc93x/include/mach/regs-timer.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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. + * + */ + +#ifndef __ASM_ARCH_REGS_TIMER_H +#define __ASM_ARCH_REGS_TIMER_H + +/* Timer Registers */ + +#define TMR_BA			NUC93X_VA_TIMER +#define REG_TCSR0		(TMR_BA+0x00) +#define REG_TICR0		(TMR_BA+0x08) +#define REG_TDR0		(TMR_BA+0x10) +#define REG_TISR		(TMR_BA+0x18) +#define REG_WTCR		(TMR_BA+0x1C) + +#endif /*  __ASM_ARCH_REGS_TIMER_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/system.h b/arch/arm/mach-nuc93x/include/mach/system.h new file mode 100644 index 00000000000..d26bd9a5284 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/system.h @@ -0,0 +1,28 @@ +/* + * arch/arm/machnuc93x/include/mach/system.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/system.h + * + * 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 <asm/proc-fns.h> + +static void arch_idle(void) +{ +} + +static void arch_reset(char mode, const char *cmd) +{ +	cpu_reset(0); +} + diff --git a/arch/arm/mach-nuc93x/include/mach/timex.h b/arch/arm/mach-nuc93x/include/mach/timex.h new file mode 100644 index 00000000000..0c719cc91aa --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/timex.h @@ -0,0 +1,25 @@ +/* + * arch/arm/mach-nuc93x/include/mach/timex.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/timex.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +/* CLOCK_TICK_RATE Now, I don't use it. */ + +#define CLOCK_TICK_RATE 27000000 + +#endif /* __ASM_ARCH_TIMEX_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/uncompress.h b/arch/arm/mach-nuc93x/include/mach/uncompress.h new file mode 100644 index 00000000000..73082cd61e8 --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/uncompress.h @@ -0,0 +1,50 @@ +/* + * arch/arm/mach-nuc93x/include/mach/uncompress.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/uncompress.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +/* Defines for UART registers */ + +#include <mach/regs-serial.h> +#include <mach/map.h> +#include <linux/serial_reg.h> + +#define arch_decomp_wdog() + +#define TX_DONE	(UART_LSR_TEMT | UART_LSR_THRE) +static u32 * uart_base = (u32 *)UART0_PA; + +static void putc(int ch) +{ +	/* Check THRE and TEMT bits before we transmit the character. +	 */ +	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE) +		barrier(); + +	*uart_base = ch; +} + +static inline void flush(void) +{ +} + +static void arch_decomp_setup(void) +{ +} + +#endif/* __ASM_NUC93X_UNCOMPRESS_H */ diff --git a/arch/arm/mach-nuc93x/include/mach/vmalloc.h b/arch/arm/mach-nuc93x/include/mach/vmalloc.h new file mode 100644 index 00000000000..98a21b81dec --- /dev/null +++ b/arch/arm/mach-nuc93x/include/mach/vmalloc.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-nuc93x/include/mach/vmalloc.h + * + * Copyright (c) 2008 Nuvoton technology corporation + * All rights reserved. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * Based on arch/arm/mach-s3c2410/include/mach/vmalloc.h + * + * 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. + * + */ + +#ifndef __ASM_ARCH_VMALLOC_H +#define __ASM_ARCH_VMALLOC_H + +#define VMALLOC_END	  (0xE0000000) + +#endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-nuc93x/irq.c b/arch/arm/mach-nuc93x/irq.c new file mode 100644 index 00000000000..a7a88ea4ec3 --- /dev/null +++ b/arch/arm/mach-nuc93x/irq.c @@ -0,0 +1,66 @@ +/* + * linux/arch/arm/mach-nuc93x/irq.c + * + * Copyright (c) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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;version 2 of the License. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/ptrace.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <asm/irq.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/regs-irq.h> + +static void nuc93x_irq_mask(unsigned int irq) +{ +	__raw_writel(1 << irq, REG_AIC_MDCR); +} + +/* + * By the w90p910 spec,any irq,only write 1 + * to REG_AIC_EOSCR for ACK + */ + +static void nuc93x_irq_ack(unsigned int irq) +{ +	__raw_writel(0x01, REG_AIC_EOSCR); +} + +static void nuc93x_irq_unmask(unsigned int irq) +{ +	__raw_writel(1 << irq, REG_AIC_MECR); + +} + +static struct irq_chip nuc93x_irq_chip = { +	.ack	   = nuc93x_irq_ack, +	.mask	   = nuc93x_irq_mask, +	.unmask	   = nuc93x_irq_unmask, +}; + +void __init nuc93x_init_irq(void) +{ +	int irqno; + +	__raw_writel(0xFFFFFFFE, REG_AIC_MDCR); + +	for (irqno = IRQ_WDT; irqno <= NR_IRQS; irqno++) { +		set_irq_chip(irqno, &nuc93x_irq_chip); +		set_irq_handler(irqno, handle_level_irq); +		set_irq_flags(irqno, IRQF_VALID); +	} +} diff --git a/arch/arm/mach-nuc93x/mach-nuc932evb.c b/arch/arm/mach-nuc93x/mach-nuc932evb.c new file mode 100644 index 00000000000..9f79266f08e --- /dev/null +++ b/arch/arm/mach-nuc93x/mach-nuc932evb.c @@ -0,0 +1,45 @@ +/* + * linux/arch/arm/mach-w90x900/mach-nuc910evb.c + * + * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche + * + * Copyright (C) 2008 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach-types.h> +#include <mach/map.h> + +#include "nuc932.h" + +static void __init nuc932evb_map_io(void) +{ +	nuc932_map_io(); +	nuc932_init_clocks(); +	nuc932_init_uartclk(); +} + +static void __init nuc932evb_init(void) +{ +	nuc932_board_init(); +} + +MACHINE_START(NUC932EVB, "NUC932EVB") +	/* Maintainer: Wan ZongShun */ +	.phys_io	= NUC93X_PA_UART, +	.io_pg_offst	= (((u32)NUC93X_VA_UART) >> 18) & 0xfffc, +	.boot_params	= 0, +	.map_io		= nuc932evb_map_io, +	.init_irq	= nuc93x_init_irq, +	.init_machine	= nuc932evb_init, +	.timer		= &nuc93x_timer, +MACHINE_END diff --git a/arch/arm/mach-nuc93x/nuc932.c b/arch/arm/mach-nuc93x/nuc932.c new file mode 100644 index 00000000000..3966ead686f --- /dev/null +++ b/arch/arm/mach-nuc93x/nuc932.c @@ -0,0 +1,65 @@ +/* + * linux/arch/arm/mach-nuc93x/nuc932.c + * + * Copyright (c) 2009 Nuvoton corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * NUC932 cpu support + * + * 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;version 2 of the License. + * + */ + +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <asm/mach/map.h> +#include <mach/hardware.h> + +#include "cpu.h" +#include "clock.h" + +/* define specific CPU platform device */ + +static struct platform_device *nuc932_dev[] __initdata = { +}; + +/* define specific CPU platform io map */ + +static struct map_desc nuc932evb_iodesc[] __initdata = { +}; + +/*Init NUC932 evb io*/ + +void __init nuc932_map_io(void) +{ +	nuc93x_map_io(nuc932evb_iodesc, ARRAY_SIZE(nuc932evb_iodesc)); +} + +/*Init NUC932 clock*/ + +void __init nuc932_init_clocks(void) +{ +	nuc93x_init_clocks(); +} + +/*enable NUC932 uart clock*/ + +void __init nuc932_init_uartclk(void) +{ +	struct clk *ck_uart = clk_get(NULL, "uart"); +	BUG_ON(IS_ERR(ck_uart)); + +	clk_enable(ck_uart); +} + +/*Init NUC932 board info*/ + +void __init nuc932_board_init(void) +{ +	nuc93x_board_init(nuc932_dev, ARRAY_SIZE(nuc932_dev)); +} diff --git a/arch/arm/mach-nuc93x/nuc932.h b/arch/arm/mach-nuc93x/nuc932.h new file mode 100644 index 00000000000..9a66edd5338 --- /dev/null +++ b/arch/arm/mach-nuc93x/nuc932.h @@ -0,0 +1,29 @@ +/* + * arch/arm/mach-nuc93x/nuc932.h + * + * Copyright (c) 2008 Nuvoton corporation + * + * Header file for NUC93x CPU support + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +struct map_desc; +struct sys_timer; + +/* core initialisation functions */ + +extern void nuc93x_init_irq(void); +extern struct sys_timer nuc93x_timer; + +/* extern file from nuc932.c */ + +extern void nuc932_board_init(void); +extern void nuc932_init_clocks(void); +extern void nuc932_map_io(void); +extern void nuc932_init_uartclk(void); diff --git a/arch/arm/mach-nuc93x/time.c b/arch/arm/mach-nuc93x/time.c new file mode 100644 index 00000000000..2f90f9dc6e3 --- /dev/null +++ b/arch/arm/mach-nuc93x/time.c @@ -0,0 +1,100 @@ +/* + * linux/arch/arm/mach-nuc93x/time.c + * + * Copyright (c) 2009 Nuvoton technology corporation. + * + * Wan ZongShun <mcuos.com@gmail.com> + * + * 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/kernel.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/leds.h> + +#include <asm/mach-types.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> + +#include <mach/system.h> +#include <mach/map.h> +#include <mach/regs-timer.h> + +#define RESETINT	0x01 +#define PERIOD		(0x01 << 27) +#define ONESHOT		(0x00 << 27) +#define COUNTEN		(0x01 << 30) +#define INTEN		(0x01 << 29) + +#define TICKS_PER_SEC	100 +#define PRESCALE	0x63 /* Divider = prescale + 1 */ + +unsigned int timer0_load; + +static unsigned long nuc93x_gettimeoffset(void) +{ +	return 0; +} + +/*IRQ handler for the timer*/ + +static irqreturn_t nuc93x_timer_interrupt(int irq, void *dev_id) +{ +	timer_tick(); +	__raw_writel(0x01, REG_TISR); /* clear TIF0 */ +	return IRQ_HANDLED; +} + +static struct irqaction nuc93x_timer_irq = { +	.name		= "nuc93x Timer Tick", +	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, +	.handler	= nuc93x_timer_interrupt, +}; + +/*Set up timer reg.*/ + +static void nuc93x_timer_setup(void) +{ +	struct clk *ck_ext = clk_get(NULL, "ext"); +	struct clk *ck_timer = clk_get(NULL, "timer"); +	unsigned int rate, val = 0; + +	BUG_ON(IS_ERR(ck_ext) || IS_ERR(ck_timer)); + +	clk_enable(ck_timer); +	rate = clk_get_rate(ck_ext); +	clk_put(ck_ext); +	rate = rate / (PRESCALE + 0x01); + +	 /* set a known state */ +	__raw_writel(0x00, REG_TCSR0); +	__raw_writel(RESETINT, REG_TISR); + +	timer0_load = (rate / TICKS_PER_SEC); +	__raw_writel(timer0_load, REG_TICR0); + +	val |= (PERIOD | COUNTEN | INTEN | PRESCALE);; +	__raw_writel(val, REG_TCSR0); + +} + +static void __init nuc93x_timer_init(void) +{ +	nuc93x_timer_setup(); +	setup_irq(IRQ_TIMER0, &nuc93x_timer_irq); +} + +struct sys_timer nuc93x_timer = { +	.init		= nuc93x_timer_init, +	.offset		= nuc93x_gettimeoffset, +	.resume		= nuc93x_timer_setup +}; diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S index aedb746fc33..8c74cab2fa8 100644 --- a/arch/arm/mach-omap1/include/mach/debug-macro.S +++ b/arch/arm/mach-omap1/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0xff000000	@ physical base address diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 0c6be6b4a7e..8ba8fb5b251 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -28,6 +28,7 @@  #include <plat/control.h>  #include <plat/timer-gp.h>  #include <asm/hardware/gic.h> +#include <asm/hardware/cache-l2x0.h>  static struct platform_device sdp4430_lcd_device = {  	.name		= "sdp4430_lcd", @@ -50,6 +51,59 @@ static struct omap_board_config_kernel sdp4430_config[] __initdata = {  	{ OMAP_TAG_LCD,		&sdp4430_lcd_config },  }; +#ifdef CONFIG_CACHE_L2X0 +noinline void omap_smc1(u32 fn, u32 arg) +{ +	register u32 r12 asm("r12") = fn; +	register u32 r0 asm("r0") = arg; + +	/* This is common routine cache secure monitor API used to +	 * modify the PL310 secure registers. +	 * r0 contains the value to be modified and "r12" contains +	 * the monitor API number. It uses few CPU registers +	 * internally and hence they need be backed up including +	 * link register "lr". +	 * Explicitly save r11 and r12 the compiler generated code +	 * won't save it. +	 */ +	asm volatile( +		"stmfd r13!, {r11,r12}\n" +		"dsb\n" +		"smc\n" +		"ldmfd r13!, {r11,r12}\n" +		: "+r" (r0), "+r" (r12) +		: +		: "r4", "r5", "r10", "lr", "cc"); +} +EXPORT_SYMBOL(omap_smc1); + +static int __init omap_l2_cache_init(void) +{ +	void __iomem *l2cache_base; + +	/* To avoid code running on other OMAPs in +	 * multi-omap builds +	 */ +	if (!cpu_is_omap44xx()) +		return -ENODEV; + +	/* Static mapping, never released */ +	l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K); +	BUG_ON(!l2cache_base); + +	/* Enable PL310 L2 Cache controller */ +	omap_smc1(0x102, 0x1); + +	/* 32KB way size, 16-way associativity, +	* parity disabled +	*/ +	l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff); + +	return 0; +} +early_initcall(omap_l2_cache_init); +#endif +  static void __init gic_init_irq(void)  {  	void __iomem *base; diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S index e9f255df916..86979d7bd87 100644 --- a/arch/arm/mach-omap2/include/mach/debug-macro.S +++ b/arch/arm/mach-omap2/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  #ifdef  CONFIG_ARCH_OMAP2 diff --git a/arch/arm/mach-orion5x/include/mach/debug-macro.S b/arch/arm/mach-orion5x/include/mach/debug-macro.S index c7f808bfe27..91e0e39bb23 100644 --- a/arch/arm/mach-orion5x/include/mach/debug-macro.S +++ b/arch/arm/mach-orion5x/include/mach/debug-macro.S @@ -10,7 +10,7 @@  #include <mach/orion5x.h> -	.macro  addruart,rx +	.macro  addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1					@ MMU enabled?  	ldreq	\rx, =ORION5X_REGS_PHYS_BASE diff --git a/arch/arm/mach-orion5x/include/mach/vmalloc.h b/arch/arm/mach-orion5x/include/mach/vmalloc.h index 7147a297e97..06b50aeff7b 100644 --- a/arch/arm/mach-orion5x/include/mach/vmalloc.h +++ b/arch/arm/mach-orion5x/include/mach/vmalloc.h @@ -2,4 +2,4 @@   * arch/arm/mach-orion5x/include/mach/vmalloc.h   */ -#define VMALLOC_END       0xfd800000 +#define VMALLOC_END       0xfd800000UL diff --git a/arch/arm/mach-pnx4008/include/mach/debug-macro.S b/arch/arm/mach-pnx4008/include/mach/debug-macro.S index 6d1407f319f..6ca8bd30bf4 100644 --- a/arch/arm/mach-pnx4008/include/mach/debug-macro.S +++ b/arch/arm/mach-pnx4008/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		mov	\rx, #0x00090000 diff --git a/arch/arm/mach-pxa/include/mach/debug-macro.S b/arch/arm/mach-pxa/include/mach/debug-macro.S index 55d6a175ab1..01cf81393fe 100644 --- a/arch/arm/mach-pxa/include/mach/debug-macro.S +++ b/arch/arm/mach-pxa/include/mach/debug-macro.S @@ -13,7 +13,7 @@  #include "hardware.h" -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x40000000		@ physical diff --git a/arch/arm/mach-pxa/include/mach/vmalloc.h b/arch/arm/mach-pxa/include/mach/vmalloc.h index e90c5eeb81d..bfecfbf5f46 100644 --- a/arch/arm/mach-pxa/include/mach/vmalloc.h +++ b/arch/arm/mach-pxa/include/mach/vmalloc.h @@ -8,4 +8,4 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   */ -#define VMALLOC_END       (0xe8000000) +#define VMALLOC_END       (0xe8000000UL) diff --git a/arch/arm/mach-realview/include/mach/debug-macro.S b/arch/arm/mach-realview/include/mach/debug-macro.S index 932d8af1806..86622289b74 100644 --- a/arch/arm/mach-realview/include/mach/debug-macro.S +++ b/arch/arm/mach-realview/include/mach/debug-macro.S @@ -33,7 +33,7 @@  #error "Unknown RealView platform"  #endif -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx,      #0x10000000 diff --git a/arch/arm/mach-realview/include/mach/vmalloc.h b/arch/arm/mach-realview/include/mach/vmalloc.h index fe0de1b507a..a2a4c686140 100644 --- a/arch/arm/mach-realview/include/mach/vmalloc.h +++ b/arch/arm/mach-realview/include/mach/vmalloc.h @@ -18,4 +18,4 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ -#define VMALLOC_END		0xf8000000 +#define VMALLOC_END		0xf8000000UL diff --git a/arch/arm/mach-rpc/include/mach/debug-macro.S b/arch/arm/mach-rpc/include/mach/debug-macro.S index b2a939ffdcd..6fc8d66395d 100644 --- a/arch/arm/mach-rpc/include/mach/debug-macro.S +++ b/arch/arm/mach-rpc/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x03000000 diff --git a/arch/arm/mach-s3c2410/include/mach/debug-macro.S b/arch/arm/mach-s3c2410/include/mach/debug-macro.S index 4c29a89ad07..0eef78b4a6e 100644 --- a/arch/arm/mach-s3c2410/include/mach/debug-macro.S +++ b/arch/arm/mach-s3c2410/include/mach/debug-macro.S @@ -19,7 +19,7 @@  #define S3C2410_UART1_OFF (0x4000)  #define SHIFT_2440TXF (14-9) -	.macro addruart, rx +	.macro addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1  		ldreq	\rx, = S3C24XX_PA_UART diff --git a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S index f0ef0ab475f..239476b81f3 100644 --- a/arch/arm/mach-s3c24a0/include/mach/debug-macro.S +++ b/arch/arm/mach-s3c24a0/include/mach/debug-macro.S @@ -10,7 +10,7 @@  #include <mach/map.h>  #include <plat/regs-serial.h> -	.macro addruart, rx +	.macro addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1  		ldreq	\rx, = S3C24XX_PA_UART diff --git a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h index 4d4fe484958..91465682079 100644 --- a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h +++ b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h @@ -12,6 +12,6 @@  #ifndef __ASM_ARCH_VMALLOC_H  #define __ASM_ARCH_VMALLOC_H -#define VMALLOC_END	  (0xE0000000) +#define VMALLOC_END	  (0xe0000000UL)  #endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/debug-macro.S b/arch/arm/mach-s3c6400/include/mach/debug-macro.S index b18ac5266df..5c88875d6a3 100644 --- a/arch/arm/mach-s3c6400/include/mach/debug-macro.S +++ b/arch/arm/mach-s3c6400/include/mach/debug-macro.S @@ -21,7 +21,7 @@  	 * aligned and add in the offset when we load the value here.  	 */ -	.macro addruart, rx +	.macro addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1  		ldreq	\rx, = S3C_PA_UART diff --git a/arch/arm/mach-s5pc100/include/mach/debug-macro.S b/arch/arm/mach-s5pc100/include/mach/debug-macro.S index 9d142ccf654..e181f578948 100644 --- a/arch/arm/mach-s5pc100/include/mach/debug-macro.S +++ b/arch/arm/mach-s5pc100/include/mach/debug-macro.S @@ -22,7 +22,7 @@  	 * aligned and add in the offset when we load the value here.  	 */ -	.macro addruart, rx +	.macro addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1  		ldreq	\rx, = S3C_PA_UART diff --git a/arch/arm/mach-sa1100/include/mach/debug-macro.S b/arch/arm/mach-sa1100/include/mach/debug-macro.S index 1f0634d9270..336adccea54 100644 --- a/arch/arm/mach-sa1100/include/mach/debug-macro.S +++ b/arch/arm/mach-sa1100/include/mach/debug-macro.S @@ -12,7 +12,7 @@  */  #include <mach/hardware.h> -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x80000000	@ physical base address diff --git a/arch/arm/mach-sa1100/include/mach/vmalloc.h b/arch/arm/mach-sa1100/include/mach/vmalloc.h index ec8fdc5a360..b3d00239848 100644 --- a/arch/arm/mach-sa1100/include/mach/vmalloc.h +++ b/arch/arm/mach-sa1100/include/mach/vmalloc.h @@ -1,4 +1,4 @@  /*   * arch/arm/mach-sa1100/include/mach/vmalloc.h   */ -#define VMALLOC_END       (0xe8000000) +#define VMALLOC_END       (0xe8000000UL) diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S index f97a7626bd5..50f071c5bf4 100644 --- a/arch/arm/mach-shark/include/mach/debug-macro.S +++ b/arch/arm/mach-shark/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mov	\rx, #0xe0000000  		orr	\rx, \rx, #0x000003f8  		.endm diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index c174ed1f369..5af71d5ba66 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c @@ -610,34 +610,34 @@ EXPORT_SYMBOL(clk_get_rate);  static unsigned long clk_round_rate_mclk(struct clk *clk, unsigned long rate)  { -	if (rate >= 18900000) +	if (rate <= 18900000)  		return 18900000; -	if (rate >= 20800000) +	if (rate <= 20800000)  		return 20800000; -	if (rate >= 23100000) +	if (rate <= 23100000)  		return 23100000; -	if (rate >= 26000000) +	if (rate <= 26000000)  		return 26000000; -	if (rate >= 29700000) +	if (rate <= 29700000)  		return 29700000; -	if (rate >= 34700000) +	if (rate <= 34700000)  		return 34700000; -	if (rate >= 41600000) +	if (rate <= 41600000)  		return 41600000; -	if (rate >= 52000000) +	if (rate <= 52000000)  		return 52000000;  	return -EINVAL;  }  static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate)  { -	if (rate >= 13000000) +	if (rate <= 13000000)  		return 13000000; -	if (rate >= 52000000) +	if (rate <= 52000000)  		return 52000000; -	if (rate >= 104000000) +	if (rate <= 104000000)  		return 104000000; -	if (rate >= 208000000) +	if (rate <= 208000000)  		return 208000000;  	return -EINVAL;  } diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 653e25be3dd..01b50313914 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -3,7 +3,7 @@   * arch/arm/mach-u300/core.c   *   * - * Copyright (C) 2007-2009 ST-Ericsson AB + * Copyright (C) 2007-2010 ST-Ericsson AB   * License terms: GNU General Public License (GPL) version 2   * Core platform support, IRQ handling and device definitions.   * Author: Linus Walleij <linus.walleij@stericsson.com> @@ -19,6 +19,7 @@  #include <linux/amba/bus.h>  #include <linux/platform_device.h>  #include <linux/gpio.h> +#include <mach/coh901318.h>  #include <asm/types.h>  #include <asm/setup.h> @@ -29,6 +30,7 @@  #include <mach/hardware.h>  #include <mach/syscon.h> +#include <mach/dma_channels.h>  #include "clock.h"  #include "mmc.h" @@ -372,8 +374,1019 @@ static struct resource ave_resources[] = {  	},  }; +static struct resource dma_resource[] = { +	{ +		.start = U300_DMAC_BASE, +		.end = U300_DMAC_BASE + PAGE_SIZE - 1, +		.flags =  IORESOURCE_MEM, +	}, +	{ +		.start = IRQ_U300_DMA, +		.end = IRQ_U300_DMA, +		.flags =  IORESOURCE_IRQ, +	} +}; + +#ifdef CONFIG_MACH_U300_BS335 +/* points out all dma slave channels. + * Syntax is [A1, B1, A2, B2, .... ,-1,-1] + * Select all channels from A to B, end of list is marked with -1,-1 + */ +static int dma_slave_channels[] = { +	U300_DMA_MSL_TX_0, U300_DMA_SPI_RX, +	U300_DMA_UART1_TX, U300_DMA_UART1_RX, -1, -1}; + +/* points out all dma memcpy channels. */ +static int dma_memcpy_channels[] = { +	U300_DMA_GENERAL_PURPOSE_0, U300_DMA_GENERAL_PURPOSE_8, -1, -1}; + +#else /* CONFIG_MACH_U300_BS335 */ + +static int dma_slave_channels[] = {U300_DMA_MSL_TX_0, U300_DMA_SPI_RX, -1, -1}; +static int dma_memcpy_channels[] = { +	U300_DMA_GENERAL_PURPOSE_0, U300_DMA_GENERAL_PURPOSE_10, -1, -1}; + +#endif + +/** register dma for memory access + * + * active  1 means dma intends to access memory + *         0 means dma wont access memory + */ +static void coh901318_access_memory_state(struct device *dev, bool active) +{ +} + +#define flags_memcpy_config (COH901318_CX_CFG_CH_DISABLE | \ +			COH901318_CX_CFG_RM_MEMORY_TO_MEMORY | \ +			COH901318_CX_CFG_LCR_DISABLE | \ +			COH901318_CX_CFG_TC_IRQ_ENABLE | \ +			COH901318_CX_CFG_BE_IRQ_ENABLE) +#define flags_memcpy_lli_chained (COH901318_CX_CTRL_TC_ENABLE | \ +			COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \ +			COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \ +			COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \ +			COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \ +			COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \ +			COH901318_CX_CTRL_MASTER_MODE_M1RW | \ +			COH901318_CX_CTRL_TCP_DISABLE | \ +			COH901318_CX_CTRL_TC_IRQ_DISABLE | \ +			COH901318_CX_CTRL_HSP_DISABLE | \ +			COH901318_CX_CTRL_HSS_DISABLE | \ +			COH901318_CX_CTRL_DDMA_LEGACY | \ +			COH901318_CX_CTRL_PRDD_SOURCE) +#define flags_memcpy_lli (COH901318_CX_CTRL_TC_ENABLE | \ +			COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \ +			COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \ +			COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \ +			COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \ +			COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \ +			COH901318_CX_CTRL_MASTER_MODE_M1RW | \ +			COH901318_CX_CTRL_TCP_DISABLE | \ +			COH901318_CX_CTRL_TC_IRQ_DISABLE | \ +			COH901318_CX_CTRL_HSP_DISABLE | \ +			COH901318_CX_CTRL_HSS_DISABLE | \ +			COH901318_CX_CTRL_DDMA_LEGACY | \ +			COH901318_CX_CTRL_PRDD_SOURCE) +#define flags_memcpy_lli_last (COH901318_CX_CTRL_TC_ENABLE | \ +			COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \ +			COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \ +			COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \ +			COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \ +			COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \ +			COH901318_CX_CTRL_MASTER_MODE_M1RW | \ +			COH901318_CX_CTRL_TCP_DISABLE | \ +			COH901318_CX_CTRL_TC_IRQ_ENABLE | \ +			COH901318_CX_CTRL_HSP_DISABLE | \ +			COH901318_CX_CTRL_HSS_DISABLE | \ +			COH901318_CX_CTRL_DDMA_LEGACY | \ +			COH901318_CX_CTRL_PRDD_SOURCE) + +const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { +	{ +		.number = U300_DMA_MSL_TX_0, +		.name = "MSL TX 0", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 0 * 0x40 + 0x20, +	}, +	{ +		.number = U300_DMA_MSL_TX_1, +		.name = "MSL TX 1", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 1 * 0x40 + 0x20, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +	}, +	{ +		.number = U300_DMA_MSL_TX_2, +		.name = "MSL TX 2", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 2 * 0x40 + 0x20, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.desc_nbr_max = 10, +	}, +	{ +		.number = U300_DMA_MSL_TX_3, +		.name = "MSL TX 3", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 3 * 0x40 + 0x20, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +	}, +	{ +		.number = U300_DMA_MSL_TX_4, +		.name = "MSL TX 4", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 4 * 0x40 + 0x20, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1R_M2W | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +	}, +	{ +		.number = U300_DMA_MSL_TX_5, +		.name = "MSL TX 5", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 5 * 0x40 + 0x20, +	}, +	{ +		.number = U300_DMA_MSL_TX_6, +		.name = "MSL TX 6", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x20, +	}, +	{ +		.number = U300_DMA_MSL_RX_0, +		.name = "MSL RX 0", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 0 * 0x40 + 0x220, +	}, +	{ +		.number = U300_DMA_MSL_RX_1, +		.name = "MSL RX 1", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 1 * 0x40 + 0x220, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli = 0, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +	}, +	{ +		.number = U300_DMA_MSL_RX_2, +		.name = "MSL RX 2", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 2 * 0x40 + 0x220, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +	}, +	{ +		.number = U300_DMA_MSL_RX_3, +		.name = "MSL RX 3", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 3 * 0x40 + 0x220, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +	}, +	{ +		.number = U300_DMA_MSL_RX_4, +		.name = "MSL RX 4", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 4 * 0x40 + 0x220, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +	}, +	{ +		.number = U300_DMA_MSL_RX_5, +		.name = "MSL RX 5", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 5 * 0x40 + 0x220, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M2R_M1W | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_DEMAND_DMA1 | +				COH901318_CX_CTRL_PRDD_DEST, +	}, +	{ +		.number = U300_DMA_MSL_RX_6, +		.name = "MSL RX 6", +		.priority_high = 0, +		.dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220, +	}, +	{ +		.number = U300_DMA_MMCSD_RX_TX, +		.name = "MMCSD RX TX", +		.priority_high = 0, +		.dev_addr =  U300_MMCSD_BASE + 0x080, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_32_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY, + +	}, +	{ +		.number = U300_DMA_MSPRO_TX, +		.name = "MSPRO TX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_MSPRO_RX, +		.name = "MSPRO RX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_UART0_TX, +		.name = "UART0 TX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_UART0_RX, +		.name = "UART0 RX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_APEX_TX, +		.name = "APEX TX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_APEX_RX, +		.name = "APEX RX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_PCM_I2S0_TX, +		.name = "PCM I2S0 TX", +		.priority_high = 1, +		.dev_addr = U300_PCM_I2S0_BASE + 0x14, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +	}, +	{ +		.number = U300_DMA_PCM_I2S0_RX, +		.name = "PCM I2S0 RX", +		.priority_high = 1, +		.dev_addr = U300_PCM_I2S0_BASE + 0x10, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_DEST, +	}, +	{ +		.number = U300_DMA_PCM_I2S1_TX, +		.name = "PCM I2S1 TX", +		.priority_high = 1, +		.dev_addr =  U300_PCM_I2S1_BASE + 0x14, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_SOURCE, +	}, +	{ +		.number = U300_DMA_PCM_I2S1_RX, +		.name = "PCM I2S1 RX", +		.priority_high = 1, +		.dev_addr = U300_PCM_I2S1_BASE + 0x10, +		.param.config = COH901318_CX_CFG_CH_DISABLE | +				COH901318_CX_CFG_LCR_DISABLE | +				COH901318_CX_CFG_TC_IRQ_ENABLE | +				COH901318_CX_CFG_BE_IRQ_ENABLE, +		.param.ctrl_lli_chained = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_DISABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_DISABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_DEST, +		.param.ctrl_lli_last = 0 | +				COH901318_CX_CTRL_TC_ENABLE | +				COH901318_CX_CTRL_BURST_COUNT_16_BYTES | +				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE | +				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | +				COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | +				COH901318_CX_CTRL_MASTER_MODE_M1RW | +				COH901318_CX_CTRL_TCP_ENABLE | +				COH901318_CX_CTRL_TC_IRQ_ENABLE | +				COH901318_CX_CTRL_HSP_ENABLE | +				COH901318_CX_CTRL_HSS_DISABLE | +				COH901318_CX_CTRL_DDMA_LEGACY | +				COH901318_CX_CTRL_PRDD_DEST, +	}, +	{ +		.number = U300_DMA_XGAM_CDI, +		.name = "XGAM CDI", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_XGAM_PDI, +		.name = "XGAM PDI", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_SPI_TX, +		.name = "SPI TX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_SPI_RX, +		.name = "SPI RX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_0, +		.name = "GENERAL 00", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_1, +		.name = "GENERAL 01", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_2, +		.name = "GENERAL 02", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_3, +		.name = "GENERAL 03", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_4, +		.name = "GENERAL 04", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_5, +		.name = "GENERAL 05", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_6, +		.name = "GENERAL 06", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_7, +		.name = "GENERAL 07", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_8, +		.name = "GENERAL 08", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +#ifdef CONFIG_MACH_U300_BS335 +	{ +		.number = U300_DMA_UART1_TX, +		.name = "UART1 TX", +		.priority_high = 0, +	}, +	{ +		.number = U300_DMA_UART1_RX, +		.name = "UART1 RX", +		.priority_high = 0, +	} +#else +	{ +		.number = U300_DMA_GENERAL_PURPOSE_9, +		.name = "GENERAL 09", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	}, +	{ +		.number = U300_DMA_GENERAL_PURPOSE_10, +		.name = "GENERAL 10", +		.priority_high = 0, + +		.param.config = flags_memcpy_config, +		.param.ctrl_lli_chained = flags_memcpy_lli_chained, +		.param.ctrl_lli = flags_memcpy_lli, +		.param.ctrl_lli_last = flags_memcpy_lli_last, +	} +#endif +}; + + +static struct coh901318_platform coh901318_platform = { +	.chans_slave = dma_slave_channels, +	.chans_memcpy = dma_memcpy_channels, +	.access_memory_state = coh901318_access_memory_state, +	.chan_conf = chan_config, +	.max_channels = U300_DMA_CHANNELS, +}; +  static struct platform_device wdog_device = { -	.name = "wdog", +	.name = "coh901327_wdog",  	.id = -1,  	.num_resources = ARRAY_SIZE(wdog_resources),  	.resource = wdog_resources, @@ -428,11 +1441,23 @@ static struct platform_device ave_device = {  	.resource = ave_resources,  }; +static struct platform_device dma_device = { +	.name		= "coh901318", +	.id		= -1, +	.resource	= dma_resource, +	.num_resources  = ARRAY_SIZE(dma_resource), +	.dev = { +		.platform_data = &coh901318_platform, +		.coherent_dma_mask = ~0, +	}, +}; +  /*   * Notice that AMBA devices are initialized before platform devices.   *   */  static struct platform_device *platform_devs[] __initdata = { +	&dma_device,  	&i2c0_device,  	&i2c1_device,  	&keypad_device, diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c index 0b35826b7d1..5f61fd45a0c 100644 --- a/arch/arm/mach-u300/gpio.c +++ b/arch/arm/mach-u300/gpio.c @@ -546,7 +546,7 @@ static void gpio_set_initial_values(void)  	for (i = 0; i < U300_GPIO_MAX; i++) {  		val = 0;  		for (j = 0; j < 8; j++) -			val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP)) << j; +			val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j);  		local_irq_save(flags);  		writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);  		local_irq_restore(flags); diff --git a/arch/arm/mach-u300/include/mach/debug-macro.S b/arch/arm/mach-u300/include/mach/debug-macro.S index f3a1cbbeeab..ca4a028c266 100644 --- a/arch/arm/mach-u300/include/mach/debug-macro.S +++ b/arch/arm/mach-u300/include/mach/debug-macro.S @@ -10,7 +10,7 @@   */  #include <mach/hardware.h> -	.macro	addruart,rx +	.macro	addruart, rx, tmp  	/* If we move the adress using MMU, use this. */  	mrc	p15, 0, \rx, c1, c0  	tst	\rx, #1			@ MMU enabled? diff --git a/arch/arm/mach-u300/include/mach/dma_channels.h b/arch/arm/mach-u300/include/mach/dma_channels.h new file mode 100644 index 00000000000..b239149ba0d --- /dev/null +++ b/arch/arm/mach-u300/include/mach/dma_channels.h @@ -0,0 +1,69 @@ +/* + * + * arch/arm/mach-u300/include/mach/dma_channels.h + * + * + * Copyright (C) 2007-2009 ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + * Map file for the U300 dma driver. + * Author: Per Friden <per.friden@stericsson.com> + */ + +#ifndef DMA_CHANNELS_H +#define DMA_CHANNELS_H + +#define U300_DMA_MSL_TX_0             0 +#define U300_DMA_MSL_TX_1             1 +#define U300_DMA_MSL_TX_2             2 +#define U300_DMA_MSL_TX_3             3 +#define U300_DMA_MSL_TX_4             4 +#define U300_DMA_MSL_TX_5             5 +#define U300_DMA_MSL_TX_6             6 +#define U300_DMA_MSL_RX_0             7 +#define U300_DMA_MSL_RX_1             8 +#define U300_DMA_MSL_RX_2             9 +#define U300_DMA_MSL_RX_3             10 +#define U300_DMA_MSL_RX_4             11 +#define U300_DMA_MSL_RX_5             12 +#define U300_DMA_MSL_RX_6             13 +#define U300_DMA_MMCSD_RX_TX          14 +#define U300_DMA_MSPRO_TX             15 +#define U300_DMA_MSPRO_RX             16 +#define U300_DMA_UART0_TX             17 +#define U300_DMA_UART0_RX             18 +#define U300_DMA_APEX_TX              19 +#define U300_DMA_APEX_RX              20 +#define U300_DMA_PCM_I2S0_TX          21 +#define U300_DMA_PCM_I2S0_RX          22 +#define U300_DMA_PCM_I2S1_TX          23 +#define U300_DMA_PCM_I2S1_RX          24 +#define U300_DMA_XGAM_CDI             25 +#define U300_DMA_XGAM_PDI             26 +#define U300_DMA_SPI_TX               27 +#define U300_DMA_SPI_RX               28 +#define U300_DMA_GENERAL_PURPOSE_0    29 +#define U300_DMA_GENERAL_PURPOSE_1    30 +#define U300_DMA_GENERAL_PURPOSE_2    31 +#define U300_DMA_GENERAL_PURPOSE_3    32 +#define U300_DMA_GENERAL_PURPOSE_4    33 +#define U300_DMA_GENERAL_PURPOSE_5    34 +#define U300_DMA_GENERAL_PURPOSE_6    35 +#define U300_DMA_GENERAL_PURPOSE_7    36 +#define U300_DMA_GENERAL_PURPOSE_8    37 +#ifdef CONFIG_MACH_U300_BS335 +#define U300_DMA_UART1_TX             38 +#define U300_DMA_UART1_RX             39 +#else +#define U300_DMA_GENERAL_PURPOSE_9    38 +#define U300_DMA_GENERAL_PURPOSE_10   39 +#endif + +#ifdef CONFIG_MACH_U300_BS335 +#define U300_DMA_DEVICE_CHANNELS      32 +#else +#define U300_DMA_DEVICE_CHANNELS      30 +#endif +#define U300_DMA_CHANNELS             40 + + +#endif /* DMA_CHANNELS_H */ diff --git a/arch/arm/mach-u300/include/mach/vmalloc.h b/arch/arm/mach-u300/include/mach/vmalloc.h index b00c51a66fb..ec423b92b81 100644 --- a/arch/arm/mach-u300/include/mach/vmalloc.h +++ b/arch/arm/mach-u300/include/mach/vmalloc.h @@ -9,4 +9,4 @@   * End must be above the I/O registers and on an even 2MiB boundary.   * Author: Linus Walleij <linus.walleij@stericsson.com>   */ -#define VMALLOC_END	0xfe800000 +#define VMALLOC_END	0xfe800000UL diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index aa5afbcc90f..803aec1d672 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -22,6 +22,7 @@  #include <asm/mach/arch.h>  #include <plat/mtu.h> +#include <plat/i2c.h>  #include <mach/hardware.h>  #include <mach/setup.h> @@ -108,11 +109,96 @@ static struct amba_device pl022_device = {  	.periphid = SSP_PER_ID,  }; +static struct amba_device pl031_device = { +	.dev = { +		.init_name = "pl031", +	}, +	.res = { +		.start = U8500_RTC_BASE, +		.end = U8500_RTC_BASE + SZ_4K - 1, +		.flags = IORESOURCE_MEM, +	}, +	.irq = {IRQ_RTC_RTT, NO_IRQ}, +}; + +#define U8500_I2C_RESOURCES(id, size)		\ +static struct resource u8500_i2c_resources_##id[] = {	\ +	[0] = {					\ +		.start	= U8500_I2C##id##_BASE,	\ +		.end	= U8500_I2C##id##_BASE + size - 1, \ +		.flags	= IORESOURCE_MEM,	\ +	},					\ +	[1] = {					\ +		.start	= IRQ_I2C##id,		\ +		.end	= IRQ_I2C##id,		\ +		.flags	= IORESOURCE_IRQ	\ +	}					\ +} + +U8500_I2C_RESOURCES(0, SZ_4K); +U8500_I2C_RESOURCES(1, SZ_4K); +U8500_I2C_RESOURCES(2, SZ_4K); +U8500_I2C_RESOURCES(3, SZ_4K); + +#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ +static struct nmk_i2c_controller u8500_i2c_##id = { \ +	/*				\ +	 * slave data setup time, which is	\ +	 * 250 ns,100ns,10ns which is 14,6,2	\ +	 * respectively for a 48 Mhz	\ +	 * i2c clock			\ +	 */				\ +	.slsu		= _slsu,	\ +	/* Tx FIFO threshold */		\ +	.tft		= _tft,		\ +	/* Rx FIFO threshold */		\ +	.rft		= _rft,		\ +	/* std. mode operation */	\ +	.clk_freq	= clk,		\ +	.sm		= _sm,		\ +} + +/* + * The board uses 4 i2c controllers, initialize all of + * them with slave data setup time of 250 ns, + * Tx & Rx FIFO threshold values as 1 and standard + * mode of operation + */ +U8500_I2C_CONTROLLER(0, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); +U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); +U8500_I2C_CONTROLLER(2,	0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); +U8500_I2C_CONTROLLER(3,	0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); + +#define U8500_I2C_PDEVICE(cid)		\ +static struct platform_device i2c_controller##cid = { \ +	.name = "nmk-i2c",		\ +	.id	 = cid,			\ +	.num_resources = 2,		\ +	.resource = u8500_i2c_resources_##cid,	\ +	.dev = {			\ +		.platform_data = &u8500_i2c_##cid \ +	}				\ +} + +U8500_I2C_PDEVICE(0); +U8500_I2C_PDEVICE(1); +U8500_I2C_PDEVICE(2); +U8500_I2C_PDEVICE(3); +  static struct amba_device *amba_devs[] __initdata = {  	&uart0_device,  	&uart1_device,  	&uart2_device,  	&pl022_device, +	&pl031_device, +}; + +/* add any platform devices here - TODO */ +static struct platform_device *platform_devs[] __initdata = { +	&i2c_controller0, +	&i2c_controller1, +	&i2c_controller2, +	&i2c_controller3,  };  static void __init u8500_timer_init(void) @@ -139,6 +225,8 @@ static void __init u8500_init_machine(void)  	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)  		amba_device_register(amba_devs[i], &iomem_resource); +	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); +  	spi_register_board_info(u8500_spi_devices,  			ARRAY_SIZE(u8500_spi_devices)); diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 5f05e5850f7..397bc1f9ed9 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -33,6 +33,7 @@ static struct platform_device *platform_devs[] __initdata = {  /* minimum static i/o mapping required to boot U8500 platforms */  static struct map_desc u8500_io_desc[] __initdata = { +	__IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),  	__IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K),  	__IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),  	__IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S index 8f21b6a95dc..09cbfda8aee 100644 --- a/arch/arm/mach-ux500/include/mach/debug-macro.S +++ b/arch/arm/mach-ux500/include/mach/debug-macro.S @@ -8,12 +8,13 @@   * published by the Free Software Foundation.   *   */ -	.macro	addruart,rx +#include <mach/hardware.h> + +	.macro	addruart, rx, tmp  	mrc	p15, 0, \rx, c1, c0 -	tst	\rx, #1			@MMU enabled? -	moveq	\rx, #0x80000000	@MMU off, Physical address -	movne	\rx, #0xF0000000	@MMU on, Virtual address -	orr	\rx, \rx, #0x7000 +	tst	\rx, #1					@ MMU enabled? +	ldreq	\rx, =U8500_UART2_BASE			@ no, physical address +	ldrne	\rx, =IO_ADDRESS(U8500_UART2_BASE)	@ yes, virtual address  	.endm  #include <asm/hardware/debug-pl01x.S> diff --git a/arch/arm/mach-ux500/include/mach/vmalloc.h b/arch/arm/mach-ux500/include/mach/vmalloc.h index 86cdbbce184..a4945cb4117 100644 --- a/arch/arm/mach-ux500/include/mach/vmalloc.h +++ b/arch/arm/mach-ux500/include/mach/vmalloc.h @@ -15,4 +15,4 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ -#define VMALLOC_END	0xf0000000 +#define VMALLOC_END	0xf0000000UL diff --git a/arch/arm/mach-versatile/include/mach/debug-macro.S b/arch/arm/mach-versatile/include/mach/debug-macro.S index b4ac00eacf6..6fea7199c62 100644 --- a/arch/arm/mach-versatile/include/mach/debug-macro.S +++ b/arch/arm/mach-versatile/include/mach/debug-macro.S @@ -11,7 +11,7 @@   *  */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx,      #0x10000000 diff --git a/arch/arm/mach-w90x900/cpu.c b/arch/arm/mach-w90x900/cpu.c index 6f5ca532883..642207e1819 100644 --- a/arch/arm/mach-w90x900/cpu.c +++ b/arch/arm/mach-w90x900/cpu.c @@ -45,6 +45,7 @@ static struct map_desc nuc900_iodesc[] __initdata = {  	IODESC_ENT(UART),  	IODESC_ENT(TIMER),  	IODESC_ENT(EBI), +	IODESC_ENT(GPIO),  };  /* Initial clock declarations. */ @@ -68,6 +69,11 @@ static DEFINE_CLK(gdma, 27);  static DEFINE_CLK(adc, 28);  static DEFINE_CLK(usi, 29);  static DEFINE_CLK(ext, 0); +static DEFINE_CLK(timer0, 19); +static DEFINE_CLK(timer1, 20); +static DEFINE_CLK(timer2, 21); +static DEFINE_CLK(timer3, 22); +static DEFINE_CLK(timer4, 23);  static struct clk_lookup nuc900_clkregs[] = {  	DEF_CLKLOOK(&clk_lcd, "nuc900-lcd", NULL), @@ -90,6 +96,11 @@ static struct clk_lookup nuc900_clkregs[] = {  	DEF_CLKLOOK(&clk_adc, "nuc900-adc", NULL),  	DEF_CLKLOOK(&clk_usi, "nuc900-spi", NULL),  	DEF_CLKLOOK(&clk_ext, NULL, "ext"), +	DEF_CLKLOOK(&clk_timer0, NULL, "timer0"), +	DEF_CLKLOOK(&clk_timer1, NULL, "timer1"), +	DEF_CLKLOOK(&clk_timer2, NULL, "timer2"), +	DEF_CLKLOOK(&clk_timer3, NULL, "timer3"), +	DEF_CLKLOOK(&clk_timer4, NULL, "timer4"),  };  /* Initial serial platform data */ diff --git a/arch/arm/mach-w90x900/include/mach/vmalloc.h b/arch/arm/mach-w90x900/include/mach/vmalloc.h index 2f9dfb92853..b067e44500a 100644 --- a/arch/arm/mach-w90x900/include/mach/vmalloc.h +++ b/arch/arm/mach-w90x900/include/mach/vmalloc.h @@ -18,6 +18,6 @@  #ifndef __ASM_ARCH_VMALLOC_H  #define __ASM_ARCH_VMALLOC_H -#define VMALLOC_END	  (0xE0000000) +#define VMALLOC_END	  (0xe0000000UL)  #endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index baf638487a2..c4ed9f93f64 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -399,7 +399,7 @@ config CPU_V6  config CPU_32v6K  	bool "Support ARM V6K processor extensions" if !SMP  	depends on CPU_V6 -	default y if SMP && !ARCH_MX3 +	default y if SMP && !(ARCH_MX3 || ARCH_OMAP2)  	help  	  Say Y here if your ARMv6 processor supports the 'K' extension.  	  This enables the kernel to use some instructions not present @@ -410,7 +410,7 @@ config CPU_32v6K  # ARMv7  config CPU_V7  	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX -	select CPU_32v6K +	select CPU_32v6K if !ARCH_OMAP2  	select CPU_32v7  	select CPU_ABRT_EV7  	select CPU_PABRT_V7 @@ -754,7 +754,7 @@ config CACHE_FEROCEON_L2_WRITETHROUGH  config CACHE_L2X0  	bool "Enable the L2x0 outer cache controller"  	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ -		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK +		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK || ARCH_OMAP4  	default y  	select OUTER_CACHE  	help @@ -779,5 +779,5 @@ config CACHE_XSC3L2  config ARM_L1_CACHE_SHIFT  	int -	default 6 if ARCH_OMAP3 || ARCH_S5PC1XX +	default 6 if ARM_L1_CACHE_SHIFT_6  	default 5 diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index b270d6228fe..0c5eb6983ce 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -898,11 +898,7 @@ static int __init alignment_init(void)  #ifdef CONFIG_PROC_FS  	struct proc_dir_entry *res; -	res = proc_mkdir("cpu", NULL); -	if (!res) -		return -ENOMEM; - -	res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res); +	res = create_proc_entry("cpu/alignment", S_IWUSR | S_IRUGO, NULL);  	if (!res)  		return -ENOMEM; diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index a89444a3c01..7148e53e607 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S @@ -157,7 +157,7 @@ ENTRY(fa_flush_kern_dcache_area)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(fa_dma_inv_range) +fa_dma_inv_range:  	tst	r0, #CACHE_DLINESIZE - 1  	bic	r0, r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c14, 1		@ clean & invalidate D entry @@ -180,7 +180,7 @@ ENTRY(fa_dma_inv_range)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(fa_dma_clean_range) +fa_dma_clean_range:  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  	add	r0, r0, #CACHE_DLINESIZE @@ -205,6 +205,30 @@ ENTRY(fa_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(fa_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	fa_dma_clean_range +	bcs	fa_dma_inv_range +	b	fa_dma_flush_range +ENDPROC(fa_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(fa_dma_unmap_area) +	mov	pc, lr +ENDPROC(fa_dma_unmap_area) +  	__INITDATA  	.type	fa_cache_fns, #object @@ -215,7 +239,7 @@ ENTRY(fa_cache_fns)  	.long	fa_coherent_kern_range  	.long	fa_coherent_user_range  	.long	fa_flush_kern_dcache_area -	.long	fa_dma_inv_range -	.long	fa_dma_clean_range +	.long	fa_dma_map_area +	.long	fa_dma_unmap_area  	.long	fa_dma_flush_range  	.size	fa_cache_fns, . - fa_cache_fns diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index cb8fc6573b1..07334632d3e 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -42,6 +42,57 @@ static inline void cache_sync(void)  	cache_wait(base + L2X0_CACHE_SYNC, 1);  } +static inline void l2x0_clean_line(unsigned long addr) +{ +	void __iomem *base = l2x0_base; +	cache_wait(base + L2X0_CLEAN_LINE_PA, 1); +	writel(addr, base + L2X0_CLEAN_LINE_PA); +} + +static inline void l2x0_inv_line(unsigned long addr) +{ +	void __iomem *base = l2x0_base; +	cache_wait(base + L2X0_INV_LINE_PA, 1); +	writel(addr, base + L2X0_INV_LINE_PA); +} + +#ifdef CONFIG_PL310_ERRATA_588369 +static void debug_writel(unsigned long val) +{ +	extern void omap_smc1(u32 fn, u32 arg); + +	/* +	 * Texas Instrument secure monitor api to modify the +	 * PL310 Debug Control Register. +	 */ +	omap_smc1(0x100, val); +} + +static inline void l2x0_flush_line(unsigned long addr) +{ +	void __iomem *base = l2x0_base; + +	/* Clean by PA followed by Invalidate by PA */ +	cache_wait(base + L2X0_CLEAN_LINE_PA, 1); +	writel(addr, base + L2X0_CLEAN_LINE_PA); +	cache_wait(base + L2X0_INV_LINE_PA, 1); +	writel(addr, base + L2X0_INV_LINE_PA); +} +#else + +/* Optimised out for non-errata case */ +static inline void debug_writel(unsigned long val) +{ +} + +static inline void l2x0_flush_line(unsigned long addr) +{ +	void __iomem *base = l2x0_base; +	cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); +	writel(addr, base + L2X0_CLEAN_INV_LINE_PA); +} +#endif +  static inline void l2x0_inv_all(void)  {  	unsigned long flags; @@ -62,23 +113,24 @@ static void l2x0_inv_range(unsigned long start, unsigned long end)  	spin_lock_irqsave(&l2x0_lock, flags);  	if (start & (CACHE_LINE_SIZE - 1)) {  		start &= ~(CACHE_LINE_SIZE - 1); -		cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); -		writel(start, base + L2X0_CLEAN_INV_LINE_PA); +		debug_writel(0x03); +		l2x0_flush_line(start); +		debug_writel(0x00);  		start += CACHE_LINE_SIZE;  	}  	if (end & (CACHE_LINE_SIZE - 1)) {  		end &= ~(CACHE_LINE_SIZE - 1); -		cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); -		writel(end, base + L2X0_CLEAN_INV_LINE_PA); +		debug_writel(0x03); +		l2x0_flush_line(end); +		debug_writel(0x00);  	}  	while (start < end) {  		unsigned long blk_end = start + min(end - start, 4096UL);  		while (start < blk_end) { -			cache_wait(base + L2X0_INV_LINE_PA, 1); -			writel(start, base + L2X0_INV_LINE_PA); +			l2x0_inv_line(start);  			start += CACHE_LINE_SIZE;  		} @@ -103,8 +155,7 @@ static void l2x0_clean_range(unsigned long start, unsigned long end)  		unsigned long blk_end = start + min(end - start, 4096UL);  		while (start < blk_end) { -			cache_wait(base + L2X0_CLEAN_LINE_PA, 1); -			writel(start, base + L2X0_CLEAN_LINE_PA); +			l2x0_clean_line(start);  			start += CACHE_LINE_SIZE;  		} @@ -128,11 +179,12 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)  	while (start < end) {  		unsigned long blk_end = start + min(end - start, 4096UL); +		debug_writel(0x03);  		while (start < blk_end) { -			cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); -			writel(start, base + L2X0_CLEAN_INV_LINE_PA); +			l2x0_flush_line(start);  			start += CACHE_LINE_SIZE;  		} +		debug_writel(0x00);  		if (blk_end < end) {  			spin_unlock_irqrestore(&l2x0_lock, flags); diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index 2a482731ea3..c2ff3c599fe 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -84,20 +84,6 @@ ENTRY(v3_flush_kern_dcache_area)  	/* FALLTHROUGH */  /* - *	dma_inv_range(start, end) - * - *	Invalidate (discard) the specified virtual address range. - *	May not write back any entries.  If 'start' or 'end' - *	are not cache line aligned, those lines must be written - *	back. - * - *	- start  - virtual start address - *	- end	 - virtual end address - */ -ENTRY(v3_dma_inv_range) -	/* FALLTHROUGH */ - -/*   *	dma_flush_range(start, end)   *   *	Clean and invalidate the specified virtual address range. @@ -108,18 +94,29 @@ ENTRY(v3_dma_inv_range)  ENTRY(v3_dma_flush_range)  	mov	r0, #0  	mcr	p15, 0, r0, c7, c0, 0		@ flush ID cache +	mov	pc, lr + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v3_dma_unmap_area) +	teq	r2, #DMA_TO_DEVICE +	bne	v3_dma_flush_range  	/* FALLTHROUGH */  /* - *	dma_clean_range(start, end) - * - *	Clean (write back) the specified virtual address range. - * - *	- start  - virtual start address - *	- end	 - virtual end address + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction   */ -ENTRY(v3_dma_clean_range) +ENTRY(v3_dma_map_area)  	mov	pc, lr +ENDPROC(v3_dma_unmap_area) +ENDPROC(v3_dma_map_area)  	__INITDATA @@ -131,7 +128,7 @@ ENTRY(v3_cache_fns)  	.long	v3_coherent_kern_range  	.long	v3_coherent_user_range  	.long	v3_flush_kern_dcache_area -	.long	v3_dma_inv_range -	.long	v3_dma_clean_range +	.long	v3_dma_map_area +	.long	v3_dma_unmap_area  	.long	v3_dma_flush_range  	.size	v3_cache_fns, . - v3_cache_fns diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index 5c7da3e372e..4810f7e3e81 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -94,20 +94,6 @@ ENTRY(v4_flush_kern_dcache_area)  	/* FALLTHROUGH */  /* - *	dma_inv_range(start, end) - * - *	Invalidate (discard) the specified virtual address range. - *	May not write back any entries.  If 'start' or 'end' - *	are not cache line aligned, those lines must be written - *	back. - * - *	- start  - virtual start address - *	- end	 - virtual end address - */ -ENTRY(v4_dma_inv_range) -	/* FALLTHROUGH */ - -/*   *	dma_flush_range(start, end)   *   *	Clean and invalidate the specified virtual address range. @@ -120,18 +106,29 @@ ENTRY(v4_dma_flush_range)  	mov	r0, #0  	mcr	p15, 0, r0, c7, c7, 0		@ flush ID cache  #endif +	mov	pc, lr + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v4_dma_unmap_area) +	teq	r2, #DMA_TO_DEVICE +	bne	v4_dma_flush_range  	/* FALLTHROUGH */  /* - *	dma_clean_range(start, end) - * - *	Clean (write back) the specified virtual address range. - * - *	- start  - virtual start address - *	- end	 - virtual end address + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction   */ -ENTRY(v4_dma_clean_range) +ENTRY(v4_dma_map_area)  	mov	pc, lr +ENDPROC(v4_dma_unmap_area) +ENDPROC(v4_dma_map_area)  	__INITDATA @@ -143,7 +140,7 @@ ENTRY(v4_cache_fns)  	.long	v4_coherent_kern_range  	.long	v4_coherent_user_range  	.long	v4_flush_kern_dcache_area -	.long	v4_dma_inv_range -	.long	v4_dma_clean_range +	.long	v4_dma_map_area +	.long	v4_dma_unmap_area  	.long	v4_dma_flush_range  	.size	v4_cache_fns, . - v4_cache_fns diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 3dbedf1ec0e..df8368afa10 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -173,7 +173,7 @@ ENTRY(v4wb_coherent_user_range)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(v4wb_dma_inv_range) +v4wb_dma_inv_range:  	tst	r0, #CACHE_DLINESIZE - 1  	bic	r0, r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -194,7 +194,7 @@ ENTRY(v4wb_dma_inv_range)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(v4wb_dma_clean_range) +v4wb_dma_clean_range:  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  	add	r0, r0, #CACHE_DLINESIZE @@ -216,6 +216,30 @@ ENTRY(v4wb_dma_clean_range)  	.globl	v4wb_dma_flush_range  	.set	v4wb_dma_flush_range, v4wb_coherent_kern_range +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v4wb_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	v4wb_dma_clean_range +	bcs	v4wb_dma_inv_range +	b	v4wb_dma_flush_range +ENDPROC(v4wb_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v4wb_dma_unmap_area) +	mov	pc, lr +ENDPROC(v4wb_dma_unmap_area) +  	__INITDATA  	.type	v4wb_cache_fns, #object @@ -226,7 +250,7 @@ ENTRY(v4wb_cache_fns)  	.long	v4wb_coherent_kern_range  	.long	v4wb_coherent_user_range  	.long	v4wb_flush_kern_dcache_area -	.long	v4wb_dma_inv_range -	.long	v4wb_dma_clean_range +	.long	v4wb_dma_map_area +	.long	v4wb_dma_unmap_area  	.long	v4wb_dma_flush_range  	.size	v4wb_cache_fns, . - v4wb_cache_fns diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index b3b7410270b..45c70312f43 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -142,23 +142,12 @@ ENTRY(v4wt_flush_kern_dcache_area)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(v4wt_dma_inv_range) +v4wt_dma_inv_range:  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry  	add	r0, r0, #CACHE_DLINESIZE  	cmp	r0, r1  	blo	1b -	/* FALLTHROUGH */ - -/* - *	dma_clean_range(start, end) - * - *	Clean the specified virtual address range. - * - *	- start  - virtual start address - *	- end	 - virtual end address - */ -ENTRY(v4wt_dma_clean_range)  	mov	pc, lr  /* @@ -172,6 +161,29 @@ ENTRY(v4wt_dma_clean_range)  	.globl	v4wt_dma_flush_range  	.equ	v4wt_dma_flush_range, v4wt_dma_inv_range +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v4wt_dma_unmap_area) +	add	r1, r1, r0 +	teq	r2, #DMA_TO_DEVICE +	bne	v4wt_dma_inv_range +	/* FALLTHROUGH */ + +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v4wt_dma_map_area) +	mov	pc, lr +ENDPROC(v4wt_dma_unmap_area) +ENDPROC(v4wt_dma_map_area) +  	__INITDATA  	.type	v4wt_cache_fns, #object @@ -182,7 +194,7 @@ ENTRY(v4wt_cache_fns)  	.long	v4wt_coherent_kern_range  	.long	v4wt_coherent_user_range  	.long	v4wt_flush_kern_dcache_area -	.long	v4wt_dma_inv_range -	.long	v4wt_dma_clean_range +	.long	v4wt_dma_map_area +	.long	v4wt_dma_unmap_area  	.long	v4wt_dma_flush_range  	.size	v4wt_cache_fns, . - v4wt_cache_fns diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 4ba0a24ce6f..9d89c67a1cc 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -195,7 +195,7 @@ ENTRY(v6_flush_kern_dcache_area)   *	- start   - virtual start address of region   *	- end     - virtual end address of region   */ -ENTRY(v6_dma_inv_range) +v6_dma_inv_range:  	tst	r0, #D_CACHE_LINE_SIZE - 1  	bic	r0, r0, #D_CACHE_LINE_SIZE - 1  #ifdef HARVARD_CACHE @@ -228,7 +228,7 @@ ENTRY(v6_dma_inv_range)   *	- start   - virtual start address of region   *	- end     - virtual end address of region   */ -ENTRY(v6_dma_clean_range) +v6_dma_clean_range:  	bic	r0, r0, #D_CACHE_LINE_SIZE - 1  1:  #ifdef HARVARD_CACHE @@ -263,6 +263,32 @@ ENTRY(v6_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v6_dma_map_area) +	add	r1, r1, r0 +	teq	r2, #DMA_FROM_DEVICE +	beq	v6_dma_inv_range +	b	v6_dma_clean_range +ENDPROC(v6_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v6_dma_unmap_area) +	add	r1, r1, r0 +	teq	r2, #DMA_TO_DEVICE +	bne	v6_dma_inv_range +	mov	pc, lr +ENDPROC(v6_dma_unmap_area) +  	__INITDATA  	.type	v6_cache_fns, #object @@ -273,7 +299,7 @@ ENTRY(v6_cache_fns)  	.long	v6_coherent_kern_range  	.long	v6_coherent_user_range  	.long	v6_flush_kern_dcache_area -	.long	v6_dma_inv_range -	.long	v6_dma_clean_range +	.long	v6_dma_map_area +	.long	v6_dma_unmap_area  	.long	v6_dma_flush_range  	.size	v6_cache_fns, . - v6_cache_fns diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 9073db849fb..bcd64f26587 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -216,7 +216,7 @@ ENDPROC(v7_flush_kern_dcache_area)   *	- start   - virtual start address of region   *	- end     - virtual end address of region   */ -ENTRY(v7_dma_inv_range) +v7_dma_inv_range:  	dcache_line_size r2, r3  	sub	r3, r2, #1  	tst	r0, r3 @@ -240,7 +240,7 @@ ENDPROC(v7_dma_inv_range)   *	- start   - virtual start address of region   *	- end     - virtual end address of region   */ -ENTRY(v7_dma_clean_range) +v7_dma_clean_range:  	dcache_line_size r2, r3  	sub	r3, r2, #1  	bic	r0, r0, r3 @@ -271,6 +271,32 @@ ENTRY(v7_dma_flush_range)  	mov	pc, lr  ENDPROC(v7_dma_flush_range) +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v7_dma_map_area) +	add	r1, r1, r0 +	teq	r2, #DMA_FROM_DEVICE +	beq	v7_dma_inv_range +	b	v7_dma_clean_range +ENDPROC(v7_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(v7_dma_unmap_area) +	add	r1, r1, r0 +	teq	r2, #DMA_TO_DEVICE +	bne	v7_dma_inv_range +	mov	pc, lr +ENDPROC(v7_dma_unmap_area) +  	__INITDATA  	.type	v7_cache_fns, #object @@ -281,7 +307,7 @@ ENTRY(v7_cache_fns)  	.long	v7_coherent_kern_range  	.long	v7_coherent_user_range  	.long	v7_flush_kern_dcache_area -	.long	v7_dma_inv_range -	.long	v7_dma_clean_range +	.long	v7_dma_map_area +	.long	v7_dma_unmap_area  	.long	v7_dma_flush_range  	.size	v7_cache_fns, . - v7_cache_fns diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index a9e22e31eaa..b0ee9ba3cfa 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -10,12 +10,17 @@  #include <linux/init.h>  #include <linux/sched.h>  #include <linux/mm.h> +#include <linux/smp.h> +#include <linux/percpu.h>  #include <asm/mmu_context.h>  #include <asm/tlbflush.h>  static DEFINE_SPINLOCK(cpu_asid_lock);  unsigned int cpu_last_asid = ASID_FIRST_VERSION; +#ifdef CONFIG_SMP +DEFINE_PER_CPU(struct mm_struct *, current_mm); +#endif  /*   * We fork()ed a process, and we need a new context for the child @@ -26,13 +31,109 @@ unsigned int cpu_last_asid = ASID_FIRST_VERSION;  void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)  {  	mm->context.id = 0; +	spin_lock_init(&mm->context.id_lock);  } +static void flush_context(void) +{ +	/* set the reserved ASID before flushing the TLB */ +	asm("mcr	p15, 0, %0, c13, c0, 1\n" : : "r" (0)); +	isb(); +	local_flush_tlb_all(); +	if (icache_is_vivt_asid_tagged()) { +		__flush_icache_all(); +		dsb(); +	} +} + +#ifdef CONFIG_SMP + +static void set_mm_context(struct mm_struct *mm, unsigned int asid) +{ +	unsigned long flags; + +	/* +	 * Locking needed for multi-threaded applications where the +	 * same mm->context.id could be set from different CPUs during +	 * the broadcast. This function is also called via IPI so the +	 * mm->context.id_lock has to be IRQ-safe. +	 */ +	spin_lock_irqsave(&mm->context.id_lock, flags); +	if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) { +		/* +		 * Old version of ASID found. Set the new one and +		 * reset mm_cpumask(mm). +		 */ +		mm->context.id = asid; +		cpumask_clear(mm_cpumask(mm)); +	} +	spin_unlock_irqrestore(&mm->context.id_lock, flags); + +	/* +	 * Set the mm_cpumask(mm) bit for the current CPU. +	 */ +	cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); +} + +/* + * Reset the ASID on the current CPU. This function call is broadcast + * from the CPU handling the ASID rollover and holding cpu_asid_lock. + */ +static void reset_context(void *info) +{ +	unsigned int asid; +	unsigned int cpu = smp_processor_id(); +	struct mm_struct *mm = per_cpu(current_mm, cpu); + +	/* +	 * Check if a current_mm was set on this CPU as it might still +	 * be in the early booting stages and using the reserved ASID. +	 */ +	if (!mm) +		return; + +	smp_rmb(); +	asid = cpu_last_asid + cpu + 1; + +	flush_context(); +	set_mm_context(mm, asid); + +	/* set the new ASID */ +	asm("mcr	p15, 0, %0, c13, c0, 1\n" : : "r" (mm->context.id)); +	isb(); +} + +#else + +static inline void set_mm_context(struct mm_struct *mm, unsigned int asid) +{ +	mm->context.id = asid; +	cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id())); +} + +#endif +  void __new_context(struct mm_struct *mm)  {  	unsigned int asid;  	spin_lock(&cpu_asid_lock); +#ifdef CONFIG_SMP +	/* +	 * Check the ASID again, in case the change was broadcast from +	 * another CPU before we acquired the lock. +	 */ +	if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) { +		cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); +		spin_unlock(&cpu_asid_lock); +		return; +	} +#endif +	/* +	 * At this point, it is guaranteed that the current mm (with +	 * an old ASID) isn't active on any other CPU since the ASIDs +	 * are changed simultaneously via IPI. +	 */  	asid = ++cpu_last_asid;  	if (asid == 0)  		asid = cpu_last_asid = ASID_FIRST_VERSION; @@ -42,20 +143,15 @@ void __new_context(struct mm_struct *mm)  	 * to start a new version and flush the TLB.  	 */  	if (unlikely((asid & ~ASID_MASK) == 0)) { -		asid = ++cpu_last_asid; -		/* set the reserved ASID before flushing the TLB */ -		asm("mcr	p15, 0, %0, c13, c0, 1	@ set reserved context ID\n" -		    : -		    : "r" (0)); -		isb(); -		flush_tlb_all(); -		if (icache_is_vivt_asid_tagged()) { -			__flush_icache_all(); -			dsb(); -		} +		asid = cpu_last_asid + smp_processor_id() + 1; +		flush_context(); +#ifdef CONFIG_SMP +		smp_wmb(); +		smp_call_function(reset_context, NULL, 1); +#endif +		cpu_last_asid += NR_CPUS;  	} -	spin_unlock(&cpu_asid_lock); -	cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id())); -	mm->context.id = asid; +	set_mm_context(mm, asid); +	spin_unlock(&cpu_asid_lock);  } diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c index 70997d5bee2..5eb4fd93893 100644 --- a/arch/arm/mm/copypage-feroceon.c +++ b/arch/arm/mm/copypage-feroceon.c @@ -68,12 +68,13 @@ feroceon_copy_user_page(void *kto, const void *kfrom)  }  void feroceon_copy_user_highpage(struct page *to, struct page *from, -	unsigned long vaddr) +	unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto, *kfrom;  	kto = kmap_atomic(to, KM_USER0);  	kfrom = kmap_atomic(from, KM_USER1); +	flush_cache_page(vma, vaddr, page_to_pfn(from));  	feroceon_copy_user_page(kto, kfrom);  	kunmap_atomic(kfrom, KM_USER1);  	kunmap_atomic(kto, KM_USER0); diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c index de9c06854ad..f72303e1d80 100644 --- a/arch/arm/mm/copypage-v3.c +++ b/arch/arm/mm/copypage-v3.c @@ -38,7 +38,7 @@ v3_copy_user_page(void *kto, const void *kfrom)  }  void v3_copy_user_highpage(struct page *to, struct page *from, -	unsigned long vaddr) +	unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto, *kfrom; diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index 7370a7142b0..598c51ad507 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -69,7 +69,7 @@ mc_copy_user_page(void *from, void *to)  }  void v4_mc_copy_user_highpage(struct page *to, struct page *from, -	unsigned long vaddr) +	unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto = kmap_atomic(to, KM_USER1); diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c index 9ab09841422..7c2eb55cd4a 100644 --- a/arch/arm/mm/copypage-v4wb.c +++ b/arch/arm/mm/copypage-v4wb.c @@ -48,12 +48,13 @@ v4wb_copy_user_page(void *kto, const void *kfrom)  }  void v4wb_copy_user_highpage(struct page *to, struct page *from, -	unsigned long vaddr) +	unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto, *kfrom;  	kto = kmap_atomic(to, KM_USER0);  	kfrom = kmap_atomic(from, KM_USER1); +	flush_cache_page(vma, vaddr, page_to_pfn(from));  	v4wb_copy_user_page(kto, kfrom);  	kunmap_atomic(kfrom, KM_USER1);  	kunmap_atomic(kto, KM_USER0); diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c index 300efafd664..172e6a55458 100644 --- a/arch/arm/mm/copypage-v4wt.c +++ b/arch/arm/mm/copypage-v4wt.c @@ -44,7 +44,7 @@ v4wt_copy_user_page(void *kto, const void *kfrom)  }  void v4wt_copy_user_highpage(struct page *to, struct page *from, -	unsigned long vaddr) +	unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto, *kfrom; diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index 0fa1319273d..8bca4dea6df 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -34,7 +34,7 @@ static DEFINE_SPINLOCK(v6_lock);   * attack the kernel's existing mapping of these pages.   */  static void v6_copy_user_highpage_nonaliasing(struct page *to, -	struct page *from, unsigned long vaddr) +	struct page *from, unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto, *kfrom; @@ -81,7 +81,7 @@ static void discard_old_kernel_data(void *kto)   * Copy the page, taking account of the cache colour.   */  static void v6_copy_user_highpage_aliasing(struct page *to, -	struct page *from, unsigned long vaddr) +	struct page *from, unsigned long vaddr, struct vm_area_struct *vma)  {  	unsigned int offset = CACHE_COLOUR(vaddr);  	unsigned long kfrom, kto; diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c index bc4525f5ab2..747ad4140fc 100644 --- a/arch/arm/mm/copypage-xsc3.c +++ b/arch/arm/mm/copypage-xsc3.c @@ -71,12 +71,13 @@ xsc3_mc_copy_user_page(void *kto, const void *kfrom)  }  void xsc3_mc_copy_user_highpage(struct page *to, struct page *from, -	unsigned long vaddr) +	unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto, *kfrom;  	kto = kmap_atomic(to, KM_USER0);  	kfrom = kmap_atomic(from, KM_USER1); +	flush_cache_page(vma, vaddr, page_to_pfn(from));  	xsc3_mc_copy_user_page(kto, kfrom);  	kunmap_atomic(kfrom, KM_USER1);  	kunmap_atomic(kto, KM_USER0); diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index 76824d3e966..9920c0ae209 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c @@ -91,7 +91,7 @@ mc_copy_user_page(void *from, void *to)  }  void xscale_mc_copy_user_highpage(struct page *to, struct page *from, -	unsigned long vaddr) +	unsigned long vaddr, struct vm_area_struct *vma)  {  	void *kto = kmap_atomic(to, KM_USER1); diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 26325cb5d36..0da7eccf774 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -29,9 +29,6 @@  #error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"  #endif -#define CONSISTENT_END	(0xffe00000) -#define CONSISTENT_BASE	(CONSISTENT_END - CONSISTENT_DMA_SIZE) -  #define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)  #define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)  #define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) @@ -404,78 +401,44 @@ EXPORT_SYMBOL(dma_free_coherent);   * platforms with CONFIG_DMABOUNCE.   * Use the driver DMA support - see dma-mapping.h (dma_sync_*)   */ -void dma_cache_maint(const void *start, size_t size, int direction) +void ___dma_single_cpu_to_dev(const void *kaddr, size_t size, +	enum dma_data_direction dir)  { -	void (*inner_op)(const void *, const void *); -	void (*outer_op)(unsigned long, unsigned long); +	unsigned long paddr; -	BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1)); +	BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1)); -	switch (direction) { -	case DMA_FROM_DEVICE:		/* invalidate only */ -		inner_op = dmac_inv_range; -		outer_op = outer_inv_range; -		break; -	case DMA_TO_DEVICE:		/* writeback only */ -		inner_op = dmac_clean_range; -		outer_op = outer_clean_range; -		break; -	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */ -		inner_op = dmac_flush_range; -		outer_op = outer_flush_range; -		break; -	default: -		BUG(); -	} +	dmac_map_area(kaddr, size, dir); -	inner_op(start, start + size); -	outer_op(__pa(start), __pa(start) + size); +	paddr = __pa(kaddr); +	if (dir == DMA_FROM_DEVICE) { +		outer_inv_range(paddr, paddr + size); +	} else { +		outer_clean_range(paddr, paddr + size); +	} +	/* FIXME: non-speculating: flush on bidirectional mappings? */  } -EXPORT_SYMBOL(dma_cache_maint); +EXPORT_SYMBOL(___dma_single_cpu_to_dev); -static void dma_cache_maint_contiguous(struct page *page, unsigned long offset, -				       size_t size, int direction) +void ___dma_single_dev_to_cpu(const void *kaddr, size_t size, +	enum dma_data_direction dir)  { -	void *vaddr; -	unsigned long paddr; -	void (*inner_op)(const void *, const void *); -	void (*outer_op)(unsigned long, unsigned long); - -	switch (direction) { -	case DMA_FROM_DEVICE:		/* invalidate only */ -		inner_op = dmac_inv_range; -		outer_op = outer_inv_range; -		break; -	case DMA_TO_DEVICE:		/* writeback only */ -		inner_op = dmac_clean_range; -		outer_op = outer_clean_range; -		break; -	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */ -		inner_op = dmac_flush_range; -		outer_op = outer_flush_range; -		break; -	default: -		BUG(); -	} +	BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1)); -	if (!PageHighMem(page)) { -		vaddr = page_address(page) + offset; -		inner_op(vaddr, vaddr + size); -	} else { -		vaddr = kmap_high_get(page); -		if (vaddr) { -			vaddr += offset; -			inner_op(vaddr, vaddr + size); -			kunmap_high(page); -		} +	/* FIXME: non-speculating: not required */ +	/* don't bother invalidating if DMA to device */ +	if (dir != DMA_TO_DEVICE) { +		unsigned long paddr = __pa(kaddr); +		outer_inv_range(paddr, paddr + size);  	} -	paddr = page_to_phys(page) + offset; -	outer_op(paddr, paddr + size); +	dmac_unmap_area(kaddr, size, dir);  } +EXPORT_SYMBOL(___dma_single_dev_to_cpu); -void dma_cache_maint_page(struct page *page, unsigned long offset, -			  size_t size, int dir) +static void dma_cache_maint_page(struct page *page, unsigned long offset, +	size_t size, enum dma_data_direction dir, +	void (*op)(const void *, size_t, int))  {  	/*  	 * A single sg entry may refer to multiple physically contiguous @@ -486,20 +449,62 @@ void dma_cache_maint_page(struct page *page, unsigned long offset,  	size_t left = size;  	do {  		size_t len = left; -		if (PageHighMem(page) && len + offset > PAGE_SIZE) { -			if (offset >= PAGE_SIZE) { -				page += offset / PAGE_SIZE; -				offset %= PAGE_SIZE; +		void *vaddr; + +		if (PageHighMem(page)) { +			if (len + offset > PAGE_SIZE) { +				if (offset >= PAGE_SIZE) { +					page += offset / PAGE_SIZE; +					offset %= PAGE_SIZE; +				} +				len = PAGE_SIZE - offset;  			} -			len = PAGE_SIZE - offset; +			vaddr = kmap_high_get(page); +			if (vaddr) { +				vaddr += offset; +				op(vaddr, len, dir); +				kunmap_high(page); +			} +		} else { +			vaddr = page_address(page) + offset; +			op(vaddr, len, dir);  		} -		dma_cache_maint_contiguous(page, offset, len, dir);  		offset = 0;  		page++;  		left -= len;  	} while (left);  } -EXPORT_SYMBOL(dma_cache_maint_page); + +void ___dma_page_cpu_to_dev(struct page *page, unsigned long off, +	size_t size, enum dma_data_direction dir) +{ +	unsigned long paddr; + +	dma_cache_maint_page(page, off, size, dir, dmac_map_area); + +	paddr = page_to_phys(page) + off; +	if (dir == DMA_FROM_DEVICE) { +		outer_inv_range(paddr, paddr + size); +	} else { +		outer_clean_range(paddr, paddr + size); +	} +	/* FIXME: non-speculating: flush on bidirectional mappings? */ +} +EXPORT_SYMBOL(___dma_page_cpu_to_dev); + +void ___dma_page_dev_to_cpu(struct page *page, unsigned long off, +	size_t size, enum dma_data_direction dir) +{ +	unsigned long paddr = page_to_phys(page) + off; + +	/* FIXME: non-speculating: not required */ +	/* don't bother invalidating if DMA to device */ +	if (dir != DMA_TO_DEVICE) +		outer_inv_range(paddr, paddr + size); + +	dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); +} +EXPORT_SYMBOL(___dma_page_dev_to_cpu);  /**   * dma_map_sg - map a set of SG buffers for streaming mode DMA @@ -573,8 +578,12 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,  	int i;  	for_each_sg(sg, s, nents, i) { -		dmabounce_sync_for_cpu(dev, sg_dma_address(s), 0, -					sg_dma_len(s), dir); +		if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s), 0, +					    sg_dma_len(s), dir)) +			continue; + +		__dma_page_dev_to_cpu(sg_page(s), s->offset, +				      s->length, dir);  	}  }  EXPORT_SYMBOL(dma_sync_sg_for_cpu); @@ -597,9 +606,8 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,  					sg_dma_len(s), dir))  			continue; -		if (!arch_is_coherent()) -			dma_cache_maint_page(sg_page(s), s->offset, -					     s->length, dir); +		__dma_page_cpu_to_dev(sg_page(s), s->offset, +				      s->length, dir);  	}  }  EXPORT_SYMBOL(dma_sync_sg_for_device); diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 56ee15321b0..c9b97e9836a 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -36,28 +36,12 @@ static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE;   * Therefore those configurations which might call adjust_pte (those   * without CONFIG_CPU_CACHE_VIPT) cannot support split page_table_lock.   */ -static int adjust_pte(struct vm_area_struct *vma, unsigned long address) +static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address, +	unsigned long pfn, pte_t *ptep)  { -	pgd_t *pgd; -	pmd_t *pmd; -	pte_t *pte, entry; +	pte_t entry = *ptep;  	int ret; -	pgd = pgd_offset(vma->vm_mm, address); -	if (pgd_none(*pgd)) -		goto no_pgd; -	if (pgd_bad(*pgd)) -		goto bad_pgd; - -	pmd = pmd_offset(pgd, address); -	if (pmd_none(*pmd)) -		goto no_pmd; -	if (pmd_bad(*pmd)) -		goto bad_pmd; - -	pte = pte_offset_map(pmd, address); -	entry = *pte; -  	/*  	 * If this page is present, it's actually being shared.  	 */ @@ -68,33 +52,55 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)  	 * fault (ie, is old), we can safely ignore any issues.  	 */  	if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) { -		unsigned long pfn = pte_pfn(entry);  		flush_cache_page(vma, address, pfn);  		outer_flush_range((pfn << PAGE_SHIFT),  				  (pfn << PAGE_SHIFT) + PAGE_SIZE);  		pte_val(entry) &= ~L_PTE_MT_MASK;  		pte_val(entry) |= shared_pte_mask; -		set_pte_at(vma->vm_mm, address, pte, entry); +		set_pte_at(vma->vm_mm, address, ptep, entry);  		flush_tlb_page(vma, address);  	} -	pte_unmap(pte); +  	return ret; +} -bad_pgd: -	pgd_ERROR(*pgd); -	pgd_clear(pgd); -no_pgd: -	return 0; +static int adjust_pte(struct vm_area_struct *vma, unsigned long address, +	unsigned long pfn) +{ +	spinlock_t *ptl; +	pgd_t *pgd; +	pmd_t *pmd; +	pte_t *pte; +	int ret; + +	pgd = pgd_offset(vma->vm_mm, address); +	if (pgd_none_or_clear_bad(pgd)) +		return 0; -bad_pmd: -	pmd_ERROR(*pmd); -	pmd_clear(pmd); -no_pmd: -	return 0; +	pmd = pmd_offset(pgd, address); +	if (pmd_none_or_clear_bad(pmd)) +		return 0; + +	/* +	 * This is called while another page table is mapped, so we +	 * must use the nested version.  This also means we need to +	 * open-code the spin-locking. +	 */ +	ptl = pte_lockptr(vma->vm_mm, pmd); +	pte = pte_offset_map_nested(pmd, address); +	spin_lock(ptl); + +	ret = do_adjust_pte(vma, address, pfn, pte); + +	spin_unlock(ptl); +	pte_unmap_nested(pte); + +	return ret;  }  static void -make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) +make_coherent(struct address_space *mapping, struct vm_area_struct *vma, +	unsigned long addr, pte_t *ptep, unsigned long pfn)  {  	struct mm_struct *mm = vma->vm_mm;  	struct vm_area_struct *mpnt; @@ -122,11 +128,11 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigne  		if (!(mpnt->vm_flags & VM_MAYSHARE))  			continue;  		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; -		aliases += adjust_pte(mpnt, mpnt->vm_start + offset); +		aliases += adjust_pte(mpnt, mpnt->vm_start + offset, pfn);  	}  	flush_dcache_mmap_unlock(mapping);  	if (aliases) -		adjust_pte(vma, addr); +		do_adjust_pte(vma, addr, pfn, ptep);  	else  		flush_cache_page(vma, addr, pfn);  } @@ -144,9 +150,10 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigne   *   * Note that the pte lock will be held.   */ -void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) +void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, +	pte_t *ptep)  { -	unsigned long pfn = pte_pfn(pte); +	unsigned long pfn = pte_pfn(*ptep);  	struct address_space *mapping;  	struct page *page; @@ -168,7 +175,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)  #endif  	if (mapping) {  		if (cache_is_vivt()) -			make_coherent(mapping, vma, addr, pfn); +			make_coherent(mapping, vma, addr, ptep, pfn);  		else if (vma->vm_flags & VM_EXEC)  			__flush_icache_all();  	} diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 10e06801afb..9d40c341e07 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -18,6 +18,7 @@  #include <linux/page-flags.h>  #include <linux/sched.h>  #include <linux/highmem.h> +#include <linux/perf_event.h>  #include <asm/system.h>  #include <asm/pgtable.h> @@ -302,6 +303,12 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  	fault = __do_page_fault(mm, addr, fsr, tsk);  	up_read(&mm->mmap_sem); +	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, addr); +	if (fault & VM_FAULT_MAJOR) +		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, regs, addr); +	else if (fault & VM_FAULT_MINOR) +		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, regs, addr); +  	/*  	 * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR  	 */ diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 6f3a4b7a3b8..e34f095e209 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -13,6 +13,7 @@  #include <asm/cacheflush.h>  #include <asm/cachetype.h> +#include <asm/smp_plat.h>  #include <asm/system.h>  #include <asm/tlbflush.h> @@ -87,13 +88,26 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig  	if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged())  		__flush_icache_all();  } +#else +#define flush_pfn_alias(pfn,vaddr)	do { } while (0) +#endif +#ifdef CONFIG_SMP +static void flush_ptrace_access_other(void *args) +{ +	__flush_icache_all(); +} +#endif + +static  void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, -			 unsigned long uaddr, void *kaddr, -			 unsigned long len, int write) +			 unsigned long uaddr, void *kaddr, unsigned long len)  {  	if (cache_is_vivt()) { -		vivt_flush_ptrace_access(vma, page, uaddr, kaddr, len, write); +		if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) { +			unsigned long addr = (unsigned long)kaddr; +			__cpuc_coherent_kern_range(addr, addr + len); +		}  		return;  	} @@ -104,16 +118,37 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,  	}  	/* VIPT non-aliasing cache */ -	if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm)) && -	    vma->vm_flags & VM_EXEC) { +	if (vma->vm_flags & VM_EXEC) {  		unsigned long addr = (unsigned long)kaddr; -		/* only flushing the kernel mapping on non-aliasing VIPT */  		__cpuc_coherent_kern_range(addr, addr + len); +#ifdef CONFIG_SMP +		if (cache_ops_need_broadcast()) +			smp_call_function(flush_ptrace_access_other, +					  NULL, 1); +#endif  	}  } -#else -#define flush_pfn_alias(pfn,vaddr)	do { } while (0) + +/* + * Copy user data from/to a page which is mapped into a different + * processes address space.  Really, we want to allow our "user + * space" model to handle this. + * + * Note that this code needs to run on the current CPU. + */ +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, +		       unsigned long uaddr, void *dst, const void *src, +		       unsigned long len) +{ +#ifdef CONFIG_SMP +	preempt_disable();  #endif +	memcpy(dst, src, len); +	flush_ptrace_access(vma, page, uaddr, dst, len); +#ifdef CONFIG_SMP +	preempt_enable(); +#endif +}  void __flush_dcache_page(struct address_space *mapping, struct page *page)  { diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index a04ffbbbe25..7829cb5425f 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -23,6 +23,7 @@  #include <asm/setup.h>  #include <asm/sizes.h>  #include <asm/tlb.h> +#include <asm/fixmap.h>  #include <asm/mach/arch.h>  #include <asm/mach/map.h> @@ -32,19 +33,21 @@  static unsigned long phys_initrd_start __initdata = 0;  static unsigned long phys_initrd_size __initdata = 0; -static void __init early_initrd(char **p) +static int __init early_initrd(char *p)  {  	unsigned long start, size; +	char *endp; -	start = memparse(*p, p); -	if (**p == ',') { -		size = memparse((*p) + 1, p); +	start = memparse(p, &endp); +	if (*endp == ',') { +		size = memparse(endp + 1, NULL);  		phys_initrd_start = start;  		phys_initrd_size = size;  	} +	return 0;  } -__early_param("initrd=", early_initrd); +early_param("initrd", early_initrd);  static int __init parse_tag_initrd(const struct tag *tag)  { @@ -560,7 +563,7 @@ static void __init free_unused_memmap_node(int node, struct meminfo *mi)   */  void __init mem_init(void)  { -	unsigned int codesize, datasize, initsize; +	unsigned long reserved_pages, free_pages;  	int i, node;  #ifndef CONFIG_DISCONTIGMEM @@ -596,6 +599,33 @@ void __init mem_init(void)  	totalram_pages += totalhigh_pages;  #endif +	reserved_pages = free_pages = 0; + +	for_each_online_node(node) { +		pg_data_t *n = NODE_DATA(node); +		struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn; + +		for_each_nodebank(i, &meminfo, node) { +			struct membank *bank = &meminfo.bank[i]; +			unsigned int pfn1, pfn2; +			struct page *page, *end; + +			pfn1 = bank_pfn_start(bank); +			pfn2 = bank_pfn_end(bank); + +			page = map + pfn1; +			end  = map + pfn2; + +			do { +				if (PageReserved(page)) +					reserved_pages++; +				else if (!page_count(page)) +					free_pages++; +				page++; +			} while (page < end); +		} +	} +  	/*  	 * Since our memory may not be contiguous, calculate the  	 * real number of pages we have in this system @@ -608,16 +638,71 @@ void __init mem_init(void)  	}  	printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); -	codesize = _etext - _text; -	datasize = _end - _data; -	initsize = __init_end - __init_begin; - -	printk(KERN_NOTICE "Memory: %luKB available (%dK code, " -		"%dK data, %dK init, %luK highmem)\n", -		nr_free_pages() << (PAGE_SHIFT-10), codesize >> 10, -		datasize >> 10, initsize >> 10, +	printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n", +		nr_free_pages() << (PAGE_SHIFT-10), +		free_pages << (PAGE_SHIFT-10), +		reserved_pages << (PAGE_SHIFT-10),  		totalhigh_pages << (PAGE_SHIFT-10)); +#define MLK(b, t) b, t, ((t) - (b)) >> 10 +#define MLM(b, t) b, t, ((t) - (b)) >> 20 +#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) + +	printk(KERN_NOTICE "Virtual kernel memory layout:\n" +			"    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n" +			"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n" +#ifdef CONFIG_MMU +			"    DMA     : 0x%08lx - 0x%08lx   (%4ld MB)\n" +#endif +			"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n" +			"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n" +#ifdef CONFIG_HIGHMEM +			"    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n" +#endif +			"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n" +			"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n" +			"      .text : 0x%p" " - 0x%p" "   (%4d kB)\n" +			"      .data : 0x%p" " - 0x%p" "   (%4d kB)\n", + +			MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) + +				(PAGE_SIZE)), +			MLK(FIXADDR_START, FIXADDR_TOP), +#ifdef CONFIG_MMU +			MLM(CONSISTENT_BASE, CONSISTENT_END), +#endif +			MLM(VMALLOC_START, VMALLOC_END), +			MLM(PAGE_OFFSET, (unsigned long)high_memory), +#ifdef CONFIG_HIGHMEM +			MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) * +				(PAGE_SIZE)), +#endif +			MLM(MODULES_VADDR, MODULES_END), + +			MLK_ROUNDUP(__init_begin, __init_end), +			MLK_ROUNDUP(_text, _etext), +			MLK_ROUNDUP(_data, _edata)); + +#undef MLK +#undef MLM +#undef MLK_ROUNDUP + +	/* +	 * Check boundaries twice: Some fundamental inconsistencies can +	 * be detected at build time already. +	 */ +#ifdef CONFIG_MMU +	BUILD_BUG_ON(VMALLOC_END			> CONSISTENT_BASE); +	BUG_ON(VMALLOC_END				> CONSISTENT_BASE); + +	BUILD_BUG_ON(TASK_SIZE				> MODULES_VADDR); +	BUG_ON(TASK_SIZE 				> MODULES_VADDR); +#endif + +#ifdef CONFIG_HIGHMEM +	BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > PAGE_OFFSET); +	BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE	> PAGE_OFFSET); +#endif +  	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {  		extern int sysctl_overcommit_memory;  		/* diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 0ab75c60f7c..28c8b950ef0 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -139,8 +139,8 @@ void __check_kvm_seq(struct mm_struct *mm)   * which requires the new ioremap'd region to be referenced, the CPU will   * reference the _old_ region.   * - * Note that get_vm_area() allocates a guard 4K page, so we need to mask - * the size back to 1MB aligned or we will overflow in the loop below. + * Note that get_vm_area_caller() allocates a guard 4K page, so we need to + * mask the size back to 1MB aligned or we will overflow in the loop below.   */  static void unmap_area_sections(unsigned long virt, unsigned long size)  { @@ -254,22 +254,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,  }  #endif - -/* - * Remap an arbitrary physical address space into the kernel virtual - * address space. Needed when the kernel wants to access high addresses - * directly. - * - * NOTE! We need to allow non-page-aligned mappings too: we will obviously - * have to convert them into an offset in a page-aligned mapping, but the - * caller shouldn't need to know that small detail. - * - * 'flags' are the extra L_PTE_ flags that you want to specify for this - * mapping.  See <asm/pgtable.h> for more information. - */ -void __iomem * -__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, -		  unsigned int mtype) +void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, +	unsigned long offset, size_t size, unsigned int mtype, void *caller)  {  	const struct mem_type *type;  	int err; @@ -291,7 +277,7 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,  	 */  	size = PAGE_ALIGN(offset + size); - 	area = get_vm_area(size, VM_IOREMAP); +	area = get_vm_area_caller(size, VM_IOREMAP, caller);   	if (!area)   		return NULL;   	addr = (unsigned long)area->addr; @@ -318,10 +304,9 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,  	flush_cache_vmap(addr, addr + size);  	return (void __iomem *) (offset + addr);  } -EXPORT_SYMBOL(__arm_ioremap_pfn); -void __iomem * -__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) +void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size, +	unsigned int mtype, void *caller)  {  	unsigned long last_addr;   	unsigned long offset = phys_addr & ~PAGE_MASK; @@ -334,7 +319,33 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)  	if (!size || last_addr < phys_addr)  		return NULL; - 	return __arm_ioremap_pfn(pfn, offset, size, mtype); +	return __arm_ioremap_pfn_caller(pfn, offset, size, mtype, +			caller); +} + +/* + * Remap an arbitrary physical address space into the kernel virtual + * address space. Needed when the kernel wants to access high addresses + * directly. + * + * NOTE! We need to allow non-page-aligned mappings too: we will obviously + * have to convert them into an offset in a page-aligned mapping, but the + * caller shouldn't need to know that small detail. + */ +void __iomem * +__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, +		  unsigned int mtype) +{ +	return __arm_ioremap_pfn_caller(pfn, offset, size, mtype, +			__builtin_return_address(0)); +} +EXPORT_SYMBOL(__arm_ioremap_pfn); + +void __iomem * +__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) +{ +	return __arm_ioremap_caller(phys_addr, size, mtype, +			__builtin_return_address(0));  }  EXPORT_SYMBOL(__arm_ioremap); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 761ffede6a2..9d4da6ac28e 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -100,18 +100,17 @@ static struct cachepolicy cache_policies[] __initdata = {   * writebuffer to be turned off.  (Note: the write   * buffer should not be on and the cache off).   */ -static void __init early_cachepolicy(char **p) +static int __init early_cachepolicy(char *p)  {  	int i;  	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {  		int len = strlen(cache_policies[i].policy); -		if (memcmp(*p, cache_policies[i].policy, len) == 0) { +		if (memcmp(p, cache_policies[i].policy, len) == 0) {  			cachepolicy = i;  			cr_alignment &= ~cache_policies[i].cr_mask;  			cr_no_alignment &= ~cache_policies[i].cr_mask; -			*p += len;  			break;  		}  	} @@ -130,36 +129,37 @@ static void __init early_cachepolicy(char **p)  	}  	flush_cache_all();  	set_cr(cr_alignment); +	return 0;  } -__early_param("cachepolicy=", early_cachepolicy); +early_param("cachepolicy", early_cachepolicy); -static void __init early_nocache(char **__unused) +static int __init early_nocache(char *__unused)  {  	char *p = "buffered";  	printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p); -	early_cachepolicy(&p); +	early_cachepolicy(p); +	return 0;  } -__early_param("nocache", early_nocache); +early_param("nocache", early_nocache); -static void __init early_nowrite(char **__unused) +static int __init early_nowrite(char *__unused)  {  	char *p = "uncached";  	printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p); -	early_cachepolicy(&p); +	early_cachepolicy(p); +	return 0;  } -__early_param("nowb", early_nowrite); +early_param("nowb", early_nowrite); -static void __init early_ecc(char **p) +static int __init early_ecc(char *p)  { -	if (memcmp(*p, "on", 2) == 0) { +	if (memcmp(p, "on", 2) == 0)  		ecc_mask = PMD_PROTECTION; -		*p += 2; -	} else if (memcmp(*p, "off", 3) == 0) { +	else if (memcmp(p, "off", 3) == 0)  		ecc_mask = 0; -		*p += 3; -	} +	return 0;  } -__early_param("ecc=", early_ecc); +early_param("ecc", early_ecc);  static int __init noalign_setup(char *__unused)  { @@ -670,9 +670,9 @@ static unsigned long __initdata vmalloc_reserve = SZ_128M;   * bytes. This can be used to increase (or decrease) the vmalloc   * area - the default is 128m.   */ -static void __init early_vmalloc(char **arg) +static int __init early_vmalloc(char *arg)  { -	vmalloc_reserve = memparse(*arg, arg); +	vmalloc_reserve = memparse(arg, NULL);  	if (vmalloc_reserve < SZ_16M) {  		vmalloc_reserve = SZ_16M; @@ -687,8 +687,9 @@ static void __init early_vmalloc(char **arg)  			"vmalloc area is too big, limiting to %luMB\n",  			vmalloc_reserve >> 20);  	} +	return 0;  } -__early_param("vmalloc=", early_vmalloc); +early_param("vmalloc", early_vmalloc);  #define VMALLOC_MIN	(void *)(VMALLOC_END - vmalloc_reserve) diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 374a8311bc8..9bfeb6b9509 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -74,6 +74,12 @@ void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset,  }  EXPORT_SYMBOL(__arm_ioremap_pfn); +void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, +			   size_t size, unsigned int mtype, void *caller) +{ +	return __arm_ioremap_pfn(pfn, offset, size, mtype); +} +  void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,  			    unsigned int mtype)  { @@ -81,6 +87,12 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,  }  EXPORT_SYMBOL(__arm_ioremap); +void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, +			    unsigned int mtype, void *caller) +{ +	return __arm_ioremap(phys_addr, size, mtype); +} +  void __iounmap(volatile void __iomem *addr)  {  } diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 8012e24282b..72507c630ce 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -265,7 +265,7 @@ ENTRY(arm1020_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm1020_dma_inv_range) +arm1020_dma_inv_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	tst	r0, #CACHE_DLINESIZE - 1 @@ -295,7 +295,7 @@ ENTRY(arm1020_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm1020_dma_clean_range) +arm1020_dma_clean_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	bic	r0, r0, #CACHE_DLINESIZE - 1 @@ -330,6 +330,30 @@ ENTRY(arm1020_dma_flush_range)  	mcr	p15, 0, ip, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1020_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm1020_dma_clean_range +	bcs	arm1020_dma_inv_range +	b	arm1020_dma_flush_range +ENDPROC(arm1020_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1020_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm1020_dma_unmap_area) +  ENTRY(arm1020_cache_fns)  	.long	arm1020_flush_kern_cache_all  	.long	arm1020_flush_user_cache_all @@ -337,8 +361,8 @@ ENTRY(arm1020_cache_fns)  	.long	arm1020_coherent_kern_range  	.long	arm1020_coherent_user_range  	.long	arm1020_flush_kern_dcache_area -	.long	arm1020_dma_inv_range -	.long	arm1020_dma_clean_range +	.long	arm1020_dma_map_area +	.long	arm1020_dma_unmap_area  	.long	arm1020_dma_flush_range  	.align	5 diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 41fe25d234f..d2782980560 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -258,7 +258,7 @@ ENTRY(arm1020e_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm1020e_dma_inv_range) +arm1020e_dma_inv_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	tst	r0, #CACHE_DLINESIZE - 1 @@ -284,7 +284,7 @@ ENTRY(arm1020e_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm1020e_dma_clean_range) +arm1020e_dma_clean_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	bic	r0, r0, #CACHE_DLINESIZE - 1 @@ -316,6 +316,30 @@ ENTRY(arm1020e_dma_flush_range)  	mcr	p15, 0, ip, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1020e_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm1020e_dma_clean_range +	bcs	arm1020e_dma_inv_range +	b	arm1020e_dma_flush_range +ENDPROC(arm1020e_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1020e_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm1020e_dma_unmap_area) +  ENTRY(arm1020e_cache_fns)  	.long	arm1020e_flush_kern_cache_all  	.long	arm1020e_flush_user_cache_all @@ -323,8 +347,8 @@ ENTRY(arm1020e_cache_fns)  	.long	arm1020e_coherent_kern_range  	.long	arm1020e_coherent_user_range  	.long	arm1020e_flush_kern_dcache_area -	.long	arm1020e_dma_inv_range -	.long	arm1020e_dma_clean_range +	.long	arm1020e_dma_map_area +	.long	arm1020e_dma_unmap_area  	.long	arm1020e_dma_flush_range  	.align	5 diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 20a5b1b31a7..ce13e4a827d 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -247,7 +247,7 @@ ENTRY(arm1022_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm1022_dma_inv_range) +arm1022_dma_inv_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	tst	r0, #CACHE_DLINESIZE - 1 @@ -273,7 +273,7 @@ ENTRY(arm1022_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm1022_dma_clean_range) +arm1022_dma_clean_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	bic	r0, r0, #CACHE_DLINESIZE - 1 @@ -305,6 +305,30 @@ ENTRY(arm1022_dma_flush_range)  	mcr	p15, 0, ip, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1022_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm1022_dma_clean_range +	bcs	arm1022_dma_inv_range +	b	arm1022_dma_flush_range +ENDPROC(arm1022_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1022_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm1022_dma_unmap_area) +  ENTRY(arm1022_cache_fns)  	.long	arm1022_flush_kern_cache_all  	.long	arm1022_flush_user_cache_all @@ -312,8 +336,8 @@ ENTRY(arm1022_cache_fns)  	.long	arm1022_coherent_kern_range  	.long	arm1022_coherent_user_range  	.long	arm1022_flush_kern_dcache_area -	.long	arm1022_dma_inv_range -	.long	arm1022_dma_clean_range +	.long	arm1022_dma_map_area +	.long	arm1022_dma_unmap_area  	.long	arm1022_dma_flush_range  	.align	5 diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 96aedb10fcc..636672a29c6 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -241,7 +241,7 @@ ENTRY(arm1026_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm1026_dma_inv_range) +arm1026_dma_inv_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	tst	r0, #CACHE_DLINESIZE - 1 @@ -267,7 +267,7 @@ ENTRY(arm1026_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm1026_dma_clean_range) +arm1026_dma_clean_range:  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_DISABLE  	bic	r0, r0, #CACHE_DLINESIZE - 1 @@ -299,6 +299,30 @@ ENTRY(arm1026_dma_flush_range)  	mcr	p15, 0, ip, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1026_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm1026_dma_clean_range +	bcs	arm1026_dma_inv_range +	b	arm1026_dma_flush_range +ENDPROC(arm1026_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm1026_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm1026_dma_unmap_area) +  ENTRY(arm1026_cache_fns)  	.long	arm1026_flush_kern_cache_all  	.long	arm1026_flush_user_cache_all @@ -306,8 +330,8 @@ ENTRY(arm1026_cache_fns)  	.long	arm1026_coherent_kern_range  	.long	arm1026_coherent_user_range  	.long	arm1026_flush_kern_dcache_area -	.long	arm1026_dma_inv_range -	.long	arm1026_dma_clean_range +	.long	arm1026_dma_map_area +	.long	arm1026_dma_unmap_area  	.long	arm1026_dma_flush_range  	.align	5 diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 471669e2d7c..8be81992645 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -239,7 +239,7 @@ ENTRY(arm920_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm920_dma_inv_range) +arm920_dma_inv_range:  	tst	r0, #CACHE_DLINESIZE - 1  	bic	r0, r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -262,7 +262,7 @@ ENTRY(arm920_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm920_dma_clean_range) +arm920_dma_clean_range:  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  	add	r0, r0, #CACHE_DLINESIZE @@ -288,6 +288,30 @@ ENTRY(arm920_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm920_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm920_dma_clean_range +	bcs	arm920_dma_inv_range +	b	arm920_dma_flush_range +ENDPROC(arm920_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm920_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm920_dma_unmap_area) +  ENTRY(arm920_cache_fns)  	.long	arm920_flush_kern_cache_all  	.long	arm920_flush_user_cache_all @@ -295,8 +319,8 @@ ENTRY(arm920_cache_fns)  	.long	arm920_coherent_kern_range  	.long	arm920_coherent_user_range  	.long	arm920_flush_kern_dcache_area -	.long	arm920_dma_inv_range -	.long	arm920_dma_clean_range +	.long	arm920_dma_map_area +	.long	arm920_dma_unmap_area  	.long	arm920_dma_flush_range  #endif diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index ee111b00fa4..c0ff8e4b107 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -241,7 +241,7 @@ ENTRY(arm922_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm922_dma_inv_range) +arm922_dma_inv_range:  	tst	r0, #CACHE_DLINESIZE - 1  	bic	r0, r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -264,7 +264,7 @@ ENTRY(arm922_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm922_dma_clean_range) +arm922_dma_clean_range:  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  	add	r0, r0, #CACHE_DLINESIZE @@ -290,6 +290,30 @@ ENTRY(arm922_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm922_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm922_dma_clean_range +	bcs	arm922_dma_inv_range +	b	arm922_dma_flush_range +ENDPROC(arm922_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm922_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm922_dma_unmap_area) +  ENTRY(arm922_cache_fns)  	.long	arm922_flush_kern_cache_all  	.long	arm922_flush_user_cache_all @@ -297,8 +321,8 @@ ENTRY(arm922_cache_fns)  	.long	arm922_coherent_kern_range  	.long	arm922_coherent_user_range  	.long	arm922_flush_kern_dcache_area -	.long	arm922_dma_inv_range -	.long	arm922_dma_clean_range +	.long	arm922_dma_map_area +	.long	arm922_dma_unmap_area  	.long	arm922_dma_flush_range  #endif diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 8deb5bde58e..3c6cffe400f 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -283,7 +283,7 @@ ENTRY(arm925_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm925_dma_inv_range) +arm925_dma_inv_range:  #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH  	tst	r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -308,7 +308,7 @@ ENTRY(arm925_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm925_dma_clean_range) +arm925_dma_clean_range:  #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -341,6 +341,30 @@ ENTRY(arm925_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm925_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm925_dma_clean_range +	bcs	arm925_dma_inv_range +	b	arm925_dma_flush_range +ENDPROC(arm925_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm925_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm925_dma_unmap_area) +  ENTRY(arm925_cache_fns)  	.long	arm925_flush_kern_cache_all  	.long	arm925_flush_user_cache_all @@ -348,8 +372,8 @@ ENTRY(arm925_cache_fns)  	.long	arm925_coherent_kern_range  	.long	arm925_coherent_user_range  	.long	arm925_flush_kern_dcache_area -	.long	arm925_dma_inv_range -	.long	arm925_dma_clean_range +	.long	arm925_dma_map_area +	.long	arm925_dma_unmap_area  	.long	arm925_dma_flush_range  ENTRY(cpu_arm925_dcache_clean_area) diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 64db6e275a4..75b707c9cce 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -246,7 +246,7 @@ ENTRY(arm926_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(arm926_dma_inv_range) +arm926_dma_inv_range:  #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH  	tst	r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -271,7 +271,7 @@ ENTRY(arm926_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(arm926_dma_clean_range) +arm926_dma_clean_range:  #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -304,6 +304,30 @@ ENTRY(arm926_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm926_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm926_dma_clean_range +	bcs	arm926_dma_inv_range +	b	arm926_dma_flush_range +ENDPROC(arm926_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm926_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm926_dma_unmap_area) +  ENTRY(arm926_cache_fns)  	.long	arm926_flush_kern_cache_all  	.long	arm926_flush_user_cache_all @@ -311,8 +335,8 @@ ENTRY(arm926_cache_fns)  	.long	arm926_coherent_kern_range  	.long	arm926_coherent_user_range  	.long	arm926_flush_kern_dcache_area -	.long	arm926_dma_inv_range -	.long	arm926_dma_clean_range +	.long	arm926_dma_map_area +	.long	arm926_dma_unmap_area  	.long	arm926_dma_flush_range  ENTRY(cpu_arm926_dcache_clean_area) diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index 8196b9f401f..1af1657819e 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S @@ -171,7 +171,7 @@ ENTRY(arm940_flush_kern_dcache_area)   *	- start	- virtual start address   *	- end	- virtual end address   */ -ENTRY(arm940_dma_inv_range) +arm940_dma_inv_range:  	mov	ip, #0  	mov	r1, #(CACHE_DSEGMENTS - 1) << 4	@ 4 segments  1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries @@ -192,7 +192,7 @@ ENTRY(arm940_dma_inv_range)   *	- start	- virtual start address   *	- end	- virtual end address   */ -ENTRY(arm940_dma_clean_range) +arm940_dma_clean_range:  ENTRY(cpu_arm940_dcache_clean_area)  	mov	ip, #0  #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH @@ -233,6 +233,30 @@ ENTRY(arm940_dma_flush_range)  	mcr	p15, 0, ip, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm940_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm940_dma_clean_range +	bcs	arm940_dma_inv_range +	b	arm940_dma_flush_range +ENDPROC(arm940_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm940_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm940_dma_unmap_area) +  ENTRY(arm940_cache_fns)  	.long	arm940_flush_kern_cache_all  	.long	arm940_flush_user_cache_all @@ -240,8 +264,8 @@ ENTRY(arm940_cache_fns)  	.long	arm940_coherent_kern_range  	.long	arm940_coherent_user_range  	.long	arm940_flush_kern_dcache_area -	.long	arm940_dma_inv_range -	.long	arm940_dma_clean_range +	.long	arm940_dma_map_area +	.long	arm940_dma_unmap_area  	.long	arm940_dma_flush_range  	__INIT diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index 9a951239c86..1664b6aaff7 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S @@ -215,7 +215,7 @@ ENTRY(arm946_flush_kern_dcache_area)   *	- end	- virtual end address   * (same as arm926)   */ -ENTRY(arm946_dma_inv_range) +arm946_dma_inv_range:  #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH  	tst	r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -240,7 +240,7 @@ ENTRY(arm946_dma_inv_range)   *   * (same as arm926)   */ -ENTRY(arm946_dma_clean_range) +arm946_dma_clean_range:  #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -275,6 +275,30 @@ ENTRY(arm946_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm946_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	arm946_dma_clean_range +	bcs	arm946_dma_inv_range +	b	arm946_dma_flush_range +ENDPROC(arm946_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(arm946_dma_unmap_area) +	mov	pc, lr +ENDPROC(arm946_dma_unmap_area) +  ENTRY(arm946_cache_fns)  	.long	arm946_flush_kern_cache_all  	.long	arm946_flush_user_cache_all @@ -282,8 +306,8 @@ ENTRY(arm946_cache_fns)  	.long	arm946_coherent_kern_range  	.long	arm946_coherent_user_range  	.long	arm946_flush_kern_dcache_area -	.long	arm946_dma_inv_range -	.long	arm946_dma_clean_range +	.long	arm946_dma_map_area +	.long	arm946_dma_unmap_area  	.long	arm946_dma_flush_range diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index dbc39383e66..53e63234384 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S @@ -274,7 +274,7 @@ ENTRY(feroceon_range_flush_kern_dcache_area)   * (same as v4wb)   */  	.align	5 -ENTRY(feroceon_dma_inv_range) +feroceon_dma_inv_range:  	tst	r0, #CACHE_DLINESIZE - 1  	bic	r0, r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -288,7 +288,7 @@ ENTRY(feroceon_dma_inv_range)  	mov	pc, lr  	.align	5 -ENTRY(feroceon_range_dma_inv_range) +feroceon_range_dma_inv_range:  	mrs	r2, cpsr  	tst	r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -314,7 +314,7 @@ ENTRY(feroceon_range_dma_inv_range)   * (same as v4wb)   */  	.align	5 -ENTRY(feroceon_dma_clean_range) +feroceon_dma_clean_range:  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  	add	r0, r0, #CACHE_DLINESIZE @@ -324,7 +324,7 @@ ENTRY(feroceon_dma_clean_range)  	mov	pc, lr  	.align	5 -ENTRY(feroceon_range_dma_clean_range) +feroceon_range_dma_clean_range:  	mrs	r2, cpsr  	cmp	r1, r0  	subne	r1, r1, #1			@ top address is inclusive @@ -367,6 +367,44 @@ ENTRY(feroceon_range_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(feroceon_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	feroceon_dma_clean_range +	bcs	feroceon_dma_inv_range +	b	feroceon_dma_flush_range +ENDPROC(feroceon_dma_map_area) + +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(feroceon_range_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	feroceon_range_dma_clean_range +	bcs	feroceon_range_dma_inv_range +	b	feroceon_range_dma_flush_range +ENDPROC(feroceon_range_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(feroceon_dma_unmap_area) +	mov	pc, lr +ENDPROC(feroceon_dma_unmap_area) +  ENTRY(feroceon_cache_fns)  	.long	feroceon_flush_kern_cache_all  	.long	feroceon_flush_user_cache_all @@ -374,8 +412,8 @@ ENTRY(feroceon_cache_fns)  	.long	feroceon_coherent_kern_range  	.long	feroceon_coherent_user_range  	.long	feroceon_flush_kern_dcache_area -	.long	feroceon_dma_inv_range -	.long	feroceon_dma_clean_range +	.long	feroceon_dma_map_area +	.long	feroceon_dma_unmap_area  	.long	feroceon_dma_flush_range  ENTRY(feroceon_range_cache_fns) @@ -385,8 +423,8 @@ ENTRY(feroceon_range_cache_fns)  	.long	feroceon_coherent_kern_range  	.long	feroceon_coherent_user_range  	.long	feroceon_range_flush_kern_dcache_area -	.long	feroceon_range_dma_inv_range -	.long	feroceon_range_dma_clean_range +	.long	feroceon_range_dma_map_area +	.long	feroceon_dma_unmap_area  	.long	feroceon_range_dma_flush_range  	.align	5 diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S index 9674d36cc97..caa31154e7d 100644 --- a/arch/arm/mm/proc-mohawk.S +++ b/arch/arm/mm/proc-mohawk.S @@ -218,7 +218,7 @@ ENTRY(mohawk_flush_kern_dcache_area)   *   * (same as v4wb)   */ -ENTRY(mohawk_dma_inv_range) +mohawk_dma_inv_range:  	tst	r0, #CACHE_DLINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry  	tst	r1, #CACHE_DLINESIZE - 1 @@ -241,7 +241,7 @@ ENTRY(mohawk_dma_inv_range)   *   * (same as v4wb)   */ -ENTRY(mohawk_dma_clean_range) +mohawk_dma_clean_range:  	bic	r0, r0, #CACHE_DLINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  	add	r0, r0, #CACHE_DLINESIZE @@ -268,6 +268,30 @@ ENTRY(mohawk_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ drain WB  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(mohawk_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	mohawk_dma_clean_range +	bcs	mohawk_dma_inv_range +	b	mohawk_dma_flush_range +ENDPROC(mohawk_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(mohawk_dma_unmap_area) +	mov	pc, lr +ENDPROC(mohawk_dma_unmap_area) +  ENTRY(mohawk_cache_fns)  	.long	mohawk_flush_kern_cache_all  	.long	mohawk_flush_user_cache_all @@ -275,8 +299,8 @@ ENTRY(mohawk_cache_fns)  	.long	mohawk_coherent_kern_range  	.long	mohawk_coherent_user_range  	.long	mohawk_flush_kern_dcache_area -	.long	mohawk_dma_inv_range -	.long	mohawk_dma_clean_range +	.long	mohawk_dma_map_area +	.long	mohawk_dma_unmap_area  	.long	mohawk_dma_flush_range  ENTRY(cpu_mohawk_dcache_clean_area) diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 8e4f6dca899..e5797f1c1db 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -257,7 +257,7 @@ ENTRY(xsc3_flush_kern_dcache_area)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(xsc3_dma_inv_range) +xsc3_dma_inv_range:  	tst	r0, #CACHELINESIZE - 1  	bic	r0, r0, #CACHELINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean L1 D line @@ -278,7 +278,7 @@ ENTRY(xsc3_dma_inv_range)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(xsc3_dma_clean_range) +xsc3_dma_clean_range:  	bic	r0, r0, #CACHELINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean L1 D line  	add	r0, r0, #CACHELINESIZE @@ -304,6 +304,30 @@ ENTRY(xsc3_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(xsc3_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	xsc3_dma_clean_range +	bcs	xsc3_dma_inv_range +	b	xsc3_dma_flush_range +ENDPROC(xsc3_dma_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(xsc3_dma_unmap_area) +	mov	pc, lr +ENDPROC(xsc3_dma_unmap_area) +  ENTRY(xsc3_cache_fns)  	.long	xsc3_flush_kern_cache_all  	.long	xsc3_flush_user_cache_all @@ -311,8 +335,8 @@ ENTRY(xsc3_cache_fns)  	.long	xsc3_coherent_kern_range  	.long	xsc3_coherent_user_range  	.long	xsc3_flush_kern_dcache_area -	.long	xsc3_dma_inv_range -	.long	xsc3_dma_clean_range +	.long	xsc3_dma_map_area +	.long	xsc3_dma_unmap_area  	.long	xsc3_dma_flush_range  ENTRY(cpu_xsc3_dcache_clean_area) diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 93df47265f2..63037e2162f 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -315,7 +315,7 @@ ENTRY(xscale_flush_kern_dcache_area)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(xscale_dma_inv_range) +xscale_dma_inv_range:  	tst	r0, #CACHELINESIZE - 1  	bic	r0, r0, #CACHELINESIZE - 1  	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry @@ -336,7 +336,7 @@ ENTRY(xscale_dma_inv_range)   *	- start  - virtual start address   *	- end	 - virtual end address   */ -ENTRY(xscale_dma_clean_range) +xscale_dma_clean_range:  	bic	r0, r0, #CACHELINESIZE - 1  1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  	add	r0, r0, #CACHELINESIZE @@ -363,6 +363,43 @@ ENTRY(xscale_dma_flush_range)  	mcr	p15, 0, r0, c7, c10, 4		@ Drain Write (& Fill) Buffer  	mov	pc, lr +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(xscale_dma_map_area) +	add	r1, r1, r0 +	cmp	r2, #DMA_TO_DEVICE +	beq	xscale_dma_clean_range +	bcs	xscale_dma_inv_range +	b	xscale_dma_flush_range +ENDPROC(xscale_dma_map_area) + +/* + *	dma_map_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(xscale_dma_a0_map_area) +	add	r1, r1, r0 +	teq	r2, #DMA_TO_DEVICE +	beq	xscale_dma_clean_range +	b	xscale_dma_flush_range +ENDPROC(xscsale_dma_a0_map_area) + +/* + *	dma_unmap_area(start, size, dir) + *	- start	- kernel virtual start address + *	- size	- size of region + *	- dir	- DMA direction + */ +ENTRY(xscale_dma_unmap_area) +	mov	pc, lr +ENDPROC(xscale_dma_unmap_area) +  ENTRY(xscale_cache_fns)  	.long	xscale_flush_kern_cache_all  	.long	xscale_flush_user_cache_all @@ -370,8 +407,8 @@ ENTRY(xscale_cache_fns)  	.long	xscale_coherent_kern_range  	.long	xscale_coherent_user_range  	.long	xscale_flush_kern_dcache_area -	.long	xscale_dma_inv_range -	.long	xscale_dma_clean_range +	.long	xscale_dma_map_area +	.long	xscale_dma_unmap_area  	.long	xscale_dma_flush_range  /* @@ -394,8 +431,8 @@ ENTRY(xscale_80200_A0_A1_cache_fns)  	.long	xscale_coherent_kern_range  	.long	xscale_coherent_user_range  	.long	xscale_flush_kern_dcache_area -	.long	xscale_dma_flush_range -	.long	xscale_dma_clean_range +	.long	xscale_dma_a0_map_area +	.long	xscale_dma_unmap_area  	.long	xscale_dma_flush_range  ENTRY(cpu_xscale_dcache_clean_area) diff --git a/arch/arm/oprofile/op_model_arm11_core.c b/arch/arm/oprofile/op_model_arm11_core.c index ad80752cb9f..ef3e2653b90 100644 --- a/arch/arm/oprofile/op_model_arm11_core.c +++ b/arch/arm/oprofile/op_model_arm11_core.c @@ -132,7 +132,7 @@ static irqreturn_t arm11_pmu_interrupt(int irq, void *arg)  	return IRQ_HANDLED;  } -int arm11_request_interrupts(int *irqs, int nr) +int arm11_request_interrupts(const int *irqs, int nr)  {  	unsigned int i;  	int ret = 0; @@ -153,7 +153,7 @@ int arm11_request_interrupts(int *irqs, int nr)  	return ret;  } -void arm11_release_interrupts(int *irqs, int nr) +void arm11_release_interrupts(const int *irqs, int nr)  {  	unsigned int i; diff --git a/arch/arm/oprofile/op_model_arm11_core.h b/arch/arm/oprofile/op_model_arm11_core.h index 6f8538e5a96..1902b99d9df 100644 --- a/arch/arm/oprofile/op_model_arm11_core.h +++ b/arch/arm/oprofile/op_model_arm11_core.h @@ -39,7 +39,7 @@  int arm11_setup_pmu(void);  int arm11_start_pmu(void);  int arm11_stop_pmu(void); -int arm11_request_interrupts(int *, int); -void arm11_release_interrupts(int *, int); +int arm11_request_interrupts(const int *, int); +void arm11_release_interrupts(const int *, int);  #endif diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c index 4ce0f9801e2..f73ce875a39 100644 --- a/arch/arm/oprofile/op_model_mpcore.c +++ b/arch/arm/oprofile/op_model_mpcore.c @@ -32,6 +32,7 @@  /* #define DEBUG */  #include <linux/types.h>  #include <linux/errno.h> +#include <linux/err.h>  #include <linux/sched.h>  #include <linux/oprofile.h>  #include <linux/interrupt.h> @@ -43,6 +44,7 @@  #include <mach/hardware.h>  #include <mach/board-eb.h>  #include <asm/system.h> +#include <asm/pmu.h>  #include "op_counter.h"  #include "op_arm_model.h" @@ -58,6 +60,7 @@   * Bitmask of used SCU counters   */  static unsigned int scu_em_used; +static const struct pmu_irqs *pmu_irqs;  /*   * 2 helper fns take a counter number from 0-7 (not the userspace-visible counter number) @@ -225,33 +228,40 @@ static int em_setup_ctrs(void)  	return 0;  } -static int arm11_irqs[] = { -	[0]	= IRQ_EB11MP_PMU_CPU0, -	[1]	= IRQ_EB11MP_PMU_CPU1, -	[2]	= IRQ_EB11MP_PMU_CPU2, -	[3]	= IRQ_EB11MP_PMU_CPU3 -}; -  static int em_start(void)  {  	int ret; -	ret = arm11_request_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs)); +	pmu_irqs = reserve_pmu(); +	if (IS_ERR(pmu_irqs)) { +		ret = PTR_ERR(pmu_irqs); +		goto out; +	} + +	ret = arm11_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs);  	if (ret == 0) {  		em_call_function(arm11_start_pmu);  		ret = scu_start(); -		if (ret) -			arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs)); +		if (ret) { +			arm11_release_interrupts(pmu_irqs->irqs, +						 pmu_irqs->num_irqs); +		} else { +			release_pmu(pmu_irqs); +			pmu_irqs = NULL; +		}  	} + +out:  	return ret;  }  static void em_stop(void)  {  	em_call_function(arm11_stop_pmu); -	arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs)); +	arm11_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs);  	scu_stop(); +	release_pmu(pmu_irqs);  }  /* @@ -283,15 +293,7 @@ static int em_setup(void)  	em_route_irq(IRQ_EB11MP_PMU_SCU6, 3);  	em_route_irq(IRQ_EB11MP_PMU_SCU7, 3); -	/* -	 * Send CP15 PMU interrupts to the owner CPU. -	 */ -	em_route_irq(IRQ_EB11MP_PMU_CPU0, 0); -	em_route_irq(IRQ_EB11MP_PMU_CPU1, 1); -	em_route_irq(IRQ_EB11MP_PMU_CPU2, 2); -	em_route_irq(IRQ_EB11MP_PMU_CPU3, 3); - -	return 0; +	return init_pmu();  }  struct op_arm_model_spec op_mpcore_spec = { diff --git a/arch/arm/oprofile/op_model_v6.c b/arch/arm/oprofile/op_model_v6.c index f7d2ec5ee9a..a22357a2fd0 100644 --- a/arch/arm/oprofile/op_model_v6.c +++ b/arch/arm/oprofile/op_model_v6.c @@ -19,39 +19,47 @@  /* #define DEBUG */  #include <linux/types.h>  #include <linux/errno.h> +#include <linux/err.h>  #include <linux/sched.h>  #include <linux/oprofile.h>  #include <linux/interrupt.h>  #include <asm/irq.h>  #include <asm/system.h> +#include <asm/pmu.h>  #include "op_counter.h"  #include "op_arm_model.h"  #include "op_model_arm11_core.h" -static int irqs[] = { -#ifdef CONFIG_ARCH_OMAP2 -	3, -#endif -#ifdef CONFIG_ARCH_BCMRING -	IRQ_PMUIRQ, /* for BCMRING, ARM PMU interrupt is 43 */ -#endif -}; +static const struct pmu_irqs *pmu_irqs;  static void armv6_pmu_stop(void)  {  	arm11_stop_pmu(); -	arm11_release_interrupts(irqs, ARRAY_SIZE(irqs)); +	arm11_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); +	release_pmu(pmu_irqs); +	pmu_irqs = NULL;  }  static int armv6_pmu_start(void)  {  	int ret; -	ret = arm11_request_interrupts(irqs, ARRAY_SIZE(irqs)); -	if (ret >= 0) +	pmu_irqs = reserve_pmu(); +	if (IS_ERR(pmu_irqs)) { +		ret = PTR_ERR(pmu_irqs); +		goto out; +	} + +	ret = arm11_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); +	if (ret >= 0) {  		ret = arm11_start_pmu(); +	} else { +		release_pmu(pmu_irqs); +		pmu_irqs = NULL; +	} +out:  	return ret;  } diff --git a/arch/arm/oprofile/op_model_v7.c b/arch/arm/oprofile/op_model_v7.c index 2088a6c0cc0..8642d0891ae 100644 --- a/arch/arm/oprofile/op_model_v7.c +++ b/arch/arm/oprofile/op_model_v7.c @@ -11,11 +11,14 @@   */  #include <linux/types.h>  #include <linux/errno.h> +#include <linux/err.h>  #include <linux/oprofile.h>  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/smp.h> +#include <asm/pmu.h> +  #include "op_counter.h"  #include "op_arm_model.h"  #include "op_model_v7.h" @@ -295,7 +298,7 @@ static irqreturn_t armv7_pmnc_interrupt(int irq, void *arg)  	return IRQ_HANDLED;  } -int armv7_request_interrupts(int *irqs, int nr) +int armv7_request_interrupts(const int *irqs, int nr)  {  	unsigned int i;  	int ret = 0; @@ -318,7 +321,7 @@ int armv7_request_interrupts(int *irqs, int nr)  	return ret;  } -void armv7_release_interrupts(int *irqs, int nr) +void armv7_release_interrupts(const int *irqs, int nr)  {  	unsigned int i; @@ -362,12 +365,7 @@ static void armv7_pmnc_dump_regs(void)  }  #endif - -static int irqs[] = { -#ifdef CONFIG_ARCH_OMAP3 -	INT_34XX_BENCH_MPU_EMUL, -#endif -}; +static const struct pmu_irqs *pmu_irqs;  static void armv7_pmnc_stop(void)  { @@ -375,19 +373,29 @@ static void armv7_pmnc_stop(void)  	armv7_pmnc_dump_regs();  #endif  	armv7_stop_pmnc(); -	armv7_release_interrupts(irqs, ARRAY_SIZE(irqs)); +	armv7_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); +	release_pmu(pmu_irqs); +	pmu_irqs = NULL;  }  static int armv7_pmnc_start(void)  {  	int ret; +	pmu_irqs = reserve_pmu(); +	if (IS_ERR(pmu_irqs)) +		return PTR_ERR(pmu_irqs); +  #ifdef DEBUG  	armv7_pmnc_dump_regs();  #endif -	ret = armv7_request_interrupts(irqs, ARRAY_SIZE(irqs)); -	if (ret >= 0) +	ret = armv7_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); +	if (ret >= 0) {  		armv7_start_pmnc(); +	} else { +		release_pmu(pmu_irqs); +		pmu_irqs = NULL; +	}  	return ret;  } diff --git a/arch/arm/oprofile/op_model_v7.h b/arch/arm/oprofile/op_model_v7.h index 0e19bcc2e10..9ca334b39c7 100644 --- a/arch/arm/oprofile/op_model_v7.h +++ b/arch/arm/oprofile/op_model_v7.h @@ -97,7 +97,7 @@  int armv7_setup_pmu(void);  int armv7_start_pmu(void);  int armv7_stop_pmu(void); -int armv7_request_interrupts(int *, int); -void armv7_release_interrupts(int *, int); +int armv7_request_interrupts(const int *, int); +void armv7_release_interrupts(const int *, int);  #endif diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c index 724ab9ce252..1d34a02048b 100644 --- a/arch/arm/oprofile/op_model_xscale.c +++ b/arch/arm/oprofile/op_model_xscale.c @@ -17,12 +17,14 @@  /* #define DEBUG */  #include <linux/types.h>  #include <linux/errno.h> +#include <linux/err.h>  #include <linux/sched.h>  #include <linux/oprofile.h>  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <asm/cputype.h> +#include <asm/pmu.h>  #include "op_counter.h"  #include "op_arm_model.h" @@ -33,17 +35,6 @@  #define	PMU_RESET	(CCNT_RESET | PMN_RESET)  #define PMU_CNT64	0x008	/* Make CCNT count every 64th cycle */ -/* TODO do runtime detection */ -#ifdef CONFIG_ARCH_IOP32X -#define XSCALE_PMU_IRQ  IRQ_IOP32X_CORE_PMU -#endif -#ifdef CONFIG_ARCH_IOP33X -#define XSCALE_PMU_IRQ  IRQ_IOP33X_CORE_PMU -#endif -#ifdef CONFIG_ARCH_PXA -#define XSCALE_PMU_IRQ  IRQ_PMU -#endif -  /*   * Different types of events that can be counted by the XScale PMU   * as used by Oprofile userspace. Here primarily for documentation @@ -367,6 +358,8 @@ static irqreturn_t xscale_pmu_interrupt(int irq, void *arg)  	return IRQ_HANDLED;  } +static const struct pmu_irqs *pmu_irqs; +  static void xscale_pmu_stop(void)  {  	u32 pmnc = read_pmnc(); @@ -374,20 +367,30 @@ static void xscale_pmu_stop(void)  	pmnc &= ~PMU_ENABLE;  	write_pmnc(pmnc); -	free_irq(XSCALE_PMU_IRQ, results); +	free_irq(pmu_irqs->irqs[0], results); +	release_pmu(pmu_irqs); +	pmu_irqs = NULL;  }  static int xscale_pmu_start(void)  {  	int ret; -	u32 pmnc = read_pmnc(); +	u32 pmnc; + +	pmu_irqs = reserve_pmu(); +	if (IS_ERR(pmu_irqs)) +		return PTR_ERR(pmu_irqs); + +	pmnc = read_pmnc(); -	ret = request_irq(XSCALE_PMU_IRQ, xscale_pmu_interrupt, IRQF_DISABLED, -			"XScale PMU", (void *)results); +	ret = request_irq(pmu_irqs->irqs[0], xscale_pmu_interrupt, +			  IRQF_DISABLED, "XScale PMU", (void *)results);  	if (ret < 0) {  		printk(KERN_ERR "oprofile: unable to request IRQ%d for XScale PMU\n", -			XSCALE_PMU_IRQ); +		       pmu_irqs->irqs[0]); +		release_pmu(pmu_irqs); +		pmu_irqs = NULL;  		return ret;  	} diff --git a/arch/arm/plat-iop/io.c b/arch/arm/plat-iop/io.c index ed0bbece0d6..e15bc17db90 100644 --- a/arch/arm/plat-iop/io.c +++ b/arch/arm/plat-iop/io.c @@ -34,7 +34,8 @@ void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size,  		retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie);  		break;  	default: -		retval = __arm_ioremap(cookie, size, mtype); +		retval = __arm_ioremap_caller(cookie, size, mtype, +				__builtin_return_address(0));  	}  	return retval; diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S index 15b2b148a10..5a6ae1b9e1e 100644 --- a/arch/arm/plat-mxc/include/mach/debug-macro.S +++ b/arch/arm/plat-mxc/include/mach/debug-macro.S @@ -52,7 +52,7 @@  #define UART_PADDR	MXC91231_UART2_BASE_ADDR  #define UART_VADDR	MXC91231_AIPS1_IO_ADDRESS(MXC91231_UART2_BASE_ADDR)  #endif -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		ldreq	\rx, =UART_PADDR	@ physical diff --git a/arch/arm/plat-mxc/include/mach/vmalloc.h b/arch/arm/plat-mxc/include/mach/vmalloc.h index 62d97623412..44243a27843 100644 --- a/arch/arm/plat-mxc/include/mach/vmalloc.h +++ b/arch/arm/plat-mxc/include/mach/vmalloc.h @@ -21,6 +21,6 @@  #define __ASM_ARCH_MXC_VMALLOC_H__  /* vmalloc ending address */ -#define VMALLOC_END       0xF4000000 +#define VMALLOC_END       0xf4000000UL  #endif /* __ASM_ARCH_MXC_VMALLOC_H__ */ diff --git a/arch/arm/plat-nomadik/include/plat/i2c.h b/arch/arm/plat-nomadik/include/plat/i2c.h new file mode 100644 index 00000000000..1621db67a53 --- /dev/null +++ b/arch/arm/plat-nomadik/include/plat/i2c.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2009 ST-Ericsson + * + * 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 __PLAT_I2C_H +#define __PLAT_I2C_H + +enum i2c_freq_mode { +	I2C_FREQ_MODE_STANDARD,		/* up to 100 Kb/s */ +	I2C_FREQ_MODE_FAST,		/* up to 400 Kb/s */ +	I2C_FREQ_MODE_FAST_PLUS,	/* up to 1 Mb/s */ +	I2C_FREQ_MODE_HIGH_SPEED	/* up to 3.4 Mb/s */ +}; + +/** + * struct nmk_i2c_controller - client specific controller configuration + * @clk_freq:	clock frequency for the operation mode + * @slsu:	Slave data setup time in ns. + *		The needed setup time for three modes of operation + *		are 250ns, 100ns and 10ns respectively thus leading + *		to the values of 14, 6, 2 for a 48 MHz i2c clk + * @tft:	Tx FIFO Threshold in bytes + * @rft:	Rx FIFO Threshold in bytes + * @sm:		speed mode + */ +struct nmk_i2c_controller { +	unsigned long	clk_freq; +	unsigned short	slsu; +	unsigned char 	tft; +	unsigned char 	rft; +	enum i2c_freq_mode	sm; +}; + +#endif	/* __PLAT_I2C_H */ diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index e2ea04a4c8a..2e3eec66086 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -22,6 +22,7 @@ config ARCH_OMAP3  	bool "TI OMAP3"  	select CPU_V7  	select COMMON_CLKDEV +	select ARM_L1_CACHE_SHIFT_6  config ARCH_OMAP4  	bool "TI OMAP4" diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h index ef870de43c2..c7d628ecb46 100644 --- a/arch/arm/plat-omap/include/plat/omap44xx.h +++ b/arch/arm/plat-omap/include/plat/omap44xx.h @@ -40,6 +40,7 @@  #define OMAP44XX_GIC_CPU_BASE		0x48240100  #define OMAP44XX_SCU_BASE		0x48240000  #define OMAP44XX_LOCAL_TWD_BASE		0x48240600 +#define OMAP44XX_L2CACHE_BASE		0x48242000  #define OMAP44XX_WKUPGEN_BASE		0x48281000  #define OMAP44XX_MAILBOX_BASE		(L4_44XX_BASE + 0xF4000) diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c index 0cfd54f519c..4cbd4fb3232 100644 --- a/arch/arm/plat-omap/io.c +++ b/arch/arm/plat-omap/io.c @@ -128,7 +128,7 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)  			return XLATE(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_VIRT);  	}  #endif -	return __arm_ioremap(p, size, type); +	return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));  }  EXPORT_SYMBOL(omap_ioremap); diff --git a/arch/arm/plat-s3c/include/mach/vmalloc.h b/arch/arm/plat-s3c/include/mach/vmalloc.h index bfd2ca6e307..299d95f365c 100644 --- a/arch/arm/plat-s3c/include/mach/vmalloc.h +++ b/arch/arm/plat-s3c/include/mach/vmalloc.h @@ -15,6 +15,6 @@  #ifndef __ASM_ARCH_VMALLOC_H  #define __ASM_ARCH_VMALLOC_H -#define VMALLOC_END	  (0xE0000000) +#define VMALLOC_END	  (0xe0000000UL)  #endif /* __ASM_ARCH_VMALLOC_H */ diff --git a/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S index fb3b969bf0a..1b9348bf0e4 100644 --- a/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S +++ b/arch/arm/plat-stmp3xxx/include/mach/debug-macro.S @@ -16,7 +16,7 @@   * http://www.gnu.org/copyleft/gpl.html   */ -		.macro	addruart,rx +		.macro	addruart, rx, tmp  		mrc	p15, 0, \rx, c1, c0  		tst	\rx, #1			@ MMU enabled?  		moveq	\rx, #0x80000000	@ physical base address diff --git a/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h b/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h index 541b880c186..943c1a29d64 100644 --- a/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h +++ b/arch/arm/plat-stmp3xxx/include/mach/vmalloc.h @@ -9,4 +9,4 @@   * http://www.opensource.org/licenses/gpl-license.html   * http://www.gnu.org/copyleft/gpl.html   */ -#define VMALLOC_END       (0xF0000000) +#define VMALLOC_END       0xf0000000UL diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index f60a5400a25..def19f83d81 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -430,7 +430,11 @@ static inline void vfp_pm_init(void) { }   * saved one. This function is used by the ptrace mechanism.   */  #ifdef CONFIG_SMP -void vfp_sync_state(struct thread_info *thread) +void vfp_sync_hwstate(struct thread_info *thread) +{ +} + +void vfp_flush_hwstate(struct thread_info *thread)  {  	/*  	 * On SMP systems, the VFP state is automatically saved at every @@ -441,35 +445,48 @@ void vfp_sync_state(struct thread_info *thread)  	thread->vfpstate.hard.cpu = NR_CPUS;  }  #else -void vfp_sync_state(struct thread_info *thread) +void vfp_sync_hwstate(struct thread_info *thread)  {  	unsigned int cpu = get_cpu(); -	u32 fpexc = fmrx(FPEXC);  	/* -	 * If VFP is enabled, the previous state was already saved and -	 * last_VFP_context updated. +	 * If the thread we're interested in is the current owner of the +	 * hardware VFP state, then we need to save its state.  	 */ -	if (fpexc & FPEXC_EN) -		goto out; +	if (last_VFP_context[cpu] == &thread->vfpstate) { +		u32 fpexc = fmrx(FPEXC); -	if (!last_VFP_context[cpu]) -		goto out; +		/* +		 * Save the last VFP state on this CPU. +		 */ +		fmxr(FPEXC, fpexc | FPEXC_EN); +		vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); +		fmxr(FPEXC, fpexc); +	} -	/* -	 * Save the last VFP state on this CPU. -	 */ -	fmxr(FPEXC, fpexc | FPEXC_EN); -	vfp_save_state(last_VFP_context[cpu], fpexc); -	fmxr(FPEXC, fpexc); +	put_cpu(); +} + +void vfp_flush_hwstate(struct thread_info *thread) +{ +	unsigned int cpu = get_cpu();  	/* -	 * Set the context to NULL to force a reload the next time the thread -	 * uses the VFP. +	 * If the thread we're interested in is the current owner of the +	 * hardware VFP state, then we need to save its state.  	 */ -	last_VFP_context[cpu] = NULL; +	if (last_VFP_context[cpu] == &thread->vfpstate) { +		u32 fpexc = fmrx(FPEXC); + +		fmxr(FPEXC, fpexc & ~FPEXC_EN); + +		/* +		 * Set the context to NULL to force a reload the next time +		 * the thread uses the VFP. +		 */ +		last_VFP_context[cpu] = NULL; +	} -out:  	put_cpu();  }  #endif diff --git a/arch/avr32/include/asm/pgtable.h b/arch/avr32/include/asm/pgtable.h index fecdda16f44..a9ae30c41e7 100644 --- a/arch/avr32/include/asm/pgtable.h +++ b/arch/avr32/include/asm/pgtable.h @@ -325,7 +325,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)  struct vm_area_struct;  extern void update_mmu_cache(struct vm_area_struct * vma, -			     unsigned long address, pte_t pte); +			     unsigned long address, pte_t *ptep);  /*   * Encode and decode a swap entry diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c index 06677be98ff..0da23109f81 100644 --- a/arch/avr32/mm/tlb.c +++ b/arch/avr32/mm/tlb.c @@ -101,7 +101,7 @@ static void update_dtlb(unsigned long address, pte_t pte)  }  void update_mmu_cache(struct vm_area_struct *vma, -		      unsigned long address, pte_t pte) +		      unsigned long address, pte_t *ptep)  {  	unsigned long flags; @@ -110,7 +110,7 @@ void update_mmu_cache(struct vm_area_struct *vma,  		return;  	local_irq_save(flags); -	update_dtlb(address, pte); +	update_dtlb(address, *ptep);  	local_irq_restore(flags);  } diff --git a/arch/cris/include/asm/pgtable.h b/arch/cris/include/asm/pgtable.h index 1fcce00f01f..99ea6cd1b14 100644 --- a/arch/cris/include/asm/pgtable.h +++ b/arch/cris/include/asm/pgtable.h @@ -270,7 +270,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */   * Actually I am not sure on what this could be used for.   */  static inline void update_mmu_cache(struct vm_area_struct * vma, -	unsigned long address, pte_t pte) +	unsigned long address, pte_t *ptep)  {  } diff --git a/arch/frv/include/asm/pgtable.h b/arch/frv/include/asm/pgtable.h index 22c60692b55..c18b0d32e63 100644 --- a/arch/frv/include/asm/pgtable.h +++ b/arch/frv/include/asm/pgtable.h @@ -505,7 +505,7 @@ static inline int pte_file(pte_t pte)  /*   * preload information about a newly instantiated PTE into the SCR0/SCR1 PGE cache   */ -static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)  {  	struct mm_struct *mm;  	unsigned long ampr; diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h index 69bf13857a9..c3286f42e50 100644 --- a/arch/ia64/include/asm/pgtable.h +++ b/arch/ia64/include/asm/pgtable.h @@ -462,7 +462,7 @@ pte_same (pte_t a, pte_t b)  	return pte_val(a) == pte_val(b);  } -#define update_mmu_cache(vma, address, pte) do { } while (0) +#define update_mmu_cache(vma, address, ptep) do { } while (0)  extern pgd_t swapper_pg_dir[PTRS_PER_PGD];  extern void paging_init (void); diff --git a/arch/m32r/include/asm/tlbflush.h b/arch/m32r/include/asm/tlbflush.h index 0ef95307784..92614b0ccf1 100644 --- a/arch/m32r/include/asm/tlbflush.h +++ b/arch/m32r/include/asm/tlbflush.h @@ -92,6 +92,6 @@ static __inline__ void __flush_tlb_all(void)  	);  } -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);  #endif	/* _ASM_M32R_TLBFLUSH_H */ diff --git a/arch/m32r/mm/fault-nommu.c b/arch/m32r/mm/fault-nommu.c index 88469178ea6..888aab1157e 100644 --- a/arch/m32r/mm/fault-nommu.c +++ b/arch/m32r/mm/fault-nommu.c @@ -95,7 +95,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,   * update_mmu_cache()   *======================================================================*/  void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, -	pte_t pte) +	pte_t *ptep)  {  	BUG();  } diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c index 7274b47f4c2..28ee389e5f5 100644 --- a/arch/m32r/mm/fault.c +++ b/arch/m32r/mm/fault.c @@ -336,7 +336,7 @@ vmalloc_fault:  		addr = (address & PAGE_MASK);  		set_thread_fault_code(error_code); -		update_mmu_cache(NULL, addr, *pte_k); +		update_mmu_cache(NULL, addr, pte_k);  		set_thread_fault_code(0);  		return;  	} @@ -349,7 +349,7 @@ vmalloc_fault:  #define ITLB_END	(unsigned long *)(ITLB_BASE + (NR_TLB_ENTRIES * 8))  #define DTLB_END	(unsigned long *)(DTLB_BASE + (NR_TLB_ENTRIES * 8))  void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr, -	pte_t pte) +	pte_t *ptep)  {  	volatile unsigned long *entry1, *entry2;  	unsigned long pte_data, flags; @@ -365,7 +365,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr,  	vaddr = (vaddr & PAGE_MASK) | get_asid(); -	pte_data = pte_val(pte); +	pte_data = pte_val(*ptep);  #ifdef CONFIG_CHIP_OPSP  	entry1 = (unsigned long *)ITLB_BASE; diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h index aca0e28581c..87174c904d2 100644 --- a/arch/m68k/include/asm/pgtable_mm.h +++ b/arch/m68k/include/asm/pgtable_mm.h @@ -115,7 +115,7 @@ extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);   * they are updated on demand.   */  static inline void update_mmu_cache(struct vm_area_struct *vma, -				    unsigned long address, pte_t pte) +				    unsigned long address, pte_t *ptep)  {  } diff --git a/arch/microblaze/include/asm/tlbflush.h b/arch/microblaze/include/asm/tlbflush.h index eb31a0e8a77..10ec70cd873 100644 --- a/arch/microblaze/include/asm/tlbflush.h +++ b/arch/microblaze/include/asm/tlbflush.h @@ -38,7 +38,7 @@ static inline void local_flush_tlb_range(struct vm_area_struct *vma,  #define flush_tlb_kernel_range(start, end)	do { } while (0) -#define update_mmu_cache(vma, addr, pte)	do { } while (0) +#define update_mmu_cache(vma, addr, ptep)	do { } while (0)  #define flush_tlb_all local_flush_tlb_all  #define flush_tlb_mm local_flush_tlb_mm diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 1854336e56a..c56bf8afc09 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -362,8 +362,9 @@ extern void __update_cache(struct vm_area_struct *vma, unsigned long address,  	pte_t pte);  static inline void update_mmu_cache(struct vm_area_struct *vma, -	unsigned long address, pte_t pte) +	unsigned long address, pte_t *ptep)  { +	pte_t pte = *ptep;  	__update_tlb(vma, address, pte);  	__update_cache(vma, address, pte);  } diff --git a/arch/mn10300/include/asm/pgtable.h b/arch/mn10300/include/asm/pgtable.h index 6dc30fc827c..16d88577f3e 100644 --- a/arch/mn10300/include/asm/pgtable.h +++ b/arch/mn10300/include/asm/pgtable.h @@ -466,7 +466,7 @@ static inline int set_kernel_exec(unsigned long vaddr, int enable)   * the kernel page tables containing the necessary information by tlb-mn10300.S   */  extern void update_mmu_cache(struct vm_area_struct *vma, -			     unsigned long address, pte_t pte); +			     unsigned long address, pte_t *ptep);  #endif /* !__ASSEMBLY__ */ diff --git a/arch/mn10300/mm/mmu-context.c b/arch/mn10300/mm/mmu-context.c index 31c9d27a75a..36ba02191d4 100644 --- a/arch/mn10300/mm/mmu-context.c +++ b/arch/mn10300/mm/mmu-context.c @@ -51,9 +51,10 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)  /*   * preemptively set a TLB entry   */ -void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) +void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)  {  	unsigned long pteu, ptel, cnx, flags; +	pte_t pte = *ptep;  	addr &= PAGE_MASK;  	ptel = pte_val(pte) & ~(xPTEL_UNUSED1 | xPTEL_UNUSED2); diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index a27d2e200fb..01c15035e78 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -410,7 +410,7 @@ extern void paging_init (void);  #define PG_dcache_dirty         PG_arch_1 -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);  /* Encode and de-code a swap entry */ diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index b6ed34de14e..1054baa2fc6 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -68,9 +68,9 @@ flush_cache_all_local(void)  EXPORT_SYMBOL(flush_cache_all_local);  void -update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)  { -	struct page *page = pte_page(pte); +	struct page *page = pte_page(*ptep);  	if (pfn_valid(page_to_pfn(page)) && page_mapping(page) &&  	    test_bit(PG_dcache_dirty, &page->flags)) { diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 21207e54825..89f158731ce 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -209,7 +209,7 @@ extern void paging_init(void);   * corresponding HPTE into the hash table ahead of time, instead of   * waiting for the inevitable extra hash-table miss exception.   */ -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);  extern int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, unsigned long addr,  		      unsigned long end, int write, struct page **pages, int *nr); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index b9b152558f9..311224cdb7a 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -494,13 +494,13 @@ EXPORT_SYMBOL(flush_icache_user_range);   * This must always be called with the pte lock held.   */  void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, -		      pte_t pte) +		      pte_t *ptep)  {  #ifdef CONFIG_PPC_STD_MMU  	unsigned long access = 0, trap;  	/* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ -	if (!pte_young(pte) || address >= TASK_SIZE) +	if (!pte_young(*ptep) || address >= TASK_SIZE)  		return;  	/* We try to figure out if we are coming from an instruction diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index e2fa79cf061..9b5b9189c15 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -43,7 +43,7 @@ extern void vmem_map_init(void);   * The S390 doesn't have any external MMU info: the kernel page   * tables contain all the necessary information.   */ -#define update_mmu_cache(vma, address, pte)     do { } while (0) +#define update_mmu_cache(vma, address, ptep)     do { } while (0)  /*   * ZERO_PAGE is a global shared page that is always zero: used diff --git a/arch/score/include/asm/pgtable.h b/arch/score/include/asm/pgtable.h index 674934b4017..ccf38f06c57 100644 --- a/arch/score/include/asm/pgtable.h +++ b/arch/score/include/asm/pgtable.h @@ -272,8 +272,9 @@ extern void __update_cache(struct vm_area_struct *vma,  	unsigned long address,	pte_t pte);  static inline void update_mmu_cache(struct vm_area_struct *vma, -	unsigned long address, pte_t pte) +	unsigned long address, pte_t *ptep)  { +	pte_t pte = *ptep;  	__update_tlb(vma, address, pte);  	__update_cache(vma, address, pte);  } diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index ba3046e4f06..1ff93ac1aa4 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -165,8 +165,9 @@ extern void __update_tlb(struct vm_area_struct *vma,  			 unsigned long address, pte_t pte);  static inline void -update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)  { +	pte_t pte = *ptep;  	__update_cache(vma, address, pte);  	__update_tlb(vma, address, pte);  } diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 47530104e0a..1677b5ee191 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -371,7 +371,7 @@ handle_tlbmiss(struct pt_regs *regs, unsigned long writeaccess,  		local_flush_tlb_one(get_asid(), address & PAGE_MASK);  #endif -	update_mmu_cache(NULL, address, entry); +	update_mmu_cache(NULL, address, pte);  	return 0;  } diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index e0cabe790ec..77f906d8cc2 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h @@ -330,9 +330,9 @@ BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *)  #define FAULT_CODE_WRITE    0x2  #define FAULT_CODE_USER     0x4 -BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t) +BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t *) -#define update_mmu_cache(vma,addr,pte) BTFIXUP_CALL(update_mmu_cache)(vma,addr,pte) +#define update_mmu_cache(vma,addr,ptep) BTFIXUP_CALL(update_mmu_cache)(vma,addr,ptep)  BTFIXUPDEF_CALL(void, sparc_mapiorange, unsigned int, unsigned long,      unsigned long, unsigned int) diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index f3cb790fa2a..f5b5fa76c02 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -706,7 +706,7 @@ extern unsigned long find_ecache_flush_span(unsigned long size);  #define mmu_unlockarea(vaddr, len)		do { } while(0)  struct vm_area_struct; -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);  /* Encode and de-code a swap entry */  #define __swp_type(entry)	(((entry).val >> PAGE_SHIFT) & 0xffUL) diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index b99f81c4906..43e20efb251 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c @@ -370,7 +370,7 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,  			       unsigned long address)  {  	extern void sun4c_update_mmu_cache(struct vm_area_struct *, -					   unsigned long,pte_t); +					   unsigned long,pte_t *);  	extern pte_t *sun4c_pte_offset_kernel(pmd_t *,unsigned long);  	struct task_struct *tsk = current;  	struct mm_struct *mm = tsk->mm; @@ -447,7 +447,7 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,  		 *       on the CPU and doing a shrink_mmap() on this vma.  		 */  		sun4c_update_mmu_cache (find_vma(current->mm, address), address, -					*ptep); +					ptep);  	else  		do_sparc_fault(regs, text_fault, write, address);  } diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 1886d37d411..9245a822a2f 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -289,12 +289,13 @@ static void flush_dcache(unsigned long pfn)  	}  } -void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)  {  	struct mm_struct *mm;  	struct tsb *tsb;  	unsigned long tag, flags;  	unsigned long tsb_index, tsb_hash_shift; +	pte_t pte = *ptep;  	if (tlb_type != hypervisor) {  		unsigned long pfn = pte_pfn(pte); diff --git a/arch/sparc/mm/nosun4c.c b/arch/sparc/mm/nosun4c.c index 196263f895b..4e62c27147c 100644 --- a/arch/sparc/mm/nosun4c.c +++ b/arch/sparc/mm/nosun4c.c @@ -62,7 +62,7 @@ pte_t *sun4c_pte_offset_kernel(pmd_t *dir, unsigned long address)  	return NULL;  } -void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)  {  } diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 367321a030d..df49b200ca4 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -694,7 +694,7 @@ extern void tsunami_setup_blockops(void);   * The following code is a deadwood that may be necessary when   * we start to make precise page flushes again. --zaitcev   */ -static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) +static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t *ptep)  {  #if 0  	static unsigned long last; @@ -703,10 +703,10 @@ static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long ad  	if (address == last) {  		val = srmmu_hwprobe(address); -		if (val != 0 && pte_val(pte) != val) { +		if (val != 0 && pte_val(*ptep) != val) {  			printk("swift_update_mmu_cache: "  			    "addr %lx put %08x probed %08x from %p\n", -			    address, pte_val(pte), val, +			    address, pte_val(*ptep), val,  			    __builtin_return_address(0));  			srmmu_flush_whole_tlb();  		} diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index a89baf0d875..18652534b91 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1887,7 +1887,7 @@ static void sun4c_check_pgt_cache(int low, int high)  /* An experiment, turn off by default for now... -DaveM */  #define SUN4C_PRELOAD_PSEG -void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)  {  	unsigned long flags;  	int pseg; @@ -1929,7 +1929,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p  			start += PAGE_SIZE;  		}  #ifndef SUN4C_PRELOAD_PSEG -		sun4c_put_pte(address, pte_val(pte)); +		sun4c_put_pte(address, pte_val(*ptep));  #endif  		local_irq_restore(flags);  		return; @@ -1940,7 +1940,7 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p  		add_lru(entry);  	} -	sun4c_put_pte(address, pte_val(pte)); +	sun4c_put_pte(address, pte_val(*ptep));  	local_irq_restore(flags);  } diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index 9ce3f165111..a9f7251b4a8 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h @@ -345,7 +345,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)  struct mm_struct;  extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); -#define update_mmu_cache(vma,address,pte) do ; while (0) +#define update_mmu_cache(vma,address,ptep) do ; while (0)  /* Encode and de-code a swap entry */  #define __swp_type(x)			(((x).val >> 4) & 0x3f) diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 01fd9461d32..a2866839650 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -80,7 +80,7 @@ do {						\   * The i386 doesn't have any external MMU info: the kernel page   * tables contain all the necessary information.   */ -#define update_mmu_cache(vma, address, pte) do { } while (0) +#define update_mmu_cache(vma, address, ptep) do { } while (0)  #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index c57a3011714..181be528c61 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -129,7 +129,7 @@ static inline int pgd_large(pgd_t pgd) { return 0; }  #define pte_unmap(pte) /* NOP */  #define pte_unmap_nested(pte) /* NOP */ -#define update_mmu_cache(vma, address, pte) do { } while (0) +#define update_mmu_cache(vma, address, ptep) do { } while (0)  /* Encode and de-code a swap entry */  #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index a138770c358..76bf3555411 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -394,7 +394,7 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)  #define kern_addr_valid(addr)	(1)  extern  void update_mmu_cache(struct vm_area_struct * vma, -			      unsigned long address, pte_t pte); +			      unsigned long address, pte_t *ptep);  /*   * remap a physical page `pfn' of size `size' with page protection `prot' diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index 3ba990c6767..85df4655d32 100644 --- a/arch/xtensa/mm/cache.c +++ b/arch/xtensa/mm/cache.c @@ -147,9 +147,9 @@ void flush_cache_page(struct vm_area_struct* vma, unsigned long address,  #endif  void -update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte) +update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)  { -	unsigned long pfn = pte_pfn(pte); +	unsigned long pfn = pte_pfn(*ptep);  	struct page *page;  	if (!pfn_valid(pfn)) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 90d168ad03b..84c103a7ee1 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -2,6 +2,7 @@   *  linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver   *   *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. + *  Copyright (C) 2010 ST-Ericsson AB.   *   * 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 @@ -34,9 +35,6 @@  #define DRIVER_NAME "mmci-pl18x" -#define DBG(host,fmt,args...)	\ -	pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args) -  static unsigned int fmax = 515633;  /* @@ -105,8 +103,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)  	void __iomem *base;  	int blksz_bits; -	DBG(host, "blksz %04x blks %04x flags %08x\n", -	    data->blksz, data->blocks, data->flags); +	dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n", +		data->blksz, data->blocks, data->flags);  	host->data = data;  	host->size = data->blksz; @@ -155,7 +153,7 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)  {  	void __iomem *base = host->base; -	DBG(host, "op %02x arg %08x flags %08x\n", +	dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n",  	    cmd->opcode, cmd->arg, cmd->flags);  	if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) { @@ -184,8 +182,20 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,  {  	if (status & MCI_DATABLOCKEND) {  		host->data_xfered += data->blksz; +#ifdef CONFIG_ARCH_U300 +		/* +		 * On the U300 some signal or other is +		 * badly routed so that a data write does +		 * not properly terminate with a MCI_DATAEND +		 * status flag. This quirk will make writes +		 * work again. +		 */ +		if (data->flags & MMC_DATA_WRITE) +			status |= MCI_DATAEND; +#endif  	}  	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { +		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);  		if (status & MCI_DATACRCFAIL)  			data->error = -EILSEQ;  		else if (status & MCI_DATATIMEOUT) @@ -307,7 +317,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)  	status = readl(base + MMCISTATUS); -	DBG(host, "irq1 %08x\n", status); +	dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status);  	do {  		unsigned long flags; @@ -401,7 +411,7 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)  		status &= readl(host->base + MMCIMASK0);  		writel(status, host->base + MMCICLEAR); -		DBG(host, "irq0 %08x\n", status); +		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);  		data = host->data;  		if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN| @@ -428,8 +438,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)  	WARN_ON(host->mrq != NULL);  	if (mrq->data && !is_power_of_2(mrq->data->blksz)) { -		printk(KERN_ERR "%s: Unsupported block size (%d bytes)\n", -			mmc_hostname(mmc), mrq->data->blksz); +		dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n", +			mrq->data->blksz);  		mrq->cmd->error = -EINVAL;  		mmc_request_done(mmc, mrq);  		return; @@ -582,8 +592,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  	host->hw_designer = amba_manf(dev);  	host->hw_revision = amba_rev(dev); -	DBG(host, "designer ID = 0x%02x\n", host->hw_designer); -	DBG(host, "revision = 0x%01x\n", host->hw_revision); +	dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer); +	dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision);  	host->clk = clk_get(&dev->dev, NULL);  	if (IS_ERR(host->clk)) { @@ -608,7 +618,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  		if (ret < 0)  			goto clk_disable;  		host->mclk = clk_get_rate(host->clk); -		DBG(host, "eventual mclk rate: %u Hz\n", host->mclk); +		dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n", +			host->mclk);  	}  	host->base = ioremap(dev->res.start, resource_size(&dev->res));  	if (!host->base) { @@ -619,6 +630,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  	mmc->ops = &mmci_ops;  	mmc->f_min = (host->mclk + 511) / 512;  	mmc->f_max = min(host->mclk, fmax); +	dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); +  #ifdef CONFIG_REGULATOR  	/* If we're using the regulator framework, try to fetch a regulator */  	host->vcc = regulator_get(&dev->dev, "vmmc"); @@ -712,7 +725,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)  	mmc_add_host(mmc); -	printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n", +	dev_info(&dev->dev, "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n",  		mmc_hostname(mmc), amba_rev(dev), amba_config(dev),  		(unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 0264b117893..c256aacfa95 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -7,6 +7,9 @@   *   * Copyright 2006 (c) MontaVista Software, Inc.   * + * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> + * Copyright 2010 (c) ST-Ericsson AB + *   * 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 @@ -18,6 +21,9 @@  #include <linux/interrupt.h>  #include <linux/amba/bus.h>  #include <linux/io.h> +#include <linux/bcd.h> +#include <linux/delay.h> +#include <linux/version.h>  /*   * Register definitions @@ -30,35 +36,207 @@  #define	RTC_RIS		0x14	/* Raw interrupt status register */  #define	RTC_MIS		0x18	/* Masked interrupt status register */  #define	RTC_ICR		0x1c	/* Interrupt clear register */ +/* ST variants have additional timer functionality */ +#define RTC_TDR		0x20	/* Timer data read register */ +#define RTC_TLR		0x24	/* Timer data load register */ +#define RTC_TCR		0x28	/* Timer control register */ +#define RTC_YDR		0x30	/* Year data read register */ +#define RTC_YMR		0x34	/* Year match register */ +#define RTC_YLR		0x38	/* Year data load register */ + +#define RTC_CR_CWEN	(1 << 26)	/* Clockwatch enable bit */ + +#define RTC_TCR_EN	(1 << 1) /* Periodic timer enable bit */ + +/* Common bit definitions for Interrupt status and control registers */ +#define RTC_BIT_AI	(1 << 0) /* Alarm interrupt bit */ +#define RTC_BIT_PI	(1 << 1) /* Periodic interrupt bit. ST variants only. */ + +/* Common bit definations for ST v2 for reading/writing time */ +#define RTC_SEC_SHIFT 0 +#define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */ +#define RTC_MIN_SHIFT 6 +#define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */ +#define RTC_HOUR_SHIFT 12 +#define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */ +#define RTC_WDAY_SHIFT 17 +#define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */ +#define RTC_MDAY_SHIFT 20 +#define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */ +#define RTC_MON_SHIFT 25 +#define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */ + +#define RTC_TIMER_FREQ 32768  struct pl031_local {  	struct rtc_device *rtc;  	void __iomem *base; +	u8 hw_designer; +	u8 hw_revision:4;  }; -static irqreturn_t pl031_interrupt(int irq, void *dev_id) +static int pl031_alarm_irq_enable(struct device *dev, +	unsigned int enabled) +{ +	struct pl031_local *ldata = dev_get_drvdata(dev); +	unsigned long imsc; + +	/* Clear any pending alarm interrupts. */ +	writel(RTC_BIT_AI, ldata->base + RTC_ICR); + +	imsc = readl(ldata->base + RTC_IMSC); + +	if (enabled == 1) +		writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC); +	else +		writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC); + +	return 0; +} + +/* + * Convert Gregorian date to ST v2 RTC format. + */ +static int pl031_stv2_tm_to_time(struct device *dev, +				 struct rtc_time *tm, unsigned long *st_time, +	unsigned long *bcd_year) +{ +	int year = tm->tm_year + 1900; +	int wday = tm->tm_wday; + +	/* wday masking is not working in hardware so wday must be valid */ +	if (wday < -1 || wday > 6) { +		dev_err(dev, "invalid wday value %d\n", tm->tm_wday); +		return -EINVAL; +	} else if (wday == -1) { +		/* wday is not provided, calculate it here */ +		unsigned long time; +		struct rtc_time calc_tm; + +		rtc_tm_to_time(tm, &time); +		rtc_time_to_tm(time, &calc_tm); +		wday = calc_tm.tm_wday; +	} + +	*bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8); + +	*st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT) +			|	(tm->tm_mday << RTC_MDAY_SHIFT) +			|	((wday + 1) << RTC_WDAY_SHIFT) +			|	(tm->tm_hour << RTC_HOUR_SHIFT) +			|	(tm->tm_min << RTC_MIN_SHIFT) +			|	(tm->tm_sec << RTC_SEC_SHIFT); + +	return 0; +} + +/* + * Convert ST v2 RTC format to Gregorian date. + */ +static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year, +	struct rtc_time *tm) +{ +	tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100); +	tm->tm_mon  = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1; +	tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT); +	tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1; +	tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT); +	tm->tm_min  = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT); +	tm->tm_sec  = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT); + +	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); +	tm->tm_year -= 1900; + +	return 0; +} + +static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct pl031_local *ldata = dev_get_drvdata(dev); + +	pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR), +			readl(ldata->base + RTC_YDR), tm); + +	return 0; +} + +static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm) +{ +	unsigned long time; +	unsigned long bcd_year; +	struct pl031_local *ldata = dev_get_drvdata(dev); +	int ret; + +	ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year); +	if (ret == 0) { +		writel(bcd_year, ldata->base + RTC_YLR); +		writel(time, ldata->base + RTC_LR); +	} + +	return ret; +} + +static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)  { -	struct rtc_device *rtc = dev_id; +	struct pl031_local *ldata = dev_get_drvdata(dev); +	int ret; + +	ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR), +			readl(ldata->base + RTC_YMR), &alarm->time); -	rtc_update_irq(rtc, 1, RTC_AF); +	alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; +	alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI; -	return IRQ_HANDLED; +	return ret;  } -static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)  {  	struct pl031_local *ldata = dev_get_drvdata(dev); +	unsigned long time; +	unsigned long bcd_year; +	int ret; + +	/* At the moment, we can only deal with non-wildcarded alarm times. */ +	ret = rtc_valid_tm(&alarm->time); +	if (ret == 0) { +		ret = pl031_stv2_tm_to_time(dev, &alarm->time, +					    &time, &bcd_year); +		if (ret == 0) { +			writel(bcd_year, ldata->base + RTC_YMR); +			writel(time, ldata->base + RTC_MR); + +			pl031_alarm_irq_enable(dev, alarm->enabled); +		} +	} + +	return ret; +} + +static irqreturn_t pl031_interrupt(int irq, void *dev_id) +{ +	struct pl031_local *ldata = dev_id; +	unsigned long rtcmis; +	unsigned long events = 0; -	switch (cmd) { -	case RTC_AIE_OFF: -		writel(1, ldata->base + RTC_MIS); -		return 0; -	case RTC_AIE_ON: -		writel(0, ldata->base + RTC_MIS); -		return 0; +	rtcmis = readl(ldata->base + RTC_MIS); +	if (rtcmis) { +		writel(rtcmis, ldata->base + RTC_ICR); + +		if (rtcmis & RTC_BIT_AI) +			events |= (RTC_AF | RTC_IRQF); + +		/* Timer interrupt is only available in ST variants */ +		if ((rtcmis & RTC_BIT_PI) && +			(ldata->hw_designer == AMBA_VENDOR_ST)) +			events |= (RTC_PF | RTC_IRQF); + +		rtc_update_irq(ldata->rtc, 1, events); + +		return IRQ_HANDLED;  	} -	return -ENOIOCTLCMD; +	return IRQ_NONE;  }  static int pl031_read_time(struct device *dev, struct rtc_time *tm) @@ -74,11 +252,14 @@ static int pl031_set_time(struct device *dev, struct rtc_time *tm)  {  	unsigned long time;  	struct pl031_local *ldata = dev_get_drvdata(dev); +	int ret; -	rtc_tm_to_time(tm, &time); -	writel(time, ldata->base + RTC_LR); +	ret = rtc_tm_to_time(tm, &time); -	return 0; +	if (ret == 0) +		writel(time, ldata->base + RTC_LR); + +	return ret;  }  static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) @@ -86,8 +267,9 @@ static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)  	struct pl031_local *ldata = dev_get_drvdata(dev);  	rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); -	alarm->pending = readl(ldata->base + RTC_RIS); -	alarm->enabled = readl(ldata->base + RTC_IMSC); + +	alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI; +	alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;  	return 0;  } @@ -96,22 +278,71 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)  {  	struct pl031_local *ldata = dev_get_drvdata(dev);  	unsigned long time; +	int ret; + +	/* At the moment, we can only deal with non-wildcarded alarm times. */ +	ret = rtc_valid_tm(&alarm->time); +	if (ret == 0) { +		ret = rtc_tm_to_time(&alarm->time, &time); +		if (ret == 0) { +			writel(time, ldata->base + RTC_MR); +			pl031_alarm_irq_enable(dev, alarm->enabled); +		} +	} + +	return ret; +} + +/* Periodic interrupt is only available in ST variants. */ +static int pl031_irq_set_state(struct device *dev, int enabled) +{ +	struct pl031_local *ldata = dev_get_drvdata(dev); + +	if (enabled == 1) { +		/* Clear any pending timer interrupt. */ +		writel(RTC_BIT_PI, ldata->base + RTC_ICR); + +		writel(readl(ldata->base + RTC_IMSC) | RTC_BIT_PI, +			ldata->base + RTC_IMSC); -	rtc_tm_to_time(&alarm->time, &time); +		/* Now start the timer */ +		writel(readl(ldata->base + RTC_TCR) | RTC_TCR_EN, +			ldata->base + RTC_TCR); -	writel(time, ldata->base + RTC_MR); -	writel(!alarm->enabled, ldata->base + RTC_MIS); +	} else { +		writel(readl(ldata->base + RTC_IMSC) & (~RTC_BIT_PI), +			ldata->base + RTC_IMSC); + +		/* Also stop the timer */ +		writel(readl(ldata->base + RTC_TCR) & (~RTC_TCR_EN), +			ldata->base + RTC_TCR); +	} +	/* Wait at least 1 RTC32 clock cycle to ensure next access +	 * to RTC_TCR will succeed. +	 */ +	udelay(40);  	return 0;  } -static const struct rtc_class_ops pl031_ops = { -	.ioctl = pl031_ioctl, -	.read_time = pl031_read_time, -	.set_time = pl031_set_time, -	.read_alarm = pl031_read_alarm, -	.set_alarm = pl031_set_alarm, -}; +static int pl031_irq_set_freq(struct device *dev, int freq) +{ +	struct pl031_local *ldata = dev_get_drvdata(dev); + +	/* Cant set timer if it is already enabled */ +	if (readl(ldata->base + RTC_TCR) & RTC_TCR_EN) { +		dev_err(dev, "can't change frequency while timer enabled\n"); +		return -EINVAL; +	} + +	/* If self start bit in RTC_TCR is set timer will start here, +	 * but we never set that bit. Instead we start the timer when +	 * set_state is called with enabled == 1. +	 */ +	writel(RTC_TIMER_FREQ / freq, ldata->base + RTC_TLR); + +	return 0; +}  static int pl031_remove(struct amba_device *adev)  { @@ -131,18 +362,20 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id)  {  	int ret;  	struct pl031_local *ldata; +	struct rtc_class_ops *ops = id->data;  	ret = amba_request_regions(adev, NULL);  	if (ret)  		goto err_req; -	ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL); +	ldata = kzalloc(sizeof(struct pl031_local), GFP_KERNEL);  	if (!ldata) {  		ret = -ENOMEM;  		goto out;  	}  	ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); +  	if (!ldata->base) {  		ret = -ENOMEM;  		goto out_no_remap; @@ -150,24 +383,36 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id)  	amba_set_drvdata(adev, ldata); -	if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED, -			"rtc-pl031", ldata->rtc)) { -		ret = -EIO; -		goto out_no_irq; -	} +	ldata->hw_designer = amba_manf(adev); +	ldata->hw_revision = amba_rev(adev); -	ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops, -					 THIS_MODULE); +	dev_dbg(&adev->dev, "designer ID = 0x%02x\n", ldata->hw_designer); +	dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); + +	/* Enable the clockwatch on ST Variants */ +	if ((ldata->hw_designer == AMBA_VENDOR_ST) && +	    (ldata->hw_revision > 1)) +		writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, +		       ldata->base + RTC_CR); + +	ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, +					THIS_MODULE);  	if (IS_ERR(ldata->rtc)) {  		ret = PTR_ERR(ldata->rtc);  		goto out_no_rtc;  	} +	if (request_irq(adev->irq[0], pl031_interrupt, +			IRQF_DISABLED | IRQF_SHARED, "rtc-pl031", ldata)) { +		ret = -EIO; +		goto out_no_irq; +	} +  	return 0; -out_no_rtc: -	free_irq(adev->irq[0], ldata->rtc);  out_no_irq: +	rtc_device_unregister(ldata->rtc); +out_no_rtc:  	iounmap(ldata->base);  	amba_set_drvdata(adev, NULL);  out_no_remap: @@ -175,13 +420,57 @@ out_no_remap:  out:  	amba_release_regions(adev);  err_req: +  	return ret;  } +/* Operations for the original ARM version */ +static struct rtc_class_ops arm_pl031_ops = { +	.read_time = pl031_read_time, +	.set_time = pl031_set_time, +	.read_alarm = pl031_read_alarm, +	.set_alarm = pl031_set_alarm, +	.alarm_irq_enable = pl031_alarm_irq_enable, +}; + +/* The First ST derivative */ +static struct rtc_class_ops stv1_pl031_ops = { +	.read_time = pl031_read_time, +	.set_time = pl031_set_time, +	.read_alarm = pl031_read_alarm, +	.set_alarm = pl031_set_alarm, +	.alarm_irq_enable = pl031_alarm_irq_enable, +	.irq_set_state = pl031_irq_set_state, +	.irq_set_freq = pl031_irq_set_freq, +}; + +/* And the second ST derivative */ +static struct rtc_class_ops stv2_pl031_ops = { +	.read_time = pl031_stv2_read_time, +	.set_time = pl031_stv2_set_time, +	.read_alarm = pl031_stv2_read_alarm, +	.set_alarm = pl031_stv2_set_alarm, +	.alarm_irq_enable = pl031_alarm_irq_enable, +	.irq_set_state = pl031_irq_set_state, +	.irq_set_freq = pl031_irq_set_freq, +}; +  static struct amba_id pl031_ids[] __initdata = {  	{  		.id = 0x00041031,  		.mask = 0x000fffff, +		.data = &arm_pl031_ops, +	}, +	/* ST Micro variants */ +	{ +		.id = 0x00180031, +		.mask = 0x00ffffff, +		.data = &stv1_pl031_ops, +	}, +	{ +		.id = 0x00280031, +		.mask = 0x00ffffff, +		.data = &stv2_pl031_ops,  	},  	{0, 0},  }; diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index ef7adc8135d..ce6c35333ff 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -71,6 +71,7 @@ struct uart_amba_port {  	unsigned int		im;	/* interrupt mask */  	unsigned int		old_status;  	unsigned int		ifls;	/* vendor-specific */ +	bool			autorts;  };  /* There is by now at least one vendor with differing details, so handle it */ @@ -308,6 +309,11 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)  	TIOCMBIT(TIOCM_OUT1, UART011_CR_OUT1);  	TIOCMBIT(TIOCM_OUT2, UART011_CR_OUT2);  	TIOCMBIT(TIOCM_LOOP, UART011_CR_LBE); + +	if (uap->autorts) { +		/* We need to disable auto-RTS if we want to turn RTS off */ +		TIOCMBIT(TIOCM_RTS, UART011_CR_RTSEN); +	}  #undef TIOCMBIT  	writew(cr, uap->port.membase + UART011_CR); @@ -437,6 +443,7 @@ static void pl011_shutdown(struct uart_port *port)  	/*  	 * disable the port  	 */ +	uap->autorts = false;  	writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);  	/* @@ -456,6 +463,7 @@ static void  pl011_set_termios(struct uart_port *port, struct ktermios *termios,  		     struct ktermios *old)  { +	struct uart_amba_port *uap = (struct uart_amba_port *)port;  	unsigned int lcr_h, old_cr;  	unsigned long flags;  	unsigned int baud, quot; @@ -532,6 +540,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,  	old_cr = readw(port->membase + UART011_CR);  	writew(0, port->membase + UART011_CR); +	if (termios->c_cflag & CRTSCTS) { +		if (old_cr & UART011_CR_RTS) +			old_cr |= UART011_CR_RTSEN; + +		old_cr |= UART011_CR_CTSEN; +		uap->autorts = true; +	} else { +		old_cr &= ~(UART011_CR_CTSEN | UART011_CR_RTSEN); +		uap->autorts = false; +	} +  	/* Set baud rate */  	writew(quot & 0x3f, port->membase + UART011_FBRD);  	writew(quot >> 6, port->membase + UART011_IBRD); diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index ff5bbb9c43c..9aeb6811310 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -363,6 +363,7 @@ struct pl022 {  	void				*rx_end;  	enum ssp_reading		read;  	enum ssp_writing		write; +	u32				exp_fifo_level;  };  /** @@ -501,6 +502,9 @@ static int flush(struct pl022 *pl022)  		while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)  			readw(SSP_DR(pl022->virtbase));  	} while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); + +	pl022->exp_fifo_level = 0; +  	return limit;  } @@ -583,10 +587,9 @@ static void readwriter(struct pl022 *pl022)  	 * errons in 8bit wide transfers on ARM variants (just 8 words  	 * FIFO, means only 8x8 = 64 bits in FIFO) at least.  	 * -	 * FIXME: currently we have no logic to account for this. -	 * perhaps there is even something broken in HW regarding -	 * 8bit transfers (it doesn't fail on 16bit) so this needs -	 * more investigation... +	 * To prevent this issue, the TX FIFO is only filled to the +	 * unused RX FIFO fill length, regardless of what the TX +	 * FIFO status flag indicates.  	 */  	dev_dbg(&pl022->adev->dev,  		"%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", @@ -613,11 +616,12 @@ static void readwriter(struct pl022 *pl022)  			break;  		}  		pl022->rx += (pl022->cur_chip->n_bytes); +		pl022->exp_fifo_level--;  	}  	/* -	 * Write as much as you can, while keeping an eye on the RX FIFO! +	 * Write as much as possible up to the RX FIFO size  	 */ -	while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) +	while ((pl022->exp_fifo_level < pl022->vendor->fifodepth)  	       && (pl022->tx < pl022->tx_end)) {  		switch (pl022->write) {  		case WRITING_NULL: @@ -634,6 +638,7 @@ static void readwriter(struct pl022 *pl022)  			break;  		}  		pl022->tx += (pl022->cur_chip->n_bytes); +		pl022->exp_fifo_level++;  		/*  		 * This inner reader takes care of things appearing in the RX  		 * FIFO as we're transmitting. This will happen a lot since the @@ -660,6 +665,7 @@ static void readwriter(struct pl022 *pl022)  				break;  			}  			pl022->rx += (pl022->cur_chip->n_bytes); +			pl022->exp_fifo_level--;  		}  	}  	/* diff --git a/mm/hugetlb.c b/mm/hugetlb.c index e91b81b6367..94cd94df56e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2088,7 +2088,7 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,  	entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep)));  	if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1)) { -		update_mmu_cache(vma, address, entry); +		update_mmu_cache(vma, address, ptep);  	}  } @@ -2559,7 +2559,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,  	entry = pte_mkyoung(entry);  	if (huge_ptep_set_access_flags(vma, address, ptep, entry,  						flags & FAULT_FLAG_WRITE)) -		update_mmu_cache(vma, address, entry); +		update_mmu_cache(vma, address, ptep);  out_page_table_lock:  	spin_unlock(&mm->page_table_lock); diff --git a/mm/memory.c b/mm/memory.c index 09e4b1be7b6..72fb5f39bcc 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1593,7 +1593,7 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,  	/* Ok, finally just insert the thing.. */  	entry = pte_mkspecial(pfn_pte(pfn, prot));  	set_pte_at(mm, addr, pte, entry); -	update_mmu_cache(vma, addr, entry); /* XXX: why not for insert_page? */ +	update_mmu_cache(vma, addr, pte); /* XXX: why not for insert_page? */  	retval = 0;  out_unlock: @@ -2116,7 +2116,7 @@ reuse:  		entry = pte_mkyoung(orig_pte);  		entry = maybe_mkwrite(pte_mkdirty(entry), vma);  		if (ptep_set_access_flags(vma, address, page_table, entry,1)) -			update_mmu_cache(vma, address, entry); +			update_mmu_cache(vma, address, page_table);  		ret |= VM_FAULT_WRITE;  		goto unlock;  	} @@ -2185,7 +2185,7 @@ gotten:  		 * new page to be mapped directly into the secondary page table.  		 */  		set_pte_at_notify(mm, address, page_table, entry); -		update_mmu_cache(vma, address, entry); +		update_mmu_cache(vma, address, page_table);  		if (old_page) {  			/*  			 * Only after switching the pte to the new page may @@ -2629,7 +2629,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,  	}  	/* No need to invalidate - it was non-present before */ -	update_mmu_cache(vma, address, pte); +	update_mmu_cache(vma, address, page_table);  unlock:  	pte_unmap_unlock(page_table, ptl);  out: @@ -2694,7 +2694,7 @@ setpte:  	set_pte_at(mm, address, page_table, entry);  	/* No need to invalidate - it was non-present before */ -	update_mmu_cache(vma, address, entry); +	update_mmu_cache(vma, address, page_table);  unlock:  	pte_unmap_unlock(page_table, ptl);  	return 0; @@ -2855,7 +2855,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,  		set_pte_at(mm, address, page_table, entry);  		/* no need to invalidate: a not-present page won't be cached */ -		update_mmu_cache(vma, address, entry); +		update_mmu_cache(vma, address, page_table);  	} else {  		if (charged)  			mem_cgroup_uncharge_page(page); @@ -2992,7 +2992,7 @@ static inline int handle_pte_fault(struct mm_struct *mm,  	}  	entry = pte_mkyoung(entry);  	if (ptep_set_access_flags(vma, address, pte, entry, flags & FAULT_FLAG_WRITE)) { -		update_mmu_cache(vma, address, entry); +		update_mmu_cache(vma, address, pte);  	} else {  		/*  		 * This is needed only for protection faults but the arch code diff --git a/mm/migrate.c b/mm/migrate.c index efddbf0926b..e58e5da25b9 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -134,7 +134,7 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,  		page_add_file_rmap(new);  	/* No need to invalidate - it was non-present before */ -	update_mmu_cache(vma, addr, pte); +	update_mmu_cache(vma, addr, ptep);  unlock:  	pte_unmap_unlock(ptep, ptl);  out:  |