diff options
433 files changed, 8592 insertions, 3290 deletions
diff --git a/Documentation/arm/OMAP/omap_dvfs b/Documentation/arm/OMAP/omap_dvfs new file mode 100644 index 00000000000..3ddc5a5c78d --- /dev/null +++ b/Documentation/arm/OMAP/omap_dvfs @@ -0,0 +1,111 @@ +*=============* +* DVFS Framework * +*=============* +(C) 2011 Vishwnath BS <vishwanath.bs@ti.com>, Texas Instruments Incorporated +Contents +-------- +1. Introduction +2. Data Structure Organization +3. DVFS APIs + +1. Introduction +=============== +DVFS is a technique that uses the optimal operating frequency and voltage to +allow a task to be performed in the required amount of time. +OMAP processors have voltage domains whose voltage can be scaled to +various levels depending on which the operating frequencies of certain +devices belonging to the domain will also need to be scaled. This voltage +frequency tuple is known as Operating Performance Point (OPP). A device +can have multiple OPP's. Also a voltage domain could be shared between +multiple devices. Also there could be dependencies between various +voltage domains for maintaining system performance like VDD<X> +should be at voltage v1 when VDD<Y> is at voltage v2. + +The design of this framework takes into account all the above mentioned points. +To summarize the basic design of DVFS framework:- + +1. Have device opp tables for each device whose operating frequency can be + scaled. This is easy now due to the existance of hwmod layer which + allow storing of device specific info. The device opp tables contain + the opp pairs (frequency voltage tuples), the voltage domain pointer + to which the device belongs to, the device specific set_rate and + get_rate API's which will do the actual scaling of the device frequency + and retrieve the current device frequency. +2. Introduce use counting on a per VDD basis. This is to take care multiple + requests to scale a VDD. The VDD will be scaled to the maximum of the + voltages requested. +3. Keep track of all scalable devices belonging to a particular voltage + domain the voltage layer. +4. Keep track of frequency requests for each of the device. This will enable + to scale individual devices to different frequency (even w/o scaling voltage + aka frequency throttling) +5. Generic dvfs API that can be called by anybody to scale a device opp. + This API takes the device pointer and frequency to which the device + needs to be scaled to. This API then internally finds out the voltage + domain to which the device belongs to and the voltage to which the voltage + domain needs to be put to for the device to be scaled to the new frequency + from he device opp table. Then this API will add requested frequency into + the corresponding target device frequency list and add voltage request to + the corresponding vdd. Subsequently it calls voltage scale function which + will find out the highest requested voltage for the given vdd and scales + the voltage to the required one. It also runs through the list of all + scalable devices belonging to this voltage domain and scale them to the + appropriate frequencies using the set_rate pointer in the device opp tables. +6. Handle inter VDD dependecies. + + +2. The Core DVFS data structure: +================================= + + |-------------------| |-------------------| + |User2 (dev2, freq2)| |User4 (dev4, freq4)| + |-------^-----------| |-------^-----------| + | | + |-------|-----------| |-------|-----------| + |User1 (dev1, freq1)| |User3 (dev3, freq3)|(omap_dev_user_list) + |-------^-----------| |-------^-----------| + | | + |---|--------------| |------------------| + |--------->| DEV1 (dev) |------------>| DEV2 (dev) |(omap_vdd_dev_list) + | |omap_dev_user_list| |omap_dev_user_list| + | |------------------| |------------------| + | + |---------|-----------| + | VDD_n | + | omap_vdd_dev_list | + | omap_vdd_user_list |(omap_vdd_dvfs_info) + | | + |--------|------------| + | + | |------------| |------------| |--------------| + |---------> | vdd_user1 |->| vdd_user2 |->| vdd_user3 | (omap_vdd_user_list) + | (dev, volt)| | (dev, volt)| | (dev, volt) | + |------------| |------------| |--------------| + +3. APIs: + ===== + 1. omap_device_scale - Set a new rate at which the device is to operate + + Examples: + 1. Simple Device scaling: + Suppose module M wants to put device dev1 to frequency f1. Let's say that mdev + is the device * for module M. Then this could be achieved by + ret = omap_device_scale(mdev, dev1, f1) + if (ret) + /* handle error *. + + 2. Frequency Throttling + Suppose say there are 2 modules M1 and M2 in Voltage domain VDDx. + Module M1 wants to set VDDx to OPP100 voltage which means M1 and M2 will + be running at OPP100 frequency. Suppose Module M2 wants to run at OPP50 + frequency (say f2_opp50) instead of OPP100. This can be achieved by + + /* this operation will place M1 and M2 to run at OPP100 */ + ret = omap_device_scale(mdev1, dev1, f1_opp100); + if (ret) + /* handle error *. + + /* This operation will bring M2 to run at f2_opp50 w/o decreasing VDDx voltage */ + ret = omap_device_scale(mdev2, dev2, f2_opp50); + if (ret) + /* handle error *. diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt index 737988fca64..e74d0a2eb1c 100644 --- a/Documentation/cpu-freq/governors.txt +++ b/Documentation/cpu-freq/governors.txt @@ -158,6 +158,17 @@ intensive calculation on your laptop that you do not care how long it takes to complete as you can 'nice' it and prevent it from taking part in the deciding process of whether to increase your CPU frequency. +sampling_down_factor: this parameter controls the rate at which the +kernel makes a decision on when to decrease the frequency while running +at top speed. When set to 1 (the default) decisions to reevaluate load +are made at the same interval regardless of current clock speed. But +when set to greater than 1 (e.g. 100) it acts as a multiplier for the +scheduling interval for reevaluating load when the CPU is at its top +speed due to high load. This improves performance by reducing the overhead +of load evaluation and helping the CPU stay at its top speed when truly +busy, rather than shifting back and forth in speed. This tunable has no +effect on behavior at lower speeds/lower CPU loads. + 2.5 Conservative ---------------- diff --git a/MAINTAINERS b/MAINTAINERS index 560ecce38ff..f1bc3dc6b36 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4292,10 +4292,7 @@ S: Maintained F: net/sched/sch_netem.c NETERION 10GbE DRIVERS (s2io/vxge) -M: Ramkrishna Vepa <ramkrishna.vepa@exar.com> -M: Sivakumar Subramani <sivakumar.subramani@exar.com> -M: Sreenivasa Honnur <sreenivasa.honnur@exar.com> -M: Jon Mason <jon.mason@exar.com> +M: Jon Mason <jdmason@kudzu.us> L: netdev@vger.kernel.org W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 38 -EXTRAVERSION = -rc8 +EXTRAVERSION = NAME = Flesh-Eating Bats with Fangs # *DOCUMENTATION* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 166efa2a19c..a53245a9ef5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -7,7 +7,7 @@ config ARM select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION - select GENERIC_ATOMIC64 if (!CPU_32v6K || !AEABI) + select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI) select HAVE_OPROFILE if (HAVE_PERF_EVENTS) select HAVE_ARCH_KGDB select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL) @@ -24,7 +24,7 @@ config ARM select HAVE_PERF_EVENTS select PERF_USE_VMALLOC select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7)) + select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)) select HAVE_C_RECORDMCOUNT select HAVE_GENERIC_HARDIRQS select HAVE_SPARSE_IRQ @@ -178,11 +178,6 @@ config FIQ config ARCH_MTD_XIP bool -config ARM_L1_CACHE_SHIFT_6 - bool - help - Setting ARM L1 cache line size to 64 Bytes. - config VECTORS_BASE hex default 0xffff0000 if MMU || CPU_HIGH_VECTOR @@ -191,6 +186,22 @@ config VECTORS_BASE help The base address of exception vectors. +config ARM_PATCH_PHYS_VIRT + bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on !XIP_KERNEL && MMU + depends on !ARCH_REALVIEW || !SPARSEMEM + help + Patch phys-to-virt translation functions at runtime according to + the position of the kernel in system memory. + + This can only be used with non-XIP with MMU kernels where + the base of physical memory is at a 16MB boundary. + +config ARM_PATCH_PHYS_VIRT_16BIT + def_bool y + depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM + source "init/Kconfig" source "kernel/Kconfig.freezer" @@ -457,6 +468,7 @@ config ARCH_IXP4XX config ARCH_DOVE bool "Marvell Dove" + select CPU_V6K select PCI select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS @@ -1048,7 +1060,7 @@ config XSCALE_PMU default y config CPU_HAS_PMU - depends on (CPU_V6 || CPU_V7 || XSCALE_PMU) && \ + depends on (CPU_V6 || CPU_V6K || CPU_V7 || XSCALE_PMU) && \ (!ARCH_OMAP3 || OMAP3_EMU) default y bool @@ -1064,7 +1076,7 @@ endif config ARM_ERRATA_411920 bool "ARM errata: Invalidation of the Instruction Cache operation can fail" - depends on CPU_V6 + depends on CPU_V6 || CPU_V6K help Invalidation of the Instruction Cache operation can fail. This erratum is present in 1136 (before r1p4), 1156 and 1176. @@ -1275,6 +1287,7 @@ source "kernel/time/Kconfig" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" depends on EXPERIMENTAL + depends on CPU_V6K || CPU_V7 depends on GENERIC_CLOCKEVENTS depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ @@ -1386,7 +1399,7 @@ config HZ config THUMB2_KERNEL bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)" - depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL + depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL select AEABI select ARM_ASM_UNIFIED help @@ -1396,6 +1409,37 @@ config THUMB2_KERNEL If unsure, say N. +config THUMB2_AVOID_R_ARM_THM_JUMP11 + bool "Work around buggy Thumb-2 short branch relocations in gas" + depends on THUMB2_KERNEL && MODULES + default y + help + Various binutils versions can resolve Thumb-2 branches to + locally-defined, preemptible global symbols as short-range "b.n" + branch instructions. + + This is a problem, because there's no guarantee the final + destination of the symbol, or any candidate locations for a + trampoline, are within range of the branch. For this reason, the + kernel does not support fixing up the R_ARM_THM_JUMP11 (102) + relocation in modules at all, and it makes little sense to add + support. + + The symptom is that the kernel fails with an "unsupported + relocation" error when loading some modules. + + Until fixed tools are available, passing + -fno-optimize-sibling-calls to gcc should prevent gcc generating + code which hits this problem, at the cost of a bit of extra runtime + stack usage in some cases. + + The problem is described in more detail at: + https://bugs.launchpad.net/binutils-linaro/+bug/725126 + + Only Thumb-2 kernels are affected. + + Unless you are sure your tools don't have this problem, say Y. + config ARM_ASM_UNIFIED bool @@ -1611,6 +1655,13 @@ endmenu menu "Boot options" +config USE_OF + bool "Flattened Device Tree support" + select OF + select OF_EARLY_FLATTREE + help + Include support for flattened device tree machine descriptions. + # Compressed boot loader in ROM. Yes, we really want to ask about # TEXT and BSS so we preserve their values in the config files. config ZBOOT_ROM_TEXT @@ -1877,7 +1928,7 @@ config FPE_FASTFPE config VFP bool "VFP-format floating point maths" - depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON + depends on CPU_V6 || CPU_V6K || CPU_ARM926T || CPU_V7 || CPU_FEROCEON help Say Y to include VFP support code in the kernel. This is needed if your hardware includes a VFP unit. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 6f7b29294c8..b1031504fad 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -89,6 +89,7 @@ tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale tune-$(CONFIG_CPU_FEROCEON) :=$(call cc-option,-mtune=marvell-f,-mtune=xscale) tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) +tune-$(CONFIG_CPU_V6K) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) ifeq ($(CONFIG_AEABI),y) CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork @@ -105,6 +106,10 @@ AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mau AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W) CFLAGS_THUMB2 :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) AFLAGS_THUMB2 :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb +# Work around buggy relocation from gas if requested: +ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y) +CFLAGS_MODULE +=-fno-optimize-sibling-calls +endif endif # Need -Uarm for gcc < 3.x @@ -280,7 +285,7 @@ bzImage: zImage zImage Image xipImage bootpImage uImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ -zinstall install: vmlinux +zinstall uinstall install: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ # We use MRPROPER_FILES and CLEAN_FILES now @@ -301,6 +306,7 @@ define archhelp echo ' (supply initrd image via make variable INITRD=<path>)' echo ' install - Install uncompressed kernel' echo ' zinstall - Install compressed kernel' + echo ' uinstall - Install U-Boot wrapped compressed kernel' echo ' Install using (your) ~/bin/$(INSTALLKERNEL) or' echo ' (distribution) /sbin/$(INSTALLKERNEL) or' echo ' install to $$(INSTALL_PATH) and run lilo' diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 4d26f2c52a7..9128fddf110 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -99,6 +99,10 @@ zinstall: $(obj)/zImage $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ $(obj)/zImage System.map "$(INSTALL_PATH)" +uinstall: $(obj)/uImage + $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ + $(obj)/uImage System.map "$(INSTALL_PATH)" + zi: $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ $(obj)/zImage System.map "$(INSTALL_PATH)" diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0a8f748e506..3c0c68ff6a8 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -83,9 +83,11 @@ endif EXTRA_CFLAGS := -fpic -fno-builtin EXTRA_AFLAGS := -Wa,-march=all +# Provide size of uncompressed kernel to the decompressor via a linker symbol. +LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image) # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) -LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) +LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) endif ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 7193884ed8b..84ac4d65631 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -21,7 +21,7 @@ #if defined(CONFIG_DEBUG_ICEDCC) -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) .macro loadsp, rb, tmp .endm .macro writeb, ch, rb @@ -128,14 +128,14 @@ wait: mrc p14, 0, pc, c0, c1, 0 .arm @ Always enter in ARM state start: .type start,#function - THUMB( adr r12, BSYM(1f) ) - THUMB( bx r12 ) - THUMB( .rept 6 ) - ARM( .rept 8 ) + .rept 7 mov r0, r0 .endr + ARM( mov r0, r0 ) + ARM( b 1f ) + THUMB( adr r12, BSYM(1f) ) + THUMB( bx r12 ) - b 1f .word 0x016f2818 @ Magic numbers to help the loader .word start @ absolute load/run zImage address .word _edata @ zImage end address @@ -174,9 +174,7 @@ not_angel: */ .text - adr r0, LC0 - ldmia r0, {r1, r2, r3, r5, r6, r11, ip} - ldr sp, [r0, #28] + #ifdef CONFIG_AUTO_ZRELADDR @ determine final kernel image address mov r4, pc @@ -185,35 +183,108 @@ not_angel: #else ldr r4, =zreladdr #endif - subs r0, r0, r1 @ calculate the delta offset - @ if delta is zero, we are - beq not_relocated @ running at the address we - @ were linked at. + bl cache_on + +restart: adr r0, LC0 + ldmia r0, {r1, r2, r3, r5, r6, r9, r11, r12} + ldr sp, [r0, #32] + + /* + * We might be running at a different address. We need + * to fix up various pointers. + */ + sub r0, r0, r1 @ calculate the delta offset + add r5, r5, r0 @ _start + add r6, r6, r0 @ _edata +#ifndef CONFIG_ZBOOT_ROM + /* malloc space is above the relocated stack (64k max) */ + add sp, sp, r0 + add r10, sp, #0x10000 +#else /* - * We're running at a different address. We need to fix - * up various pointers: - * r5 - zImage base address (_start) - * r6 - size of decompressed image - * r11 - GOT start - * ip - GOT end + * With ZBOOT_ROM the bss/stack is non relocatable, + * but someone could still run this code from RAM, + * in which case our reference is _edata. */ - add r5, r5, r0 + mov r10, r6 +#endif + +/* + * Check to see if we will overwrite ourselves. + * r4 = final kernel address + * r5 = start of this image + * r9 = size of decompressed image + * r10 = end of this image, including bss/stack/malloc space if non XIP + * We basically want: + * r4 >= r10 -> OK + * r4 + image length <= r5 -> OK + */ + cmp r4, r10 + bhs wont_overwrite + add r10, r4, r9 + cmp r10, r5 + bls wont_overwrite + +/* + * Relocate ourselves past the end of the decompressed kernel. + * r5 = start of this image + * r6 = _edata + * r10 = end of the decompressed kernel + * Because we always copy ahead, we need to do it from the end and go + * backward in case the source and destination overlap. + */ + /* Round up to next 256-byte boundary. */ + add r10, r10, #256 + bic r10, r10, #255 + + sub r9, r6, r5 @ size to copy + add r9, r9, #31 @ rounded up to a multiple + bic r9, r9, #31 @ ... of 32 bytes + add r6, r9, r5 + add r9, r9, r10 + +1: ldmdb r6!, {r0 - r3, r10 - r12, lr} + cmp r6, r5 + stmdb r9!, {r0 - r3, r10 - r12, lr} + bhi 1b + + /* Preserve offset to relocated code. */ + sub r6, r9, r6 + + bl cache_clean_flush + + adr r0, BSYM(restart) + add r0, r0, r6 + mov pc, r0 + +wont_overwrite: +/* + * If delta is zero, we are running at the address we were linked at. + * r0 = delta + * r2 = BSS start + * r3 = BSS end + * r4 = kernel execution address + * r7 = architecture ID + * r8 = atags pointer + * r11 = GOT start + * r12 = GOT end + * sp = stack pointer + */ + teq r0, #0 + beq not_relocated add r11, r11, r0 - add ip, ip, r0 + add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM /* * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, * we need to fix up pointers into the BSS region. - * r2 - BSS start - * r3 - BSS end - * sp - stack pointer + * Note that the stack pointer has already been fixed up. */ add r2, r2, r0 add r3, r3, r0 - add sp, sp, r0 /* * Relocate all entries in the GOT table. @@ -221,7 +292,7 @@ not_angel: 1: ldr r1, [r11, #0] @ relocate entries in the GOT add r1, r1, r0 @ table. This fixes up the str r1, [r11], #4 @ C references. - cmp r11, ip + cmp r11, r12 blo 1b #else @@ -234,7 +305,7 @@ not_angel: cmphs r3, r1 @ _end < entry addlo r1, r1, r0 @ table. This fixes up the str r1, [r11], #4 @ C references. - cmp r11, ip + cmp r11, r12 blo 1b #endif @@ -246,76 +317,24 @@ not_relocated: mov r0, #0 cmp r2, r3 blo 1b - /* - * The C runtime environment should now be setup - * sufficiently. Turn the cache on, set up some - * pointers, and start decompressing. - */ - bl cache_on - - mov r1, sp @ malloc space above stack - add r2, sp, #0x10000 @ 64k max - /* - * Check to see if we will overwrite ourselves. - * r4 = final kernel address - * r5 = start of this image - * r6 = size of decompressed image - * r2 = end of malloc space (and therefore this image) - * We basically want: - * r4 >= r2 -> OK - * r4 + image length <= r5 -> OK + * The C runtime environment should now be setup sufficiently. + * Set up some pointers, and start decompressing. + * r4 = kernel execution address + * r7 = architecture ID + * r8 = atags pointer */ - cmp r4, r2 - bhs wont_overwrite - add r0, r4, r6 - cmp r0, r5 - bls wont_overwrite - - mov r5, r2 @ decompress after malloc space - mov r0, r5 + mov r0, r4 + mov r1, sp @ malloc space above stack + add r2, sp, #0x10000 @ 64k max mov r3, r7 bl decompress_kernel - - add r0, r0, #127 + 128 @ alignment + stack - bic r0, r0, #127 @ align the kernel length -/* - * r0 = decompressed kernel length - * r1-r3 = unused - * r4 = kernel execution address - * r5 = decompressed kernel start - * r7 = architecture ID - * r8 = atags pointer - * r9-r12,r14 = corrupted - */ - add r1, r5, r0 @ end of decompressed kernel - adr r2, reloc_start - ldr r3, LC1 - add r3, r2, r3 -1: ldmia r2!, {r9 - r12, r14} @ copy relocation code - stmia r1!, {r9 - r12, r14} - ldmia r2!, {r9 - r12, r14} - stmia r1!, {r9 - r12, r14} - cmp r2, r3 - blo 1b - mov sp, r1 - add sp, sp, #128 @ relocate the stack - bl cache_clean_flush - ARM( add pc, r5, r0 ) @ call relocation code - THUMB( add r12, r5, r0 ) - THUMB( mov pc, r12 ) @ call relocation code - -/* - * We're not in danger of overwriting ourselves. Do this the simple way. - * - * r4 = kernel execution address - * r7 = architecture ID - */ -wont_overwrite: mov r0, r4 - mov r3, r7 - bl decompress_kernel - b call_kernel + bl cache_off + mov r0, #0 @ must be zero + mov r1, r7 @ restore architecture number + mov r2, r8 @ restore atags pointer + mov pc, r4 @ call kernel .align 2 .type LC0, #object @@ -323,11 +342,11 @@ LC0: .word LC0 @ r1 .word __bss_start @ r2 .word _end @ r3 .word _start @ r5 - .word _image_size @ r6 + .word _edata @ r6 + .word _image_size @ r9 .word _got_start @ r11 .word _got_end @ ip .word user_stack_end @ sp -LC1: .word reloc_end - reloc_start .size LC0, . - LC0 #ifdef CONFIG_ARCH_RPC @@ -353,7 +372,7 @@ params: ldr r0, =0x10000100 @ params_phys for RPC * On exit, * r0, r1, r2, r3, r9, r10, r12 corrupted * This routine must preserve: - * r4, r5, r6, r7, r8 + * r4, r7, r8 */ .align 5 cache_on: mov r3, #8 @ cache_on function @@ -551,43 +570,6 @@ __common_mmu_cache_on: #endif /* - * All code following this line is relocatable. It is relocated by - * the above code to the end of the decompressed kernel image and - * executed there. During this time, we have no stacks. - * - * r0 = decompressed kernel length - * r1-r3 = unused - * r4 = kernel execution address - * r5 = decompressed kernel start - * r7 = architecture ID - * r8 = atags pointer - * r9-r12,r14 = corrupted - */ - .align 5 -reloc_start: add r9, r5, r0 - sub r9, r9, #128 @ do not copy the stack - debug_reloc_start - mov r1, r4 -1: - .rept 4 - ldmia r5!, {r0, r2, r3, r10 - r12, r14} @ relocate kernel - stmia r1!, {r0, r2, r3, r10 - r12, r14} - .endr - - cmp r5, r9 - blo 1b - mov sp, r1 - add sp, sp, #128 @ relocate the stack - debug_reloc_end - -call_kernel: bl cache_clean_flush - bl cache_off - mov r0, #0 @ must be zero - mov r1, r7 @ restore architecture number - mov r2, r8 @ restore atags pointer - mov pc, r4 @ call kernel - -/* * Here follow the relocatable cache support functions for the * various processors. This is a generic hook for locating an * entry and jumping to an instruction at the specified offset @@ -791,7 +773,7 @@ proc_types: * On exit, * r0, r1, r2, r3, r9, r12 corrupted * This routine must preserve: - * r4, r6, r7 + * r4, r7, r8 */ .align 5 cache_off: mov r3, #12 @ cache_off function @@ -866,7 +848,7 @@ __armv3_mmu_cache_off: * On exit, * r1, r2, r3, r9, r10, r11, r12 corrupted * This routine must preserve: - * r0, r4, r5, r6, r7 + * r4, r6, r7, r8 */ .align 5 cache_clean_flush: @@ -1088,7 +1070,6 @@ memdump: mov r12, r0 #endif .ltorg -reloc_end: .align .section ".stack", "aw", %nobits diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index e653a6d3c8d..4657e877bf8 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -36,7 +36,7 @@ extern void error(char *x); #ifdef CONFIG_DEBUG_ICEDCC -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) static void icedcc_putc(int ch) { diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index 366a924019a..5309909d728 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -43,9 +43,6 @@ SECTIONS _etext = .; - /* Assume size of decompressed image is 4x the compressed image */ - _image_size = (_etext - _text) * 4; - _got_start = .; .got : { *(.got) } _got_end = .; diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 22437721115..e21c1f4218d 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -142,25 +142,24 @@ static int gic_set_type(struct irq_data *d, unsigned int type) } #ifdef CONFIG_SMP -static int -gic_set_cpu(struct irq_data *d, const struct cpumask *mask_val, bool force) +static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + bool force) { void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); unsigned int shift = (d->irq % 4) * 8; unsigned int cpu = cpumask_first(mask_val); - u32 val; - struct irq_desc *desc; + u32 val, mask, bit; - spin_lock(&irq_controller_lock); - desc = irq_to_desc(d->irq); - if (desc == NULL) { - spin_unlock(&irq_controller_lock); + if (cpu >= 8) return -EINVAL; - } + + mask = 0xff << shift; + bit = 1 << (cpu + shift); + + spin_lock(&irq_controller_lock); d->node = cpu; - val = readl(reg) & ~(0xff << shift); - val |= 1 << (cpu + shift); - writel(val, reg); + val = readl(reg) & ~mask; + writel(val | bit, reg); spin_unlock(&irq_controller_lock); return 0; @@ -203,7 +202,7 @@ static struct irq_chip gic_chip = { .irq_unmask = gic_unmask_irq, .irq_set_type = gic_set_type, #ifdef CONFIG_SMP - .irq_set_affinity = gic_set_cpu, + .irq_set_affinity = gic_set_affinity, #endif }; diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index ae890caa17a..ccfd51cd2bc 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -58,6 +58,7 @@ CONFIG_ARM_ERRATA_411920=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y +CONFIG_NR_CPUS=2 # CONFIG_LOCAL_TIMERS is not set CONFIG_AEABI=y CONFIG_LEDS=y @@ -291,3 +292,7 @@ CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=y CONFIG_CRC7=y CONFIG_LIBCRC32C=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_OMAP_SMARTREFLEX=y +CONFIG_OMAP_SMARTREFLEX_CLASS3=y diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 52d86c4485b..e1d602029a4 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -1,7 +1,6 @@ CONFIG_EXPERIMENTAL=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y CONFIG_MODULES=y @@ -13,43 +12,93 @@ CONFIG_UX500_SOC_DB5500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_U8500=y CONFIG_MACH_U5500=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y CONFIG_PREEMPT=y CONFIG_AEABI=y CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8" +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_VFP=y CONFIG_NEON=y +CONFIG_NET=y +CONFIG_PHONET=y +CONFIG_PHONET_PIPECTRLR=y +# CONFIG_WIRELESS is not set +CONFIG_CAIF=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 -# CONFIG_MISC_DEVICES is not set +CONFIG_MISC_DEVICES=y +CONFIG_AB8500_PWM=y +CONFIG_SENSORS_BH1780=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_NOMADIK=y +CONFIG_KEYBOARD_STMPE=y +CONFIG_KEYBOARD_TC3589X=y # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_BU21013=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AB8500_PONKEY=y # CONFIG_SERIO is not set CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y # CONFIG_LEGACY_PTYS is not set -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_NOMADIK=y +CONFIG_I2C=y +CONFIG_I2C_NOMADIK=y CONFIG_SPI=y CONFIG_SPI_PL022=y +CONFIG_GPIO_STMPE=y +CONFIG_GPIO_TC3589X=y # CONFIG_HWMON is not set -# CONFIG_VGA_CONSOLE is not set +CONFIG_MFD_STMPE=y +CONFIG_MFD_TC3589X=y +CONFIG_AB8500_CORE=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_AB8500=y # CONFIG_HID_SUPPORT is not set -# CONFIG_USB_SUPPORT is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_MUSB_PIO_ONLY=y +CONFIG_USB_GADGET=y +CONFIG_AB8500_USB=y +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_LP5521=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AB8500=y +CONFIG_RTC_DRV_PL031=y +CONFIG_DMADEVICES=y +CONFIG_STE_DMA40=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y -CONFIG_INOTIFY=y +CONFIG_EXT3_FS=y +CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_CONFIGFS_FS=m # CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_SCHED_DEBUG is not set # CONFIG_DEBUG_PREEMPT is not set @@ -58,5 +107,3 @@ CONFIG_DEBUG_INFO=y # CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y -CONFIG_CRC_T10DIF=m -# CONFIG_CRC32 is not set diff --git a/arch/arm/configs/vexpress_defconfig b/arch/arm/configs/vexpress_defconfig new file mode 100644 index 00000000000..f2de51f0bd1 --- /dev/null +++ b/arch/arm/configs/vexpress_defconfig @@ -0,0 +1,140 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CPUSETS=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_VEXPRESS=y +CONFIG_ARCH_VEXPRESS_CA9X4=y +# CONFIG_SWP_EMULATE is not set +CONFIG_SMP=y +CONFIG_VMSPLIT_2G=y +CONFIG_HOTPLUG_CPU=y +CONFIG_AEABI=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M" +CONFIG_VFP=y +CONFIG_NEON=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_INET_LRO is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_MTD=y +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_MISC_DEVICES=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +# CONFIG_SATA_PMP is not set +CONFIG_NETDEVICES=y +CONFIG_NET_ETHERNET=y +CONFIG_SMSC911X=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_AMBAKMI=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +CONFIG_FB=y +CONFIG_FB_ARMCLCD=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +# CONFIG_SND_DRIVERS is not set +CONFIG_SND_ARMAACI=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_NTRIG=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_ZEROPLUS=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_MON=y +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_PL031=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_JFFS2_FS=y +CONFIG_CRAMFS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_ROOT_NFS=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_SCHED_DEBUG is not set +CONFIG_DEBUG_INFO=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h index 7b1bb2bbaf8..af54ed102f5 100644 --- a/arch/arm/include/asm/bitops.h +++ b/arch/arm/include/asm/bitops.h @@ -149,14 +149,18 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p) */ /* + * Native endian assembly bitops. nr = 0 -> word 0 bit 0. + */ +extern void _set_bit(int nr, volatile unsigned long * p); +extern void _clear_bit(int nr, volatile unsigned long * p); +extern void _change_bit(int nr, volatile unsigned long * p); +extern int _test_and_set_bit(int nr, volatile unsigned long * p); +extern int _test_and_clear_bit(int nr, volatile unsigned long * p); +extern int _test_and_change_bit(int nr, volatile unsigned long * p); + +/* * Little endian assembly bitops. nr = 0 -> byte 0 bit 0. */ -extern void _set_bit_le(int nr, volatile unsigned long * p); -extern void _clear_bit_le(int nr, volatile unsigned long * p); -extern void _change_bit_le(int nr, volatile unsigned long * p); -extern int _test_and_set_bit_le(int nr, volatile unsigned long * p); -extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p); -extern int _test_and_change_bit_le(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_le(const void * p, unsigned size); extern int _find_next_zero_bit_le(const void * p, int size, int offset); extern int _find_first_bit_le(const unsigned long *p, unsigned size); @@ -165,12 +169,6 @@ extern int _find_next_bit_le(const unsigned long *p, int size, int offset); /* * Big endian assembly bitops. nr = 0 -> byte 3 bit 0. */ -extern void _set_bit_be(int nr, volatile unsigned long * p); -extern void _clear_bit_be(int nr, volatile unsigned long * p); -extern void _change_bit_be(int nr, volatile unsigned long * p); -extern int _test_and_set_bit_be(int nr, volatile unsigned long * p); -extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p); -extern int _test_and_change_bit_be(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_be(const void * p, unsigned size); extern int _find_next_zero_bit_be(const void * p, int size, int offset); extern int _find_first_bit_be(const unsigned long *p, unsigned size); @@ -180,33 +178,26 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); /* * The __* form of bitops are non-atomic and may be reordered. */ -#define ATOMIC_BITOP_LE(name,nr,p) \ - (__builtin_constant_p(nr) ? \ - ____atomic_##name(nr, p) : \ - _##name##_le(nr,p)) - -#define ATOMIC_BITOP_BE(name,nr,p) \ - (__builtin_constant_p(nr) ? \ - ____atomic_##name(nr, p) : \ - _##name##_be(nr,p)) +#define ATOMIC_BITOP(name,nr,p) \ + (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p)) #else -#define ATOMIC_BITOP_LE(name,nr,p) _##name##_le(nr,p) -#define ATOMIC_BITOP_BE(name,nr,p) _##name##_be(nr,p) +#define ATOMIC_BITOP(name,nr,p) _##name(nr,p) #endif -#define NONATOMIC_BITOP(name,nr,p) \ - (____nonatomic_##name(nr, p)) +/* + * Native endian atomic definitions. + */ +#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p) +#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p) +#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p) +#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p) +#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p) +#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p) #ifndef __ARMEB__ /* * These are the little endian, atomic definitions. */ -#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p) -#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p) -#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p) -#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p) -#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p) -#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off) #define find_first_bit(p,sz) _find_first_bit_le(p,sz) @@ -215,16 +206,9 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); #define WORD_BITOFF_TO_LE(x) ((x)) #else - /* * These are the big endian, atomic definitions. */ -#define set_bit(nr,p) ATOMIC_BITOP_BE(set_bit,nr,p) -#define clear_bit(nr,p) ATOMIC_BITOP_BE(clear_bit,nr,p) -#define change_bit(nr,p) ATOMIC_BITOP_BE(change_bit,nr,p) -#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p) -#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p) -#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off) #define find_first_bit(p,sz) _find_first_bit_be(p,sz) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 3acd8fa25e3..d9b4c42d62f 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -116,20 +116,20 @@ # define MULTI_CACHE 1 #endif -#if defined(CONFIG_CPU_V6) -//# ifdef _CACHE +#if defined(CONFIG_CPU_CACHE_V6) +# ifdef _CACHE # define MULTI_CACHE 1 -//# else -//# define _CACHE v6 -//# endif +# else +# define _CACHE v6 +# endif #endif -#if defined(CONFIG_CPU_V7) -//# ifdef _CACHE +#if defined(CONFIG_CPU_CACHE_V7) +# ifdef _CACHE # define MULTI_CACHE 1 -//# else -//# define _CACHE v7 -//# endif +# else +# define _CACHE v7 +# endif #endif #if !defined(_CACHE) && !defined(MULTI_CACHE) @@ -316,7 +316,8 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, * Optimized __flush_icache_all for the common cases. Note that UP ARMv7 * will fall through to use __flush_icache_all_generic. */ -#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) || \ +#if (defined(CONFIG_CPU_V7) && \ + (defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K))) || \ defined(CONFIG_SMP_ON_UP) #define __flush_icache_preferred __cpuc_flush_icache_all #elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index 20ae96cc002..ed5bc9e05a4 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -23,6 +23,8 @@ #define CPUID_EXT_ISAR4 "c2, 4" #define CPUID_EXT_ISAR5 "c2, 5" +extern unsigned int processor_id; + #ifdef CONFIG_CPU_CP15 #define read_cpuid(reg) \ ({ \ @@ -43,7 +45,6 @@ __val; \ }) #else -extern unsigned int processor_id; #define read_cpuid(reg) (processor_id) #define read_cpuid_ext(reg) 0 #endif diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h new file mode 100644 index 00000000000..de535474692 --- /dev/null +++ b/arch/arm/include/asm/fncpy.h @@ -0,0 +1,94 @@ +/* + * arch/arm/include/asm/fncpy.h - helper macros for function body copying + * + * Copyright (C) 2011 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This 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 + */ + +/* + * These macros are intended for use when there is a need to copy a low-level + * function body into special memory. + * + * For example, when reconfiguring the SDRAM controller, the code doing the + * reconfiguration may need to run from SRAM. + * + * NOTE: that the copied function body must be entirely self-contained and + * position-independent in order for this to work properly. + * + * NOTE: in order for embedded literals and data to get referenced correctly, + * the alignment of functions must be preserved when copying. To ensure this, + * the source and destination addresses for fncpy() must be aligned to a + * multiple of 8 bytes: you will be get a BUG() if this condition is not met. + * You will typically need a ".align 3" directive in the assembler where the + * function to be copied is defined, and ensure that your allocator for the + * destination buffer returns 8-byte-aligned pointers. + * + * Typical usage example: + * + * extern int f(args); + * extern uint32_t size_of_f; + * int (*copied_f)(args); + * void *sram_buffer; + * + * copied_f = fncpy(sram_buffer, &f, size_of_f); + * + * ... later, call the function: ... + * + * copied_f(args); + * + * The size of the function to be copied can't be determined from C: + * this must be determined by other means, such as adding assmbler directives + * in the file where f is defined. + */ + +#ifndef __ASM_FNCPY_H +#define __ASM_FNCPY_H + +#include <linux/types.h> +#include <linux/string.h> + +#include <asm/bug.h> +#include <asm/cacheflush.h> + +/* + * Minimum alignment requirement for the source and destination addresses + * for function copying. + */ +#define FNCPY_ALIGN 8 + +#define fncpy(dest_buf, funcp, size) ({ \ + uintptr_t __funcp_address; \ + typeof(funcp) __result; \ + \ + asm("" : "=r" (__funcp_address) : "0" (funcp)); \ + \ + /* \ + * Ensure alignment of source and destination addresses, \ + * disregarding the function's Thumb bit: \ + */ \ + BUG_ON((uintptr_t)(dest_buf) & (FNCPY_ALIGN - 1) || \ + (__funcp_address & ~(uintptr_t)1 & (FNCPY_ALIGN - 1))); \ + \ + memcpy(dest_buf, (void const *)(__funcp_address & ~1), size); \ + flush_icache_range((unsigned long)(dest_buf), \ + (unsigned long)(dest_buf) + (size)); \ + \ + asm("" : "=r" (__result) \ + : "0" ((uintptr_t)(dest_buf) | (__funcp_address & 1))); \ + \ + __result; \ +}) + +#endif /* !__ASM_FNCPY_H */ diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 7080e2c8fa6..a4edd19dd3d 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -19,11 +19,36 @@ extern pte_t *pkmap_page_table; +extern void *kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +/* + * The reason for kmap_high_get() is to ensure that the currently kmap'd + * page usage count does not decrease to zero while we're using its + * existing virtual mapping in an atomic context. With a VIVT cache this + * is essential to do, but with a VIPT cache this is only an optimization + * so not to pay the price of establishing a second mapping if an existing + * one can be used. However, on platforms without hardware TLB maintenance + * broadcast, we simply cannot use ARCH_NEEDS_KMAP_HIGH_GET at all since + * the locking involved must also disable IRQs which is incompatible with + * the IPI mechanism used by global TLB operations. + */ #define ARCH_NEEDS_KMAP_HIGH_GET +#if defined(CONFIG_SMP) && defined(CONFIG_CPU_TLB_V6) +#undef ARCH_NEEDS_KMAP_HIGH_GET +#if defined(CONFIG_HIGHMEM) && defined(CONFIG_CPU_CACHE_VIVT) +#error "The sum of features in your kernel config cannot be supported together" +#endif +#endif -extern void *kmap_high(struct page *page); +#ifdef ARCH_NEEDS_KMAP_HIGH_GET extern void *kmap_high_get(struct page *page); -extern void kunmap_high(struct page *page); +#else +static inline void *kmap_high_get(struct page *page) +{ + return NULL; +} +#endif /* * The following functions are already defined by <linux/highmem.h> diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index bf13b814c1b..946f4d778f7 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -18,6 +18,8 @@ struct machine_desc { unsigned int nr; /* architecture number */ const char *name; /* architecture name */ unsigned long boot_params; /* tagged list */ + const char **dt_compat; /* array of device tree + * 'compatible' strings */ unsigned int nr_irqs; /* number of IRQs */ @@ -48,6 +50,13 @@ struct machine_desc { extern struct machine_desc *machine_desc; /* + * Machine type table - also only accessible during boot + */ +extern struct machine_desc __arch_info_begin[], __arch_info_end[]; +#define for_each_machine_desc(p) \ + for (p = __arch_info_begin; p < __arch_info_end; p++) + +/* * Set of macros to define architecture features. This is built into * a table by the linker. */ diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index d0ee74b7cf8..431077c5a86 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -15,6 +15,7 @@ #include <linux/compiler.h> #include <linux/const.h> +#include <linux/types.h> #include <mach/memory.h> #include <asm/sizes.h> @@ -133,20 +134,10 @@ #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. - */ -#ifndef __virt_to_phys -#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) -#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) -#endif - -/* * Convert a physical address to a Page Frame Number and back */ -#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT) -#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) +#define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT)) +#define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) /* * Convert a page to/from a physical address @@ -157,6 +148,62 @@ #ifndef __ASSEMBLY__ /* + * 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. + */ +#ifndef __virt_to_phys +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + +/* + * Constants used to force the right instruction encodings and shifts + * so that all we need to do is modify the 8-bit constant field. + */ +#define __PV_BITS_31_24 0x81000000 +#define __PV_BITS_23_16 0x00810000 + +extern unsigned long __pv_phys_offset; +#define PHYS_OFFSET __pv_phys_offset + +#define __pv_stub(from,to,instr,type) \ + __asm__("@ __pv_stub\n" \ + "1: " instr " %0, %1, %2\n" \ + " .pushsection .pv_table,\"a\"\n" \ + " .long 1b\n" \ + " .popsection\n" \ + : "=r" (to) \ + : "r" (from), "I" (type)) + +static inline unsigned long __virt_to_phys(unsigned long x) +{ + unsigned long t; + __pv_stub(x, t, "add", __PV_BITS_31_24); +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + __pv_stub(t, t, "add", __PV_BITS_23_16); +#endif + return t; +} + +static inline unsigned long __phys_to_virt(unsigned long x) +{ + unsigned long t; + __pv_stub(x, t, "sub", __PV_BITS_31_24); +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + __pv_stub(t, t, "sub", __PV_BITS_23_16); +#endif + return t; +} +#else +#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) +#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) +#endif +#endif + +#ifndef PHYS_OFFSET +#define PHYS_OFFSET PLAT_PHYS_OFFSET +#endif + +/* * The DMA mask corresponding to the maximum bus address allocatable * using GFP_DMA. The default here places no restriction on DMA * allocations. This must be the smallest DMA mask in the system, @@ -188,12 +235,12 @@ * translation for translating DMA addresses. Use the driver * DMA support - see dma-mapping.h. */ -static inline unsigned long virt_to_phys(const volatile void *x) +static inline phys_addr_t virt_to_phys(const volatile void *x) { return __virt_to_phys((unsigned long)(x)); } -static inline void *phys_to_virt(unsigned long x) +static inline void *phys_to_virt(phys_addr_t x) { return (void *)(__phys_to_virt((unsigned long)(x))); } diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 12c8e680cbf..543b44916d2 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -25,8 +25,31 @@ struct mod_arch_specific { }; /* - * Include the ARM architecture version. + * Add the ARM architecture version to the version magic string */ -#define MODULE_ARCH_VERMAGIC "ARMv" __stringify(__LINUX_ARM_ARCH__) " " +#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " " + +/* Add __virt_to_phys patching state as well */ +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT +#define MODULE_ARCH_VERMAGIC_P2V "p2v16 " +#else +#define MODULE_ARCH_VERMAGIC_P2V "p2v8 " +#endif +#else +#define MODULE_ARCH_VERMAGIC_P2V "" +#endif + +/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */ +#ifdef CONFIG_THUMB2_KERNEL +#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 " +#else +#define MODULE_ARCH_VERMAGIC_ARMTHUMB "" +#endif + +#define MODULE_ARCH_VERMAGIC \ + MODULE_ARCH_VERMAGIC_ARMVSN \ + MODULE_ARCH_VERMAGIC_ARMTHUMB \ + MODULE_ARCH_VERMAGIC_P2V #endif /* _ASM_ARM_MODULE_H */ diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 8ccea012722..7544ce6b481 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -12,11 +12,25 @@ #ifndef __ARM_PMU_H__ #define __ARM_PMU_H__ +#include <linux/interrupt.h> + enum arm_pmu_type { ARM_PMU_DEVICE_CPU = 0, ARM_NUM_PMU_DEVICES, }; +/* + * struct arm_pmu_platdata - ARM PMU platform data + * + * @handle_irq: an optional handler which will be called from the interrupt and + * passed the address of the low level handler, and can be used to implement + * any platform specific handling before or after calling it. + */ +struct arm_pmu_platdata { + irqreturn_t (*handle_irq)(int irq, void *dev, + irq_handler_t pmu_handler); +}; + #ifdef CONFIG_CPU_HAS_PMU /** diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 8fdae9bc9ab..296ca47489f 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -231,7 +231,7 @@ # endif #endif -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) # ifdef CPU_NAME # undef MULTI_CPU # define MULTI_CPU diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 67357baaeee..b439b41aeac 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h @@ -29,19 +29,7 @@ #define STACK_TOP_MAX TASK_SIZE #endif -union debug_insn { - u32 arm; - u16 thumb; -}; - -struct debug_entry { - u32 address; - union debug_insn insn; -}; - struct debug_info { - int nsaved; - struct debug_entry bp[2]; #ifdef CONFIG_HAVE_HW_BREAKPOINT struct perf_event *hbp[ARM_MAX_HBP_SLOTS]; #endif diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h new file mode 100644 index 00000000000..11b8708fc4d --- /dev/null +++ b/arch/arm/include/asm/prom.h @@ -0,0 +1,37 @@ +/* + * arch/arm/include/asm/prom.h + * + * Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.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. + * + */ +#ifndef __ASMARM_PROM_H +#define __ASMARM_PROM_H + +#ifdef CONFIG_OF + +#include <asm/setup.h> +#include <asm/irq.h> + +static inline void irq_dispose_mapping(unsigned int virq) +{ + return; +} + +extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys); +extern void arm_dt_memblock_reserve(void); + +#else /* CONFIG_OF */ + +static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys) +{ + return NULL; +} + +static inline void arm_dt_memblock_reserve(void) { } + +#endif /* CONFIG_OF */ +#endif /* ASMARM_PROM_H */ diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 783d50f3261..a8ff22b2a39 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -130,8 +130,6 @@ struct pt_regs { #ifdef __KERNEL__ -#define arch_has_single_step() (1) - #define user_mode(regs) \ (((regs)->ARM_cpsr & 0xf) == 0) diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index f1e5a9bca24..207f911a173 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -221,6 +221,11 @@ extern struct meminfo meminfo; #define bank_phys_end(bank) ((bank)->start + (bank)->size) #define bank_phys_size(bank) (bank)->size +extern int arm_add_memory(unsigned long start, unsigned long size); +extern char cmd_line[COMMAND_LINE_SIZE]; +extern void early_print(const char *str, ...); +extern void dump_machine_table(void); + #endif /* __KERNEL__ */ #endif diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h index 17eb355707d..fdd3820edff 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -5,17 +5,52 @@ #error SMP not supported on pre-ARMv6 CPUs #endif +/* + * sev and wfe are ARMv6K extensions. Uniprocessor ARMv6 may not have the K + * extensions, so when running on UP, we have to patch these instructions away. + */ +#define ALT_SMP(smp, up) \ + "9998: " smp "\n" \ + " .pushsection \".alt.smp.init\", \"a\"\n" \ + " .long 9998b\n" \ + " " up "\n" \ + " .popsection\n" + +#ifdef CONFIG_THUMB2_KERNEL +#define SEV ALT_SMP("sev.w", "nop.w") +/* + * For Thumb-2, special care is needed to ensure that the conditional WFE + * instruction really does assemble to exactly 4 bytes (as required by + * the SMP_ON_UP fixup code). By itself "wfene" might cause the + * assembler to insert a extra (16-bit) IT instruction, depending on the + * presence or absence of neighbouring conditional instructions. + * + * To avoid this unpredictableness, an approprite IT is inserted explicitly: + * the assembler won't change IT instructions which are explicitly present + * in the input. + */ +#define WFE(cond) ALT_SMP( \ + "it " cond "\n\t" \ + "wfe" cond ".n", \ + \ + "nop.w" \ +) +#else +#define SEV ALT_SMP("sev", "nop") +#define WFE(cond) ALT_SMP("wfe" cond, "nop") +#endif + static inline void dsb_sev(void) { #if __LINUX_ARM_ARCH__ >= 7 __asm__ __volatile__ ( "dsb\n" - "sev" + SEV ); -#elif defined(CONFIG_CPU_32v6K) +#else __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c10, 4\n" - "sev" + SEV : : "r" (0) ); #endif @@ -46,9 +81,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) __asm__ __volatile__( "1: ldrex %0, [%1]\n" " teq %0, #0\n" -#ifdef CONFIG_CPU_32v6K -" wfene\n" -#endif + WFE("ne") " strexeq %0, %2, [%1]\n" " teqeq %0, #0\n" " bne 1b" @@ -107,9 +140,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw) __asm__ __volatile__( "1: ldrex %0, [%1]\n" " teq %0, #0\n" -#ifdef CONFIG_CPU_32v6K -" wfene\n" -#endif + WFE("ne") " strexeq %0, %2, [%1]\n" " teq %0, #0\n" " bne 1b" @@ -176,9 +207,7 @@ static inline void arch_read_lock(arch_rwlock_t *rw) "1: ldrex %0, [%2]\n" " adds %0, %0, #1\n" " strexpl %1, %0, [%2]\n" -#ifdef CONFIG_CPU_32v6K -" wfemi\n" -#endif + WFE("mi") " rsbpls %0, %1, #0\n" " bmi 1b" : "=&r" (tmp), "=&r" (tmp2) diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 97f6d60297d..9a87823642d 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -347,6 +347,7 @@ void cpu_idle_wait(void); #include <asm-generic/cmpxchg-local.h> #if __LINUX_ARM_ARCH__ < 6 +/* min ARCH < ARMv6 */ #ifdef CONFIG_SMP #error "SMP is not supported on this platform" @@ -365,7 +366,7 @@ void cpu_idle_wait(void); #include <asm-generic/cmpxchg.h> #endif -#else /* __LINUX_ARM_ARCH__ >= 6 */ +#else /* min ARCH >= ARMv6 */ extern void __bad_cmpxchg(volatile void *ptr, int size); @@ -379,7 +380,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long oldval, res; switch (size) { -#ifdef CONFIG_CPU_32v6K +#ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */ case 1: do { asm volatile("@ __cmpxchg1\n" @@ -404,7 +405,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, : "memory", "cc"); } while (res); break; -#endif /* CONFIG_CPU_32v6K */ +#endif case 4: do { asm volatile("@ __cmpxchg4\n" @@ -450,12 +451,12 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, unsigned long ret; switch (size) { -#ifndef CONFIG_CPU_32v6K +#ifdef CONFIG_CPU_V6 /* min ARCH == ARMv6 */ case 1: case 2: ret = __cmpxchg_local_generic(ptr, old, new, size); break; -#endif /* !CONFIG_CPU_32v6K */ +#endif default: ret = __cmpxchg(ptr, old, new, size); } @@ -469,7 +470,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, (unsigned long)(n), \ sizeof(*(ptr)))) -#ifdef CONFIG_CPU_32v6K +#ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */ /* * Note : ARMv7-M (currently unsupported by Linux) does not support @@ -524,11 +525,11 @@ static inline unsigned long long __cmpxchg64_mb(volatile void *ptr, (unsigned long long)(o), \ (unsigned long long)(n))) -#else /* !CONFIG_CPU_32v6K */ +#else /* min ARCH = ARMv6 */ #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) -#endif /* CONFIG_CPU_32v6K */ +#endif #endif /* __LINUX_ARM_ARCH__ >= 6 */ diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h index e71d6ff8d10..60843eb0f61 100644 --- a/arch/arm/include/asm/tls.h +++ b/arch/arm/include/asm/tls.h @@ -28,15 +28,14 @@ #define tls_emu 1 #define has_tls_reg 1 #define set_tls set_tls_none -#elif __LINUX_ARM_ARCH__ >= 7 || \ - (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K)) -#define tls_emu 0 -#define has_tls_reg 1 -#define set_tls set_tls_v6k -#elif __LINUX_ARM_ARCH__ == 6 +#elif defined(CONFIG_CPU_V6) #define tls_emu 0 #define has_tls_reg (elf_hwcap & HWCAP_TLS) #define set_tls set_tls_v6 +#elif defined(CONFIG_CPU_32v6K) +#define tls_emu 0 +#define has_tls_reg 1 +#define set_tls set_tls_v6k #else #define tls_emu 0 #define has_tls_reg 0 diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index 1b960d5ef6a..f90756dc16d 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h @@ -45,6 +45,7 @@ static inline int in_exception_text(unsigned long ptr) extern void __init early_trap_init(void); extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); +extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs); extern void *vectors_page; diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 185ee822c93..8df05fd4c91 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o +obj-$(CONFIG_OF) += devtree.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o CFLAGS_swp_emulate.o := -Wa,-march=armv7-a diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index e5e1e538767..acca35aebe2 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -140,24 +140,18 @@ EXPORT_SYMBOL(__aeabi_ulcmp); #endif /* bitops */ -EXPORT_SYMBOL(_set_bit_le); -EXPORT_SYMBOL(_test_and_set_bit_le); -EXPORT_SYMBOL(_clear_bit_le); -EXPORT_SYMBOL(_test_and_clear_bit_le); -EXPORT_SYMBOL(_change_bit_le); -EXPORT_SYMBOL(_test_and_change_bit_le); +EXPORT_SYMBOL(_set_bit); +EXPORT_SYMBOL(_test_and_set_bit); +EXPORT_SYMBOL(_clear_bit); +EXPORT_SYMBOL(_test_and_clear_bit); +EXPORT_SYMBOL(_change_bit); +EXPORT_SYMBOL(_test_and_change_bit); EXPORT_SYMBOL(_find_first_zero_bit_le); EXPORT_SYMBOL(_find_next_zero_bit_le); EXPORT_SYMBOL(_find_first_bit_le); EXPORT_SYMBOL(_find_next_bit_le); #ifdef __ARMEB__ -EXPORT_SYMBOL(_set_bit_be); -EXPORT_SYMBOL(_test_and_set_bit_be); -EXPORT_SYMBOL(_clear_bit_be); -EXPORT_SYMBOL(_test_and_clear_bit_be); -EXPORT_SYMBOL(_change_bit_be); -EXPORT_SYMBOL(_test_and_change_bit_be); EXPORT_SYMBOL(_find_first_zero_bit_be); EXPORT_SYMBOL(_find_next_zero_bit_be); EXPORT_SYMBOL(_find_first_bit_be); @@ -170,3 +164,7 @@ EXPORT_SYMBOL(mcount); #endif EXPORT_SYMBOL(__gnu_mcount_nc); #endif + +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT +EXPORT_SYMBOL(__pv_phys_offset); +#endif diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index c6273a3bfc2..d86fcd44b22 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -583,6 +583,11 @@ void __init pci_common_init(struct hw_pci *hw) * Assign resources. */ pci_bus_assign_resources(bus); + + /* + * Enable bridges + */ + pci_enable_bridges(bus); } /* diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index a0f07521ca8..d2d983be096 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -25,7 +25,7 @@ .macro addruart, rp, rv .endm -#if defined(CONFIG_CPU_V6) +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) .macro senduart, rd, rx mcr p14, 0, \rd, c0, c5, 0 diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c new file mode 100644 index 00000000000..4dd725acba6 --- /dev/null +++ b/arch/arm/kernel/devtree.c @@ -0,0 +1,147 @@ +/* + * linux/arch/arm/kernel/devtree.c + * + * Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.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. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/bootmem.h> +#include <linux/memblock.h> +#include <linux/of.h> +#include <linux/of_fdt.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> + +#include <asm/setup.h> +#include <asm/page.h> +#include <asm/mach/arch.h> +#include <asm/mach-types.h> + +void __init early_init_dt_add_memory_arch(u64 base, u64 size) +{ + arm_add_memory(base, size); +} + +void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) +{ + return alloc_bootmem_align(size, align); +} + +void __init arm_dt_memblock_reserve(void) +{ + u64 *reserve_map, base, size; + + if (!initial_boot_params) + return; + + /* Reserve the dtb region */ + memblock_reserve(virt_to_phys(initial_boot_params), + be32_to_cpu(initial_boot_params->totalsize)); + + /* + * Process the reserve map. This will probably overlap the initrd + * and dtb locations which are already reserved, but overlaping + * doesn't hurt anything + */ + reserve_map = ((void*)initial_boot_params) + + be32_to_cpu(initial_boot_params->off_mem_rsvmap); + while (1) { + base = be64_to_cpup(reserve_map++); + size = be64_to_cpup(reserve_map++); + if (!size) + break; + memblock_reserve(base, size); + } +} + +/** + * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq# + * + * Currently the mapping mechanism is trivial; simple flat hwirq numbers are + * mapped 1:1 onto Linux irq numbers. Cascaded irq controllers are not + * supported. + */ +unsigned int irq_create_of_mapping(struct device_node *controller, + const u32 *intspec, unsigned int intsize) +{ + return intspec[0]; +} +EXPORT_SYMBOL_GPL(irq_create_of_mapping); + +/** + * setup_machine_fdt - Machine setup when an dtb was passed to the kernel + * @dt_phys: physical address of dt blob + * + * If a dtb was passed to the kernel in r2, then use it to choose the + * correct machine_desc and to setup the system. + */ +struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) +{ + struct boot_param_header *devtree; + struct machine_desc *mdesc, *mdesc_best = NULL; + unsigned int score, mdesc_score = ~1; + unsigned long dt_root; + const char *model; + + devtree = phys_to_virt(dt_phys); + + /* check device tree validity */ + if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) + return NULL; + + /* Search the mdescs for the 'best' compatible value match */ + initial_boot_params = devtree; + dt_root = of_get_flat_dt_root(); + for_each_machine_desc(mdesc) { + score = of_flat_dt_match(dt_root, mdesc->dt_compat); + if (score > 0 && score < mdesc_score) { + mdesc_best = mdesc; + mdesc_score = score; + } + } + if (!mdesc_best) { + const char *prop; + long size; + + early_print("\nError: unrecognized/unsupported " + "device tree compatible list:\n[ "); + + prop = of_get_flat_dt_prop(dt_root, "compatible", &size); + while (size > 0) { + early_print("'%s' ", prop); + size -= strlen(prop) + 1; + prop += strlen(prop) + 1; + } + early_print("]\n\n"); + + dump_machine_table(); /* does not return */ + } + + model = of_get_flat_dt_prop(dt_root, "model", NULL); + if (!model) + model = of_get_flat_dt_prop(dt_root, "compatible", NULL); + if (!model) + model = "<unknown>"; + pr_info("Machine: %s, model: %s\n", mdesc_best->name, model); + + /* Retrieve various information from the /chosen node */ + of_scan_flat_dt(early_init_dt_scan_chosen, NULL); + /* Initialize {size,address}-cells info */ + of_scan_flat_dt(early_init_dt_scan_root, NULL); + /* Setup memory, calling early_init_dt_add_memory_arch */ + of_scan_flat_dt(early_init_dt_scan_memory, NULL); + /* Save command line for /proc/cmdline */ + strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); + + /* Change machine number to match the mdesc we're using */ + __machine_arch_type = mdesc->nr; + + return mdesc_best; +} diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index ae946490016..051166c2a93 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -76,13 +76,13 @@ #ifndef CONFIG_THUMB2_KERNEL .macro svc_exit, rpsr msr spsr_cxsf, \rpsr -#if defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr -#elif defined (CONFIG_CPU_V6) +#if defined(CONFIG_CPU_V6) ldr r0, [sp] strex r1, r2, [sp] @ clear the exclusive monitor ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr +#elif defined(CONFIG_CPU_32v6K) + clrex @ clear the exclusive monitor + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr #else ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr #endif @@ -92,10 +92,10 @@ ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr ldr lr, [sp, #\offset + S_PC]! @ get pc msr spsr_cxsf, r1 @ save in spsr_svc -#if defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor -#elif defined (CONFIG_CPU_V6) +#if defined(CONFIG_CPU_V6) strex r1, r2, [sp] @ clear the exclusive monitor +#elif defined(CONFIG_CPU_32v6K) + clrex @ clear the exclusive monitor #endif .if \fast ldmdb sp, {r1 - lr}^ @ get calling r1 - lr diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 11db62806a1..052b509e2d5 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -338,7 +338,7 @@ static struct miscdevice etb_miscdev = { .fops = &etb_fops, }; -static int __init etb_probe(struct amba_device *dev, struct amba_id *id) +static int __init etb_probe(struct amba_device *dev, const struct amba_id *id) { struct tracectx *t = &tracer; int ret = 0; @@ -530,7 +530,7 @@ static ssize_t trace_mode_store(struct kobject *kobj, static struct kobj_attribute trace_mode_attr = __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store); -static int __init etm_probe(struct amba_device *dev, struct amba_id *id) +static int __init etm_probe(struct amba_device *dev, const struct amba_id *id) { struct tracectx *t = &tracer; int ret = 0; diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 8f57515bbdb..854bd22380d 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -15,6 +15,12 @@ #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) +#ifdef CONFIG_CPU_BIG_ENDIAN +#define OF_DT_MAGIC 0xd00dfeed +#else +#define OF_DT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */ +#endif + /* * Exception handling. Something went wrong and we can't proceed. We * ought to tell the user, but since we don't have any guarantee that @@ -25,102 +31,29 @@ * machine ID for example). */ __HEAD -__error_a: -#ifdef CONFIG_DEBUG_LL - mov r4, r1 @ preserve machine ID - adr r0, str_a1 - bl printascii - mov r0, r4 - bl printhex8 - adr r0, str_a2 - bl printascii - adr r3, __lookup_machine_type_data - ldmia r3, {r4, r5, r6} @ get machine desc list - sub r4, r3, r4 @ get offset between virt&phys - add r5, r5, r4 @ convert virt addresses to - add r6, r6, r4 @ physical address space -1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type - bl printhex8 - mov r0, #'\t' - bl printch - ldr r0, [r5, #MACHINFO_NAME] @ get machine name - add r0, r0, r4 - bl printascii - mov r0, #'\n' - bl printch - add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc - cmp r5, r6 - blo 1b - adr r0, str_a3 - bl printascii - b __error -ENDPROC(__error_a) - -str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x" -str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n" -str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n" - .align -#else - b __error -#endif - -/* - * Lookup machine architecture in the linker-build list of architectures. - * Note that we can't use the absolute addresses for the __arch_info - * lists since we aren't running with the MMU on (and therefore, we are - * not in the correct address space). We have to calculate the offset. - * - * r1 = machine architecture number - * Returns: - * r3, r4, r6 corrupted - * r5 = mach_info pointer in physical address space - */ -__lookup_machine_type: - adr r3, __lookup_machine_type_data - ldmia r3, {r4, r5, r6} - sub r3, r3, r4 @ get offset between virt&phys - add r5, r5, r3 @ convert virt addresses to - add r6, r6, r3 @ physical address space -1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type - teq r3, r1 @ matches loader number? - beq 2f @ found - add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc - cmp r5, r6 - blo 1b - mov r5, #0 @ unknown machine -2: mov pc, lr -ENDPROC(__lookup_machine_type) - -/* - * Look in arch/arm/kernel/arch.[ch] for information about the - * __arch_info structures. - */ - .align 2 - .type __lookup_machine_type_data, %object -__lookup_machine_type_data: - .long . - .long __arch_info_begin - .long __arch_info_end - .size __lookup_machine_type_data, . - __lookup_machine_type_data /* Determine validity of the r2 atags pointer. The heuristic requires * that the pointer be aligned, in the first 16k of physical RAM and - * that the ATAG_CORE marker is first and present. Future revisions + * that the ATAG_CORE marker is first and present. If CONFIG_OF_FLATTREE + * is selected, then it will also accept a dtb pointer. Future revisions * of this function may be more lenient with the physical address and * may also be able to move the ATAGS block if necessary. * - * r8 = machinfo - * * Returns: - * r2 either valid atags pointer, or zero + * r2 either valid atags pointer, valid dtb pointer, or zero * r5, r6 corrupted */ __vet_atags: tst r2, #0x3 @ aligned? bne 1f - ldr r5, [r2, #0] @ is first tag ATAG_CORE? - cmp r5, #ATAG_CORE_SIZE + ldr r5, [r2, #0] +#ifdef CONFIG_OF_FLATTREE + ldr r6, =OF_DT_MAGIC @ is it a DTB? + cmp r5, r6 + beq 2f +#endif + cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE? cmpne r5, #ATAG_CORE_SIZE_EMPTY bne 1f ldr r5, [r2, #4] @@ -128,7 +61,7 @@ __vet_atags: cmp r5, r6 bne 1f - mov pc, lr @ atag pointer is ok +2: mov pc, lr @ atag/dtb pointer is ok 1: mov r2, #0 mov pc, lr @@ -140,7 +73,7 @@ ENDPROC(__vet_atags) * * r0 = cp#15 control register * r1 = machine ID - * r2 = atags pointer + * r2 = atags/dtb pointer * r9 = processor ID */ __INIT @@ -185,17 +118,6 @@ __mmap_switched_data: .size __mmap_switched_data, . - __mmap_switched_data /* - * This provides a C-API version of __lookup_machine_type - */ -ENTRY(lookup_machine_type) - stmfd sp!, {r4 - r6, lr} - mov r1, r0 - bl __lookup_machine_type - mov r0, r5 - ldmfd sp!, {r4 - r6, pc} -ENDPROC(lookup_machine_type) - -/* * This provides a C-API version of __lookup_processor_type */ ENTRY(lookup_processor_type) diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 814ce1a7327..6b1e0ad9ec3 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -44,9 +44,6 @@ ENTRY(stext) bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)? beq __error_p @ yes, error 'p' - bl __lookup_machine_type @ r5=machinfo - movs r8, r5 @ invalid machine (r5=0)? - beq __error_a @ yes, error 'a' adr lr, BSYM(__after_proc_init) @ return (PIC) address ARM( add pc, r10, #PROCINFO_INITFUNC ) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index f06ff9feb0d..a5e5c5b9b48 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -26,14 +26,6 @@ #include <mach/debug-macro.S> #endif -#if (PHYS_OFFSET & 0x001fffff) -#error "PHYS_OFFSET must be at an even 2MiB boundary!" -#endif - -#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) -#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) - - /* * swapper_pg_dir is the virtual address of the initial page table. * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must @@ -41,6 +33,7 @@ * the least significant 16 bits to be 0x8000, but we could probably * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. */ +#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) #if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 #error KERNEL_RAM_VADDR must start at 0xXXXX8000 #endif @@ -48,8 +41,8 @@ .globl swapper_pg_dir .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 - .macro pgtbl, rd - ldr \rd, =(KERNEL_RAM_PADDR - 0x4000) + .macro pgtbl, rd, phys + add \rd, \phys, #TEXT_OFFSET - 0x4000 .endm #ifdef CONFIG_XIP_KERNEL @@ -66,7 +59,7 @@ * * This is normally called from the decompressor code. The requirements * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, - * r1 = machine nr, r2 = atags pointer. + * r1 = machine nr, r2 = atags or dtb pointer. * * This code is mostly position independent, so if you link the kernel at * 0xc0008000, you call this at __pa(0xc0008000). @@ -87,25 +80,33 @@ ENTRY(stext) movs r10, r5 @ invalid processor (r5=0)? THUMB( it eq ) @ force fixup-able long branch encoding beq __error_p @ yes, error 'p' - bl __lookup_machine_type @ r5=machinfo - movs r8, r5 @ invalid machine (r5=0)? - THUMB( it eq ) @ force fixup-able long branch encoding - beq __error_a @ yes, error 'a' + +#ifndef CONFIG_XIP_KERNEL + adr r3, 2f + ldmia r3, {r4, r8} + sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET) + add r8, r8, r4 @ PHYS_OFFSET +#else + ldr r8, =PLAT_PHYS_OFFSET +#endif /* - * r1 = machine no, r2 = atags, - * r8 = machinfo, r9 = cpuid, r10 = procinfo + * r1 = machine no, r2 = atags or dtb, + * r8 = phys_offset, r9 = cpuid, r10 = procinfo */ bl __vet_atags #ifdef CONFIG_SMP_ON_UP bl __fixup_smp #endif +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + bl __fixup_pv_table +#endif bl __create_page_tables /* * The following calls CPU specific code in a position independent * manner. See arch/arm/mm/proc-*.S for details. r10 = base of - * xxx_proc_info structure selected by __lookup_machine_type + * xxx_proc_info structure selected by __lookup_processor_type * above. On return, the CPU will be ready for the MMU to be * turned on, and r0 will hold the CPU control register value. */ @@ -118,22 +119,24 @@ ENTRY(stext) 1: b __enable_mmu ENDPROC(stext) .ltorg +#ifndef CONFIG_XIP_KERNEL +2: .long . + .long PAGE_OFFSET +#endif /* * Setup the initial page tables. We only setup the barest * amount which are required to get the kernel running, which * generally means mapping in the kernel code. * - * r8 = machinfo - * r9 = cpuid - * r10 = procinfo + * r8 = phys_offset, r9 = cpuid, r10 = procinfo * * Returns: * r0, r3, r5-r7 corrupted * r4 = physical page table address */ __create_page_tables: - pgtbl r4 @ page table address + pgtbl r4, r8 @ page table address /* * Clear the 16K level 1 swapper page table @@ -189,10 +192,8 @@ __create_page_tables: /* * Map some ram to cover our .data and .bss areas. */ - orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000) - .if (KERNEL_RAM_PADDR & 0x00f00000) - orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000) - .endif + add r3, r8, #TEXT_OFFSET + orr r3, r3, r7 add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! ldr r6, =(_end - 1) @@ -205,14 +206,17 @@ __create_page_tables: #endif /* - * Then map first 1MB of ram in case it contains our boot params. + * Then map boot params address in r2 or + * the first 1MB of ram if boot params address is not specified. */ - add r0, r4, #PAGE_OFFSET >> 18 - orr r6, r7, #(PHYS_OFFSET & 0xff000000) - .if (PHYS_OFFSET & 0x00f00000) - orr r6, r6, #(PHYS_OFFSET & 0x00f00000) - .endif - str r6, [r0] + mov r0, r2, lsr #20 + movs r0, r0, lsl #20 + moveq r0, r8 + sub r3, r0, r8 + add r3, r3, #PAGE_OFFSET + add r3, r4, r3, lsr #18 + orr r6, r7, r0 + str r6, [r3] #ifdef CONFIG_DEBUG_LL #ifndef CONFIG_DEBUG_ICEDCC @@ -335,7 +339,7 @@ __secondary_data: * * r0 = cp#15 control register * r1 = machine ID - * r2 = atags pointer + * r2 = atags or dtb pointer * r4 = page table pointer * r9 = processor ID * r13 = *virtual* address to jump to upon completion @@ -372,7 +376,7 @@ ENDPROC(__enable_mmu) * * r0 = cp#15 control register * r1 = machine ID - * r2 = atags pointer + * r2 = atags or dtb pointer * r9 = processor ID * r13 = *virtual* address to jump to upon completion * @@ -457,4 +461,129 @@ ENTRY(fixup_smp) ldmfd sp!, {r4 - r6, pc} ENDPROC(fixup_smp) +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + +/* __fixup_pv_table - patch the stub instructions with the delta between + * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and + * can be expressed by an immediate shifter operand. The stub instruction + * has a form of '(add|sub) rd, rn, #imm'. + */ + __HEAD +__fixup_pv_table: + adr r0, 1f + ldmia r0, {r3-r5, r7} + sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET + add r4, r4, r3 @ adjust table start address + add r5, r5, r3 @ adjust table end address + add r7, r7, r3 @ adjust __pv_phys_offset address + str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset +#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + mov r6, r3, lsr #24 @ constant for add/sub instructions + teq r3, r6, lsl #24 @ must be 16MiB aligned +#else + mov r6, r3, lsr #16 @ constant for add/sub instructions + teq r3, r6, lsl #16 @ must be 64kiB aligned +#endif +THUMB( it ne @ cross section branch ) + bne __error + str r6, [r7, #4] @ save to __pv_offset + b __fixup_a_pv_table +ENDPROC(__fixup_pv_table) + + .align +1: .long . + .long __pv_table_begin + .long __pv_table_end +2: .long __pv_phys_offset + + .text +__fixup_a_pv_table: +#ifdef CONFIG_THUMB2_KERNEL +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + lsls r0, r6, #24 + lsr r6, #8 + beq 1f + clz r7, r0 + lsr r0, #24 + lsl r0, r7 + bic r0, 0x0080 + lsrs r7, #1 + orrcs r0, #0x0080 + orr r0, r0, r7, lsl #12 +#endif +1: lsls r6, #24 + beq 4f + clz r7, r6 + lsr r6, #24 + lsl r6, r7 + bic r6, #0x0080 + lsrs r7, #1 + orrcs r6, #0x0080 + orr r6, r6, r7, lsl #12 + orr r6, #0x4000 + b 4f +2: @ at this point the C flag is always clear + add r7, r3 +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + ldrh ip, [r7] + tst ip, 0x0400 @ the i bit tells us LS or MS byte + beq 3f + cmp r0, #0 @ set C flag, and ... + biceq ip, 0x0400 @ immediate zero value has a special encoding + streqh ip, [r7] @ that requires the i bit cleared +#endif +3: ldrh ip, [r7, #2] + and ip, 0x8f00 + orrcc ip, r6 @ mask in offset bits 31-24 + orrcs ip, r0 @ mask in offset bits 23-16 + strh ip, [r7, #2] +4: cmp r4, r5 + ldrcc r7, [r4], #4 @ use branch for delay slot + bcc 2b + bx lr +#else +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + and r0, r6, #255 @ offset bits 23-16 + mov r6, r6, lsr #8 @ offset bits 31-24 +#else + mov r0, #0 @ just in case... +#endif + b 3f +2: ldr ip, [r7, r3] + bic ip, ip, #0x000000ff + tst ip, #0x400 @ rotate shift tells us LS or MS byte + orrne ip, ip, r6 @ mask in offset bits 31-24 + orreq ip, ip, r0 @ mask in offset bits 23-16 + str ip, [r7, r3] +3: cmp r4, r5 + ldrcc r7, [r4], #4 @ use branch for delay slot + bcc 2b + mov pc, lr +#endif +ENDPROC(__fixup_a_pv_table) + +ENTRY(fixup_pv_table) + stmfd sp!, {r4 - r7, lr} + ldr r2, 2f @ get address of __pv_phys_offset + mov r3, #0 @ no offset + mov r4, r0 @ r0 = table start + add r5, r0, r1 @ r1 = table size + ldr r6, [r2, #4] @ get __pv_offset + bl __fixup_a_pv_table + ldmfd sp!, {r4 - r7, pc} +ENDPROC(fixup_pv_table) + + .align +2: .long __pv_phys_offset + + .data + .globl __pv_phys_offset + .type __pv_phys_offset, %object +__pv_phys_offset: + .long 0 + .size __pv_phys_offset, . - __pv_phys_offset +__pv_offset: + .long 0 +#endif + #include "head-common.S" diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 28536e352de..3535d3793e6 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -179,14 +179,21 @@ int __init arch_probe_nr_irqs(void) #ifdef CONFIG_HOTPLUG_CPU -static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) +static bool migrate_one_irq(struct irq_data *d) { - pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->irq_data.node, cpu); + unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask); + bool ret = false; - raw_spin_lock_irq(&desc->lock); - desc->irq_data.chip->irq_set_affinity(&desc->irq_data, - cpumask_of(cpu), false); - raw_spin_unlock_irq(&desc->lock); + if (cpu >= nr_cpu_ids) { + cpu = cpumask_any(cpu_online_mask); + ret = true; + } + + pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu); + + d->chip->irq_set_affinity(d, cpumask_of(cpu), true); + + return ret; } /* @@ -198,25 +205,30 @@ void migrate_irqs(void) { unsigned int i, cpu = smp_processor_id(); struct irq_desc *desc; + unsigned long flags; + + local_irq_save(flags); for_each_irq_desc(i, desc) { struct irq_data *d = &desc->irq_data; + bool affinity_broken = false; - if (d->node == cpu) { - unsigned int newcpu = cpumask_any_and(d->affinity, - cpu_online_mask); - if (newcpu >= nr_cpu_ids) { - if (printk_ratelimit()) - printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n", - i, cpu); + raw_spin_lock(&desc->lock); + do { + if (desc->action == NULL) + break; - cpumask_setall(d->affinity); - newcpu = cpumask_any_and(d->affinity, - cpu_online_mask); - } + if (d->node != cpu) + break; - route_irq(desc, i, newcpu); - } + affinity_broken = migrate_one_irq(d); + } while (0); + raw_spin_unlock(&desc->lock); + + if (affinity_broken && printk_ratelimit()) + pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu); } + + local_irq_restore(flags); } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 6d4105e6872..fee7c36349e 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -76,6 +76,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { unsigned long loc; Elf32_Sym *sym; + const char *symname; s32 offset; #ifdef CONFIG_THUMB2_KERNEL u32 upper, lower, sign, j1, j2; @@ -83,18 +84,18 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset = ELF32_R_SYM(rel->r_info); if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { - printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n", + pr_err("%s: section %u reloc %u: bad relocation sym offset\n", module->name, relindex, i); return -ENOEXEC; } sym = ((Elf32_Sym *)symsec->sh_addr) + offset; + symname = strtab + sym->st_name; if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { - printk(KERN_ERR "%s: out of bounds relocation, " - "section %d reloc %d offset %d size %d\n", - module->name, relindex, i, rel->r_offset, - dstsec->sh_size); + pr_err("%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n", + module->name, relindex, i, symname, + rel->r_offset, dstsec->sh_size); return -ENOEXEC; } @@ -120,10 +121,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (offset & 3 || offset <= (s32)0xfe000000 || offset >= (s32)0x02000000) { - printk(KERN_ERR - "%s: relocation out of range, section " - "%d reloc %d sym '%s'\n", module->name, - relindex, i, strtab + sym->st_name); + pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", + module->name, relindex, i, symname, + ELF32_R_TYPE(rel->r_info), loc, + sym->st_value); return -ENOEXEC; } @@ -196,10 +197,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (!(offset & 1) || offset <= (s32)0xff000000 || offset >= (s32)0x01000000) { - printk(KERN_ERR - "%s: relocation out of range, section " - "%d reloc %d sym '%s'\n", module->name, - relindex, i, strtab + sym->st_name); + pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", + module->name, relindex, i, symname, + ELF32_R_TYPE(rel->r_info), loc, + sym->st_value); return -ENOEXEC; } @@ -282,12 +283,13 @@ static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr, return NULL; } +extern void fixup_pv_table(const void *, unsigned long); extern void fixup_smp(const void *, unsigned long); int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) { - const Elf_Shdr * __maybe_unused s = NULL; + const Elf_Shdr *s = NULL; #ifdef CONFIG_ARM_UNWIND const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; @@ -332,6 +334,11 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, maps[i].txt_sec->sh_addr, maps[i].txt_sec->sh_size); #endif +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + s = find_mod_section(hdr, sechdrs, ".pv_table"); + if (s) + fixup_pv_table((void *)s->sh_addr, s->sh_size); +#endif s = find_mod_section(hdr, sechdrs, ".alt.smp.init"); if (s && !is_smp()) fixup_smp((void *)s->sh_addr, s->sh_size); diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index d150ad1ccb5..22e194eb853 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -377,9 +377,18 @@ validate_group(struct perf_event *event) return 0; } +static irqreturn_t armpmu_platform_irq(int irq, void *dev) +{ + struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev); + + return plat->handle_irq(irq, dev, armpmu->handle_irq); +} + static int armpmu_reserve_hardware(void) { + struct arm_pmu_platdata *plat; + irq_handler_t handle_irq; int i, err = -ENODEV, irq; pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU); @@ -390,6 +399,12 @@ armpmu_reserve_hardware(void) init_pmu(ARM_PMU_DEVICE_CPU); + plat = dev_get_platdata(&pmu_device->dev); + if (plat && plat->handle_irq) + handle_irq = armpmu_platform_irq; + else + handle_irq = armpmu->handle_irq; + if (pmu_device->num_resources < 1) { pr_err("no irqs for PMUs defined\n"); return -ENODEV; @@ -400,7 +415,7 @@ armpmu_reserve_hardware(void) if (irq < 0) continue; - err = request_irq(irq, armpmu->handle_irq, + err = request_irq(irq, handle_irq, IRQF_DISABLED | IRQF_NOBALANCING, "armpmu", NULL); if (err) { diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index c058bfc8532..6fc2d228db5 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c @@ -30,7 +30,7 @@ * enable the interrupt. */ -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) enum armv6_perf_types { ARMV6_PERFCTR_ICACHE_MISS = 0x0, ARMV6_PERFCTR_IBUF_STALL = 0x1, @@ -669,4 +669,4 @@ static const struct arm_pmu *__init armv6mpcore_pmu_init(void) { return NULL; } -#endif /* CONFIG_CPU_V6 */ +#endif /* CONFIG_CPU_V6 || CONFIG_CPU_V6K */ diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index b13e70f63d7..2bf27f364d0 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -26,8 +26,6 @@ #include <asm/system.h> #include <asm/traps.h> -#include "ptrace.h" - #define REG_PC 15 #define REG_PSR 16 /* @@ -184,389 +182,12 @@ put_user_reg(struct task_struct *task, int offset, long data) return ret; } -static inline int -read_u32(struct task_struct *task, unsigned long addr, u32 *res) -{ - int ret; - - ret = access_process_vm(task, addr, res, sizeof(*res), 0); - - return ret == sizeof(*res) ? 0 : -EIO; -} - -static inline int -read_instr(struct task_struct *task, unsigned long addr, u32 *res) -{ - int ret; - - if (addr & 1) { - u16 val; - ret = access_process_vm(task, addr & ~1, &val, sizeof(val), 0); - ret = ret == sizeof(val) ? 0 : -EIO; - *res = val; - } else { - u32 val; - ret = access_process_vm(task, addr & ~3, &val, sizeof(val), 0); - ret = ret == sizeof(val) ? 0 : -EIO; - *res = val; - } - return ret; -} - -/* - * Get value of register `rn' (in the instruction) - */ -static unsigned long -ptrace_getrn(struct task_struct *child, unsigned long insn) -{ - unsigned int reg = (insn >> 16) & 15; - unsigned long val; - - val = get_user_reg(child, reg); - if (reg == 15) - val += 8; - - return val; -} - -/* - * Get value of operand 2 (in an ALU instruction) - */ -static unsigned long -ptrace_getaluop2(struct task_struct *child, unsigned long insn) -{ - unsigned long val; - int shift; - int type; - - if (insn & 1 << 25) { - val = insn & 255; - shift = (insn >> 8) & 15; - type = 3; - } else { - val = get_user_reg (child, insn & 15); - - if (insn & (1 << 4)) - shift = (int)get_user_reg (child, (insn >> 8) & 15); - else - shift = (insn >> 7) & 31; - - type = (insn >> 5) & 3; - } - - switch (type) { - case 0: val <<= shift; break; - case 1: val >>= shift; break; - case 2: - val = (((signed long)val) >> shift); - break; - case 3: - val = (val >> shift) | (val << (32 - shift)); - break; - } - return val; -} - -/* - * Get value of operand 2 (in a LDR instruction) - */ -static unsigned long -ptrace_getldrop2(struct task_struct *child, unsigned long insn) -{ - unsigned long val; - int shift; - int type; - - val = get_user_reg(child, insn & 15); - shift = (insn >> 7) & 31; - type = (insn >> 5) & 3; - - switch (type) { - case 0: val <<= shift; break; - case 1: val >>= shift; break; - case 2: - val = (((signed long)val) >> shift); - break; - case 3: - val = (val >> shift) | (val << (32 - shift)); - break; - } - return val; -} - -#define OP_MASK 0x01e00000 -#define OP_AND 0x00000000 -#define OP_EOR 0x00200000 -#define OP_SUB 0x00400000 -#define OP_RSB 0x00600000 -#define OP_ADD 0x00800000 -#define OP_ADC 0x00a00000 -#define OP_SBC 0x00c00000 -#define OP_RSC 0x00e00000 -#define OP_ORR 0x01800000 -#define OP_MOV 0x01a00000 -#define OP_BIC 0x01c00000 -#define OP_MVN 0x01e00000 - -static unsigned long -get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn) -{ - u32 alt = 0; - - switch (insn & 0x0e000000) { - case 0x00000000: - case 0x02000000: { - /* - * data processing - */ - long aluop1, aluop2, ccbit; - - if ((insn & 0x0fffffd0) == 0x012fff10) { - /* - * bx or blx - */ - alt = get_user_reg(child, insn & 15); - break; - } - - - if ((insn & 0xf000) != 0xf000) - break; - - aluop1 = ptrace_getrn(child, insn); - aluop2 = ptrace_getaluop2(child, insn); - ccbit = get_user_reg(child, REG_PSR) & PSR_C_BIT ? 1 : 0; - - switch (insn & OP_MASK) { - case OP_AND: alt = aluop1 & aluop2; break; - case OP_EOR: alt = aluop1 ^ aluop2; break; - case OP_SUB: alt = aluop1 - aluop2; break; - case OP_RSB: alt = aluop2 - aluop1; break; - case OP_ADD: alt = aluop1 + aluop2; break; - case OP_ADC: alt = aluop1 + aluop2 + ccbit; break; - case OP_SBC: alt = aluop1 - aluop2 + ccbit; break; - case OP_RSC: alt = aluop2 - aluop1 + ccbit; break; - case OP_ORR: alt = aluop1 | aluop2; break; - case OP_MOV: alt = aluop2; break; - case OP_BIC: alt = aluop1 & ~aluop2; break; - case OP_MVN: alt = ~aluop2; break; - } - break; - } - - case 0x04000000: - case 0x06000000: - /* - * ldr - */ - if ((insn & 0x0010f000) == 0x0010f000) { - unsigned long base; - - base = ptrace_getrn(child, insn); - if (insn & 1 << 24) { - long aluop2; - - if (insn & 0x02000000) - aluop2 = ptrace_getldrop2(child, insn); - else - aluop2 = insn & 0xfff; - - if (insn & 1 << 23) - base += aluop2; - else - base -= aluop2; - } - read_u32(child, base, &alt); - } - break; - - case 0x08000000: - /* - * ldm - */ - if ((insn & 0x00108000) == 0x00108000) { - unsigned long base; - unsigned int nr_regs; - - if (insn & (1 << 23)) { - nr_regs = hweight16(insn & 65535) << 2; - - if (!(insn & (1 << 24))) - nr_regs -= 4; - } else { - if (insn & (1 << 24)) - nr_regs = -4; - else - nr_regs = 0; - } - - base = ptrace_getrn(child, insn); - - read_u32(child, base + nr_regs, &alt); - break; - } - break; - - case 0x0a000000: { - /* - * bl or b - */ - signed long displ; - /* It's a branch/branch link: instead of trying to - * figure out whether the branch will be taken or not, - * we'll put a breakpoint at both locations. This is - * simpler, more reliable, and probably not a whole lot - * slower than the alternative approach of emulating the - * branch. - */ - displ = (insn & 0x00ffffff) << 8; - displ = (displ >> 6) + 8; - if (displ != 0 && displ != 4) - alt = pc + displ; - } - break; - } - - return alt; -} - -static int -swap_insn(struct task_struct *task, unsigned long addr, - void *old_insn, void *new_insn, int size) -{ - int ret; - - ret = access_process_vm(task, addr, old_insn, size, 0); - if (ret == size) - ret = access_process_vm(task, addr, new_insn, size, 1); - return ret; -} - -static void -add_breakpoint(struct task_struct *task, struct debug_info *dbg, unsigned long addr) -{ - int nr = dbg->nsaved; - - if (nr < 2) { - u32 new_insn = BREAKINST_ARM; - int res; - - res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4); - - if (res == 4) { - dbg->bp[nr].address = addr; - dbg->nsaved += 1; - } - } else - printk(KERN_ERR "ptrace: too many breakpoints\n"); -} - -/* - * Clear one breakpoint in the user program. We copy what the hardware - * does and use bit 0 of the address to indicate whether this is a Thumb - * breakpoint or an ARM breakpoint. - */ -static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp) -{ - unsigned long addr = bp->address; - union debug_insn old_insn; - int ret; - - if (addr & 1) { - ret = swap_insn(task, addr & ~1, &old_insn.thumb, - &bp->insn.thumb, 2); - - if (ret != 2 || old_insn.thumb != BREAKINST_THUMB) - printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at " - "0x%08lx (0x%04x)\n", task->comm, - task_pid_nr(task), addr, old_insn.thumb); - } else { - ret = swap_insn(task, addr & ~3, &old_insn.arm, - &bp->insn.arm, 4); - - if (ret != 4 || old_insn.arm != BREAKINST_ARM) - printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at " - "0x%08lx (0x%08x)\n", task->comm, - task_pid_nr(task), addr, old_insn.arm); - } -} - -void ptrace_set_bpt(struct task_struct *child) -{ - struct pt_regs *regs; - unsigned long pc; - u32 insn; - int res; - - regs = task_pt_regs(child); - pc = instruction_pointer(regs); - - if (thumb_mode(regs)) { - printk(KERN_WARNING "ptrace: can't handle thumb mode\n"); - return; - } - - res = read_instr(child, pc, &insn); - if (!res) { - struct debug_info *dbg = &child->thread.debug; - unsigned long alt; - - dbg->nsaved = 0; - - alt = get_branch_address(child, pc, insn); - if (alt) - add_breakpoint(child, dbg, alt); - - /* - * Note that we ignore the result of setting the above - * breakpoint since it may fail. When it does, this is - * not so much an error, but a forewarning that we may - * be receiving a prefetch abort shortly. - * - * If we don't set this breakpoint here, then we can - * lose control of the thread during single stepping. - */ - if (!alt || predicate(insn) != PREDICATE_ALWAYS) - add_breakpoint(child, dbg, pc + 4); - } -} - -/* - * Ensure no single-step breakpoint is pending. Returns non-zero - * value if child was being single-stepped. - */ -void ptrace_cancel_bpt(struct task_struct *child) -{ - int i, nsaved = child->thread.debug.nsaved; - - child->thread.debug.nsaved = 0; - - if (nsaved > 2) { - printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); - nsaved = 2; - } - - for (i = 0; i < nsaved; i++) - clear_breakpoint(child, &child->thread.debug.bp[i]); -} - -void user_disable_single_step(struct task_struct *task) -{ - task->ptrace &= ~PT_SINGLESTEP; - ptrace_cancel_bpt(task); -} - -void user_enable_single_step(struct task_struct *task) -{ - task->ptrace |= PT_SINGLESTEP; -} - /* * Called by kernel/ptrace.c when detaching.. */ void ptrace_disable(struct task_struct *child) { - user_disable_single_step(child); + /* Nothing to do. */ } /* @@ -576,8 +197,6 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) { siginfo_t info; - ptrace_cancel_bpt(tsk); - info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h deleted file mode 100644 index 3926605b82e..00000000000 --- a/arch/arm/kernel/ptrace.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * linux/arch/arm/kernel/ptrace.h - * - * Copyright (C) 2000-2003 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/ptrace.h> - -extern void ptrace_cancel_bpt(struct task_struct *); -extern void ptrace_set_bpt(struct task_struct *); -extern void ptrace_break(struct task_struct *, struct pt_regs *); - -/* - * Send SIGTRAP if we're single-stepping - */ -static inline void single_step_trap(struct task_struct *task) -{ - if (task->ptrace & PT_SINGLESTEP) { - ptrace_cancel_bpt(task); - send_sig(SIGTRAP, task, 1); - } -} - -static inline void single_step_clear(struct task_struct *task) -{ - if (task->ptrace & PT_SINGLESTEP) - ptrace_cancel_bpt(task); -} - -static inline void single_step_set(struct task_struct *task) -{ - if (task->ptrace & PT_SINGLESTEP) - ptrace_set_bpt(task); -} diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index 9cf4cbf8f95..a2599e7e151 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -7,8 +7,8 @@ .globl relocate_new_kernel relocate_new_kernel: - ldr r0,kexec_indirection_page - ldr r1,kexec_start_address + ldr r0,__kexec_indirection_page + ldr r1,__kexec_start_address /* * If there is no indirection page (we are doing crashdumps) @@ -55,27 +55,31 @@ relocate_new_kernel: /* Jump to relocated kernel */ mov lr,r1 mov r0,#0 - ldr r1,kexec_mach_type - ldr r2,kexec_boot_atags + ldr r1,__kexec_mach_type + ldr r2,__kexec_boot_atags mov pc,lr .align .globl kexec_start_address kexec_start_address: +__kexec_start_address: .long 0x0 .globl kexec_indirection_page kexec_indirection_page: +__kexec_indirection_page: .long 0x0 .globl kexec_mach_type kexec_mach_type: +__kexec_mach_type: .long 0x0 /* phy addr of the atags for the new kernel */ .globl kexec_boot_atags kexec_boot_atags: +__kexec_boot_atags: .long 0x0 relocate_new_kernel_end: diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index df246da4cec..0b13a72f855 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c @@ -9,6 +9,7 @@ * the Free Software Foundation. */ #include <linux/module.h> +#include <linux/ftrace.h> #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) #include <linux/sched.h> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 5ea4fb718b9..319199b0ab2 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -20,6 +20,7 @@ #include <linux/screen_info.h> #include <linux/init.h> #include <linux/kexec.h> +#include <linux/of_fdt.h> #include <linux/crash_dump.h> #include <linux/root_dev.h> #include <linux/cpu.h> @@ -42,6 +43,7 @@ #include <asm/cachetype.h> #include <asm/tlbflush.h> +#include <asm/prom.h> #include <asm/mach/arch.h> #include <asm/mach/irq.h> #include <asm/mach/time.h> @@ -125,7 +127,7 @@ EXPORT_SYMBOL(elf_platform); static const char *cpu_name; static const char *machine_name; -static char __initdata cmd_line[COMMAND_LINE_SIZE]; +char cmd_line[COMMAND_LINE_SIZE]; struct machine_desc *machine_desc __initdata; static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; @@ -308,7 +310,22 @@ static void __init cacheid_init(void) * already provide the required functionality. */ extern struct proc_info_list *lookup_processor_type(unsigned int); -extern struct machine_desc *lookup_machine_type(unsigned int); + +void __init early_print(const char *str, ...) +{ + extern void printascii(const char *); + char buf[256]; + va_list ap; + + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + +#ifdef CONFIG_DEBUG_LL + printascii(buf); +#endif + printk("%s", buf); +} static void __init feat_v6_fixup(void) { @@ -424,26 +441,21 @@ void cpu_init(void) : "r14"); } -static struct machine_desc * __init setup_machine(unsigned int nr) +void __init dump_machine_table(void) { - struct machine_desc *list; + struct machine_desc *p; - /* - * locate machine in the list of supported machines. - */ - list = lookup_machine_type(nr); - if (!list) { - printk("Machine configuration botched (nr %d), unable " - "to continue.\n", nr); - while (1); - } + early_print("Available machine support:\n\nID (hex)\tNAME\n"); + for_each_machine_desc(p) + early_print("%08x\t%s\n", p->nr, p->name); - printk("Machine: %s\n", list->name); + early_print("\nPlease check your kernel config and/or bootloader.\n"); - return list; + while (true) + /* can't use cpu_relax() here as it may require MMU setup */; } -static int __init arm_add_memory(unsigned long start, unsigned long size) +int __init arm_add_memory(unsigned long start, unsigned long size) { struct membank *bank = &meminfo.bank[meminfo.nr_banks]; @@ -703,7 +715,7 @@ static struct init_tags { { tag_size(tag_core), ATAG_CORE }, { 1, PAGE_SIZE, 0xff }, { tag_size(tag_mem32), ATAG_MEM }, - { MEM_SIZE, PHYS_OFFSET }, + { MEM_SIZE }, { 0, ATAG_NONE } }; @@ -796,26 +808,51 @@ static void __init squash_mem_tags(struct tag *tag) tag->hdr.tag = ATAG_NONE; } -void __init setup_arch(char **cmdline_p) +static struct machine_desc * __init setup_machine_tags(unsigned int nr) { struct tag *tags = (struct tag *)&init_tags; - struct machine_desc *mdesc; + struct machine_desc *mdesc = NULL, *p; char *from = default_command_line; - unwind_init(); + /* + * locate machine in the list of supported machines. + */ + for_each_machine_desc(p) + if (nr == p->nr) { + printk("Machine: %s\n", p->name); + mdesc = p; + break; + } - setup_processor(); - mdesc = setup_machine(machine_arch_type); - machine_desc = mdesc; - machine_name = mdesc->name; + if (!mdesc) { + early_print("\nError: unrecognized/unsupported machine ID" + " (r1 = 0x%08x).\n\n", nr); + dump_machine_table(); /* does not return */ + } - if (mdesc->soft_reboot) - reboot_setup("s"); + printk("Machine: %s\n", mdesc->name); if (__atags_pointer) tags = phys_to_virt(__atags_pointer); - else if (mdesc->boot_params) - tags = phys_to_virt(mdesc->boot_params); + else if (mdesc->boot_params) { +#ifdef CONFIG_MMU + /* + * We still are executing with a minimal MMU mapping created + * with the presumption that the machine default for this + * is located in the first MB of RAM. Anything else will + * fault and silently hang the kernel at this point. + */ + if (mdesc->boot_params < PHYS_OFFSET || + mdesc->boot_params >= PHYS_OFFSET + SZ_1M) { + printk(KERN_WARNING + "Default boot params at physical 0x%08lx out of reach\n", + mdesc->boot_params); + } else +#endif + { + tags = phys_to_virt(mdesc->boot_params); + } + } #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) /* @@ -838,16 +875,39 @@ void __init setup_arch(char **cmdline_p) parse_tags(tags); } - init_mm.start_code = (unsigned long) _text; - init_mm.end_code = (unsigned long) _etext; - init_mm.end_data = (unsigned long) _edata; - init_mm.brk = (unsigned long) _end; - /* 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); + + return mdesc; +} + + +void __init setup_arch(char **cmdline_p) +{ + struct machine_desc *mdesc; + + init_tags.mem.start = PHYS_OFFSET; + + unwind_init(); + + setup_processor(); + mdesc = setup_machine_fdt(__atags_pointer); + if (!mdesc) + mdesc = setup_machine_tags(machine_arch_type); + machine_desc = mdesc; + machine_name = mdesc->name; + + if (mdesc->soft_reboot) + reboot_setup("s"); + + init_mm.start_code = (unsigned long) _text; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; + init_mm.brk = (unsigned long) _end; + *cmdline_p = cmd_line; parse_early_param(); @@ -857,6 +917,8 @@ void __init setup_arch(char **cmdline_p) paging_init(mdesc); request_standard_resources(mdesc); + unflatten_device_tree(); + #ifdef CONFIG_SMP if (is_smp()) smp_init_cpus(); diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index abaf8445ce2..cb839831764 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -20,7 +20,6 @@ #include <asm/unistd.h> #include <asm/vfp.h> -#include "ptrace.h" #include "signal.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -348,8 +347,6 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) if (restore_sigframe(regs, frame)) goto badframe; - single_step_trap(current); - return regs->ARM_r0; badframe: @@ -383,8 +380,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) goto badframe; - single_step_trap(current); - return regs->ARM_r0; badframe: @@ -706,8 +701,6 @@ static void do_signal(struct pt_regs *regs, int syscall) if (try_to_freeze()) goto no_signal; - single_step_clear(current); - signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; @@ -726,7 +719,6 @@ static void do_signal(struct pt_regs *regs, int syscall) if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } - single_step_set(current); return; } @@ -772,7 +764,6 @@ static void do_signal(struct pt_regs *regs, int syscall) sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } - single_step_set(current); } asmlinkage void diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index 26685c2f7a4..f5cf660eefc 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c @@ -15,7 +15,7 @@ #include <linux/string.h> /* memcpy */ #include <asm/cputype.h> #include <asm/mach/map.h> -#include <mach/memory.h> +#include <asm/memory.h> #include "tcm.h" static struct gen_pool *tcm_pool; diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index ee57640ba2b..21ac43f1c2d 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -23,6 +23,7 @@ #include <linux/kexec.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/sched.h> #include <asm/atomic.h> #include <asm/cacheflush.h> @@ -32,7 +33,6 @@ #include <asm/unwind.h> #include <asm/tls.h> -#include "ptrace.h" #include "signal.h" static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; @@ -256,7 +256,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt return ret; } -DEFINE_SPINLOCK(die_lock); +static DEFINE_SPINLOCK(die_lock); /* * This function is protected against re-entrancy. diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 61462790757..dfbb377e251 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -64,6 +64,10 @@ SECTIONS __smpalt_end = .; #endif + __pv_table_begin = .; + *(.pv_table) + __pv_table_end = .; + INIT_SETUP(16) INIT_CALLS diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index d42252918bf..10d868a5a48 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -1,44 +1,52 @@ - -#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K) +#if __LINUX_ARM_ARCH__ >= 6 .macro bitop, instr + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned mov r2, #1 - and r3, r0, #7 @ Get bit offset - add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #31 @ Get bit offset + mov r0, r0, lsr #5 + add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 -1: ldrexb r2, [r1] +1: ldrex r2, [r1] \instr r2, r2, r3 - strexb r0, r2, [r1] + strex r0, r2, [r1] cmp r0, #0 bne 1b - mov pc, lr + bx lr .endm .macro testop, instr, store - and r3, r0, #7 @ Get bit offset + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned mov r2, #1 - add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #31 @ Get bit offset + mov r0, r0, lsr #5 + add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 @ create mask smp_dmb -1: ldrexb r2, [r1] +1: ldrex r2, [r1] ands r0, r2, r3 @ save old value of bit - \instr r2, r2, r3 @ toggle bit - strexb ip, r2, [r1] + \instr r2, r2, r3 @ toggle bit + strex ip, r2, [r1] cmp ip, #0 bne 1b smp_dmb cmp r0, #0 movne r0, #1 -2: mov pc, lr +2: bx lr .endm #else .macro bitop, instr - and r2, r0, #7 + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned + and r2, r0, #31 + mov r0, r0, lsr #5 mov r3, #1 mov r3, r3, lsl r2 save_and_disable_irqs ip - ldrb r2, [r1, r0, lsr #3] + ldr r2, [r1, r0, lsl #2] \instr r2, r2, r3 - strb r2, [r1, r0, lsr #3] + str r2, [r1, r0, lsl #2] restore_irqs ip mov pc, lr .endm @@ -52,11 +60,13 @@ * to avoid dirtying the data cache. */ .macro testop, instr, store - add r1, r1, r0, lsr #3 - and r3, r0, #7 - mov r0, #1 + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned + and r3, r0, #31 + mov r0, r0, lsr #5 save_and_disable_irqs ip - ldrb r2, [r1] + ldr r2, [r1, r0, lsl #2]! + mov r0, #1 tst r2, r0, lsl r3 \instr r2, r2, r0, lsl r3 \store r2, [r1] diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S index 80f3115cbee..68ed5b62e83 100644 --- a/arch/arm/lib/changebit.S +++ b/arch/arm/lib/changebit.S @@ -12,12 +12,6 @@ #include "bitops.h" .text -/* Purpose : Function to change a bit - * Prototype: int change_bit(int bit, void *addr) - */ -ENTRY(_change_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_change_bit_le) +ENTRY(_change_bit) bitop eor -ENDPROC(_change_bit_be) -ENDPROC(_change_bit_le) +ENDPROC(_change_bit) diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S index 1a63e43a1df..4c04c3b51ee 100644 --- a/arch/arm/lib/clearbit.S +++ b/arch/arm/lib/clearbit.S @@ -12,13 +12,6 @@ #include "bitops.h" .text -/* - * Purpose : Function to clear a bit - * Prototype: int clear_bit(int bit, void *addr) - */ -ENTRY(_clear_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_clear_bit_le) +ENTRY(_clear_bit) bitop bic -ENDPROC(_clear_bit_be) -ENDPROC(_clear_bit_le) +ENDPROC(_clear_bit) diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S index 1dd7176c4b2..bbee5c66a23 100644 --- a/arch/arm/lib/setbit.S +++ b/arch/arm/lib/setbit.S @@ -12,13 +12,6 @@ #include "bitops.h" .text -/* - * Purpose : Function to set a bit - * Prototype: int set_bit(int bit, void *addr) - */ -ENTRY(_set_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_set_bit_le) +ENTRY(_set_bit) bitop orr -ENDPROC(_set_bit_be) -ENDPROC(_set_bit_le) +ENDPROC(_set_bit) diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S index 5c98dc567f0..15a4d431f22 100644 --- a/arch/arm/lib/testchangebit.S +++ b/arch/arm/lib/testchangebit.S @@ -12,9 +12,6 @@ #include "bitops.h" .text -ENTRY(_test_and_change_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_test_and_change_bit_le) - testop eor, strb -ENDPROC(_test_and_change_bit_be) -ENDPROC(_test_and_change_bit_le) +ENTRY(_test_and_change_bit) + testop eor, str +ENDPROC(_test_and_change_bit) diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S index 543d7094d18..521b66b5b95 100644 --- a/arch/arm/lib/testclearbit.S +++ b/arch/arm/lib/testclearbit.S @@ -12,9 +12,6 @@ #include "bitops.h" .text -ENTRY(_test_and_clear_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_test_and_clear_bit_le) - testop bicne, strneb -ENDPROC(_test_and_clear_bit_be) -ENDPROC(_test_and_clear_bit_le) +ENTRY(_test_and_clear_bit) + testop bicne, strne +ENDPROC(_test_and_clear_bit) diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S index 0b3f390401c..1c98cc2185b 100644 --- a/arch/arm/lib/testsetbit.S +++ b/arch/arm/lib/testsetbit.S @@ -12,9 +12,6 @@ #include "bitops.h" .text -ENTRY(_test_and_set_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_test_and_set_bit_le) - testop orreq, streqb -ENDPROC(_test_and_set_bit_be) -ENDPROC(_test_and_set_bit_le) +ENTRY(_test_and_set_bit) + testop orreq, streq +ENDPROC(_test_and_set_bit) diff --git a/arch/arm/mach-aaec2000/include/mach/memory.h b/arch/arm/mach-aaec2000/include/mach/memory.h index 4f93c567a35..4a10bf0bd36 100644 --- a/arch/arm/mach-aaec2000/include/mach/memory.h +++ b/arch/arm/mach-aaec2000/include/mach/memory.h @@ -12,6 +12,6 @@ #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0xf0000000) +#define PLAT_PHYS_OFFSET UL(0xf0000000) #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-at91/include/mach/memory.h b/arch/arm/mach-at91/include/mach/memory.h index 14f4ef4b6a9..c2cfe504064 100644 --- a/arch/arm/mach-at91/include/mach/memory.h +++ b/arch/arm/mach-at91/include/mach/memory.h @@ -23,6 +23,6 @@ #include <mach/hardware.h> -#define PHYS_OFFSET (AT91_SDRAM_BASE) +#define PLAT_PHYS_OFFSET (AT91_SDRAM_BASE) #endif diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h index 447eb340c61..8bf3564fba5 100644 --- a/arch/arm/mach-bcmring/include/mach/hardware.h +++ b/arch/arm/mach-bcmring/include/mach/hardware.h @@ -31,7 +31,7 @@ * *_SIZE is the size of the region * *_BASE is the virtual address */ -#define RAM_START PHYS_OFFSET +#define RAM_START PLAT_PHYS_OFFSET #define RAM_SIZE (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED) #define RAM_BASE PAGE_OFFSET diff --git a/arch/arm/mach-bcmring/include/mach/memory.h b/arch/arm/mach-bcmring/include/mach/memory.h index 114f942bb4f..15162e4c75f 100644 --- a/arch/arm/mach-bcmring/include/mach/memory.h +++ b/arch/arm/mach-bcmring/include/mach/memory.h @@ -23,7 +23,7 @@ * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. */ -#define PHYS_OFFSET CFG_GLOBAL_RAM_BASE +#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE /* * Maximum DMA memory allowed is 14M diff --git a/arch/arm/mach-clps711x/include/mach/memory.h b/arch/arm/mach-clps711x/include/mach/memory.h index f45c8e892cb..3a032a67725 100644 --- a/arch/arm/mach-clps711x/include/mach/memory.h +++ b/arch/arm/mach-clps711x/include/mach/memory.h @@ -23,7 +23,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) #if !defined(CONFIG_ARCH_CDB89712) && !defined (CONFIG_ARCH_AUTCPU12) diff --git a/arch/arm/mach-cns3xxx/include/mach/memory.h b/arch/arm/mach-cns3xxx/include/mach/memory.h index 3b6b769b7a2..dc16c5c5d86 100644 --- a/arch/arm/mach-cns3xxx/include/mach/memory.h +++ b/arch/arm/mach-cns3xxx/include/mach/memory.h @@ -13,7 +13,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define __phys_to_bus(x) ((x) + PHYS_OFFSET) #define __bus_to_phys(x) ((x) - PHYS_OFFSET) diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h index 22eb97c1c30..78822723f38 100644 --- a/arch/arm/mach-davinci/include/mach/memory.h +++ b/arch/arm/mach-davinci/include/mach/memory.h @@ -26,9 +26,9 @@ #if defined(CONFIG_ARCH_DAVINCI_DA8XX) && defined(CONFIG_ARCH_DAVINCI_DMx) #error Cannot enable DaVinci and DA8XX platforms concurrently #elif defined(CONFIG_ARCH_DAVINCI_DA8XX) -#define PHYS_OFFSET DA8XX_DDR_BASE +#define PLAT_PHYS_OFFSET DA8XX_DDR_BASE #else -#define PHYS_OFFSET DAVINCI_DDR_BASE +#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE #endif #define DDR2_SDRCR_OFFSET 0xc diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig index a4ed3900912..dd937c526a4 100644 --- a/arch/arm/mach-dove/Kconfig +++ b/arch/arm/mach-dove/Kconfig @@ -9,7 +9,7 @@ config MACH_DOVE_DB Say 'Y' here if you want your kernel to support the Marvell DB-MV88AP510 Development Board. - config MACH_CM_A510 +config MACH_CM_A510 bool "CompuLab CM-A510 Board" help Say 'Y' here if you want your kernel to support the diff --git a/arch/arm/mach-dove/include/mach/memory.h b/arch/arm/mach-dove/include/mach/memory.h index d6687207494..bbc93fee6c7 100644 --- a/arch/arm/mach-dove/include/mach/memory.h +++ b/arch/arm/mach-dove/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ebsa110/include/mach/memory.h b/arch/arm/mach-ebsa110/include/mach/memory.h index 0ca66d080c6..8e49066ad85 100644 --- a/arch/arm/mach-ebsa110/include/mach/memory.h +++ b/arch/arm/mach-ebsa110/include/mach/memory.h @@ -19,7 +19,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) /* * Cache flushing area - SRAM diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h index 554064e9030..c9400cf0051 100644 --- a/arch/arm/mach-ep93xx/include/mach/memory.h +++ b/arch/arm/mach-ep93xx/include/mach/memory.h @@ -6,15 +6,15 @@ #define __ASM_ARCH_MEMORY_H #if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) #elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xd0000000) +#define PLAT_PHYS_OFFSET UL(0xd0000000) #elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xe0000000) +#define PLAT_PHYS_OFFSET UL(0xe0000000) #elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xf0000000) +#define PLAT_PHYS_OFFSET UL(0xf0000000) #else #error "Kconfig bug: No EP93xx PHYS_OFFSET set" #endif diff --git a/arch/arm/mach-footbridge/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h index 8d64f457408..5c6df377f96 100644 --- a/arch/arm/mach-footbridge/include/mach/memory.h +++ b/arch/arm/mach-footbridge/include/mach/memory.h @@ -62,7 +62,7 @@ extern unsigned long __bus_to_pfn(unsigned long); /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define FLUSH_BASE_PHYS 0x50000000 diff --git a/arch/arm/mach-gemini/include/mach/memory.h b/arch/arm/mach-gemini/include/mach/memory.h index 2d14d5bf1f9..a50915f764d 100644 --- a/arch/arm/mach-gemini/include/mach/memory.h +++ b/arch/arm/mach-gemini/include/mach/memory.h @@ -11,9 +11,9 @@ #define __MACH_MEMORY_H #ifdef CONFIG_GEMINI_MEM_SWAP -# define PHYS_OFFSET UL(0x00000000) +# define PLAT_PHYS_OFFSET UL(0x00000000) #else -# define PHYS_OFFSET UL(0x10000000) +# define PLAT_PHYS_OFFSET UL(0x10000000) #endif #endif /* __MACH_MEMORY_H */ diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h index ef4c1e26f18..9d368765146 100644 --- a/arch/arm/mach-h720x/include/mach/memory.h +++ b/arch/arm/mach-h720x/include/mach/memory.h @@ -7,7 +7,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x40000000) +#define PLAT_PHYS_OFFSET UL(0x40000000) /* * This is the maximum DMA address that can be DMAd to. * There should not be more than (0xd0000000 - 0xc0000000) diff --git a/arch/arm/mach-integrator/include/mach/memory.h b/arch/arm/mach-integrator/include/mach/memory.h index 991f24d2c11..334d5e27188 100644 --- a/arch/arm/mach-integrator/include/mach/memory.h +++ b/arch/arm/mach-integrator/include/mach/memory.h @@ -23,7 +23,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define BUS_OFFSET UL(0x80000000) #define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET) diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h index 3ad45531886..1afa99ef97f 100644 --- a/arch/arm/mach-iop13xx/include/mach/memory.h +++ b/arch/arm/mach-iop13xx/include/mach/memory.h @@ -6,7 +6,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-iop32x/include/mach/memory.h b/arch/arm/mach-iop32x/include/mach/memory.h index c30f6450ad5..169cc239f76 100644 --- a/arch/arm/mach-iop32x/include/mach/memory.h +++ b/arch/arm/mach-iop32x/include/mach/memory.h @@ -8,6 +8,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xa0000000) +#define PLAT_PHYS_OFFSET UL(0xa0000000) #endif diff --git a/arch/arm/mach-iop33x/include/mach/memory.h b/arch/arm/mach-iop33x/include/mach/memory.h index a30a96aa6d2..8e1daf7006b 100644 --- a/arch/arm/mach-iop33x/include/mach/memory.h +++ b/arch/arm/mach-iop33x/include/mach/memory.h @@ -8,6 +8,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ixp2000/include/mach/memory.h b/arch/arm/mach-ixp2000/include/mach/memory.h index 98e3471be15..5f0c4fd4076 100644 --- a/arch/arm/mach-ixp2000/include/mach/memory.h +++ b/arch/arm/mach-ixp2000/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #include <mach/ixp2000-regs.h> diff --git a/arch/arm/mach-ixp23xx/include/mach/memory.h b/arch/arm/mach-ixp23xx/include/mach/memory.h index 6ef65d813f1..6cf0704e946 100644 --- a/arch/arm/mach-ixp23xx/include/mach/memory.h +++ b/arch/arm/mach-ixp23xx/include/mach/memory.h @@ -17,7 +17,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET (0x00000000) +#define PLAT_PHYS_OFFSET (0x00000000) #define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0) diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h index 0136eaa2922..6d388c9d0e2 100644 --- a/arch/arm/mach-ixp4xx/include/mach/memory.h +++ b/arch/arm/mach-ixp4xx/include/mach/memory.h @@ -12,7 +12,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #if !defined(__ASSEMBLY__) && defined(CONFIG_PCI) diff --git a/arch/arm/mach-kirkwood/include/mach/memory.h b/arch/arm/mach-kirkwood/include/mach/memory.h index 45431e13146..4600b44e3ad 100644 --- a/arch/arm/mach-kirkwood/include/mach/memory.h +++ b/arch/arm/mach-kirkwood/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h index bace9a681ad..f7e1b9bce34 100644 --- a/arch/arm/mach-ks8695/include/mach/memory.h +++ b/arch/arm/mach-ks8695/include/mach/memory.h @@ -18,7 +18,7 @@ /* * Physical SRAM offset. */ -#define PHYS_OFFSET KS8695_SDRAM_PA +#define PLAT_PHYS_OFFSET KS8695_SDRAM_PA #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-lh7a40x/include/mach/memory.h b/arch/arm/mach-lh7a40x/include/mach/memory.h index edb8f5faf5d..f77bde80fe4 100644 --- a/arch/arm/mach-lh7a40x/include/mach/memory.h +++ b/arch/arm/mach-lh7a40x/include/mach/memory.h @@ -17,7 +17,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) /* * Sparsemem version of the above diff --git a/arch/arm/mach-loki/include/mach/memory.h b/arch/arm/mach-loki/include/mach/memory.h index 2ed7e6e732c..66366657a87 100644 --- a/arch/arm/mach-loki/include/mach/memory.h +++ b/arch/arm/mach-loki/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-lpc32xx/include/mach/memory.h b/arch/arm/mach-lpc32xx/include/mach/memory.h index 044e1acecbe..a647dd624af 100644 --- a/arch/arm/mach-lpc32xx/include/mach/memory.h +++ b/arch/arm/mach-lpc32xx/include/mach/memory.h @@ -22,6 +22,6 @@ /* * Physical DRAM offset of bank 0 */ -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/mach-mmp/include/mach/memory.h b/arch/arm/mach-mmp/include/mach/memory.h index bdb21d70714..d68b50a2d6a 100644 --- a/arch/arm/mach-mmp/include/mach/memory.h +++ b/arch/arm/mach-mmp/include/mach/memory.h @@ -9,6 +9,6 @@ #ifndef __ASM_MACH_MEMORY_H #define __ASM_MACH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif /* __ASM_MACH_MEMORY_H */ diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c index e7a76eff57d..08fcd40a8cb 100644 --- a/arch/arm/mach-msm/board-msm7x27.c +++ b/arch/arm/mach-msm/board-msm7x27.c @@ -132,7 +132,7 @@ static void __init msm7x2x_map_io(void) MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, @@ -142,7 +142,7 @@ MACHINE_END MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, @@ -152,7 +152,7 @@ MACHINE_END MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, @@ -162,7 +162,7 @@ MACHINE_END MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index 6f3b9735e97..25db8fd71a7 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -26,11 +26,11 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/memory.h> #include <asm/setup.h> #include <mach/gpio.h> #include <mach/board.h> -#include <mach/memory.h> #include <mach/msm_iomap.h> #include <mach/dma.h> @@ -85,7 +85,7 @@ static void __init msm7x30_map_io(void) MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, @@ -95,7 +95,7 @@ MACHINE_END MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, @@ -105,7 +105,7 @@ MACHINE_END MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index 6dde8185205..15c2bbd2ef8 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -118,7 +118,7 @@ static void __init qsd8x50_init(void) MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = qsd8x50_map_io, .init_irq = qsd8x50_init_irq, .init_machine = qsd8x50_init, @@ -128,7 +128,7 @@ MACHINE_END MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = qsd8x50_map_io, .init_irq = qsd8x50_init_irq, .init_machine = qsd8x50_init, diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c index 8919ffb1719..83604f526f0 100644 --- a/arch/arm/mach-msm/board-sapphire.c +++ b/arch/arm/mach-msm/board-sapphire.c @@ -107,7 +107,7 @@ MACHINE_START(SAPPHIRE, "sapphire") /* Maintainer: Brian Swetland <swetland@google.com> */ #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .fixup = sapphire_fixup, .map_io = sapphire_map_io, .init_irq = sapphire_init_irq, diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index 070e17d237f..176875df241 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -18,15 +18,15 @@ /* physical offset of RAM */ #if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A) -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #elif defined(CONFIG_ARCH_QSD8X50) -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #elif defined(CONFIG_ARCH_MSM7X30) -#define PHYS_OFFSET UL(0x00200000) +#define PLAT_PHYS_OFFSET UL(0x00200000) #elif defined(CONFIG_ARCH_MSM8X60) -#define PHYS_OFFSET UL(0x40200000) +#define PLAT_PHYS_OFFSET UL(0x40200000) #else -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) #endif #endif diff --git a/arch/arm/mach-mv78xx0/include/mach/memory.h b/arch/arm/mach-mv78xx0/include/mach/memory.h index e663042d307..a648c51f2e4 100644 --- a/arch/arm/mach-mv78xx0/include/mach/memory.h +++ b/arch/arm/mach-mv78xx0/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-mx3/mach-kzm_arm11_01.c b/arch/arm/mach-mx3/mach-kzm_arm11_01.c index a5f3eb24e4d..df1a6ce8e3e 100644 --- a/arch/arm/mach-mx3/mach-kzm_arm11_01.c +++ b/arch/arm/mach-mx3/mach-kzm_arm11_01.c @@ -27,6 +27,7 @@ #include <asm/irq.h> #include <asm/mach-types.h> +#include <asm/memory.h> #include <asm/setup.h> #include <asm/mach/arch.h> #include <asm/mach/irq.h> @@ -36,7 +37,6 @@ #include <mach/clock.h> #include <mach/common.h> #include <mach/iomux-mx3.h> -#include <mach/memory.h> #include "devices-imx31.h" #include "devices.h" diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c index 0a19e7567c0..d8a65daa8be 100644 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c @@ -464,7 +464,14 @@ static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent) return 0; } +#ifdef CONFIG_CLK_DEBUG +#define __INIT_CLK_DEBUG(n) .name = #n, +#else +#define __INIT_CLK_DEBUG(n) +#endif + static struct clk main_bus_clk = { + __INIT_CLK_DEBUG(main_bus_clk) .parent = &pll2_sw_clk, .set_parent = _clk_main_bus_set_parent, }; @@ -728,23 +735,28 @@ static unsigned long _clk_ddr_hf_get_rate(struct clk *clk) /* External high frequency clock */ static struct clk ckih_clk = { + __INIT_CLK_DEBUG(ckih_clk) .get_rate = get_high_reference_clock_rate, }; static struct clk ckih2_clk = { + __INIT_CLK_DEBUG(ckih2_clk) .get_rate = get_ckih2_reference_clock_rate, }; static struct clk osc_clk = { + __INIT_CLK_DEBUG(osc_clk) .get_rate = get_oscillator_reference_clock_rate, }; /* External low frequency (32kHz) clock */ static struct clk ckil_clk = { + __INIT_CLK_DEBUG(ckil_clk) .get_rate = get_low_reference_clock_rate, }; static struct clk pll1_main_clk = { + __INIT_CLK_DEBUG(pll1_main_clk) .parent = &osc_clk, .get_rate = clk_pll_get_rate, .enable = _clk_pll_enable, @@ -762,6 +774,7 @@ static struct clk pll1_main_clk = { /* PLL1 SW supplies to ARM core */ static struct clk pll1_sw_clk = { + __INIT_CLK_DEBUG(pll1_sw_clk) .parent = &pll1_main_clk, .set_parent = _clk_pll1_sw_set_parent, .get_rate = clk_pll1_sw_get_rate, @@ -769,6 +782,7 @@ static struct clk pll1_sw_clk = { /* PLL2 SW supplies to AXI/AHB/IP buses */ static struct clk pll2_sw_clk = { + __INIT_CLK_DEBUG(pll2_sw_clk) .parent = &osc_clk, .get_rate = clk_pll_get_rate, .set_rate = _clk_pll_set_rate, @@ -779,6 +793,7 @@ static struct clk pll2_sw_clk = { /* PLL3 SW supplies to serial clocks like USB, SSI, etc. */ static struct clk pll3_sw_clk = { + __INIT_CLK_DEBUG(pll3_sw_clk) .parent = &osc_clk, .set_rate = _clk_pll_set_rate, .get_rate = clk_pll_get_rate, @@ -788,6 +803,7 @@ static struct clk pll3_sw_clk = { /* PLL4 SW supplies to LVDS Display Bridge(LDB) */ static struct clk mx53_pll4_sw_clk = { + __INIT_CLK_DEBUG(mx53_pll4_clk) .parent = &osc_clk, .set_rate = _clk_pll_set_rate, .enable = _clk_pll_enable, @@ -796,22 +812,26 @@ static struct clk mx53_pll4_sw_clk = { /* Low-power Audio Playback Mode clock */ static struct clk lp_apm_clk = { + __INIT_CLK_DEBUG(lp_apm_clk) .parent = &osc_clk, .set_parent = _clk_lp_apm_set_parent, }; static struct clk periph_apm_clk = { + __INIT_CLK_DEBUG(periph_apm_clk) .parent = &pll1_sw_clk, .set_parent = _clk_periph_apm_set_parent, }; static struct clk cpu_clk = { + __INIT_CLK_DEBUG(cpu_clk) .parent = &pll1_sw_clk, .get_rate = clk_cpu_get_rate, .set_rate = clk_cpu_set_rate, }; static struct clk ahb_clk = { + __INIT_CLK_DEBUG(ahb_clk) .parent = &main_bus_clk, .get_rate = clk_ahb_get_rate, .set_rate = _clk_ahb_set_rate, @@ -819,6 +839,7 @@ static struct clk ahb_clk = { }; static struct clk iim_clk = { + __INIT_CLK_DEBUG(iim_clk) .parent = &ipg_clk, .enable_reg = MXC_CCM_CCGR0, .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET, @@ -826,17 +847,20 @@ static struct clk iim_clk = { /* Main IP interface clock for access to registers */ static struct clk ipg_clk = { + __INIT_CLK_DEBUG(ipg_clk) .parent = &ahb_clk, .get_rate = clk_ipg_get_rate, }; static struct clk ipg_perclk = { + __INIT_CLK_DEBUG(ipg_clk) .parent = &lp_apm_clk, .get_rate = clk_ipg_per_get_rate, .set_parent = _clk_ipg_per_set_parent, }; static struct clk ahb_max_clk = { + __INIT_CLK_DEBUG(ahb_max_clk) .parent = &ahb_clk, .enable_reg = MXC_CCM_CCGR0, .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET, @@ -845,6 +869,7 @@ static struct clk ahb_max_clk = { }; static struct clk aips_tz1_clk = { + __INIT_CLK_DEBUG(aips_tz1_clk) .parent = &ahb_clk, .secondary = &ahb_max_clk, .enable_reg = MXC_CCM_CCGR0, @@ -854,6 +879,7 @@ static struct clk aips_tz1_clk = { }; static struct clk aips_tz2_clk = { + __INIT_CLK_DEBUG(aips_tz2_clk) .parent = &ahb_clk, .secondary = &ahb_max_clk, .enable_reg = MXC_CCM_CCGR0, @@ -863,11 +889,13 @@ static struct clk aips_tz2_clk = { }; static struct clk gpt_32k_clk = { + __INIT_CLK_DEBUG(gpt_32k_clk) .id = 0, .parent = &ckil_clk, }; static struct clk kpp_clk = { + __INIT_CLK_DEBUG(kpp_clk) .id = 0, }; @@ -876,6 +904,7 @@ static struct clk dummy_clk = { }; static struct clk emi_slow_clk = { + __INIT_CLK_DEBUG(emi_slow_clk) .parent = &pll2_sw_clk, .enable_reg = MXC_CCM_CCGR5, .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, @@ -989,6 +1018,7 @@ static struct clk mipi_hsp_clk = { #define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \ static struct clk name = { \ + __INIT_CLK_DEBUG(name) \ .id = i, \ .enable_reg = er, \ .enable_shift = es, \ @@ -1004,6 +1034,7 @@ static struct clk mipi_hsp_clk = { #define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \ static struct clk name = { \ + __INIT_CLK_DEBUG(name) \ .id = i, \ .enable_reg = er, \ .enable_shift = es, \ @@ -1082,6 +1113,7 @@ CLK_GET_RATE(uart, 1, UART) CLK_SET_PARENT(uart, 1, UART) static struct clk uart_root_clk = { + __INIT_CLK_DEBUG(uart_root_clk) .parent = &pll2_sw_clk, .get_rate = clk_uart_get_rate, .set_parent = clk_uart_set_parent, @@ -1092,6 +1124,7 @@ CLK_GET_RATE(usboh3, 1, USBOH3) CLK_SET_PARENT(usboh3, 1, USBOH3) static struct clk usboh3_clk = { + __INIT_CLK_DEBUG(usboh3_clk) .parent = &pll2_sw_clk, .get_rate = clk_usboh3_get_rate, .set_parent = clk_usboh3_set_parent, @@ -1137,6 +1170,7 @@ CLK_GET_RATE(ecspi, 2, CSPI) CLK_SET_PARENT(ecspi, 1, CSPI) static struct clk ecspi_main_clk = { + __INIT_CLK_DEBUG(ecspi_main_clk) .parent = &pll3_sw_clk, .get_rate = clk_ecspi_get_rate, .set_parent = clk_ecspi_set_parent, @@ -1152,7 +1186,8 @@ CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2) CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2) #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \ - static struct clk name = { \ +static struct clk name = { \ + __INIT_CLK_DEBUG(name) \ .id = i, \ .enable_reg = er, \ .enable_shift = es, \ @@ -1372,8 +1407,10 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, ckih2_reference = ckih2; oscillator_reference = osc; - for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++) + for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++) { clkdev_add(&mx51_lookups[i]); + clk_debug_register(mx51_lookups[i].clk); + } clk_tree_init(); diff --git a/arch/arm/mach-netx/include/mach/memory.h b/arch/arm/mach-netx/include/mach/memory.h index 9a363f297f9..59561496c36 100644 --- a/arch/arm/mach-netx/include/mach/memory.h +++ b/arch/arm/mach-netx/include/mach/memory.h @@ -20,7 +20,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/mach-nomadik/include/mach/memory.h b/arch/arm/mach-nomadik/include/mach/memory.h index 1e5689d98ec..d3325211ba6 100644 --- a/arch/arm/mach-nomadik/include/mach/memory.h +++ b/arch/arm/mach-nomadik/include/mach/memory.h @@ -23,6 +23,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ns9xxx/include/mach/memory.h b/arch/arm/mach-ns9xxx/include/mach/memory.h index 6107193adbf..5c65aee6e7a 100644 --- a/arch/arm/mach-ns9xxx/include/mach/memory.h +++ b/arch/arm/mach-ns9xxx/include/mach/memory.h @@ -19,6 +19,6 @@ #define NS9XXX_CS2STAT_LENGTH UL(0x1000) #define NS9XXX_CS3STAT_LENGTH UL(0x1000) -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-nuc93x/include/mach/memory.h b/arch/arm/mach-nuc93x/include/mach/memory.h index 323ab0db3f7..ef9864b002a 100644 --- a/arch/arm/mach-nuc93x/include/mach/memory.h +++ b/arch/arm/mach-nuc93x/include/mach/memory.h @@ -16,6 +16,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index ba6009f2767..cb2d3a64858 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o +# CPUFREQ driver +obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o + # Power Management obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S index 6a0fa046236..62856044eb6 100644 --- a/arch/arm/mach-omap1/include/mach/debug-macro.S +++ b/arch/arm/mach-omap1/include/mach/debug-macro.S @@ -17,6 +17,9 @@ #include <plat/serial.h> +#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET) +#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET) + .pushsection .data omap_uart_phys: .word 0x0 omap_uart_virt: .word 0x0 @@ -33,7 +36,7 @@ omap_uart_virt: .word 0x0 /* Use omap_uart_phys/virt if already configured */ 9: mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? - ldreq \rp, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rp, =omap_uart_phys @ MMU enabled add \rv, \rp, #4 @ omap_uart_virt ldr \rp, [\rp, #0] @@ -46,7 +49,7 @@ omap_uart_virt: .word 0x0 mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? ldreq \rp, =OMAP_UART_INFO @ MMU not enabled - ldrne \rp, =__phys_to_virt(OMAP_UART_INFO) @ MMU enabled + ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled ldr \rp, [\rp, #0] /* Select the UART to use based on the UART1 scratchpad value */ @@ -73,7 +76,7 @@ omap_uart_virt: .word 0x0 98: add \rp, \rp, #0xff000000 @ phys base mrc p15, 0, \rv, c1, c0 tst \rv, #1 @ MMU enabled? - ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rv, =omap_uart_phys @ MMU enabled str \rp, [\rv, #0] sub \rp, \rp, #0xff000000 @ phys base diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c new file mode 100644 index 00000000000..64faf3f28d9 --- /dev/null +++ b/arch/arm/mach-omap1/omap1-cpufreq.c @@ -0,0 +1,176 @@ +/* + * OMAP1 cpufreq driver + * + * CPU frequency scaling for OMAP + * + * Copyright (C) 2005 Nokia Corporation + * Written by Tony Lindgren <tony@atomide.com> + * + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Updated to support OMAP3 + * Rajendra Nayak <rnayak@ti.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. + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/cpufreq.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/opp.h> + +#include <asm/system.h> + +#include <plat/clock.h> +#include <plat/omap-pm.h> + +#include <mach/hardware.h> + +#define VERY_HI_RATE 900000000 + +static struct cpufreq_frequency_table *freq_table; +static struct clk *mpu_clk; + +static int omap_verify_speed(struct cpufreq_policy *policy) +{ + if (freq_table) + return cpufreq_frequency_table_verify(policy, freq_table); + + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + return 0; +} + +static unsigned int omap_getspeed(unsigned int cpu) +{ + unsigned long rate; + + if (cpu) + return 0; + + rate = clk_get_rate(mpu_clk) / 1000; + return rate; +} + +static int omap_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + int ret = 0; + + /* Ensure desired rate is within allowed range. Some govenors + * (ondemand) will just pass target_freq=0 to get the minimum. */ + if (target_freq < policy->min) + target_freq = policy->min; + if (target_freq > policy->max) + target_freq = policy->max; + + freqs.old = omap_getspeed(0); + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; + freqs.cpu = 0; + + if (freqs.old == freqs.new) + return ret; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + +#ifdef CONFIG_CPU_FREQ_DEBUG + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); +#endif + ret = clk_set_rate(mpu_clk, freqs.new * 1000); + if (!ret) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return ret; +} + +static int __init omap_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + + mpu_clk = clk_get(NULL, "mpu"); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + + if (policy->cpu != 0) + return -EINVAL; + + policy->cur = policy->min = policy->max = omap_getspeed(0); + + clk_init_cpufreq_table(&freq_table); + + if (freq_table) { + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!result) + cpufreq_frequency_table_get_attr(freq_table, + policy->cpu); + } else { + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, + VERY_HI_RATE) / 1000; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = omap_getspeed(0); + + /* FIXME: what's the actual transition time? */ + policy->cpuinfo.transition_latency = 300 * 1000; + + return 0; +} + +static int omap_cpu_exit(struct cpufreq_policy *policy) +{ + clk_exit_cpufreq_table(&freq_table); + clk_put(mpu_clk); + return 0; +} + +static struct freq_attr *omap_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver omap_driver = { + .flags = CPUFREQ_STICKY, + .verify = omap_verify_speed, + .target = omap_target, + .get = omap_getspeed, + .init = omap_cpu_init, + .exit = omap_cpu_exit, + .name = "omap1", + .attr = omap_cpufreq_attr, +}; + +static int __init omap_cpufreq_init(void) +{ + return cpufreq_register_driver(&omap_driver); +} + +static void __exit omap_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&omap_driver); +} + +MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs"); +MODULE_LICENSE("GPL"); +module_init(omap_cpufreq_init); +module_exit(omap_cpufreq_exit); diff --git a/arch/arm/mach-omap1/pm.h b/arch/arm/mach-omap1/pm.h index 56a647986ae..cd926dcb5e7 100644 --- a/arch/arm/mach-omap1/pm.h +++ b/arch/arm/mach-omap1/pm.h @@ -123,9 +123,9 @@ extern void allow_idle_sleep(void); extern void omap1_pm_idle(void); extern void omap1_pm_suspend(void); -extern void omap7xx_cpu_suspend(unsigned short, unsigned short); -extern void omap1510_cpu_suspend(unsigned short, unsigned short); -extern void omap1610_cpu_suspend(unsigned short, unsigned short); +extern void omap7xx_cpu_suspend(unsigned long, unsigned long); +extern void omap1510_cpu_suspend(unsigned long, unsigned long); +extern void omap1610_cpu_suspend(unsigned long, unsigned long); extern void omap7xx_idle_loop_suspend(void); extern void omap1510_idle_loop_suspend(void); extern void omap1610_idle_loop_suspend(void); diff --git a/arch/arm/mach-omap1/sleep.S b/arch/arm/mach-omap1/sleep.S index ef771ce8b03..c875bdc902c 100644 --- a/arch/arm/mach-omap1/sleep.S +++ b/arch/arm/mach-omap1/sleep.S @@ -58,6 +58,7 @@ */ #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) + .align 3 ENTRY(omap7xx_cpu_suspend) @ save registers on stack @@ -137,6 +138,7 @@ ENTRY(omap7xx_cpu_suspend_sz) #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */ #ifdef CONFIG_ARCH_OMAP15XX + .align 3 ENTRY(omap1510_cpu_suspend) @ save registers on stack @@ -211,6 +213,7 @@ ENTRY(omap1510_cpu_suspend_sz) #endif /* CONFIG_ARCH_OMAP15XX */ #if defined(CONFIG_ARCH_OMAP16XX) + .align 3 ENTRY(omap1610_cpu_suspend) @ save registers on stack diff --git a/arch/arm/mach-omap1/sram.S b/arch/arm/mach-omap1/sram.S index 7724e520d07..692587d07ea 100644 --- a/arch/arm/mach-omap1/sram.S +++ b/arch/arm/mach-omap1/sram.S @@ -18,6 +18,7 @@ /* * Reprograms ULPD and CKCTL. */ + .align 3 ENTRY(omap1_sram_reprogram_clock) stmfd sp!, {r0 - r12, lr} @ save registers on stack diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 1c0c2b02d87..898fffe0e9c 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -56,13 +56,16 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o endif +# CPUFREQ driver +obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o + # Power Management ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \ - cpuidle34xx.o pm_bus.o -obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o + cpuidle34xx.o pm_bus.o dvfs.o +obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o dvfs.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o @@ -242,3 +245,6 @@ obj-y += $(smc91x-m) $(smc91x-y) smsc911x-$(CONFIG_SMSC911X) := gpmc-smsc911x.o obj-y += $(smsc911x-m) $(smsc911x-y) + +disp-$(CONFIG_OMAP2_DSS) := display.o +obj-y += $(disp-m) $(disp-y) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index d4e41ef86aa..33ff4f6ba12 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -307,22 +307,8 @@ static struct omap_dss_board_info sdp3430_dss_data = { .default_device = &sdp3430_lcd_device, }; -static struct platform_device sdp3430_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &sdp3430_dss_data, - }, -}; - -static struct regulator_consumer_supply sdp3430_vdda_dac_supply = { - .supply = "vdda_dac", - .dev = &sdp3430_dss_device.dev, -}; - -static struct platform_device *sdp3430_devices[] __initdata = { - &sdp3430_dss_device, -}; +static struct regulator_consumer_supply sdp3430_vdda_dac_supply = + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); static struct omap_board_config_kernel sdp3430_config[] __initdata = { }; @@ -546,10 +532,8 @@ static struct regulator_init_data sdp3430_vdac = { /* VPLL2 for digital video outputs */ static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { - { - .supply = "vdds_dsi", - .dev = &sdp3430_dss_device.dev, - } + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), }; static struct regulator_init_data sdp3430_vpll2 = { @@ -801,7 +785,7 @@ static void __init omap_3430sdp_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3430_i2c_init(); - platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices)); + omap_display_init(&sdp3430_dss_data); if (omap_rev() > OMAP3430_REV_ES1_0) ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV2; else diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index 62645640f5e..8d05fc94f51 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -25,6 +25,24 @@ #include "board-flash.h" #include "mux.h" #include "sdram-hynix-h8mbx00u0mer-0em.h" +#include "pm.h" + +static struct cpuidle_params omap36xx_cpuidle_params_table[] = { + /* C1 */ + {1, 74, 78, 152}, + /* C2 */ + {0, 165, 90, 255}, + /* C3 */ + {1, 163, 180, 345}, + /* C4 */ + {0, 2852, 605, 3457}, + /* C5 */ + {1, 800, 366, 2120}, + /* C6 */ + {0, 4080, 801, 4881}, + /* C7 */ + {1, 4300, 8794, 159000}, +}; #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) @@ -212,6 +230,7 @@ static void __init omap_sdp_init(void) board_flash_init(sdp_flash_partitions, chip_sel_sdp); enable_board_wakeup_source(); usb_ehci_init(&ehci_pdata); + omap3_pm_init_cpuidle(omap36xx_cpuidle_params_table); } MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board") diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 10d60b7743c..548f5245eda 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -378,24 +378,12 @@ static struct omap_dss_board_info am3517_evm_dss_data = { .default_device = &am3517_evm_lcd_device, }; -static struct platform_device am3517_evm_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &am3517_evm_dss_data, - }, -}; - /* * Board initialization */ static struct omap_board_config_kernel am3517_evm_config[] __initdata = { }; -static struct platform_device *am3517_evm_devices[] __initdata = { - &am3517_evm_dss_device, -}; - static void __init am3517_evm_init_irq(void) { omap_board_config = am3517_evm_config; @@ -495,9 +483,7 @@ static void __init am3517_evm_init(void) omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); am3517_evm_i2c_init(); - platform_add_devices(am3517_evm_devices, - ARRAY_SIZE(am3517_evm_devices)); - + omap_display_init(&am3517_evm_dss_data); omap_serial_init(); /* Configure GPIO for EHCI port */ diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index dac14161066..2e9265ef3f9 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -401,14 +401,6 @@ static struct omap_dss_board_info cm_t35_dss_data = { .default_device = &cm_t35_dvi_device, }; -static struct platform_device cm_t35_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &cm_t35_dss_data, - }, -}; - static struct omap2_mcspi_device_config tdo24m_mcspi_config = { .turbo_mode = 0, .single_channel = 1, /* 0: slave, 1: master */ @@ -468,7 +460,7 @@ static void __init cm_t35_init_display(void) msleep(50); gpio_set_value(lcd_en_gpio, 1); - err = platform_device_register(&cm_t35_dss_device); + err = omap_display_init(&cm_t35_dss_data); if (err) { pr_err("CM-T35: failed to register DSS device\n"); goto err_dev_reg; @@ -495,15 +487,11 @@ static struct regulator_consumer_supply cm_t35_vsim_supply = { .supply = "vmmc_aux", }; -static struct regulator_consumer_supply cm_t35_vdac_supply = { - .supply = "vdda_dac", - .dev = &cm_t35_dss_device.dev, -}; +static struct regulator_consumer_supply cm_t35_vdac_supply = + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); -static struct regulator_consumer_supply cm_t35_vdvi_supply = { - .supply = "vdvi", - .dev = &cm_t35_dss_device.dev, -}; +static struct regulator_consumer_supply cm_t35_vdvi_supply = + REGULATOR_SUPPLY("vdvi", "omap_display"); /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ static struct regulator_init_data cm_t35_vmmc1 = { diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 9a2a31e011c..d277143c425 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -195,16 +195,8 @@ static struct omap_dss_board_info devkit8000_dss_data = { .default_device = &devkit8000_lcd_device, }; -static struct platform_device devkit8000_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &devkit8000_dss_data, - }, -}; - static struct regulator_consumer_supply devkit8000_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); static uint32_t board_keymap[] = { KEY(0, 0, KEY_1), @@ -285,8 +277,10 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = { .setup = devkit8000_twl_gpio_setup, }; -static struct regulator_consumer_supply devkit8000_vpll1_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), +}; /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ static struct regulator_init_data devkit8000_vmmc1 = { @@ -327,8 +321,8 @@ static struct regulator_init_data devkit8000_vpll1 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &devkit8000_vpll1_supply, + .num_consumer_supplies = ARRAY_SIZE(devkit8000_vpll1_supplies), + .consumer_supplies = devkit8000_vpll1_supplies, }; /* VAUX4 for ads7846 and nubs */ @@ -575,7 +569,6 @@ static void __init omap_dm9000_init(void) } static struct platform_device *devkit8000_devices[] __initdata = { - &devkit8000_dss_device, &leds_gpio, &keys_gpio, &omap_dm9000_dev, @@ -797,6 +790,7 @@ static void __init devkit8000_init(void) platform_add_devices(devkit8000_devices, ARRAY_SIZE(devkit8000_devices)); + omap_display_init(&devkit8000_dss_data); spi_register_board_info(devkit8000_spi_board_info, ARRAY_SIZE(devkit8000_spi_board_info)); diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 3be85a1f55f..dfbe3a1eaa8 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -485,17 +485,9 @@ static struct omap_dss_board_info igep2_dss_data = { .default_device = &igep2_dvi_device, }; -static struct platform_device igep2_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &igep2_dss_data, - }, -}; - -static struct regulator_consumer_supply igep2_vpll2_supply = { - .supply = "vdds_dsi", - .dev = &igep2_dss_device.dev, +static struct regulator_consumer_supply igep2_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), }; static struct regulator_init_data igep2_vpll2 = { @@ -509,8 +501,8 @@ static struct regulator_init_data igep2_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &igep2_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(igep2_vpll2_supplies), + .consumer_supplies = igep2_vpll2_supplies, }; static void __init igep2_display_init(void) @@ -521,7 +513,6 @@ static void __init igep2_display_init(void) } static struct platform_device *igep2_devices[] __initdata = { - &igep2_dss_device, &igep2_vwlan_device, }; @@ -697,6 +688,7 @@ static void __init igep2_init(void) /* Register I2C busses and drivers */ igep2_i2c_init(); platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices)); + omap_display_init(&igep2_dss_data); omap_serial_init(); usb_musb_init(&musb_board_data); usb_ehci_init(&ehci_pdata); diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 46d814ab565..caf6c8aedac 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -228,19 +228,13 @@ static struct omap_dss_board_info beagle_dss_data = { .default_device = &beagle_dvi_device, }; -static struct platform_device beagle_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &beagle_dss_data, - }, -}; - static struct regulator_consumer_supply beagle_vdac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); -static struct regulator_consumer_supply beagle_vdvi_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply beagle_vdvi_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), +}; static void __init beagle_display_init(void) { @@ -427,8 +421,8 @@ static struct regulator_init_data beagle_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vdvi_supply, + .num_consumer_supplies = ARRAY_SIZE(beagle_vdvi_supplies), + .consumer_supplies = beagle_vdvi_supplies, }; static struct twl4030_usb_data beagle_usb_data = { @@ -550,7 +544,6 @@ static void __init omap3_beagle_init_irq(void) static struct platform_device *omap3_beagle_devices[] __initdata = { &leds_gpio, &keys_gpio, - &beagle_dss_device, }; static void __init omap3beagle_flash_init(void) @@ -617,6 +610,7 @@ static void __init omap3_beagle_init(void) omap3_beagle_i2c_init(); platform_add_devices(omap3_beagle_devices, ARRAY_SIZE(omap3_beagle_devices)); + omap_display_init(&beagle_dss_data); omap_serial_init(); omap_mux_init_gpio(170, OMAP_PIN_INPUT); diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 323c3809ce3..0c56b9edf65 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -328,14 +328,6 @@ static struct omap_dss_board_info omap3_evm_dss_data = { .default_device = &omap3_evm_lcd_device, }; -static struct platform_device omap3_evm_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &omap3_evm_dss_data, - }, -}; - static struct regulator_consumer_supply omap3evm_vmmc1_supply = { .supply = "vmmc", }; @@ -500,10 +492,8 @@ static struct twl4030_codec_data omap3evm_codec_data = { .audio = &omap3evm_audio_data, }; -static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = { - .supply = "vdda_dac", - .dev = &omap3_evm_dss_device.dev, -}; +static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); /* VDAC for DSS driving S-Video */ static struct regulator_init_data omap3_evm_vdac = { @@ -521,8 +511,10 @@ static struct regulator_init_data omap3_evm_vdac = { }; /* VPLL2 for digital video outputs */ -static struct regulator_consumer_supply omap3_evm_vpll2_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply omap3_evm_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), +}; static struct regulator_init_data omap3_evm_vpll2 = { .constraints = { @@ -534,8 +526,8 @@ static struct regulator_init_data omap3_evm_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &omap3_evm_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(omap3_evm_vpll2_supplies), + .consumer_supplies = omap3_evm_vpll2_supplies, }; static struct twl4030_platform_data omap3evm_twldata = { @@ -634,10 +626,6 @@ static void __init omap3_evm_init_irq(void) omap_init_irq(); } -static struct platform_device *omap3_evm_devices[] __initdata = { - &omap3_evm_dss_device, -}; - static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = { .port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN, @@ -675,7 +663,7 @@ static void __init omap3_evm_init(void) omap3_evm_i2c_init(); - platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices)); + omap_display_init(&omap3_evm_dss_data); spi_register_board_info(omap3evm_spi_board_info, ARRAY_SIZE(omap3evm_spi_board_info)); diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 0b34beded11..b430d2bce8f 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -253,14 +253,6 @@ static struct omap_dss_board_info pandora_dss_data = { .default_device = &pandora_lcd_device, }; -static struct platform_device pandora_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &pandora_dss_data, - }, -}; - static void pandora_wl1251_init_card(struct mmc_card *card) { /* @@ -350,11 +342,12 @@ static struct regulator_consumer_supply pandora_vmmc3_supply = REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.2"); static struct regulator_consumer_supply pandora_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); static struct regulator_consumer_supply pandora_vdds_supplies[] = { - REGULATOR_SUPPLY("vdds_sdi", "omapdss"), - REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_sdi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), }; static struct regulator_consumer_supply pandora_vcc_lcd_supply = @@ -677,7 +670,6 @@ fail: static struct platform_device *omap3pandora_devices[] __initdata = { &pandora_leds_gpio, &pandora_keys_gpio, - &pandora_dss_device, &pandora_vwlan_device, }; @@ -712,6 +704,7 @@ static void __init omap3pandora_init(void) pandora_wl1251_init(); platform_add_devices(omap3pandora_devices, ARRAY_SIZE(omap3pandora_devices)); + omap_display_init(&pandora_dss_data); omap_serial_init(); spi_register_board_info(omap3pandora_spi_board_info, ARRAY_SIZE(omap3pandora_spi_board_info)); diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 2a2dad447e8..b5e868044c1 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -240,14 +240,6 @@ static struct omap_dss_board_info omap3_stalker_dss_data = { .default_device = &omap3_stalker_dvi_device, }; -static struct platform_device omap3_stalker_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &omap3_stalker_dss_data, - }, -}; - static struct regulator_consumer_supply omap3stalker_vmmc1_supply = { .supply = "vmmc", }; @@ -448,10 +440,8 @@ static struct twl4030_codec_data omap3stalker_codec_data = { .audio = &omap3stalker_audio_data, }; -static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply = { - .supply = "vdda_dac", - .dev = &omap3_stalker_dss_device.dev, -}; +static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply = + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); /* VDAC for DSS driving S-Video */ static struct regulator_init_data omap3_stalker_vdac = { @@ -469,9 +459,9 @@ static struct regulator_init_data omap3_stalker_vdac = { }; /* VPLL2 for digital video outputs */ -static struct regulator_consumer_supply omap3_stalker_vpll2_supply = { - .supply = "vdds_dsi", - .dev = &omap3_stalker_lcd_device.dev, +static struct regulator_consumer_supply omap3_stalker_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), }; static struct regulator_init_data omap3_stalker_vpll2 = { @@ -485,8 +475,8 @@ static struct regulator_init_data omap3_stalker_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &omap3_stalker_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(omap3_stalker_vpll2_supplies), + .consumer_supplies = omap3_stalker_vpll2_supplies, }; static struct twl4030_platform_data omap3stalker_twldata = { @@ -604,7 +594,6 @@ static void __init omap3_stalker_init_irq(void) } static struct platform_device *omap3_stalker_devices[] __initdata = { - &omap3_stalker_dss_device, &keys_gpio, }; @@ -644,6 +633,7 @@ static void __init omap3_stalker_init(void) platform_add_devices(omap3_stalker_devices, ARRAY_SIZE(omap3_stalker_devices)); + omap_display_init(&omap3_stalker_dss_data); spi_register_board_info(omap3stalker_spi_board_info, ARRAY_SIZE(omap3stalker_spi_board_info)); diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index e944025d5ef..b09d23925f4 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -37,6 +37,7 @@ #include <plat/common.h> #include <plat/usb.h> #include <plat/mmc.h> +#include <plat/panel-generic-dpi.h> #include "timer-gp.h" #include "hsmmc.h" @@ -76,6 +77,60 @@ static struct platform_device *panda_devices[] __initdata = { &leds_gpio, }; +/* Display DVI */ +#define PANDA_DVI_TFP410_POWER_DOWN_GPIO 0 + +static int panda_enable_dvi(struct omap_dss_device *dssdev) +{ + gpio_set_value(dssdev->reset_gpio, 1); + return 0; +} + +static void panda_disable_dvi(struct omap_dss_device *dssdev) +{ + gpio_set_value(dssdev->reset_gpio, 0); +} + +/* Using generic display panel */ +static struct panel_generic_dpi_data dvi_panel = { + .name = "generic", + .platform_enable = panda_enable_dvi, + .platform_disable = panda_disable_dvi, +}; + +struct omap_dss_device panda_dvi_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .driver_name = "generic_dpi_panel", + .data = &dvi_panel, + .phy.dpi.data_lines = 24, + .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, + .channel = OMAP_DSS_CHANNEL_LCD2, +}; + +int __init panda_dvi_init(void) +{ + int r; + + /* Requesting TFP410 DVI GPIO and disabling it, at bootup */ + r = gpio_request_one(panda_dvi_device.reset_gpio, + GPIOF_OUT_INIT_LOW, "DVI PD"); + if (r) + pr_err("Failed to get DVI powerdown GPIO\n"); + + return r; +} + +static struct omap_dss_device *panda_dss_devices[] = { + &panda_dvi_device, +}; + +static struct omap_dss_board_info panda_dss_data = { + .num_devices = ARRAY_SIZE(panda_dss_devices), + .devices = panda_dss_devices, + .default_device = &panda_dvi_device, +}; + static void __init omap4_panda_init_irq(void) { omap2_init_common_infrastructure(); @@ -375,6 +430,17 @@ static struct i2c_board_info __initdata omap4_panda_i2c_boardinfo[] = { .platform_data = &omap4_panda_twldata, }, }; + +/* + * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM + * is connected as I2C slave device, and can be accessed at address 0x50 + */ +static struct i2c_board_info __initdata panda_i2c_eeprom[] = { + { + I2C_BOARD_INFO("eeprom", 0x50), + }, +}; + static int __init omap4_panda_i2c_init(void) { /* @@ -384,13 +450,76 @@ static int __init omap4_panda_i2c_init(void) omap_register_i2c_bus(1, 400, omap4_panda_i2c_boardinfo, ARRAY_SIZE(omap4_panda_i2c_boardinfo)); omap_register_i2c_bus(2, 400, NULL, 0); - omap_register_i2c_bus(3, 400, NULL, 0); + /* + * Bus 3 is attached to the DVI port where devices like the pico DLP + * projector don't work reliably with 400kHz + */ + omap_register_i2c_bus(3, 100, panda_i2c_eeprom, + ARRAY_SIZE(panda_i2c_eeprom)); omap_register_i2c_bus(4, 400, NULL, 0); return 0; } #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { + /* gpio 0 - TFP410 PD */ + OMAP4_MUX(KPD_COL1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3), + /* dispc2_data23 */ + OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data22 */ + OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data21 */ + OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data20 */ + OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data19 */ + OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data18 */ + OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data15 */ + OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data14 */ + OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data13 */ + OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data12 */ + OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data11 */ + OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data10 */ + OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data9 */ + OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data16 */ + OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data17 */ + OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_hsync */ + OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_pclk */ + OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_vsync */ + OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_de */ + OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data8 */ + OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data7 */ + OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data6 */ + OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data5 */ + OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data4 */ + OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data3 */ + OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data2 */ + OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data1 */ + OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), + /* dispc2_data0 */ + OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5), { .reg_offset = OMAP_MUX_TERMINATOR }, }; #else @@ -400,6 +529,7 @@ static struct omap_board_mux board_mux[] __initdata = { static void __init omap4_panda_init(void) { int package = OMAP_PACKAGE_CBS; + int err; if (omap_rev() == OMAP4430_REV_ES1_0) package = OMAP_PACKAGE_CBL; @@ -411,6 +541,11 @@ static void __init omap4_panda_init(void) omap4_twl6030_hsmmc_init(mmc); omap4_ehci_init(); usb_musb_init(&musb_board_data); + + /* Enabling DVI Display */ + err = panda_dvi_init(); + if (!err) + omap_display_init(&panda_dss_data); } static void __init omap4_panda_map_io(void) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index cb26e5d8268..90c256879ed 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -28,6 +28,7 @@ #include <linux/platform_device.h> #include <linux/i2c/twl.h> #include <linux/regulator/machine.h> +#include <linux/spi/spi.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -41,10 +42,14 @@ #include <plat/board.h> #include <plat/common.h> +#include <plat/display.h> +#include <plat/panel-generic-dpi.h> #include <mach/gpio.h> #include <plat/gpmc.h> #include <mach/hardware.h> #include <plat/nand.h> +#include <plat/mcspi.h> +#include <plat/mux.h> #include <plat/usb.h> #include "mux.h" @@ -68,8 +73,6 @@ #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) -#include <plat/mcspi.h> -#include <linux/spi/spi.h> #include <linux/spi/ads7846.h> static struct omap2_mcspi_device_config ads7846_mcspi_config = { @@ -94,18 +97,6 @@ static struct ads7846_platform_data ads7846_config = { .keep_vref_on = 1, }; -static struct spi_board_info overo_spi_board_info[] __initdata = { - { - .modalias = "ads7846", - .bus_num = 1, - .chip_select = 0, - .max_speed_hz = 1500000, - .controller_data = &ads7846_mcspi_config, - .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN), - .platform_data = &ads7846_config, - } -}; - static void __init overo_ads7846_init(void) { if ((gpio_request(OVERO_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) && @@ -115,9 +106,6 @@ static void __init overo_ads7846_init(void) printk(KERN_ERR "could not obtain gpio for ADS7846_PENDOWN\n"); return; } - - spi_register_board_info(overo_spi_board_info, - ARRAY_SIZE(overo_spi_board_info)); } #else @@ -233,6 +221,140 @@ static inline void __init overo_init_smsc911x(void) static inline void __init overo_init_smsc911x(void) { return; } #endif +/* DSS */ +static int lcd_enabled; +static int dvi_enabled; + +#define OVERO_GPIO_LCD_EN 144 +#define OVERO_GPIO_LCD_BL 145 + +static void __init overo_display_init(void) +{ + if ((gpio_request(OVERO_GPIO_LCD_EN, "OVERO_GPIO_LCD_EN") == 0) && + (gpio_direction_output(OVERO_GPIO_LCD_EN, 1) == 0)) + gpio_export(OVERO_GPIO_LCD_EN, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_LCD_EN\n"); + + if ((gpio_request(OVERO_GPIO_LCD_BL, "OVERO_GPIO_LCD_BL") == 0) && + (gpio_direction_output(OVERO_GPIO_LCD_BL, 1) == 0)) + gpio_export(OVERO_GPIO_LCD_BL, 0); + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_LCD_BL\n"); +} + +static int overo_panel_enable_dvi(struct omap_dss_device *dssdev) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + dvi_enabled = 1; + + return 0; +} + +static void overo_panel_disable_dvi(struct omap_dss_device *dssdev) +{ + dvi_enabled = 0; +} + +static struct panel_generic_dpi_data dvi_panel = { + .name = "generic", + .platform_enable = overo_panel_enable_dvi, + .platform_disable = overo_panel_disable_dvi, +}; + +static struct omap_dss_device overo_dvi_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .driver_name = "generic_dpi_panel", + .data = &dvi_panel, + .phy.dpi.data_lines = 24, + .reset_gpio = -EINVAL, +}; + +static struct omap_dss_device overo_tv_device = { + .name = "tv", + .driver_name = "venc", + .type = OMAP_DISPLAY_TYPE_VENC, + .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, +}; + +static int overo_panel_enable_lcd(struct omap_dss_device *dssdev) +{ + if (dvi_enabled) { + printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); + return -EINVAL; + } + + gpio_set_value(OVERO_GPIO_LCD_EN, 1); + gpio_set_value(OVERO_GPIO_LCD_BL, 1); + lcd_enabled = 1; + return 0; +} + +static void overo_panel_disable_lcd(struct omap_dss_device *dssdev) +{ + gpio_set_value(OVERO_GPIO_LCD_EN, 0); + gpio_set_value(OVERO_GPIO_LCD_BL, 0); + lcd_enabled = 0; +} + +#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ + defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) +static struct omap_dss_device overo_lcd35_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "lcd35", + .driver_name = "lgphilips_lb035q02_panel", + .phy.dpi.data_lines = 24, + .platform_enable = overo_panel_enable_lcd, + .platform_disable = overo_panel_disable_lcd, +}; +#endif + +#if defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) || \ + defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C_MODULE) +static struct omap_dss_device overo_lcd43_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "lcd43", + .driver_name = "samsung_lte_panel", + .phy.dpi.data_lines = 24, + .platform_enable = overo_panel_enable_lcd, + .platform_disable = overo_panel_disable_lcd, +}; +#endif + +static struct omap_dss_device *overo_dss_devices[] = { + &overo_dvi_device, + &overo_tv_device, +#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ + defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) + &overo_lcd35_device, +#endif +#if defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) || \ + defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C_MODULE) + &overo_lcd43_device, +#endif +}; + +static struct omap_dss_board_info overo_dss_data = { + .num_devices = ARRAY_SIZE(overo_dss_devices), + .devices = overo_dss_devices, + .default_device = &overo_dvi_device, +}; + +static struct regulator_consumer_supply overo_vdda_dac_supply = + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); + +static struct regulator_consumer_supply overo_vdds_supplies[] = { + REGULATOR_SUPPLY("vdds_sdi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), +}; + static struct mtd_partition overo_nand_partitions[] = { { .name = "xloader", @@ -358,6 +480,37 @@ static struct regulator_init_data overo_vmmc1 = { .consumer_supplies = &overo_vmmc1_supply, }; +/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */ +static struct regulator_init_data overo_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &overo_vdda_dac_supply, +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_init_data overo_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(overo_vdds_supplies), + .consumer_supplies = &overo_vdds_supplies, +}; + +/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */ + static struct twl4030_codec_audio_data overo_audio_data = { .audio_mclk = 26000000, }; @@ -376,6 +529,8 @@ static struct twl4030_platform_data overo_twldata = { .usb = &overo_usb_data, .codec = &overo_codec_data, .vmmc1 = &overo_vmmc1, + .vdac = &overo_vdac, + .vpll2 = &overo_vpll2, }; static struct i2c_board_info __initdata overo_i2c_boardinfo[] = { @@ -396,33 +551,47 @@ static int __init overo_i2c_init(void) return 0; } -static struct platform_device overo_lcd_device = { - .name = "overo_lcd", - .id = -1, -}; - -static struct omap_lcd_config overo_lcd_config __initdata = { - .ctrl_name = "internal", +static struct spi_board_info overo_spi_board_info[] __initdata = { +#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ + defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) + { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN), + .platform_data = &ads7846_config, + }, +#endif +#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ + defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) + { + .modalias = "lgphilips_lb035q02_panel-spi", + .bus_num = 1, + .chip_select = 1, + .max_speed_hz = 500000, + .mode = SPI_MODE_3, + }, +#endif }; -static struct omap_board_config_kernel overo_config[] __initdata = { - { OMAP_TAG_LCD, &overo_lcd_config }, -}; +static int __init overo_spi_init(void) +{ + overo_ads7846_init(); + spi_register_board_info(overo_spi_board_info, + ARRAY_SIZE(overo_spi_board_info)); + return 0; +} static void __init overo_init_irq(void) { - omap_board_config = overo_config; - omap_board_config_size = ARRAY_SIZE(overo_config); omap2_init_common_infrastructure(); omap2_init_common_devices(mt46h32m32lf6_sdrc_params, mt46h32m32lf6_sdrc_params); omap_init_irq(); } -static struct platform_device *overo_devices[] __initdata = { - &overo_lcd_device, -}; - static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN, .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, @@ -450,13 +619,14 @@ static void __init overo_init(void) { omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); overo_i2c_init(); - platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices)); + omap_display_init(&overo_dss_data); omap_serial_init(); overo_flash_init(); usb_musb_init(&musb_board_data); usb_ehci_init(&ehci_pdata); - overo_ads7846_init(); + overo_spi_init(); overo_init_smsc911x(); + overo_display_init(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index e75e240cad6..b783854476b 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -360,11 +360,11 @@ static struct regulator_consumer_supply rx51_vio_supplies[] = { }; static struct regulator_consumer_supply rx51_vaux1_consumers[] = { - REGULATOR_SUPPLY("vdds_sdi", "omapdss"), + REGULATOR_SUPPLY("vdds_sdi", "omap_display"), }; static struct regulator_consumer_supply rx51_vdac_supply[] = { - REGULATOR_SUPPLY("vdda_dac", "omapdss"), + REGULATOR_SUPPLY("vdda_dac", "omap_venc"), }; static struct regulator_init_data rx51_vaux1 = { diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c index acd670054d9..89a66db8b77 100644 --- a/arch/arm/mach-omap2/board-rx51-video.c +++ b/arch/arm/mach-omap2/board-rx51-video.c @@ -66,18 +66,6 @@ static struct omap_dss_board_info rx51_dss_board_info = { .default_device = &rx51_lcd_device, }; -struct platform_device rx51_display_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &rx51_dss_board_info, - }, -}; - -static struct platform_device *rx51_video_devices[] __initdata = { - &rx51_display_device, -}; - static int __init rx51_video_init(void) { if (!machine_is_nokia_rx51()) @@ -95,8 +83,7 @@ static int __init rx51_video_init(void) gpio_direction_output(RX51_LCD_RESET_GPIO, 1); - platform_add_devices(rx51_video_devices, - ARRAY_SIZE(rx51_video_devices)); + omap_display_init(&rx51_dss_board_info); return 0; } diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c index 6bcd43657ae..37b84c2b850 100644 --- a/arch/arm/mach-omap2/board-zoom-display.c +++ b/arch/arm/mach-omap2/board-zoom-display.c @@ -130,14 +130,6 @@ static struct omap_dss_board_info zoom_dss_data = { .default_device = &zoom_lcd_device, }; -static struct platform_device zoom_dss_device = { - .name = "omapdss", - .id = -1, - .dev = { - .platform_data = &zoom_dss_data, - }, -}; - static struct omap2_mcspi_device_config dss_lcd_mcspi_config = { .turbo_mode = 1, .single_channel = 1, /* 0: slave, 1: master */ @@ -153,14 +145,9 @@ static struct spi_board_info nec_8048_spi_board_info[] __initdata = { }, }; -static struct platform_device *zoom_display_devices[] __initdata = { - &zoom_dss_device, -}; - void __init zoom_display_init(void) { - platform_add_devices(zoom_display_devices, - ARRAY_SIZE(zoom_display_devices)); + omap_display_init(&zoom_dss_data); spi_register_board_info(nec_8048_spi_board_info, ARRAY_SIZE(nec_8048_spi_board_info)); zoom_lcd_panel_init(); diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index e0e040f34c6..780a99c4359 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -226,11 +226,13 @@ static struct omap2_hsmmc_info mmc[] = { {} /* Terminator */ }; -static struct regulator_consumer_supply zoom_vpll2_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply zoom_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omap_display"), + REGULATOR_SUPPLY("vdds_dsi", "omap_dsi1"), +}; static struct regulator_consumer_supply zoom_vdda_dac_supply = - REGULATOR_SUPPLY("vdda_dac", "omapdss"); + REGULATOR_SUPPLY("vdda_dac", "omap_venc"); static struct regulator_init_data zoom_vpll2 = { .constraints = { @@ -241,8 +243,8 @@ static struct regulator_init_data zoom_vpll2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &zoom_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(zoom_vpll2_supplies), + .consumer_supplies = zoom_vpll2_supplies, }; static struct regulator_init_data zoom_vdac = { diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c index e26754c24ee..6bd364afe66 100644 --- a/arch/arm/mach-omap2/board-zoom.c +++ b/arch/arm/mach-omap2/board-zoom.c @@ -30,6 +30,24 @@ #include "mux.h" #include "sdram-micron-mt46h32m32lf-6.h" #include "sdram-hynix-h8mbx00u0mer-0em.h" +#include "pm.h" + +static struct cpuidle_params omap36xx_cpuidle_params_table[] = { + /* C1 */ + {1, 74, 78, 152}, + /* C2 */ + {0, 165, 90, 255}, + /* C3 */ + {1, 163, 180, 345}, + /* C4 */ + {0, 2852, 605, 3457}, + /* C5 */ + {1, 800, 366, 2120}, + /* C6 */ + {0, 4080, 801, 4881}, + /* C7 */ + {1, 4300, 8794, 159000}, +}; #define ZOOM3_EHCI_RESET_GPIO 64 @@ -126,6 +144,7 @@ static void __init omap_zoom_init(void) usb_ehci_init(&ehci_pdata); } + omap3_pm_init_cpuidle(omap36xx_cpuidle_params_table); board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS); zoom_debugboard_init(); diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 0a992bc8d0d..dd9fd87a731 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1786,10 +1786,10 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "gfx_2d_fck", &gfx_2d_fck, CK_242X), CLK(NULL, "gfx_ick", &gfx_ick, CK_242X), /* DSS domain clocks */ - CLK("omapdss", "ick", &dss_ick, CK_242X), - CLK("omapdss", "dss1_fck", &dss1_fck, CK_242X), - CLK("omapdss", "dss2_fck", &dss2_fck, CK_242X), - CLK("omapdss", "tv_fck", &dss_54m_fck, CK_242X), + CLK("omap_dss", "ick", &dss_ick, CK_242X), + CLK("omap_dss", "fck", &dss1_fck, CK_242X), + CLK("omap_dss", "sys_clk", &dss2_fck, CK_242X), + CLK("omap_dss", "tv_clk", &dss_54m_fck, CK_242X), /* L3 domain clocks */ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_242X), CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_242X), @@ -1799,6 +1799,7 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_242X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X), + CLK(NULL, "cpu_ck", &virt_prcm_set, CK_242X), /* general l4 interface ck, multi-parent functional clk */ CLK(NULL, "gpt1_ick", &gpt1_ick, CK_242X), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_242X), diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index c047dcd007e..c698c1c8778 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -1890,10 +1890,10 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), /* DSS domain clocks */ - CLK("omapdss", "ick", &dss_ick, CK_243X), - CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X), - CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X), - CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X), + CLK("omap_dss", "ick", &dss_ick, CK_243X), + CLK("omap_dss", "fck", &dss1_fck, CK_243X), + CLK("omap_dss", "sys_clk", &dss2_fck, CK_243X), + CLK("omap_dss", "tv_clk", &dss_54m_fck, CK_243X), /* L3 domain clocks */ CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X), CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X), @@ -1903,6 +1903,7 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X), + CLK(NULL, "cpu_ck", &virt_prcm_set, CK_243X), /* general l4 interface ck, multi-parent functional clk */ CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X), diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 403a4a1d3f9..b1c484cd891 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3224,6 +3224,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_3XXX), CLK(NULL, "sys_clkout1", &sys_clkout1, CK_3XXX), CLK(NULL, "dpll1_ck", &dpll1_ck, CK_3XXX), + CLK(NULL, "cpu_ck", &dpll1_ck, CK_3XXX), CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_3XXX), CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX), CLK(NULL, "dpll2_ck", &dpll2_ck, CK_34XX | CK_36XX), @@ -3357,13 +3358,13 @@ static struct omap_clk omap3xxx_clks[] = { CLK("omap_rng", "ick", &rng_ick, CK_34XX | CK_36XX), CLK(NULL, "sha11_ick", &sha11_ick, CK_34XX | CK_36XX), CLK(NULL, "des1_ick", &des1_ick, CK_34XX | CK_36XX), - CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), - CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("omapdss", "tv_fck", &dss_tv_fck, CK_3XXX), - CLK("omapdss", "video_fck", &dss_96m_fck, CK_3XXX), - CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_3XXX), - CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1), - CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("omap_dss", "fck", &dss1_alwon_fck_3430es1, CK_3430ES1), + CLK("omap_dss", "fck", &dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("omap_dss", "tv_clk", &dss_tv_fck, CK_3XXX), + CLK("omap_dss", "video_clk", &dss_96m_fck, CK_3XXX), + CLK("omap_dss", "sys_clk", &dss2_alwon_fck, CK_3XXX), + CLK("omap_dss", "ick", &dss_ick_3430es1, CK_3430ES1), + CLK("omap_dss", "ick", &dss_ick_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "cam_mclk", &cam_mclk, CK_34XX | CK_36XX), CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index de9ec8ddd2a..95f2c4c9503 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3057,6 +3057,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, CK_443X), CLK(NULL, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, CK_443X), CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_443X), + CLK(NULL, "cpu_ck", &dpll_mpu_ck, CK_443X), CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_443X), CLK(NULL, "per_hs_clk_div_ck", &per_hs_clk_div_ck, CK_443X), CLK(NULL, "per_hsd_byp_clk_mux_ck", &per_hsd_byp_clk_mux_ck, CK_443X), @@ -3106,11 +3107,16 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X), CLK(NULL, "dmic_fck", &dmic_fck, CK_443X), CLK(NULL, "dsp_fck", &dsp_fck, CK_443X), - CLK(NULL, "dss_sys_clk", &dss_sys_clk, CK_443X), - CLK(NULL, "dss_tv_clk", &dss_tv_clk, CK_443X), - CLK(NULL, "dss_dss_clk", &dss_dss_clk, CK_443X), - CLK(NULL, "dss_48mhz_clk", &dss_48mhz_clk, CK_443X), - CLK(NULL, "dss_fck", &dss_fck, CK_443X), + CLK("omap_dss", "sys_clk", &dss_sys_clk, CK_443X), + CLK("omap_dss", "tv_clk", &dss_tv_clk, CK_443X), + CLK("omap_dss", "dss_clk", &dss_dss_clk, CK_443X), + CLK("omap_dss", "video_clk", &dss_48mhz_clk, CK_443X), + CLK("omap_dss", "fck", &dss_fck, CK_443X), + /* + * On OMAP4, DSS ick is a dummy clock; this is needed for compatibility + * with OMAP2/3. + */ + CLK("omap_dss", "ick", &dummy_ck, CK_443X), CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X), CLK(NULL, "emif1_fck", &emif1_fck, CK_443X), CLK(NULL, "emif2_fck", &emif2_fck, CK_443X), diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index f7b22a16f38..bc9bcac2ec0 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -51,6 +51,7 @@ struct omap3_processor_cx { u8 valid; + u8 enabled; u8 type; u32 sleep_latency; u32 wakeup_latency; @@ -139,19 +140,9 @@ static int omap3_enter_idle(struct cpuidle_device *dev, if (omap_irq_pending() || need_resched()) goto return_sleep_time; - if (cx->type == OMAP3_STATE_C1) { - pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); - pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); - } - /* Execute ARM wfi */ omap_sram_idle(); - if (cx->type == OMAP3_STATE_C1) { - pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); - pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); - } - return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); @@ -283,8 +274,18 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, select_state: dev->last_state = new_state; + + if (new_state == dev->safe_state) { + pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); + pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); + } ret = omap3_enter_idle(dev, new_state); + if (new_state == dev->safe_state) { + pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); + pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); + } + /* Restore original PER state if it was modified */ if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_saved_state); @@ -309,12 +310,13 @@ void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state) for (i = OMAP3_STATE_C1; i < OMAP3_MAX_STATES; i++) { struct omap3_processor_cx *cx = &omap3_power_states[i]; - - if ((cx->mpu_state >= mpu_deepest_state) && - (cx->core_state >= core_deepest_state)) { - cx->valid = 1; - } else { - cx->valid = 0; + if (cx->enabled) { + if ((cx->mpu_state >= mpu_deepest_state) && + (cx->core_state >= core_deepest_state)) { + cx->valid = 1; + } else { + cx->valid = 0; + } } } } @@ -355,6 +357,8 @@ void omap_init_power_states(void) /* C1 . MPU WFI + Core active */ omap3_power_states[OMAP3_STATE_C1].valid = cpuidle_params_table[OMAP3_STATE_C1].valid; + omap3_power_states[OMAP3_STATE_C1].enabled = + cpuidle_params_table[OMAP3_STATE_C1].valid; omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; omap3_power_states[OMAP3_STATE_C1].sleep_latency = cpuidle_params_table[OMAP3_STATE_C1].sleep_latency; @@ -369,6 +373,8 @@ void omap_init_power_states(void) /* C2 . MPU WFI + Core inactive */ omap3_power_states[OMAP3_STATE_C2].valid = cpuidle_params_table[OMAP3_STATE_C2].valid; + omap3_power_states[OMAP3_STATE_C2].enabled = + cpuidle_params_table[OMAP3_STATE_C2].valid; omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; omap3_power_states[OMAP3_STATE_C2].sleep_latency = cpuidle_params_table[OMAP3_STATE_C2].sleep_latency; @@ -384,6 +390,8 @@ void omap_init_power_states(void) /* C3 . MPU CSWR + Core inactive */ omap3_power_states[OMAP3_STATE_C3].valid = cpuidle_params_table[OMAP3_STATE_C3].valid; + omap3_power_states[OMAP3_STATE_C3].enabled = + cpuidle_params_table[OMAP3_STATE_C3].valid; omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; omap3_power_states[OMAP3_STATE_C3].sleep_latency = cpuidle_params_table[OMAP3_STATE_C3].sleep_latency; @@ -399,6 +407,8 @@ void omap_init_power_states(void) /* C4 . MPU OFF + Core inactive */ omap3_power_states[OMAP3_STATE_C4].valid = cpuidle_params_table[OMAP3_STATE_C4].valid; + omap3_power_states[OMAP3_STATE_C4].enabled = + cpuidle_params_table[OMAP3_STATE_C4].valid; omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; omap3_power_states[OMAP3_STATE_C4].sleep_latency = cpuidle_params_table[OMAP3_STATE_C4].sleep_latency; @@ -414,6 +424,8 @@ void omap_init_power_states(void) /* C5 . MPU CSWR + Core CSWR*/ omap3_power_states[OMAP3_STATE_C5].valid = cpuidle_params_table[OMAP3_STATE_C5].valid; + omap3_power_states[OMAP3_STATE_C5].enabled = + cpuidle_params_table[OMAP3_STATE_C5].valid; omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; omap3_power_states[OMAP3_STATE_C5].sleep_latency = cpuidle_params_table[OMAP3_STATE_C5].sleep_latency; @@ -429,6 +441,8 @@ void omap_init_power_states(void) /* C6 . MPU OFF + Core CSWR */ omap3_power_states[OMAP3_STATE_C6].valid = cpuidle_params_table[OMAP3_STATE_C6].valid; + omap3_power_states[OMAP3_STATE_C6].enabled = + cpuidle_params_table[OMAP3_STATE_C6].valid; omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6; omap3_power_states[OMAP3_STATE_C6].sleep_latency = cpuidle_params_table[OMAP3_STATE_C6].sleep_latency; @@ -444,6 +458,8 @@ void omap_init_power_states(void) /* C7 . MPU OFF + Core OFF */ omap3_power_states[OMAP3_STATE_C7].valid = cpuidle_params_table[OMAP3_STATE_C7].valid; + omap3_power_states[OMAP3_STATE_C7].enabled = + cpuidle_params_table[OMAP3_STATE_C7].valid; omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7; omap3_power_states[OMAP3_STATE_C7].sleep_latency = cpuidle_params_table[OMAP3_STATE_C7].sleep_latency; @@ -463,6 +479,7 @@ void omap_init_power_states(void) */ if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) { omap3_power_states[OMAP3_STATE_C7].valid = 0; + omap3_power_states[OMAP3_STATE_C7].enabled = 0; cpuidle_params_table[OMAP3_STATE_C7].valid = 0; WARN_ONCE(1, "%s: core off state C7 disabled due to i583\n", __func__); diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c new file mode 100644 index 00000000000..cc7b4f3070d --- /dev/null +++ b/arch/arm/mach-omap2/display.c @@ -0,0 +1,103 @@ +/* + * OMAP2plus display device setup / initialization. + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Senthilvadivu Guruswamy + * Sumit Semwal + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <plat/display.h> +#include <plat/omap_hwmod.h> +#include <plat/omap_device.h> + +static struct platform_device omap_display_device = { + .name = "omap_display", + .id = -1, + .dev = { + .platform_data = NULL, + }, +}; + +static struct omap_device_pm_latency omap_dss_latency[] = { + [0] = { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int __init omap_display_init(struct omap_dss_board_info + *board_data) +{ + int r = 0; + struct omap_hwmod *oh; + struct omap_device *od; + int i; + struct omap_display_platform_data pdata; + + /* + * omap: valid DSS hwmod names + * omap2,3,4: dss_core, dss_dispc, dss_rfbi, dss_venc + * omap3,4: dss_dsi1 + * omap4: dss_dsi2, dss_hdmi + */ + char *oh_name[] = {"dss_core", "dss_dispc", "dss_rfbi", "dss_venc", "dss_dsi1", + "dss_dsi2", "dss_hdmi"}; + char *dev_name[] = {"omap_dss", "omap_dispc", "omap_rfbi", "omap_venc", "omap_dsi1", + "omap_dsi2", "omap_hdmi"}; + int oh_count; + + memset(&pdata, 0, sizeof(pdata)); + + if (cpu_is_omap24xx()) + oh_count = ARRAY_SIZE(oh_name) - 3; + /* last 3 hwmod dev in oh_name are not available for omap2 */ + else if (cpu_is_omap44xx()) + oh_count = ARRAY_SIZE(oh_name); + else + oh_count = ARRAY_SIZE(oh_name) - 2; + /* last 2 hwmod dev in oh_name are not available for omap3 */ + + + pdata.board_data = board_data; + pdata.board_data->get_last_off_on_transaction_id = NULL; + + for (i = 0; i < oh_count; i++) { + oh = omap_hwmod_lookup(oh_name[i]); + if (!oh) { + pr_err("Could not look up %s\n", oh_name[i]); + return -ENODEV; + } + od = omap_device_build(dev_name[i], -1, oh, &pdata, + sizeof(struct omap_display_platform_data), + omap_dss_latency, + ARRAY_SIZE(omap_dss_latency), 0); + + if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n", + oh_name[i])) + return -ENODEV; + } + omap_display_device.dev.platform_data = board_data; + + r = platform_device_register(&omap_display_device); + if (r < 0) + printk(KERN_ERR "Unable to register OMAP-Display device\n"); + + return r; +} diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c new file mode 100644 index 00000000000..fb9215cb927 --- /dev/null +++ b/arch/arm/mach-omap2/dvfs.c @@ -0,0 +1,770 @@ +/* + * OMAP3/OMAP4 DVFS Management Routines + * + * Author: Vishwanath BS <vishwanath.bs@ti.com> + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Vishwanath BS <vishwanath.bs@ti.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. + */ + +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/plist.h> +#include <linux/slab.h> +#include <linux/opp.h> +#include <plat/common.h> +#include <plat/voltage.h> +#include <plat/omap_device.h> +#include <plat/smartreflex.h> + +/** + * struct omap_dev_user_list - Structure maitain userlist per device + * + * @dev: The device requesting for a particular frequency + * @node: The list head entry + * @freq: frequency being requested + * + * Using this structure, user list (requesting dev * and frequency) for + * each device is maintained. This is how we can have different devices + * at different frequencies (to support frequency locking and throttling). + * Even if one of the devices in a given vdd has locked it's frequency, + * other's can still scale their frequency using this list. + * If no one has placed a frequency request for a device, then device is + * set to the frequency from it's opp table. + */ +struct omap_dev_user_list { + struct device *dev; + struct plist_node node; + u32 freq; +}; + +/** + * struct omap_vdd_dev_list - Device list per vdd + * + * @dev: The device belonging to a particular vdd + * @node: The list head entry + */ +struct omap_vdd_dev_list { + struct device *dev; + struct list_head node; + struct plist_head user_list; + spinlock_t user_lock; /* spinlock for plist */ +}; + +/** + * struct omap_vdd_user_list - The per vdd user list + * + * @dev: The device asking for the vdd to be set at a particular + * voltage + * @node: The list head entry + * @volt: The voltage requested by the device <dev> + */ +struct omap_vdd_user_list { + struct device *dev; + struct plist_node node; + u32 volt; +}; + +/** + * struct omap_vdd_dvfs_info - The per vdd dvfs info + * + * @user_lock: spinlock for plist operations + * @user_list: The vdd user list + * @scaling_mutex: Mutex for protecting dvfs data structures for a vdd + * @voltdm: Voltage domains for which dvfs info stored + * + * This is a fundamental structure used to store all the required + * DVFS related information for a vdd. + */ +struct omap_vdd_dvfs_info { + spinlock_t user_lock; /* spin lock */ + struct plist_head user_list; + struct mutex scaling_mutex; /* dvfs mutex */ + struct voltagedomain *voltdm; + struct list_head dev_list; + struct device vdd_device; +}; + +static struct omap_vdd_dvfs_info *omap_dvfs_info_list; +static int omap_nr_vdd; + +static struct voltagedomain omap3_vdd[] = { + { + .name = "mpu", + }, + { + .name = "core", + }, +}; + +static struct voltagedomain omap4_vdd[] = { + { + .name = "mpu", + }, + { + .name = "iva", + }, + { + .name = "core", + }, +}; + +static int omap_dvfs_voltage_scale(struct omap_vdd_dvfs_info *dvfs_info); + +static int __init omap_dvfs_init(void); + +static struct omap_vdd_dvfs_info *get_dvfs_info(struct voltagedomain *voltdm) +{ + int i; + if (!voltdm || !omap_dvfs_info_list) + return NULL; + + for (i = 0; i < omap_nr_vdd; i++) + if (omap_dvfs_info_list[i].voltdm == voltdm) + return &omap_dvfs_info_list[i]; + + pr_warning("%s: unable find dvfs info for vdd %s\n", + __func__, voltdm->name); + return NULL; +} + +/** + * omap_dvfs_find_voltage() - search for given voltage + * @dev: device pointer associated with the opp type + * @volt: voltage to search for + * + * Searches for exact match in the opp list and returns handle to the matching + * opp if found, else returns ERR_PTR in case of error and should be handled + * using IS_ERR. If there are multiple opps with same voltage, it will return + * the first available entry. + */ +static struct opp *omap_dvfs_find_voltage(struct device *dev, + unsigned long volt) +{ + struct opp *opp = ERR_PTR(-ENODEV); + unsigned long f = 0; + + do { + opp = opp_find_freq_ceil(dev, &f); + if (IS_ERR(opp)) + break; + if (opp_get_voltage(opp) >= volt) + break; + f++; + } while (1); + + return opp; +} + +/** + * omap_dvfs_add_vdd_user() - Add a voltage request + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @dev: device making the request + * @volt: requesting voltage in uV + * + * Adds the given devices' voltage request into corresponding + * vdd's omap_vdd_dvfs_info user list (plist). This list is used + * to find the maximum voltage request for a given vdd. + * + * Returns 0 on success. + */ +static int omap_dvfs_add_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, + struct device *dev, unsigned long volt) +{ + struct omap_vdd_user_list *user = NULL, *temp_user; + struct plist_node *node; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_warn(dev, "%s: VDD specified does not exist!\n", __func__); + return -EINVAL; + } + + mutex_lock(&dvfs_info->scaling_mutex); + + plist_for_each_entry(temp_user, &dvfs_info->user_list, node) { + if (temp_user->dev == dev) { + user = temp_user; + break; + } + } + + if (!user) { + user = kzalloc(sizeof(struct omap_vdd_user_list), GFP_KERNEL); + if (!user) { + dev_err(dev, "%s: Unable to creat a new user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + mutex_unlock(&dvfs_info->scaling_mutex); + return -ENOMEM; + } + user->dev = dev; + } else { + plist_del(&user->node, &dvfs_info->user_list); + } + + plist_node_init(&user->node, volt); + plist_add(&user->node, &dvfs_info->user_list); + node = plist_last(&dvfs_info->user_list); + user->volt = node->prio; + + mutex_unlock(&dvfs_info->scaling_mutex); + + return 0; +} + +/** + * omap_dvfs_remove_vdd_user() - Remove a voltage request + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @dev: device making the request + * + * Removes the given devices' voltage request from corresponding + * vdd's omap_vdd_dvfs_info user list (plist). + * + * Returns 0 on success. + */ +static int omap_dvfs_remove_vdd_user(struct omap_vdd_dvfs_info *dvfs_info, + struct device *dev) +{ + struct omap_vdd_user_list *user = NULL, *temp_user; + int ret = 0; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_err(dev, "%s: VDD specified does not exist!\n", __func__); + return -EINVAL; + } + + mutex_lock(&dvfs_info->scaling_mutex); + + plist_for_each_entry(temp_user, &dvfs_info->user_list, node) { + if (temp_user->dev == dev) { + user = temp_user; + break; + } + } + + if (user) + plist_del(&user->node, &dvfs_info->user_list); + else { + dev_err(dev, "%s: Unable to find the user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + ret = -ENOMEM; + } + mutex_unlock(&dvfs_info->scaling_mutex); + + return ret; +} + +/** + * omap_dvfs_register_device - Add a device into voltage domain + * @voltdm: voltage domain to which the device is to be added + * @dev: Device to be added + * + * This API will add a given device into user_list of corresponding + * vdd's omap_vdd_dvfs_info strucure. This list is traversed to scale + * frequencies of all the devices on a given vdd. This api is called + * while hwmod db is built for an omap_device. + * + * Returns 0 on success. + */ +int omap_dvfs_register_device(struct voltagedomain *voltdm, struct device *dev) +{ + struct omap_vdd_dev_list *temp_dev; + struct omap_vdd_dvfs_info *dvfs_info = get_dvfs_info(voltdm); + + if (!voltdm || IS_ERR(voltdm) || !dvfs_info) { + dev_warn(dev, "%s: VDD specified does not exist!\n", __func__); + return -EINVAL; + } + + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + if (temp_dev->dev == dev) { + dev_warn(dev, "%s: Device already added to vdee_%s\n", + __func__, dvfs_info->voltdm->name); + return -EINVAL; + } + } + + temp_dev = kzalloc(sizeof(struct omap_vdd_dev_list), GFP_KERNEL); + if (!temp_dev) { + dev_err(dev, "%s: Unable to creat a new device for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + return -ENOMEM; + } + + /* Initialize priority ordered list */ + spin_lock_init(&temp_dev->user_lock); + plist_head_init(&temp_dev->user_list, &temp_dev->user_lock); + + temp_dev->dev = dev; + list_add(&temp_dev->node, &dvfs_info->dev_list); + + return 0; +} + +/** + * omap_dvfs_add_freq_request() - add a requested device frequency + * + * + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @req_dev: device making the request + * @target_dev: target device for which frequency request is being made + * @freq: target device frequency + * + * This API adds a requested frequency into target's device frequency list. + * + * Returns 0 on success. + */ +static int omap_dvfs_add_freq_request(struct omap_vdd_dvfs_info *dvfs_info, + struct device *req_dev, struct device *target_dev, unsigned long freq) +{ + struct omap_dev_user_list *dev_user = NULL, *tmp_user; + struct omap_vdd_dev_list *temp_dev; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_warn(target_dev, "%s: VDD specified does not exist!\n", + __func__); + return -EINVAL; + } + + mutex_lock(&dvfs_info->scaling_mutex); + + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + if (temp_dev->dev == target_dev) + break; + } + + if (temp_dev->dev != target_dev) { + dev_warn(target_dev, "%s: target_dev does not exist!\n", + __func__); + mutex_unlock(&dvfs_info->scaling_mutex); + return -EINVAL; + } + + plist_for_each_entry(tmp_user, &temp_dev->user_list, node) { + if (tmp_user->dev == req_dev) { + dev_user = tmp_user; + break; + } + } + + if (!dev_user) { + dev_user = kzalloc(sizeof(struct omap_dev_user_list), + GFP_KERNEL); + if (!dev_user) { + dev_err(target_dev, "%s: Unable to creat a new user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + mutex_unlock(&dvfs_info->scaling_mutex); + return -ENOMEM; + } + dev_user->dev = req_dev; + } else { + plist_del(&dev_user->node, &temp_dev->user_list); + } + + plist_node_init(&dev_user->node, freq); + plist_add(&dev_user->node, &temp_dev->user_list); + + mutex_unlock(&dvfs_info->scaling_mutex); + return 0; +} + +/** + * omap_dvfs_remove_freq_request() - Remove the requested device frequency + * + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * @req_dev: device removing the request + * @target_dev: target device from which frequency request is being removed + * + * This API removes a requested frequency from target's device frequency list. + * + * Returns 0 on success. + */ + +static int omap_dvfs_remove_freq_request(struct omap_vdd_dvfs_info *dvfs_info, + struct device *req_dev, struct device *target_dev) +{ + struct omap_dev_user_list *dev_user = NULL, *tmp_user; + int ret = 0; + struct omap_vdd_dev_list *temp_dev; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + dev_warn(target_dev, "%s: VDD specified does not exist!\n", + __func__); + return -EINVAL; + } + + mutex_lock(&dvfs_info->scaling_mutex); + + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + if (temp_dev->dev == target_dev) + break; + } + + if (temp_dev->dev != target_dev) { + dev_warn(target_dev, "%s: target_dev does not exist!\n", + __func__); + mutex_unlock(&dvfs_info->scaling_mutex); + return -EINVAL; + } + + plist_for_each_entry(tmp_user, &temp_dev->user_list, node) { + if (tmp_user->dev == req_dev) { + dev_user = tmp_user; + break; + } + } + + if (dev_user) + plist_del(&dev_user->node, &temp_dev->user_list); + else { + dev_err(target_dev, "%s: Unable to remove the user for vdd_%s\n", + __func__, dvfs_info->voltdm->name); + ret = -EINVAL; + } + + return ret; +} + +/* Calculate dependency vdd voltage for given vdd voltage */ +static int calc_dep_vdd_volt(struct device *dev, + struct omap_vdd_info *main_vdd, unsigned long main_volt) +{ + struct omap_vdd_dep_info *dep_vdds; + int i, ret = 0; + + if (!main_vdd->dep_vdd_info) { + pr_debug("%s: No dependent VDD's for vdd_%s\n", + __func__, main_vdd->voltdm.name); + return 0; + } + + dep_vdds = main_vdd->dep_vdd_info; + + for (i = 0; i < main_vdd->nr_dep_vdd; i++) { + struct omap_vdd_dep_volt *volt_table = dep_vdds[i].dep_table; + int nr_volt = 0; + unsigned long dep_volt = 0, act_volt = 0; + + while (volt_table[nr_volt].main_vdd_volt != 0) { + if (volt_table[nr_volt].main_vdd_volt == main_volt) { + dep_volt = volt_table[nr_volt].dep_vdd_volt; + break; + } + nr_volt++; + } + if (!dep_volt) { + pr_warning("%s: Not able to find a matching volt for" + "vdd_%s corresponding to vdd_%s %ld volt\n", + __func__, dep_vdds[i].name, + main_vdd->voltdm.name, main_volt); + ret = -EINVAL; + continue; + } + + if (!dep_vdds[i].voltdm) + dep_vdds[i].voltdm = + omap_voltage_domain_lookup(dep_vdds[i].name); + + act_volt = dep_volt; + + /* See if dep_volt is possible for the vdd*/ + ret = omap_dvfs_add_vdd_user(get_dvfs_info(dep_vdds[i].voltdm), + dev, act_volt); + } + + return ret; +} + +/* Scale dependent VDD */ +static int scale_dep_vdd(struct omap_vdd_dvfs_info *vdd_info) +{ + struct omap_vdd_dep_info *dep_vdds; + int i; + struct omap_vdd_info *main_vdd; + struct voltagedomain *voltdm = vdd_info->voltdm; + main_vdd = container_of(voltdm, struct omap_vdd_info, voltdm); + + if (!main_vdd->dep_vdd_info) { + pr_debug("%s: No dependent VDD's for vdd_%s\n", + __func__, main_vdd->voltdm.name); + return 0; + } + + dep_vdds = main_vdd->dep_vdd_info; + + for (i = 0; i < main_vdd->nr_dep_vdd; i++) + omap_dvfs_voltage_scale(get_dvfs_info(dep_vdds[i].voltdm)); + + return 0; +} + +/** + * omap_dvfs_voltage_scale() : API to scale the devices associated with a + * voltage domain vdd voltage. + * + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * + * This API runs through the list of devices associated with the + * voltage domain and scales the device rates to the one requested + * by the user or those corresponding to the new voltage of the + * voltage domain. Target voltage is the highest voltage in the vdd_user_list. + * + * Returns 0 on success + * else the error value. + */ +static int omap_dvfs_voltage_scale(struct omap_vdd_dvfs_info *dvfs_info) +{ + unsigned long curr_volt; + int is_volt_scaled = 0; + struct omap_vdd_dev_list *temp_dev; + struct plist_node *node; + int ret = 0; + struct voltagedomain *voltdm; + unsigned long volt; + struct omap_vdd_info *vdd; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + pr_warning("%s: VDD specified does not exist!\n", __func__); + return -EINVAL; + } + + voltdm = dvfs_info->voltdm; + vdd = container_of(voltdm, struct omap_vdd_info, voltdm); + + mutex_lock(&dvfs_info->scaling_mutex); + + /* Find the highest voltage being requested */ + node = plist_last(&dvfs_info->user_list); + volt = node->prio; + + curr_volt = omap_voltage_get_nom_volt(voltdm); + + /* Disable smartreflex module across voltage and frequency scaling */ + omap_sr_disable(voltdm); + + if (curr_volt == volt) { + is_volt_scaled = 1; + } else if (curr_volt < volt) { + ret = omap_voltage_scale_vdd(voltdm, volt); + if (ret) { + pr_warning("%s: Unable to scale the %s to %ld volt\n", + __func__, voltdm->name, volt); + omap_sr_enable(voltdm); + mutex_unlock(&dvfs_info->scaling_mutex); + return ret; + } + is_volt_scaled = 1; + } + + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + struct device *dev; + struct opp *opp; + unsigned long freq; + + dev = temp_dev->dev; + if (!plist_head_empty(&temp_dev->user_list)) { + node = plist_last(&temp_dev->user_list); + freq = node->prio; + } else { + opp = omap_dvfs_find_voltage(dev, volt); + if (IS_ERR(opp)) + continue; + freq = opp_get_freq(opp); + } + + if (freq == omap_device_get_rate(dev)) { + dev_dbg(dev, "%s: Already at the requested" + "rate %ld\n", __func__, freq); + continue; + } + + ret |= omap_device_set_rate(dev, freq); + } + + if (!is_volt_scaled && !ret) + omap_voltage_scale_vdd(voltdm, volt); + + /* Enable Smartreflex module */ + omap_sr_enable(voltdm); + + mutex_unlock(&dvfs_info->scaling_mutex); + + /* calculate the voltages for dependent vdd's */ + if (calc_dep_vdd_volt(&dvfs_info->vdd_device, vdd, volt)) { + pr_warning("%s: Error in calculating dependent vdd voltages" + "for vdd_%s\n", __func__, voltdm->name); + return -EINVAL; + } + + /* Scale dependent vdds */ + scale_dep_vdd(dvfs_info); + + return 0; +} + +/** + * omap_device_scale() - Set a new rate at which the device is to operate + * @req_dev: pointer to the device requesting the scaling. + * @target_dev: pointer to the device that is to be scaled + * @rate: the rnew rate for the device. + * + * This API gets the device opp table associated with this device and + * tries putting the device to the requested rate and the voltage domain + * associated with the device to the voltage corresponding to the + * requested rate. Since multiple devices can be assocciated with a + * voltage domain this API finds out the possible voltage the + * voltage domain can enter and then decides on the final device + * rate. Return 0 on success else the error value + */ +int omap_device_scale(struct device *req_dev, struct device *target_dev, + unsigned long rate) +{ + struct opp *opp; + unsigned long volt, freq, min_freq, max_freq; + struct omap_vdd_dvfs_info *dvfs_info; + struct platform_device *pdev; + struct omap_device *od; + int ret = 0; + + pdev = container_of(target_dev, struct platform_device, dev); + od = container_of(pdev, struct omap_device, pdev); + + /* + * Figure out if the desired frquency lies between the + * maximum and minimum possible for the particular device + */ + min_freq = 0; + if (IS_ERR(opp_find_freq_ceil(target_dev, &min_freq))) { + dev_err(target_dev, "%s: Unable to find lowest opp\n", + __func__); + return -ENODEV; + } + + max_freq = ULONG_MAX; + if (IS_ERR(opp_find_freq_floor(target_dev, &max_freq))) { + dev_err(target_dev, "%s: Unable to find highest opp\n", + __func__); + return -ENODEV; + } + + if (rate < min_freq) + freq = min_freq; + else if (rate > max_freq) + freq = max_freq; + else + freq = rate; + + opp = opp_find_freq_ceil(target_dev, &freq); + if (IS_ERR(opp)) { + dev_err(target_dev, "%s: Unable to find OPP for freq%ld\n", + __func__, rate); + return -ENODEV; + } + + /* Get the voltage corresponding to the requested frequency */ + volt = opp_get_voltage(opp); + + /* + * Call into the voltage layer to get the final voltage possible + * for the voltage domain associated with the device. + */ + + if (rate) { + dvfs_info = get_dvfs_info(od->hwmods[0]->voltdm); + + ret = omap_dvfs_add_freq_request(dvfs_info, req_dev, + target_dev, freq); + if (ret) { + dev_err(target_dev, "%s: Unable to add frequency request\n", + __func__); + return ret; + } + + ret = omap_dvfs_add_vdd_user(dvfs_info, req_dev, volt); + if (ret) { + dev_err(target_dev, "%s: Unable to add voltage request\n", + __func__); + omap_dvfs_remove_freq_request(dvfs_info, req_dev, + target_dev); + return ret; + } + } else { + dvfs_info = get_dvfs_info(od->hwmods[0]->voltdm); + + ret = omap_dvfs_remove_freq_request(dvfs_info, req_dev, + target_dev); + if (ret) { + dev_err(target_dev, "%s: Unable to remove frequency request\n", + __func__); + return ret; + } + + ret = omap_dvfs_remove_vdd_user(dvfs_info, req_dev); + if (ret) { + dev_err(target_dev, "%s: Unable to remove voltage request\n", + __func__); + return ret; + } + } + + /* Do the actual scaling */ + ret = omap_dvfs_voltage_scale(dvfs_info); + if (!ret) + if (omap_device_get_rate(target_dev) >= rate) + return 0; + + return ret; +} +EXPORT_SYMBOL(omap_device_scale); + +/** + * omap_dvfs_init() - Initialize omap dvfs layer + * + * Initalizes omap dvfs layer. It basically allocates memory for + * omap_dvfs_info_list and populates voltdm pointer inside + * omap_vdd_dvfs_info structure for all the VDDs. + * + * Returns 0 on success. + */ +static int __init omap_dvfs_init() +{ + int i; + struct voltagedomain *vdd_list; + if (cpu_is_omap34xx()) { + omap_nr_vdd = 2; + vdd_list = omap3_vdd; + } else if (cpu_is_omap44xx()) { + omap_nr_vdd = 3; + vdd_list = omap4_vdd; + } else { + pr_warning("DVFS not supported\n"); + return -EINVAL; + } + + omap_dvfs_info_list = kzalloc(omap_nr_vdd * + sizeof(struct omap_vdd_dvfs_info), GFP_KERNEL); + if (!omap_dvfs_info_list) { + pr_warning("%s: Unable to allocate memory for vdd_list", + __func__); + return -ENOMEM; + } + + for (i = 0; i < omap_nr_vdd; i++) { + omap_dvfs_info_list[i].voltdm = + omap_voltage_domain_lookup(vdd_list[i].name); + /* Init the plist */ + spin_lock_init(&omap_dvfs_info_list[i].user_lock); + plist_head_init(&omap_dvfs_info_list[i].user_list, + &omap_dvfs_info_list[i].user_lock); + /* Init the DVFS mutex */ + mutex_init(&omap_dvfs_info_list[i].scaling_mutex); + /* Init the device list */ + INIT_LIST_HEAD(&omap_dvfs_info_list[i].dev_list); + } + + return 0; +} +core_initcall(omap_dvfs_init); diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S index 6a4d4136002..6049f465ec8 100644 --- a/arch/arm/mach-omap2/include/mach/debug-macro.S +++ b/arch/arm/mach-omap2/include/mach/debug-macro.S @@ -19,6 +19,9 @@ #define UART_OFFSET(addr) ((addr) & 0x00ffffff) +#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET) +#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET) + .pushsection .data omap_uart_phys: .word 0 omap_uart_virt: .word 0 @@ -36,7 +39,7 @@ omap_uart_lsr: .word 0 /* Use omap_uart_phys/virt if already configured */ 10: mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? - ldreq \rp, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rp, =omap_uart_phys @ MMU enabled add \rv, \rp, #4 @ omap_uart_virt ldr \rp, [\rp, #0] @@ -49,7 +52,7 @@ omap_uart_lsr: .word 0 mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? ldreq \rp, =OMAP_UART_INFO @ MMU not enabled - ldrne \rp, =__phys_to_virt(OMAP_UART_INFO) @ MMU enabled + ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled ldr \rp, [\rp, #0] /* Select the UART to use based on the UART1 scratchpad value */ @@ -94,7 +97,7 @@ omap_uart_lsr: .word 0 95: ldr \rp, =ZOOM_UART_BASE mrc p15, 0, \rv, c1, c0 tst \rv, #1 @ MMU enabled? - ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rv, =omap_uart_phys @ MMU enabled str \rp, [\rv, #0] ldr \rp, =ZOOM_UART_VIRT @@ -109,7 +112,7 @@ omap_uart_lsr: .word 0 98: add \rp, \rp, #0x48000000 @ phys base mrc p15, 0, \rv, c1, c0 tst \rv, #1 @ MMU enabled? - ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rv, =omap_uart_phys @ MMU enabled str \rp, [\rv, #0] sub \rp, \rp, #0x48000000 @ phys base @@ -131,7 +134,7 @@ omap_uart_lsr: .word 0 .macro busyuart,rd,rx 1001: mrc p15, 0, \rd, c1, c0 tst \rd, #1 @ MMU enabled? - ldreq \rd, =__virt_to_phys(omap_uart_lsr) @ MMU not enabled + ldreq \rd, =omap_uart_v2p(omap_uart_lsr) @ MMU disabled ldrne \rd, =omap_uart_lsr @ MMU enabled ldr \rd, [\rd, #0] ldrb \rd, [\rx, \rd] diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h index 5b0270b2893..de441c05a6a 100644 --- a/arch/arm/mach-omap2/include/mach/omap4-common.h +++ b/arch/arm/mach-omap2/include/mach/omap4-common.h @@ -17,8 +17,12 @@ * wfi used in low power code. Directly opcode is used instead * of instruction to avoid mulit-omap build break */ +#ifdef CONFIG_THUMB2_KERNEL +#define do_wfi() __asm__ __volatile__ ("wfi" : : : "memory") +#else #define do_wfi() \ __asm__ __volatile__ (".word 0xe320f003" : : : "memory") +#endif #ifdef CONFIG_CACHE_L2X0 extern void __iomem *l2cache_base; diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index 6ae937a06cc..4ee6aeca885 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -45,5 +45,5 @@ hold: ldr r12,=0x103 * should now contain the SVC stack for this core */ b secondary_startup -END(omap_secondary_startup) +ENDPROC(omap_secondary_startup) diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c new file mode 100644 index 00000000000..e982e13f2af --- /dev/null +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c @@ -0,0 +1,250 @@ +/* + * OMAP2PLUS cpufreq driver + * + * CPU frequency scaling for OMAP + * + * Copyright (C) 2005 Nokia Corporation + * Written by Tony Lindgren <tony@atomide.com> + * + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Updated to support OMAP3 + * Rajendra Nayak <rnayak@ti.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. + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/cpufreq.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/opp.h> +#include <linux/cpu.h> + +#include <asm/system.h> +#include <asm/smp_plat.h> +#include <asm/cpu.h> + +#include <plat/clock.h> +#include <plat/omap-pm.h> +#include <plat/common.h> + +#include <mach/hardware.h> +#include <plat/dvfs.h> + +#define VERY_HI_RATE 900000000 + +static struct cpufreq_frequency_table *freq_table; +static struct clk *mpu_clk; + +static int omap_verify_speed(struct cpufreq_policy *policy) +{ + if (freq_table) + return cpufreq_frequency_table_verify(policy, freq_table); + + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + return 0; +} + +static unsigned int omap_getspeed(unsigned int cpu) +{ + unsigned long rate; + + if (cpu >= NR_CPUS) + return 0; + + rate = clk_get_rate(mpu_clk) / 1000; + return rate; +} + +static int omap_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + int i, ret = 0; + struct cpufreq_freqs freqs; + struct device *mpu_dev = omap2_get_mpuss_device(); + + /* Wait untill all CPU's are initialized */ + if (is_smp() && (num_online_cpus() < NR_CPUS)) + return ret; + + /* Ensure desired rate is within allowed range. Some govenors + * (ondemand) will just pass target_freq=0 to get the minimum. */ + if (target_freq < policy->min) + target_freq = policy->min; + if (target_freq > policy->max) + target_freq = policy->max; + + freqs.old = omap_getspeed(policy->cpu); + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; + freqs.cpu = policy->cpu; + + if (freqs.old == freqs.new) + return ret; + + if (!is_smp()) { + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + goto set_freq; + } + + /* notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + +set_freq: +#ifdef CONFIG_CPU_FREQ_DEBUG + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); +#endif + + ret = omap_device_scale(mpu_dev, mpu_dev, freqs.new * 1000); + if (ret) + return ret; + freqs.new = omap_getspeed(policy->cpu); + + /* + * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies + * won't get updated when UP machine cpufreq build with + * CONFIG_SMP enabled. Below code is added only to manage that + * scenario + */ + if (!is_smp()) { + loops_per_jiffy = + cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + goto skip_lpj; + } + +#ifdef CONFIG_SMP + /* + * Note that loops_per_jiffy is not updated on SMP systems in + * cpufreq driver. So, update the per-CPU loops_per_jiffy value + * on frequency transition. We need to update all dependent cpus + */ + for_each_cpu(i, policy->cpus) + per_cpu(cpu_data, i).loops_per_jiffy = + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, + freqs.old, freqs.new); +#endif + + /* notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + +skip_lpj: + return ret; +} + +static int __init omap_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + struct device *mpu_dev; + static cpumask_var_t cpumask; + + mpu_clk = clk_get(NULL, "cpu_ck"); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + + if (policy->cpu >= NR_CPUS) + return -EINVAL; + + policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); + + mpu_dev = omap2_get_mpuss_device(); + if (!mpu_dev) { + pr_warning("%s: unable to get the mpu device\n", __func__); + return -EINVAL; + } + opp_init_cpufreq_table(mpu_dev, &freq_table); + + if (freq_table) { + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!result) + cpufreq_frequency_table_get_attr(freq_table, + policy->cpu); + } else { + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, + VERY_HI_RATE) / 1000; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = omap_getspeed(policy->cpu); + + /* + * On OMAP SMP configuartion, both processors share the voltage + * and clock. So both CPUs needs to be scaled together and hence + * needs software co-ordination. Use cpufreq affected_cpus + * interface to handle this scenario. Additional is_smp() check + * is to keep SMP_ON_UP builf working. + */ + if (is_smp()) { + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; + cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask); + cpumask_copy(policy->cpus, cpumask); + } + + /* FIXME: what's the actual transition time? */ + policy->cpuinfo.transition_latency = 300 * 1000; + + return 0; +} + +static int omap_cpu_exit(struct cpufreq_policy *policy) +{ + clk_exit_cpufreq_table(&freq_table); + clk_put(mpu_clk); + return 0; +} + +static struct freq_attr *omap_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver omap_driver = { + .flags = CPUFREQ_STICKY, + .verify = omap_verify_speed, + .target = omap_target, + .get = omap_getspeed, + .init = omap_cpu_init, + .exit = omap_cpu_exit, + .name = "omap2plus", + .attr = omap_cpufreq_attr, +}; + +static int __init omap_cpufreq_init(void) +{ + return cpufreq_register_driver(&omap_driver); +} + +static void __exit omap_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&omap_driver); +} + +MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs"); +MODULE_LICENSE("GPL"); +module_init(omap_cpufreq_init); +module_exit(omap_cpufreq_exit); diff --git a/arch/arm/mach-omap2/omap44xx-smc.S b/arch/arm/mach-omap2/omap44xx-smc.S index 1980dc31a1a..e69d37d9520 100644 --- a/arch/arm/mach-omap2/omap44xx-smc.S +++ b/arch/arm/mach-omap2/omap44xx-smc.S @@ -29,7 +29,7 @@ ENTRY(omap_smc1) dsb smc #0 ldmfd sp!, {r2-r12, pc} -END(omap_smc1) +ENDPROC(omap_smc1) ENTRY(omap_modify_auxcoreboot0) stmfd sp!, {r1-r12, lr} @@ -37,7 +37,7 @@ ENTRY(omap_modify_auxcoreboot0) dsb smc #0 ldmfd sp!, {r1-r12, pc} -END(omap_modify_auxcoreboot0) +ENDPROC(omap_modify_auxcoreboot0) ENTRY(omap_auxcoreboot_addr) stmfd sp!, {r2-r12, lr} @@ -45,7 +45,7 @@ ENTRY(omap_auxcoreboot_addr) dsb smc #0 ldmfd sp!, {r2-r12, pc} -END(omap_auxcoreboot_addr) +ENDPROC(omap_auxcoreboot_addr) ENTRY(omap_read_auxcoreboot0) stmfd sp!, {r2-r12, lr} @@ -54,4 +54,4 @@ ENTRY(omap_read_auxcoreboot0) smc #0 mov r0, r0, lsr #9 ldmfd sp!, {r2-r12, pc} -END(omap_read_auxcoreboot0) +ENDPROC(omap_read_auxcoreboot0) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index b85c630b64d..21014dee5e3 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -18,7 +18,8 @@ #include <plat/serial.h> #include <plat/i2c.h> #include <plat/gpio.h> - +#include <plat/l3_2xxx.h> +#include <plat/l4_2xxx.h> #include "omap_hwmod_common_data.h" #include "cm-regbits-24xx.h" @@ -38,6 +39,10 @@ static struct omap_hwmod omap2420_mpu_hwmod; static struct omap_hwmod omap2420_iva_hwmod; static struct omap_hwmod omap2420_l3_main_hwmod; static struct omap_hwmod omap2420_l4_core_hwmod; +static struct omap_hwmod omap2420_dss_core_hwmod; +static struct omap_hwmod omap2420_dss_dispc_hwmod; +static struct omap_hwmod omap2420_dss_rfbi_hwmod; +static struct omap_hwmod omap2420_dss_venc_hwmod; static struct omap_hwmod omap2420_wd_timer2_hwmod; static struct omap_hwmod omap2420_gpio1_hwmod; static struct omap_hwmod omap2420_gpio2_hwmod; @@ -64,6 +69,19 @@ static struct omap_hwmod_ocp_if *omap2420_l3_main_slaves[] = { &omap2420_mpu__l3_main, }; +/* DSS -> l3 */ +static struct omap_hwmod_ocp_if omap2420_dss__l3 = { + .master = &omap2420_dss_core_hwmod, + .slave = &omap2420_l3_main_hwmod, + .fw = { + .omap2 = { + .l3_perm_bit = OMAP2_L3_CORE_FW_CONNID_DSS, + .flags = OMAP_FIREWALL_L3, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* Master interfaces on the L3 interconnect */ static struct omap_hwmod_ocp_if *omap2420_l3_main_masters[] = { &omap2420_l3_main__l4_core, @@ -470,6 +488,291 @@ static struct omap_hwmod omap2420_uart3_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), }; +/* + * 'dss' class + * display sub-system + */ + +static struct omap_hwmod_class_sysconfig omap2420_dss_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2420_dss_hwmod_class = { + .name = "dss", + .sysc = &omap2420_dss_sysc, +}; + +/* dss */ +static struct omap_hwmod_irq_info omap2420_dss_irqs[] = { + { .irq = 25 }, +}; + +static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = { + { .name = "dispc", .dma_req = 5 }, +}; + +/* dss */ +/* dss master ports */ +static struct omap_hwmod_ocp_if *omap2420_dss_masters[] = { + &omap2420_dss__l3, +}; + +static struct omap_hwmod_addr_space omap2420_dss_addrs[] = { + { + .pa_start = 0x48050000, + .pa_end = 0x480503FF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss */ +static struct omap_hwmod_ocp_if omap2420_l4_core__dss = { + .master = &omap2420_l4_core_hwmod, + .slave = &omap2420_dss_core_hwmod, + .clk = "dss_ick", + .addr = omap2420_dss_addrs, + .addr_cnt = ARRAY_SIZE(omap2420_dss_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss slave ports */ +static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = { + &omap2420_l4_core__dss, +}; + +static struct omap_hwmod_opt_clk dss_opt_clks[] = { + { .role = "tv_clk", .clk = "dss_54m_fck" }, + { .role = "sys_clk", .clk = "dss2_fck" }, +}; + +static struct omap_hwmod omap2420_dss_core_hwmod = { + .name = "dss_core", + .class = &omap2420_dss_hwmod_class, + .main_clk = "dss1_fck", /* instead of dss_fck */ + .mpu_irqs = omap2420_dss_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dss_irqs), + .sdma_reqs = omap2420_dss_sdma_chs, + .sdma_reqs_cnt = ARRAY_SIZE(omap2420_dss_sdma_chs), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + .idlest_reg_id = 1, + .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT, + }, + }, + .opt_clks = dss_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), + .slaves = omap2420_dss_slaves, + .slaves_cnt = ARRAY_SIZE(omap2420_dss_slaves), + .masters = omap2420_dss_masters, + .masters_cnt = ARRAY_SIZE(omap2420_dss_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap2420_dispc_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2420_dispc_hwmod_class = { + .name = "dispc", + .sysc = &omap2420_dispc_sysc, +}; + +static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = { + { + .pa_start = 0x48050400, + .pa_end = 0x480507FF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_dispc */ +static struct omap_hwmod_ocp_if omap2420_l4_core__dss_dispc = { + .master = &omap2420_l4_core_hwmod, + .slave = &omap2420_dss_dispc_hwmod, + .clk = "dss_ick", + .addr = omap2420_dss_dispc_addrs, + .addr_cnt = ARRAY_SIZE(omap2420_dss_dispc_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_dispc slave ports */ +static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = { + &omap2420_l4_core__dss_dispc, +}; + +static struct omap_hwmod omap2420_dss_dispc_hwmod = { + .name = "dss_dispc", + .class = &omap2420_dispc_hwmod_class, + .main_clk = "dss1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + .idlest_reg_id = 1, + .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT, + }, + }, + .slaves = omap2420_dss_dispc_slaves, + .slaves_cnt = ARRAY_SIZE(omap2420_dss_dispc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'rfbi' class + * remote frame buffer interface + */ + +static struct omap_hwmod_class_sysconfig omap2420_rfbi_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2420_rfbi_hwmod_class = { + .name = "rfbi", + .sysc = &omap2420_rfbi_sysc, +}; + +static struct omap_hwmod_addr_space omap2420_dss_rfbi_addrs[] = { + { + .pa_start = 0x48050800, + .pa_end = 0x48050BFF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_rfbi */ +static struct omap_hwmod_ocp_if omap2420_l4_core__dss_rfbi = { + .master = &omap2420_l4_core_hwmod, + .slave = &omap2420_dss_rfbi_hwmod, + .clk = "dss_ick", + .addr = omap2420_dss_rfbi_addrs, + .addr_cnt = ARRAY_SIZE(omap2420_dss_rfbi_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_CORE_REGION, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_rfbi slave ports */ +static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = { + &omap2420_l4_core__dss_rfbi, +}; + +static struct omap_hwmod omap2420_dss_rfbi_hwmod = { + .name = "dss_rfbi", + .class = &omap2420_rfbi_hwmod_class, + .main_clk = "dss1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + }, + }, + .slaves = omap2420_dss_rfbi_slaves, + .slaves_cnt = ARRAY_SIZE(omap2420_dss_rfbi_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'venc' class + * video encoder + */ + +static struct omap_hwmod_class omap2420_venc_hwmod_class = { + .name = "venc", +}; + +/* dss_venc */ +static struct omap_hwmod_addr_space omap2420_dss_venc_addrs[] = { + { + .pa_start = 0x48050C00, + .pa_end = 0x48050FFF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_venc */ +static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = { + .master = &omap2420_l4_core_hwmod, + .slave = &omap2420_dss_venc_hwmod, + .clk = "dss_54m_fck", + .addr = omap2420_dss_venc_addrs, + .addr_cnt = ARRAY_SIZE(omap2420_dss_venc_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP2420_L4_CORE_FW_DSS_VENC_REGION, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_venc slave ports */ +static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = { + &omap2420_l4_core__dss_venc, +}; + +static struct omap_hwmod omap2420_dss_venc_hwmod = { + .name = "dss_venc", + .class = &omap2420_venc_hwmod_class, + .main_clk = "dss1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + }, + }, + .slaves = omap2420_dss_venc_slaves, + .slaves_cnt = ARRAY_SIZE(omap2420_dss_venc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), + .flags = HWMOD_NO_IDLEST, +}; + /* I2C common */ static struct omap_hwmod_class_sysconfig i2c_sysc = { .rev_offs = 0x00, @@ -874,6 +1177,12 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = { &omap2420_uart1_hwmod, &omap2420_uart2_hwmod, &omap2420_uart3_hwmod, + /* dss class */ + &omap2420_dss_core_hwmod, + &omap2420_dss_dispc_hwmod, + &omap2420_dss_rfbi_hwmod, + &omap2420_dss_venc_hwmod, + /* i2c class */ &omap2420_i2c1_hwmod, &omap2420_i2c2_hwmod, diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 8ecfbcde13b..1ef3f3fd862 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -18,6 +18,7 @@ #include <plat/serial.h> #include <plat/i2c.h> #include <plat/gpio.h> +#include <plat/l3_2xxx.h> #include "omap_hwmod_common_data.h" @@ -38,6 +39,10 @@ static struct omap_hwmod omap2430_mpu_hwmod; static struct omap_hwmod omap2430_iva_hwmod; static struct omap_hwmod omap2430_l3_main_hwmod; static struct omap_hwmod omap2430_l4_core_hwmod; +static struct omap_hwmod omap2430_dss_core_hwmod; +static struct omap_hwmod omap2430_dss_dispc_hwmod; +static struct omap_hwmod omap2430_dss_rfbi_hwmod; +static struct omap_hwmod omap2430_dss_venc_hwmod; static struct omap_hwmod omap2430_wd_timer2_hwmod; static struct omap_hwmod omap2430_gpio1_hwmod; static struct omap_hwmod omap2430_gpio2_hwmod; @@ -65,6 +70,19 @@ static struct omap_hwmod_ocp_if *omap2430_l3_main_slaves[] = { &omap2430_mpu__l3_main, }; +/* DSS -> l3 */ +static struct omap_hwmod_ocp_if omap2430_dss__l3 = { + .master = &omap2430_dss_core_hwmod, + .slave = &omap2430_l3_main_hwmod, + .fw = { + .omap2 = { + .l3_perm_bit = OMAP2_L3_CORE_FW_CONNID_DSS, + .flags = OMAP_FIREWALL_L3, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* Master interfaces on the L3 interconnect */ static struct omap_hwmod_ocp_if *omap2430_l3_main_masters[] = { &omap2430_l3_main__l4_core, @@ -469,6 +487,266 @@ static struct omap_hwmod omap2430_uart3_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), }; +/* + * 'dss' class + * display sub-system + */ + +static struct omap_hwmod_class_sysconfig omap2430_dss_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2430_dss_hwmod_class = { + .name = "dss", + .sysc = &omap2430_dss_sysc, +}; + +/* dss */ +static struct omap_hwmod_irq_info omap2430_dss_irqs[] = { + { .irq = 25 }, +}; +static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = { + { .name = "dispc", .dma_req = 5 }, +}; + +/* dss */ +/* dss master ports */ +static struct omap_hwmod_ocp_if *omap2430_dss_masters[] = { + &omap2430_dss__l3, +}; + +static struct omap_hwmod_addr_space omap2430_dss_addrs[] = { + { + .pa_start = 0x48050000, + .pa_end = 0x480503FF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss */ +static struct omap_hwmod_ocp_if omap2430_l4_core__dss = { + .master = &omap2430_l4_core_hwmod, + .slave = &omap2430_dss_core_hwmod, + .clk = "dss_ick", + .addr = omap2430_dss_addrs, + .addr_cnt = ARRAY_SIZE(omap2430_dss_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss slave ports */ +static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = { + &omap2430_l4_core__dss, +}; + +static struct omap_hwmod_opt_clk dss_opt_clks[] = { + { .role = "tv_clk", .clk = "dss_54m_fck" }, + { .role = "sys_clk", .clk = "dss2_fck" }, +}; + +static struct omap_hwmod omap2430_dss_core_hwmod = { + .name = "dss_core", + .class = &omap2430_dss_hwmod_class, + .main_clk = "dss1_fck", /* instead of dss_fck */ + .mpu_irqs = omap2430_dss_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dss_irqs), + .sdma_reqs = omap2430_dss_sdma_chs, + .sdma_reqs_cnt = ARRAY_SIZE(omap2430_dss_sdma_chs), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + .idlest_reg_id = 1, + .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT, + }, + }, + .opt_clks = dss_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), + .slaves = omap2430_dss_slaves, + .slaves_cnt = ARRAY_SIZE(omap2430_dss_slaves), + .masters = omap2430_dss_masters, + .masters_cnt = ARRAY_SIZE(omap2430_dss_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap2430_dispc_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2430_dispc_hwmod_class = { + .name = "dispc", + .sysc = &omap2430_dispc_sysc, +}; + +static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = { + { + .pa_start = 0x48050400, + .pa_end = 0x480507FF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_dispc */ +static struct omap_hwmod_ocp_if omap2430_l4_core__dss_dispc = { + .master = &omap2430_l4_core_hwmod, + .slave = &omap2430_dss_dispc_hwmod, + .clk = "dss_ick", + .addr = omap2430_dss_dispc_addrs, + .addr_cnt = ARRAY_SIZE(omap2430_dss_dispc_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_dispc slave ports */ +static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = { + &omap2430_l4_core__dss_dispc, +}; + +static struct omap_hwmod omap2430_dss_dispc_hwmod = { + .name = "dss_dispc", + .class = &omap2430_dispc_hwmod_class, + .main_clk = "dss1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + .idlest_reg_id = 1, + .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT, + }, + }, + .slaves = omap2430_dss_dispc_slaves, + .slaves_cnt = ARRAY_SIZE(omap2430_dss_dispc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'rfbi' class + * remote frame buffer interface + */ + +static struct omap_hwmod_class_sysconfig omap2430_rfbi_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2430_rfbi_hwmod_class = { + .name = "rfbi", + .sysc = &omap2430_rfbi_sysc, +}; + +static struct omap_hwmod_addr_space omap2430_dss_rfbi_addrs[] = { + { + .pa_start = 0x48050800, + .pa_end = 0x48050BFF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_rfbi */ +static struct omap_hwmod_ocp_if omap2430_l4_core__dss_rfbi = { + .master = &omap2430_l4_core_hwmod, + .slave = &omap2430_dss_rfbi_hwmod, + .clk = "dss_ick", + .addr = omap2430_dss_rfbi_addrs, + .addr_cnt = ARRAY_SIZE(omap2430_dss_rfbi_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_rfbi slave ports */ +static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = { + &omap2430_l4_core__dss_rfbi, +}; + +static struct omap_hwmod omap2430_dss_rfbi_hwmod = { + .name = "dss_rfbi", + .class = &omap2430_rfbi_hwmod_class, + .main_clk = "dss1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + }, + }, + .slaves = omap2430_dss_rfbi_slaves, + .slaves_cnt = ARRAY_SIZE(omap2430_dss_rfbi_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'venc' class + * video encoder + */ + +static struct omap_hwmod_class omap2430_venc_hwmod_class = { + .name = "venc", +}; + +/* dss_venc */ +static struct omap_hwmod_addr_space omap2430_dss_venc_addrs[] = { + { + .pa_start = 0x48050C00, + .pa_end = 0x48050FFF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_venc */ +static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = { + .master = &omap2430_l4_core_hwmod, + .slave = &omap2430_dss_venc_hwmod, + .clk = "dss_54m_fck", + .addr = omap2430_dss_venc_addrs, + .addr_cnt = ARRAY_SIZE(omap2430_dss_venc_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_venc slave ports */ +static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = { + &omap2430_l4_core__dss_venc, +}; + +static struct omap_hwmod omap2430_dss_venc_hwmod = { + .name = "dss_venc", + .class = &omap2430_venc_hwmod_class, + .main_clk = "dss1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP24XX_EN_DSS1_SHIFT, + .module_offs = CORE_MOD, + }, + }, + .slaves = omap2430_dss_venc_slaves, + .slaves_cnt = ARRAY_SIZE(omap2430_dss_venc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), + .flags = HWMOD_NO_IDLEST, +}; + /* I2C common */ static struct omap_hwmod_class_sysconfig i2c_sysc = { .rev_offs = 0x00, @@ -929,6 +1207,12 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = { &omap2430_uart1_hwmod, &omap2430_uart2_hwmod, &omap2430_uart3_hwmod, + /* dss class */ + &omap2430_dss_core_hwmod, + &omap2430_dss_dispc_hwmod, + &omap2430_dss_rfbi_hwmod, + &omap2430_dss_venc_hwmod, + /* i2c class */ &omap2430_i2c1_hwmod, &omap2430_i2c2_hwmod, diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 8d8181334f8..1201987ca6e 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -18,6 +18,7 @@ #include <plat/cpu.h> #include <plat/dma.h> #include <plat/serial.h> +#include <plat/l3_3xxx.h> #include <plat/l4_3xxx.h> #include <plat/i2c.h> #include <plat/gpio.h> @@ -44,6 +45,12 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod; static struct omap_hwmod omap3xxx_l4_core_hwmod; static struct omap_hwmod omap3xxx_l4_per_hwmod; static struct omap_hwmod omap3xxx_wd_timer2_hwmod; +static struct omap_hwmod omap3430es1_dss_core_hwmod; +static struct omap_hwmod omap3xxx_dss_core_hwmod; +static struct omap_hwmod omap3xxx_dss_dispc_hwmod; +static struct omap_hwmod omap3xxx_dss_dsi1_hwmod; +static struct omap_hwmod omap3xxx_dss_rfbi_hwmod; +static struct omap_hwmod omap3xxx_dss_venc_hwmod; static struct omap_hwmod omap3xxx_i2c1_hwmod; static struct omap_hwmod omap3xxx_i2c2_hwmod; static struct omap_hwmod omap3xxx_i2c3_hwmod; @@ -84,6 +91,19 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_slaves[] = { &omap3xxx_mpu__l3_main, }; +/* DSS -> l3 */ +static struct omap_hwmod_ocp_if omap3xxx_dss__l3 = { + .master = &omap3xxx_dss_core_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .fw = { + .omap2 = { + .l3_perm_bit = OMAP3_L3_CORE_FW_INIT_ID_DSS, + .flags = OMAP_FIREWALL_L3, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* Master interfaces on the L3 interconnect */ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = { &omap3xxx_l3_main__l4_core, @@ -94,6 +114,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = { static struct omap_hwmod omap3xxx_l3_main_hwmod = { .name = "l3_main", .class = &l3_hwmod_class, + .vdd_name = "core", .masters = omap3xxx_l3_main_masters, .masters_cnt = ARRAY_SIZE(omap3xxx_l3_main_masters), .slaves = omap3xxx_l3_main_slaves, @@ -384,6 +405,7 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = { .name = "mpu", .class = &mpu_hwmod_class, .main_clk = "arm_fck", + .vdd_name = "mpu", .masters = omap3xxx_mpu_masters, .masters_cnt = ARRAY_SIZE(omap3xxx_mpu_masters), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -412,6 +434,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_iva_masters[] = { static struct omap_hwmod omap3xxx_iva_hwmod = { .name = "iva", .class = &iva_hwmod_class, + .vdd_name = "mpu", .masters = omap3xxx_iva_masters, .masters_cnt = ARRAY_SIZE(omap3xxx_iva_masters), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430) @@ -664,6 +687,410 @@ static struct omap_hwmod_class i2c_class = { .sysc = &i2c_sysc, }; +/* + * 'dss' class + * display sub-system + */ + +static struct omap_hwmod_class_sysconfig omap3xxx_dss_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_dss_hwmod_class = { + .name = "dss", + .sysc = &omap3xxx_dss_sysc, +}; + +/* dss */ +static struct omap_hwmod_irq_info omap3xxx_dss_irqs[] = { + { .irq = 25 }, +}; + +static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = { + { .name = "dispc", .dma_req = 5 }, + { .name = "dsi1", .dma_req = 74 }, +}; + +/* dss */ +/* dss master ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dss_masters[] = { + &omap3xxx_dss__l3, +}; + +static struct omap_hwmod_addr_space omap3xxx_dss_addrs[] = { + { + .pa_start = 0x48050000, + .pa_end = 0x480503FF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss */ +static struct omap_hwmod_ocp_if omap3430es1_l4_core__dss = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3430es1_dss_core_hwmod, + .clk = "dss_ick", + .addr = omap3xxx_dss_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dss_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION, + .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_dss_core_hwmod, + .clk = "dss_ick", + .addr = omap3xxx_dss_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dss_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP3_L4_CORE_FW_DSS_CORE_REGION, + .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss slave ports */ +static struct omap_hwmod_ocp_if *omap3430es1_dss_slaves[] = { + &omap3430es1_l4_core__dss, +}; + +static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = { + &omap3xxx_l4_core__dss, +}; + +static struct omap_hwmod_opt_clk dss_opt_clks[] = { + { .role = "tv_clk", .clk = "dss_tv_fck" }, + { .role = "video_clk", .clk = "dss_96m_fck" }, + { .role = "sys_clk", .clk = "dss2_alwon_fck" }, +}; + +static struct omap_hwmod omap3430es1_dss_core_hwmod = { + .name = "dss_core", + .class = &omap3xxx_dss_hwmod_class, + .main_clk = "dss1_alwon_fck", /* instead of dss_fck */ + .mpu_irqs = omap3xxx_dss_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dss_irqs), + .sdma_reqs = omap3xxx_dss_sdma_chs, + .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs), + + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_DSS1_SHIFT, + .module_offs = OMAP3430_DSS_MOD, + .idlest_reg_id = 1, + .idlest_stdby_bit = OMAP3430ES1_ST_DSS_SHIFT, + }, + }, + .opt_clks = dss_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), + .slaves = omap3430es1_dss_slaves, + .slaves_cnt = ARRAY_SIZE(omap3430es1_dss_slaves), + .masters = omap3xxx_dss_masters, + .masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1), + .flags = HWMOD_NO_IDLEST, +}; + +static struct omap_hwmod omap3xxx_dss_core_hwmod = { + .name = "dss_core", + .class = &omap3xxx_dss_hwmod_class, + .main_clk = "dss1_alwon_fck", /* instead of dss_fck */ + .mpu_irqs = omap3xxx_dss_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dss_irqs), + .sdma_reqs = omap3xxx_dss_sdma_chs, + .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs), + + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_DSS1_SHIFT, + .module_offs = OMAP3430_DSS_MOD, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT, + .idlest_stdby_bit = OMAP3430ES2_ST_DSS_STDBY_SHIFT, + }, + }, + .opt_clks = dss_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), + .slaves = omap3xxx_dss_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_slaves), + .masters = omap3xxx_dss_masters, + .masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2 | + CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1), +}; + +/* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap3xxx_dispc_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_MIDLEMODE | SYSC_HAS_ENAWAKEUP | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = { + .name = "dispc", + .sysc = &omap3xxx_dispc_sysc, +}; + +static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = { + { + .pa_start = 0x48050400, + .pa_end = 0x480507FF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_dispc */ +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_dss_dispc_hwmod, + .clk = "dss_ick", + .addr = omap3xxx_dss_dispc_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP3_L4_CORE_FW_DSS_DISPC_REGION, + .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_dispc slave ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = { + &omap3xxx_l4_core__dss_dispc, +}; + +static struct omap_hwmod omap3xxx_dss_dispc_hwmod = { + .name = "dss_dispc", + .class = &omap3xxx_dispc_hwmod_class, + .main_clk = "dss1_alwon_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_DSS1_SHIFT, + .module_offs = OMAP3430_DSS_MOD, + }, + }, + .slaves = omap3xxx_dss_dispc_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | + CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 | + CHIP_GE_OMAP3630ES1_1), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'dsi' class + * display serial interface controller + */ + +static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = { + .name = "dsi", +}; + +/* dss_dsi1 */ +static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = { + { + .pa_start = 0x4804FC00, + .pa_end = 0x4804FFFF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_dsi1 */ +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_dss_dsi1_hwmod, + .addr = omap3xxx_dss_dsi1_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP3_L4_CORE_FW_DSS_DSI_REGION, + .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_dsi1 slave ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = { + &omap3xxx_l4_core__dss_dsi1, +}; + +static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = { + .name = "dss_dsi1", + .class = &omap3xxx_dsi_hwmod_class, + .main_clk = "dss1_alwon_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_DSS1_SHIFT, + .module_offs = OMAP3430_DSS_MOD, + }, + }, + .slaves = omap3xxx_dss_dsi1_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | + CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 | + CHIP_GE_OMAP3630ES1_1), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'rfbi' class + * remote frame buffer interface + */ + +static struct omap_hwmod_class_sysconfig omap3xxx_rfbi_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_rfbi_hwmod_class = { + .name = "rfbi", + .sysc = &omap3xxx_rfbi_sysc, +}; + +static struct omap_hwmod_addr_space omap3xxx_dss_rfbi_addrs[] = { + { + .pa_start = 0x48050800, + .pa_end = 0x48050BFF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_rfbi */ +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_dss_rfbi_hwmod, + .clk = "dss_ick", + .addr = omap3xxx_dss_rfbi_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP3_L4_CORE_FW_DSS_RFBI_REGION, + .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP , + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_rfbi slave ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = { + &omap3xxx_l4_core__dss_rfbi, +}; + +static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = { + .name = "dss_rfbi", + .class = &omap3xxx_rfbi_hwmod_class, + .main_clk = "dss1_alwon_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_DSS1_SHIFT, + .module_offs = OMAP3430_DSS_MOD, + }, + }, + .slaves = omap3xxx_dss_rfbi_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | + CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 | + CHIP_GE_OMAP3630ES1_1), + .flags = HWMOD_NO_IDLEST, +}; + +/* + * 'venc' class + * video encoder + */ + +static struct omap_hwmod_class omap3xxx_venc_hwmod_class = { + .name = "venc", +}; + +/* dss_venc */ +static struct omap_hwmod_addr_space omap3xxx_dss_venc_addrs[] = { + { + .pa_start = 0x48050C00, + .pa_end = 0x48050FFF, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_core -> dss_venc */ +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_dss_venc_hwmod, + .clk = "dss_tv_fck", + .addr = omap3xxx_dss_venc_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dss_venc_addrs), + .fw = { + .omap2 = { + .l4_fw_region = OMAP3_L4_CORE_FW_DSS_VENC_REGION, + .l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP, + .flags = OMAP_FIREWALL_L4, + } + }, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dss_venc slave ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = { + &omap3xxx_l4_core__dss_venc, +}; + +static struct omap_hwmod omap3xxx_dss_venc_hwmod = { + .name = "dss_venc", + .class = &omap3xxx_venc_hwmod_class, + .main_clk = "dss1_alwon_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_DSS1_SHIFT, + .module_offs = OMAP3430_DSS_MOD, + }, + }, + .slaves = omap3xxx_dss_venc_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_venc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | + CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 | + CHIP_GE_OMAP3630ES1_1), + .flags = HWMOD_NO_IDLEST, +}; + /* I2C1 */ static struct omap_i2c_dev_attr i2c1_dev_attr = { @@ -685,6 +1112,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = { static struct omap_hwmod omap3xxx_i2c1_hwmod = { .name = "i2c1", + .flags = HWMOD_16BIT_REG, .mpu_irqs = i2c1_mpu_irqs, .mpu_irqs_cnt = ARRAY_SIZE(i2c1_mpu_irqs), .sdma_reqs = i2c1_sdma_reqs, @@ -727,6 +1155,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = { static struct omap_hwmod omap3xxx_i2c2_hwmod = { .name = "i2c2", + .flags = HWMOD_16BIT_REG, .mpu_irqs = i2c2_mpu_irqs, .mpu_irqs_cnt = ARRAY_SIZE(i2c2_mpu_irqs), .sdma_reqs = i2c2_sdma_reqs, @@ -769,6 +1198,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = { static struct omap_hwmod omap3xxx_i2c3_hwmod = { .name = "i2c3", + .flags = HWMOD_16BIT_REG, .mpu_irqs = i2c3_mpu_irqs, .mpu_irqs_cnt = ARRAY_SIZE(i2c3_mpu_irqs), .sdma_reqs = i2c3_sdma_reqs, @@ -1368,6 +1798,15 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_uart2_hwmod, &omap3xxx_uart3_hwmod, &omap3xxx_uart4_hwmod, + /* dss class */ + &omap3430es1_dss_core_hwmod, + &omap3xxx_dss_core_hwmod, + &omap3xxx_dss_dispc_hwmod, + &omap3xxx_dss_dsi1_hwmod, + &omap3xxx_dss_rfbi_hwmod, + &omap3xxx_dss_venc_hwmod, + + /* i2c class */ &omap3xxx_i2c1_hwmod, &omap3xxx_i2c2_hwmod, &omap3xxx_i2c3_hwmod, diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index c2806bd11fb..2773bf363d4 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -43,6 +43,13 @@ static struct omap_hwmod omap44xx_dma_system_hwmod; static struct omap_hwmod omap44xx_dmm_hwmod; static struct omap_hwmod omap44xx_dsp_hwmod; +static struct omap_hwmod omap44xx_dss_core_hwmod; +static struct omap_hwmod omap44xx_dss_dispc_hwmod; +static struct omap_hwmod omap44xx_dss_dsi1_hwmod; +static struct omap_hwmod omap44xx_dss_dsi2_hwmod; +static struct omap_hwmod omap44xx_dss_hdmi_hwmod; +static struct omap_hwmod omap44xx_dss_rfbi_hwmod; +static struct omap_hwmod omap44xx_dss_venc_hwmod; static struct omap_hwmod omap44xx_emif_fw_hwmod; static struct omap_hwmod omap44xx_iva_hwmod; static struct omap_hwmod omap44xx_l3_instr_hwmod; @@ -237,12 +244,21 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* dss -> l3_main_1 */ +static struct omap_hwmod_ocp_if omap44xx_dss__l3_main_1 = { + .master = &omap44xx_dss_core_hwmod, + .slave = &omap44xx_l3_main_1_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l3_main_1 slave ports */ static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = { &omap44xx_dsp__l3_main_1, &omap44xx_l3_main_2__l3_main_1, &omap44xx_l4_cfg__l3_main_1, &omap44xx_mpu__l3_main_1, + &omap44xx_dss__l3_main_1, }; static struct omap_hwmod omap44xx_l3_main_1_hwmod = { @@ -746,6 +762,584 @@ static struct omap_hwmod omap44xx_dsp_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; +/* ==== DSS related classes ==== */ + /* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap44xx_dispc_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap44xx_dispc_hwmod_class = { + .name = "dispc", + .sysc = &omap44xx_dispc_sysc, +}; + +/* dss_dispc */ +static struct omap_hwmod_irq_info omap44xx_dss_dispc_irqs[] = { + { .irq = 25 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_dma_info omap44xx_dss_dispc_sdma_reqs[] = { + { .dma_req = 5 + OMAP44XX_DMA_REQ_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = { + { + .pa_start = 0x48041000, + .pa_end = 0x48041fff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_per -> dss_dispc */ +static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = { + .master = &omap44xx_l4_per_hwmod, + .slave = &omap44xx_dss_dispc_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dss_dispc_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_dispc_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = { + { + .pa_start = 0x58001000, + .pa_end = 0x58001fff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l3_main_2 -> dss_dispc */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_dss_dispc_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_dss_dispc_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* dss_dispc slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = { + &omap44xx_l3_main_2__dss_dispc, + &omap44xx_l4_per__dss_dispc, +}; + +static struct omap_hwmod omap44xx_dss_dispc_hwmod = { + .name = "dss_dispc", + .class = &omap44xx_dispc_hwmod_class, + .mpu_irqs = omap44xx_dss_dispc_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_irqs), + .sdma_reqs = omap44xx_dss_dispc_sdma_reqs, + .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs), + .main_clk = "dss_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + }, + }, + .slaves = omap44xx_dss_dispc_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dispc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + +/* + * 'dsi' class + * display serial interface controller + */ +static struct omap_hwmod_class_sysconfig omap44xx_dsi_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap44xx_dsi_hwmod_class = { + .name = "dsi", + .sysc = &omap44xx_dsi_sysc, +}; + +/* dss_dsi1 */ +static struct omap_hwmod_irq_info omap44xx_dss_dsi1_irqs[] = { + { .irq = 53 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_dma_info omap44xx_dss_dsi1_sdma_reqs[] = { + { .dma_req = 74 + OMAP44XX_DMA_REQ_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_dsi1_addrs[] = { + { + .pa_start = 0x48044000, + .pa_end = 0x480440ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_per -> dss_dsi1 */ +static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = { + .master = &omap44xx_l4_per_hwmod, + .slave = &omap44xx_dss_dsi1_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dss_dsi1_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = { + { + .pa_start = 0x58004000, + .pa_end = 0x580040ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l3_main_2 -> dss_dsi1 */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_dss_dsi1_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_dss_dsi1_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* dss_dsi1 slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = { + &omap44xx_l3_main_2__dss_dsi1, + &omap44xx_l4_per__dss_dsi1, +}; + +static struct omap_hwmod omap44xx_dss_dsi1_hwmod = { + .name = "dss_dsi1", + .class = &omap44xx_dsi_hwmod_class, + .mpu_irqs = omap44xx_dss_dsi1_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_irqs), + .sdma_reqs = omap44xx_dss_dsi1_sdma_reqs, + .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs), + .main_clk = "dss_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + }, + }, + .slaves = omap44xx_dss_dsi1_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + +/* dss_dsi2 */ +static struct omap_hwmod_irq_info omap44xx_dss_dsi2_irqs[] = { + { .irq = 84 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_dma_info omap44xx_dss_dsi2_sdma_reqs[] = { + { .dma_req = 83 + OMAP44XX_DMA_REQ_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_dsi2_addrs[] = { + { + .pa_start = 0x48045000, + .pa_end = 0x480450ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_per -> dss_dsi2 */ +static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = { + .master = &omap44xx_l4_per_hwmod, + .slave = &omap44xx_dss_dsi2_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dss_dsi2_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = { + { + .pa_start = 0x58005000, + .pa_end = 0x580050ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l3_main_2 -> dss_dsi2 */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_dss_dsi2_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_dss_dsi2_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* dss_dsi2 slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = { + &omap44xx_l3_main_2__dss_dsi2, + &omap44xx_l4_per__dss_dsi2, +}; + +static struct omap_hwmod omap44xx_dss_dsi2_hwmod = { + .name = "dss_dsi2", + .class = &omap44xx_dsi_hwmod_class, + .mpu_irqs = omap44xx_dss_dsi2_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_irqs), + .sdma_reqs = omap44xx_dss_dsi2_sdma_reqs, + .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs), + .main_clk = "dss_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + }, + }, + .slaves = omap44xx_dss_dsi2_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + +/* + * 'dss' class + * display sub-system + */ +static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = { + .rev_offs = 0x0000, + .syss_offs = 0x0014, + .sysc_flags = SYSS_HAS_RESET_STATUS, + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), +}; + +static struct omap_hwmod_class omap44xx_dss_hwmod_class = { + .name = "dss", + .sysc = &omap44xx_dss_sysc, +}; + +/* dss */ +/* dss master ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_masters[] = { + &omap44xx_dss__l3_main_1, +}; + +static struct omap_hwmod_irq_info omap44xx_dss_irqs[] = { + { .irq = 25 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_addrs[] = { + { + .pa_start = 0x48040000, + .pa_end = 0x4804007f, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_per -> dss */ +static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = { + .master = &omap44xx_l4_per_hwmod, + .slave = &omap44xx_dss_core_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dss_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = { + { + .pa_start = 0x58000000, + .pa_end = 0x5800007f, + .flags = ADDR_TYPE_RT + }, +}; + +/* l3_main_2 -> dss */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_dss_core_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_dss_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* dss slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = { + &omap44xx_l3_main_2__dss, + &omap44xx_l4_per__dss, +}; + +static struct omap_hwmod_opt_clk dss_opt_clks[] = { + { .role = "sys_clk", .clk = "dss_sys_clk" }, + { .role = "tv_clk", .clk = "dss_tv_clk" }, + { .role = "dss_clk", .clk = "dss_dss_clk" }, + { .role = "video_clk", .clk = "dss_48mhz_clk" }, +}; + +static struct omap_hwmod omap44xx_dss_core_hwmod = { + .name = "dss_core", + .class = &omap44xx_dss_hwmod_class, + .mpu_irqs = omap44xx_dss_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_irqs), + .main_clk = "dss_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + }, + }, + .opt_clks = dss_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), + .slaves = omap44xx_dss_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dss_slaves), + .masters = omap44xx_dss_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_dss_masters), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + +/* + * 'hdmi' class + * hdmi controller + */ + +static struct omap_hwmod_class omap44xx_hdmi_hwmod_class = { + .name = "hdmi", +}; + +/* dss_hdmi */ +static struct omap_hwmod_irq_info omap44xx_dss_hdmi_irqs[] = { + { .irq = 101 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = { + { .dma_req = 75 + OMAP44XX_DMA_REQ_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_hdmi_addrs[] = { + { + .pa_start = 0x48046000, + .pa_end = 0x48046fff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_per -> dss_hdmi */ +static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = { + .master = &omap44xx_l4_per_hwmod, + .slave = &omap44xx_dss_hdmi_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dss_hdmi_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = { + { + .pa_start = 0x58006000, + .pa_end = 0x58006fff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l3_main_2 -> dss_hdmi */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_dss_hdmi_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_dss_hdmi_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* dss_hdmi slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = { + &omap44xx_l3_main_2__dss_hdmi, + &omap44xx_l4_per__dss_hdmi, +}; + +static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { + .name = "dss_hdmi", + .class = &omap44xx_hdmi_hwmod_class, + .mpu_irqs = omap44xx_dss_hdmi_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_irqs), + .sdma_reqs = omap44xx_dss_hdmi_sdma_reqs, + .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs), + .main_clk = "dss_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + }, + }, + .slaves = omap44xx_dss_hdmi_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + + /* + * 'rfbi' class + * remote frame buffer interface + */ + +static struct omap_hwmod_class_sysconfig omap44xx_rfbi_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap44xx_rfbi_hwmod_class = { + .name = "rfbi", + .sysc = &omap44xx_rfbi_sysc, +}; + +/* dss_rfbi */ +static struct omap_hwmod_dma_info omap44xx_dss_rfbi_sdma_reqs[] = { + { .dma_req = 13 + OMAP44XX_DMA_REQ_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_rfbi_addrs[] = { + { + .pa_start = 0x48042000, + .pa_end = 0x480420ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_per -> dss_rfbi */ +static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = { + .master = &omap44xx_l4_per_hwmod, + .slave = &omap44xx_dss_rfbi_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dss_rfbi_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = { + { + .pa_start = 0x58002000, + .pa_end = 0x580020ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l3_main_2 -> dss_rfbi */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_dss_rfbi_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_dss_rfbi_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* dss_rfbi slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = { + &omap44xx_l3_main_2__dss_rfbi, + &omap44xx_l4_per__dss_rfbi, +}; + +static struct omap_hwmod omap44xx_dss_rfbi_hwmod = { + .name = "dss_rfbi", + .class = &omap44xx_rfbi_hwmod_class, + .sdma_reqs = omap44xx_dss_rfbi_sdma_reqs, + .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs), + .main_clk = "dss_fck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + }, + }, + .slaves = omap44xx_dss_rfbi_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + +/* + * 'venc' class + * video encoder + */ + +static struct omap_hwmod_class_sysconfig omap44xx_venc_sysc = { + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), +}; + +static struct omap_hwmod_class omap44xx_venc_hwmod_class = { + .name = "venc", + .sysc = &omap44xx_venc_sysc, +}; + +/* dss_venc */ +static struct omap_hwmod_addr_space omap44xx_dss_venc_addrs[] = { + { + .pa_start = 0x48043000, + .pa_end = 0x480430ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_per -> dss_venc */ +static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = { + .master = &omap44xx_l4_per_hwmod, + .slave = &omap44xx_dss_venc_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dss_venc_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_venc_addrs), + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = { + { + .pa_start = 0x58003000, + .pa_end = 0x580030ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l3_main_2 -> dss_venc */ +static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = { + .master = &omap44xx_l3_main_2_hwmod, + .slave = &omap44xx_dss_venc_hwmod, + .clk = "l3_div_ck", + .addr = omap44xx_dss_venc_dma_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dss_venc_dma_addrs), + .user = OCP_USER_SDMA, +}; + +/* dss_venc slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = { + &omap44xx_l3_main_2__dss_venc, + &omap44xx_l4_per__dss_venc, +}; + +static struct omap_hwmod omap44xx_dss_venc_hwmod = { + .name = "dss_venc", + .class = &omap44xx_venc_hwmod_class, + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, + }, + }, + .slaves = omap44xx_dss_venc_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dss_venc_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + + /* * 'gpio' class * general purpose io module @@ -1150,7 +1744,7 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = { static struct omap_hwmod omap44xx_i2c1_hwmod = { .name = "i2c1", .class = &omap44xx_i2c_hwmod_class, - .flags = HWMOD_INIT_NO_RESET, + .flags = HWMOD_INIT_NO_RESET | HWMOD_16BIT_REG, .mpu_irqs = omap44xx_i2c1_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c1_irqs), .sdma_reqs = omap44xx_i2c1_sdma_reqs, @@ -1203,7 +1797,7 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = { static struct omap_hwmod omap44xx_i2c2_hwmod = { .name = "i2c2", .class = &omap44xx_i2c_hwmod_class, - .flags = HWMOD_INIT_NO_RESET, + .flags = HWMOD_INIT_NO_RESET | HWMOD_16BIT_REG, .mpu_irqs = omap44xx_i2c2_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c2_irqs), .sdma_reqs = omap44xx_i2c2_sdma_reqs, @@ -1256,7 +1850,7 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = { static struct omap_hwmod omap44xx_i2c3_hwmod = { .name = "i2c3", .class = &omap44xx_i2c_hwmod_class, - .flags = HWMOD_INIT_NO_RESET, + .flags = HWMOD_INIT_NO_RESET | HWMOD_16BIT_REG, .mpu_irqs = omap44xx_i2c3_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c3_irqs), .sdma_reqs = omap44xx_i2c3_sdma_reqs, @@ -1309,7 +1903,7 @@ static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = { static struct omap_hwmod omap44xx_i2c4_hwmod = { .name = "i2c4", .class = &omap44xx_i2c_hwmod_class, - .flags = HWMOD_INIT_NO_RESET, + .flags = HWMOD_INIT_NO_RESET | HWMOD_16BIT_REG, .mpu_irqs = omap44xx_i2c4_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_i2c4_irqs), .sdma_reqs = omap44xx_i2c4_sdma_reqs, @@ -1464,6 +2058,7 @@ static struct omap_hwmod omap44xx_mpu_hwmod = { .mpu_irqs = omap44xx_mpu_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mpu_irqs), .main_clk = "dpll_mpu_m2_ck", + .vdd_name = "mpu", .prcm = { .omap4 = { .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL, @@ -2031,6 +2626,15 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_dsp_hwmod, &omap44xx_dsp_c0_hwmod, + /* dss class */ + &omap44xx_dss_core_hwmod, + &omap44xx_dss_dispc_hwmod, + &omap44xx_dss_dsi1_hwmod, + &omap44xx_dss_dsi2_hwmod, + &omap44xx_dss_hdmi_hwmod, + &omap44xx_dss_rfbi_hwmod, + &omap44xx_dss_venc_hwmod, + /* gpio class */ &omap44xx_gpio1_hwmod, &omap44xx_gpio2_hwmod, diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c index 00e1d2b5368..5100125bc2f 100644 --- a/arch/arm/mach-omap2/omap_twl.c +++ b/arch/arm/mach-omap2/omap_twl.c @@ -59,8 +59,15 @@ static bool is_offset_valid; static u8 smps_offset; +/* + * Flag to ensure Smartreflex bit in TWL + * being cleared in board file is not overwritten. + */ +static bool __initdata twl_sr_enable_autoinit; +#define TWL4030_DCDC_GLOBAL_CFG 0x06 #define REG_SMPS_OFFSET 0xE0 +#define SMARTREFLEX_ENABLE BIT(3) static unsigned long twl4030_vsel_to_uv(const u8 vsel) { @@ -269,6 +276,18 @@ int __init omap3_twl_init(void) omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; } + /* + * The smartreflex bit on twl4030 specifies if the setting of voltage + * is done over the I2C_SR path. Since this setting is independent of + * the actual usage of smartreflex AVS module, we enable TWL SR bit + * by default irrespective of whether smartreflex AVS module is enabled + * on the OMAP side or not. This is because without this bit enabled, + * the voltage scaling through vp forceupdate/bypass mechanism of + * voltage scaling will not function on TWL over I2C_SR. + */ + if (!twl_sr_enable_autoinit) + omap3_twl_set_sr_bit(true); + voltdm = omap_voltage_domain_lookup("mpu"); omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info); @@ -277,3 +296,44 @@ int __init omap3_twl_init(void) return 0; } + +/** + * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL + * @enable: enable SR mode in twl or not + * + * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure + * voltage scaling through OMAP SR works. Else, the smartreflex bit + * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but + * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct + * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages, + * in those scenarios this bit is to be cleared (enable = false). + * + * Returns 0 on sucess, error is returned if I2C read/write fails. + */ +int __init omap3_twl_set_sr_bit(bool enable) +{ + u8 temp; + int ret; + if (twl_sr_enable_autoinit) + pr_warning("%s: unexpected multiple calls\n", __func__); + + ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp, + TWL4030_DCDC_GLOBAL_CFG); + if (ret) + goto err; + + if (enable) + temp |= SMARTREFLEX_ENABLE; + else + temp &= ~SMARTREFLEX_ENABLE; + + ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp, + TWL4030_DCDC_GLOBAL_CFG); + if (!ret) { + twl_sr_enable_autoinit = true; + return 0; + } +err: + pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret); + return ret; +} diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c index 0486fce8a92..eefd6aff3f2 100644 --- a/arch/arm/mach-omap2/opp3xxx_data.c +++ b/arch/arm/mach-omap2/opp3xxx_data.c @@ -19,20 +19,21 @@ #include <linux/module.h> #include <plat/cpu.h> +#include <plat/voltage.h> #include "omap_opp_data.h" static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { /* MPU OPP1 */ - OPP_INITIALIZER("mpu", true, 125000000, 975000), + OPP_INITIALIZER("mpu", true, 125000000, OMAP3430_VDD_MPU_OPP1_UV), /* MPU OPP2 */ - OPP_INITIALIZER("mpu", true, 250000000, 1075000), + OPP_INITIALIZER("mpu", true, 250000000, OMAP3430_VDD_MPU_OPP2_UV), /* MPU OPP3 */ - OPP_INITIALIZER("mpu", true, 500000000, 1200000), + OPP_INITIALIZER("mpu", true, 500000000, OMAP3430_VDD_MPU_OPP3_UV), /* MPU OPP4 */ - OPP_INITIALIZER("mpu", true, 550000000, 1270000), + OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV), /* MPU OPP5 */ - OPP_INITIALIZER("mpu", true, 600000000, 1350000), + OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV), /* * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is @@ -42,47 +43,47 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { * impact that frequency will do to the MPU and the whole system in * general. */ - OPP_INITIALIZER("l3_main", false, 41500000, 975000), + OPP_INITIALIZER("l3_main", false, 41500000, OMAP3430_VDD_CORE_OPP1_UV), /* L3 OPP2 */ - OPP_INITIALIZER("l3_main", true, 83000000, 1050000), + OPP_INITIALIZER("l3_main", true, 83000000, OMAP3430_VDD_CORE_OPP2_UV), /* L3 OPP3 */ - OPP_INITIALIZER("l3_main", true, 166000000, 1150000), + OPP_INITIALIZER("l3_main", true, 166000000, OMAP3430_VDD_CORE_OPP3_UV), /* DSP OPP1 */ - OPP_INITIALIZER("iva", true, 90000000, 975000), + OPP_INITIALIZER("iva", true, 90000000, OMAP3430_VDD_MPU_OPP1_UV), /* DSP OPP2 */ - OPP_INITIALIZER("iva", true, 180000000, 1075000), + OPP_INITIALIZER("iva", true, 180000000, OMAP3430_VDD_MPU_OPP2_UV), /* DSP OPP3 */ - OPP_INITIALIZER("iva", true, 360000000, 1200000), + OPP_INITIALIZER("iva", true, 360000000, OMAP3430_VDD_MPU_OPP3_UV), /* DSP OPP4 */ - OPP_INITIALIZER("iva", true, 400000000, 1270000), + OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV), /* DSP OPP5 */ - OPP_INITIALIZER("iva", true, 430000000, 1350000), + OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV), }; static struct omap_opp_def __initdata omap36xx_opp_def_list[] = { /* MPU OPP1 - OPP50 */ - OPP_INITIALIZER("mpu", true, 300000000, 1012500), + OPP_INITIALIZER("mpu", true, 300000000, OMAP3630_VDD_MPU_OPP50_UV), /* MPU OPP2 - OPP100 */ - OPP_INITIALIZER("mpu", true, 600000000, 1200000), + OPP_INITIALIZER("mpu", true, 600000000, OMAP3630_VDD_MPU_OPP100_UV), /* MPU OPP3 - OPP-Turbo */ - OPP_INITIALIZER("mpu", false, 800000000, 1325000), + OPP_INITIALIZER("mpu", false, 800000000, OMAP3630_VDD_MPU_OPP120_UV), /* MPU OPP4 - OPP-SB */ - OPP_INITIALIZER("mpu", false, 1000000000, 1375000), + OPP_INITIALIZER("mpu", false, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV), /* L3 OPP1 - OPP50 */ - OPP_INITIALIZER("l3_main", true, 100000000, 1000000), + OPP_INITIALIZER("l3_main", true, 100000000, OMAP3630_VDD_CORE_OPP50_UV), /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ - OPP_INITIALIZER("l3_main", true, 200000000, 1200000), + OPP_INITIALIZER("l3_main", true, 200000000, OMAP3630_VDD_CORE_OPP100_UV), /* DSP OPP1 - OPP50 */ - OPP_INITIALIZER("iva", true, 260000000, 1012500), + OPP_INITIALIZER("iva", true, 260000000, OMAP3630_VDD_MPU_OPP50_UV), /* DSP OPP2 - OPP100 */ - OPP_INITIALIZER("iva", true, 520000000, 1200000), + OPP_INITIALIZER("iva", true, 520000000, OMAP3630_VDD_MPU_OPP100_UV), /* DSP OPP3 - OPP-Turbo */ - OPP_INITIALIZER("iva", false, 660000000, 1325000), + OPP_INITIALIZER("iva", false, 660000000, OMAP3630_VDD_MPU_OPP120_UV), /* DSP OPP4 - OPP-SB */ - OPP_INITIALIZER("iva", false, 800000000, 1375000), + OPP_INITIALIZER("iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV), }; /** diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index a11fa566d8e..2e8bb8a6ba9 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -20,22 +20,23 @@ #include <linux/module.h> #include <plat/cpu.h> +#include <plat/voltage.h> #include "omap_opp_data.h" static struct omap_opp_def __initdata omap44xx_opp_def_list[] = { /* MPU OPP1 - OPP50 */ - OPP_INITIALIZER("mpu", true, 300000000, 1100000), + OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV), /* MPU OPP2 - OPP100 */ - OPP_INITIALIZER("mpu", true, 600000000, 1200000), + OPP_INITIALIZER("mpu", true, 600000000, OMAP4430_VDD_MPU_OPP100_UV), /* MPU OPP3 - OPP-Turbo */ - OPP_INITIALIZER("mpu", false, 800000000, 1260000), + OPP_INITIALIZER("mpu", true, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV), /* MPU OPP4 - OPP-SB */ - OPP_INITIALIZER("mpu", false, 1008000000, 1350000), + OPP_INITIALIZER("mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV), /* L3 OPP1 - OPP50 */ - OPP_INITIALIZER("l3_main_1", true, 100000000, 930000), + OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV), /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ - OPP_INITIALIZER("l3_main_1", true, 200000000, 1100000), + OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV), /* TODO: add IVA, DSP, aess, fdif, gpu */ }; diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index d5a102c7198..51b0dcdef60 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -23,6 +23,9 @@ #include "powerdomain.h" #include "clockdomain.h" #include "pm.h" +#include "cm2xxx_3xxx.h" +#include "cm-regbits-34xx.h" +#include "prm.h" static struct omap_device_pm_latency *pm_lats; @@ -31,6 +34,8 @@ static struct device *iva_dev; static struct device *l3_dev; static struct device *dsp_dev; +static struct clk *dpll1_clk, *dpll2_clk, *dpll3_clk; + struct device *omap2_get_mpuss_device(void) { WARN_ON_ONCE(!mpu_dev); @@ -77,6 +82,73 @@ static int _init_omap_device(char *name, struct device **new_dev) return 0; } +static unsigned long omap3_mpu_get_rate(struct device *dev) +{ + return dpll1_clk->rate; +} + +static int omap3_mpu_set_rate(struct device *dev, unsigned long rate) +{ + int ret; + + ret = clk_set_rate(dpll1_clk, rate); + if (ret) { + dev_warn(dev, "%s: Unable to set rate to %ld\n", + __func__, rate); + return ret; + } + + return 0; +} + +static int omap3_iva_set_rate(struct device *dev, unsigned long rate) +{ + return clk_set_rate(dpll2_clk, rate); +} + +static unsigned long omap3_iva_get_rate(struct device *dev) +{ + return dpll2_clk->rate; +} + +static int omap3_l3_set_rate(struct device *dev, unsigned long rate) +{ + int l3_div; + + l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & + OMAP3430_CLKSEL_L3_MASK; + + return clk_set_rate(dpll3_clk, rate * l3_div); +} + +static unsigned long omap3_l3_get_rate(struct device *dev) +{ + int l3_div; + + l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & + OMAP3430_CLKSEL_L3_MASK; + return dpll3_clk->rate / l3_div; +} + +static int omap4_mpu_set_rate(struct device *dev, unsigned long rate) +{ + int ret; + + ret = clk_set_rate(dpll1_clk, rate); + if (ret) { + dev_warn(dev, "%s: Unable to set rate to %ld\n", + __func__, rate); + return ret; + } + + return 0; +} + +static unsigned long omap4_mpu_get_rate(struct device *dev) +{ + return dpll1_clk->rate; +} + /* * Build omap_devices for processors and bus. */ @@ -90,6 +162,30 @@ static void omap2_init_processor_devices(void) } else { _init_omap_device("l3_main", &l3_dev); } + + if (cpu_is_omap34xx()) { + dpll1_clk = clk_get(NULL, "dpll1_ck"); + dpll2_clk = clk_get(NULL, "dpll2_ck"); + dpll3_clk = clk_get(NULL, "dpll3_m2_ck"); + + if (mpu_dev) + omap_device_register_dvfs_callbacks(mpu_dev, + omap3_mpu_set_rate, omap3_mpu_get_rate); + if (iva_dev) + omap_device_register_dvfs_callbacks(iva_dev, + omap3_iva_set_rate, omap3_iva_get_rate); + if (l3_dev) + omap_device_register_dvfs_callbacks(l3_dev, + omap3_l3_set_rate, omap3_l3_get_rate); + + } else if (cpu_is_omap44xx()) { + dpll1_clk = clk_get(NULL, "dpll_mpu_ck"); + + if (mpu_dev) + omap_device_register_dvfs_callbacks(mpu_dev, + omap4_mpu_set_rate, omap4_mpu_get_rate); + } + } /* Types of sleep_switch used in omap_set_pwrdm_state */ diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 1c1b0ab5b97..797bfd12b64 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void); extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl, void __iomem *sdrc_power); extern void omap34xx_cpu_suspend(u32 *addr, int save_state); -extern void save_secure_ram_context(u32 *addr); +extern int save_secure_ram_context(u32 *addr); extern void omap3_save_scratchpad_contents(void); extern unsigned int omap24xx_idle_loop_suspend_sz; @@ -127,6 +127,7 @@ static inline void omap_enable_smartreflex_on_init(void) {} #ifdef CONFIG_TWL4030_CORE extern int omap3_twl_init(void); extern int omap4_twl_init(void); +extern int omap3_twl_set_sr_bit(bool enable); #else static inline int omap3_twl_init(void) { diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index c7780cc8d91..b5071a47ec3 100644 --- a/arch/arm/mach-omap2/sleep24xx.S +++ b/arch/arm/mach-omap2/sleep24xx.S @@ -47,6 +47,7 @@ * Note: This code get's copied to internal SRAM at boot. When the OMAP * wakes up it continues execution at the point it went to sleep. */ + .align 3 ENTRY(omap24xx_idle_loop_suspend) stmfd sp!, {r0, lr} @ save registers on stack mov r0, #0 @ clear for mcr setup @@ -82,6 +83,7 @@ ENTRY(omap24xx_idle_loop_suspend_sz) * The DLL load value is not kept in RETENTION or OFF. It needs to be restored * at wake */ + .align 3 ENTRY(omap24xx_cpu_suspend) stmfd sp!, {r0 - r12, lr} @ save registers on stack mov r3, #0x0 @ clear for mcr call diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 98d8232808b..6147088e6bc 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -64,6 +64,11 @@ #define SDRC_DLLA_STATUS_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS) #define SDRC_DLLA_CTRL_V OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL) +/* + * This file needs be built unconditionally as ARM to interoperate correctly + * with non-Thumb-2-capable firmware. + */ + .arm /* * API functions @@ -82,6 +87,8 @@ ENTRY(get_restore_pointer) stmfd sp!, {lr} @ save registers on stack adr r0, restore ldmfd sp!, {pc} @ restore regs and return +ENDPROC(get_restore_pointer) + .align ENTRY(get_restore_pointer_sz) .word . - get_restore_pointer @@ -91,6 +98,8 @@ ENTRY(get_omap3630_restore_pointer) stmfd sp!, {lr} @ save registers on stack adr r0, restore_3630 ldmfd sp!, {pc} @ restore regs and return +ENDPROC(get_omap3630_restore_pointer) + .align ENTRY(get_omap3630_restore_pointer_sz) .word . - get_omap3630_restore_pointer @@ -100,6 +109,8 @@ ENTRY(get_es3_restore_pointer) stmfd sp!, {lr} @ save registers on stack adr r0, restore_es3 ldmfd sp!, {pc} @ restore regs and return +ENDPROC(get_es3_restore_pointer) + .align ENTRY(get_es3_restore_pointer_sz) .word . - get_es3_restore_pointer @@ -113,11 +124,14 @@ ENTRY(enable_omap3630_toggle_l2_on_restore) stmfd sp!, {lr} @ save registers on stack /* Setup so that we will disable and enable l2 */ mov r1, #0x1 - str r1, l2dis_3630 + adrl r2, l2dis_3630 @ may be too distant for plain adr + str r1, [r2] ldmfd sp!, {pc} @ restore regs and return +ENDPROC(enable_omap3630_toggle_l2_on_restore) .text /* Function to call rom code to save secure ram context */ + .align 3 ENTRY(save_secure_ram_context) stmfd sp!, {r1-r12, lr} @ save registers on stack adr r3, api_params @ r3 points to parameters @@ -133,18 +147,20 @@ ENTRY(save_secure_ram_context) mov r6, #0xff mcr p15, 0, r0, c7, c10, 4 @ data write barrier mcr p15, 0, r0, c7, c10, 5 @ data memory barrier - .word 0xE1600071 @ call SMI monitor (smi #1) + smc #1 @ call SMI monitor (smi #1) nop nop nop nop ldmfd sp!, {r1-r12, pc} + .align sram_phy_addr_mask: .word SRAM_BASE_P high_mask: .word 0xffff api_params: .word 0x4, 0x0, 0x0, 0x1, 0x1 +ENDPROC(save_secure_ram_context) ENTRY(save_secure_ram_context_sz) .word . - save_secure_ram_context @@ -169,6 +185,7 @@ ENTRY(save_secure_ram_context_sz) * depending on the low power mode (non-OFF vs OFF modes), * cf. 'Resume path for xxx mode' comments. */ + .align 3 ENTRY(omap34xx_cpu_suspend) stmfd sp!, {r0-r12, lr} @ save registers on stack @@ -279,8 +296,18 @@ clean_l2: * - 'might' have to copy address, load and jump to it */ ldr r1, kernel_flush - mov lr, pc - bx r1 + blx r1 + /* + * The kernel doesn't interwork: v7_flush_dcache_all in particluar will + * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled. + * This sequence switches back to ARM. Note that .align may insert a + * nop: bx pc needs to be word-aligned in order to work. + */ + THUMB( .thumb ) + THUMB( .align ) + THUMB( bx pc ) + THUMB( nop ) + .arm omap3_do_wfi: ldr r4, sdrc_power @ read the SDRC_POWER register @@ -346,9 +373,9 @@ restore_es3: and r4, r4, #0x3 cmp r4, #0x0 @ Check if previous power state of CORE is OFF bne restore - adr r0, es3_sdrc_fix + adr r0, _es3_sdrc_fix ldr r1, sram_base - ldr r2, es3_sdrc_fix_sz + ldr r2, _es3_sdrc_fix_sz mov r2, r2, ror #2 copy_to_sram: ldmia r0!, {r3} @ val = *src @@ -408,7 +435,7 @@ skipl2dis: adr r3, l2_inv_api_params @ r3 points to dummy parameters mcr p15, 0, r0, c7, c10, 4 @ data write barrier mcr p15, 0, r0, c7, c10, 5 @ data memory barrier - .word 0xE1600071 @ call SMI monitor (smi #1) + smc #1 @ call SMI monitor (smi #1) /* Write to Aux control register to set some bits */ mov r0, #42 @ set service ID for PPA mov r12, r0 @ copy secure Service ID in r12 @@ -419,7 +446,7 @@ skipl2dis: ldr r3, [r4, #0xBC] @ r3 points to parameters mcr p15, 0, r0, c7, c10, 4 @ data write barrier mcr p15, 0, r0, c7, c10, 5 @ data memory barrier - .word 0xE1600071 @ call SMI monitor (smi #1) + smc #1 @ call SMI monitor (smi #1) #ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE /* Restore L2 aux control register */ @@ -434,27 +461,28 @@ skipl2dis: adds r3, r3, #8 @ r3 points to parameters mcr p15, 0, r0, c7, c10, 4 @ data write barrier mcr p15, 0, r0, c7, c10, 5 @ data memory barrier - .word 0xE1600071 @ call SMI monitor (smi #1) + smc #1 @ call SMI monitor (smi #1) #endif b logic_l1_restore + .align l2_inv_api_params: .word 0x1, 0x00 l2_inv_gp: /* Execute smi to invalidate L2 cache */ mov r12, #0x1 @ set up to invalidate L2 - .word 0xE1600070 @ Call SMI monitor (smieq) + smc #0 @ Call SMI monitor (smieq) /* Write to Aux control register to set some bits */ ldr r4, scratchpad_base ldr r3, [r4,#0xBC] ldr r0, [r3,#4] mov r12, #0x3 - .word 0xE1600070 @ Call SMI monitor (smieq) + smc #0 @ Call SMI monitor (smieq) ldr r4, scratchpad_base ldr r3, [r4,#0xBC] ldr r0, [r3,#12] mov r12, #0x2 - .word 0xE1600070 @ Call SMI monitor (smieq) + smc #0 @ Call SMI monitor (smieq) logic_l1_restore: ldr r1, l2dis_3630 cmp r1, #0x1 @ Test if L2 re-enable needed on 3630 @@ -607,6 +635,9 @@ usettbr0: /* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */ .text + .align 3 +.type _es3_sdrc_fix, %function +_es3_sdrc_fix: ENTRY(es3_sdrc_fix) ldr r4, sdrc_syscfg @ get config addr ldr r5, [r4] @ get value @@ -634,6 +665,7 @@ ENTRY(es3_sdrc_fix) str r5, [r4] @ kick off refreshes bx lr + .align sdrc_syscfg: .word SDRC_SYSCONFIG_P sdrc_mr_0: @@ -648,6 +680,8 @@ sdrc_emr2_1: .word SDRC_EMR2_1_P sdrc_manual_1: .word SDRC_MANUAL_1_P +ENDPROC(es3_sdrc_fix) +_es3_sdrc_fix_sz: ENTRY(es3_sdrc_fix_sz) .word . - es3_sdrc_fix @@ -682,6 +716,12 @@ wait_sdrc_ready: bic r5, r5, #0x40 str r5, [r4] +/* + * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a + * base instead. + * Be careful not to clobber r7 when maintaining this code. + */ + is_dll_in_lock_mode: /* Is dll in lock mode? */ ldr r4, sdrc_dlla_ctrl @@ -689,10 +729,11 @@ is_dll_in_lock_mode: tst r5, #0x4 bxne lr @ Return if locked /* wait till dll locks */ + adr r7, kick_counter wait_dll_lock_timed: ldr r4, wait_dll_lock_counter add r4, r4, #1 - str r4, wait_dll_lock_counter + str r4, [r7, #wait_dll_lock_counter - kick_counter] ldr r4, sdrc_dlla_status /* Wait 20uS for lock */ mov r6, #8 @@ -718,9 +759,10 @@ kick_dll: dsb ldr r4, kick_counter add r4, r4, #1 - str r4, kick_counter + str r4, [r7] @ kick_counter b wait_dll_lock_timed + .align cm_idlest1_core: .word CM_IDLEST1_CORE_V cm_idlest_ckgen: @@ -763,6 +805,7 @@ kick_counter: .word 0 wait_dll_lock_counter: .word 0 +ENDPROC(omap34xx_cpu_suspend) ENTRY(omap34xx_cpu_suspend_sz) .word . - omap34xx_cpu_suspend diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S index 055310cc77d..ff9b9dbcb30 100644 --- a/arch/arm/mach-omap2/sram242x.S +++ b/arch/arm/mach-omap2/sram242x.S @@ -39,6 +39,7 @@ .text + .align 3 ENTRY(omap242x_sram_ddr_init) stmfd sp!, {r0 - r12, lr} @ save registers on stack @@ -143,6 +144,7 @@ ENTRY(omap242x_sram_ddr_init_sz) * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR] * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0 */ + .align 3 ENTRY(omap242x_sram_reprogram_sdrc) stmfd sp!, {r0 - r10, lr} @ save registers on stack mov r3, #0x0 @ clear for mrc call @@ -238,6 +240,7 @@ ENTRY(omap242x_sram_reprogram_sdrc_sz) /* * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode. */ + .align 3 ENTRY(omap242x_sram_set_prcm) stmfd sp!, {r0-r12, lr} @ regs to stack adr r4, pbegin @ addr of preload start diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S index f9007580aea..76730209fa0 100644 --- a/arch/arm/mach-omap2/sram243x.S +++ b/arch/arm/mach-omap2/sram243x.S @@ -39,6 +39,7 @@ .text + .align 3 ENTRY(omap243x_sram_ddr_init) stmfd sp!, {r0 - r12, lr} @ save registers on stack @@ -143,6 +144,7 @@ ENTRY(omap243x_sram_ddr_init_sz) * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR] * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0 */ + .align 3 ENTRY(omap243x_sram_reprogram_sdrc) stmfd sp!, {r0 - r10, lr} @ save registers on stack mov r3, #0x0 @ clear for mrc call @@ -238,6 +240,7 @@ ENTRY(omap243x_sram_reprogram_sdrc_sz) /* * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode. */ + .align 3 ENTRY(omap243x_sram_set_prcm) stmfd sp!, {r0-r12, lr} @ regs to stack adr r4, pbegin @ addr of preload start diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 7f893a29d50..13a8eba81d6 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -34,6 +34,12 @@ #include "sdrc.h" #include "cm2xxx_3xxx.h" +/* + * This file needs be built unconditionally as ARM to interoperate correctly + * with non-Thumb-2-capable firmware. + */ + .arm + .text /* r1 parameters */ @@ -111,29 +117,42 @@ * since it will cause the ARM MMU to attempt to walk the page tables. * These crashes may be intermittent. */ + .align 3 ENTRY(omap3_sram_configure_core_dpll) stmfd sp!, {r1-r12, lr} @ store regs to stack @ pull the extra args off the stack @ and store them in SRAM + +/* + * PC-relative stores are deprecated in ARMv7 and lead to undefined behaviour + * in Thumb-2: use a r7 as a base instead. + * Be careful not to clobber r7 when maintaing this file. + */ + THUMB( adr r7, omap3_sram_configure_core_dpll ) + .macro strtext Rt:req, label:req + ARM( str \Rt, \label ) + THUMB( str \Rt, [r7, \label - omap3_sram_configure_core_dpll] ) + .endm + ldr r4, [sp, #52] - str r4, omap_sdrc_rfr_ctrl_0_val + strtext r4, omap_sdrc_rfr_ctrl_0_val ldr r4, [sp, #56] - str r4, omap_sdrc_actim_ctrl_a_0_val + strtext r4, omap_sdrc_actim_ctrl_a_0_val ldr r4, [sp, #60] - str r4, omap_sdrc_actim_ctrl_b_0_val + strtext r4, omap_sdrc_actim_ctrl_b_0_val ldr r4, [sp, #64] - str r4, omap_sdrc_mr_0_val + strtext r4, omap_sdrc_mr_0_val ldr r4, [sp, #68] - str r4, omap_sdrc_rfr_ctrl_1_val + strtext r4, omap_sdrc_rfr_ctrl_1_val cmp r4, #0 @ if SDRC_RFR_CTRL_1 is 0, beq skip_cs1_params @ do not use cs1 params ldr r4, [sp, #72] - str r4, omap_sdrc_actim_ctrl_a_1_val + strtext r4, omap_sdrc_actim_ctrl_a_1_val ldr r4, [sp, #76] - str r4, omap_sdrc_actim_ctrl_b_1_val + strtext r4, omap_sdrc_actim_ctrl_b_1_val ldr r4, [sp, #80] - str r4, omap_sdrc_mr_1_val + strtext r4, omap_sdrc_mr_1_val skip_cs1_params: mrc p15, 0, r8, c1, c0, 0 @ read ctrl register bic r10, r8, #0x800 @ clear Z-bit, disable branch prediction @@ -271,6 +290,7 @@ skip_cs1_prog: ldr r12, [r11] @ posted-write barrier for SDRC bx lr + .align omap3_sdrc_power: .word OMAP34XX_SDRC_REGADDR(SDRC_POWER) omap3_cm_clksel1_pll: @@ -319,6 +339,7 @@ omap3_sdrc_dlla_ctrl: .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL) core_m2_mask_val: .word 0x07FFFFFF +ENDPROC(omap3_sram_configure_core_dpll) ENTRY(omap3_sram_configure_core_dpll_sz) .word . - omap3_sram_configure_core_dpll diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index 12be525b8df..f5d591a5088 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -39,123 +39,6 @@ #define VP_TRANXDONE_TIMEOUT 300 #define VOLTAGE_DIR_SIZE 16 -/* Voltage processor register offsets */ -struct vp_reg_offs { - u8 vpconfig; - u8 vstepmin; - u8 vstepmax; - u8 vlimitto; - u8 vstatus; - u8 voltage; -}; - -/* Voltage Processor bit field values, shifts and masks */ -struct vp_reg_val { - /* PRM module */ - u16 prm_mod; - /* VPx_VPCONFIG */ - u32 vpconfig_erroroffset; - u16 vpconfig_errorgain; - u32 vpconfig_errorgain_mask; - u8 vpconfig_errorgain_shift; - u32 vpconfig_initvoltage_mask; - u8 vpconfig_initvoltage_shift; - u32 vpconfig_timeouten; - u32 vpconfig_initvdd; - u32 vpconfig_forceupdate; - u32 vpconfig_vpenable; - /* VPx_VSTEPMIN */ - u8 vstepmin_stepmin; - u16 vstepmin_smpswaittimemin; - u8 vstepmin_stepmin_shift; - u8 vstepmin_smpswaittimemin_shift; - /* VPx_VSTEPMAX */ - u8 vstepmax_stepmax; - u16 vstepmax_smpswaittimemax; - u8 vstepmax_stepmax_shift; - u8 vstepmax_smpswaittimemax_shift; - /* VPx_VLIMITTO */ - u8 vlimitto_vddmin; - u8 vlimitto_vddmax; - u16 vlimitto_timeout; - u8 vlimitto_vddmin_shift; - u8 vlimitto_vddmax_shift; - u8 vlimitto_timeout_shift; - /* PRM_IRQSTATUS*/ - u32 tranxdone_status; -}; - -/* Voltage controller registers and offsets */ -struct vc_reg_info { - /* PRM module */ - u16 prm_mod; - /* VC register offsets */ - u8 smps_sa_reg; - u8 smps_volra_reg; - u8 bypass_val_reg; - u8 cmdval_reg; - u8 voltsetup_reg; - /*VC_SMPS_SA*/ - u8 smps_sa_shift; - u32 smps_sa_mask; - /* VC_SMPS_VOL_RA */ - u8 smps_volra_shift; - u32 smps_volra_mask; - /* VC_BYPASS_VAL */ - u8 data_shift; - u8 slaveaddr_shift; - u8 regaddr_shift; - u32 valid; - /* VC_CMD_VAL */ - u8 cmd_on_shift; - u8 cmd_onlp_shift; - u8 cmd_ret_shift; - u8 cmd_off_shift; - u32 cmd_on_mask; - /* PRM_VOLTSETUP */ - u8 voltsetup_shift; - u32 voltsetup_mask; -}; - -/** - * omap_vdd_info - Per Voltage Domain info - * - * @volt_data : voltage table having the distinct voltages supported - * by the domain and other associated per voltage data. - * @pmic_info : pmic specific parameters which should be populted by - * the pmic drivers. - * @vp_offs : structure containing the offsets for various - * vp registers - * @vp_reg : the register values, shifts, masks for various - * vp registers - * @vc_reg : structure containing various various vc registers, - * shifts, masks etc. - * @voltdm : pointer to the voltage domain structure - * @debug_dir : debug directory for this voltage domain. - * @curr_volt : current voltage for this vdd. - * @ocp_mod : The prm module for accessing the prm irqstatus reg. - * @prm_irqst_reg : prm irqstatus register. - * @vp_enabled : flag to keep track of whether vp is enabled or not - * @volt_scale : API to scale the voltage of the vdd. - */ -struct omap_vdd_info { - struct omap_volt_data *volt_data; - struct omap_volt_pmic_info *pmic_info; - struct vp_reg_offs vp_offs; - struct vp_reg_val vp_reg; - struct vc_reg_info vc_reg; - struct voltagedomain voltdm; - struct dentry *debug_dir; - u32 curr_volt; - u16 ocp_mod; - u8 prm_irqst_reg; - bool vp_enabled; - u32 (*read_reg) (u16 mod, u8 offset); - void (*write_reg) (u32 val, u16 mod, u8 offset); - int (*volt_scale) (struct omap_vdd_info *vdd, - unsigned long target_volt); -}; - static struct omap_vdd_info *vdd_info; /* * Number of scalable voltage domains. @@ -308,6 +191,39 @@ static struct omap_volt_data omap44xx_vdd_core_volt_data[] = { VOLT_DATA_DEFINE(0, 0, 0, 0), }; +/* OMAP 3430 MPU Core VDD dependency table */ +static struct omap_vdd_dep_volt omap34xx_vdd1_vdd2_data[] = { + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP1_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP2_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP2_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP2_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP3_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP3_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP4_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP3_UV}, + {.main_vdd_volt = OMAP3430_VDD_MPU_OPP5_UV, .dep_vdd_volt = OMAP3430_VDD_CORE_OPP3_UV}, + {.main_vdd_volt = 0, .dep_vdd_volt = 0}, +}; + +static struct omap_vdd_dep_info omap34xx_vdd1_dep_info[] = { + { + .name = "core", + .dep_table = omap34xx_vdd1_vdd2_data, + }, +}; + +/* OMAP 3630 MPU Core VDD dependency table */ +static struct omap_vdd_dep_volt omap36xx_vdd1_vdd2_data[] = { + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP50_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP50_UV}, + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP100_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP120_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = OMAP3630_VDD_MPU_OPP1G_UV, .dep_vdd_volt = OMAP3630_VDD_CORE_OPP100_UV}, + {.main_vdd_volt = 0, .dep_vdd_volt = 0}, +}; + +static struct omap_vdd_dep_info omap36xx_vdd1_dep_info[] = { + { + .name = "core", + .dep_table = omap36xx_vdd1_vdd2_data, + }, +}; + static struct dentry *voltage_dir; /* Init function pointers */ @@ -814,10 +730,15 @@ static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd) } if (!strcmp(vdd->voltdm.name, "mpu")) { - if (cpu_is_omap3630()) + if (cpu_is_omap3630()) { vdd->volt_data = omap36xx_vddmpu_volt_data; - else + vdd->dep_vdd_info = omap36xx_vdd1_dep_info; + vdd->nr_dep_vdd = ARRAY_SIZE(omap36xx_vdd1_dep_info); + } else { vdd->volt_data = omap34xx_vddmpu_volt_data; + vdd->dep_vdd_info = omap34xx_vdd1_dep_info; + vdd->nr_dep_vdd = ARRAY_SIZE(omap34xx_vdd1_dep_info); + } vdd->vp_reg.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK; vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET; diff --git a/arch/arm/mach-orion5x/include/mach/memory.h b/arch/arm/mach-orion5x/include/mach/memory.h index 52a2955d0f8..6769917882f 100644 --- a/arch/arm/mach-orion5x/include/mach/memory.h +++ b/arch/arm/mach-orion5x/include/mach/memory.h @@ -7,6 +7,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-pnx4008/include/mach/memory.h b/arch/arm/mach-pnx4008/include/mach/memory.h index 0e877008105..1275db61cee 100644 --- a/arch/arm/mach-pnx4008/include/mach/memory.h +++ b/arch/arm/mach-pnx4008/include/mach/memory.h @@ -16,6 +16,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index a134a1413e0..e194d928cda 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -829,5 +829,5 @@ MACHINE_START(BALLOON3, "Balloon3") .init_irq = balloon3_init_irq, .timer = &pxa_timer, .init_machine = balloon3_init, - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, MACHINE_END diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h index 92361a66b22..7f68724dcc2 100644 --- a/arch/arm/mach-pxa/include/mach/memory.h +++ b/arch/arm/mach-pxa/include/mach/memory.h @@ -15,7 +15,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xa0000000) +#define PLAT_PHYS_OFFSET UL(0xa0000000) #if !defined(__ASSEMBLY__) && defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) void cmx2xx_pci_adjust_zones(unsigned long *size, unsigned long *holes); diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 7ca138a943a..b9a9805e482 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -19,7 +19,7 @@ config REALVIEW_EB_A9MP config REALVIEW_EB_ARM11MP bool "Support ARM11MPCore Tile" depends on MACH_REALVIEW_EB - select CPU_V6 + select CPU_V6K select ARCH_HAS_BARRIERS if SMP help Enable support for the ARM11MPCore tile fitted to the Realview(R) @@ -36,7 +36,7 @@ config REALVIEW_EB_ARM11MP_REVB config MACH_REALVIEW_PB11MP bool "Support RealView(R) Platform Baseboard for ARM11MPCore" - select CPU_V6 + select CPU_V6K select ARM_GIC select HAVE_PATA_PLATFORM select ARCH_HAS_BARRIERS if SMP @@ -45,6 +45,7 @@ config MACH_REALVIEW_PB11MP the ARM11MPCore. This platform has an on-board ARM11MPCore and has support for PCI-E and Compact Flash. +# ARMv6 CPU without K extensions, but does have the new exclusive ops config MACH_REALVIEW_PB1176 bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S" select CPU_V6 diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h index 5dafc157b27..e05fc2c4c08 100644 --- a/arch/arm/mach-realview/include/mach/memory.h +++ b/arch/arm/mach-realview/include/mach/memory.h @@ -24,9 +24,9 @@ * Physical DRAM offset. */ #ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET -#define PHYS_OFFSET UL(0x70000000) +#define PLAT_PHYS_OFFSET UL(0x70000000) #else -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif #if !defined(__ASSEMBLY__) && defined(CONFIG_ZONE_DMA) diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 6ef5c5e528b..8ede983b861 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -484,7 +484,7 @@ static void __init realview_eb_init(void) MACHINE_START(REALVIEW_EB, "ARM-RealView EB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_eb_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index cbdc97a5685..9f26369555c 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -379,7 +379,7 @@ static void __init realview_pb1176_init(void) MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_pb1176_fixup, .map_io = realview_pb1176_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 8e8ab7d29a6..dea06b2da3a 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -381,7 +381,7 @@ static void __init realview_pb11mp_init(void) MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_pb11mp_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 841118e3e11..7d0f1734a21 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -331,7 +331,7 @@ static void __init realview_pba8_init(void) MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_pba8_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 02b755b009d..b89e28f8853 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -414,7 +414,7 @@ static void __init realview_pbx_init(void) MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_pbx_fixup, .map_io = realview_pbx_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-rpc/include/mach/memory.h b/arch/arm/mach-rpc/include/mach/memory.h index 78191bf2519..18a221093bf 100644 --- a/arch/arm/mach-rpc/include/mach/memory.h +++ b/arch/arm/mach-rpc/include/mach/memory.h @@ -21,7 +21,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) /* * Cache flushing area - ROM diff --git a/arch/arm/mach-s3c2400/include/mach/memory.h b/arch/arm/mach-s3c2400/include/mach/memory.h index cf5901ffd38..3f33670dd01 100644 --- a/arch/arm/mach-s3c2400/include/mach/memory.h +++ b/arch/arm/mach-s3c2400/include/mach/memory.h @@ -15,6 +15,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x0C000000) +#define PLAT_PHYS_OFFSET UL(0x0C000000) #endif diff --git a/arch/arm/mach-s3c2410/include/mach/memory.h b/arch/arm/mach-s3c2410/include/mach/memory.h index 6f1e5871ae4..f92b97b89c0 100644 --- a/arch/arm/mach-s3c2410/include/mach/memory.h +++ b/arch/arm/mach-s3c2410/include/mach/memory.h @@ -11,6 +11,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x30000000) +#define PLAT_PHYS_OFFSET UL(0x30000000) #endif diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 2970ea9f7c2..18187a48a55 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -213,7 +213,7 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { /* NAND Flash on BAST board */ -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static int bast_pm_suspend(struct sys_device *sd, pm_message_t state) { /* ensure that an nRESET is not generated on resume. */ diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c index 923e01bdf01..10643ef84eb 100644 --- a/arch/arm/mach-s3c2412/mach-jive.c +++ b/arch/arm/mach-s3c2412/mach-jive.c @@ -485,7 +485,7 @@ static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = { /* Jive power management device */ -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static int jive_pm_suspend(struct sys_device *sd, pm_message_t state) { /* Write the magic value u-boot uses to check for resume into diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index 14dc6789775..06d115aae7d 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -281,7 +281,7 @@ static struct platform_device osiris_pcmcia = { /* Osiris power management device */ -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static unsigned char pm_osiris_ctrl0; static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state) diff --git a/arch/arm/mach-s3c2440/s3c244x.c b/arch/arm/mach-s3c2440/s3c244x.c index 90c1707b9c9..7e693a082f4 100644 --- a/arch/arm/mach-s3c2440/s3c244x.c +++ b/arch/arm/mach-s3c2440/s3c244x.c @@ -134,7 +134,7 @@ void __init s3c244x_init_clocks(int xtal) s3c2410_baseclk_add(); } -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static struct sleep_save s3c244x_sleep[] = { SAVE_ITEM(S3C2440_DSC0), diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h index 7d74fd5c8d6..7d208a71b17 100644 --- a/arch/arm/mach-s3c24a0/include/mach/memory.h +++ b/arch/arm/mach-s3c24a0/include/mach/memory.h @@ -11,7 +11,7 @@ #ifndef __ASM_ARCH_24A0_MEMORY_H #define __ASM_ARCH_24A0_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) #define __virt_to_bus(x) __virt_to_phys(x) #define __bus_to_virt(x) __phys_to_virt(x) diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index 4657363f067..183ebb395ed 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -43,9 +43,9 @@ obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o # PM -obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_PM) += sleep.o -obj-$(CONFIG_PM) += irq-pm.o +obj-$(CONFIG_SUSPEND) += pm.o +obj-$(CONFIG_SUSPEND) += sleep.o +obj-$(CONFIG_SUSPEND) += irq-pm.o # Machine support diff --git a/arch/arm/mach-s3c64xx/include/mach/memory.h b/arch/arm/mach-s3c64xx/include/mach/memory.h index 42cc54e2ee3..4760cdae1eb 100644 --- a/arch/arm/mach-s3c64xx/include/mach/memory.h +++ b/arch/arm/mach-s3c64xx/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x50000000) +#define PLAT_PHYS_OFFSET UL(0x50000000) #define CONSISTENT_DMA_SIZE SZ_8M diff --git a/arch/arm/mach-s5p6442/include/mach/memory.h b/arch/arm/mach-s5p6442/include/mach/memory.h index 9ddd877ba2e..cfe259dded3 100644 --- a/arch/arm/mach-s5p6442/include/mach/memory.h +++ b/arch/arm/mach-s5p6442/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE SZ_8M #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h index 1b036b0a24c..365a6eb4b88 100644 --- a/arch/arm/mach-s5p64x0/include/mach/memory.h +++ b/arch/arm/mach-s5p64x0/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE SZ_8M #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/memory.h b/arch/arm/mach-s5pc100/include/mach/memory.h index 4b60d18179f..bda4e79fd5f 100644 --- a/arch/arm/mach-s5pc100/include/mach/memory.h +++ b/arch/arm/mach-s5pc100/include/mach/memory.h @@ -13,6 +13,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #endif diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c index a6f22920a2c..7e697cdf698 100644 --- a/arch/arm/mach-s5pv210/cpufreq.c +++ b/arch/arm/mach-s5pv210/cpufreq.c @@ -389,7 +389,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) { @@ -470,7 +470,7 @@ static struct cpufreq_driver s5pv210_driver = { .get = s5pv210_getspeed, .init = s5pv210_cpu_init, .name = "s5pv210", -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND .suspend = s5pv210_cpufreq_suspend, .resume = s5pv210_cpufreq_resume, #endif diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h index d503e0c4ce4..7b5fcf0da0c 100644 --- a/arch/arm/mach-s5pv210/include/mach/memory.h +++ b/arch/arm/mach-s5pv210/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE (SZ_8M + SZ_4M + SZ_2M) /* diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S index d4d222b716b..27376223ea9 100644 --- a/arch/arm/mach-s5pv210/sleep.S +++ b/arch/arm/mach-s5pv210/sleep.S @@ -65,7 +65,7 @@ resume_with_mmu: /* * After MMU is turned on, restore the previous MMU table. */ - ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET) + ldr r9 , =(PAGE_OFFSET - PLAT_PHYS_OFFSET) add r4, r4, r9 str r12, [r4] diff --git a/arch/arm/mach-s5pv310/cpufreq.c b/arch/arm/mach-s5pv310/cpufreq.c index b04cbc73112..8493b6d05fb 100644 --- a/arch/arm/mach-s5pv310/cpufreq.c +++ b/arch/arm/mach-s5pv310/cpufreq.c @@ -457,7 +457,7 @@ static int s5pv310_target(struct cpufreq_policy *policy, return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static int s5pv310_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) { @@ -497,7 +497,7 @@ static struct cpufreq_driver s5pv310_driver = { .get = s5pv310_getspeed, .init = s5pv310_cpufreq_cpu_init, .name = "s5pv310_cpufreq", -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND .suspend = s5pv310_cpufreq_suspend, .resume = s5pv310_cpufreq_resume, #endif diff --git a/arch/arm/mach-s5pv310/include/mach/memory.h b/arch/arm/mach-s5pv310/include/mach/memory.h index 1dffb482324..470b01bf861 100644 --- a/arch/arm/mach-s5pv310/include/mach/memory.h +++ b/arch/arm/mach-s5pv310/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x40000000) +#define PLAT_PHYS_OFFSET UL(0x40000000) /* Maximum of 256MiB in one bank */ #define MAX_PHYSMEM_BITS 32 diff --git a/arch/arm/mach-s5pv310/irq-eint.c b/arch/arm/mach-s5pv310/irq-eint.c index 477bd9e97f0..39c7f7b2d7b 100644 --- a/arch/arm/mach-s5pv310/irq-eint.c +++ b/arch/arm/mach-s5pv310/irq-eint.c @@ -152,7 +152,7 @@ static struct irq_chip s5pv310_irq_eint = { .irq_mask_ack = s5pv310_irq_eint_maskack, .irq_ack = s5pv310_irq_eint_ack, .irq_set_type = s5pv310_irq_eint_set_type, -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND .irq_set_wake = s3c_irqext_wake, #endif }; diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h index 128a1dfa96b..a44da6a2916 100644 --- a/arch/arm/mach-sa1100/include/mach/memory.h +++ b/arch/arm/mach-sa1100/include/mach/memory.h @@ -12,7 +12,7 @@ /* * Physical DRAM offset is 0xc0000000 on the SA1100 */ -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h index d9c4812f1c3..9afb1700000 100644 --- a/arch/arm/mach-shark/include/mach/memory.h +++ b/arch/arm/mach-shark/include/mach/memory.h @@ -15,7 +15,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x08000000) +#define PLAT_PHYS_OFFSET UL(0x08000000) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-shmobile/include/mach/memory.h b/arch/arm/mach-shmobile/include/mach/memory.h index 377584e57e0..ad00c3c258f 100644 --- a/arch/arm/mach-shmobile/include/mach/memory.h +++ b/arch/arm/mach-shmobile/include/mach/memory.h @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_MEMORY_H #define __ASM_MACH_MEMORY_H -#define PHYS_OFFSET UL(CONFIG_MEMORY_START) +#define PLAT_PHYS_OFFSET UL(CONFIG_MEMORY_START) #define MEM_SIZE UL(CONFIG_MEMORY_SIZE) /* DMA memory at 0xf6000000 - 0xffdfffff */ diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c index 7991415e666..fb6426ddeb7 100644 --- a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c +++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c @@ -54,7 +54,7 @@ static void __init tcc8k_map_io(void) } MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board") - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .map_io = tcc8k_map_io, .init_irq = tcc8k_init_irq, .init_machine = tcc8k_init, diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index b9dbdb1289d..99884e9dd69 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -113,6 +113,11 @@ static void __init tegra_harmony_init(void) platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices)); } +static const char * tegra_harmony_board_compat[] = { + "nvidia,harmony", + NULL +}; + MACHINE_START(HARMONY, "harmony") .boot_params = 0x00000100, .fixup = tegra_harmony_fixup, @@ -120,4 +125,5 @@ MACHINE_START(HARMONY, "harmony") .init_machine = tegra_harmony_init, .map_io = tegra_map_common_io, .timer = &tegra_timer, + .dt_compat = tegra_harmony_board_compat, MACHINE_END diff --git a/arch/arm/mach-tegra/include/mach/memory.h b/arch/arm/mach-tegra/include/mach/memory.h index 6151bab62af..537db3aa81a 100644 --- a/arch/arm/mach-tegra/include/mach/memory.h +++ b/arch/arm/mach-tegra/include/mach/memory.h @@ -22,7 +22,7 @@ #define __MACH_TEGRA_MEMORY_H /* physical offset of RAM */ -#define PHYS_OFFSET UL(0) +#define PLAT_PHYS_OFFSET UL(0) #endif diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h index bf134bcc129..888e2e351ee 100644 --- a/arch/arm/mach-u300/include/mach/memory.h +++ b/arch/arm/mach-u300/include/mach/memory.h @@ -15,17 +15,17 @@ #ifdef CONFIG_MACH_U300_DUAL_RAM -#define PHYS_OFFSET UL(0x48000000) +#define PLAT_PHYS_OFFSET UL(0x48000000) #define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100) #else #ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX -#define PHYS_OFFSET (0x28000000 + \ +#define PLAT_PHYS_OFFSET (0x28000000 + \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024) #else -#define PHYS_OFFSET (0x28000000 + \ +#define PLAT_PHYS_OFFSET (0x28000000 + \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024) #endif diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c index 07c35a84642..48b3b7f3996 100644 --- a/arch/arm/mach-u300/u300.c +++ b/arch/arm/mach-u300/u300.c @@ -19,9 +19,9 @@ #include <linux/io.h> #include <mach/hardware.h> #include <mach/platform.h> -#include <mach/memory.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/memory.h> static void __init u300_reserve(void) { diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 247caa3400d..203b986280f 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -6,6 +6,7 @@ config UX500_SOC_COMMON select ARM_GIC select HAS_MTU select NOMADIK_GPIO + select ARM_ERRATA_753970 menu "Ux500 SoC" diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 4b996676594..4ba3d930a06 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -106,8 +106,8 @@ void mop500_sdi_tc35892_init(void) if (ret) return; - gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1); - gpio_direction_output(GPIO_SDMMC_EN, 0); + gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 0); + gpio_direction_output(GPIO_SDMMC_EN, 1); db8500_add_sdi0(&mop500_sdi0_data); } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index a393f57ed2a..9119565f159 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -224,3 +224,13 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .timer = &ux500_timer, .init_machine = u8500_init_machine, MACHINE_END + +MACHINE_START(NOMADIK, "ST-Ericsson MOP500 platform") + /* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */ + .boot_params = 0x100, + .map_io = u8500_map_io, + .init_irq = ux500_init_irq, + /* we re-use nomadik timer here */ + .timer = &ux500_timer, + .init_machine = u8500_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index b2b0a3b9be8..9a0a6ed9cd5 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -313,7 +313,7 @@ static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000); static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK); static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */ static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000); -static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 50000000); +static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000); static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK); static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK); static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 1748fbc5853..5c0fabf5fa0 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -12,22 +12,20 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/amba/bus.h> +#include <linux/interrupt.h> #include <linux/irq.h> #include <linux/gpio.h> #include <linux/platform_device.h> #include <linux/io.h> #include <asm/mach/map.h> +#include <asm/pmu.h> #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> #include "devices-db8500.h" -static struct platform_device *platform_devs[] __initdata = { - &u8500_dma40_device, -}; - /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_uart_io_desc[] __initdata = { __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), @@ -89,6 +87,51 @@ void __init u8500_map_io(void) iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); } +static struct resource db8500_pmu_resources[] = { + [0] = { + .start = IRQ_DB8500_PMU, + .end = IRQ_DB8500_PMU, + .flags = IORESOURCE_IRQ, + }, +}; + +/* + * The PMU IRQ lines of two cores are wired together into a single interrupt. + * Bounce the interrupt to the other core if it's not ours. + */ +static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler) +{ + irqreturn_t ret = handler(irq, dev); + int other = !smp_processor_id(); + + if (ret == IRQ_NONE && cpu_online(other)) + irq_set_affinity(irq, cpumask_of(other)); + + /* + * We should be able to get away with the amount of IRQ_NONEs we give, + * while still having the spurious IRQ detection code kick in if the + * interrupt really starts hitting spuriously. + */ + return ret; +} + +static struct arm_pmu_platdata db8500_pmu_platdata = { + .handle_irq = db8500_pmu_handler, +}; + +static struct platform_device db8500_pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = ARRAY_SIZE(db8500_pmu_resources), + .resource = db8500_pmu_resources, + .dev.platform_data = &db8500_pmu_platdata, +}; + +static struct platform_device *platform_devs[] __initdata = { + &u8500_dma40_device, + &db8500_pmu_device, +}; + static resource_size_t __initdata db8500_gpio_base[] = { U8500_GPIOBANK0_BASE, U8500_GPIOBANK1_BASE, diff --git a/arch/arm/mach-ux500/include/mach/memory.h b/arch/arm/mach-ux500/include/mach/memory.h index 510571a59e2..2ef697a6700 100644 --- a/arch/arm/mach-ux500/include/mach/memory.h +++ b/arch/arm/mach-ux500/include/mach/memory.h @@ -12,7 +12,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define BUS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-versatile/include/mach/memory.h b/arch/arm/mach-versatile/include/mach/memory.h index 79aeab86b90..dacc9d8e4e6 100644 --- a/arch/arm/mach-versatile/include/mach/memory.h +++ b/arch/arm/mach-versatile/include/mach/memory.h @@ -23,6 +23,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c index aa9730fb13b..62053dfd54c 100644 --- a/arch/arm/mach-versatile/versatile_ab.c +++ b/arch/arm/mach-versatile/versatile_ab.c @@ -33,6 +33,11 @@ #include "core.h" +static const char *versatile_ab_match[] __initdata = { + "arm,versatile-ab", + NULL, +}; + MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .boot_params = 0x00000100, @@ -40,4 +45,5 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") .init_irq = versatile_init_irq, .timer = &versatile_timer, .init_machine = versatile_init, + .dt_compat = versatile_ab_match, MACHINE_END diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c index bf469642a3f..eba12fa1db0 100644 --- a/arch/arm/mach-versatile/versatile_pb.c +++ b/arch/arm/mach-versatile/versatile_pb.c @@ -106,6 +106,11 @@ static void __init versatile_pb_init(void) } } +static const char *versatile_pb_match[] __initdata = { + "arm,versatile-pb", + NULL, +}; + MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .boot_params = 0x00000100, @@ -113,4 +118,5 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") .init_irq = versatile_init_irq, .timer = &versatile_timer, .init_machine = versatile_pb_init, + .dt_compat = versatile_pb_match, MACHINE_END diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index 3f19b660a16..931148487f0 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -5,5 +5,8 @@ config ARCH_VEXPRESS_CA9X4 bool "Versatile Express Cortex-A9x4 tile" select CPU_V7 select ARM_GIC + select ARM_ERRATA_720789 + select ARM_ERRATA_751472 + select ARM_ERRATA_753970 endmenu diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index e628402b754..e9bccc5230c 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -243,7 +243,7 @@ static void __init ct_ca9x4_init(void) } MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .map_io = ct_ca9x4_map_io, .init_irq = ct_ca9x4_init_irq, #if 0 diff --git a/arch/arm/mach-vexpress/include/mach/memory.h b/arch/arm/mach-vexpress/include/mach/memory.h index be28232ae63..5b7fcd439d8 100644 --- a/arch/arm/mach-vexpress/include/mach/memory.h +++ b/arch/arm/mach-vexpress/include/mach/memory.h @@ -20,6 +20,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x60000000) +#define PLAT_PHYS_OFFSET UL(0x60000000) #endif diff --git a/arch/arm/mach-w90x900/include/mach/memory.h b/arch/arm/mach-w90x900/include/mach/memory.h index 971b80702c2..f02905ba774 100644 --- a/arch/arm/mach-w90x900/include/mach/memory.h +++ b/arch/arm/mach-w90x900/include/mach/memory.h @@ -18,6 +18,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index e4509bae8fc..89266382b53 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -390,7 +390,7 @@ config CPU_PJ4 # ARMv6 config CPU_V6 - bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_DOVE + bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX select CPU_32v6 select CPU_ABRT_EV6 select CPU_PABRT_V6 @@ -402,16 +402,18 @@ config CPU_V6 select CPU_TLB_V6 if MMU # ARMv6k -config CPU_32v6K - bool "Support ARM V6K processor extensions" if !SMP - depends on CPU_V6 || CPU_V7 - default y if SMP - help - Say Y here if your ARMv6 processor supports the 'K' extension. - This enables the kernel to use some instructions not present - on previous processors, and as such a kernel build with this - enabled will not boot on processors with do not support these - instructions. +config CPU_V6K + bool "Support ARM V6K processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX + select CPU_32v6 + select CPU_32v6K + select CPU_ABRT_EV6 + select CPU_PABRT_V6 + select CPU_CACHE_V6 + select CPU_CACHE_VIPT + select CPU_CP15_MMU + select CPU_HAS_ASID if MMU + select CPU_COPY_V6 if MMU + select CPU_TLB_V6 if MMU # ARMv7 config CPU_V7 @@ -433,25 +435,33 @@ config CPU_32v3 bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v4 bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v4T bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v5 bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v6 bool select TLS_REG_EMUL if !CPU_32v6K && !MMU + select CPU_USE_DOMAINS if CPU_V6 && MMU + +config CPU_32v6K + bool config CPU_32v7 bool @@ -607,8 +617,6 @@ config CPU_CP15_MPU config CPU_USE_DOMAINS bool - depends on MMU - default y if !CPU_32v6K help This option enables or disables the use of domain switching via the set_fs() function. @@ -623,7 +631,7 @@ comment "Processor Features" config ARM_THUMB bool "Support Thumb user binaries" - depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V7 || CPU_FEROCEON + depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON default y help Say Y if you want to include kernel support for running user space @@ -644,7 +652,7 @@ config ARM_THUMBEE config SWP_EMULATE bool "Emulate SWP/SWPB instructions" - depends on !CPU_USE_DOMAINS && CPU_V7 && !CPU_V6 + depends on !CPU_USE_DOMAINS && CPU_V7 select HAVE_PROC_CPU if PROC_FS default y if SMP help @@ -681,7 +689,7 @@ config CPU_BIG_ENDIAN config CPU_ENDIAN_BE8 bool depends on CPU_BIG_ENDIAN - default CPU_V6 || CPU_V7 + default CPU_V6 || CPU_V6K || CPU_V7 help Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors. @@ -747,7 +755,7 @@ config CPU_CACHE_ROUND_ROBIN config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526 + depends on CPU_ARM1020 || CPU_V6 || CPU_V6K || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526 help Say Y here to disable branch prediction. If unsure, say N. @@ -767,7 +775,7 @@ config NEEDS_SYSCALL_FOR_CMPXCHG config DMA_CACHE_RWFO bool "Enable read/write for ownership DMA cache maintenance" - depends on CPU_V6 && SMP + depends on CPU_V6K && SMP default y help The Snoop Control Unit on ARM11MPCore does not detect the @@ -823,7 +831,7 @@ config CACHE_L2X0 config CACHE_PL310 bool depends on CACHE_L2X0 - default y if CPU_V7 && !CPU_V6 + default y if CPU_V7 && !(CPU_V6 || CPU_V6K) help This option enables optimisations for the PL310 cache controller. @@ -845,16 +853,21 @@ config CACHE_XSC3L2 help This option enables the L2 cache on XScale3. +config ARM_L1_CACHE_SHIFT_6 + bool + help + Setting ARM L1 cache line size to 64 Bytes. + config ARM_L1_CACHE_SHIFT int default 6 if ARM_L1_CACHE_SHIFT_6 default 5 config ARM_DMA_MEM_BUFFERABLE - bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7 + bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7 depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \ MACH_REALVIEW_PB11MP) - default y if CPU_V6 || CPU_V7 + default y if CPU_V6 || CPU_V6K || CPU_V7 help Historically, the kernel has used strongly ordered mappings to provide DMA coherent memory. With the advent of ARMv7, mapping diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 00d74a04af3..bca7e61928c 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o obj-$(CONFIG_CPU_MOHAWK) += proc-mohawk.o obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o obj-$(CONFIG_CPU_V6) += proc-v6.o +obj-$(CONFIG_CPU_V6K) += proc-v6.o obj-$(CONFIG_CPU_V7) += proc-v7.o AFLAGS_proc-v6.o :=-Wa,-march=armv6 diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index f332df7f0d3..1478aa52214 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S @@ -20,11 +20,11 @@ */ .align 5 ENTRY(v6_early_abort) -#ifdef CONFIG_CPU_32v6K - clrex -#else +#ifdef CONFIG_CPU_V6 sub r1, sp, #4 @ Get unused stack location strex r0, r1, [r1] @ Clear the exclusive monitor +#elif defined(CONFIG_CPU_32v6K) + clrex #endif mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index cddd684364d..8e3387cadaf 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -15,12 +15,14 @@ #include <linux/mman.h> #include <linux/nodemask.h> #include <linux/initrd.h> +#include <linux/of_fdt.h> #include <linux/highmem.h> #include <linux/gfp.h> #include <linux/memblock.h> #include <linux/sort.h> #include <asm/mach-types.h> +#include <asm/prom.h> #include <asm/sections.h> #include <asm/setup.h> #include <asm/sizes.h> @@ -71,6 +73,14 @@ static int __init parse_tag_initrd2(const struct tag *tag) __tagtable(ATAG_INITRD2, parse_tag_initrd2); +#ifdef CONFIG_OF_FLATTREE +void __init early_init_dt_setup_initrd_arch(unsigned long start, unsigned long end) +{ + phys_initrd_start = start; + phys_initrd_size = end - start + 1; +} +#endif /* CONFIG_OF_FLATTREE */ + /* * This keeps memory configuration data used by a couple memory * initialization functions, as well as show_mem() for the skipping @@ -313,6 +323,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) #endif arm_mm_memblock_reserve(); + arm_dt_memblock_reserve(); /* reserve any platform specific memblock areas */ if (mdesc->reserve) diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index b0a98305055..afe209e1e1f 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -31,7 +31,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned long start_addr; -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) unsigned int cache_type; int do_align = 0, aliasing = 0; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 3c67e92f7d5..ff7b43b5885 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -827,16 +827,6 @@ static void __init sanity_check_meminfo(void) * rather difficult. */ reason = "with VIPT aliasing cache"; - } else if (is_smp() && tlb_ops_need_broadcast()) { - /* - * kmap_high needs to occasionally flush TLB entries, - * however, if the TLB entries need to be broadcast - * we may deadlock: - * kmap_high(irqs off)->flush_all_zero_pkmaps-> - * flush_tlb_kernel_range->smp_call_function_many - * (must not be called with irqs off) - */ - reason = "without hardware TLB ops broadcasting"; } if (reason) { printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n", diff --git a/arch/arm/mm/vmregion.c b/arch/arm/mm/vmregion.c index 935993e1b1e..036fdbfdd62 100644 --- a/arch/arm/mm/vmregion.c +++ b/arch/arm/mm/vmregion.c @@ -38,7 +38,7 @@ struct arm_vmregion * arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, size_t size, gfp_t gfp) { - unsigned long addr = head->vm_start, end = head->vm_end - size; + unsigned long start = head->vm_start, addr = head->vm_end; unsigned long flags; struct arm_vmregion *c, *new; @@ -54,21 +54,20 @@ arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, spin_lock_irqsave(&head->vm_lock, flags); - list_for_each_entry(c, &head->vm_list, vm_list) { - if ((addr + size) < addr) - goto nospc; - if ((addr + size) <= c->vm_start) + addr = rounddown(addr - size, align); + list_for_each_entry_reverse(c, &head->vm_list, vm_list) { + if (addr >= c->vm_end) goto found; - addr = ALIGN(c->vm_end, align); - if (addr > end) + addr = rounddown(c->vm_start - size, align); + if (addr < start) goto nospc; } found: /* - * Insert this entry _before_ the one we found. + * Insert this entry after the one we found. */ - list_add_tail(&new->vm_list, &c->vm_list); + list_add(&new->vm_list, &c->vm_list); new->vm_start = addr; new->vm_end = addr + size; new->vm_active = 1; diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 389f2179501..a97f7334bc7 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -119,4 +119,10 @@ config IRAM_ALLOC bool select GENERIC_ALLOCATOR +config CLK_DEBUG + bool "clock debug information export to user space" + depends on PM_DEBUG && DEBUG_FS + default n + help + export clk debug information to user space endif diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c index 2ed3ab173ad..190bce1221a 100644 --- a/arch/arm/plat-mxc/clock.c +++ b/arch/arm/plat-mxc/clock.c @@ -37,6 +37,8 @@ #include <linux/proc_fs.h> #include <linux/semaphore.h> #include <linux/string.h> +#include <linux/slab.h> +#include <linux/debugfs.h> #include <mach/clock.h> #include <mach/hardware.h> @@ -244,3 +246,122 @@ unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq) return ll; } + +#ifdef CONFIG_CLK_DEBUG +/* + * debugfs support to trace clock tree hierarchy and attributes + */ +static int clk_debug_rate_get(void *data, u64 *val) +{ + struct clk *clk = data; + + *val = (u64)clk_get_rate(clk); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(clk_debug_rate_fops, clk_debug_rate_get, NULL, + "%llu\n"); + + +static struct dentry *clk_root; +static int clk_debug_register_one(struct clk *clk) +{ + int err; + struct dentry *d, *child, *child_tmp; + struct clk *pa = clk_get_parent(clk); + + if (pa && !IS_ERR(pa)) + d = debugfs_create_dir(clk->name, pa->dentry); + else { + if (!clk_root) + clk_root = debugfs_create_dir("clock", NULL); + if (!clk_root) + return -ENOMEM; + d = debugfs_create_dir(clk->name, clk_root); + } + + if (!d) + return -ENOMEM; + + clk->dentry = d; + + d = debugfs_create_u32("enable_count", S_IRUGO, clk->dentry, + (u32 *)&clk->usecount); + if (!d) { + err = -ENOMEM; + goto err_out; + } + + d = debugfs_create_file("rate", S_IRUGO, clk->dentry, (void *)clk, + &clk_debug_rate_fops); + if (!d) { + err = -ENOMEM; + goto err_out; + } + + return 0; + +err_out: + d = clk->dentry; + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(clk->dentry); + return err; +} + +struct preinit_clk { + struct list_head list; + struct clk *clk; +}; +static LIST_HEAD(preinit_clks); +static DEFINE_MUTEX(preinit_lock); +static int init_done; + +void clk_debug_register(struct clk *clk) +{ + int err; + struct clk *pa; + + if (init_done) { + pa = clk_get_parent(clk); + + if (pa && !IS_ERR(pa) && !pa->dentry) + clk_debug_register(pa); + + if (!clk->dentry) { + err = clk_debug_register_one(clk); + if (err) + return; + } + } else { + struct preinit_clk *p; + mutex_lock(&preinit_lock); + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (p) { + p->clk = clk; + list_add(&p->list, &preinit_clks); + } + mutex_unlock(&preinit_lock); + } +} +EXPORT_SYMBOL_GPL(clk_debug_register); + +static int __init clk_debugfs_init(void) +{ + struct preinit_clk *pclk, *tmp; + + init_done = 1; + + mutex_lock(&preinit_lock); + list_for_each_entry(pclk, &preinit_clks, list) { + clk_debug_register(pclk->clk); + } + + list_for_each_entry_safe(pclk, tmp, &preinit_clks, list) { + list_del(&pclk->list); + kfree(pclk); + } + mutex_unlock(&preinit_lock); + return 0; +} +late_initcall(clk_debugfs_init); +#endif diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h index 753a5988d85..fb0e0bd3f51 100644 --- a/arch/arm/plat-mxc/include/mach/clock.h +++ b/arch/arm/plat-mxc/include/mach/clock.h @@ -23,9 +23,14 @@ #ifndef __ASSEMBLY__ #include <linux/list.h> +#define CLK_NAME_LEN 32 struct module; struct clk { +#ifdef CONFIG_CLK_DEBUG + char name[CLK_NAME_LEN]; + struct dentry *dentry; +#endif int id; /* Source clock this clk depends on */ struct clk *parent; @@ -62,5 +67,11 @@ void clk_unregister(struct clk *clk); unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref); +#ifdef CONFIG_CLK_DEBUG +void clk_debug_register(struct clk *clk); +#else +static inline void clk_debug_register(struct clk *clk) {} +#endif + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_MXC_CLOCK_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h index 83861408133..5d51cbb9889 100644 --- a/arch/arm/plat-mxc/include/mach/memory.h +++ b/arch/arm/plat-mxc/include/mach/memory.h @@ -23,23 +23,23 @@ #if !defined(CONFIG_RUNTIME_PHYS_OFFSET) # if defined CONFIG_ARCH_MX1 -# define PHYS_OFFSET MX1_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX1_PHYS_OFFSET # elif defined CONFIG_MACH_MX21 -# define PHYS_OFFSET MX21_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX21_PHYS_OFFSET # elif defined CONFIG_ARCH_MX25 -# define PHYS_OFFSET MX25_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX25_PHYS_OFFSET # elif defined CONFIG_MACH_MX27 -# define PHYS_OFFSET MX27_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX27_PHYS_OFFSET # elif defined CONFIG_ARCH_MX3 -# define PHYS_OFFSET MX3x_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX3x_PHYS_OFFSET # elif defined CONFIG_ARCH_MXC91231 -# define PHYS_OFFSET MXC91231_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MXC91231_PHYS_OFFSET # elif defined CONFIG_ARCH_MX50 -# define PHYS_OFFSET MX50_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX50_PHYS_OFFSET # elif defined CONFIG_ARCH_MX51 -# define PHYS_OFFSET MX51_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX51_PHYS_OFFSET # elif defined CONFIG_ARCH_MX53 -# define PHYS_OFFSET MX53_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX53_PHYS_OFFSET # endif #endif diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index a4a12859fdd..ec7862e9149 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 537f4e449f5..2fb057e1cb9 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -23,6 +23,7 @@ #include <linux/list.h> #include <linux/kobject.h> #include <linux/device.h> +#include <linux/platform_device.h> #include <asm/atomic.h> #define DISPC_IRQ_FRAMEDONE (1 << 0) @@ -226,6 +227,21 @@ struct omap_dss_board_info { struct omap_dss_device *default_device; }; +#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS) +/* Init with the board info */ +extern int omap_display_init(struct omap_dss_board_info *board_data); +#else +static inline int omap_display_init(struct omap_dss_board_info *board_data) +{ + return 0; +} +#endif + +struct omap_display_platform_data { + struct omap_dss_board_info *board_data; + /* TODO: Additional members to be added when PM is considered */ +}; + struct omap_video_timings { /* Unit: pixels */ u16 x_res; diff --git a/arch/arm/plat-omap/include/plat/dvfs.h b/arch/arm/plat-omap/include/plat/dvfs.h new file mode 100644 index 00000000000..1be2b9d8bd3 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/dvfs.h @@ -0,0 +1,34 @@ +/* + * OMAP3/OMAP4 DVFS Management Routines + * + * Author: Vishwanath BS <vishwanath.bs@ti.com> + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Vishwanath BS <vishwanath.bs@ti.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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_DVFS_H +#define __ARCH_ARM_MACH_OMAP2_DVFS_H +#include <plat/voltage.h> + +#ifdef CONFIG_PM +int omap_dvfs_register_device(struct voltagedomain *voltdm, struct device *dev); +int omap_device_scale(struct device *req_dev, struct device *dev, + unsigned long rate); +#else +static inline int omap_dvfs_register_device(struct voltagedomain *voltdm, + struct device *dev) +{ + return -EINVAL; +} +static inline int omap_device_scale(struct device *req_dev, struct devices + *target_dev, unsigned long rate); +{ + return -EINVAL; +} +#endif +#endif diff --git a/arch/arm/plat-omap/include/plat/l3_2xxx.h b/arch/arm/plat-omap/include/plat/l3_2xxx.h new file mode 100644 index 00000000000..b8b5641379b --- /dev/null +++ b/arch/arm/plat-omap/include/plat/l3_2xxx.h @@ -0,0 +1,20 @@ +/* + * arch/arm/plat-omap/include/plat/l3_2xxx.h - L3 firewall definitions + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Sumit Semwal + * + * 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H + +/* L3 CONNIDs */ +/* Display Sub system (DSS) */ +#define OMAP2_L3_CORE_FW_CONNID_DSS 8 + +#endif diff --git a/arch/arm/plat-omap/include/plat/l3_3xxx.h b/arch/arm/plat-omap/include/plat/l3_3xxx.h new file mode 100644 index 00000000000..cde1938c5f8 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/l3_3xxx.h @@ -0,0 +1,20 @@ +/* + * arch/arm/plat-omap/include/plat/l3_3xxx.h - L3 firewall definitions + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Sumit Semwal + * + * 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H + +/* L3 Initiator IDs */ +/* Display Sub system (DSS) */ +#define OMAP3_L3_CORE_FW_INIT_ID_DSS 29 + +#endif diff --git a/arch/arm/plat-omap/include/plat/l4_2xxx.h b/arch/arm/plat-omap/include/plat/l4_2xxx.h new file mode 100644 index 00000000000..3f39cf8a35c --- /dev/null +++ b/arch/arm/plat-omap/include/plat/l4_2xxx.h @@ -0,0 +1,24 @@ +/* + * arch/arm/plat-omap/include/plat/l4_2xxx.h - L4 firewall definitions + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Sumit Semwal + * + * 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H + +/* L4 CORE */ +/* Display Sub system (DSS) */ +#define OMAP2420_L4_CORE_FW_DSS_CORE_REGION 28 +#define OMAP2420_L4_CORE_FW_DSS_DISPC_REGION 29 +#define OMAP2420_L4_CORE_FW_DSS_RFBI_REGION 30 +#define OMAP2420_L4_CORE_FW_DSS_VENC_REGION 31 +#define OMAP2420_L4_CORE_FW_DSS_TA_REGION 32 + +#endif diff --git a/arch/arm/plat-omap/include/plat/l4_3xxx.h b/arch/arm/plat-omap/include/plat/l4_3xxx.h index 5e194937542..881a858b1ff 100644 --- a/arch/arm/plat-omap/include/plat/l4_3xxx.h +++ b/arch/arm/plat-omap/include/plat/l4_3xxx.h @@ -21,4 +21,14 @@ #define OMAP3_L4_CORE_FW_I2C3_REGION 73 #define OMAP3_L4_CORE_FW_I2C3_TA_REGION 74 +/* Display Sub system (DSS) */ +#define OMAP3_L4_CORE_FW_DSS_PROT_GROUP 2 + +#define OMAP3_L4_CORE_FW_DSS_DSI_REGION 104 +#define OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION 3 +#define OMAP3_L4_CORE_FW_DSS_CORE_REGION 4 +#define OMAP3_L4_CORE_FW_DSS_DISPC_REGION 4 +#define OMAP3_L4_CORE_FW_DSS_RFBI_REGION 5 +#define OMAP3_L4_CORE_FW_DSS_VENC_REGION 6 +#define OMAP3_L4_CORE_FW_DSS_TA_REGION 7 #endif diff --git a/arch/arm/plat-omap/include/plat/memory.h b/arch/arm/plat-omap/include/plat/memory.h index f8d922fb558..e6720aa2d55 100644 --- a/arch/arm/plat-omap/include/plat/memory.h +++ b/arch/arm/plat-omap/include/plat/memory.h @@ -37,9 +37,9 @@ * Physical DRAM offset. */ #if defined(CONFIG_ARCH_OMAP1) -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) #else -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif /* diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index e4c349ff9fd..204fb0a9b2f 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -50,6 +50,8 @@ extern struct device omap_device_parent; * @hwmods: (one .. many per omap_device) * @hwmods_cnt: ARRAY_SIZE() of @hwmods * @pm_lats: ptr to an omap_device_pm_latency table + * @set_rate: fn ptr to change the operating rate. + * @get_rate: fn ptr to retrieve the current operating rate. * @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats * @pm_lat_level: array index of the last odpl entry executed - -1 if never * @dev_wakeup_lat: dev wakeup latency in nanoseconds @@ -73,6 +75,8 @@ struct omap_device { s8 pm_lat_level; u8 hwmods_cnt; u8 _state; + int (*set_rate)(struct device *dev, unsigned long rate); + unsigned long (*get_rate) (struct device *dev); }; /* Device driver interface (call via platform_data fn ptrs) */ @@ -107,6 +111,11 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od); int omap_device_align_pm_lat(struct platform_device *pdev, u32 new_wakeup_lat_limit); struct powerdomain *omap_device_get_pwrdm(struct omap_device *od); +int omap_device_set_rate(struct device *dev, unsigned long freq); +unsigned long omap_device_get_rate(struct device *dev); +void omap_device_register_dvfs_callbacks(struct device *dev, + int (*set_rate)(struct device *dev, unsigned long rate), + unsigned long (*get_rate) (struct device *dev)); u32 omap_device_get_context_loss_count(struct platform_device *pdev); /* Other */ diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index cec5d56db2e..8ff605c83ac 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -27,7 +27,7 @@ * 2. We assume printascii is called at least once before paging_init, * and addruart has a chance to read OMAP_UART_INFO */ -#define OMAP_UART_INFO (PHYS_OFFSET + 0x3ffc) +#define OMAP_UART_INFO (PLAT_PHYS_OFFSET + 0x3ffc) /* OMAP1 serial ports */ #define OMAP1_UART1_BASE 0xfffb0000 diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h index 9967d5e855c..f500fc34d06 100644 --- a/arch/arm/plat-omap/include/plat/sram.h +++ b/arch/arm/plat-omap/include/plat/sram.h @@ -12,7 +12,19 @@ #define __ARCH_ARM_OMAP_SRAM_H #ifndef __ASSEMBLY__ -extern void * omap_sram_push(void * start, unsigned long size); +#include <asm/fncpy.h> + +extern void *omap_sram_push_address(unsigned long size); + +/* Macro to push a function to the internal SRAM, using the fncpy API */ +#define omap_sram_push(funcp, size) ({ \ + typeof(&(funcp)) _res = NULL; \ + void *_sram_address = omap_sram_push_address(size); \ + if (_sram_address) \ + _res = fncpy(_sram_address, &(funcp), size); \ + _res; \ +}) + extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl); extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h index 5bd204e55c3..e0b7f22155d 100644 --- a/arch/arm/plat-omap/include/plat/voltage.h +++ b/arch/arm/plat-omap/include/plat/voltage.h @@ -113,6 +113,154 @@ struct omap_volt_pmic_info { u8 (*uv_to_vsel) (unsigned long uV); }; +/* Voltage processor register offsets */ +struct vp_reg_offs { + u8 vpconfig; + u8 vstepmin; + u8 vstepmax; + u8 vlimitto; + u8 vstatus; + u8 voltage; +}; + +/* Voltage Processor bit field values, shifts and masks */ +struct vp_reg_val { + /* PRM module */ + u16 prm_mod; + /* VPx_VPCONFIG */ + u32 vpconfig_erroroffset; + u16 vpconfig_errorgain; + u32 vpconfig_errorgain_mask; + u8 vpconfig_errorgain_shift; + u32 vpconfig_initvoltage_mask; + u8 vpconfig_initvoltage_shift; + u32 vpconfig_timeouten; + u32 vpconfig_initvdd; + u32 vpconfig_forceupdate; + u32 vpconfig_vpenable; + /* VPx_VSTEPMIN */ + u8 vstepmin_stepmin; + u16 vstepmin_smpswaittimemin; + u8 vstepmin_stepmin_shift; + u8 vstepmin_smpswaittimemin_shift; + /* VPx_VSTEPMAX */ + u8 vstepmax_stepmax; + u16 vstepmax_smpswaittimemax; + u8 vstepmax_stepmax_shift; + u8 vstepmax_smpswaittimemax_shift; + /* VPx_VLIMITTO */ + u8 vlimitto_vddmin; + u8 vlimitto_vddmax; + u16 vlimitto_timeout; + u8 vlimitto_vddmin_shift; + u8 vlimitto_vddmax_shift; + u8 vlimitto_timeout_shift; + /* PRM_IRQSTATUS*/ + u32 tranxdone_status; +}; + +/* Voltage controller registers and offsets */ +struct vc_reg_info { + /* PRM module */ + u16 prm_mod; + /* VC register offsets */ + u8 smps_sa_reg; + u8 smps_volra_reg; + u8 bypass_val_reg; + u8 cmdval_reg; + u8 voltsetup_reg; + /*VC_SMPS_SA*/ + u8 smps_sa_shift; + u32 smps_sa_mask; + /* VC_SMPS_VOL_RA */ + u8 smps_volra_shift; + u32 smps_volra_mask; + /* VC_BYPASS_VAL */ + u8 data_shift; + u8 slaveaddr_shift; + u8 regaddr_shift; + u32 valid; + /* VC_CMD_VAL */ + u8 cmd_on_shift; + u8 cmd_onlp_shift; + u8 cmd_ret_shift; + u8 cmd_off_shift; + u32 cmd_on_mask; + /* PRM_VOLTSETUP */ + u8 voltsetup_shift; + u32 voltsetup_mask; +}; + + +/** + * omap_vdd_dep_volt - Table containing the parent vdd voltage and the + * dependent vdd voltage corresponding to it. + * + * @main_vdd_volt : The main vdd voltage + * @dep_vdd_volt : The voltage at which the dependent vdd should be + * when the main vdd is at <main_vdd_volt> voltage + */ +struct omap_vdd_dep_volt { + u32 main_vdd_volt; + u32 dep_vdd_volt; +}; + +/** + * omap_vdd_dep_info - Dependent vdd info + * + * @name : Dependent vdd name + * @voltdm : Dependent vdd pointer + * @dep_table : Table containing the dependent vdd voltage + * corresponding to every main vdd voltage. + */ +struct omap_vdd_dep_info { + char *name; + struct voltagedomain *voltdm; + struct omap_vdd_dep_volt *dep_table; +}; + + +/** + * omap_vdd_info - Per Voltage Domain info + * + * @volt_data : voltage table having the distinct voltages supported + * by the domain and other associated per voltage data. + * @pmic_info : pmic specific parameters which should be populted by + * the pmic drivers. + * @vp_offs : structure containing the offsets for various + * vp registers + * @vp_reg : the register values, shifts, masks for various + * vp registers + * @vc_reg : structure containing various various vc registers, + * shifts, masks etc. + * @voltdm : pointer to the voltage domain structure + * @debug_dir : debug directory for this voltage domain. + * @curr_volt : current voltage for this vdd. + * @ocp_mod : The prm module for accessing the prm irqstatus reg. + * @prm_irqst_reg : prm irqstatus register. + * @vp_enabled : flag to keep track of whether vp is enabled or not + * @volt_scale : API to scale the voltage of the vdd. + */ +struct omap_vdd_info { + struct omap_volt_data *volt_data; + struct omap_volt_pmic_info *pmic_info; + struct vp_reg_offs vp_offs; + struct vp_reg_val vp_reg; + struct vc_reg_info vc_reg; + struct voltagedomain voltdm; + struct omap_vdd_dep_info *dep_vdd_info; + int nr_dep_vdd; + struct dentry *debug_dir; + u32 curr_volt; + u16 ocp_mod; + u8 prm_irqst_reg; + bool vp_enabled; + u32 (*read_reg) (u16 mod, u8 offset); + void (*write_reg) (u32 val, u16 mod, u8 offset); + int (*volt_scale) (struct omap_vdd_info *vdd, + unsigned long target_volt); +}; + unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm); void omap_vp_enable(struct voltagedomain *voltdm); void omap_vp_disable(struct voltagedomain *voltdm); diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index 57adb270767..4cee430c40d 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -86,6 +86,7 @@ #include <plat/omap_device.h> #include <plat/omap_hwmod.h> +#include <plat/dvfs.h> /* These parameters are passed to _omap_device_{de,}activate() */ #define USE_WAKEUP_LAT 0 @@ -481,6 +482,14 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, for (i = 0; i < oh_cnt; i++) { hwmods[i]->od = od; _add_optional_clock_alias(od, hwmods[i]); + if (!is_early_device && hwmods[i]->vdd_name) { + struct omap_hwmod *oh = hwmods[i]; + struct voltagedomain *voltdm; + + voltdm = omap_voltage_domain_lookup(oh->vdd_name); + if (!omap_dvfs_register_device(voltdm, &od->pdev.dev)) + oh->voltdm = voltdm; + } } if (ret) @@ -801,6 +810,55 @@ int omap_device_enable_clocks(struct omap_device *od) return 0; } +int omap_device_set_rate(struct device *dev, unsigned long freq) +{ + struct platform_device *pdev; + struct omap_device *od; + + pdev = container_of(dev, struct platform_device, dev); + od = _find_by_pdev(pdev); + + if (!od->set_rate) { + dev_err(dev, "%s: No set_rate API for scaling device\n", + __func__); + return -ENODATA; + } + + return od->set_rate(dev, freq); +} + +unsigned long omap_device_get_rate(struct device *dev) +{ + struct platform_device *pdev; + struct omap_device *od; + + pdev = container_of(dev, struct platform_device, dev); + od = _find_by_pdev(pdev); + + + if (!od->get_rate) { + dev_err(dev, "%s: No get rate API for the device\n", + __func__); + return 0; + } + + return od->get_rate(dev); +} + +void omap_device_register_dvfs_callbacks(struct device *dev, + int (*set_rate)(struct device *dev, unsigned long rate), + unsigned long (*get_rate) (struct device *dev)) +{ + struct platform_device *pdev; + struct omap_device *od; + + pdev = container_of(dev, struct platform_device, dev); + od = _find_by_pdev(pdev); + + od->set_rate = set_rate; + od->get_rate = get_rate; +} + struct device omap_device_parent = { .init_name = "omap", .parent = &platform_bus, diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index e26e50487d6..68fcc7dc56e 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -242,7 +242,14 @@ static void __init omap_map_sram(void) omap_sram_size - SRAM_BOOTLOADER_SZ); } -void * omap_sram_push(void * start, unsigned long size) +/* + * Memory allocator for SRAM: calculates the new ceiling address + * for pushing a function using the fncpy API. + * + * Note that fncpy requires the returned address to be aligned + * to an 8-byte boundary. + */ +void *omap_sram_push_address(unsigned long size) { if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) { printk(KERN_ERR "Not enough space in SRAM\n"); @@ -250,10 +257,7 @@ void * omap_sram_push(void * start, unsigned long size) } omap_sram_ceil -= size; - omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *)); - memcpy((void *)omap_sram_ceil, start, size); - flush_icache_range((unsigned long)omap_sram_ceil, - (unsigned long)(omap_sram_ceil + size)); + omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN); return (void *)omap_sram_ceil; } diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index c2064c30871..763b7bb44c9 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile @@ -26,9 +26,9 @@ obj-$(CONFIG_CPU_FREQ_S3C24XX_DEBUGFS) += cpu-freq-debugfs.o # Architecture dependant builds obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o -obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_PM) += irq-pm.o -obj-$(CONFIG_PM) += sleep.o +obj-$(CONFIG_SUSPEND) += pm.o +obj-$(CONFIG_SUSPEND) += irq-pm.o +obj-$(CONFIG_SUSPEND) += sleep.o obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o obj-$(CONFIG_S3C2443_CLOCK) += s3c2443-clock.o obj-$(CONFIG_S3C2410_DMA) += dma.o diff --git a/arch/arm/plat-s3c24xx/cpu-freq.c b/arch/arm/plat-s3c24xx/cpu-freq.c index 25a8fc7f512..1d38db56971 100644 --- a/arch/arm/plat-s3c24xx/cpu-freq.c +++ b/arch/arm/plat-s3c24xx/cpu-freq.c @@ -429,7 +429,7 @@ static int s3c_cpufreq_verify(struct cpufreq_policy *policy) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static struct cpufreq_frequency_table suspend_pll; static unsigned int suspend_freq; diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 6ad274e7593..6199b6e419a 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1202,7 +1202,7 @@ static inline struct s3c2410_dma_chan *to_dma_chan(struct sys_device *dev) /* system device class */ -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state) { diff --git a/arch/arm/plat-s3c24xx/include/plat/irq.h b/arch/arm/plat-s3c24xx/include/plat/irq.h index ec087d6054b..ca6354ff7ec 100644 --- a/arch/arm/plat-s3c24xx/include/plat/irq.h +++ b/arch/arm/plat-s3c24xx/include/plat/irq.h @@ -106,7 +106,7 @@ s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group) /* exported for use in arch/arm/mach-s3c2410 */ -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND extern int s3c_irq_wake(struct irq_data *data, unsigned int state); #else #define s3c_irq_wake NULL diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 4bd5cf90897..ce5a0a77964 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -20,8 +20,8 @@ obj-y += irq.o obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o -obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_PM) += irq-pm.o +obj-$(CONFIG_SUSPEND) += pm.o +obj-$(CONFIG_SUSPEND) += irq-pm.o # devices diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c index 225aa25405d..e203a656de2 100644 --- a/arch/arm/plat-s5p/irq-eint.c +++ b/arch/arm/plat-s5p/irq-eint.c @@ -125,7 +125,7 @@ static struct irq_chip s5p_irq_eint = { .irq_mask_ack = s5p_irq_eint_maskack, .irq_ack = s5p_irq_eint_ack, .irq_set_type = s5p_irq_eint_set_type, -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND .irq_set_wake = s3c_irqext_wake, #endif }; @@ -195,7 +195,7 @@ static struct irq_chip s5p_irq_vic_eint = { .irq_mask_ack = s5p_irq_vic_eint_maskack, .irq_ack = s5p_irq_vic_eint_ack, .irq_set_type = s5p_irq_eint_set_type, -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND .irq_set_wake = s3c_irqext_wake, #endif }; diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 29932f88a8d..7e92457915b 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -68,8 +68,8 @@ obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o # PM support -obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_PM) += pm-gpio.o +obj-$(CONFIG_SUSPEND) += pm.o +obj-$(CONFIG_SUSPEND) += pm-gpio.o obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index e8f2be2d67f..d818405eea0 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -412,7 +412,7 @@ static int __devexit s3c_adc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state) { struct adc_device *adc = platform_get_drvdata(pdev); diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c index 7743c4b8b2f..4f3700f9a69 100644 --- a/arch/arm/plat-samsung/gpio.c +++ b/arch/arm/plat-samsung/gpio.c @@ -143,7 +143,7 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) if (!gc->get) gc->get = s3c_gpiolib_get; -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND if (chip->pm != NULL) { if (!chip->pm->save || !chip->pm->resume) printk(KERN_ERR "gpio: %s has missing PM functions\n", diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index dac35d0a711..8b5209baa99 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -68,7 +68,7 @@ struct s3c_gpio_chip { int irq_base; int group; spinlock_t lock; -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND u32 pm_save[4]; #endif }; @@ -153,7 +153,7 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip) static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { } #endif -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND extern struct s3c_gpio_pm s3c_gpio_pm_1bit; extern struct s3c_gpio_pm s3c_gpio_pm_2bit; extern struct s3c_gpio_pm s3c_gpio_pm_4bit; @@ -164,7 +164,7 @@ extern struct s3c_gpio_pm s3c_gpio_pm_4bit; #define s3c_gpio_pm_4bit NULL #define __gpio_pm(x) NULL -#endif /* CONFIG_PM */ +#endif /* CONFIG_SUSPEND */ /* locking wrappers to deal with multiple access to the same gpio bank */ #define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index 30518cc9a67..69f4cc8b31f 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -19,7 +19,7 @@ struct sys_device; -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND extern __init int s3c_pm_init(void); @@ -103,7 +103,7 @@ extern void s3c_pm_do_save(struct sleep_save *ptr, int count); extern void s3c_pm_do_restore(struct sleep_save *ptr, int count); extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count); -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND extern int s3c_irqext_wake(struct irq_data *data, unsigned int state); extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state); extern int s3c24xx_irq_resume(struct sys_device *dev); diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c index 2eeb49fa056..926f08d331c 100644 --- a/arch/arm/plat-samsung/pwm.c +++ b/arch/arm/plat-samsung/pwm.c @@ -380,7 +380,7 @@ static int __devexit s3c_pwm_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_SUSPEND static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state) { struct pwm_device *pwm = platform_get_drvdata(pdev); diff --git a/arch/arm/plat-spear/include/plat/memory.h b/arch/arm/plat-spear/include/plat/memory.h index 27a4aba7734..7e3599e1104 100644 --- a/arch/arm/plat-spear/include/plat/memory.h +++ b/arch/arm/plat-spear/include/plat/memory.h @@ -15,6 +15,6 @@ #define __PLAT_MEMORY_H /* Physical DRAM offset */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif /* __PLAT_MEMORY_H */ diff --git a/arch/arm/plat-stmp3xxx/include/mach/memory.h b/arch/arm/plat-stmp3xxx/include/mach/memory.h index 7b875a07a1a..61fa54882e1 100644 --- a/arch/arm/plat-stmp3xxx/include/mach/memory.h +++ b/arch/arm/plat-stmp3xxx/include/mach/memory.h @@ -17,6 +17,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x40000000) +#define PLAT_PHYS_OFFSET UL(0x40000000) #endif diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h index cd91ba8a670..28a6e0cd13b 100644 --- a/arch/arm/plat-tcc/include/mach/memory.h +++ b/arch/arm/plat-tcc/include/mach/memory.h @@ -13,6 +13,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #endif diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 0797cb528b4..bbf3da012af 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -153,7 +153,7 @@ static struct notifier_block vfp_notifier_block = { * Raise a SIGFPE for the current process. * sicode describes the signal being raised. */ -void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) +static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) { siginfo_t info; @@ -489,8 +489,11 @@ void vfp_flush_hwstate(struct thread_info *thread) /* * VFP hardware can lose all context when a CPU goes offline. - * Safely clear our held state when a CPU has been killed, and - * re-enable access to VFP when the CPU comes back online. + * As we will be running in SMP mode with CPU hotplug, we will save the + * hardware state at every thread switch. We clear our held state when + * a CPU has been killed, indicating that the VFP hardware doesn't contain + * a threads VFP state. When a CPU starts up, we re-enable access to the + * VFP hardware. * * Both CPU_DYING and CPU_STARTING are called on the CPU which * is being offlined/onlined. diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f5ecc0566bc..d88983516e2 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -4,6 +4,7 @@ config MIPS select HAVE_GENERIC_DMA_COHERENT select HAVE_IDE select HAVE_OPROFILE + select HAVE_IRQ_WORK select HAVE_PERF_EVENTS select PERF_USE_VMALLOC select HAVE_ARCH_KGDB @@ -208,6 +209,7 @@ config MACH_JZ4740 select ARCH_REQUIRE_GPIOLIB select SYS_HAS_EARLY_PRINTK select HAVE_PWM + select HAVE_CLK config LASAT bool "LASAT Networks platforms" @@ -333,6 +335,8 @@ config PNX8550_STB810 config PMC_MSP bool "PMC-Sierra MSP chipsets" depends on EXPERIMENTAL + select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select SWAP_IO_SPACE select NO_EXCEPT_FILL diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c index 6398fa95905..40b84b99119 100644 --- a/arch/mips/alchemy/mtx-1/board_setup.c +++ b/arch/mips/alchemy/mtx-1/board_setup.c @@ -54,8 +54,8 @@ int mtx1_pci_idsel(unsigned int devsel, int assert); static void mtx1_reset(char *c) { - /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ - au_writel(0x00000000, 0xAE00001C); + /* Jump to the reset vector */ + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); } static void mtx1_power_off(void) diff --git a/arch/mips/alchemy/mtx-1/platform.c b/arch/mips/alchemy/mtx-1/platform.c index e30e42add69..956f946218c 100644 --- a/arch/mips/alchemy/mtx-1/platform.c +++ b/arch/mips/alchemy/mtx-1/platform.c @@ -28,6 +28,8 @@ #include <linux/mtd/physmap.h> #include <mtd/mtd-abi.h> +#include <asm/mach-au1x00/au1xxx_eth.h> + static struct gpio_keys_button mtx1_gpio_button[] = { { .gpio = 207, @@ -140,10 +142,17 @@ static struct __initdata platform_device * mtx1_devs[] = { &mtx1_mtd, }; +static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = { + .phy_search_highest_addr = 1, + .phy1_search_mac0 = 1, +}; + static int __init mtx1_register_devices(void) { int rc; + au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata); + rc = gpio_request(mtx1_gpio_button[0].gpio, mtx1_gpio_button[0].desc); if (rc < 0) { diff --git a/arch/mips/alchemy/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c index b43c918925d..80c521e5290 100644 --- a/arch/mips/alchemy/xxs1500/board_setup.c +++ b/arch/mips/alchemy/xxs1500/board_setup.c @@ -36,8 +36,8 @@ static void xxs1500_reset(char *c) { - /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ - au_writel(0x00000000, 0xAE00001C); + /* Jump to the reset vector */ + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); } static void xxs1500_power_off(void) diff --git a/arch/mips/include/asm/perf_event.h b/arch/mips/include/asm/perf_event.h index e00007cf816..d0c77496c72 100644 --- a/arch/mips/include/asm/perf_event.h +++ b/arch/mips/include/asm/perf_event.h @@ -11,15 +11,5 @@ #ifndef __MIPS_PERF_EVENT_H__ #define __MIPS_PERF_EVENT_H__ - -/* - * MIPS performance counters do not raise NMI upon overflow, a regular - * interrupt will be signaled. Hence we can do the pending perf event - * work at the tail of the irq handler. - */ -static inline void -set_perf_event_pending(void) -{ -} - +/* Leave it empty here. The file is required by linux/perf_event.h */ #endif /* __MIPS_PERF_EVENT_H__ */ diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index 5a84a1f1123..94ca2b018af 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -17,29 +17,13 @@ #include <asm/cacheflush.h> #include <asm/uasm.h> -/* - * If the Instruction Pointer is in module space (0xc0000000), return true; - * otherwise, it is in kernel space (0x80000000), return false. - * - * FIXME: This will not work when the kernel space and module space are the - * same. If they are the same, we need to modify scripts/recordmcount.pl, - * ftrace_make_nop/call() and the other related parts to ensure the - * enabling/disabling of the calling site to _mcount is right for both kernel - * and module. - */ - -static inline int in_module(unsigned long ip) -{ - return ip & 0x40000000; -} +#include <asm-generic/sections.h> #ifdef CONFIG_DYNAMIC_FTRACE #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ -#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */ -#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */ #define INSN_NOP 0x00000000 /* nop */ #define INSN_JAL(addr) \ ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK))) @@ -69,6 +53,20 @@ static inline void ftrace_dyn_arch_init_insns(void) #endif } +/* + * Check if the address is in kernel space + * + * Clone core_kernel_text() from kernel/extable.c, but doesn't call + * init_kernel_text() for Ftrace doesn't trace functions in init sections. + */ +static inline int in_kernel_space(unsigned long ip) +{ + if (ip >= (unsigned long)_stext && + ip <= (unsigned long)_etext) + return 1; + return 0; +} + static int ftrace_modify_code(unsigned long ip, unsigned int new_code) { int faulted; @@ -84,6 +82,42 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) return 0; } +/* + * The details about the calling site of mcount on MIPS + * + * 1. For kernel: + * + * move at, ra + * jal _mcount --> nop + * + * 2. For modules: + * + * 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT + * + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) + * addiu v1, v1, low_16bit_of_mcount + * move at, ra + * move $12, ra_address + * jalr v1 + * sub sp, sp, 8 + * 1: offset = 5 instructions + * 2.2 For the Other situations + * + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) + * addiu v1, v1, low_16bit_of_mcount + * move at, ra + * jalr v1 + * nop | move $12, ra_address | sub sp, sp, 8 + * 1: offset = 4 instructions + */ + +#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) +#define MCOUNT_OFFSET_INSNS 5 +#else +#define MCOUNT_OFFSET_INSNS 4 +#endif +#define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS) + int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { @@ -91,39 +125,11 @@ int ftrace_make_nop(struct module *mod, unsigned long ip = rec->ip; /* - * We have compiled module with -mlong-calls, but compiled the kernel - * without it, we need to cope with them respectively. + * If ip is in kernel space, no long call, otherwise, long call is + * needed. */ - if (in_module(ip)) { -#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) - /* - * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) - * addiu v1, v1, low_16bit_of_mcount - * move at, ra - * move $12, ra_address - * jalr v1 - * sub sp, sp, 8 - * 1: offset = 5 instructions - */ - new = INSN_B_1F_5; -#else - /* - * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) - * addiu v1, v1, low_16bit_of_mcount - * move at, ra - * jalr v1 - * nop | move $12, ra_address | sub sp, sp, 8 - * 1: offset = 4 instructions - */ - new = INSN_B_1F_4; -#endif - } else { - /* - * move at, ra - * jal _mcount --> nop - */ - new = INSN_NOP; - } + new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; + return ftrace_modify_code(ip, new); } @@ -132,8 +138,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) unsigned int new; unsigned long ip = rec->ip; - /* ip, module: 0xc0000000, kernel: 0x80000000 */ - new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; + new = in_kernel_space(ip) ? insn_jal_ftrace_caller : + insn_lui_v1_hi16_mcount; return ftrace_modify_code(ip, new); } @@ -190,29 +196,25 @@ int ftrace_disable_ftrace_graph_caller(void) #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ -unsigned long ftrace_get_parent_addr(unsigned long self_addr, - unsigned long parent, - unsigned long parent_addr, - unsigned long fp) +unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long + old_parent_ra, unsigned long parent_ra_addr, unsigned long fp) { - unsigned long sp, ip, ra; + unsigned long sp, ip, tmp; unsigned int code; int faulted; /* - * For module, move the ip from calling site of mcount to the - * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for - * kernel, move to the instruction "move ra, at"(offset is 12) + * For module, move the ip from the return address after the + * instruction "lui v1, hi_16bit_of_mcount"(offset is 24), but for + * kernel, move after the instruction "move ra, at"(offset is 16) */ - ip = self_addr - (in_module(self_addr) ? 20 : 12); + ip = self_ra - (in_kernel_space(self_ra) ? 16 : 24); /* * search the text until finding the non-store instruction or "s{d,w} * ra, offset(sp)" instruction */ do { - ip -= 4; - /* get the code at "ip": code = *(unsigned int *)ip; */ safe_load_code(code, ip, faulted); @@ -224,18 +226,20 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, * store the ra on the stack */ if ((code & S_R_SP) != S_R_SP) - return parent_addr; + return parent_ra_addr; - } while (((code & S_RA_SP) != S_RA_SP)); + /* Move to the next instruction */ + ip -= 4; + } while ((code & S_RA_SP) != S_RA_SP); sp = fp + (code & OFFSET_MASK); - /* ra = *(unsigned long *)sp; */ - safe_load_stack(ra, sp, faulted); + /* tmp = *(unsigned long *)sp; */ + safe_load_stack(tmp, sp, faulted); if (unlikely(faulted)) return 0; - if (ra == parent) + if (tmp == old_parent_ra) return sp; return 0; } @@ -246,21 +250,21 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, * Hook the return address and push it in the stack of return addrs * in current thread info. */ -void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, +void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra, unsigned long fp) { - unsigned long old; + unsigned long old_parent_ra; struct ftrace_graph_ent trace; unsigned long return_hooker = (unsigned long) &return_to_handler; - int faulted; + int faulted, insns; if (unlikely(atomic_read(¤t->tracing_graph_pause))) return; /* - * "parent" is the stack address saved the return address of the caller - * of _mcount. + * "parent_ra_addr" is the stack address saved the return address of + * the caller of _mcount. * * if the gcc < 4.5, a leaf function does not save the return address * in the stack address, so, we "emulate" one in _mcount's stack space, @@ -275,37 +279,44 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, * do it in ftrace_graph_caller of mcount.S. */ - /* old = *parent; */ - safe_load_stack(old, parent, faulted); + /* old_parent_ra = *parent_ra_addr; */ + safe_load_stack(old_parent_ra, parent_ra_addr, faulted); if (unlikely(faulted)) goto out; #ifndef KBUILD_MCOUNT_RA_ADDRESS - parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, - (unsigned long)parent, fp); + parent_ra_addr = (unsigned long *)ftrace_get_parent_ra_addr(self_ra, + old_parent_ra, (unsigned long)parent_ra_addr, fp); /* * If fails when getting the stack address of the non-leaf function's * ra, stop function graph tracer and return */ - if (parent == 0) + if (parent_ra_addr == 0) goto out; #endif - /* *parent = return_hooker; */ - safe_store_stack(return_hooker, parent, faulted); + /* *parent_ra_addr = return_hooker; */ + safe_store_stack(return_hooker, parent_ra_addr, faulted); if (unlikely(faulted)) goto out; - if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) == - -EBUSY) { - *parent = old; + if (ftrace_push_return_trace(old_parent_ra, self_ra, &trace.depth, fp) + == -EBUSY) { + *parent_ra_addr = old_parent_ra; return; } - trace.func = self_addr; + /* + * Get the recorded ip of the current mcount calling site in the + * __mcount_loc section, which will be used to filter the function + * entries configured through the tracing/set_graph_function interface. + */ + + insns = in_kernel_space(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1; + trace.func = self_ra - (MCOUNT_INSN_SIZE * insns); /* Only trace if the calling function expects to */ if (!ftrace_graph_entry(&trace)) { current->curr_ret_stack--; - *parent = old; + *parent_ra_addr = old_parent_ra; } return; out: diff --git a/arch/mips/kernel/perf_event.c b/arch/mips/kernel/perf_event.c index 2b7f3f703b8..a8244854d3d 100644 --- a/arch/mips/kernel/perf_event.c +++ b/arch/mips/kernel/perf_event.c @@ -161,41 +161,6 @@ mipspmu_event_set_period(struct perf_event *event, return ret; } -static int mipspmu_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; - - /* To look for a free counter for this event. */ - idx = mipspmu->alloc_counter(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; - mipspmu->disable_event(idx); - cpuc->events[idx] = event; - - /* Set the period for the event. */ - mipspmu_event_set_period(event, hwc, idx); - - /* Enable the event. */ - mipspmu->enable_event(hwc, idx); - - /* Propagate our changes to the userspace mapping. */ - perf_event_update_userpage(event); - -out: - return err; -} - static void mipspmu_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx) @@ -204,7 +169,7 @@ static void mipspmu_event_update(struct perf_event *event, unsigned long flags; int shift = 64 - TOTAL_BITS; s64 prev_raw_count, new_raw_count; - s64 delta; + u64 delta; again: prev_raw_count = local64_read(&hwc->prev_count); @@ -231,32 +196,90 @@ again: return; } -static void mipspmu_disable(struct perf_event *event) +static void mipspmu_start(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + if (!mipspmu) + return; + + if (flags & PERF_EF_RELOAD) + WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); + + hwc->state = 0; + + /* Set the period for the event. */ + mipspmu_event_set_period(event, hwc, hwc->idx); + + /* Enable the event. */ + mipspmu->enable_event(hwc, hwc->idx); +} + +static void mipspmu_stop(struct perf_event *event, int flags) +{ + struct hw_perf_event *hwc = &event->hw; + + if (!mipspmu) + return; + + if (!(hwc->state & PERF_HES_STOPPED)) { + /* We are working on a local event. */ + mipspmu->disable_event(hwc->idx); + barrier(); + mipspmu_event_update(event, hwc, hwc->idx); + hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; + } +} + +static int mipspmu_add(struct perf_event *event, int flags) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; + int idx; + int err = 0; + perf_pmu_disable(event->pmu); - WARN_ON(idx < 0 || idx >= mipspmu->num_counters); + /* To look for a free counter for this event. */ + idx = mipspmu->alloc_counter(cpuc, hwc); + if (idx < 0) { + err = idx; + goto out; + } - /* We are working on a local event. */ + /* + * If there is an event in the counter we are going to use then + * make sure it is disabled. + */ + event->hw.idx = idx; mipspmu->disable_event(idx); + cpuc->events[idx] = event; - barrier(); - - mipspmu_event_update(event, hwc, idx); - cpuc->events[idx] = NULL; - clear_bit(idx, cpuc->used_mask); + hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; + if (flags & PERF_EF_START) + mipspmu_start(event, PERF_EF_RELOAD); + /* Propagate our changes to the userspace mapping. */ perf_event_update_userpage(event); + +out: + perf_pmu_enable(event->pmu); + return err; } -static void mipspmu_unthrottle(struct perf_event *event) +static void mipspmu_del(struct perf_event *event, int flags) { + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; + int idx = hwc->idx; - mipspmu->enable_event(hwc, hwc->idx); + WARN_ON(idx < 0 || idx >= mipspmu->num_counters); + + mipspmu_stop(event, PERF_EF_UPDATE); + cpuc->events[idx] = NULL; + clear_bit(idx, cpuc->used_mask); + + perf_event_update_userpage(event); } static void mipspmu_read(struct perf_event *event) @@ -270,12 +293,17 @@ static void mipspmu_read(struct perf_event *event) mipspmu_event_update(event, hwc, hwc->idx); } -static struct pmu pmu = { - .enable = mipspmu_enable, - .disable = mipspmu_disable, - .unthrottle = mipspmu_unthrottle, - .read = mipspmu_read, -}; +static void mipspmu_enable(struct pmu *pmu) +{ + if (mipspmu) + mipspmu->start(); +} + +static void mipspmu_disable(struct pmu *pmu) +{ + if (mipspmu) + mipspmu->stop(); +} static atomic_t active_events = ATOMIC_INIT(0); static DEFINE_MUTEX(pmu_reserve_mutex); @@ -318,6 +346,82 @@ static void mipspmu_free_irq(void) perf_irq = save_perf_irq; } +/* + * mipsxx/rm9000/loongson2 have different performance counters, they have + * specific low-level init routines. + */ +static void reset_counters(void *arg); +static int __hw_perf_event_init(struct perf_event *event); + +static void hw_perf_event_destroy(struct perf_event *event) +{ + if (atomic_dec_and_mutex_lock(&active_events, + &pmu_reserve_mutex)) { + /* + * We must not call the destroy function with interrupts + * disabled. + */ + on_each_cpu(reset_counters, + (void *)(long)mipspmu->num_counters, 1); + mipspmu_free_irq(); + mutex_unlock(&pmu_reserve_mutex); + } +} + +static int mipspmu_event_init(struct perf_event *event) +{ + int err = 0; + + switch (event->attr.type) { + case PERF_TYPE_RAW: + case PERF_TYPE_HARDWARE: + case PERF_TYPE_HW_CACHE: + break; + + default: + return -ENOENT; + } + + if (!mipspmu || event->cpu >= nr_cpumask_bits || + (event->cpu >= 0 && !cpu_online(event->cpu))) + return -ENODEV; + + if (!atomic_inc_not_zero(&active_events)) { + if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { + atomic_dec(&active_events); + return -ENOSPC; + } + + mutex_lock(&pmu_reserve_mutex); + if (atomic_read(&active_events) == 0) + err = mipspmu_get_irq(); + + if (!err) + atomic_inc(&active_events); + mutex_unlock(&pmu_reserve_mutex); + } + + if (err) + return err; + + err = __hw_perf_event_init(event); + if (err) + hw_perf_event_destroy(event); + + return err; +} + +static struct pmu pmu = { + .pmu_enable = mipspmu_enable, + .pmu_disable = mipspmu_disable, + .event_init = mipspmu_event_init, + .add = mipspmu_add, + .del = mipspmu_del, + .start = mipspmu_start, + .stop = mipspmu_stop, + .read = mipspmu_read, +}; + static inline unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev) { @@ -382,8 +486,9 @@ static int validate_event(struct cpu_hw_events *cpuc, { struct hw_perf_event fake_hwc = event->hw; - if (event->pmu && event->pmu != &pmu) - return 0; + /* Allow mixed event group. So return 1 to pass validation. */ + if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF) + return 1; return mipspmu->alloc_counter(cpuc, &fake_hwc) >= 0; } @@ -409,73 +514,6 @@ static int validate_group(struct perf_event *event) return 0; } -/* - * mipsxx/rm9000/loongson2 have different performance counters, they have - * specific low-level init routines. - */ -static void reset_counters(void *arg); -static int __hw_perf_event_init(struct perf_event *event); - -static void hw_perf_event_destroy(struct perf_event *event) -{ - if (atomic_dec_and_mutex_lock(&active_events, - &pmu_reserve_mutex)) { - /* - * We must not call the destroy function with interrupts - * disabled. - */ - on_each_cpu(reset_counters, - (void *)(long)mipspmu->num_counters, 1); - mipspmu_free_irq(); - mutex_unlock(&pmu_reserve_mutex); - } -} - -const struct pmu *hw_perf_event_init(struct perf_event *event) -{ - int err = 0; - - if (!mipspmu || event->cpu >= nr_cpumask_bits || - (event->cpu >= 0 && !cpu_online(event->cpu))) - return ERR_PTR(-ENODEV); - - if (!atomic_inc_not_zero(&active_events)) { - if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { - atomic_dec(&active_events); - return ERR_PTR(-ENOSPC); - } - - mutex_lock(&pmu_reserve_mutex); - if (atomic_read(&active_events) == 0) - err = mipspmu_get_irq(); - - 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) -{ - if (mipspmu) - mipspmu->start(); -} - -void hw_perf_disable(void) -{ - if (mipspmu) - mipspmu->stop(); -} - /* This is needed by specific irq handlers in perf_event_*.c */ static void handle_associated_event(struct cpu_hw_events *cpuc, @@ -496,21 +534,13 @@ handle_associated_event(struct cpu_hw_events *cpuc, #include "perf_event_mipsxx.c" /* 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; -} /* * Leave userspace callchain empty for now. When we find a way to trace * the user stack callchains, we add here. */ -static void -perf_callchain_user(struct pt_regs *regs, - struct perf_callchain_entry *entry) +void perf_callchain_user(struct perf_callchain_entry *entry, + struct pt_regs *regs) { } @@ -523,23 +553,21 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry, while (!kstack_end(sp)) { addr = *sp++; if (__kernel_text_address(addr)) { - callchain_store(entry, addr); + perf_callchain_store(entry, addr); if (entry->nr >= PERF_MAX_STACK_DEPTH) break; } } } -static void -perf_callchain_kernel(struct pt_regs *regs, - struct perf_callchain_entry *entry) +void perf_callchain_kernel(struct perf_callchain_entry *entry, + struct pt_regs *regs) { unsigned long sp = regs->regs[29]; #ifdef CONFIG_KALLSYMS unsigned long ra = regs->regs[31]; unsigned long pc = regs->cp0_epc; - callchain_store(entry, PERF_CONTEXT_KERNEL); if (raw_show_trace || !__kernel_text_address(pc)) { unsigned long stack_page = (unsigned long)task_stack_page(current); @@ -549,53 +577,12 @@ perf_callchain_kernel(struct pt_regs *regs, return; } do { - callchain_store(entry, pc); + perf_callchain_store(entry, pc); if (entry->nr >= PERF_MAX_STACK_DEPTH) break; pc = unwind_stack(current, &sp, pc, &ra); } while (pc); #else - callchain_store(entry, PERF_CONTEXT_KERNEL); save_raw_perf_callchain(entry, sp); #endif } - -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) - regs = task_pt_regs(current); - else - regs = NULL; - } - if (regs) - 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/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 183e0d22666..d9a7db78ed6 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -696,7 +696,7 @@ static int mipsxx_pmu_handle_shared_irq(void) * interrupt, not NMI. */ if (handled == IRQ_HANDLED) - perf_event_do_pending(); + irq_work_run(); #ifdef CONFIG_MIPS_MT_SMP read_unlock(&pmuint_rwlock); @@ -1045,6 +1045,8 @@ init_hw_perf_events(void) "CPU, irq %d%s\n", mipspmu->name, counters, irq, irq < 0 ? " (share with timer interrupt)" : ""); + perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); + return 0; } early_initcall(init_hw_perf_events); diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 5922342bca3..dbbe0ce48d8 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -84,7 +84,7 @@ static int protected_save_fp_context(struct sigcontext __user *sc) static int protected_restore_fp_context(struct sigcontext __user *sc) { - int err, tmp; + int err, tmp __maybe_unused; while (1) { lock_fpu_owner(); own_fpu_inatomic(0); diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index a0ed0e052b2..aae98661379 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -115,7 +115,7 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc) static int protected_restore_fp_context32(struct sigcontext32 __user *sc) { - int err, tmp; + int err, tmp __maybe_unused; while (1) { lock_fpu_owner(); own_fpu_inatomic(0); diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 383aeb95cb4..32a25610108 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -193,6 +193,22 @@ void __devinit smp_prepare_boot_cpu(void) */ static struct task_struct *cpu_idle_thread[NR_CPUS]; +struct create_idle { + struct work_struct work; + struct task_struct *idle; + struct completion done; + int cpu; +}; + +static void __cpuinit do_fork_idle(struct work_struct *work) +{ + struct create_idle *c_idle = + container_of(work, struct create_idle, work); + + c_idle->idle = fork_idle(c_idle->cpu); + complete(&c_idle->done); +} + int __cpuinit __cpu_up(unsigned int cpu) { struct task_struct *idle; @@ -203,8 +219,19 @@ int __cpuinit __cpu_up(unsigned int cpu) * Linux can schedule processes on this slave. */ if (!cpu_idle_thread[cpu]) { - idle = fork_idle(cpu); - cpu_idle_thread[cpu] = idle; + /* + * Schedule work item to avoid forking user task + * Ported from arch/x86/kernel/smpboot.c + */ + struct create_idle c_idle = { + .cpu = cpu, + .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), + }; + + INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); + schedule_work(&c_idle.work); + wait_for_completion(&c_idle.done); + idle = cpu_idle_thread[cpu] = c_idle.idle; if (IS_ERR(idle)) panic(KERN_ERR "Fork failed for CPU %d", cpu); diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 1dc6edff45e..58beabf50b3 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -383,12 +383,11 @@ save_static_function(sys_sysmips); static int __used noinline _sys_sysmips(nabi_no_regargs struct pt_regs regs) { - long cmd, arg1, arg2, arg3; + long cmd, arg1, arg2; cmd = regs.regs[4]; arg1 = regs.regs[5]; arg2 = regs.regs[6]; - arg3 = regs.regs[7]; switch (cmd) { case MIPS_ATOMIC_SET: @@ -405,7 +404,7 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs) if (arg1 & 2) set_thread_flag(TIF_LOGADE); else - clear_thread_flag(TIF_FIXADE); + clear_thread_flag(TIF_LOGADE); return 0; diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 6a1fdfef8fd..ab52b7cf3b6 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -148,9 +148,9 @@ struct { spinlock_t tc_list_lock; struct list_head tc_list; /* Thread contexts */ } vpecontrol = { - .vpe_list_lock = SPIN_LOCK_UNLOCKED, + .vpe_list_lock = __SPIN_LOCK_UNLOCKED(vpe_list_lock), .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list), - .tc_list_lock = SPIN_LOCK_UNLOCKED, + .tc_list_lock = __SPIN_LOCK_UNLOCKED(tc_list_lock), .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list) }; diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 6e1b77fec7e..aca93eed877 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -1,6 +1,7 @@ +if MACH_LOONGSON + choice prompt "Machine Type" - depends on MACH_LOONGSON config LEMOTE_FULOONG2E bool "Lemote Fuloong(2e) mini-PC" @@ -87,3 +88,5 @@ config LOONGSON_UART_BASE config LOONGSON_MC146818 bool default n + +endif # MACH_LOONGSON diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson/common/cmdline.c index 1a06defc4f7..353e1d2e41a 100644 --- a/arch/mips/loongson/common/cmdline.c +++ b/arch/mips/loongson/common/cmdline.c @@ -44,10 +44,5 @@ void __init prom_init_cmdline(void) strcat(arcs_cmdline, " "); } - if ((strstr(arcs_cmdline, "console=")) == NULL) - strcat(arcs_cmdline, " console=ttyS0,115200"); - if ((strstr(arcs_cmdline, "root=")) == NULL) - strcat(arcs_cmdline, " root=/dev/hda1"); - prom_init_machtype(); } diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c index 81fbe6b73f9..2efd5d9dee2 100644 --- a/arch/mips/loongson/common/machtype.c +++ b/arch/mips/loongson/common/machtype.c @@ -41,7 +41,7 @@ void __weak __init mach_prom_init_machtype(void) void __init prom_init_machtype(void) { - char *p, str[MACHTYPE_LEN]; + char *p, str[MACHTYPE_LEN + 1]; int machtype = MACH_LEMOTE_FL2E; mips_machtype = LOONGSON_MACHTYPE; @@ -53,6 +53,7 @@ void __init prom_init_machtype(void) } p += strlen("machtype="); strncpy(str, p, MACHTYPE_LEN); + str[MACHTYPE_LEN] = '\0'; p = strstr(str, " "); if (p) *p = '\0'; diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 2701d950095..2a7d43f4f16 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -70,7 +70,7 @@ #define COMPXSP \ - unsigned xm; int xe; int xs; int xc + unsigned xm; int xe; int xs __maybe_unused; int xc #define COMPYSP \ unsigned ym; int ye; int ys; int yc @@ -104,7 +104,7 @@ #define COMPXDP \ -u64 xm; int xe; int xs; int xc +u64 xm; int xe; int xs __maybe_unused; int xc #define COMPYDP \ u64 ym; int ye; int ys; int yc diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 2efcbd24c82..279599e9a77 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -324,7 +324,7 @@ int page_is_ram(unsigned long pagenr) void __init paging_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES]; - unsigned long lastpfn; + unsigned long lastpfn __maybe_unused; pagetable_init(); diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 083d3412d0b..04f9e17db9d 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -109,6 +109,8 @@ static bool scratchpad_available(void) static int scratchpad_offset(int i) { BUG(); + /* Really unreachable, but evidently some GCC want this. */ + return 0; } #endif /* diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index b7c03d80c88..68798f869c0 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -308,7 +308,7 @@ static struct resource pci_mem_resource = { * RETURNS: PCIBIOS_SUCCESSFUL - success * ****************************************************************************/ -static int bpci_interrupt(int irq, void *dev_id) +static irqreturn_t bpci_interrupt(int irq, void *dev_id) { struct msp_pci_regs *preg = (void *)PCI_BASE_REG; unsigned int stat = preg->if_status; @@ -326,7 +326,7 @@ static int bpci_interrupt(int irq, void *dev_id) /* write to clear all asserted interrupts */ preg->if_status = stat; - return PCIBIOS_SUCCESSFUL; + return IRQ_HANDLED; } /***************************************************************************** diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig index c139988bb85..8d798497c61 100644 --- a/arch/mips/pmc-sierra/Kconfig +++ b/arch/mips/pmc-sierra/Kconfig @@ -4,15 +4,11 @@ choice config PMC_MSP4200_EVAL bool "PMC-Sierra MSP4200 Eval Board" - select CEVT_R4K - select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI config PMC_MSP4200_GW bool "PMC-Sierra MSP4200 VoIP Gateway" - select CEVT_R4K - select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c index cca64e15f57..01df84ce31e 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_time.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c @@ -81,7 +81,7 @@ void __init plat_time_init(void) mips_hpt_frequency = cpu_rate/2; } -unsigned int __init get_c0_compare_int(void) +unsigned int __cpuinit get_c0_compare_int(void) { return MSP_INT_VPE0_TIMER; } diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h index 92d2f9298e3..9d773a63951 100644 --- a/arch/mn10300/include/asm/atomic.h +++ b/arch/mn10300/include/asm/atomic.h @@ -139,7 +139,7 @@ static inline unsigned long __cmpxchg(volatile unsigned long *m, * Atomically reads the value of @v. Note that the guaranteed * useful range of an atomic_t is only 24 bits. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (ACCESS_ONCE((v)->counter)) /** * atomic_set - set atomic variable diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h index 679dee0bbd0..3d6e60dad9d 100644 --- a/arch/mn10300/include/asm/uaccess.h +++ b/arch/mn10300/include/asm/uaccess.h @@ -160,9 +160,10 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user_check(x, ptr, size) \ ({ \ + const __typeof__(ptr) __guc_ptr = (ptr); \ int _e; \ - if (likely(__access_ok((unsigned long) (ptr), (size)))) \ - _e = __get_user_nocheck((x), (ptr), (size)); \ + if (likely(__access_ok((unsigned long) __guc_ptr, (size)))) \ + _e = __get_user_nocheck((x), __guc_ptr, (size)); \ else { \ _e = -EFAULT; \ (x) = (__typeof__(x))0; \ diff --git a/arch/mn10300/mm/cache-inv-icache.c b/arch/mn10300/mm/cache-inv-icache.c index a8933a60b2d..a6b63dde603 100644 --- a/arch/mn10300/mm/cache-inv-icache.c +++ b/arch/mn10300/mm/cache-inv-icache.c @@ -69,7 +69,7 @@ static void flush_icache_page_range(unsigned long start, unsigned long end) /* invalidate the icache coverage on that region */ mn10300_local_icache_inv_range2(addr + off, size); - smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); + smp_cache_call(SMP_ICACHE_INV_RANGE, start, end); } /** @@ -101,7 +101,7 @@ void flush_icache_range(unsigned long start, unsigned long end) * directly */ start_page = (start >= 0x80000000UL) ? start : 0x80000000UL; mn10300_icache_inv_range(start_page, end); - smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); + smp_cache_call(SMP_ICACHE_INV_RANGE, start, end); if (start_page == start) goto done; end = start_page; diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c index 646aa78ba5f..46a82388243 100644 --- a/arch/x86/boot/compressed/mkpiggy.c +++ b/arch/x86/boot/compressed/mkpiggy.c @@ -62,7 +62,12 @@ int main(int argc, char *argv[]) if (fseek(f, -4L, SEEK_END)) { perror(argv[1]); } - fread(&olen, sizeof olen, 1, f); + + if (fread(&olen, sizeof(olen), 1, f) != 1) { + perror(argv[1]); + return 1; + } + ilen = ftell(f); olen = getle32(&olen); fclose(f); diff --git a/arch/x86/include/asm/ce4100.h b/arch/x86/include/asm/ce4100.h new file mode 100644 index 00000000000..e656ad8c0a2 --- /dev/null +++ b/arch/x86/include/asm/ce4100.h @@ -0,0 +1,6 @@ +#ifndef _ASM_CE4100_H_ +#define _ASM_CE4100_H_ + +int ce4100_pci_init(void); + +#endif diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index ce1d54c8a43..3e094af443c 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -176,7 +176,7 @@ struct bau_msg_payload { struct bau_msg_header { unsigned int dest_subnodeid:6; /* must be 0x10, for the LB */ /* bits 5:0 */ - unsigned int base_dest_nodeid:15; /* nasid (pnode<<1) of */ + unsigned int base_dest_nodeid:15; /* nasid of the */ /* bits 20:6 */ /* first bit in uvhub map */ unsigned int command:8; /* message type */ /* bits 28:21 */ diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c index 13a38917951..452932d3473 100644 --- a/arch/x86/kernel/check.c +++ b/arch/x86/kernel/check.c @@ -106,8 +106,8 @@ void __init setup_bios_corruption_check(void) addr += size; } - printk(KERN_INFO "Scanning %d areas for low memory corruption\n", - num_scan_areas); + if (num_scan_areas) + printk(KERN_INFO "Scanning %d areas for low memory corruption\n", num_scan_areas); } @@ -143,12 +143,12 @@ static void check_corruption(struct work_struct *dummy) { check_for_bios_corruption(); schedule_delayed_work(&bios_check_work, - round_jiffies_relative(corruption_check_period*HZ)); + round_jiffies_relative(corruption_check_period*HZ)); } static int start_periodic_check_for_corruption(void) { - if (!memory_corruption_check || corruption_check_period == 0) + if (!num_scan_areas || !memory_corruption_check || corruption_check_period == 0) return 0; printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n", diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 7d90ceb882a..20e3f8702d1 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -229,15 +229,14 @@ void vmalloc_sync_all(void) for (address = VMALLOC_START & PMD_MASK; address >= TASK_SIZE && address < FIXADDR_TOP; address += PMD_SIZE) { - - unsigned long flags; struct page *page; - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); list_for_each_entry(page, &pgd_list, lru) { spinlock_t *pgt_lock; pmd_t *ret; + /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); @@ -247,7 +246,7 @@ void vmalloc_sync_all(void) if (!ret) break; } - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); } } @@ -828,6 +827,13 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, unsigned long address, unsigned int fault) { if (fault & VM_FAULT_OOM) { + /* Kernel mode? Handle exceptions or die: */ + if (!(error_code & PF_USER)) { + up_read(¤t->mm->mmap_sem); + no_context(regs, error_code, address); + return; + } + out_of_memory(regs, error_code, address); } else { if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 71a59296af8..c14a5422e15 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -105,18 +105,18 @@ void sync_global_pgds(unsigned long start, unsigned long end) for (address = start; address <= end; address += PGDIR_SIZE) { const pgd_t *pgd_ref = pgd_offset_k(address); - unsigned long flags; struct page *page; if (pgd_none(*pgd_ref)) continue; - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); list_for_each_entry(page, &pgd_list, lru) { pgd_t *pgd; spinlock_t *pgt_lock; pgd = (pgd_t *)page_address(page) + pgd_index(address); + /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); @@ -128,7 +128,7 @@ void sync_global_pgds(unsigned long start, unsigned long end) spin_unlock(pgt_lock); } - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); } } diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 95ea1551eeb..1337c51b07d 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -780,11 +780,7 @@ void __cpuinit numa_add_cpu(int cpu) int physnid; int nid = NUMA_NO_NODE; - apicid = early_per_cpu(x86_cpu_to_apicid, cpu); - if (apicid != BAD_APICID) - nid = apicid_to_node[apicid]; - if (nid == NUMA_NO_NODE) - nid = early_cpu_to_node(cpu); + nid = early_cpu_to_node(cpu); BUG_ON(nid == NUMA_NO_NODE || !node_online(nid)); /* diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index d343b3c81f3..90825f2eb0f 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -57,12 +57,10 @@ static unsigned long direct_pages_count[PG_LEVEL_NUM]; void update_page_count(int level, unsigned long pages) { - unsigned long flags; - /* Protect against CPA */ - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); direct_pages_count[level] += pages; - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); } static void split_page_count(int level) @@ -394,7 +392,7 @@ static int try_preserve_large_page(pte_t *kpte, unsigned long address, struct cpa_data *cpa) { - unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn; + unsigned long nextpage_addr, numpages, pmask, psize, addr, pfn; pte_t new_pte, old_pte, *tmp; pgprot_t old_prot, new_prot, req_prot; int i, do_split = 1; @@ -403,7 +401,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, if (cpa->force_split) return 1; - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); /* * Check for races, another CPU might have split this page * up already: @@ -498,14 +496,14 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, } out_unlock: - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); return do_split; } static int split_large_page(pte_t *kpte, unsigned long address) { - unsigned long flags, pfn, pfninc = 1; + unsigned long pfn, pfninc = 1; unsigned int i, level; pte_t *pbase, *tmp; pgprot_t ref_prot; @@ -519,7 +517,7 @@ static int split_large_page(pte_t *kpte, unsigned long address) if (!base) return -ENOMEM; - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); /* * Check for races, another CPU might have split this page * up for us already: @@ -591,7 +589,7 @@ out_unlock: */ if (base) __free_page(base); - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); return 0; } diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 500242d3c96..0113d19c8aa 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -121,14 +121,12 @@ static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd) static void pgd_dtor(pgd_t *pgd) { - unsigned long flags; /* can be called from interrupt context */ - if (SHARED_KERNEL_PMD) return; - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); pgd_list_del(pgd); - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); } /* @@ -260,7 +258,6 @@ pgd_t *pgd_alloc(struct mm_struct *mm) { pgd_t *pgd; pmd_t *pmds[PREALLOCATED_PMDS]; - unsigned long flags; pgd = (pgd_t *)__get_free_page(PGALLOC_GFP); @@ -280,12 +277,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm) * respect to anything walking the pgd_list, so that they * never see a partially populated pgd. */ - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); pgd_ctor(mm, pgd); pgd_prepopulate_pmd(mm, pgd, pmds); - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); return pgd; diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c index 85b68ef5e80..9260b3eb18d 100644 --- a/arch/x86/pci/ce4100.c +++ b/arch/x86/pci/ce4100.c @@ -34,6 +34,7 @@ #include <linux/pci.h> #include <linux/init.h> +#include <asm/ce4100.h> #include <asm/pci_x86.h> struct sim_reg { @@ -306,10 +307,10 @@ struct pci_raw_ops ce4100_pci_conf = { .write = ce4100_conf_write, }; -static int __init ce4100_pci_init(void) +int __init ce4100_pci_init(void) { init_sim_regs(); raw_pci_ops = &ce4100_pci_conf; - return 0; + /* Indicate caller that it should invoke pci_legacy_init() */ + return 1; } -subsys_initcall(ce4100_pci_init); diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c index d2c0d51a717..cd6f184c3b3 100644 --- a/arch/x86/platform/ce4100/ce4100.c +++ b/arch/x86/platform/ce4100/ce4100.c @@ -15,6 +15,7 @@ #include <linux/serial_reg.h> #include <linux/serial_8250.h> +#include <asm/ce4100.h> #include <asm/setup.h> #include <asm/io.h> @@ -129,4 +130,5 @@ void __init x86_ce4100_early_setup(void) x86_init.resources.probe_roms = x86_init_noop; x86_init.mpparse.get_smp_config = x86_init_uint_noop; x86_init.mpparse.find_smp_config = sdv_find_smp_config; + x86_init.pci.init = ce4100_pci_init; } diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index df58e9cad96..a7b38d35c29 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1364,11 +1364,11 @@ uv_activation_descriptor_init(int node, int pnode) memset(bd2, 0, sizeof(struct bau_desc)); bd2->header.sw_ack_flag = 1; /* - * base_dest_nodeid is the nasid (pnode<<1) of the first uvhub + * base_dest_nodeid is the nasid of the first uvhub * in the partition. The bit map will indicate uvhub numbers, * which are 0-N in a partition. Pnodes are unique system-wide. */ - bd2->header.base_dest_nodeid = uv_partition_base_pnode << 1; + bd2->header.base_dest_nodeid = UV_PNODE_TO_NASID(uv_partition_base_pnode); bd2->header.dest_subnodeid = 0x10; /* the LB */ bd2->header.command = UV_NET_ENDPOINT_INTD; bd2->header.int_both = 1; diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 5e92b61ad57..f6089421147 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -986,10 +986,9 @@ static void xen_pgd_pin(struct mm_struct *mm) */ void xen_mm_pin_all(void) { - unsigned long flags; struct page *page; - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); list_for_each_entry(page, &pgd_list, lru) { if (!PagePinned(page)) { @@ -998,7 +997,7 @@ void xen_mm_pin_all(void) } } - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); } /* @@ -1099,10 +1098,9 @@ static void xen_pgd_unpin(struct mm_struct *mm) */ void xen_mm_unpin_all(void) { - unsigned long flags; struct page *page; - spin_lock_irqsave(&pgd_lock, flags); + spin_lock(&pgd_lock); list_for_each_entry(page, &pgd_list, lru) { if (PageSavePinned(page)) { @@ -1112,7 +1110,7 @@ void xen_mm_unpin_all(void) } } - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock(&pgd_lock); } void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) diff --git a/block/blk-lib.c b/block/blk-lib.c index eec78becb35..bd3e8df4d5e 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -109,7 +109,6 @@ struct bio_batch atomic_t done; unsigned long flags; struct completion *wait; - bio_end_io_t *end_io; }; static void bio_batch_end_io(struct bio *bio, int err) @@ -122,12 +121,9 @@ static void bio_batch_end_io(struct bio *bio, int err) else clear_bit(BIO_UPTODATE, &bb->flags); } - if (bb) { - if (bb->end_io) - bb->end_io(bio, err); - atomic_inc(&bb->done); - complete(bb->wait); - } + if (bb) + if (atomic_dec_and_test(&bb->done)) + complete(bb->wait); bio_put(bio); } @@ -150,13 +146,12 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, int ret; struct bio *bio; struct bio_batch bb; - unsigned int sz, issued = 0; + unsigned int sz; DECLARE_COMPLETION_ONSTACK(wait); - atomic_set(&bb.done, 0); + atomic_set(&bb.done, 1); bb.flags = 1 << BIO_UPTODATE; bb.wait = &wait; - bb.end_io = NULL; submit: ret = 0; @@ -185,12 +180,12 @@ submit: break; } ret = 0; - issued++; + atomic_inc(&bb.done); submit_bio(WRITE, bio); } /* Wait for bios in-flight */ - while (issued != atomic_read(&bb.done)) + if (!atomic_dec_and_test(&bb.done)) wait_for_completion(&wait); if (!test_bit(BIO_UPTODATE, &bb.flags)) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index e7df019d29d..43088996a07 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -21,8 +21,8 @@ #define to_amba_device(d) container_of(d, struct amba_device, dev) #define to_amba_driver(d) container_of(d, struct amba_driver, drv) -static struct amba_id * -amba_lookup(struct amba_id *table, struct amba_device *dev) +static const struct amba_id * +amba_lookup(const struct amba_id *table, struct amba_device *dev) { int ret = 0; @@ -106,7 +106,7 @@ static struct device_attribute amba_dev_attrs[] = { * Primecells are part of the Advanced Microcontroller Bus Architecture, * so we call the bus "amba". */ -static struct bus_type amba_bustype = { +struct bus_type amba_bustype = { .name = "amba", .dev_attrs = amba_dev_attrs, .match = amba_match, @@ -188,7 +188,7 @@ static int amba_probe(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *pcdrv = to_amba_driver(dev->driver); - struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); + const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); int ret; do { diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index a348c7e9aa0..dd1d143eb8e 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c @@ -39,7 +39,7 @@ static struct hwrng nmk_rng = { .read = nmk_rng_read, }; -static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id) +static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) { void __iomem *base; int ret; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 7855f9f45b8..62787e30d50 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -900,6 +900,14 @@ static void sender(void *send_info, printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif + /* + * last_timeout_jiffies is updated here to avoid + * smi_timeout() handler passing very large time_diff + * value to smi_event_handler() that causes + * the send command to abort. + */ + smi_info->last_timeout_jiffies = jiffies; + mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); if (smi_info->thread) diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 07bca4970e5..e6d7228b147 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1845,7 +1845,7 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) } #endif -static int pl08x_probe(struct amba_device *adev, struct amba_id *id) +static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) { struct pl08x_driver_data *pl08x; const struct vendor_data *vd = id->data; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 7c50f6dfd3f..6abe1ec1f2c 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -657,7 +657,7 @@ static irqreturn_t pl330_irq_handler(int irq, void *data) } static int __devinit -pl330_probe(struct amba_device *adev, struct amba_id *id) +pl330_probe(struct amba_device *adev, const struct amba_id *id) { struct dma_pl330_platdata *pdat; struct dma_pl330_dmac *pdmac; diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/ml_ioh_gpio.c index cead8e6ff34..7f6f01a4b14 100644 --- a/drivers/gpio/ml_ioh_gpio.c +++ b/drivers/gpio/ml_ioh_gpio.c @@ -326,6 +326,7 @@ static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, { 0, } }; +MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id); static struct pci_driver ioh_gpio_driver = { .name = "ml_ioh_gpio", diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c index 0eba0a75c80..2c6af870510 100644 --- a/drivers/gpio/pch_gpio.c +++ b/drivers/gpio/pch_gpio.c @@ -286,6 +286,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, { 0, } }; +MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); static struct pci_driver pch_gpio_driver = { .name = "pch_gpio", diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 2975d22daff..838ddbdf90c 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c @@ -232,7 +232,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) desc->irq_data.chip->irq_unmask(&desc->irq_data); } -static int pl061_probe(struct amba_device *dev, struct amba_id *id) +static int pl061_probe(struct amba_device *dev, const struct amba_id *id) { struct pl061_platform_data *pdata; struct pl061_gpio *chip; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3e6f486f460..2abe240dae5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1553,7 +1553,17 @@ /* Backlight control */ #define BLC_PWM_CTL 0x61254 +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) #define BLC_PWM_CTL2 0x61250 /* 965+ only */ +#define BLM_COMBINATION_MODE (1 << 30) +/* + * This is the most significant 15 bits of the number of backlight cycles in a + * complete cycle of the modulated backlight control. + * + * The actual value is this field multiplied by two. + */ +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) /* * This is the number of cycles out of the backlight modulation cycle for which * the backlight is on. diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index d860abeda70..f8f86e57df2 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -30,6 +30,8 @@ #include "intel_drv.h" +#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ + void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -110,6 +112,19 @@ done: dev_priv->pch_pf_size = (width << 16) | height; } +static int is_backlight_combination_mode(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (INTEL_INFO(dev)->gen >= 4) + return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; + + if (IS_GEN2(dev)) + return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; + + return 0; +} + static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) { u32 val; @@ -166,6 +181,9 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev) if (INTEL_INFO(dev)->gen < 4) max &= ~1; } + + if (is_backlight_combination_mode(dev)) + max *= 0xff; } DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); @@ -183,6 +201,14 @@ u32 intel_panel_get_backlight(struct drm_device *dev) val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; if (IS_PINEVIEW(dev)) val >>= 1; + + if (is_backlight_combination_mode(dev)){ + u8 lbpc; + + val &= ~1; + pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); + val *= lbpc; + } } DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); @@ -205,6 +231,16 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level) if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); + + if (is_backlight_combination_mode(dev)){ + u32 max = intel_panel_get_max_backlight(dev); + u8 lbpc; + + lbpc = level * 0xfe / max + 1; + level /= lbpc; + pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); + } + tmp = I915_READ(BLC_PWM_CTL); if (IS_PINEVIEW(dev)) { tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index d270b3ff896..6140ea1de45 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2194,7 +2194,6 @@ int evergreen_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; } rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r700_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); @@ -2934,7 +2933,7 @@ static int evergreen_startup(struct radeon_device *rdev) /* XXX: ontario has problems blitting to gart at the moment */ if (rdev->family == CHIP_PALM) { rdev->asic->copy = NULL; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); } /* allocate wb buffer */ diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 2adfb03f479..2be698e78ff 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -623,7 +623,7 @@ done: dev_err(rdev->dev, "(%d) pin blit object failed\n", r); return r; } - rdev->mc.active_vram_size = rdev->mc.real_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } @@ -631,7 +631,7 @@ void evergreen_blit_fini(struct radeon_device *rdev) { int r; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); if (rdev->r600_blit.shader_obj == NULL) return; /* If we can't reserve the bo, unref should be enough to destroy diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 93fa735c8c1..e372f9e1e5c 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -70,23 +70,6 @@ MODULE_FIRMWARE(FIRMWARE_R520); void r100_pre_page_flip(struct radeon_device *rdev, int crtc) { - struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; - u32 tmp; - - /* make sure flip is at vb rather than hb */ - tmp = RREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset); - tmp &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; - /* make sure pending bit is asserted */ - tmp |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; - WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, tmp); - - /* set pageflip to happen as late as possible in the vblank interval. - * same field for crtc1/2 - */ - tmp = RREG32(RADEON_CRTC_GEN_CNTL); - tmp &= ~RADEON_CRTC_VSTAT_MODE_MASK; - WREG32(RADEON_CRTC_GEN_CNTL, tmp); - /* enable the pflip int */ radeon_irq_kms_pflip_irq_get(rdev, crtc); } @@ -1041,7 +1024,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) return r; } rdev->cp.ready = true; - rdev->mc.active_vram_size = rdev->mc.real_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } @@ -1059,7 +1042,7 @@ void r100_cp_fini(struct radeon_device *rdev) void r100_cp_disable(struct radeon_device *rdev) { /* Disable ring */ - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); rdev->cp.ready = false; WREG32(RADEON_CP_CSQ_MODE, 0); WREG32(RADEON_CP_CSQ_CNTL, 0); @@ -2329,7 +2312,6 @@ void r100_vram_init_sizes(struct radeon_device *rdev) /* FIXME we don't use the second aperture yet when we could use it */ if (rdev->mc.visible_vram_size > rdev->mc.aper_size) rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); if (rdev->flags & RADEON_IS_IGP) { uint32_t tom; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index de88624d5f8..9b3fad23b76 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1255,7 +1255,6 @@ int r600_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); if (rdev->flags & RADEON_IS_IGP) { @@ -1937,7 +1936,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) */ void r600_cp_stop(struct radeon_device *rdev) { - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); WREG32(SCRATCH_UMSK, 0); } diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 41f7aafc97c..df68d91e819 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -558,7 +558,7 @@ done: dev_err(rdev->dev, "(%d) pin blit object failed\n", r); return r; } - rdev->mc.active_vram_size = rdev->mc.real_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } @@ -566,7 +566,7 @@ void r600_blit_fini(struct radeon_device *rdev) { int r; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); if (rdev->r600_blit.shader_obj == NULL) return; /* If we can't reserve the bo, unref should be enough to destroy diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 56c48b67ef3..6b342949511 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -345,7 +345,6 @@ struct radeon_mc { * about vram size near mc fb location */ u64 mc_vram_size; u64 visible_vram_size; - u64 active_vram_size; u64 gtt_size; u64 gtt_start; u64 gtt_end; @@ -1448,6 +1447,7 @@ extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *m extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern int radeon_resume_kms(struct drm_device *dev); extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); +extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ extern bool r600_card_posted(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index e75d63b8e21..793c5e6026a 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -834,6 +834,9 @@ static struct radeon_asic sumo_asic = { .pm_finish = &evergreen_pm_finish, .pm_init_profile = &rs780_pm_init_profile, .pm_get_dynpm_state = &r600_pm_get_dynpm_state, + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, }; static struct radeon_asic btc_asic = { diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index df95eb83dac..1fe95dfe48c 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -156,9 +156,12 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_info *args = data; + struct ttm_mem_type_manager *man; + + man = &rdev->mman.bdev.man[TTM_PL_VRAM]; args->vram_size = rdev->mc.real_vram_size; - args->vram_visible = rdev->mc.real_vram_size; + args->vram_visible = (u64)man->size << PAGE_SHIFT; if (rdev->stollen_vga_memory) args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); args->vram_visible -= radeon_fbdev_total_size(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index cf0638c3b7c..78968b738e8 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -443,7 +443,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, (target_fb->bits_per_pixel * 8)); crtc_pitch |= crtc_pitch << 16; - + crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; if (tiling_flags & RADEON_TILING_MACRO) { if (ASIC_IS_R300(rdev)) crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | @@ -502,6 +502,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, gen_cntl_val = RREG32(gen_cntl_reg); gen_cntl_val &= ~(0xf << 8); gen_cntl_val |= (format << 8); + gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK; WREG32(gen_cntl_reg, gen_cntl_val); crtc_offset = (u32)base; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index e5b2cf10cbf..8389b4c63d1 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -589,6 +589,20 @@ void radeon_ttm_fini(struct radeon_device *rdev) DRM_INFO("radeon: ttm finalized\n"); } +/* this should only be called at bootup or when userspace + * isn't running */ +void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) +{ + struct ttm_mem_type_manager *man; + + if (!rdev->mman.initialized) + return; + + man = &rdev->mman.bdev.man[TTM_PL_VRAM]; + /* this just adjusts TTM size idea, which sets lpfn to the correct value */ + man->size = size >> PAGE_SHIFT; +} + static struct vm_operations_struct radeon_ttm_vm_ops; static const struct vm_operations_struct *ttm_vm_ops = NULL; diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 5afe294ed51..8af4679db23 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -751,7 +751,6 @@ void rs600_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); base = RREG32_MC(R_000004_MC_FB_LOCATION); base = G_000004_MC_FB_START(base) << 16; diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 6638c8e4c81..66c949b7c18 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -157,7 +157,6 @@ void rs690_mc_init(struct radeon_device *rdev) rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index d8ba6769065..714ad45757d 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -307,7 +307,7 @@ static void rv770_mc_program(struct radeon_device *rdev) */ void r700_cp_stop(struct radeon_device *rdev) { - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); WREG32(SCRATCH_UMSK, 0); } @@ -1123,7 +1123,6 @@ int rv770_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; - rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r700_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 3f49dd376f0..6e06019015a 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -37,7 +37,7 @@ #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ -#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */ #define SIO_REG_LDSEL 0x07 /* Logical device select */ #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ @@ -2111,7 +2111,6 @@ static int f71882fg_remove(struct platform_device *pdev) int nr_fans = (data->type == f71882fg) ? 4 : 3; u8 start_reg = f71882fg_read8(data, F71882FG_REG_START); - platform_set_drvdata(pdev, NULL); if (data->hwmon_dev) hwmon_device_unregister(data->hwmon_dev); @@ -2178,6 +2177,7 @@ static int f71882fg_remove(struct platform_device *pdev) } } + platform_set_drvdata(pdev, NULL); kfree(data); return 0; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 58a58c7eaa1..051bdd34c17 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -72,11 +72,12 @@ enum { OMAP_I2C_SCLH_REG, OMAP_I2C_SYSTEST_REG, OMAP_I2C_BUFSTAT_REG, - OMAP_I2C_REVNB_LO, - OMAP_I2C_REVNB_HI, - OMAP_I2C_IRQSTATUS_RAW, - OMAP_I2C_IRQENABLE_SET, - OMAP_I2C_IRQENABLE_CLR, + /* only on OMAP4430 */ + OMAP_I2C_OMAP4430_REVNB_LO, + OMAP_I2C_OMAP4430_REVNB_HI, + OMAP_I2C_OMAP4430_IRQSTATUS_RAW, + OMAP_I2C_OMAP4430_IRQENABLE_SET, + OMAP_I2C_OMAP4430_IRQENABLE_CLR, }; /* I2C Interrupt Enable Register (OMAP_I2C_IE): */ @@ -244,11 +245,11 @@ const static u8 omap4_reg_map[] = { [OMAP_I2C_SCLH_REG] = 0xb8, [OMAP_I2C_SYSTEST_REG] = 0xbC, [OMAP_I2C_BUFSTAT_REG] = 0xc0, - [OMAP_I2C_REVNB_LO] = 0x00, - [OMAP_I2C_REVNB_HI] = 0x04, - [OMAP_I2C_IRQSTATUS_RAW] = 0x24, - [OMAP_I2C_IRQENABLE_SET] = 0x2c, - [OMAP_I2C_IRQENABLE_CLR] = 0x30, + [OMAP_I2C_OMAP4430_REVNB_LO] = 0x00, + [OMAP_I2C_OMAP4430_REVNB_HI] = 0x04, + [OMAP_I2C_OMAP4430_IRQSTATUS_RAW] = 0x24, + [OMAP_I2C_OMAP4430_IRQENABLE_SET] = 0x2c, + [OMAP_I2C_OMAP4430_IRQENABLE_CLR] = 0x30, }; static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, @@ -308,8 +309,8 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) pdata = pdev->dev.platform_data; dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); - if (dev->rev >= OMAP_I2C_REV_ON_4430) - omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1); + if (cpu_is_omap44xx()) + omap_i2c_write_reg(dev, OMAP_I2C_OMAP4430_IRQENABLE_CLR, 1); else omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); @@ -1034,6 +1035,17 @@ omap_i2c_probe(struct platform_device *pdev) else dev->reg_shift = 2; + dev->regs = (u8 *)reg_map; + + /* + * this is a bit tricky, implementation on 4430 has the active + * part of its ID register moved to +4 instead of +0 as + * previously. So, we can't probe just using the ID register + * Complicating matters the older implementation using the + * simpler register set on 3530 also reports its revision as + * 0x40, same as the 4430 newer implementation. + */ + if (cpu_is_omap44xx()) dev->regs = (u8 *) omap4_reg_map; else diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 92563a681d6..12abc50508e 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -107,7 +107,8 @@ static void amba_kmi_close(struct serio *io) clk_disable(kmi->clk); } -static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit amba_kmi_probe(struct amba_device *dev, + const struct amba_id *id) { struct amba_kmi_port *kmi; struct serio *io; diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index bc6a67768af..8c4852114ee 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -658,13 +658,13 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) #define TDA8290_ID 0x89 u8 reg = 0x1f, id; struct i2c_msg msg_read[] = { - { .addr = 0x4b, .flags = 0, .len = 1, .buf = ® }, - { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id }, + { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, }; /* detect tda8290 */ if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { - printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n", + printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", __func__, reg); return -ENODEV; } @@ -685,13 +685,13 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) #define TDA8295C2_ID 0x8b u8 reg = 0x2f, id; struct i2c_msg msg_read[] = { - { .addr = 0x4b, .flags = 0, .len = 1, .buf = ® }, - { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id }, + { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, }; - /* detect tda8290 */ + /* detect tda8295 */ if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { - printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n", + printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", __func__, reg); return -ENODEV; } diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index defd83964ce..193cdb77b76 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -870,6 +870,23 @@ static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index, + u16 pid, int onoff) +{ + struct dib0700_state *st = adapter->dev->priv; + if (st->is_dib7000pc) + return dib7000p_pid_filter(adapter->fe, index, pid, onoff); + return dib7000m_pid_filter(adapter->fe, index, pid, onoff); +} + +static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) +{ + struct dib0700_state *st = adapter->dev->priv; + if (st->is_dib7000pc) + return dib7000p_pid_filter_ctrl(adapter->fe, onoff); + return dib7000m_pid_filter_ctrl(adapter->fe, onoff); +} + static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) { return dib7000p_pid_filter(adapter->fe, index, pid, onoff); @@ -1875,8 +1892,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter = stk70x0p_pid_filter, - .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, + .pid_filter = stk7700p_pid_filter, + .pid_filter_ctrl = stk7700p_pid_filter_ctrl, .frontend_attach = stk7700p_frontend_attach, .tuner_attach = stk7700p_tuner_attach, diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index 9eea4188303..46ccd01a769 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -659,7 +659,7 @@ static int lme2510_download_firmware(struct usb_device *dev, } /* Default firmware for LME2510C */ -const char lme_firmware[50] = "dvb-usb-lme2510c-s7395.fw"; +char lme_firmware[50] = "dvb-usb-lme2510c-s7395.fw"; static void lme_coldreset(struct usb_device *dev) { @@ -1006,7 +1006,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .download_firmware = lme2510_download_firmware, - .firmware = lme_firmware, + .firmware = (const char *)&lme_firmware, .size_of_priv = sizeof(struct lme2510_state), .num_adapters = 1, .adapter = { @@ -1109,5 +1109,5 @@ module_exit(lme2510_module_exit); MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.74"); +MODULE_VERSION("1.75"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index c7f5ccf54aa..289a79837f2 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -1285,6 +1285,25 @@ struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum di } EXPORT_SYMBOL(dib7000m_get_i2c_master); +int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) +{ + struct dib7000m_state *state = fe->demodulator_priv; + u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef; + val |= (onoff & 0x1) << 4; + dprintk("PID filter enabled %d", onoff); + return dib7000m_write_word(state, 294 + state->reg_offs, val); +} +EXPORT_SYMBOL(dib7000m_pid_filter_ctrl); + +int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) +{ + struct dib7000m_state *state = fe->demodulator_priv; + dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff); + return dib7000m_write_word(state, 300 + state->reg_offs + id, + onoff ? (1 << 13) | pid : 0); +} +EXPORT_SYMBOL(dib7000m_pid_filter); + #if 0 /* used with some prototype boards */ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h index 113819ce9f0..81fcf2241c6 100644 --- a/drivers/media/dvb/frontends/dib7000m.h +++ b/drivers/media/dvb/frontends/dib7000m.h @@ -46,6 +46,8 @@ extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, extern struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); +extern int dib7000m_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); +extern int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff); #else static inline struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, @@ -63,6 +65,19 @@ struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *demod, printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } +static inline int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, + u16 pid, u8 onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +static inline int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, + uint8_t onoff) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} #endif /* TODO diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 59feeb84aec..10a432a79d0 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -22,7 +22,6 @@ #include <linux/moduleparam.h> #include <linux/kernel.h> #include <asm/io.h> -#include <asm/pgtable.h> #include <asm/page.h> #include <linux/kmod.h> #include <linux/vmalloc.h> diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 73230ff93b8..01f258a2a57 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -112,7 +112,7 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) { ktime_t now; s64 delta; /* ns */ - struct ir_raw_event ev; + DEFINE_IR_RAW_EVENT(ev); int rc = 0; if (!dev->raw) @@ -125,7 +125,6 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) * being called for the first time, note that delta can't * possibly be negative. */ - ev.duration = 0; if (delta > IR_MAX_DURATION || !dev->raw->last_type) type |= IR_START_EVENT; else diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 6df0a498064..e4f8eac7f71 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -148,6 +148,7 @@ enum mceusb_model_type { MCE_GEN2_TX_INV, POLARIS_EVK, CX_HYBRID_TV, + MULTIFUNCTION, }; struct mceusb_model { @@ -155,9 +156,10 @@ struct mceusb_model { u32 mce_gen2:1; u32 mce_gen3:1; u32 tx_mask_normal:1; - u32 is_polaris:1; u32 no_tx:1; + int ir_intfnum; + const char *rc_map; /* Allow specify a per-board map */ const char *name; /* per-board name */ }; @@ -179,7 +181,6 @@ static const struct mceusb_model mceusb_model[] = { .tx_mask_normal = 1, }, [POLARIS_EVK] = { - .is_polaris = 1, /* * In fact, the EVK is shipped without * remotes, but we should have something handy, @@ -189,10 +190,13 @@ static const struct mceusb_model mceusb_model[] = { .name = "Conexant Hybrid TV (cx231xx) MCE IR", }, [CX_HYBRID_TV] = { - .is_polaris = 1, .no_tx = 1, /* tx isn't wired up at all */ .name = "Conexant Hybrid TV (cx231xx) MCE IR", }, + [MULTIFUNCTION] = { + .mce_gen2 = 1, + .ir_intfnum = 2, + }, }; static struct usb_device_id mceusb_dev_table[] = { @@ -216,8 +220,9 @@ static struct usb_device_id mceusb_dev_table[] = { { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, /* Philips/Spinel plus IR transceiver for ASUS */ { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, - /* Realtek MCE IR Receiver */ - { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, + /* Realtek MCE IR Receiver and card reader */ + { USB_DEVICE(VENDOR_REALTEK, 0x0161), + .driver_info = MULTIFUNCTION }, /* SMK/Toshiba G83C0004D410 */ { USB_DEVICE(VENDOR_SMK, 0x031d), .driver_info = MCE_GEN2_TX_INV }, @@ -1101,7 +1106,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, bool is_gen3; bool is_microsoft_gen1; bool tx_mask_normal; - bool is_polaris; + int ir_intfnum; dev_dbg(&intf->dev, "%s called\n", __func__); @@ -1110,13 +1115,11 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, is_gen3 = mceusb_model[model].mce_gen3; is_microsoft_gen1 = mceusb_model[model].mce_gen1; tx_mask_normal = mceusb_model[model].tx_mask_normal; - is_polaris = mceusb_model[model].is_polaris; + ir_intfnum = mceusb_model[model].ir_intfnum; - if (is_polaris) { - /* Interface 0 is IR */ - if (idesc->desc.bInterfaceNumber) - return -ENODEV; - } + /* There are multi-function devices with non-IR interfaces */ + if (idesc->desc.bInterfaceNumber != ir_intfnum) + return -ENODEV; /* step through the endpoints to find first bulk in and out endpoint */ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 273d9d67479..d4d64492a05 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -385,8 +385,9 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) { - /* set number of bytes needed for wake key comparison (default 67) */ - nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP); + /* set number of bytes needed for wake from s3 (default 65) */ + nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_CMP_BYTES, + CIR_WAKE_FIFO_CMP_DEEP); /* set tolerance/variance allowed per byte during wake compare */ nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE, diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 1df82351cb0..048135eea70 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -305,8 +305,11 @@ struct nvt_dev { #define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 #define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 -/* CIR Wake FIFO buffer is 67 bytes long */ -#define CIR_WAKE_FIFO_LEN 67 +/* + * The CIR Wake FIFO buffer is 67 bytes long, but the stock remote wakes + * the system comparing only 65 bytes (fails with this set to 67) + */ +#define CIR_WAKE_FIFO_CMP_BYTES 65 /* CIR Wake byte comparison tolerance */ #define CIR_WAKE_CMP_TOLERANCE 5 diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 512a2f4ada0..5b4422ef4e6 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -850,7 +850,7 @@ static ssize_t store_protocols(struct device *device, count++; } else { for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { + if (!strcasecmp(tmp, proto_names[i].name)) { tmp += strlen(proto_names[i].name); mask = proto_names[i].type; break; diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index e41e4ad5cc4..9c475c600fc 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1758,7 +1758,12 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (rc < 0) return rc; - return videobuf_reqbufs(&fh->vb_vidq, rb); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + rc = videobuf_reqbufs(&fh->vb_vidq, rb); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + rc = videobuf_reqbufs(&fh->vb_vbiq, rb); + + return rc; } static int vidioc_querybuf(struct file *file, void *priv, @@ -1772,7 +1777,12 @@ static int vidioc_querybuf(struct file *file, void *priv, if (rc < 0) return rc; - return videobuf_querybuf(&fh->vb_vidq, b); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + rc = videobuf_querybuf(&fh->vb_vidq, b); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + rc = videobuf_querybuf(&fh->vb_vbiq, b); + + return rc; } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1785,7 +1795,12 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return videobuf_qbuf(&fh->vb_vidq, b); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + rc = videobuf_qbuf(&fh->vb_vidq, b); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + rc = videobuf_qbuf(&fh->vb_vbiq, b); + + return rc; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1806,7 +1821,12 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) dev->greenscreen_detected = 0; } - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK); + + return rc; } static struct v4l2_file_operations au0828_v4l_fops = { diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 87177733cf9..68ad1963f42 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -95,6 +95,53 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { .i2c = &cx18_i2c_std, }; +static const struct cx18_card cx18_card_hvr1600_s5h1411 = { + .type = CX18_CARD_HVR_1600_S5H1411, + .name = "Hauppauge HVR-1600", + .comment = "Simultaneous Digital and Analog TV capture supported\n", + .v4l2_capabilities = CX18_CAP_ENCODER, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_muxer = CX18_HW_CS5345, + .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | + CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL | + CX18_HW_Z8F0811_IR_HAUP, + .video_inputs = { + { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, + { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, + { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 }, + { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 }, + { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 }, + }, + .audio_inputs = { + { CX18_CARD_INPUT_AUD_TUNER, + CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, + { CX18_CARD_INPUT_LINE_IN1, + CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 }, + { CX18_CARD_INPUT_LINE_IN2, + CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 }, + }, + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, + CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 }, + .ddr = { + /* ESMT M13S128324A-5B memory */ + .chip_config = 0x003, + .refresh = 0x30c, + .timing1 = 0x44220e82, + .timing2 = 0x08, + .tune_lane = 0, + .initial_emrs = 0, + }, + .gpio_init.initial_value = 0x3001, + .gpio_init.direction = 0x3001, + .gpio_i2c_slave_reset = { + .active_lo_mask = 0x3001, + .msecs_asserted = 10, + .msecs_recovery = 40, + .ir_reset_mask = 0x0001, + }, + .i2c = &cx18_i2c_std, +}; + static const struct cx18_card cx18_card_hvr1600_samsung = { .type = CX18_CARD_HVR_1600_SAMSUNG, .name = "Hauppauge HVR-1600 (Preproduction)", @@ -523,7 +570,8 @@ static const struct cx18_card *cx18_card_list[] = { &cx18_card_toshiba_qosmio_dvbt, &cx18_card_leadtek_pvr2100, &cx18_card_leadtek_dvr3100h, - &cx18_card_gotview_dvd3 + &cx18_card_gotview_dvd3, + &cx18_card_hvr1600_s5h1411 }; const struct cx18_card *cx18_get_card(u16 index) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 944af8adbe0..b1c3cbd9274 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -157,6 +157,7 @@ MODULE_PARM_DESC(cardtype, "\t\t\t 7 = Leadtek WinFast PVR2100\n" "\t\t\t 8 = Leadtek WinFast DVR3100 H\n" "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n" + "\t\t\t 10 = Hauppauge HVR 1600 (S5H1411)\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); @@ -337,6 +338,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) switch (cx->card->type) { case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: + case CX18_CARD_HVR_1600_S5H1411: tveeprom_hauppauge_analog(&c, tv, eedata); break; case CX18_CARD_YUAN_MPC718: @@ -365,7 +367,25 @@ static void cx18_process_eeprom(struct cx18 *cx) from the model number. Use the cardtype module option if you have one of these preproduction models. */ switch (tv.model) { - case 74000 ... 74999: + case 74301: /* Retail models */ + case 74321: + case 74351: /* OEM models */ + case 74361: + /* Digital side is s5h1411/tda18271 */ + cx->card = cx18_get_card(CX18_CARD_HVR_1600_S5H1411); + break; + case 74021: /* Retail models */ + case 74031: + case 74041: + case 74141: + case 74541: /* OEM models */ + case 74551: + case 74591: + case 74651: + case 74691: + case 74751: + case 74891: + /* Digital side is s5h1409/mxl5005s */ cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); break; case 0x718: @@ -377,7 +397,8 @@ static void cx18_process_eeprom(struct cx18 *cx) CX18_ERR("Invalid EEPROM\n"); return; default: - CX18_ERR("Unknown model %d, defaulting to HVR-1600\n", tv.model); + CX18_ERR("Unknown model %d, defaulting to original HVR-1600 " + "(cardtype=1)\n", tv.model); cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); break; } diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 306caac6d3f..f736679d251 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -85,7 +85,8 @@ #define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ #define CX18_CARD_LEADTEK_DVR3100H 7 /* Leadtek WinFast DVR3100 H */ #define CX18_CARD_GOTVIEW_PCI_DVD3 8 /* GoTView PCI DVD3 Hybrid */ -#define CX18_CARD_LAST 8 +#define CX18_CARD_HVR_1600_S5H1411 9 /* Hauppauge HVR 1600 s5h1411/tda18271*/ +#define CX18_CARD_LAST 9 #define CX18_ENC_STREAM_TYPE_MPG 0 #define CX18_ENC_STREAM_TYPE_TS 1 diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index f0381d62518..f41922bd402 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -29,6 +29,8 @@ #include "cx18-gpio.h" #include "s5h1409.h" #include "mxl5005s.h" +#include "s5h1411.h" +#include "tda18271.h" #include "zl10353.h" #include <linux/firmware.h> @@ -77,6 +79,32 @@ static struct s5h1409_config hauppauge_hvr1600_config = { }; /* + * CX18_CARD_HVR_1600_S5H1411 + */ +static struct s5h1411_config hcw_s5h1411_config = { + .output_mode = S5H1411_SERIAL_OUTPUT, + .gpio = S5H1411_GPIO_OFF, + .vsb_if = S5H1411_IF_44000, + .qam_if = S5H1411_IF_4000, + .inversion = S5H1411_INVERSION_ON, + .status_mode = S5H1411_DEMODLOCKING, + .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + +static struct tda18271_std_map hauppauge_tda18271_std_map = { + .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, + .if_lvl = 6, .rfagc_top = 0x37 }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, + .if_lvl = 6, .rfagc_top = 0x37 }, +}; + +static struct tda18271_config hauppauge_tda18271_config = { + .std_map = &hauppauge_tda18271_std_map, + .gate = TDA18271_GATE_DIGITAL, + .output_opt = TDA18271_OUTPUT_LT_OFF, +}; + +/* * CX18_CARD_LEADTEK_DVR3100H */ /* Information/confirmation of proper config values provided by Terry Wu */ @@ -244,6 +272,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) switch (cx->card->type) { case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: + case CX18_CARD_HVR_1600_S5H1411: v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL); v |= 0x00400000; /* Serial Mode */ v |= 0x00002000; /* Data Length - Byte */ @@ -455,6 +484,15 @@ static int dvb_register(struct cx18_stream *stream) ret = 0; } break; + case CX18_CARD_HVR_1600_S5H1411: + dvb->fe = dvb_attach(s5h1411_attach, + &hcw_s5h1411_config, + &cx->i2c_adap[0]); + if (dvb->fe != NULL) + dvb_attach(tda18271_attach, dvb->fe, + 0x60, &cx->i2c_adap[0], + &hauppauge_tda18271_config); + break; case CX18_CARD_LEADTEK_DVR3100H: dvb->fe = dvb_attach(zl10353_attach, &leadtek_dvr3100h_demod, diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index ed3d8f55029..307ff543c25 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -122,10 +122,6 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (!i2c_wait_done(i2c_adap)) goto eio; - if (!i2c_slave_did_ack(i2c_adap)) { - retval = -ENXIO; - goto err; - } if (i2c_debug) { printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]); if (!(ctrl & I2C_NOSTOP)) @@ -158,7 +154,6 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; - err: if (i2c_debug) printk(KERN_ERR " ERR: %d\n", retval); return retval; @@ -209,10 +204,6 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, if (!i2c_wait_done(i2c_adap)) goto eio; - if (cnt == 0 && !i2c_slave_did_ack(i2c_adap)) { - retval = -ENXIO; - goto err; - } msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; if (i2c_debug) { dprintk(1, " %02x", msg->buf[cnt]); @@ -224,7 +215,6 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, eio: retval = -EIO; - err: if (i2c_debug) printk(KERN_ERR " ERR: %d\n", retval); return retval; diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 6fc09dd41b9..35796e03524 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -2015,7 +2015,8 @@ static int cx25840_probe(struct i2c_client *client, kfree(state); return err; } - v4l2_ctrl_cluster(2, &state->volume); + if (!is_cx2583x(state)) + v4l2_ctrl_cluster(2, &state->volume); v4l2_ctrl_handler_setup(&state->hdl); if (client->dev.platform_data) { diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 9b4faf00919..9c29e964d40 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -628,22 +628,66 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv) static void ivtv_irq_dma_err(struct ivtv *itv) { u32 data[CX2341X_MBOX_MAX_DATA]; + u32 status; del_timer(&itv->dma_timer); + ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); + status = read_reg(IVTV_REG_DMASTATUS); IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], - read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); - write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); + status, itv->cur_dma_stream); + /* + * We do *not* write back to the IVTV_REG_DMASTATUS register to + * clear the error status, if either the encoder write (0x02) or + * decoder read (0x01) bus master DMA operation do not indicate + * completed. We can race with the DMA engine, which may have + * transitioned to completed status *after* we read the register. + * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the + * DMA engine has completed, will cause the DMA engine to stop working. + */ + status &= 0x3; + if (status == 0x3) + write_reg(status, IVTV_REG_DMASTATUS); + if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) { struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream]; - /* retry */ - if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) + if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { + /* retry */ + /* + * FIXME - handle cases of DMA error similar to + * encoder below, except conditioned on status & 0x1 + */ ivtv_dma_dec_start(s); - else - ivtv_dma_enc_start(s); - return; + return; + } else { + if ((status & 0x2) == 0) { + /* + * CX2341x Bus Master DMA write is ongoing. + * Reset the timer and let it complete. + */ + itv->dma_timer.expires = + jiffies + msecs_to_jiffies(600); + add_timer(&itv->dma_timer); + return; + } + + if (itv->dma_retries < 3) { + /* + * CX2341x Bus Master DMA write has ended. + * Retry the write, starting with the first + * xfer segment. Just retrying the current + * segment is not sufficient. + */ + s->sg_processed = 0; + itv->dma_retries++; + ivtv_dma_enc_start_xfer(s); + return; + } + /* Too many retries, give up on this one */ + } + } if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { ivtv_udma_start(itv); diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index c179041d91f..e7e717800ee 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -1011,7 +1011,6 @@ static int m2mtest_remove(struct platform_device *pdev) v4l2_m2m_release(dev->m2m_dev); del_timer_sync(&dev->timer); video_unregister_device(dev->vfd); - video_device_release(dev->vfd); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index b63f8cafa67..561909b65ce 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -57,7 +57,7 @@ #include <linux/usb.h> #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 20 +#define S2255_MINOR_VERSION 21 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -312,9 +312,9 @@ struct s2255_fh { }; /* current cypress EEPROM firmware version */ -#define S2255_CUR_USB_FWVER ((3 << 8) | 6) +#define S2255_CUR_USB_FWVER ((3 << 8) | 11) /* current DSP FW version */ -#define S2255_CUR_DSP_FWVER 8 +#define S2255_CUR_DSP_FWVER 10102 /* Need DSP version 5+ for video status feature */ #define S2255_MIN_DSP_STATUS 5 #define S2255_MIN_DSP_COLORFILTER 8 @@ -492,9 +492,11 @@ static void planar422p_to_yuv_packed(const unsigned char *in, static void s2255_reset_dsppower(struct s2255_dev *dev) { - s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1); + s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b01, NULL, 0, 1); msleep(10); s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1); + msleep(600); + s2255_vendor_req(dev, 0x10, 0x0000, 0x0000, NULL, 0, 1); return; } diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2d6de3e03e2..67f17d61b97 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -713,7 +713,8 @@ static const struct mmc_host_ops mmci_ops = { .get_cd = mmci_get_cd, }; -static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit mmci_probe(struct amba_device *dev, + const struct amba_id *id) { struct mmci_platform_data *plat = dev->dev.platform_data; struct variant_data *variant = id->data; diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index a8c3e1c9b02..4aaa88f8ab5 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1230,10 +1230,32 @@ static int inval_cache_and_wait_for_operation( sleep_time = chip_op_time / 2; for (;;) { + if (chip->state != chip_state) { + /* Someone's suspended the operation: sleep */ + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + mutex_unlock(&chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + mutex_lock(&chip->mutex); + continue; + } + status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; + if (chip->erase_suspended && chip_state == FL_ERASING) { + /* Erase suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->erase_suspended = 0; + } + if (chip->write_suspended && chip_state == FL_WRITING) { + /* Write suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->write_suspended = 0; + } if (!timeo) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; @@ -1257,27 +1279,6 @@ static int inval_cache_and_wait_for_operation( timeo--; } mutex_lock(&chip->mutex); - - while (chip->state != chip_state) { - /* Someone's suspended the operation: sleep */ - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - mutex_lock(&chip->mutex); - } - if (chip->erase_suspended && chip_state == FL_ERASING) { - /* Erase suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->erase_suspended = 0; - } - if (chip->write_suspended && chip_state == FL_WRITING) { - /* Write suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->write_suspended = 0; - } } /* Done and happy. */ diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index d72a5fb2d04..4e1be51cc12 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -1935,14 +1935,14 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi) } -static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) +static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int index) { int i,num_erase_regions; uint8_t uaddr; - if (! (jedec_table[index].devtypes & p_cfi->device_type)) { + if (!(jedec_table[index].devtypes & cfi->device_type)) { DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", - jedec_table[index].name, 4 * (1<<p_cfi->device_type)); + jedec_table[index].name, 4 * (1<<cfi->device_type)); return 0; } @@ -1950,27 +1950,28 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) num_erase_regions = jedec_table[index].nr_regions; - p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); - if (!p_cfi->cfiq) { + cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); + if (!cfi->cfiq) { //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); return 0; } - memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); + memset(cfi->cfiq, 0, sizeof(struct cfi_ident)); - p_cfi->cfiq->P_ID = jedec_table[index].cmd_set; - p_cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; - p_cfi->cfiq->DevSize = jedec_table[index].dev_size; - p_cfi->cfi_mode = CFI_MODE_JEDEC; + cfi->cfiq->P_ID = jedec_table[index].cmd_set; + cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; + cfi->cfiq->DevSize = jedec_table[index].dev_size; + cfi->cfi_mode = CFI_MODE_JEDEC; + cfi->sector_erase_cmd = CMD(0x30); for (i=0; i<num_erase_regions; i++){ - p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; + cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; } - p_cfi->cmdset_priv = NULL; + cfi->cmdset_priv = NULL; /* This may be redundant for some cases, but it doesn't hurt */ - p_cfi->mfr = jedec_table[index].mfr_id; - p_cfi->id = jedec_table[index].dev_id; + cfi->mfr = jedec_table[index].mfr_id; + cfi->id = jedec_table[index].dev_id; uaddr = jedec_table[index].uaddr; @@ -1978,8 +1979,8 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) our brains explode when we see the datasheets talking about address lines numbered from A-1 to A18. The CFI table has unlock addresses in device-words according to the mode the device is connected in */ - p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / p_cfi->device_type; - p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / p_cfi->device_type; + cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / cfi->device_type; + cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / cfi->device_type; return 1; /* ok */ } @@ -2175,7 +2176,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", __func__, cfi->mfr, cfi->id, cfi->addr_unlock1, cfi->addr_unlock2 ); - if (!cfi_jedec_setup(cfi, i)) + if (!cfi_jedec_setup(map, cfi, i)) return 0; goto ok_out; } diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 77d64ce19e9..92de7e3a49a 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -151,6 +151,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, printk(KERN_ERR MOD_NAME " %s(): Unable to register resource %pR - kernel bug?\n", __func__, &window->rsrc); + return -EBUSY; } diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index cb20c67995d..e0a2373bf0e 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -413,7 +413,6 @@ error3: error2: list_del(&new->list); error1: - kfree(new); return ret; } diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 15682ec8530..28af71c6183 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -968,6 +968,6 @@ static void __exit omap_nand_exit(void) module_init(omap_nand_init); module_exit(omap_nand_exit); -MODULE_ALIAS(DRIVER_NAME); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards"); diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index e78914938c5..ac08750748a 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c @@ -131,7 +131,7 @@ static struct platform_driver generic_onenand_driver = { .remove = __devexit_p(generic_onenand_remove), }; -MODULE_ALIAS(DRIVER_NAME); +MODULE_ALIAS("platform:" DRIVER_NAME); static int __init generic_onenand_init(void) { diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index ac31f461cc1..c849cacf4b2 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -860,7 +860,7 @@ static void __exit omap2_onenand_exit(void) module_init(omap2_onenand_init); module_exit(omap2_onenand_exit); -MODULE_ALIAS(DRIVER_NAME); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>"); MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3"); diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 39214e51245..7ca0eded256 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -425,11 +425,6 @@ static irqreturn_t ariadne_interrupt(int irq, void *data) int csr0, boguscnt; int handled = 0; - if (dev == NULL) { - printk(KERN_WARNING "ariadne_interrupt(): irq for unknown device.\n"); - return IRQ_NONE; - } - lance->RAP = CSR0; /* PCnet-ISA Controller Status */ if (!(lance->RDP & INTR)) /* Check if any interrupt has been */ diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 7897d114b29..8849699c66c 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -1211,6 +1211,7 @@ struct bnx2x { /* DCBX Negotation results */ struct dcbx_features dcbx_local_feat; u32 dcbx_error; + u32 pending_max; }; /** @@ -1616,8 +1617,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, /* CMNG constants, as derived from system spec calculations */ /* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */ #define DEF_MIN_RATE 100 -/* resolution of the rate shaping timer - 100 usec */ -#define RS_PERIODIC_TIMEOUT_USEC 100 +/* resolution of the rate shaping timer - 400 usec */ +#define RS_PERIODIC_TIMEOUT_USEC 400 /* number of bytes in single QM arbitration cycle - * coefficient for calculating the fairness timer */ #define QM_ARB_BYTES 160000 diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 93798129061..a71b3294053 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -996,6 +996,23 @@ void bnx2x_free_skbs(struct bnx2x *bp) bnx2x_free_rx_skbs(bp); } +void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value) +{ + /* load old values */ + u32 mf_cfg = bp->mf_config[BP_VN(bp)]; + + if (value != bnx2x_extract_max_cfg(bp, mf_cfg)) { + /* leave all but MAX value */ + mf_cfg &= ~FUNC_MF_CFG_MAX_BW_MASK; + + /* set new MAX value */ + mf_cfg |= (value << FUNC_MF_CFG_MAX_BW_SHIFT) + & FUNC_MF_CFG_MAX_BW_MASK; + + bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, mf_cfg); + } +} + static void bnx2x_free_msix_irqs(struct bnx2x *bp) { int i, offset = 1; @@ -1464,6 +1481,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bnx2x_set_eth_mac(bp, 1); + if (bp->pending_max) { + bnx2x_update_max_mf_config(bp, bp->pending_max); + bp->pending_max = 0; + } + if (bp->port.pmf) bnx2x_initial_phy_init(bp, load_mode); diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 326ba44b3de..85ea7f26b51 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -341,6 +341,15 @@ void bnx2x_dcbx_init(struct bnx2x *bp); */ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state); +/** + * Updates MAX part of MF configuration in HW + * (if required) + * + * @param bp + * @param value + */ +void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value); + /* dev_close main block */ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index ef2919987a1..7e92f9d0dcf 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -238,7 +238,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) speed |= (cmd->speed_hi << 16); if (IS_MF_SI(bp)) { - u32 param = 0, part; + u32 part; u32 line_speed = bp->link_vars.line_speed; /* use 10G if no link detected */ @@ -251,24 +251,22 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) REQ_BC_VER_4_SET_MF_BW); return -EINVAL; } + part = (speed * 100) / line_speed; + if (line_speed < speed || !part) { BNX2X_DEV_INFO("Speed setting should be in a range " "from 1%% to 100%% " "of actual line speed\n"); return -EINVAL; } - /* load old values */ - param = bp->mf_config[BP_VN(bp)]; - /* leave only MIN value */ - param &= FUNC_MF_CFG_MIN_BW_MASK; - - /* set new MAX value */ - param |= (part << FUNC_MF_CFG_MAX_BW_SHIFT) - & FUNC_MF_CFG_MAX_BW_MASK; + if (bp->state != BNX2X_STATE_OPEN) + /* store value for following "load" */ + bp->pending_max = part; + else + bnx2x_update_max_mf_config(bp, part); - bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, param); return 0; } diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 032ae184b60..aa032339e32 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -2092,8 +2092,9 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type) bnx2x_calc_vn_weight_sum(bp); /* calculate and set min-max rate for each vn */ - for (vn = VN_0; vn < E1HVN_MAX; vn++) - bnx2x_init_vn_minmax(bp, vn); + if (bp->port.pmf) + for (vn = VN_0; vn < E1HVN_MAX; vn++) + bnx2x_init_vn_minmax(bp, vn); /* always enable rate shaping and fairness */ bp->cmng.flags.cmng_enables |= @@ -2162,13 +2163,6 @@ static void bnx2x_link_attn(struct bnx2x *bp) bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); } - /* indicate link status only if link status actually changed */ - if (prev_link_status != bp->link_vars.link_status) - bnx2x_link_report(bp); - - if (IS_MF(bp)) - bnx2x_link_sync_notify(bp); - if (bp->link_vars.link_up && bp->link_vars.line_speed) { int cmng_fns = bnx2x_get_cmng_fns_mode(bp); @@ -2180,6 +2174,13 @@ static void bnx2x_link_attn(struct bnx2x *bp) DP(NETIF_MSG_IFUP, "single function mode without fairness\n"); } + + if (IS_MF(bp)) + bnx2x_link_sync_notify(bp); + + /* indicate link status only if link status actually changed */ + if (prev_link_status != bp->link_vars.link_status) + bnx2x_link_report(bp); } void bnx2x__link_status_update(struct bnx2x *bp) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 1024ae15822..a5d5d0b5b15 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -281,23 +281,23 @@ static inline int __check_agg_selection_timer(struct port *port) } /** - * __get_rx_machine_lock - lock the port's RX machine + * __get_state_machine_lock - lock the port's state machines * @port: the port we're looking at * */ -static inline void __get_rx_machine_lock(struct port *port) +static inline void __get_state_machine_lock(struct port *port) { - spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); + spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); } /** - * __release_rx_machine_lock - unlock the port's RX machine + * __release_state_machine_lock - unlock the port's state machines * @port: the port we're looking at * */ -static inline void __release_rx_machine_lock(struct port *port) +static inline void __release_state_machine_lock(struct port *port) { - spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); + spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); } /** @@ -388,14 +388,14 @@ static u8 __get_duplex(struct port *port) } /** - * __initialize_port_locks - initialize a port's RX machine spinlock + * __initialize_port_locks - initialize a port's STATE machine spinlock * @port: the port we're looking at * */ static inline void __initialize_port_locks(struct port *port) { // make sure it isn't called twice - spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); + spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); } //conversions @@ -1025,9 +1025,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) { rx_states_t last_state; - // Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback) - __get_rx_machine_lock(port); - // keep current State Machine state to compare later if it was changed last_state = port->sm_rx_state; @@ -1133,7 +1130,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) pr_err("%s: An illegal loopback occurred on adapter (%s).\n" "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", port->slave->dev->master->name, port->slave->dev->name); - __release_rx_machine_lock(port); return; } __update_selected(lacpdu, port); @@ -1153,7 +1149,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) break; } } - __release_rx_machine_lock(port); } /** @@ -2155,6 +2150,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work) goto re_arm; } + /* Lock around state machines to protect data accessed + * by all (e.g., port->sm_vars). ad_rx_machine may run + * concurrently due to incoming LACPDU. + */ + __get_state_machine_lock(port); + ad_rx_machine(NULL, port); ad_periodic_machine(port); ad_port_selection_logic(port); @@ -2164,6 +2165,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work) // turn off the BEGIN bit, since we already handled it if (port->sm_vars & AD_PORT_BEGIN) port->sm_vars &= ~AD_PORT_BEGIN; + + __release_state_machine_lock(port); } re_arm: @@ -2200,7 +2203,10 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u case AD_TYPE_LACPDU: pr_debug("Received LACPDU on port %d\n", port->actor_port_number); + /* Protect against concurrent state machines */ + __get_state_machine_lock(port); ad_rx_machine(lacpdu, port); + __release_state_machine_lock(port); break; case AD_TYPE_MARKER: diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 2c46a154f2c..b28baff7086 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -264,7 +264,8 @@ struct ad_bond_info { struct ad_slave_info { struct aggregator aggregator; // 802.3ad aggregator structure struct port port; // 802.3ad port structure - spinlock_t rx_machine_lock; // To avoid race condition between callback and receive interrupt + spinlock_t state_machine_lock; /* mutex state machines vs. + incoming LACPDU */ u16 id; }; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 5933621ac3f..fc27a9926d9 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -528,8 +528,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, vnet_hdr_len = q->vnet_hdr_sz; err = -EINVAL; - if ((len -= vnet_hdr_len) < 0) + if (len < vnet_hdr_len) goto err; + len -= vnet_hdr_len; err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, sizeof(vnet_hdr)); diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 27e6f6d43ca..e3ebd90ae65 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -49,8 +49,8 @@ #include <asm/processor.h> #define DRV_NAME "r6040" -#define DRV_VERSION "0.26" -#define DRV_RELDATE "30May2010" +#define DRV_VERSION "0.27" +#define DRV_RELDATE "23Feb2011" /* PHY CHIP Address */ #define PHY1_ADDR 1 /* For MAC1 */ @@ -69,6 +69,8 @@ /* MAC registers */ #define MCR0 0x00 /* Control register 0 */ +#define MCR0_PROMISC 0x0020 /* Promiscuous mode */ +#define MCR0_HASH_EN 0x0100 /* Enable multicast hash table function */ #define MCR1 0x04 /* Control register 1 */ #define MAC_RST 0x0001 /* Reset the MAC */ #define MBCR 0x08 /* Bus control */ @@ -851,77 +853,92 @@ static void r6040_multicast_list(struct net_device *dev) { struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - u16 *adrp; - u16 reg; unsigned long flags; struct netdev_hw_addr *ha; int i; + u16 *adrp; + u16 hash_table[4] = { 0 }; + + spin_lock_irqsave(&lp->lock, flags); - /* MAC Address */ + /* Keep our MAC Address */ adrp = (u16 *)dev->dev_addr; iowrite16(adrp[0], ioaddr + MID_0L); iowrite16(adrp[1], ioaddr + MID_0M); iowrite16(adrp[2], ioaddr + MID_0H); - /* Promiscous Mode */ - spin_lock_irqsave(&lp->lock, flags); - /* Clear AMCP & PROM bits */ - reg = ioread16(ioaddr) & ~0x0120; - if (dev->flags & IFF_PROMISC) { - reg |= 0x0020; - lp->mcr0 |= 0x0020; - } - /* Too many multicast addresses - * accept all traffic */ - else if ((netdev_mc_count(dev) > MCAST_MAX) || - (dev->flags & IFF_ALLMULTI)) - reg |= 0x0020; + lp->mcr0 = ioread16(ioaddr + MCR0) & ~(MCR0_PROMISC | MCR0_HASH_EN); - iowrite16(reg, ioaddr); - spin_unlock_irqrestore(&lp->lock, flags); + /* Promiscuous mode */ + if (dev->flags & IFF_PROMISC) + lp->mcr0 |= MCR0_PROMISC; - /* Build the hash table */ - if (netdev_mc_count(dev) > MCAST_MAX) { - u16 hash_table[4]; - u32 crc; + /* Enable multicast hash table function to + * receive all multicast packets. */ + else if (dev->flags & IFF_ALLMULTI) { + lp->mcr0 |= MCR0_HASH_EN; - for (i = 0; i < 4; i++) - hash_table[i] = 0; + for (i = 0; i < MCAST_MAX ; i++) { + iowrite16(0, ioaddr + MID_1L + 8 * i); + iowrite16(0, ioaddr + MID_1M + 8 * i); + iowrite16(0, ioaddr + MID_1H + 8 * i); + } + for (i = 0; i < 4; i++) + hash_table[i] = 0xffff; + } + /* Use internal multicast address registers if the number of + * multicast addresses is not greater than MCAST_MAX. */ + else if (netdev_mc_count(dev) <= MCAST_MAX) { + i = 0; netdev_for_each_mc_addr(ha, dev) { - char *addrs = ha->addr; + u16 *adrp = (u16 *) ha->addr; + iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); + iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); + iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); + i++; + } + while (i < MCAST_MAX) { + iowrite16(0, ioaddr + MID_1L + 8 * i); + iowrite16(0, ioaddr + MID_1M + 8 * i); + iowrite16(0, ioaddr + MID_1H + 8 * i); + i++; + } + } + /* Otherwise, Enable multicast hash table function. */ + else { + u32 crc; - if (!(*addrs & 1)) - continue; + lp->mcr0 |= MCR0_HASH_EN; + + for (i = 0; i < MCAST_MAX ; i++) { + iowrite16(0, ioaddr + MID_1L + 8 * i); + iowrite16(0, ioaddr + MID_1M + 8 * i); + iowrite16(0, ioaddr + MID_1H + 8 * i); + } - crc = ether_crc_le(6, addrs); + /* Build multicast hash table */ + netdev_for_each_mc_addr(ha, dev) { + u8 *addrs = ha->addr; + + crc = ether_crc(ETH_ALEN, addrs); crc >>= 26; - hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); + hash_table[crc >> 4] |= 1 << (crc & 0xf); } - /* Fill the MAC hash tables with their values */ + } + + iowrite16(lp->mcr0, ioaddr + MCR0); + + /* Fill the MAC hash tables with their values */ + if (lp->mcr0 && MCR0_HASH_EN) { iowrite16(hash_table[0], ioaddr + MAR0); iowrite16(hash_table[1], ioaddr + MAR1); iowrite16(hash_table[2], ioaddr + MAR2); iowrite16(hash_table[3], ioaddr + MAR3); } - /* Multicast Address 1~4 case */ - i = 0; - netdev_for_each_mc_addr(ha, dev) { - if (i >= MCAST_MAX) - break; - adrp = (u16 *) ha->addr; - iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); - iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); - iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); - i++; - } - while (i < MCAST_MAX) { - iowrite16(0xffff, ioaddr + MID_1L + 8 * i); - iowrite16(0xffff, ioaddr + MID_1M + 8 * i); - iowrite16(0xffff, ioaddr + MID_1H + 8 * i); - i++; - } + + spin_unlock_irqrestore(&lp->lock, flags); } static void netdev_get_drvinfo(struct net_device *dev, diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 64bfdae5956..d70bde95460 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1178,6 +1178,11 @@ static int smsc911x_open(struct net_device *dev) smsc911x_reg_write(pdata, HW_CFG, 0x00050000); smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740); + /* Increase the legal frame size of VLAN tagged frames to 1522 bytes */ + spin_lock_irq(&pdata->mac_lock); + smsc911x_mac_write(pdata, VLAN1, ETH_P_8021Q); + spin_unlock_irq(&pdata->mac_lock); + /* Make sure EEPROM has finished loading before setting GPIO_CFG */ timeout = 50; while ((smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) && diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index bbdb2f02798..baff724cd40 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -103,7 +103,7 @@ static const struct rtc_class_ops pl030_ops = { .set_alarm = pl030_set_alarm, }; -static int pl030_probe(struct amba_device *dev, struct amba_id *id) +static int pl030_probe(struct amba_device *dev, const struct amba_id *id) { struct pl030_rtc *rtc; int ret; diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index b7a6690e5b3..6568f4b37e1 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -358,7 +358,7 @@ static int pl031_remove(struct amba_device *adev) return 0; } -static int pl031_probe(struct amba_device *adev, struct amba_id *id) +static int pl031_probe(struct amba_device *adev, const struct amba_id *id) { int ret; struct pl031_local *ldata; diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 71a1219a995..95e58c70a2c 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -2021,7 +2021,7 @@ static void pl022_cleanup(struct spi_device *spi) static int __devinit -pl022_probe(struct amba_device *adev, struct amba_id *id) +pl022_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct pl022_ssp_controller *platform_info = adev->dev.platform_data; diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 158cecbec71..4a109835e42 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -282,6 +282,9 @@ int core_tmr_lun_reset( atomic_set(&task->task_active, 0); atomic_set(&task->task_stop, 0); + } else { + if (atomic_read(&task->task_execute_queue) != 0) + transport_remove_task_from_execute_queue(task, dev); } __transport_stop_task_timer(task, &flags); @@ -301,6 +304,7 @@ int core_tmr_lun_reset( DEBUG_LR("LUN_RESET: got t_transport_active = 1 for" " task: %p, t_fe_count: %d dev: %p\n", task, fe_count, dev); + atomic_set(&T_TASK(cmd)->t_transport_aborted, 1); spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); @@ -310,6 +314,7 @@ int core_tmr_lun_reset( } DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p," " t_fe_count: %d dev: %p\n", task, fe_count, dev); + atomic_set(&T_TASK(cmd)->t_transport_aborted, 1); spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 236e22d8cfa..4bbf6c147f8 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1207,7 +1207,7 @@ transport_get_task_from_execute_queue(struct se_device *dev) * * */ -static void transport_remove_task_from_execute_queue( +void transport_remove_task_from_execute_queue( struct se_task *task, struct se_device *dev) { @@ -5549,7 +5549,8 @@ static void transport_generic_wait_for_tasks( atomic_set(&T_TASK(cmd)->transport_lun_stop, 0); } - if (!atomic_read(&T_TASK(cmd)->t_transport_active)) + if (!atomic_read(&T_TASK(cmd)->t_transport_active) || + atomic_read(&T_TASK(cmd)->t_transport_aborted)) goto remove; atomic_set(&T_TASK(cmd)->t_transport_stop, 1); @@ -5956,6 +5957,9 @@ static void transport_processing_shutdown(struct se_device *dev) atomic_set(&task->task_active, 0); atomic_set(&task->task_stop, 0); + } else { + if (atomic_read(&task->task_execute_queue) != 0) + transport_remove_task_from_execute_queue(task, dev); } __transport_stop_task_timer(task, &flags); diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 2904aa04412..d742dd2c525 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -676,7 +676,7 @@ static struct uart_driver amba_reg = { .cons = AMBA_CONSOLE, }; -static int pl010_probe(struct amba_device *dev, struct amba_id *id) +static int pl010_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; void __iomem *base; diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e76d7d00012..0dae46f9102 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1349,7 +1349,7 @@ static struct uart_driver amba_reg = { .cons = AMBA_CONSOLE, }; -static int pl011_probe(struct amba_device *dev, struct amba_id *id) +static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; struct vendor_data *vendor = id->data; diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 1c2c68356ea..013c8ce5720 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -461,7 +461,7 @@ static int clcdfb_register(struct clcd_fb *fb) return ret; } -static int clcdfb_probe(struct amba_device *dev, struct amba_id *id) +static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id) { struct clcd_board *board = dev->dev.platform_data; struct clcd_fb *fb; diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 43b64403eaa..0d031b2ad3e 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -1,8 +1,8 @@ menuconfig OMAP2_DSS - tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" - depends on ARCH_OMAP2 || ARCH_OMAP3 + tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" + depends on ARCH_OMAP2PLUS help - OMAP2/3 Display Subsystem support. + OMAP2+ Display Subsystem support. if OMAP2_DSS diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8e89f604928..3c4ad3a66f3 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -34,32 +34,17 @@ #include <linux/regulator/consumer.h> #include <plat/display.h> -#include <plat/clock.h> #include "dss.h" #include "dss_features.h" static struct { struct platform_device *pdev; - int ctx_id; - - struct clk *dss_ick; - struct clk *dss1_fck; - struct clk *dss2_fck; - struct clk *dss_54m_fck; - struct clk *dss_96m_fck; - unsigned num_clks_enabled; struct regulator *vdds_dsi_reg; struct regulator *vdds_sdi_reg; - struct regulator *vdda_dac_reg; } core; -static void dss_clk_enable_all_no_ctx(void); -static void dss_clk_disable_all_no_ctx(void); -static void dss_clk_enable_no_ctx(enum dss_clock clks); -static void dss_clk_disable_no_ctx(enum dss_clock clks); - static char *def_disp_name; module_param_named(def_disp, def_disp_name, charp, 0); MODULE_PARM_DESC(def_disp_name, "default display name"); @@ -69,297 +54,6 @@ unsigned int dss_debug; module_param_named(debug, dss_debug, bool, 0644); #endif -/* CONTEXT */ -static int dss_get_ctx_id(void) -{ - struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; - int r; - - if (!pdata->get_last_off_on_transaction_id) - return 0; - r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); - if (r < 0) { - dev_err(&core.pdev->dev, "getting transaction ID failed, " - "will force context restore\n"); - r = -1; - } - return r; -} - -int dss_need_ctx_restore(void) -{ - int id = dss_get_ctx_id(); - - if (id < 0 || id != core.ctx_id) { - DSSDBG("ctx id %d -> id %d\n", - core.ctx_id, id); - core.ctx_id = id; - return 1; - } else { - return 0; - } -} - -static void save_all_ctx(void) -{ - DSSDBG("save context\n"); - - dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); - - dss_save_context(); - dispc_save_context(); -#ifdef CONFIG_OMAP2_DSS_DSI - dsi_save_context(); -#endif - - dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); -} - -static void restore_all_ctx(void) -{ - DSSDBG("restore context\n"); - - dss_clk_enable_all_no_ctx(); - - dss_restore_context(); - dispc_restore_context(); -#ifdef CONFIG_OMAP2_DSS_DSI - dsi_restore_context(); -#endif - - dss_clk_disable_all_no_ctx(); -} - -#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) -/* CLOCKS */ -static void core_dump_clocks(struct seq_file *s) -{ - int i; - struct clk *clocks[5] = { - core.dss_ick, - core.dss1_fck, - core.dss2_fck, - core.dss_54m_fck, - core.dss_96m_fck - }; - - seq_printf(s, "- CORE -\n"); - - seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); - - for (i = 0; i < 5; i++) { - if (!clocks[i]) - continue; - seq_printf(s, "%-15s\t%lu\t%d\n", - clocks[i]->name, - clk_get_rate(clocks[i]), - clocks[i]->usecount); - } -} -#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ - -static int dss_get_clock(struct clk **clock, const char *clk_name) -{ - struct clk *clk; - - clk = clk_get(&core.pdev->dev, clk_name); - - if (IS_ERR(clk)) { - DSSERR("can't get clock %s", clk_name); - return PTR_ERR(clk); - } - - *clock = clk; - - DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); - - return 0; -} - -static int dss_get_clocks(void) -{ - int r; - - core.dss_ick = NULL; - core.dss1_fck = NULL; - core.dss2_fck = NULL; - core.dss_54m_fck = NULL; - core.dss_96m_fck = NULL; - - r = dss_get_clock(&core.dss_ick, "ick"); - if (r) - goto err; - - r = dss_get_clock(&core.dss1_fck, "dss1_fck"); - if (r) - goto err; - - r = dss_get_clock(&core.dss2_fck, "dss2_fck"); - if (r) - goto err; - - r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); - if (r) - goto err; - - r = dss_get_clock(&core.dss_96m_fck, "video_fck"); - if (r) - goto err; - - return 0; - -err: - if (core.dss_ick) - clk_put(core.dss_ick); - if (core.dss1_fck) - clk_put(core.dss1_fck); - if (core.dss2_fck) - clk_put(core.dss2_fck); - if (core.dss_54m_fck) - clk_put(core.dss_54m_fck); - if (core.dss_96m_fck) - clk_put(core.dss_96m_fck); - - return r; -} - -static void dss_put_clocks(void) -{ - if (core.dss_96m_fck) - clk_put(core.dss_96m_fck); - clk_put(core.dss_54m_fck); - clk_put(core.dss1_fck); - clk_put(core.dss2_fck); - clk_put(core.dss_ick); -} - -unsigned long dss_clk_get_rate(enum dss_clock clk) -{ - switch (clk) { - case DSS_CLK_ICK: - return clk_get_rate(core.dss_ick); - case DSS_CLK_FCK1: - return clk_get_rate(core.dss1_fck); - case DSS_CLK_FCK2: - return clk_get_rate(core.dss2_fck); - case DSS_CLK_54M: - return clk_get_rate(core.dss_54m_fck); - case DSS_CLK_96M: - return clk_get_rate(core.dss_96m_fck); - } - - BUG(); - return 0; -} - -static unsigned count_clk_bits(enum dss_clock clks) -{ - unsigned num_clks = 0; - - if (clks & DSS_CLK_ICK) - ++num_clks; - if (clks & DSS_CLK_FCK1) - ++num_clks; - if (clks & DSS_CLK_FCK2) - ++num_clks; - if (clks & DSS_CLK_54M) - ++num_clks; - if (clks & DSS_CLK_96M) - ++num_clks; - - return num_clks; -} - -static void dss_clk_enable_no_ctx(enum dss_clock clks) -{ - unsigned num_clks = count_clk_bits(clks); - - if (clks & DSS_CLK_ICK) - clk_enable(core.dss_ick); - if (clks & DSS_CLK_FCK1) - clk_enable(core.dss1_fck); - if (clks & DSS_CLK_FCK2) - clk_enable(core.dss2_fck); - if (clks & DSS_CLK_54M) - clk_enable(core.dss_54m_fck); - if (clks & DSS_CLK_96M) - clk_enable(core.dss_96m_fck); - - core.num_clks_enabled += num_clks; -} - -void dss_clk_enable(enum dss_clock clks) -{ - bool check_ctx = core.num_clks_enabled == 0; - - dss_clk_enable_no_ctx(clks); - - if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) - restore_all_ctx(); -} - -static void dss_clk_disable_no_ctx(enum dss_clock clks) -{ - unsigned num_clks = count_clk_bits(clks); - - if (clks & DSS_CLK_ICK) - clk_disable(core.dss_ick); - if (clks & DSS_CLK_FCK1) - clk_disable(core.dss1_fck); - if (clks & DSS_CLK_FCK2) - clk_disable(core.dss2_fck); - if (clks & DSS_CLK_54M) - clk_disable(core.dss_54m_fck); - if (clks & DSS_CLK_96M) - clk_disable(core.dss_96m_fck); - - core.num_clks_enabled -= num_clks; -} - -void dss_clk_disable(enum dss_clock clks) -{ - if (cpu_is_omap34xx()) { - unsigned num_clks = count_clk_bits(clks); - - BUG_ON(core.num_clks_enabled < num_clks); - - if (core.num_clks_enabled == num_clks) - save_all_ctx(); - } - - dss_clk_disable_no_ctx(clks); -} - -static void dss_clk_enable_all_no_ctx(void) -{ - enum dss_clock clks; - - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; - if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; - dss_clk_enable_no_ctx(clks); -} - -static void dss_clk_disable_all_no_ctx(void) -{ - enum dss_clock clks; - - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; - if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; - dss_clk_disable_no_ctx(clks); -} - -static void dss_clk_disable_all(void) -{ - enum dss_clock clks; - - clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; - if (cpu_is_omap34xx()) - clks |= DSS_CLK_96M; - dss_clk_disable(clks); -} - /* REGULATORS */ struct regulator *dss_get_vdds_dsi(void) @@ -390,32 +84,7 @@ struct regulator *dss_get_vdds_sdi(void) return reg; } -struct regulator *dss_get_vdda_dac(void) -{ - struct regulator *reg; - - if (core.vdda_dac_reg != NULL) - return core.vdda_dac_reg; - - reg = regulator_get(&core.pdev->dev, "vdda_dac"); - if (!IS_ERR(reg)) - core.vdda_dac_reg = reg; - - return reg; -} - -/* DEBUGFS */ #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) -static void dss_debug_dump_clocks(struct seq_file *s) -{ - core_dump_clocks(s); - dss_dump_clocks(s); - dispc_dump_clocks(s); -#ifdef CONFIG_OMAP2_DSS_DSI - dsi_dump_clocks(s); -#endif -} - static int dss_debug_show(struct seq_file *s, void *unused) { void (*func)(struct seq_file *) = s->private; @@ -508,30 +177,18 @@ static int omap_dss_probe(struct platform_device *pdev) dss_init_overlay_managers(pdev); dss_init_overlays(pdev); - r = dss_get_clocks(); - if (r) - goto err_clocks; - - dss_clk_enable_all_no_ctx(); - - core.ctx_id = dss_get_ctx_id(); - DSSDBG("initial ctx id %u\n", core.ctx_id); - -#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT - /* DISPC_CONTROL */ - if (omap_readl(0x48050440) & 1) /* LCD enabled? */ - skip_init = 1; -#endif - - r = dss_init(skip_init); + r = dss_init_platform_driver(); if (r) { - DSSERR("Failed to initialize DSS\n"); + DSSERR("Failed to initialize DSS platform driver\n"); goto err_dss; } - r = rfbi_init(); + /* keep clocks enabled to prevent context saves/restores during init */ + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + + r = rfbi_init_platform_driver(); if (r) { - DSSERR("Failed to initialize rfbi\n"); + DSSERR("Failed to initialize rfbi platform driver\n"); goto err_rfbi; } @@ -541,18 +198,23 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_dpi; } - r = dispc_init(); + r = dispc_init_platform_driver(); if (r) { - DSSERR("Failed to initialize dispc\n"); + DSSERR("Failed to initialize dispc platform driver\n"); goto err_dispc; } - r = venc_init(pdev); + r = venc_init_platform_driver(); if (r) { - DSSERR("Failed to initialize venc\n"); + DSSERR("Failed to initialize venc platform driver\n"); goto err_venc; } +#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT + /* DISPC_CONTROL */ + if (omap_readl(0x48050440) & 1) /* LCD enabled? */ + skip_init = 1; +#endif if (cpu_is_omap34xx()) { r = sdi_init(skip_init); if (r) { @@ -560,9 +222,9 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_sdi; } - r = dsi_init(pdev); + r = dsi_init_platform_driver(); if (r) { - DSSERR("Failed to initialize DSI\n"); + DSSERR("Failed to initialize DSI platform driver\n"); goto err_dsi; } } @@ -589,7 +251,7 @@ static int omap_dss_probe(struct platform_device *pdev) pdata->default_device = dssdev; } - dss_clk_disable_all(); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; @@ -597,24 +259,21 @@ err_register: dss_uninitialize_debugfs(); err_debugfs: if (cpu_is_omap34xx()) - dsi_exit(); + dsi_uninit_platform_driver(); err_dsi: if (cpu_is_omap34xx()) sdi_exit(); err_sdi: - venc_exit(); + venc_uninit_platform_driver(); err_venc: - dispc_exit(); + dispc_uninit_platform_driver(); err_dispc: dpi_exit(); err_dpi: - rfbi_exit(); + rfbi_uninit_platform_driver(); err_rfbi: - dss_exit(); + dss_uninit_platform_driver(); err_dss: - dss_clk_disable_all_no_ctx(); - dss_put_clocks(); -err_clocks: return r; } @@ -623,61 +282,19 @@ static int omap_dss_remove(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; int i; - int c; dss_uninitialize_debugfs(); - venc_exit(); - dispc_exit(); + venc_uninit_platform_driver(); + dispc_uninit_platform_driver(); dpi_exit(); - rfbi_exit(); + rfbi_uninit_platform_driver(); if (cpu_is_omap34xx()) { - dsi_exit(); + dsi_uninit_platform_driver(); sdi_exit(); } - dss_exit(); - - /* these should be removed at some point */ - c = core.dss_ick->usecount; - if (c > 0) { - DSSERR("warning: dss_ick usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss_ick); - } - - c = core.dss1_fck->usecount; - if (c > 0) { - DSSERR("warning: dss1_fck usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss1_fck); - } - - c = core.dss2_fck->usecount; - if (c > 0) { - DSSERR("warning: dss2_fck usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss2_fck); - } - - c = core.dss_54m_fck->usecount; - if (c > 0) { - DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); - while (c-- > 0) - clk_disable(core.dss_54m_fck); - } - - if (core.dss_96m_fck) { - c = core.dss_96m_fck->usecount; - if (c > 0) { - DSSERR("warning: dss_96m_fck usecount %d, disabling\n", - c); - while (c-- > 0) - clk_disable(core.dss_96m_fck); - } - } - - dss_put_clocks(); + dss_uninit_platform_driver(); dss_uninit_overlays(pdev); dss_uninit_overlay_managers(pdev); @@ -715,7 +332,7 @@ static struct platform_driver omap_dss_driver = { .suspend = omap_dss_suspend, .resume = omap_dss_resume, .driver = { - .name = "omapdss", + .name = "omap_display", .owner = THIS_MODULE, }, }; @@ -965,11 +582,6 @@ static void __exit omap_dss_exit(void) core.vdds_sdi_reg = NULL; } - if (core.vdda_dac_reg != NULL) { - regulator_put(core.vdda_dac_reg); - core.vdda_dac_reg = NULL; - } - platform_driver_unregister(&omap_dss_driver); omap_dss_bus_unregister(); diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9f8c69f16e6..cda1d2e9ac4 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -42,8 +42,6 @@ #include "dss_features.h" /* DISPC */ -#define DISPC_BASE 0x48050400 - #define DISPC_SZ_REGS SZ_4K struct dispc_reg { u16 idx; }; @@ -74,7 +72,12 @@ struct dispc_reg { u16 idx; }; #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) -#define DISPC_DIVISOR(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) +/* + * Use DISPC_DIVISORo(ch) when DISPC_DIVISOR1 or DISPC_DIVISOR2 has to be + * configured. OMAP4 TRM uses DISPC_DIVISORo generically to refer DISPC_DIVISOR1 + * and DISPC_DIVISOR2 + */ +#define DISPC_DIVISORo(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) #define DISPC_SIZE_DIG DISPC_REG(0x0078) #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) @@ -129,6 +132,17 @@ struct dispc_reg { u16 idx; }; #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) +/* + * The OMAP4 DISPC_DIVISOR1 is backward compatible to OMAP3xxx DISPC_DIVISOR. + * However DISPC_DIVISOR is also provided in OMAP4, to control DISPC_CORE_CLK. + * This allows DISPC_CORE_CLK to be independent of logical clock dividers (lcd) + * of LCD1 (primary) and LCD2 (secondary) displays. + * + * To derive pixel clocks for Primary and Secondary LCD channels, configure the + * lcd and pcd in DISPC_DIVISOR1 and DISPC_DIVISOR2 respectively, using the + * DISPC_DIVISORo(ch). + */ +#define DISPC_DIVISOR DISPC_REG(0x0804) #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ DISPC_IRQ_OCP_ERR | \ @@ -178,6 +192,7 @@ struct dispc_irq_stats { }; static struct { + struct platform_device *pdev; void __iomem *base; u32 fifo_size[3]; @@ -230,7 +245,7 @@ void dispc_save_context(void) SR(TIMING_H(0)); SR(TIMING_V(0)); SR(POL_FREQ(0)); - SR(DIVISOR(0)); + SR(DIVISORo(0)); SR(GLOBAL_ALPHA); SR(SIZE_DIG); SR(SIZE_LCD(0)); @@ -242,7 +257,7 @@ void dispc_save_context(void) SR(TIMING_H(2)); SR(TIMING_V(2)); SR(POL_FREQ(2)); - SR(DIVISOR(2)); + SR(DIVISORo(2)); SR(CONFIG2); } @@ -373,6 +388,9 @@ void dispc_save_context(void) SR(VID_FIR_COEF_V(1, 7)); SR(VID_PRELOAD(1)); + + if (dss_has_feature(FEAT_CORE_CLK_DIV)) + SR(DIVISOR); } void dispc_restore_context(void) @@ -389,7 +407,7 @@ void dispc_restore_context(void) RR(TIMING_H(0)); RR(TIMING_V(0)); RR(POL_FREQ(0)); - RR(DIVISOR(0)); + RR(DIVISORo(0)); RR(GLOBAL_ALPHA); RR(SIZE_DIG); RR(SIZE_LCD(0)); @@ -400,7 +418,7 @@ void dispc_restore_context(void) RR(TIMING_H(2)); RR(TIMING_V(2)); RR(POL_FREQ(2)); - RR(DIVISOR(2)); + RR(DIVISORo(2)); RR(CONFIG2); } @@ -532,6 +550,9 @@ void dispc_restore_context(void) RR(VID_PRELOAD(1)); + if (dss_has_feature(FEAT_CORE_CLK_DIV)) + RR(DIVISOR); + /* enable last, because LCD & DIGIT enable are here */ RR(CONTROL); if (dss_has_feature(FEAT_MGR_LCD2)) @@ -552,9 +573,9 @@ void dispc_restore_context(void) static inline void enable_clocks(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } bool dispc_go_busy(enum omap_channel channel) @@ -2293,7 +2314,7 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, BUG_ON(pck_div < 2); enable_clocks(1); - dispc_write_reg(DISPC_DIVISOR(channel), + dispc_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); enable_clocks(0); } @@ -2302,7 +2323,7 @@ static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, int *pck_div) { u32 l; - l = dispc_read_reg(DISPC_DIVISOR(channel)); + l = dispc_read_reg(DISPC_DIVISORo(channel)); *lck_div = FLD_GET(l, 23, 16); *pck_div = FLD_GET(l, 7, 0); } @@ -2312,7 +2333,7 @@ unsigned long dispc_fclk_rate(void) unsigned long r = 0; if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) - r = dss_clk_get_rate(DSS_CLK_FCK1); + r = dss_clk_get_rate(DSS_CLK_FCK); else #ifdef CONFIG_OMAP2_DSS_DSI r = dsi_get_dsi1_pll_rate(); @@ -2328,7 +2349,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) unsigned long r; u32 l; - l = dispc_read_reg(DISPC_DIVISOR(channel)); + l = dispc_read_reg(DISPC_DIVISORo(channel)); lcd = FLD_GET(l, 23, 16); @@ -2343,7 +2364,7 @@ unsigned long dispc_pclk_rate(enum omap_channel channel) unsigned long r; u32 l; - l = dispc_read_reg(DISPC_DIVISOR(channel)); + l = dispc_read_reg(DISPC_DIVISORo(channel)); lcd = FLD_GET(l, 23, 16); pcd = FLD_GET(l, 7, 0); @@ -2440,7 +2461,7 @@ void dispc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DISPC_REVISION); DUMPREG(DISPC_SYSCONFIG); @@ -2459,7 +2480,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_TIMING_H(0)); DUMPREG(DISPC_TIMING_V(0)); DUMPREG(DISPC_POL_FREQ(0)); - DUMPREG(DISPC_DIVISOR(0)); + DUMPREG(DISPC_DIVISORo(0)); DUMPREG(DISPC_GLOBAL_ALPHA); DUMPREG(DISPC_SIZE_DIG); DUMPREG(DISPC_SIZE_LCD(0)); @@ -2471,7 +2492,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_TIMING_H(2)); DUMPREG(DISPC_TIMING_V(2)); DUMPREG(DISPC_POL_FREQ(2)); - DUMPREG(DISPC_DIVISOR(2)); + DUMPREG(DISPC_DIVISORo(2)); DUMPREG(DISPC_SIZE_LCD(2)); } @@ -2597,7 +2618,7 @@ void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_VID_PRELOAD(0)); DUMPREG(DISPC_VID_PRELOAD(1)); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -2713,8 +2734,8 @@ int dispc_get_clock_div(enum omap_channel channel, fck = dispc_fclk_rate(); - cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16); - cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0); + cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16); + cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0); cinfo->lck = fck / cinfo->lck_div; cinfo->pck = cinfo->lck / cinfo->pck_div; @@ -3253,6 +3274,15 @@ static void _omap_dispc_initial_config(void) l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ dispc_write_reg(DISPC_SYSCONFIG, l); + /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ + if (dss_has_feature(FEAT_CORE_CLK_DIV)) { + l = dispc_read_reg(DISPC_DIVISOR); + /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ + l = FLD_MOD(l, 1, 0, 0); + l = FLD_MOD(l, 1, 23, 16); + dispc_write_reg(DISPC_DIVISOR, l); + } + /* FUNCGATED */ if (dss_has_feature(FEAT_FUNCGATED)) REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); @@ -3269,47 +3299,6 @@ static void _omap_dispc_initial_config(void) dispc_read_plane_fifo_sizes(); } -int dispc_init(void) -{ - u32 rev; - - spin_lock_init(&dispc.irq_lock); - -#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS - spin_lock_init(&dispc.irq_stats_lock); - dispc.irq_stats.last_reset = jiffies; -#endif - - INIT_WORK(&dispc.error_work, dispc_error_worker); - - dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); - if (!dispc.base) { - DSSERR("can't ioremap DISPC\n"); - return -ENOMEM; - } - - enable_clocks(1); - - _omap_dispc_initial_config(); - - _omap_dispc_initialize_irq(); - - dispc_save_context(); - - rev = dispc_read_reg(DISPC_REVISION); - printk(KERN_INFO "OMAP DISPC rev %d.%d\n", - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - - enable_clocks(0); - - return 0; -} - -void dispc_exit(void) -{ - iounmap(dispc.base); -} - int dispc_enable_plane(enum omap_plane plane, bool enable) { DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); @@ -3359,3 +3348,73 @@ int dispc_setup_plane(enum omap_plane plane, return r; } + +/* DISPC HW IP initialisation */ +static int omap_dispchw_probe(struct platform_device *pdev) +{ + u32 rev; + struct resource *dispc_mem; + + dispc.pdev = pdev; + + spin_lock_init(&dispc.irq_lock); + +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_lock_init(&dispc.irq_stats_lock); + dispc.irq_stats.last_reset = jiffies; +#endif + + INIT_WORK(&dispc.error_work, dispc_error_worker); + + dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); + if (!dispc_mem) { + DSSERR("can't get IORESOURCE_MEM DISPC\n"); + return -EINVAL; + } + dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); + if (!dispc.base) { + DSSERR("can't ioremap DISPC\n"); + return -ENOMEM; + } + + enable_clocks(1); + + _omap_dispc_initial_config(); + + _omap_dispc_initialize_irq(); + + dispc_save_context(); + + rev = dispc_read_reg(DISPC_REVISION); + dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + enable_clocks(0); + + return 0; +} + +static int omap_dispchw_remove(struct platform_device *pdev) +{ + iounmap(dispc.base); + return 0; +} + +static struct platform_driver omap_dispchw_driver = { + .probe = omap_dispchw_probe, + .remove = omap_dispchw_remove, + .driver = { + .name = "omap_dispc", + .owner = THIS_MODULE, + }, +}; + +int dispc_init_platform_driver(void) +{ + return platform_driver_register(&omap_dispchw_driver); +} + +void dispc_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_dispchw_driver); +} diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 75fb0a51543..746f1b6dd89 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -107,7 +107,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) bool is_tft; int r = 0; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); @@ -137,7 +137,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) dispc_set_lcd_timings(dssdev->manager->id, t); err0: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); return r; } @@ -173,14 +173,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) goto err1; } - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); r = dpi_basic_init(dssdev); if (r) goto err2; #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL - dss_clk_enable(DSS_CLK_FCK2); + dss_clk_enable(DSS_CLK_SYSCK); r = dsi_pll_init(dssdev, 0, 1); if (r) goto err3; @@ -199,10 +199,10 @@ err4: #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dsi_pll_uninit(); err3: - dss_clk_disable(DSS_CLK_FCK2); + dss_clk_disable(DSS_CLK_SYSCK); #endif err2: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); err1: @@ -219,10 +219,10 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); dsi_pll_uninit(); - dss_clk_disable(DSS_CLK_FCK2); + dss_clk_disable(DSS_CLK_SYSCK); #endif - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) regulator_disable(dpi.vdds_dsi_reg); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index ddf3a056082..1802057cbed 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -42,8 +42,6 @@ /*#define VERBOSE_IRQ*/ #define DSI_CATCH_MISSING_TE -#define DSI_BASE 0x4804FC00 - struct dsi_reg { u16 idx; }; #define DSI_REG(idx) ((const struct dsi_reg) { idx }) @@ -222,6 +220,7 @@ struct dsi_irq_stats { static struct { + struct platform_device *pdev; void __iomem *base; struct dsi_clock_info current_cinfo; @@ -292,6 +291,20 @@ static inline u32 dsi_read_reg(const struct dsi_reg idx) return __raw_readl(dsi.base + idx.idx); } +static struct regulator *dsi_get_vdds_dsi(void) +{ + struct regulator *reg; + + if (dsi.vdds_dsi_reg != NULL) + return dsi.vdds_dsi_reg; + + reg = regulator_get(&dsi.pdev->dev, "vdds_dsi"); + if (!IS_ERR(reg)) + dsi.vdds_dsi_reg = reg; + + return reg; +} + void dsi_save_context(void) { @@ -641,18 +654,18 @@ static void dsi_vc_disable_bta_irq(int channel) static inline void enable_clocks(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } /* source clock for DSI PLL. this could also be PCLKFREE */ static inline void dsi_enable_pll_clock(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_FCK2); + dss_clk_enable(DSS_CLK_SYSCK); else - dss_clk_disable(DSS_CLK_FCK2); + dss_clk_disable(DSS_CLK_SYSCK); if (enable && dsi.pll_locked) { if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) @@ -728,7 +741,7 @@ static unsigned long dsi_fclk_rate(void) if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ - r = dss_clk_get_rate(DSS_CLK_FCK1); + r = dss_clk_get_rate(DSS_CLK_FCK); } else { /* DSI FCLK source is DSI2_PLL_FCLK */ r = dsi_get_dsi2_pll_rate(); @@ -808,7 +821,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, return -EINVAL; if (cinfo->use_dss2_fck) { - cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); + cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); /* XXX it is unclear if highfreq should be used * with DSS2_FCK source also */ cinfo->highfreq = 0; @@ -854,7 +867,7 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, int match = 0; unsigned long dss_clk_fck2; - dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); + dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_SYSCK); if (req_pck == dsi.cache_req_pck && dsi.cache_cinfo.clkin == dss_clk_fck2) { @@ -1306,7 +1319,7 @@ void dsi_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DSI_REVISION); DUMPREG(DSI_SYSCONFIG); @@ -1378,7 +1391,7 @@ void dsi_dump_regs(struct seq_file *s) DUMPREG(DSI_PLL_CONFIGURATION1); DUMPREG(DSI_PLL_CONFIGURATION2); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -3238,10 +3251,11 @@ void dsi_wait_dsi2_pll_active(void) DSSERR("DSI2 PLL clock not active\n"); } -int dsi_init(struct platform_device *pdev) +static int dsi_init(struct platform_device *pdev) { u32 rev; int r; + struct resource *dsi_mem; spin_lock_init(&dsi.errors_lock); dsi.errors = 0; @@ -3268,14 +3282,20 @@ int dsi_init(struct platform_device *pdev) dsi.te_timer.function = dsi_te_timeout; dsi.te_timer.data = 0; #endif - dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); + dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0); + if (!dsi_mem) { + DSSERR("can't get IORESOURCE_MEM DSI\n"); + r = -EINVAL; + goto err0; + } + dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem)); if (!dsi.base) { DSSERR("can't ioremap DSI\n"); r = -ENOMEM; goto err1; } - dsi.vdds_dsi_reg = dss_get_vdds_dsi(); + dsi.vdds_dsi_reg = dsi_get_vdds_dsi(); if (IS_ERR(dsi.vdds_dsi_reg)) { DSSERR("can't get VDDS_DSI regulator\n"); r = PTR_ERR(dsi.vdds_dsi_reg); @@ -3285,7 +3305,7 @@ int dsi_init(struct platform_device *pdev) enable_clocks(1); rev = dsi_read_reg(DSI_REVISION); - printk(KERN_INFO "OMAP DSI rev %d.%d\n", + dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); enable_clocks(0); @@ -3295,11 +3315,17 @@ err2: iounmap(dsi.base); err1: destroy_workqueue(dsi.workqueue); +err0: return r; } -void dsi_exit(void) +static void dsi_exit(void) { + if (dsi.vdds_dsi_reg != NULL) { + regulator_put(dsi.vdds_dsi_reg); + dsi.vdds_dsi_reg = NULL; + } + iounmap(dsi.base); destroy_workqueue(dsi.workqueue); @@ -3307,3 +3333,41 @@ void dsi_exit(void) DSSDBG("omap_dsi_exit\n"); } +/* DSI1 HW IP initialisation */ +static int omap_dsi1hw_probe(struct platform_device *pdev) +{ + int r; + dsi.pdev = pdev; + r = dsi_init(pdev); + if (r) { + DSSERR("Failed to initialize DSI\n"); + goto err_dsi; + } +err_dsi: + return r; +} + +static int omap_dsi1hw_remove(struct platform_device *pdev) +{ + dsi_exit(); + return 0; +} + +static struct platform_driver omap_dsi1hw_driver = { + .probe = omap_dsi1hw_probe, + .remove = omap_dsi1hw_remove, + .driver = { + .name = "omap_dsi1", + .owner = THIS_MODULE, + }, +}; + +int dsi_init_platform_driver(void) +{ + return platform_driver_register(&omap_dsi1hw_driver); +} + +void dsi_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_dsi1hw_driver); +} diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 77c3621c917..d76bc2678c5 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -31,9 +31,9 @@ #include <linux/clk.h> #include <plat/display.h> +#include <plat/clock.h> #include "dss.h" - -#define DSS_BASE 0x48050000 +#include "dss_features.h" #define DSS_SZ_REGS SZ_512 @@ -59,9 +59,19 @@ struct dss_reg { dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) static struct { + struct platform_device *pdev; void __iomem *base; - - struct clk *dpll4_m4_ck; + int ctx_id; + int irq; + + /* Points to DPLL4_M4 in OMAP3xxx, and DPLL_PER_M5 in OMAP44xx */ + struct clk *dpll_per_mx_ck; + struct clk *dss_ick; + struct clk *dss_fck; + struct clk *dss_sys_clk; + struct clk *dss_tv_fck; + struct clk *dss_video_fck; + unsigned num_clks_enabled; unsigned long cache_req_pck; unsigned long cache_prate; @@ -74,6 +84,11 @@ static struct { u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; +static void dss_clk_enable_all_no_ctx(void); +static void dss_clk_disable_all_no_ctx(void); +static void dss_clk_enable_no_ctx(enum dss_clock clks); +static void dss_clk_disable_no_ctx(enum dss_clock clks); + static int _omap_dss_wait_reset(void); static inline void dss_write_reg(const struct dss_reg idx, u32 val) @@ -211,37 +226,37 @@ void dss_sdi_disable(void) void dss_dump_clocks(struct seq_file *s) { - unsigned long dpll4_ck_rate; - unsigned long dpll4_m4_ck_rate; + unsigned long dpll_per_ck_rate; + unsigned long dpll_per_mx_ck_rate; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); - dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); + dpll_per_ck_rate = clk_get_rate(clk_get_parent(dss.dpll_per_mx_ck)); + dpll_per_mx_ck_rate = clk_get_rate(dss.dpll_per_mx_ck); seq_printf(s, "- DSS -\n"); - seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); + seq_printf(s, "dpll_per_ck %lu\n", dpll_per_ck_rate); if (cpu_is_omap3630()) seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", - dpll4_ck_rate, - dpll4_ck_rate / dpll4_m4_ck_rate, - dss_clk_get_rate(DSS_CLK_FCK1)); + dpll_per_ck_rate, + dpll_per_ck_rate / dpll_per_mx_ck_rate, + dss_clk_get_rate(DSS_CLK_FCK)); else seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", - dpll4_ck_rate, - dpll4_ck_rate / dpll4_m4_ck_rate, - dss_clk_get_rate(DSS_CLK_FCK1)); + dpll_per_ck_rate, + dpll_per_ck_rate / dpll_per_mx_ck_rate, + dss_clk_get_rate(DSS_CLK_FCK)); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } void dss_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(DSS_REVISION); DUMPREG(DSS_SYSCONFIG); @@ -252,7 +267,7 @@ void dss_dump_regs(struct seq_file *s) DUMPREG(DSS_PLL_CONTROL); DUMPREG(DSS_SDI_STATUS); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } @@ -305,11 +320,12 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo) { unsigned long prate; - if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || - cinfo->fck_div == 0) + if (cinfo->fck_div > + (dss_has_feature(FEAT_DPLL_FCK_32_DIV) ? 32 : 16) || + cinfo->fck_div == 0) return -EINVAL; - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + prate = clk_get_rate(clk_get_parent(dss.dpll_per_mx_ck)); cinfo->fck = prate / cinfo->fck_div; @@ -321,11 +337,11 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) unsigned long prate; int r; - if (cpu_is_omap34xx()) { - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - DSSDBG("dpll4_m4 = %ld\n", prate); + if (dss_has_feature(FEAT_VAR_DPLL_FCK)) { + prate = clk_get_rate(clk_get_parent(dss.dpll_per_mx_ck)); + DSSDBG("dpll_per_mx parent rate = %ld\n", prate); - r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); + r = clk_set_rate(dss.dpll_per_mx_ck, prate / cinfo->fck_div); if (r) return r; } @@ -337,12 +353,12 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) int dss_get_clock_div(struct dss_clock_info *cinfo) { - cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); + cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); - if (cpu_is_omap34xx()) { + if (dss_has_feature(FEAT_VAR_DPLL_FCK)) { unsigned long prate; - prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - if (cpu_is_omap3630()) + prate = clk_get_rate(clk_get_parent(dss.dpll_per_mx_ck)); + if (dss_has_feature(FEAT_DPLL_FCK_32_DIV)) cinfo->fck_div = prate / (cinfo->fck); else cinfo->fck_div = prate / (cinfo->fck / 2); @@ -353,10 +369,10 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) return 0; } -unsigned long dss_get_dpll4_rate(void) +unsigned long dss_get_dpll_per_rate(void) { - if (cpu_is_omap34xx()) - return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); + if (dss_has_feature(FEAT_VAR_DPLL_FCK)) + return clk_get_rate(clk_get_parent(dss.dpll_per_mx_ck)); else return 0; } @@ -376,12 +392,13 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, int match = 0; int min_fck_per_pck; - prate = dss_get_dpll4_rate(); + prate = dss_get_dpll_per_rate(); - fck = dss_clk_get_rate(DSS_CLK_FCK1); + fck = dss_clk_get_rate(DSS_CLK_FCK); if (req_pck == dss.cache_req_pck && - ((cpu_is_omap34xx() && prate == dss.cache_prate) || - dss.cache_dss_cinfo.fck == fck)) { + ((dss_has_feature(FEAT_VAR_DPLL_FCK) && + prate == dss.cache_prate) || + dss.cache_dss_cinfo.fck == fck)) { DSSDBG("dispc clock info found from cache.\n"); *dss_cinfo = dss.cache_dss_cinfo; *dispc_cinfo = dss.cache_dispc_cinfo; @@ -402,10 +419,10 @@ retry: memset(&best_dss, 0, sizeof(best_dss)); memset(&best_dispc, 0, sizeof(best_dispc)); - if (cpu_is_omap24xx()) { + if (!dss_has_feature(FEAT_VAR_DPLL_FCK)) { struct dispc_clock_info cur_dispc; /* XXX can we change the clock on omap2? */ - fck = dss_clk_get_rate(DSS_CLK_FCK1); + fck = dss_clk_get_rate(DSS_CLK_FCK); fck_div = 1; dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); @@ -417,12 +434,13 @@ retry: best_dispc = cur_dispc; goto found; - } else if (cpu_is_omap34xx()) { - for (fck_div = (cpu_is_omap3630() ? 32 : 16); - fck_div > 0; --fck_div) { + } else { + for (fck_div = + (dss_has_feature(FEAT_DPLL_FCK_32_DIV) ? 32 : 16); + fck_div > 0; --fck_div) { struct dispc_clock_info cur_dispc; - if (cpu_is_omap3630()) + if (dss_has_feature(FEAT_DPLL_FCK_32_DIV)) fck = prate / fck_div; else fck = prate / fck_div * 2; @@ -450,8 +468,6 @@ retry: goto found; } } - } else { - BUG(); } found: @@ -482,28 +498,22 @@ found: return 0; } - - -static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) -{ - dispc_irq_handler(); - - return IRQ_HANDLED; -} - -static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) +static irqreturn_t dss_irq_handler(int irq, void *arg) { - u32 irqstatus; + if (dss_has_feature(FEAT_COMMON_IRQ_DISPC_DSI)) { + u32 irqstatus; - irqstatus = dss_read_reg(DSS_IRQSTATUS); + irqstatus = dss_read_reg(DSS_IRQSTATUS); - if (irqstatus & (1<<0)) /* DISPC_IRQ */ - dispc_irq_handler(); + if (irqstatus & (1<<0)) /* DISPC_IRQ */ + dispc_irq_handler(); #ifdef CONFIG_OMAP2_DSS_DSI - if (irqstatus & (1<<1)) /* DSI_IRQ */ - dsi_irq_handler(); + if (irqstatus & (1<<1)) /* DSI_IRQ */ + dsi_irq_handler(); #endif - + } else { + dispc_irq_handler(); + } return IRQ_HANDLED; } @@ -549,12 +559,19 @@ void dss_set_dac_pwrdn_bgz(bool enable) REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ } -int dss_init(bool skip_init) +static int dss_init(bool skip_init) { int r; u32 rev; + struct resource *dss_mem; - dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); + dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); + if (!dss_mem) { + DSSERR("can't get IORESOURCE_MEM DSS\n"); + r = -EINVAL; + goto fail0; + } + dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); if (!dss.base) { DSSERR("can't ioremap DSS\n"); r = -ENOMEM; @@ -590,11 +607,14 @@ int dss_init(bool skip_init) REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ #endif - r = request_irq(INT_24XX_DSS_IRQ, - cpu_is_omap24xx() - ? dss_irq_handler_omap2 - : dss_irq_handler_omap3, - 0, "OMAP DSS", NULL); + dss.irq = platform_get_irq(dss.pdev, 0); + if (dss.irq < 0) { + DSSERR("omap2 dss: platform_get_irq failed\n"); + r = -ENODEV; + goto fail1; + } + + r = request_irq(dss.irq, dss_irq_handler, 0, "OMAP DSS", NULL); if (r < 0) { DSSERR("omap2 dss: request_irq failed\n"); @@ -602,10 +622,17 @@ int dss_init(bool skip_init) } if (cpu_is_omap34xx()) { - dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); - if (IS_ERR(dss.dpll4_m4_ck)) { + dss.dpll_per_mx_ck = clk_get(NULL, "dpll4_m4_ck"); + if (IS_ERR(dss.dpll_per_mx_ck)) { DSSERR("Failed to get dpll4_m4_ck\n"); - r = PTR_ERR(dss.dpll4_m4_ck); + r = PTR_ERR(dss.dpll_per_mx_ck); + goto fail2; + } + } else if (cpu_is_omap44xx()) { + dss.dpll_per_mx_ck = clk_get(NULL, "dpll_per_m5x2_ck"); + if (IS_ERR(dss.dpll_per_mx_ck)) { + DSSERR("Failed to get dpll_per_mx_ck\n"); + r = PTR_ERR(dss.dpll_per_mx_ck); goto fail2; } } @@ -622,20 +649,389 @@ int dss_init(bool skip_init) return 0; fail2: - free_irq(INT_24XX_DSS_IRQ, NULL); + free_irq(dss.irq, NULL); fail1: iounmap(dss.base); fail0: return r; } -void dss_exit(void) +static void dss_exit(void) { - if (cpu_is_omap34xx()) - clk_put(dss.dpll4_m4_ck); + if (dss_has_feature(FEAT_VAR_DPLL_FCK)) + clk_put(dss.dpll_per_mx_ck); - free_irq(INT_24XX_DSS_IRQ, NULL); + free_irq(dss.irq, NULL); iounmap(dss.base); } +/* CONTEXT */ +static int dss_get_ctx_id(void) +{ + struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; + int r; + + if (!pdata->board_data->get_last_off_on_transaction_id) + return 0; + r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); + if (r < 0) { + dev_err(&dss.pdev->dev, "getting transaction ID failed, " + "will force context restore\n"); + r = -1; + } + return r; +} + +int dss_need_ctx_restore(void) +{ + int id = dss_get_ctx_id(); + + if (id < 0 || id != dss.ctx_id) { + DSSDBG("ctx id %d -> id %d\n", + dss.ctx_id, id); + dss.ctx_id = id; + return 1; + } else { + return 0; + } +} + +static void save_all_ctx(void) +{ + DSSDBG("save context\n"); + + dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); + + dss_save_context(); + dispc_save_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_save_context(); +#endif + + dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); +} + +static void restore_all_ctx(void) +{ + DSSDBG("restore context\n"); + + dss_clk_enable_all_no_ctx(); + + dss_restore_context(); + dispc_restore_context(); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_restore_context(); +#endif + + dss_clk_disable_all_no_ctx(); +} + +static int dss_get_clock(struct clk **clock, const char *clk_name) +{ + struct clk *clk; + + clk = clk_get(&dss.pdev->dev, clk_name); + + if (IS_ERR(clk)) { + DSSERR("can't get clock %s", clk_name); + return PTR_ERR(clk); + } + + *clock = clk; + + DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); + + return 0; +} + +static int dss_get_clocks(void) +{ + int r; + + dss.dss_ick = NULL; + dss.dss_fck = NULL; + dss.dss_sys_clk = NULL; + dss.dss_tv_fck = NULL; + dss.dss_video_fck = NULL; + + r = dss_get_clock(&dss.dss_ick, "ick"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss_fck, "fck"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); + if (r) + goto err; + + r = dss_get_clock(&dss.dss_video_fck, "video_clk"); + if (r) + goto err; + + return 0; + +err: + if (dss.dss_ick) + clk_put(dss.dss_ick); + if (dss.dss_fck) + clk_put(dss.dss_fck); + if (dss.dss_sys_clk) + clk_put(dss.dss_sys_clk); + if (dss.dss_tv_fck) + clk_put(dss.dss_tv_fck); + if (dss.dss_video_fck) + clk_put(dss.dss_video_fck); + + return r; +} + +static void dss_put_clocks(void) +{ + if (dss.dss_video_fck) + clk_put(dss.dss_video_fck); + clk_put(dss.dss_tv_fck); + clk_put(dss.dss_fck); + clk_put(dss.dss_sys_clk); + clk_put(dss.dss_ick); +} + +unsigned long dss_clk_get_rate(enum dss_clock clk) +{ + switch (clk) { + case DSS_CLK_ICK: + return clk_get_rate(dss.dss_ick); + case DSS_CLK_FCK: + return clk_get_rate(dss.dss_fck); + case DSS_CLK_SYSCK: + return clk_get_rate(dss.dss_sys_clk); + case DSS_CLK_TVFCK: + return clk_get_rate(dss.dss_tv_fck); + case DSS_CLK_VIDFCK: + return clk_get_rate(dss.dss_video_fck); + } + + BUG(); + return 0; +} + +static unsigned count_clk_bits(enum dss_clock clks) +{ + unsigned num_clks = 0; + + if (clks & DSS_CLK_ICK) + ++num_clks; + if (clks & DSS_CLK_FCK) + ++num_clks; + if (clks & DSS_CLK_SYSCK) + ++num_clks; + if (clks & DSS_CLK_TVFCK) + ++num_clks; + if (clks & DSS_CLK_VIDFCK) + ++num_clks; + + return num_clks; +} + +static void dss_clk_enable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_enable(dss.dss_ick); + if (clks & DSS_CLK_FCK) + clk_enable(dss.dss_fck); + if (clks & DSS_CLK_SYSCK) + clk_enable(dss.dss_sys_clk); + if (clks & DSS_CLK_TVFCK) + clk_enable(dss.dss_tv_fck); + if (clks & DSS_CLK_VIDFCK) + clk_enable(dss.dss_video_fck); + + dss.num_clks_enabled += num_clks; +} + +void dss_clk_enable(enum dss_clock clks) +{ + bool check_ctx = dss.num_clks_enabled == 0; + + dss_clk_enable_no_ctx(clks); + + if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) + restore_all_ctx(); +} + +static void dss_clk_disable_no_ctx(enum dss_clock clks) +{ + unsigned num_clks = count_clk_bits(clks); + + if (clks & DSS_CLK_ICK) + clk_disable(dss.dss_ick); + if (clks & DSS_CLK_FCK) + clk_disable(dss.dss_fck); + if (clks & DSS_CLK_SYSCK) + clk_disable(dss.dss_sys_clk); + if (clks & DSS_CLK_TVFCK) + clk_disable(dss.dss_tv_fck); + if (clks & DSS_CLK_VIDFCK) + clk_disable(dss.dss_video_fck); + + dss.num_clks_enabled -= num_clks; +} + +void dss_clk_disable(enum dss_clock clks) +{ + if (cpu_is_omap34xx()) { + unsigned num_clks = count_clk_bits(clks); + + BUG_ON(dss.num_clks_enabled < num_clks); + + if (dss.num_clks_enabled == num_clks) + save_all_ctx(); + } + + dss_clk_disable_no_ctx(clks); +} + +static void dss_clk_enable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_VIDFCK; + dss_clk_enable_no_ctx(clks); +} + +static void dss_clk_disable_all_no_ctx(void) +{ + enum dss_clock clks; + + clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; + if (cpu_is_omap34xx()) + clks |= DSS_CLK_VIDFCK; + dss_clk_disable_no_ctx(clks); +} + +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +/* CLOCKS */ +static void core_dump_clocks(struct seq_file *s) +{ + int i; + struct clk *clocks[5] = { + dss.dss_ick, + dss.dss_fck, + dss.dss_sys_clk, + dss.dss_tv_fck, + dss.dss_video_fck + }; + + seq_printf(s, "- CORE -\n"); + + seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); + + for (i = 0; i < 5; i++) { + if (!clocks[i]) + continue; + seq_printf(s, "%-15s\t%lu\t%d\n", + clocks[i]->name, + clk_get_rate(clocks[i]), + clocks[i]->usecount); + } +} +#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ + +/* DEBUGFS */ +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +void dss_debug_dump_clocks(struct seq_file *s) +{ + core_dump_clocks(s); + dss_dump_clocks(s); + dispc_dump_clocks(s); +#ifdef CONFIG_OMAP2_DSS_DSI + dsi_dump_clocks(s); +#endif +} +#endif + + +/* DSS HW IP initialisation */ +static int omap_dsshw_probe(struct platform_device *pdev) +{ + int r; + int skip_init = 0; + + dss.pdev = pdev; + + r = dss_get_clocks(); + if (r) + goto err_clocks; + + dss_clk_enable_all_no_ctx(); + + dss.ctx_id = dss_get_ctx_id(); + DSSDBG("initial ctx id %u\n", dss.ctx_id); + +#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT + /* DISPC_CONTROL */ + if (omap_readl(0x48050440) & 1) /* LCD enabled? */ + skip_init = 1; +#endif + + r = dss_init(skip_init); + if (r) { + DSSERR("Failed to initialize DSS\n"); + goto err_dss; + } + + dss_clk_disable_all_no_ctx(); + return 0; + +err_dss: + dss_clk_disable_all_no_ctx(); + dss_put_clocks(); +err_clocks: + return r; +} + +static int omap_dsshw_remove(struct platform_device *pdev) +{ + + dss_exit(); + + /* + * As part of hwmod changes, DSS is not the only controller of dss + * clocks; hwmod framework itself will also enable clocks during hwmod + * init for dss, and autoidle is set in h/w for DSS. Hence, there's no + * need to disable clocks if their usecounts > 1. + */ + WARN_ON(dss.num_clks_enabled > 0); + + dss_put_clocks(); + return 0; +} + +static struct platform_driver omap_dsshw_driver = { + .probe = omap_dsshw_probe, + .remove = omap_dsshw_remove, + .driver = { + .name = "omap_dss", + .owner = THIS_MODULE, + }, +}; + +int dss_init_platform_driver(void) +{ + return platform_driver_register(&omap_dsshw_driver); +} + +void dss_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_dsshw_driver); +} diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index b394951120a..4b02e079f20 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -112,11 +112,11 @@ enum omap_parallel_interface_mode { }; enum dss_clock { - DSS_CLK_ICK = 1 << 0, - DSS_CLK_FCK1 = 1 << 1, - DSS_CLK_FCK2 = 1 << 2, - DSS_CLK_54M = 1 << 3, - DSS_CLK_96M = 1 << 4, + DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */ + DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */ + DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */ + DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */ + DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ }; enum dss_clk_source { @@ -169,15 +169,9 @@ struct seq_file; struct platform_device; /* core */ -void dss_clk_enable(enum dss_clock clks); -void dss_clk_disable(enum dss_clock clks); -unsigned long dss_clk_get_rate(enum dss_clock clk); -int dss_need_ctx_restore(void); -void dss_dump_clocks(struct seq_file *s); struct bus_type *dss_get_bus(void); struct regulator *dss_get_vdds_dsi(void); struct regulator *dss_get_vdds_sdi(void); -struct regulator *dss_get_vdda_dac(void); /* display */ int dss_suspend_all_devices(void); @@ -214,13 +208,21 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); /* DSS */ -int dss_init(bool skip_init); -void dss_exit(void); +int dss_init_platform_driver(void); +void dss_uninit_platform_driver(void); void dss_save_context(void); void dss_restore_context(void); +void dss_clk_enable(enum dss_clock clks); +void dss_clk_disable(enum dss_clock clks); +unsigned long dss_clk_get_rate(enum dss_clock clk); +int dss_need_ctx_restore(void); +void dss_dump_clocks(struct seq_file *s); void dss_dump_regs(struct seq_file *s); +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) +void dss_debug_dump_clocks(struct seq_file *s); +#endif void dss_sdi_init(u8 datapairs); int dss_sdi_enable(void); @@ -259,8 +261,8 @@ static inline void sdi_exit(void) /* DSI */ #ifdef CONFIG_OMAP2_DSS_DSI -int dsi_init(struct platform_device *pdev); -void dsi_exit(void); +int dsi_init_platform_driver(void); +void dsi_uninit_platform_driver(void); void dsi_dump_clocks(struct seq_file *s); void dsi_dump_irqs(struct seq_file *s); @@ -285,11 +287,11 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, void dsi_wait_dsi1_pll_active(void); void dsi_wait_dsi2_pll_active(void); #else -static inline int dsi_init(struct platform_device *pdev) +static inline int dsi_init_platform_driver(void) { return 0; } -static inline void dsi_exit(void) +static inline void dsi_uninit_platform_driver(void) { } static inline void dsi_wait_dsi1_pll_active(void) @@ -316,8 +318,8 @@ static inline void dpi_exit(void) #endif /* DISPC */ -int dispc_init(void); -void dispc_exit(void); +int dispc_init_platform_driver(void); +void dispc_uninit_platform_driver(void); void dispc_dump_clocks(struct seq_file *s); void dispc_dump_irqs(struct seq_file *s); void dispc_dump_regs(struct seq_file *s); @@ -409,24 +411,24 @@ int dispc_get_clock_div(enum omap_channel channel, /* VENC */ #ifdef CONFIG_OMAP2_DSS_VENC -int venc_init(struct platform_device *pdev); -void venc_exit(void); +int venc_init_platform_driver(void); +void venc_uninit_platform_driver(void); void venc_dump_regs(struct seq_file *s); int venc_init_display(struct omap_dss_device *display); #else -static inline int venc_init(struct platform_device *pdev) +static inline int venc_init_platform_driver(void) { return 0; } -static inline void venc_exit(void) +static inline void venc_uninit_platform_driver(void) { } #endif /* RFBI */ #ifdef CONFIG_OMAP2_DSS_RFBI -int rfbi_init(void); -void rfbi_exit(void); +int rfbi_init_platform_driver(void); +void rfbi_uninit_platform_driver(void); void rfbi_dump_regs(struct seq_file *s); int rfbi_configure(int rfbi_module, int bpp, int lines); @@ -437,11 +439,11 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); unsigned long rfbi_get_max_tx_rate(void); int rfbi_init_display(struct omap_dss_device *display); #else -static inline int rfbi_init(void) +static inline int rfbi_init_platform_driver(void) { return 0; } -static inline void rfbi_exit(void) +static inline void rfbi_uninit_platform_driver(void) { } #endif diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index cf3ef696e14..39864f6bb46 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -157,7 +157,8 @@ static struct omap_dss_features omap3430_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | - FEAT_FUNCGATED, + FEAT_FUNCGATED | FEAT_COMMON_IRQ_DISPC_DSI | + FEAT_VAR_DPLL_FCK, .num_mgrs = 2, .num_ovls = 3, @@ -172,7 +173,9 @@ static struct omap_dss_features omap3630_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | - FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED, + FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | + FEAT_COMMON_IRQ_DISPC_DSI | FEAT_VAR_DPLL_FCK | + FEAT_DPLL_FCK_32_DIV, .num_mgrs = 2, .num_ovls = 3, @@ -187,7 +190,8 @@ static struct omap_dss_features omap4_dss_features = { .has_feature = FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | - FEAT_MGR_LCD2, + FEAT_MGR_LCD2 | FEAT_VAR_DPLL_FCK | + FEAT_DPLL_FCK_32_DIV | FEAT_CORE_CLK_DIV, .num_mgrs = 3, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b9c70be9258..ed5c880a276 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -25,14 +25,20 @@ /* DSS has feature id */ enum dss_feat_id { - FEAT_GLOBAL_ALPHA = 1 << 0, - FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, - FEAT_PRE_MULT_ALPHA = 1 << 2, - FEAT_LCDENABLEPOL = 1 << 3, - FEAT_LCDENABLESIGNAL = 1 << 4, - FEAT_PCKFREEENABLE = 1 << 5, - FEAT_FUNCGATED = 1 << 6, - FEAT_MGR_LCD2 = 1 << 7, + FEAT_GLOBAL_ALPHA = 1 << 0, + FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, + FEAT_PRE_MULT_ALPHA = 1 << 2, + FEAT_LCDENABLEPOL = 1 << 3, + FEAT_LCDENABLESIGNAL = 1 << 4, + FEAT_PCKFREEENABLE = 1 << 5, + FEAT_FUNCGATED = 1 << 6, + FEAT_MGR_LCD2 = 1 << 7, + FEAT_COMMON_IRQ_DISPC_DSI = 1 << 8, + FEAT_VAR_DPLL_FCK = 1 << 9, /* Variable DPLL Func CLK */ + /* DPLL FCLK has max divider value 32 */ + FEAT_DPLL_FCK_32_DIV = 1 << 10, + /* Independent core clk divider */ + FEAT_CORE_CLK_DIV = 1 << 11, }; /* DSS register field id */ diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 172d4e69730..1f53bf20b6c 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -1394,7 +1394,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) } r = 0; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); if (!dss_cache.irq_enabled) { u32 mask; @@ -1407,7 +1407,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) dss_cache.irq_enabled = true; } configure_dispc(); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); spin_unlock_irqrestore(&dss_cache.lock, flags); diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 456efef03c2..996e9a4f677 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -490,7 +490,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, ovl->manager = mgr; - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); /* XXX: on manual update display, in auto update mode, a bug happens * here. When an overlay is first enabled on LCD, then it's disabled, * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT @@ -499,7 +499,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, * but I don't understand how or why. */ msleep(40); dispc_set_channel_out(ovl->id, mgr->id); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; } diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 10a2ffe0288..9e0f196a983 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -36,8 +36,6 @@ #include <plat/display.h> #include "dss.h" -#define RFBI_BASE 0x48050800 - struct rfbi_reg { u16 idx; }; #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) @@ -100,6 +98,7 @@ static int rfbi_convert_timings(struct rfbi_timings *t); static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); static struct { + struct platform_device *pdev; void __iomem *base; unsigned long l4_khz; @@ -142,9 +141,9 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx) static void rfbi_enable_clocks(bool enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); } void omap_rfbi_write_command(const void *buf, u32 len) @@ -497,7 +496,7 @@ unsigned long rfbi_get_max_tx_rate(void) }; l4_rate = rfbi.l4_khz / 1000; - dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; + dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000; for (i = 0; i < ARRAY_SIZE(ftab); i++) { /* Use a window instead of an exact match, to account @@ -922,7 +921,7 @@ void rfbi_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); DUMPREG(RFBI_REVISION); DUMPREG(RFBI_SYSCONFIG); @@ -953,54 +952,10 @@ void rfbi_dump_regs(struct seq_file *s) DUMPREG(RFBI_VSYNC_WIDTH); DUMPREG(RFBI_HSYNC_WIDTH); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); #undef DUMPREG } -int rfbi_init(void) -{ - u32 rev; - u32 l; - - spin_lock_init(&rfbi.cmd_lock); - - init_completion(&rfbi.cmd_done); - atomic_set(&rfbi.cmd_fifo_full, 0); - atomic_set(&rfbi.cmd_pending, 0); - - rfbi.base = ioremap(RFBI_BASE, SZ_256); - if (!rfbi.base) { - DSSERR("can't ioremap RFBI\n"); - return -ENOMEM; - } - - rfbi_enable_clocks(1); - - msleep(10); - - rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; - - /* Enable autoidle and smart-idle */ - l = rfbi_read_reg(RFBI_SYSCONFIG); - l |= (1 << 0) | (2 << 3); - rfbi_write_reg(RFBI_SYSCONFIG, l); - - rev = rfbi_read_reg(RFBI_REVISION); - printk(KERN_INFO "OMAP RFBI rev %d.%d\n", - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - - rfbi_enable_clocks(0); - - return 0; -} - -void rfbi_exit(void) -{ - DSSDBG("rfbi_exit\n"); - - iounmap(rfbi.base); -} - int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { int r; @@ -1056,3 +1011,74 @@ int rfbi_init_display(struct omap_dss_device *dssdev) dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; return 0; } + +/* RFBI HW IP initialisation */ +static int omap_rfbihw_probe(struct platform_device *pdev) +{ + u32 rev; + u32 l; + struct resource *rfbi_mem; + + rfbi.pdev = pdev; + + spin_lock_init(&rfbi.cmd_lock); + + init_completion(&rfbi.cmd_done); + atomic_set(&rfbi.cmd_fifo_full, 0); + atomic_set(&rfbi.cmd_pending, 0); + + rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); + if (!rfbi_mem) { + DSSERR("can't get IORESOURCE_MEM RFBI\n"); + return -EINVAL; + } + rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); + if (!rfbi.base) { + DSSERR("can't ioremap RFBI\n"); + return -ENOMEM; + } + + rfbi_enable_clocks(1); + + msleep(10); + + rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; + + /* Enable autoidle and smart-idle */ + l = rfbi_read_reg(RFBI_SYSCONFIG); + l |= (1 << 0) | (2 << 3); + rfbi_write_reg(RFBI_SYSCONFIG, l); + + rev = rfbi_read_reg(RFBI_REVISION); + dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", + FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + rfbi_enable_clocks(0); + + return 0; +} + +static int omap_rfbihw_remove(struct platform_device *pdev) +{ + iounmap(rfbi.base); + return 0; +} + +static struct platform_driver omap_rfbihw_driver = { + .probe = omap_rfbihw_probe, + .remove = omap_rfbihw_remove, + .driver = { + .name = "omap_rfbi", + .owner = THIS_MODULE, + }, +}; + +int rfbi_init_platform_driver(void) +{ + return platform_driver_register(&omap_rfbihw_driver); +} + +void rfbi_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_rfbihw_driver); +} diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index b64adf7dfc8..8272fc1f327 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -70,7 +70,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) /* In case of skip_init sdi_init has already enabled the clocks */ if (!sdi.skip_init) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); sdi_basic_init(dssdev); @@ -130,7 +130,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) return 0; err2: - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); regulator_disable(sdi.vdds_sdi_reg); err1: omap_dss_stop_device(dssdev); @@ -145,7 +145,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) dss_sdi_disable(); - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); regulator_disable(sdi.vdds_sdi_reg); @@ -175,7 +175,7 @@ int sdi_init(bool skip_init) * of them until sdi_display_enable is called. */ if (skip_init) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); return 0; } diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index eff35050e28..2adae129f4d 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -39,8 +39,6 @@ #include "dss.h" -#define VENC_BASE 0x48050C00 - /* Venc registers */ #define VENC_REV_ID 0x00 #define VENC_STATUS 0x04 @@ -289,6 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { EXPORT_SYMBOL(omap_dss_ntsc_timings); static struct { + struct platform_device *pdev; void __iomem *base; struct mutex venc_lock; u32 wss_data; @@ -306,6 +305,17 @@ static inline u32 venc_read_reg(int idx) return l; } +static struct regulator *venc_get_vdda_dac(void) +{ + struct regulator *reg; + + reg = regulator_get(&venc.pdev->dev, "vdda_dac"); + if (!IS_ERR(reg)) + venc.vdda_dac_reg = reg; + + return reg; +} + static void venc_write_config(const struct venc_config *config) { DSSDBG("write venc conf\n"); @@ -381,11 +391,11 @@ static void venc_reset(void) static void venc_enable_clocks(int enable) { if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | - DSS_CLK_96M); + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | + DSS_CLK_VIDFCK); else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | - DSS_CLK_96M); + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | + DSS_CLK_VIDFCK); } static const struct venc_config *venc_timings_to_config( @@ -641,46 +651,6 @@ static struct omap_dss_driver venc_driver = { }; /* driver end */ - - -int venc_init(struct platform_device *pdev) -{ - u8 rev_id; - - mutex_init(&venc.venc_lock); - - venc.wss_data = 0; - - venc.base = ioremap(VENC_BASE, SZ_1K); - if (!venc.base) { - DSSERR("can't ioremap VENC\n"); - return -ENOMEM; - } - - venc.vdda_dac_reg = dss_get_vdda_dac(); - if (IS_ERR(venc.vdda_dac_reg)) { - iounmap(venc.base); - DSSERR("can't get VDDA_DAC regulator\n"); - return PTR_ERR(venc.vdda_dac_reg); - } - - venc_enable_clocks(1); - - rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); - printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); - - venc_enable_clocks(0); - - return omap_dss_register_driver(&venc_driver); -} - -void venc_exit(void) -{ - omap_dss_unregister_driver(&venc_driver); - - iounmap(venc.base); -} - int venc_init_display(struct omap_dss_device *dssdev) { DSSDBG("init_display\n"); @@ -740,3 +710,74 @@ void venc_dump_regs(struct seq_file *s) #undef DUMPREG } + +/* VENC HW IP initialisation */ +static int omap_venchw_probe(struct platform_device *pdev) +{ + u8 rev_id; + struct resource *venc_mem; + + venc.pdev = pdev; + + mutex_init(&venc.venc_lock); + + venc.wss_data = 0; + + venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); + if (!venc_mem) { + DSSERR("can't get IORESOURCE_MEM VENC\n"); + return -EINVAL; + } + venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); + if (!venc.base) { + DSSERR("can't ioremap VENC\n"); + return -ENOMEM; + } + + venc.vdda_dac_reg = venc_get_vdda_dac(); + if (IS_ERR(venc.vdda_dac_reg)) { + iounmap(venc.base); + DSSERR("can't get VDDA_DAC regulator\n"); + return PTR_ERR(venc.vdda_dac_reg); + } + + venc_enable_clocks(1); + + rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); + dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); + + venc_enable_clocks(0); + + return omap_dss_register_driver(&venc_driver); +} + +static int omap_venchw_remove(struct platform_device *pdev) +{ + if (venc.vdda_dac_reg != NULL) { + regulator_put(venc.vdda_dac_reg); + venc.vdda_dac_reg = NULL; + } + omap_dss_unregister_driver(&venc_driver); + + iounmap(venc.base); + return 0; +} + +static struct platform_driver omap_venchw_driver = { + .probe = omap_venchw_probe, + .remove = omap_venchw_remove, + .driver = { + .name = "omap_venc", + .owner = THIS_MODULE, + }, +}; + +int venc_init_platform_driver(void) +{ + return platform_driver_register(&omap_venchw_driver); +} + +void venc_uninit_platform_driver(void) +{ + return platform_driver_unregister(&omap_venchw_driver); +} diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index 65149b22cf3..1da712e9e71 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig @@ -1,5 +1,5 @@ menuconfig FB_OMAP2 - tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" + tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" depends on FB && OMAP2_DSS select OMAP2_VRAM @@ -8,10 +8,10 @@ menuconfig FB_OMAP2 select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT help - Frame buffer driver for OMAP2/3 based boards. + Frame buffer driver for OMAP2+ based boards. config FB_OMAP2_DEBUG_SUPPORT - bool "Debug support for OMAP2/3 FB" + bool "Debug support for OMAP2+ FB" default y depends on FB_OMAP2 help diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index eca855a55c0..3de4ba0260a 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -646,7 +646,7 @@ static int __devexit cpwd_remove(struct platform_device *op) struct cpwd *p = dev_get_drvdata(&op->dev); int i; - for (i = 0; i < 4; i++) { + for (i = 0; i < WD_NUMDEVS; i++) { misc_deregister(&p->devs[i].misc); if (!p->enabled) { diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 24b966d5061..204a5603c4a 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -710,7 +710,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) return 0; } -static void __devexit hpwdt_exit_nmi_decoding(void) +static void hpwdt_exit_nmi_decoding(void) { unregister_die_notifier(&die_notifier); if (cru_rom_addr) @@ -726,7 +726,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) return 0; } -static void __devexit hpwdt_exit_nmi_decoding(void) +static void hpwdt_exit_nmi_decoding(void) { } #endif /* CONFIG_HPWDT_NMI_DECODING */ diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 0461858e07d..b61ab1c5429 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -508,7 +508,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr) sch311x_sio_outb(sio_config_port, 0x07, 0x0a); /* Check if Logical Device Register is currently active */ - if (sch311x_sio_inb(sio_config_port, 0x30) && 0x01 == 0) + if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0) printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n"); /* Get the base address of the runtime registers */ diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 9127eda2145..0a0efe713bc 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -278,7 +278,7 @@ static struct miscdevice sp805_wdt_miscdev = { }; static int __devinit -sp805_wdt_probe(struct amba_device *adev, struct amba_id *id) +sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index a6c12dec91a..df2a64dc967 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c @@ -109,7 +109,7 @@ static int w83697ug_select_wd_register(void) outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ outb_p(0x30, WDT_EFER); /* select CR30 */ c = inb_p(WDT_EFDR); - outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ + outb_p(c | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ return 0; } diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6f820fa23df..7f78cc78fdd 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -729,6 +729,15 @@ struct btrfs_space_info { u64 disk_total; /* total bytes on disk, takes mirrors into account */ + /* + * we bump reservation progress every time we decrement + * bytes_reserved. This way people waiting for reservations + * know something good has happened and they can check + * for progress. The number here isn't to be trusted, it + * just shows reclaim activity + */ + unsigned long reservation_progress; + int full; /* indicates that we cannot allocate any more chunks for this space */ int force_alloc; /* set if we need to force a chunk alloc for diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 588ff984987..7b3089b5c2d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3342,15 +3342,16 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, u64 max_reclaim; u64 reclaimed = 0; long time_left; - int pause = 1; int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; int loops = 0; + unsigned long progress; block_rsv = &root->fs_info->delalloc_block_rsv; space_info = block_rsv->space_info; smp_mb(); reserved = space_info->bytes_reserved; + progress = space_info->reservation_progress; if (reserved == 0) return 0; @@ -3365,31 +3366,36 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); spin_lock(&space_info->lock); - if (reserved > space_info->bytes_reserved) { - loops = 0; + if (reserved > space_info->bytes_reserved) reclaimed += reserved - space_info->bytes_reserved; - } else { - loops++; - } reserved = space_info->bytes_reserved; spin_unlock(&space_info->lock); + loops++; + if (reserved == 0 || reclaimed >= max_reclaim) break; if (trans && trans->transaction->blocked) return -EAGAIN; - __set_current_state(TASK_INTERRUPTIBLE); - time_left = schedule_timeout(pause); + time_left = schedule_timeout_interruptible(1); /* We were interrupted, exit */ if (time_left) break; - pause <<= 1; - if (pause > HZ / 10) - pause = HZ / 10; + /* we've kicked the IO a few times, if anything has been freed, + * exit. There is no sense in looping here for a long time + * when we really need to commit the transaction, or there are + * just too many writers without enough free space + */ + + if (loops > 3) { + smp_mb(); + if (progress != space_info->reservation_progress) + break; + } } return reclaimed >= to_reclaim; @@ -3612,6 +3618,7 @@ void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv, if (num_bytes) { spin_lock(&space_info->lock); space_info->bytes_reserved -= num_bytes; + space_info->reservation_progress++; spin_unlock(&space_info->lock); } } @@ -3844,6 +3851,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) if (block_rsv->reserved >= block_rsv->size) { num_bytes = block_rsv->reserved - block_rsv->size; sinfo->bytes_reserved -= num_bytes; + sinfo->reservation_progress++; block_rsv->reserved = block_rsv->size; block_rsv->full = 1; } @@ -4005,7 +4013,6 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) to_reserve = 0; } spin_unlock(&BTRFS_I(inode)->accounting_lock); - to_reserve += calc_csum_metadata_size(inode, num_bytes); ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); if (ret) @@ -4133,6 +4140,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, btrfs_set_block_group_used(&cache->item, old_val); cache->reserved -= num_bytes; cache->space_info->bytes_reserved -= num_bytes; + cache->space_info->reservation_progress++; cache->space_info->bytes_used += num_bytes; cache->space_info->disk_used += num_bytes * factor; spin_unlock(&cache->lock); @@ -4184,6 +4192,7 @@ static int pin_down_extent(struct btrfs_root *root, if (reserved) { cache->reserved -= num_bytes; cache->space_info->bytes_reserved -= num_bytes; + cache->space_info->reservation_progress++; } spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); @@ -4234,6 +4243,7 @@ static int update_reserved_bytes(struct btrfs_block_group_cache *cache, space_info->bytes_readonly += num_bytes; cache->reserved -= num_bytes; space_info->bytes_reserved -= num_bytes; + space_info->reservation_progress++; } spin_unlock(&cache->lock); spin_unlock(&space_info->lock); @@ -4712,6 +4722,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, if (ret) { spin_lock(&cache->space_info->lock); cache->space_info->bytes_reserved -= buf->len; + cache->space_info->reservation_progress++; spin_unlock(&cache->space_info->lock); } goto out; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index fd3f172e94e..714adc4ac4c 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3046,17 +3046,38 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, } while (!end) { - off = extent_map_end(em); - if (off >= max) - end = 1; + u64 offset_in_extent; + + /* break if the extent we found is outside the range */ + if (em->start >= max || extent_map_end(em) < off) + break; + + /* + * get_extent may return an extent that starts before our + * requested range. We have to make sure the ranges + * we return to fiemap always move forward and don't + * overlap, so adjust the offsets here + */ + em_start = max(em->start, off); - em_start = em->start; - em_len = em->len; + /* + * record the offset from the start of the extent + * for adjusting the disk offset below + */ + offset_in_extent = em_start - em->start; em_end = extent_map_end(em); + em_len = em_end - em_start; emflags = em->flags; disko = 0; flags = 0; + /* + * bump off for our next call to get_extent + */ + off = extent_map_end(em); + if (off >= max) + end = 1; + if (em->block_start == EXTENT_MAP_LAST_BYTE) { end = 1; flags |= FIEMAP_EXTENT_LAST; @@ -3067,7 +3088,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, flags |= (FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN); } else { - disko = em->block_start; + disko = em->block_start + offset_in_extent; } if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) flags |= FIEMAP_EXTENT_ENCODED; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 7084140d594..f447b783bb8 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -70,6 +70,19 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, /* Flush processor's dcache for this page */ flush_dcache_page(page); + + /* + * if we get a partial write, we can end up with + * partially up to date pages. These add + * a lot of complexity, so make sure they don't + * happen by forcing this copy to be retried. + * + * The rest of the btrfs_file_write code will fall + * back to page at a time copies after we return 0. + */ + if (!PageUptodate(page) && copied < count) + copied = 0; + iov_iter_advance(i, copied); write_bytes -= copied; total_copied += copied; @@ -763,6 +776,27 @@ out: } /* + * on error we return an unlocked page and the error value + * on success we return a locked page and 0 + */ +static int prepare_uptodate_page(struct page *page, u64 pos) +{ + int ret = 0; + + if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) { + ret = btrfs_readpage(NULL, page); + if (ret) + return ret; + lock_page(page); + if (!PageUptodate(page)) { + unlock_page(page); + return -EIO; + } + } + return 0; +} + +/* * this gets pages into the page cache and locks them down, it also properly * waits for data=ordered extents to finish before allowing the pages to be * modified. @@ -777,6 +811,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, unsigned long index = pos >> PAGE_CACHE_SHIFT; struct inode *inode = fdentry(file)->d_inode; int err = 0; + int faili = 0; u64 start_pos; u64 last_pos; @@ -794,15 +829,24 @@ again: for (i = 0; i < num_pages; i++) { pages[i] = grab_cache_page(inode->i_mapping, index + i); if (!pages[i]) { - int c; - for (c = i - 1; c >= 0; c--) { - unlock_page(pages[c]); - page_cache_release(pages[c]); - } - return -ENOMEM; + faili = i - 1; + err = -ENOMEM; + goto fail; + } + + if (i == 0) + err = prepare_uptodate_page(pages[i], pos); + if (i == num_pages - 1) + err = prepare_uptodate_page(pages[i], + pos + write_bytes); + if (err) { + page_cache_release(pages[i]); + faili = i - 1; + goto fail; } wait_on_page_writeback(pages[i]); } + err = 0; if (start_pos < inode->i_size) { struct btrfs_ordered_extent *ordered; lock_extent_bits(&BTRFS_I(inode)->io_tree, @@ -842,6 +886,14 @@ again: WARN_ON(!PageLocked(pages[i])); } return 0; +fail: + while (faili >= 0) { + unlock_page(pages[faili]); + page_cache_release(pages[faili]); + faili--; + } + return err; + } static ssize_t btrfs_file_aio_write(struct kiocb *iocb, @@ -851,7 +903,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, struct file *file = iocb->ki_filp; struct inode *inode = fdentry(file)->d_inode; struct btrfs_root *root = BTRFS_I(inode)->root; - struct page *pinned[2]; struct page **pages = NULL; struct iov_iter i; loff_t *ppos = &iocb->ki_pos; @@ -872,9 +923,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || (file->f_flags & O_DIRECT)); - pinned[0] = NULL; - pinned[1] = NULL; - start_pos = pos; vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); @@ -962,32 +1010,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, first_index = pos >> PAGE_CACHE_SHIFT; last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; - /* - * there are lots of better ways to do this, but this code - * makes sure the first and last page in the file range are - * up to date and ready for cow - */ - if ((pos & (PAGE_CACHE_SIZE - 1))) { - pinned[0] = grab_cache_page(inode->i_mapping, first_index); - if (!PageUptodate(pinned[0])) { - ret = btrfs_readpage(NULL, pinned[0]); - BUG_ON(ret); - wait_on_page_locked(pinned[0]); - } else { - unlock_page(pinned[0]); - } - } - if ((pos + iov_iter_count(&i)) & (PAGE_CACHE_SIZE - 1)) { - pinned[1] = grab_cache_page(inode->i_mapping, last_index); - if (!PageUptodate(pinned[1])) { - ret = btrfs_readpage(NULL, pinned[1]); - BUG_ON(ret); - wait_on_page_locked(pinned[1]); - } else { - unlock_page(pinned[1]); - } - } - while (iov_iter_count(&i) > 0) { size_t offset = pos & (PAGE_CACHE_SIZE - 1); size_t write_bytes = min(iov_iter_count(&i), @@ -1024,8 +1046,20 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, copied = btrfs_copy_from_user(pos, num_pages, write_bytes, pages, &i); - dirty_pages = (copied + offset + PAGE_CACHE_SIZE - 1) >> - PAGE_CACHE_SHIFT; + + /* + * if we have trouble faulting in the pages, fall + * back to one page at a time + */ + if (copied < write_bytes) + nrptrs = 1; + + if (copied == 0) + dirty_pages = 0; + else + dirty_pages = (copied + offset + + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT; if (num_pages > dirty_pages) { if (copied > 0) @@ -1069,10 +1103,6 @@ out: err = ret; kfree(pages); - if (pinned[0]) - page_cache_release(pinned[0]); - if (pinned[1]) - page_cache_release(pinned[1]); *ppos = pos; /* diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0efdb65953c..9007bbd01db 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4821,10 +4821,11 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, goto fail; /* - * 1 item for inode ref + * 2 items for inode and inode ref * 2 items for dir items + * 1 item for parent inode */ - trans = btrfs_start_transaction(root, 3); + trans = btrfs_start_transaction(root, 5); if (IS_ERR(trans)) { err = PTR_ERR(trans); goto fail; @@ -6056,6 +6057,7 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, if (!skip_sum) { dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); if (!dip->csums) { + kfree(dip); ret = -ENOMEM; goto free_ordered; } diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 099a58615b9..ebafa65a29b 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -993,7 +993,7 @@ static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) { struct inode *dir; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; dir = dentry->d_parent->d_inode; diff --git a/fs/compat.c b/fs/compat.c index f6fd0a00e6c..691c3fd8ce1 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1228,7 +1228,9 @@ compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_readv(file, vec, vlen, &pos); + ret = -ESPIPE; + if (file->f_mode & FMODE_PREAD) + ret = compat_readv(file, vec, vlen, &pos); fput_light(file, fput_needed); return ret; } @@ -1285,7 +1287,9 @@ compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_writev(file, vec, vlen, &pos); + ret = -ESPIPE; + if (file->f_mode & FMODE_PWRITE) + ret = compat_writev(file, vec, vlen, &pos); fput_light(file, fput_needed); return ret; } diff --git a/fs/dcache.c b/fs/dcache.c index 2a6bd9a4ae9..611ffe928c0 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1523,6 +1523,28 @@ struct dentry * d_alloc_root(struct inode * root_inode) } EXPORT_SYMBOL(d_alloc_root); +static struct dentry * __d_find_any_alias(struct inode *inode) +{ + struct dentry *alias; + + if (list_empty(&inode->i_dentry)) + return NULL; + alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias); + __dget(alias); + return alias; +} + +static struct dentry * d_find_any_alias(struct inode *inode) +{ + struct dentry *de; + + spin_lock(&inode->i_lock); + de = __d_find_any_alias(inode); + spin_unlock(&inode->i_lock); + return de; +} + + /** * d_obtain_alias - find or allocate a dentry for a given inode * @inode: inode to allocate the dentry for @@ -1552,7 +1574,7 @@ struct dentry *d_obtain_alias(struct inode *inode) if (IS_ERR(inode)) return ERR_CAST(inode); - res = d_find_alias(inode); + res = d_find_any_alias(inode); if (res) goto out_iput; @@ -1565,7 +1587,7 @@ struct dentry *d_obtain_alias(struct inode *inode) spin_lock(&inode->i_lock); - res = __d_find_alias(inode, 0); + res = __d_find_any_alias(inode); if (res) { spin_unlock(&inode->i_lock); dput(tmp); diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index f88f752babd..adae3fb7451 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -43,7 +43,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry) static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) { - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; /* This is not negative dentry. Always valid. */ @@ -54,7 +54,7 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) { - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; /* diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 83543b5ff94..8bd0ef9286c 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -158,7 +158,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) { struct inode *inode; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; inode = entry->d_inode; diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c index 4a456338b87..0da8da2c991 100644 --- a/fs/gfs2/dentry.c +++ b/fs/gfs2/dentry.c @@ -44,7 +44,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) int error; int had_lock = 0; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; parent = dget_parent(dentry); diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 81ead850ddb..5a2b269428a 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1600,7 +1600,7 @@ out: static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) { - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; /* * This is not negative dentry. Always valid. diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 1cc600e77bb..2f8e61816d7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -37,6 +37,7 @@ #include <linux/inet.h> #include <linux/nfs_xdr.h> #include <linux/slab.h> +#include <linux/compat.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -89,7 +90,11 @@ int nfs_wait_bit_killable(void *word) */ u64 nfs_compat_user_ino64(u64 fileid) { - int ino; +#ifdef CONFIG_COMPAT + compat_ulong_t ino; +#else + unsigned long ino; +#endif if (enable_ino64) return fileid; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 7a747407314..1be36cf65bf 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -298,6 +298,11 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); #if defined(CONFIG_NFS_V4_1) struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); +extern void nfs4_schedule_session_recovery(struct nfs4_session *); +#else +static inline void nfs4_schedule_session_recovery(struct nfs4_session *session) +{ +} #endif /* CONFIG_NFS_V4_1 */ extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); @@ -307,10 +312,9 @@ extern void nfs4_put_open_state(struct nfs4_state *); extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t); extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t); extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); -extern void nfs4_schedule_state_recovery(struct nfs_client *); +extern void nfs4_schedule_lease_recovery(struct nfs_client *); extern void nfs4_schedule_state_manager(struct nfs_client *); -extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); -extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); +extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); extern void nfs41_handle_recall_slot(struct nfs_client *clp); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index f5c9b125e8c..b73c34375f6 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c @@ -219,6 +219,10 @@ decode_and_add_ds(__be32 **pp, struct inode *inode) goto out_err; } buf = kmalloc(rlen + 1, GFP_KERNEL); + if (!buf) { + dprintk("%s: Not enough memory\n", __func__); + goto out_err; + } buf[rlen] = '\0'; memcpy(buf, r_addr, rlen); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1ff76acc7e9..0a07e353a96 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -51,7 +51,6 @@ #include <linux/sunrpc/bc_xprt.h> #include <linux/xattr.h> #include <linux/utsname.h> -#include <linux/mm.h> #include "nfs4_fs.h" #include "delegation.h" @@ -257,12 +256,13 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, case -NFS4ERR_OPENMODE: if (state == NULL) break; - nfs4_state_mark_reclaim_nograce(clp, state); - goto do_state_recovery; + nfs4_schedule_stateid_recovery(server, state); + goto wait_on_recovery; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_EXPIRED: - goto do_state_recovery; + nfs4_schedule_lease_recovery(clp); + goto wait_on_recovery; #if defined(CONFIG_NFS_V4_1) case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: @@ -273,7 +273,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, case -NFS4ERR_SEQ_MISORDERED: dprintk("%s ERROR: %d Reset session\n", __func__, errorcode); - nfs4_schedule_state_recovery(clp); + nfs4_schedule_session_recovery(clp->cl_session); exception->retry = 1; break; #endif /* defined(CONFIG_NFS_V4_1) */ @@ -296,8 +296,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, } /* We failed to handle the error */ return nfs4_map_errors(ret); -do_state_recovery: - nfs4_schedule_state_recovery(clp); +wait_on_recovery: ret = nfs4_wait_clnt_recover(clp); if (ret == 0) exception->retry = 1; @@ -436,8 +435,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * clp = res->sr_session->clp; do_renew_lease(clp, timestamp); /* Check sequence flags */ - if (atomic_read(&clp->cl_count) > 1) - nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); + if (res->sr_status_flags != 0) + nfs4_schedule_lease_recovery(clp); break; case -NFS4ERR_DELAY: /* The server detected a resend of the RPC call and @@ -1256,14 +1255,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: case -NFS4ERR_DEADSESSION: - nfs4_schedule_state_recovery( - server->nfs_client); + nfs4_schedule_session_recovery(server->nfs_client->cl_session); goto out; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: /* Don't recall a delegation if it was lost */ - nfs4_schedule_state_recovery(server->nfs_client); + nfs4_schedule_lease_recovery(server->nfs_client); goto out; case -ERESTARTSYS: /* @@ -1272,7 +1270,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state */ case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: - nfs4_state_mark_reclaim_nograce(server->nfs_client, state); + nfs4_schedule_stateid_recovery(server, state); case -EKEYEXPIRED: /* * User RPCSEC_GSS context has expired. @@ -1588,7 +1586,7 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) break; - nfs4_schedule_state_recovery(clp); + nfs4_schedule_state_manager(clp); ret = -EIO; } return ret; @@ -3179,7 +3177,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) if (task->tk_status < 0) { /* Unless we're shutting down, schedule state recovery! */ if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) - nfs4_schedule_state_recovery(clp); + nfs4_schedule_lease_recovery(clp); return; } do_renew_lease(clp, timestamp); @@ -3262,7 +3260,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen, spages = pages; do { - len = min(PAGE_CACHE_SIZE, buflen); + len = min_t(size_t, PAGE_CACHE_SIZE, buflen); newpage = alloc_page(GFP_KERNEL); if (newpage == NULL) @@ -3504,12 +3502,13 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, case -NFS4ERR_OPENMODE: if (state == NULL) break; - nfs4_state_mark_reclaim_nograce(clp, state); - goto do_state_recovery; + nfs4_schedule_stateid_recovery(server, state); + goto wait_on_recovery; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_EXPIRED: - goto do_state_recovery; + nfs4_schedule_lease_recovery(clp); + goto wait_on_recovery; #if defined(CONFIG_NFS_V4_1) case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: @@ -3520,7 +3519,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, case -NFS4ERR_SEQ_MISORDERED: dprintk("%s ERROR %d, Reset session\n", __func__, task->tk_status); - nfs4_schedule_state_recovery(clp); + nfs4_schedule_session_recovery(clp->cl_session); task->tk_status = 0; return -EAGAIN; #endif /* CONFIG_NFS_V4_1 */ @@ -3537,9 +3536,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, } task->tk_status = nfs4_map_errors(task->tk_status); return 0; -do_state_recovery: +wait_on_recovery: rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); - nfs4_schedule_state_recovery(clp); if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); task->tk_status = 0; @@ -4150,7 +4148,7 @@ static void nfs4_lock_release(void *calldata) task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, data->arg.lock_seqid); if (!IS_ERR(task)) - rpc_put_task(task); + rpc_put_task_async(task); dprintk("%s: cancelling lock!\n", __func__); } else nfs_free_seqid(data->arg.lock_seqid); @@ -4174,23 +4172,18 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = { static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) { - struct nfs_client *clp = server->nfs_client; - struct nfs4_state *state = lsp->ls_state; - switch (error) { case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: - case -NFS4ERR_EXPIRED: + lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; if (new_lock_owner != 0 || (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) - nfs4_state_mark_reclaim_nograce(clp, state); - lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; + nfs4_schedule_stateid_recovery(server, lsp->ls_state); break; case -NFS4ERR_STALE_STATEID: - if (new_lock_owner != 0 || - (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) - nfs4_state_mark_reclaim_reboot(clp, state); lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; + case -NFS4ERR_EXPIRED: + nfs4_schedule_lease_recovery(server->nfs_client); }; } @@ -4406,12 +4399,14 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) case -NFS4ERR_EXPIRED: case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: + nfs4_schedule_lease_recovery(server->nfs_client); + goto out; case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: case -NFS4ERR_BAD_HIGH_SLOT: case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: case -NFS4ERR_DEADSESSION: - nfs4_schedule_state_recovery(server->nfs_client); + nfs4_schedule_session_recovery(server->nfs_client->cl_session); goto out; case -ERESTARTSYS: /* @@ -4421,7 +4416,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: case -NFS4ERR_OPENMODE: - nfs4_state_mark_reclaim_nograce(server->nfs_client, state); + nfs4_schedule_stateid_recovery(server, state); err = 0; goto out; case -EKEYEXPIRED: @@ -5028,10 +5023,20 @@ int nfs4_proc_create_session(struct nfs_client *clp) int status; unsigned *ptr; struct nfs4_session *session = clp->cl_session; + long timeout = 0; + int err; dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); - status = _nfs4_proc_create_session(clp); + do { + status = _nfs4_proc_create_session(clp); + if (status == -NFS4ERR_DELAY) { + err = nfs4_delay(clp->cl_rpcclient, &timeout); + if (err) + status = err; + } + } while (status == -NFS4ERR_DELAY); + if (status) goto out; @@ -5140,7 +5145,7 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client rpc_delay(task, NFS4_POLL_RETRY_MAX); return -EAGAIN; default: - nfs4_schedule_state_recovery(clp); + nfs4_schedule_lease_recovery(clp); } return 0; } @@ -5227,7 +5232,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr if (IS_ERR(task)) ret = PTR_ERR(task); else - rpc_put_task(task); + rpc_put_task_async(task); dprintk("<-- %s status=%d\n", __func__, ret); return ret; } @@ -5243,8 +5248,13 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) goto out; } ret = rpc_wait_for_completion_task(task); - if (!ret) + if (!ret) { + struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; + + if (task->tk_status == 0) + nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); ret = task->tk_status; + } rpc_put_task(task); out: dprintk("<-- %s status=%d\n", __func__, ret); @@ -5281,7 +5291,7 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf rpc_delay(task, NFS4_POLL_RETRY_MAX); return -EAGAIN; default: - nfs4_schedule_state_recovery(clp); + nfs4_schedule_lease_recovery(clp); } return 0; } @@ -5349,6 +5359,9 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) status = PTR_ERR(task); goto out; } + status = nfs4_wait_for_completion_rpc_task(task); + if (status == 0) + status = task->tk_status; rpc_put_task(task); return 0; out: diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e6742b57a04..0592288f9f0 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1007,9 +1007,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) } /* - * Schedule a state recovery attempt + * Schedule a lease recovery attempt */ -void nfs4_schedule_state_recovery(struct nfs_client *clp) +void nfs4_schedule_lease_recovery(struct nfs_client *clp) { if (!clp) return; @@ -1018,7 +1018,7 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp) nfs4_schedule_state_manager(clp); } -int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) +static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) { set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); @@ -1032,7 +1032,7 @@ int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *st return 1; } -int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) +static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) { set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); @@ -1041,6 +1041,14 @@ int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *s return 1; } +void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state) +{ + struct nfs_client *clp = server->nfs_client; + + nfs4_state_mark_reclaim_nograce(clp, state); + nfs4_schedule_state_manager(clp); +} + static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) { struct inode *inode = state->inode; @@ -1436,10 +1444,15 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) } #ifdef CONFIG_NFS_V4_1 +void nfs4_schedule_session_recovery(struct nfs4_session *session) +{ + nfs4_schedule_lease_recovery(session->clp); +} + void nfs41_handle_recall_slot(struct nfs_client *clp) { set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); - nfs4_schedule_state_recovery(clp); + nfs4_schedule_state_manager(clp); } static void nfs4_reset_all_state(struct nfs_client *clp) @@ -1447,7 +1460,7 @@ static void nfs4_reset_all_state(struct nfs_client *clp) if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { clp->cl_boot_time = CURRENT_TIME; nfs4_state_start_reclaim_nograce(clp); - nfs4_schedule_state_recovery(clp); + nfs4_schedule_state_manager(clp); } } @@ -1455,7 +1468,7 @@ static void nfs41_handle_server_reboot(struct nfs_client *clp) { if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { nfs4_state_start_reclaim_reboot(clp); - nfs4_schedule_state_recovery(clp); + nfs4_schedule_state_manager(clp); } } @@ -1475,7 +1488,7 @@ static void nfs41_handle_cb_path_down(struct nfs_client *clp) { nfs_expire_all_delegations(clp); if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) - nfs4_schedule_state_recovery(clp); + nfs4_schedule_state_manager(clp); } void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 4e2c168b6ee..94d50e86a12 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -1660,7 +1660,7 @@ static void encode_create_session(struct xdr_stream *xdr, p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); *p++ = cpu_to_be32(OP_CREATE_SESSION); - p = xdr_encode_hyper(p, clp->cl_ex_clid); + p = xdr_encode_hyper(p, clp->cl_clientid); *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ *p++ = cpu_to_be32(args->flags); /*flags */ @@ -4694,7 +4694,7 @@ static int decode_exchange_id(struct xdr_stream *xdr, p = xdr_inline_decode(xdr, 8); if (unlikely(!p)) goto out_overflow; - xdr_decode_hyper(p, &clp->cl_ex_clid); + xdr_decode_hyper(p, &clp->cl_clientid); p = xdr_inline_decode(xdr, 12); if (unlikely(!p)) goto out_overflow; diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 903908a2002..c541093a5bf 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -86,11 +86,14 @@ /* Default path we try to mount. "%s" gets replaced by our IP address */ #define NFS_ROOT "/tftpboot/%s" +/* Default NFSROOT mount options. */ +#define NFS_DEF_OPTIONS "udp" + /* Parameters passed from the kernel command line */ static char nfs_root_parms[256] __initdata = ""; /* Text-based mount options passed to super.c */ -static char nfs_root_options[256] __initdata = ""; +static char nfs_root_options[256] __initdata = NFS_DEF_OPTIONS; /* Address of NFS server */ static __be32 servaddr __initdata = htonl(INADDR_NONE); @@ -160,8 +163,14 @@ static int __init root_nfs_copy(char *dest, const char *src, } static int __init root_nfs_cat(char *dest, const char *src, - const size_t destlen) + const size_t destlen) { + size_t len = strlen(dest); + + if (len && dest[len - 1] != ',') + if (strlcat(dest, ",", destlen) > destlen) + return -1; + if (strlcat(dest, src, destlen) > destlen) return -1; return 0; @@ -194,16 +203,6 @@ static int __init root_nfs_parse_options(char *incoming, char *exppath, if (root_nfs_cat(nfs_root_options, incoming, sizeof(nfs_root_options))) return -1; - - /* - * Possibly prepare for more options to be appended - */ - if (nfs_root_options[0] != '\0' && - nfs_root_options[strlen(nfs_root_options)] != ',') - if (root_nfs_cat(nfs_root_options, ",", - sizeof(nfs_root_options))) - return -1; - return 0; } @@ -217,7 +216,7 @@ static int __init root_nfs_parse_options(char *incoming, char *exppath, */ static int __init root_nfs_data(char *cmdline) { - char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; + char mand_options[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; int len, retval = -1; char *tmp = NULL; const size_t tmplen = sizeof(nfs_export_path); @@ -244,9 +243,9 @@ static int __init root_nfs_data(char *cmdline) * Append mandatory options for nfsroot so they override * what has come before */ - snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4", + snprintf(mand_options, sizeof(mand_options), "nolock,addr=%pI4", &servaddr); - if (root_nfs_cat(nfs_root_options, addr_option, + if (root_nfs_cat(nfs_root_options, mand_options, sizeof(nfs_root_options))) goto out_optionstoolong; diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index e313a51acdd..6481d537d69 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -180,7 +180,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n task_setup_data.rpc_client = NFS_CLIENT(dir); task = rpc_run_task(&task_setup_data); if (!IS_ERR(task)) - rpc_put_task(task); + rpc_put_task_async(task); return 1; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c8278f4046c..42b92d7a9cc 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1292,6 +1292,8 @@ static int nfs_commit_rpcsetup(struct list_head *head, task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); + if (how & FLUSH_SYNC) + rpc_wait_for_completion_task(task); rpc_put_task(task); return 0; } diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 6d80ecc7834..7eb90403fc8 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -56,7 +56,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, int ret = 0; /* if all else fails, just return false */ struct ocfs2_super *osb; - if (nd->flags & LOOKUP_RCU) + if (nd && nd->flags & LOOKUP_RCU) return -ECHILD; inode = dentry->d_inode; diff --git a/fs/open.c b/fs/open.c index 5a2c6ebc22b..b47aab39c05 100644 --- a/fs/open.c +++ b/fs/open.c @@ -233,6 +233,14 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!(file->f_mode & FMODE_WRITE)) return -EBADF; + + /* It's not possible punch hole on append only file */ + if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode)) + return -EPERM; + + if (IS_IMMUTABLE(inode)) + return -EPERM; + /* * Revalidate the write permissions, in case security policy has * changed since the files were opened. diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c index 48cec7cbca1..be03a0b08b4 100644 --- a/fs/partitions/osf.c +++ b/fs/partitions/osf.c @@ -10,10 +10,13 @@ #include "check.h" #include "osf.h" +#define MAX_OSF_PARTITIONS 8 + int osf_partition(struct parsed_partitions *state) { int i; int slot = 1; + unsigned int npartitions; Sector sect; unsigned char *data; struct disklabel { @@ -45,7 +48,7 @@ int osf_partition(struct parsed_partitions *state) u8 p_fstype; u8 p_frag; __le16 p_cpg; - } d_partitions[8]; + } d_partitions[MAX_OSF_PARTITIONS]; } * label; struct d_partition * partition; @@ -63,7 +66,12 @@ int osf_partition(struct parsed_partitions *state) put_dev_sector(sect); return 0; } - for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { + npartitions = le16_to_cpu(label->d_npartitions); + if (npartitions > MAX_OSF_PARTITIONS) { + put_dev_sector(sect); + return 0; + } + for (i = 0 ; i < npartitions; i++, partition++) { if (slot == state->limit) break; if (le32_to_cpu(partition->p_size)) diff --git a/fs/proc/base.c b/fs/proc/base.c index 9d096e82b20..d49c4b5d2c3 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2620,35 +2620,6 @@ static const struct pid_entry proc_base_stuff[] = { &proc_self_inode_operations, NULL, {}), }; -/* - * Exceptional case: normally we are not allowed to unhash a busy - * directory. In this case, however, we can do it - no aliasing problems - * due to the way we treat inodes. - */ -static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd) -{ - struct inode *inode; - struct task_struct *task; - - if (nd->flags & LOOKUP_RCU) - return -ECHILD; - - inode = dentry->d_inode; - task = get_proc_task(inode); - if (task) { - put_task_struct(task); - return 1; - } - d_drop(dentry); - return 0; -} - -static const struct dentry_operations proc_base_dentry_operations = -{ - .d_revalidate = proc_base_revalidate, - .d_delete = pid_delete_dentry, -}; - static struct dentry *proc_base_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr) { @@ -2685,7 +2656,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir, if (p->fop) inode->i_fop = p->fop; ei->op = p->op; - d_set_d_op(dentry, &proc_base_dentry_operations); d_add(dentry, inode); error = NULL; out: diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 3cfb2e93364..5c11ca82b78 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -978,8 +978,6 @@ int reiserfs_permission(struct inode *inode, int mask, unsigned int flags) static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) { - if (nd->flags & LOOKUP_RCU) - return -ECHILD; return -EPERM; } diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 9e7f259346e..227d590cd8d 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -43,12 +43,12 @@ struct amba_id { struct amba_driver { struct device_driver drv; - int (*probe)(struct amba_device *, struct amba_id *); + int (*probe)(struct amba_device *, const struct amba_id *); int (*remove)(struct amba_device *); void (*shutdown)(struct amba_device *); int (*suspend)(struct amba_device *, pm_message_t); int (*resume)(struct amba_device *); - struct amba_id *id_table; + const struct amba_id *id_table; }; enum amba_vendor { @@ -56,6 +56,8 @@ enum amba_vendor { AMBA_VENDOR_ST = 0x80, }; +extern struct bus_type amba_bustype; + #define amba_get_drvdata(d) dev_get_drvdata(&d->dev) #define amba_set_drvdata(d,p) dev_set_drvdata(&d->dev, p) diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index b197563913b..3e112de12d8 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -68,11 +68,7 @@ struct nfs_client { unsigned char cl_id_uniquifier; u32 cl_cb_ident; /* v4.0 callback identifier */ const struct nfs4_minor_version_ops *cl_mvops; -#endif /* CONFIG_NFS_V4 */ -#ifdef CONFIG_NFS_V4_1 - /* clientid returned from EXCHANGE_ID, used by session operations */ - u64 cl_ex_clid; /* The sequence id to use for the next CREATE_SESSION */ u32 cl_seqid; /* The flags used for obtaining the clientid during EXCHANGE_ID */ @@ -80,7 +76,7 @@ struct nfs_client { struct nfs4_session *cl_session; /* sharred session */ struct list_head cl_layouts; struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */ -#endif /* CONFIG_NFS_V4_1 */ +#endif /* CONFIG_NFS_V4 */ #ifdef CONFIG_NFS_FSCACHE struct fscache_cookie *fscache; /* client index cache cookie */ @@ -185,7 +181,7 @@ struct nfs_server { /* maximum number of slots to use */ #define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE -#if defined(CONFIG_NFS_V4_1) +#if defined(CONFIG_NFS_V4) /* Sessions */ #define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long))) @@ -225,5 +221,5 @@ struct nfs4_session { struct nfs_client *clp; }; -#endif /* CONFIG_NFS_V4_1 */ +#endif /* CONFIG_NFS_V4 */ #endif diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 88513fd8e20..d81db8012c6 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -212,6 +212,7 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *); struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, const struct rpc_call_ops *ops); void rpc_put_task(struct rpc_task *); +void rpc_put_task_async(struct rpc_task *); void rpc_exit_task(struct rpc_task *); void rpc_exit(struct rpc_task *, int); void rpc_release_calldata(const struct rpc_call_ops *, void *); diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index 24694051157..2e8ec51f061 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h @@ -135,6 +135,8 @@ extern void transport_complete_task(struct se_task *, int); extern void transport_add_task_to_execute_queue(struct se_task *, struct se_task *, struct se_device *); +extern void transport_remove_task_from_execute_queue(struct se_task *, + struct se_device *); unsigned char *transport_dump_cmd_direction(struct se_cmd *); extern void transport_dump_dev_state(struct se_device *, char *, int *); extern void transport_dump_dev_info(struct se_device *, struct se_lun *, diff --git a/kernel/sched.c b/kernel/sched.c index 18d38e4ec7b..42eab5a8437 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4213,6 +4213,7 @@ void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key) { __wake_up_common(q, mode, 1, 0, key); } +EXPORT_SYMBOL_GPL(__wake_up_locked_key); /** * __wake_up_sync_key - wake up threads blocked on a waitqueue. diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index ad6267714c8..01f75a5f17a 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -210,11 +210,12 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se); static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) { - int this_cpu = smp_processor_id(); struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; struct sched_rt_entity *rt_se; - rt_se = rt_rq->tg->rt_se[this_cpu]; + int cpu = cpu_of(rq_of_rt_rq(rt_rq)); + + rt_se = rt_rq->tg->rt_se[cpu]; if (rt_rq->rt_nr_running) { if (rt_se && !on_rt_rq(rt_se)) @@ -226,10 +227,10 @@ static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) static void sched_rt_rq_dequeue(struct rt_rq *rt_rq) { - int this_cpu = smp_processor_id(); struct sched_rt_entity *rt_se; + int cpu = cpu_of(rq_of_rt_rq(rt_rq)); - rt_se = rt_rq->tg->rt_se[this_cpu]; + rt_se = rt_rq->tg->rt_se[cpu]; if (rt_se && on_rt_rq(rt_se)) dequeue_rt_entity(rt_se); @@ -565,8 +566,11 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun) if (rt_rq->rt_time || rt_rq->rt_nr_running) idle = 0; raw_spin_unlock(&rt_rq->rt_runtime_lock); - } else if (rt_rq->rt_nr_running) + } else if (rt_rq->rt_nr_running) { idle = 0; + if (!rt_rq_throttled(rt_rq)) + enqueue = 1; + } if (enqueue) sched_rt_rq_enqueue(rt_rq); diff --git a/mm/huge_memory.c b/mm/huge_memory.c index dbe99a5f207..113e35c4750 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1762,6 +1762,10 @@ static void collapse_huge_page(struct mm_struct *mm, #ifndef CONFIG_NUMA VM_BUG_ON(!*hpage); new_page = *hpage; + if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { + up_read(&mm->mmap_sem); + return; + } #else VM_BUG_ON(*hpage); /* @@ -1781,12 +1785,12 @@ static void collapse_huge_page(struct mm_struct *mm, *hpage = ERR_PTR(-ENOMEM); return; } -#endif if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { up_read(&mm->mmap_sem); put_page(new_page); return; } +#endif /* after allocating the hugepage upgrade to mmap_sem write mode */ up_read(&mm->mmap_sem); diff --git a/mm/rmap.c b/mm/rmap.c index f21f4a1d6a1..941bf82e896 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -497,41 +497,51 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, struct mm_struct *mm = vma->vm_mm; int referenced = 0; - /* - * Don't want to elevate referenced for mlocked page that gets this far, - * in order that it progresses to try_to_unmap and is moved to the - * unevictable list. - */ - if (vma->vm_flags & VM_LOCKED) { - *mapcount = 0; /* break early from loop */ - *vm_flags |= VM_LOCKED; - goto out; - } - - /* Pretend the page is referenced if the task has the - swap token and is in the middle of a page fault. */ - if (mm != current->mm && has_swap_token(mm) && - rwsem_is_locked(&mm->mmap_sem)) - referenced++; - if (unlikely(PageTransHuge(page))) { pmd_t *pmd; spin_lock(&mm->page_table_lock); + /* + * rmap might return false positives; we must filter + * these out using page_check_address_pmd(). + */ pmd = page_check_address_pmd(page, mm, address, PAGE_CHECK_ADDRESS_PMD_FLAG); - if (pmd && !pmd_trans_splitting(*pmd) && - pmdp_clear_flush_young_notify(vma, address, pmd)) + if (!pmd) { + spin_unlock(&mm->page_table_lock); + goto out; + } + + if (vma->vm_flags & VM_LOCKED) { + spin_unlock(&mm->page_table_lock); + *mapcount = 0; /* break early from loop */ + *vm_flags |= VM_LOCKED; + goto out; + } + + /* go ahead even if the pmd is pmd_trans_splitting() */ + if (pmdp_clear_flush_young_notify(vma, address, pmd)) referenced++; spin_unlock(&mm->page_table_lock); } else { pte_t *pte; spinlock_t *ptl; + /* + * rmap might return false positives; we must filter + * these out using page_check_address(). + */ pte = page_check_address(page, mm, address, &ptl, 0); if (!pte) goto out; + if (vma->vm_flags & VM_LOCKED) { + pte_unmap_unlock(pte, ptl); + *mapcount = 0; /* break early from loop */ + *vm_flags |= VM_LOCKED; + goto out; + } + if (ptep_clear_flush_young_notify(vma, address, pte)) { /* * Don't treat a reference through a sequentially read @@ -546,6 +556,12 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, pte_unmap_unlock(pte, ptl); } + /* Pretend the page is referenced if the task has the + swap token and is in the middle of a page fault. */ + if (mm != current->mm && has_swap_token(mm) && + rwsem_is_locked(&mm->mmap_sem)) + referenced++; + (*mapcount)--; if (referenced) diff --git a/net/Makefile b/net/Makefile index a3330ebe2c5..a51d9465e62 100644 --- a/net/Makefile +++ b/net/Makefile @@ -19,9 +19,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_INET) += ipv4/ obj-$(CONFIG_XFRM) += xfrm/ obj-$(CONFIG_UNIX) += unix/ -ifneq ($(CONFIG_IPV6),) -obj-y += ipv6/ -endif +obj-$(CONFIG_NET) += ipv6/ obj-$(CONFIG_PACKET) += packet/ obj-$(CONFIG_NET_KEY) += key/ obj-$(CONFIG_BRIDGE) += bridge/ diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index 9190ae462cb..6dee7bf648a 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig @@ -6,6 +6,7 @@ config BRIDGE tristate "802.1d Ethernet Bridging" select LLC select STP + depends on IPV6 || IPV6=n ---help--- If you say Y here, then your Linux box will be able to act as an Ethernet bridge, which means that the different Ethernet segments it diff --git a/net/core/pktgen.c b/net/core/pktgen.c index a9e7fc4c461..b5bada92f63 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3321,7 +3321,7 @@ static void show_results(struct pktgen_dev *pkt_dev, int nr_frags) pkt_dev->started_at); ktime_t idle = ns_to_ktime(pkt_dev->idle_acc); - p += sprintf(p, "OK: %llu(c%llu+d%llu) nsec, %llu (%dbyte,%dfrags)\n", + p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n", (unsigned long long)ktime_to_us(elapsed), (unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)), (unsigned long long)ktime_to_us(idle), diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index df4616fce92..036652c8166 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -670,7 +670,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ifap = &ifa->ifa_next) { if (!strcmp(ifr.ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == - ifa->ifa_address) { + ifa->ifa_local) { break; /* found */ } } @@ -1040,8 +1040,8 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev, return; arp_send(ARPOP_REQUEST, ETH_P_ARP, - ifa->ifa_address, dev, - ifa->ifa_address, NULL, + ifa->ifa_local, dev, + ifa->ifa_local, NULL, dev->dev_addr, NULL); } diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 4f4483e697b..e528a42a52b 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -57,6 +57,7 @@ MODULE_AUTHOR("Ville Nuorvala"); MODULE_DESCRIPTION("IPv6 tunneling device"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_NETDEV("ip6tnl0"); #ifdef IP6_TNL_DEBUG #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 904312e25a3..e7db7014e89 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -739,8 +739,10 @@ restart: if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); - else + else if (!(rt->dst.flags & DST_HOST)) nrt = rt6_alloc_clone(rt, &fl->fl6_dst); + else + goto out2; dst_release(&rt->dst); rt = nrt ? : net->ipv6.ip6_null_entry; diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index 71f373c421b..c47a511f203 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -551,7 +551,10 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, if (conn->c_loopback && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { rds_cong_map_updated(conn->c_fcong, ~(u64) 0); - return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; + scat = &rm->data.op_sg[sg]; + ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; + ret = min_t(int, ret, scat->length - conn->c_xmit_data_off); + return ret; } /* FIXME we may overallocate here */ diff --git a/net/rds/loop.c b/net/rds/loop.c index aeec1d483b1..bca6761a3ca 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c @@ -61,10 +61,15 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm, unsigned int hdr_off, unsigned int sg, unsigned int off) { + struct scatterlist *sgp = &rm->data.op_sg[sg]; + int ret = sizeof(struct rds_header) + + be32_to_cpu(rm->m_inc.i_hdr.h_len); + /* Do not send cong updates to loopback */ if (rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { rds_cong_map_updated(conn->c_fcong, ~(u64) 0); - return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; + ret = min_t(int, ret, sgp->length - conn->c_xmit_data_off); + goto out; } BUG_ON(hdr_off || sg || off); @@ -80,8 +85,8 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm, NULL); rds_inc_put(&rm->m_inc); - - return sizeof(struct rds_header) + be32_to_cpu(rm->m_inc.i_hdr.h_len); +out: + return ret; } /* diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 243fc09b164..59e599498e3 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -252,23 +252,37 @@ static void rpc_set_active(struct rpc_task *task) /* * Mark an RPC call as having completed by clearing the 'active' bit + * and then waking up all tasks that were sleeping. */ -static void rpc_mark_complete_task(struct rpc_task *task) +static int rpc_complete_task(struct rpc_task *task) { - smp_mb__before_clear_bit(); + void *m = &task->tk_runstate; + wait_queue_head_t *wq = bit_waitqueue(m, RPC_TASK_ACTIVE); + struct wait_bit_key k = __WAIT_BIT_KEY_INITIALIZER(m, RPC_TASK_ACTIVE); + unsigned long flags; + int ret; + + spin_lock_irqsave(&wq->lock, flags); clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); - smp_mb__after_clear_bit(); - wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); + ret = atomic_dec_and_test(&task->tk_count); + if (waitqueue_active(wq)) + __wake_up_locked_key(wq, TASK_NORMAL, &k); + spin_unlock_irqrestore(&wq->lock, flags); + return ret; } /* * Allow callers to wait for completion of an RPC call + * + * Note the use of out_of_line_wait_on_bit() rather than wait_on_bit() + * to enforce taking of the wq->lock and hence avoid races with + * rpc_complete_task(). */ int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) { if (action == NULL) action = rpc_wait_bit_killable; - return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, + return out_of_line_wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, action, TASK_KILLABLE); } EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); @@ -857,34 +871,67 @@ static void rpc_async_release(struct work_struct *work) rpc_free_task(container_of(work, struct rpc_task, u.tk_work)); } -void rpc_put_task(struct rpc_task *task) +static void rpc_release_resources_task(struct rpc_task *task) { - if (!atomic_dec_and_test(&task->tk_count)) - return; - /* Release resources */ if (task->tk_rqstp) xprt_release(task); if (task->tk_msg.rpc_cred) put_rpccred(task->tk_msg.rpc_cred); rpc_task_release_client(task); - if (task->tk_workqueue != NULL) { +} + +static void rpc_final_put_task(struct rpc_task *task, + struct workqueue_struct *q) +{ + if (q != NULL) { INIT_WORK(&task->u.tk_work, rpc_async_release); - queue_work(task->tk_workqueue, &task->u.tk_work); + queue_work(q, &task->u.tk_work); } else rpc_free_task(task); } + +static void rpc_do_put_task(struct rpc_task *task, struct workqueue_struct *q) +{ + if (atomic_dec_and_test(&task->tk_count)) { + rpc_release_resources_task(task); + rpc_final_put_task(task, q); + } +} + +void rpc_put_task(struct rpc_task *task) +{ + rpc_do_put_task(task, NULL); +} EXPORT_SYMBOL_GPL(rpc_put_task); +void rpc_put_task_async(struct rpc_task *task) +{ + rpc_do_put_task(task, task->tk_workqueue); +} +EXPORT_SYMBOL_GPL(rpc_put_task_async); + static void rpc_release_task(struct rpc_task *task) { dprintk("RPC: %5u release task\n", task->tk_pid); BUG_ON (RPC_IS_QUEUED(task)); - /* Wake up anyone who is waiting for task completion */ - rpc_mark_complete_task(task); + rpc_release_resources_task(task); - rpc_put_task(task); + /* + * Note: at this point we have been removed from rpc_clnt->cl_tasks, + * so it should be safe to use task->tk_count as a test for whether + * or not any other processes still hold references to our rpc_task. + */ + if (atomic_read(&task->tk_count) != 1 + !RPC_IS_ASYNC(task)) { + /* Wake up anyone who may be waiting for task completion */ + if (!rpc_complete_task(task)) + return; + } else { + if (!atomic_dec_and_test(&task->tk_count)) + return; + } + rpc_final_put_task(task, task->tk_workqueue); } int rpciod_up(void) diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 9df1eadc912..1a10dcd999e 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -1335,6 +1335,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, p, 0, length, DMA_FROM_DEVICE); if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { put_page(p); + svc_rdma_put_context(ctxt, 1); return; } atomic_inc(&xprt->sc_dma_used); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c431f5a5796..be96d429b47 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1631,7 +1631,8 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt, } xs_reclassify_socket(family, sock); - if (xs_bind(transport, sock)) { + err = xs_bind(transport, sock); + if (err) { sock_release(sock); goto out; } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index dd419d28620..437a99e560e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1724,7 +1724,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_namelen = 0; - mutex_lock(&u->readlock); + err = mutex_lock_interruptible(&u->readlock); + if (err) { + err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); + goto out; + } skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { @@ -1864,7 +1868,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, memset(&tmp_scm, 0, sizeof(tmp_scm)); } - mutex_lock(&u->readlock); + err = mutex_lock_interruptible(&u->readlock); + if (err) { + err = sock_intr_errno(timeo); + goto out; + } do { int chunk; @@ -1895,11 +1903,12 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, timeo = unix_stream_data_wait(sk, timeo); - if (signal_pending(current)) { + if (signal_pending(current) + || mutex_lock_interruptible(&u->readlock)) { err = sock_intr_errno(timeo); goto out; } - mutex_lock(&u->readlock); + continue; unlock: unix_state_unlock(sk); diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 6c94c6ce292..291228e2598 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -309,6 +309,11 @@ static void do_config_file(const char *filename) close(fd); } +/* + * Important: The below generated source_foo.o and deps_foo.o variable + * assignments are parsed not only by make, but also by the rather simple + * parser in scripts/mod/sumversion.c. + */ static void parse_dep_file(void *map, size_t len) { char *m = map; @@ -323,7 +328,6 @@ static void parse_dep_file(void *map, size_t len) exit(1); } memcpy(s, m, p-m); s[p-m] = 0; - printf("deps_%s := \\\n", target); m = p+1; clear_config(); @@ -343,12 +347,15 @@ static void parse_dep_file(void *map, size_t len) strrcmp(s, "arch/um/include/uml-config.h") && strrcmp(s, ".ver")) { /* - * Do not output the first dependency (the - * source file), so that kbuild is not confused - * if a .c file is rewritten into .S or vice - * versa. + * Do not list the source file as dependency, so that + * kbuild is not confused if a .c file is rewritten + * into .S or vice versa. Storing it in source_* is + * needed for modpost to compute srcversions. */ - if (!first) + if (first) { + printf("source_%s := %s\n\n", target, s); + printf("deps_%s := \\\n", target); + } else printf(" %s \\\n", s); do_config_file(s); } diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index ecf9c7dc182..9dfcd6d988d 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -300,8 +300,8 @@ static int is_static_library(const char *objfile) return 0; } -/* We have dir/file.o. Open dir/.file.o.cmd, look for deps_ line to - * figure out source file. */ +/* We have dir/file.o. Open dir/.file.o.cmd, look for source_ and deps_ line + * to figure out source files. */ static int parse_source_files(const char *objfile, struct md4_ctx *md) { char *cmd, *file, *line, *dir; @@ -340,6 +340,21 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) */ while ((line = get_next_line(&pos, file, flen)) != NULL) { char* p = line; + + if (strncmp(line, "source_", sizeof("source_")-1) == 0) { + p = strrchr(line, ' '); + if (!p) { + warn("malformed line: %s\n", line); + goto out_file; + } + p++; + if (!parse_file(p, md)) { + warn("could not open %s: %s\n", + p, strerror(errno)); + goto out_file; + } + continue; + } if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) { check_files = 1; continue; diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 7c1fc64cb53..d0821f8974a 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -1011,7 +1011,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) return i; } -static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) +static int __devinit aaci_probe(struct amba_device *dev, + const struct amba_id *id) { struct aaci *aaci; int ret, i; diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 4bbc3442703..8dfb0a0da67 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -145,18 +145,18 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { SOC_SINGLE("DAC Playback Limiter Threshold", WM8978_DAC_LIMITER_2, 4, 7, 0), SOC_SINGLE("DAC Playback Limiter Boost", - WM8978_DAC_LIMITER_2, 0, 15, 0), + WM8978_DAC_LIMITER_2, 0, 12, 0), SOC_ENUM("ALC Enable Switch", alc1), SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), SOC_SINGLE("ALC Capture Max Gain", WM8978_ALC_CONTROL_1, 3, 7, 0), - SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 7, 0), + SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 10, 0), SOC_SINGLE("ALC Capture Target", WM8978_ALC_CONTROL_2, 0, 15, 0), SOC_ENUM("ALC Capture Mode", alc3), - SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 15, 0), - SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 15, 0), + SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 10, 0), + SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 10, 0), SOC_SINGLE("ALC Capture Noise Gate Switch", WM8978_NOISE_GATE, 3, 1, 0), SOC_SINGLE("ALC Capture Noise Gate Threshold", @@ -211,8 +211,10 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1), /* DAC / ADC oversampling */ - SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, 8, 1, 0), - SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, 8, 1, 0), + SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, + 5, 1, 0), + SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, + 5, 1, 0), }; /* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */ diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 4afbe3b2e44..c6c958ee5d5 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1418,7 +1418,7 @@ SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_SOC_NOPM, 0, 0, static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), -SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), +SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), }; @@ -3325,6 +3325,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) case WM8958: snd_soc_add_controls(codec, wm8958_snd_controls, ARRAY_SIZE(wm8958_snd_controls)); + snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, + ARRAY_SIZE(wm8994_lateclk_widgets)); + snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, + ARRAY_SIZE(wm8994_adc_widgets)); + snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, + ARRAY_SIZE(wm8994_dac_widgets)); snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, ARRAY_SIZE(wm8958_dapm_widgets)); break; @@ -3350,6 +3356,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) } break; case WM8958: + snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, + ARRAY_SIZE(wm8994_lateclk_intercon)); snd_soc_dapm_add_routes(dapm, wm8958_intercon, ARRAY_SIZE(wm8958_intercon)); break; diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 161750443eb..73dde4a1adc 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -139,7 +139,7 @@ static struct snd_soc_dai_link am3517evm_dai = { .cpu_dai_name ="omap-mcbsp-dai.0", .codec_dai_name = "tlv320aic23-hifi", .platform_name = "omap-pcm-audio", - .codec_name = "tlv320aic23-codec", + .codec_name = "tlv320aic23-codec.2-001a", .init = am3517evm_aic23_init, .ops = &am3517evm_ops, }; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 25e54230cc6..1790f83ee66 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -941,7 +941,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, } if (!list_empty(&pending)) - dapm_seq_run_coalesced(dapm, &pending); + dapm_seq_run_coalesced(cur_dapm, &pending); } static void dapm_widget_update(struct snd_soc_dapm_context *dapm) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f6a929e7498..0866bcdb5e8 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -270,11 +270,15 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, const char *name, bool is_kallsyms) { const size_t size = PATH_MAX; - char *realname = realpath(name, NULL), - *filename = malloc(size), + char *realname, *filename = malloc(size), *linkname = malloc(size), *targetname; int len, err = -1; + if (is_kallsyms) + realname = (char *)name; + else + realname = realpath(name, NULL); + if (realname == NULL || filename == NULL || linkname == NULL) goto out_free; @@ -306,7 +310,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, if (symlink(targetname, linkname) == 0) err = 0; out_free: - free(realname); + if (!is_kallsyms) + free(realname); free(filename); free(linkname); return err; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 7821d0e6866..b1bf490aff8 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1836,7 +1836,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map, int err = -1, fd; char symfs_vmlinux[PATH_MAX]; - snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s", + snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", symbol_conf.symfs, vmlinux); fd = open(symfs_vmlinux, O_RDONLY); if (fd < 0) |