diff options
386 files changed, 6743 insertions, 10611 deletions
diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README index 1fe2d7f..5e38e158 100644 --- a/Documentation/arm/sunxi/README +++ b/Documentation/arm/sunxi/README @@ -36,7 +36,7 @@ SunXi family + User Manual http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf - - Allwinner A23 + - Allwinner A23 (sun8i) + Datasheet http://dl.linux-sunxi.org/A23/A23%20Datasheet%20V1.0%2020130830.pdf + User Manual @@ -55,7 +55,23 @@ SunXi family + User Manual http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20User%20Manual%20%20V1.0%2020130322.pdf + - Allwinner A33 (sun8i) + + Datasheet + http://dl.linux-sunxi.org/A33/A33%20Datasheet%20release%201.1.pdf + + User Manual + http://dl.linux-sunxi.org/A33/A33%20user%20manual%20release%201.1.pdf + + - Allwinner H3 (sun8i) + + Datasheet + http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf + * Quad ARM Cortex-A15, Quad ARM Cortex-A7 based SoCs - Allwinner A80 + Datasheet http://dl.linux-sunxi.org/A80/A80_Datasheet_Revision_1.0_0404.pdf + + * Octa ARM Cortex-A7 based SoCs + - Allwinner A83T + + Not Supported + + Datasheet + http://dl.linux-sunxi.org/A83T/A83T_datasheet_Revision_1.1.pdf diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt index 42941fd..67da205 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.txt +++ b/Documentation/devicetree/bindings/arm/sunxi.txt @@ -9,4 +9,6 @@ using one of the following compatible strings: allwinner,sun6i-a31 allwinner,sun7i-a20 allwinner,sun8i-a23 + allwinner,sun8i-a33 + allwinner,sun8i-h3 allwinner,sun9i-a80 diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt index 938f8e1..0db6047 100644 --- a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt +++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt @@ -8,6 +8,7 @@ of the EMIF IP and memory parts attached to it. Required properties: - compatible : Should be of the form "ti,emif-<ip-rev>" where <ip-rev> is the IP revision of the specific EMIF instance. + For am437x should be ti,emif-am4372. - phy-type : <u32> indicating the DDR phy type. Following are the allowed values diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index f732a83..8cc17ca 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -410,8 +410,17 @@ Documentation/usb/persist.txt. Q: Can I suspend-to-disk using a swap partition under LVM? -A: No. You can suspend successfully, but you'll not be able to -resume. uswsusp should be able to work with LVM. See suspend.sf.net. +A: Yes and No. You can suspend successfully, but the kernel will not be able +to resume on its own. You need an initramfs that can recognize the resume +situation, activate the logical volume containing the swap volume (but not +touch any filesystems!), and eventually call + +echo -n "$major:$minor" > /sys/power/resume + +where $major and $minor are the respective major and minor device numbers of +the swap volume. + +uswsusp works with LVM, too. See http://suspend.sourceforge.net/ Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were compiled with the similar configuration files. Anyway I found that diff --git a/MAINTAINERS b/MAINTAINERS index 8133cef..40acdf3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1464,9 +1464,7 @@ F: arch/arm/boot/dts/emev2* F: arch/arm/boot/dts/r7s* F: arch/arm/boot/dts/r8a* F: arch/arm/boot/dts/sh* -F: arch/arm/configs/armadillo800eva_defconfig F: arch/arm/configs/bockw_defconfig -F: arch/arm/configs/kzm9g_defconfig F: arch/arm/configs/marzen_defconfig F: arch/arm/configs/shmobile_defconfig F: arch/arm/include/debug/renesas-scif.S @@ -1614,6 +1612,7 @@ M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/boot/dts/vexpress* +F: arch/arm64/boot/dts/arm/vexpress* F: arch/arm/mach-vexpress/ F: */*/vexpress* F: */*/*/vexpress* @@ -2562,19 +2561,31 @@ F: arch/powerpc/include/uapi/asm/spu*.h F: arch/powerpc/oprofile/*cell* F: arch/powerpc/platforms/cell/ -CEPH DISTRIBUTED FILE SYSTEM CLIENT +CEPH COMMON CODE (LIBCEPH) +M: Ilya Dryomov <idryomov@gmail.com> M: "Yan, Zheng" <zyan@redhat.com> M: Sage Weil <sage@redhat.com> L: ceph-devel@vger.kernel.org W: http://ceph.com/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git +T: git git://github.com/ceph/ceph-client.git S: Supported -F: Documentation/filesystems/ceph.txt -F: fs/ceph/ F: net/ceph/ F: include/linux/ceph/ F: include/linux/crush/ +CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH) +M: "Yan, Zheng" <zyan@redhat.com> +M: Sage Weil <sage@redhat.com> +M: Ilya Dryomov <idryomov@gmail.com> +L: ceph-devel@vger.kernel.org +W: http://ceph.com/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git +T: git git://github.com/ceph/ceph-client.git +S: Supported +F: Documentation/filesystems/ceph.txt +F: fs/ceph/ + CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: L: linux-usb@vger.kernel.org S: Orphan @@ -6147,6 +6158,7 @@ L: linux-nvdimm@lists.01.org Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ S: Supported F: drivers/nvdimm/pmem.c +F: include/linux/pmem.h LINUX FOR IBM pSERIES (RS/6000) M: Paul Mackerras <paulus@au.ibm.com> @@ -6161,7 +6173,7 @@ M: Michael Ellerman <mpe@ellerman.id.au> W: http://www.penguinppc.org/ L: linuxppc-dev@lists.ozlabs.org Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git S: Supported F: Documentation/powerpc/ F: arch/powerpc/ @@ -8366,10 +8378,12 @@ RADOS BLOCK DEVICE (RBD) M: Ilya Dryomov <idryomov@gmail.com> M: Sage Weil <sage@redhat.com> M: Alex Elder <elder@kernel.org> -M: ceph-devel@vger.kernel.org +L: ceph-devel@vger.kernel.org W: http://ceph.com/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git +T: git git://github.com/ceph/ceph-client.git S: Supported +F: Documentation/ABI/testing/sysfs-bus-rbd F: drivers/block/rbd.c F: drivers/block/rbd_types.h @@ -1,7 +1,7 @@ VERSION = 4 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Hurr durr I'ma sheep # *DOCUMENTATION* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a750c14..e787353 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -268,7 +268,6 @@ config PHYS_OFFSET depends on !ARM_PATCH_PHYS_VIRT default DRAM_BASE if !MMU default 0x00000000 if ARCH_EBSA110 || \ - EP93XX_SDCE3_SYNC_PHYS_OFFSET || \ ARCH_FOOTBRIDGE || \ ARCH_INTEGRATOR || \ ARCH_IOP13XX || \ @@ -277,10 +276,7 @@ config PHYS_OFFSET default 0x10000000 if ARCH_OMAP1 || ARCH_RPC default 0x20000000 if ARCH_S5PV210 default 0x70000000 if REALVIEW_HIGH_PHYS_OFFSET - default 0xc0000000 if EP93XX_SDCE0_PHYS_OFFSET || ARCH_SA1100 - default 0xd0000000 if EP93XX_SDCE1_PHYS_OFFSET - default 0xe0000000 if EP93XX_SDCE2_PHYS_OFFSET - default 0xf0000000 if EP93XX_SDCE3_ASYNC_PHYS_OFFSET + default 0xc0000000 if ARCH_SA1100 help Please provide the physical address corresponding to the location of main memory in your system. @@ -418,11 +414,14 @@ config ARCH_EP93XX bool "EP93xx-based" select ARCH_HAS_HOLES_MEMORYMODEL select ARCH_REQUIRE_GPIOLIB - select ARCH_USES_GETTIMEOFFSET select ARM_AMBA + select ARM_PATCH_PHYS_VIRT select ARM_VIC + select AUTO_ZRELADDR select CLKDEV_LOOKUP + select CLKSRC_MMIO select CPU_ARM920T + select GENERIC_CLOCKEVENTS help This enables support for the Cirrus EP93xx series of CPUs. @@ -1693,6 +1692,12 @@ config HIGHMEM config HIGHPTE bool "Allocate 2nd-level pagetables from highmem" depends on HIGHMEM + help + The VM uses one page of physical memory for each page table. + For systems with a lot of processes, this can use a lot of + precious low memory, eventually leading to low memory being + consumed by page tables. Setting this option will allow + user-space 2nd level page tables to reside in high memory. config HW_PERF_EVENTS bool "Enable hardware performance counter support for perf events" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index f1b1579..a2e16f9 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1635,7 +1635,7 @@ config PID_IN_CONTEXTIDR config DEBUG_SET_MODULE_RONX bool "Set loadable kernel module data as NX and text as RO" - depends on MODULES + depends on MODULES && MMU ---help--- This option helps catch unintended modifications to loadable kernel module's text and read-only data. It also prevents execution diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 7a13aeb..3f9a9eb 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -51,10 +51,6 @@ else endif endif -ifeq ($(CONFIG_ARCH_SHMOBILE_LEGACY),y) -OBJS += head-shmobile.o -endif - # # We now have a PIC decompressor implementation. Decompressors running # from RAM should not define ZTEXTADDR. Decompressors running directly diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S deleted file mode 100644 index 22a7525..0000000 --- a/arch/arm/boot/compressed/head-shmobile.S +++ /dev/null @@ -1,71 +0,0 @@ -/* - * The head-file for SH-Mobile ARM platforms - * - * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * Simon Horman <horms@verge.net.au> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef CONFIG_ZBOOT_ROM - - .section ".start", "ax" - - /* load board-specific initialization code */ -#include <mach/zboot.h> - - adr r0, dtb_info - ldmia r0, {r1, r3, r4, r5, r7} - - sub r0, r0, r1 @ calculate the delta offset - add r5, r5, r0 @ _edata - - ldr lr, [r5, #0] @ check if valid DTB is present - cmp lr, r3 - bne 0f - - add r9, r7, #31 @ rounded up to a multiple - bic r9, r9, #31 @ ... of 32 bytes - - add r6, r9, r5 @ copy from _edata - add r9, r9, r4 @ to MEMORY_START - -1: ldmdb r6!, {r0 - r3, r10 - r12, lr} - cmp r6, r5 - stmdb r9!, {r0 - r3, r10 - r12, lr} - bhi 1b - - /* Success: Zero board ID, pointer to start of memory for atag/dtb */ - mov r7, #0 - mov r8, r4 - b 2f - - .align 2 -dtb_info: - .word dtb_info -#ifndef __ARMEB__ - .word 0xedfe0dd0 @ sig is 0xd00dfeed big endian -#else - .word 0xd00dfeed -#endif - .word MEMORY_START - .word _edata - .word 0x4000 @ maximum DTB size -0: - /* Failure: Zero board ID, NULL atag/dtb */ - mov r7, #0 - mov r8, #0 @ pass null pointer as atag -2 : - -#endif /* CONFIG_ZBOOT_ROM */ diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 2e3faba..d10eea8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -501,9 +501,9 @@ dtb-$(CONFIG_ARCH_S5PV210) += \ s5pv210-smdkv210.dtb \ s5pv210-torbreck.dtb dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ - r8a7740-armadillo800eva.dtb \ r8a7778-bockw.dtb \ r8a7778-bockw-reference.dtb \ + r8a7779-marzen.dtb \ sh73a0-kzm9g.dtb dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \ emev2-kzm9d.dtb \ diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts index 901739f..5c42d25 100644 --- a/arch/arm/boot/dts/am335x-boneblack.dts +++ b/arch/arm/boot/dts/am335x-boneblack.dts @@ -80,3 +80,7 @@ status = "okay"; }; }; + +&rtc { + system-power-controller; +}; diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index c80a3e2..ade28c79 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -132,6 +132,12 @@ }; }; + emif: emif@4c000000 { + compatible = "ti,emif-am4372"; + reg = <0x4c000000 0x1000000>; + ti,hwmods = "emif"; + }; + edma: edma@49000000 { compatible = "ti,edma3"; ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2"; @@ -941,6 +947,7 @@ ti,hwmods = "dss_rfbi"; clocks = <&disp_clk>; clock-names = "fck"; + status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index a42cc37..a63bf78 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -605,6 +605,10 @@ phy-supply = <&ldousb_reg>; }; +&usb2_phy2 { + phy-supply = <&ldousb_reg>; +}; + &usb1 { dr_mode = "host"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/atlas7.dtsi b/arch/arm/boot/dts/atlas7.dtsi index 5dfd3a4..3e21311 100644 --- a/arch/arm/boot/dts/atlas7.dtsi +++ b/arch/arm/boot/dts/atlas7.dtsi @@ -135,6 +135,1025 @@ compatible = "sirf,atlas7-ioc"; reg = <0x18880000 0x1000>, <0x10E40000 0x1000>; + + audio_ac97_pmx: audio_ac97@0 { + audio_ac97 { + groups = "audio_ac97_grp"; + function = "audio_ac97"; + }; + }; + + audio_func_dbg_pmx: audio_func_dbg@0 { + audio_func_dbg { + groups = "audio_func_dbg_grp"; + function = "audio_func_dbg"; + }; + }; + + audio_i2s_pmx: audio_i2s@0 { + audio_i2s { + groups = "audio_i2s_grp"; + function = "audio_i2s"; + }; + }; + + audio_i2s_2ch_pmx: audio_i2s_2ch@0 { + audio_i2s_2ch { + groups = "audio_i2s_2ch_grp"; + function = "audio_i2s_2ch"; + }; + }; + + audio_i2s_extclk_pmx: audio_i2s_extclk@0 { + audio_i2s_extclk { + groups = "audio_i2s_extclk_grp"; + function = "audio_i2s_extclk"; + }; + }; + + audio_uart0_pmx: audio_uart0@0 { + audio_uart0 { + groups = "audio_uart0_grp"; + function = "audio_uart0"; + }; + }; + + audio_uart1_pmx: audio_uart1@0 { + audio_uart1 { + groups = "audio_uart1_grp"; + function = "audio_uart1"; + }; + }; + + audio_uart2_pmx0: audio_uart2@0 { + audio_uart2_0 { + groups = "audio_uart2_grp0"; + function = "audio_uart2_m0"; + }; + }; + + audio_uart2_pmx1: audio_uart2@1 { + audio_uart2_1 { + groups = "audio_uart2_grp1"; + function = "audio_uart2_m1"; + }; + }; + + c_can_trnsvr_pmx: c_can_trnsvr@0 { + c_can_trnsvr { + groups = "c_can_trnsvr_grp"; + function = "c_can_trnsvr"; + }; + }; + + c0_can_pmx0: c0_can@0 { + c0_can_0 { + groups = "c0_can_grp0"; + function = "c0_can_m0"; + }; + }; + + c0_can_pmx1: c0_can@1 { + c0_can_1 { + groups = "c0_can_grp1"; + function = "c0_can_m1"; + }; + }; + + c1_can_pmx0: c1_can@0 { + c1_can_0 { + groups = "c1_can_grp0"; + function = "c1_can_m0"; + }; + }; + + c1_can_pmx1: c1_can@1 { + c1_can_1 { + groups = "c1_can_grp1"; + function = "c1_can_m1"; + }; + }; + + c1_can_pmx2: c1_can@2 { + c1_can_2 { + groups = "c1_can_grp2"; + function = "c1_can_m2"; + }; + }; + + ca_audio_lpc_pmx: ca_audio_lpc@0 { + ca_audio_lpc { + groups = "ca_audio_lpc_grp"; + function = "ca_audio_lpc"; + }; + }; + + ca_bt_lpc_pmx: ca_bt_lpc@0 { + ca_bt_lpc { + groups = "ca_bt_lpc_grp"; + function = "ca_bt_lpc"; + }; + }; + + ca_coex_pmx: ca_coex@0 { + ca_coex { + groups = "ca_coex_grp"; + function = "ca_coex"; + }; + }; + + ca_curator_lpc_pmx: ca_curator_lpc@0 { + ca_curator_lpc { + groups = "ca_curator_lpc_grp"; + function = "ca_curator_lpc"; + }; + }; + + ca_pcm_debug_pmx: ca_pcm_debug@0 { + ca_pcm_debug { + groups = "ca_pcm_debug_grp"; + function = "ca_pcm_debug"; + }; + }; + + ca_pio_pmx: ca_pio@0 { + ca_pio { + groups = "ca_pio_grp"; + function = "ca_pio"; + }; + }; + + ca_sdio_debug_pmx: ca_sdio_debug@0 { + ca_sdio_debug { + groups = "ca_sdio_debug_grp"; + function = "ca_sdio_debug"; + }; + }; + + ca_spi_pmx: ca_spi@0 { + ca_spi { + groups = "ca_spi_grp"; + function = "ca_spi"; + }; + }; + + ca_trb_pmx: ca_trb@0 { + ca_trb { + groups = "ca_trb_grp"; + function = "ca_trb"; + }; + }; + + ca_uart_debug_pmx: ca_uart_debug@0 { + ca_uart_debug { + groups = "ca_uart_debug_grp"; + function = "ca_uart_debug"; + }; + }; + + clkc_pmx0: clkc@0 { + clkc_0 { + groups = "clkc_grp0"; + function = "clkc_m0"; + }; + }; + + clkc_pmx1: clkc@1 { + clkc_1 { + groups = "clkc_grp1"; + function = "clkc_m1"; + }; + }; + + gn_gnss_i2c_pmx: gn_gnss_i2c@0 { + gn_gnss_i2c { + groups = "gn_gnss_i2c_grp"; + function = "gn_gnss_i2c"; + }; + }; + + gn_gnss_uart_nopause_pmx: gn_gnss_uart_nopause@0 { + gn_gnss_uart_nopause { + groups = "gn_gnss_uart_nopause_grp"; + function = "gn_gnss_uart_nopause"; + }; + }; + + gn_gnss_uart_pmx: gn_gnss_uart@0 { + gn_gnss_uart { + groups = "gn_gnss_uart_grp"; + function = "gn_gnss_uart"; + }; + }; + + gn_trg_spi_pmx0: gn_trg_spi@0 { + gn_trg_spi_0 { + groups = "gn_trg_spi_grp0"; + function = "gn_trg_spi_m0"; + }; + }; + + gn_trg_spi_pmx1: gn_trg_spi@1 { + gn_trg_spi_1 { + groups = "gn_trg_spi_grp1"; + function = "gn_trg_spi_m1"; + }; + }; + + cvbs_dbg_pmx: cvbs_dbg@0 { + cvbs_dbg { + groups = "cvbs_dbg_grp"; + function = "cvbs_dbg"; + }; + }; + + cvbs_dbg_test_pmx0: cvbs_dbg_test@0 { + cvbs_dbg_test_0 { + groups = "cvbs_dbg_test_grp0"; + function = "cvbs_dbg_test_m0"; + }; + }; + + cvbs_dbg_test_pmx1: cvbs_dbg_test@1 { + cvbs_dbg_test_1 { + groups = "cvbs_dbg_test_grp1"; + function = "cvbs_dbg_test_m1"; + }; + }; + + cvbs_dbg_test_pmx2: cvbs_dbg_test@2 { + cvbs_dbg_test_2 { + groups = "cvbs_dbg_test_grp2"; + function = "cvbs_dbg_test_m2"; + }; + }; + + cvbs_dbg_test_pmx3: cvbs_dbg_test@3 { + cvbs_dbg_test_3 { + groups = "cvbs_dbg_test_grp3"; + function = "cvbs_dbg_test_m3"; + }; + }; + + cvbs_dbg_test_pmx4: cvbs_dbg_test@4 { + cvbs_dbg_test_4 { + groups = "cvbs_dbg_test_grp4"; + function = "cvbs_dbg_test_m4"; + }; + }; + + cvbs_dbg_test_pmx5: cvbs_dbg_test@5 { + cvbs_dbg_test_5 { + groups = "cvbs_dbg_test_grp5"; + function = "cvbs_dbg_test_m5"; + }; + }; + + cvbs_dbg_test_pmx6: cvbs_dbg_test@6 { + cvbs_dbg_test_6 { + groups = "cvbs_dbg_test_grp6"; + function = "cvbs_dbg_test_m6"; + }; + }; + + cvbs_dbg_test_pmx7: cvbs_dbg_test@7 { + cvbs_dbg_test_7 { + groups = "cvbs_dbg_test_grp7"; + function = "cvbs_dbg_test_m7"; + }; + }; + + cvbs_dbg_test_pmx8: cvbs_dbg_test@8 { + cvbs_dbg_test_8 { + groups = "cvbs_dbg_test_grp8"; + function = "cvbs_dbg_test_m8"; + }; + }; + + cvbs_dbg_test_pmx9: cvbs_dbg_test@9 { + cvbs_dbg_test_9 { + groups = "cvbs_dbg_test_grp9"; + function = "cvbs_dbg_test_m9"; + }; + }; + + cvbs_dbg_test_pmx10: cvbs_dbg_test@10 { + cvbs_dbg_test_10 { + groups = "cvbs_dbg_test_grp10"; + function = "cvbs_dbg_test_m10"; + }; + }; + + cvbs_dbg_test_pmx11: cvbs_dbg_test@11 { + cvbs_dbg_test_11 { + groups = "cvbs_dbg_test_grp11"; + function = "cvbs_dbg_test_m11"; + }; + }; + + cvbs_dbg_test_pmx12: cvbs_dbg_test@12 { + cvbs_dbg_test_12 { + groups = "cvbs_dbg_test_grp12"; + function = "cvbs_dbg_test_m12"; + }; + }; + + cvbs_dbg_test_pmx13: cvbs_dbg_test@13 { + cvbs_dbg_test_13 { + groups = "cvbs_dbg_test_grp13"; + function = "cvbs_dbg_test_m13"; + }; + }; + + cvbs_dbg_test_pmx14: cvbs_dbg_test@14 { + cvbs_dbg_test_14 { + groups = "cvbs_dbg_test_grp14"; + function = "cvbs_dbg_test_m14"; + }; + }; + + cvbs_dbg_test_pmx15: cvbs_dbg_test@15 { + cvbs_dbg_test_15 { + groups = "cvbs_dbg_test_grp15"; + function = "cvbs_dbg_test_m15"; + }; + }; + + gn_gnss_power_pmx: gn_gnss_power@0 { + gn_gnss_power { + groups = "gn_gnss_power_grp"; + function = "gn_gnss_power"; + }; + }; + + gn_gnss_sw_status_pmx: gn_gnss_sw_status@0 { + gn_gnss_sw_status { + groups = "gn_gnss_sw_status_grp"; + function = "gn_gnss_sw_status"; + }; + }; + + gn_gnss_eclk_pmx: gn_gnss_eclk@0 { + gn_gnss_eclk { + groups = "gn_gnss_eclk_grp"; + function = "gn_gnss_eclk"; + }; + }; + + gn_gnss_irq1_pmx0: gn_gnss_irq1@0 { + gn_gnss_irq1_0 { + groups = "gn_gnss_irq1_grp0"; + function = "gn_gnss_irq1_m0"; + }; + }; + + gn_gnss_irq2_pmx0: gn_gnss_irq2@0 { + gn_gnss_irq2_0 { + groups = "gn_gnss_irq2_grp0"; + function = "gn_gnss_irq2_m0"; + }; + }; + + gn_gnss_tm_pmx: gn_gnss_tm@0 { + gn_gnss_tm { + groups = "gn_gnss_tm_grp"; + function = "gn_gnss_tm"; + }; + }; + + gn_gnss_tsync_pmx: gn_gnss_tsync@0 { + gn_gnss_tsync { + groups = "gn_gnss_tsync_grp"; + function = "gn_gnss_tsync"; + }; + }; + + gn_io_gnsssys_sw_cfg_pmx: gn_io_gnsssys_sw_cfg@0 { + gn_io_gnsssys_sw_cfg { + groups = "gn_io_gnsssys_sw_cfg_grp"; + function = "gn_io_gnsssys_sw_cfg"; + }; + }; + + gn_trg_pmx0: gn_trg@0 { + gn_trg_0 { + groups = "gn_trg_grp0"; + function = "gn_trg_m0"; + }; + }; + + gn_trg_pmx1: gn_trg@1 { + gn_trg_1 { + groups = "gn_trg_grp1"; + function = "gn_trg_m1"; + }; + }; + + gn_trg_shutdown_pmx0: gn_trg_shutdown@0 { + gn_trg_shutdown_0 { + groups = "gn_trg_shutdown_grp0"; + function = "gn_trg_shutdown_m0"; + }; + }; + + gn_trg_shutdown_pmx1: gn_trg_shutdown@1 { + gn_trg_shutdown_1 { + groups = "gn_trg_shutdown_grp1"; + function = "gn_trg_shutdown_m1"; + }; + }; + + gn_trg_shutdown_pmx2: gn_trg_shutdown@2 { + gn_trg_shutdown_2 { + groups = "gn_trg_shutdown_grp2"; + function = "gn_trg_shutdown_m2"; + }; + }; + + gn_trg_shutdown_pmx3: gn_trg_shutdown@3 { + gn_trg_shutdown_3 { + groups = "gn_trg_shutdown_grp3"; + function = "gn_trg_shutdown_m3"; + }; + }; + + i2c0_pmx: i2c0@0 { + i2c0 { + groups = "i2c0_grp"; + function = "i2c0"; + }; + }; + + i2c1_pmx: i2c1@0 { + i2c1 { + groups = "i2c1_grp"; + function = "i2c1"; + }; + }; + + jtag_pmx0: jtag@0 { + jtag_0 { + groups = "jtag_grp0"; + function = "jtag_m0"; + }; + }; + + ks_kas_spi_pmx0: ks_kas_spi@0 { + ks_kas_spi_0 { + groups = "ks_kas_spi_grp0"; + function = "ks_kas_spi_m0"; + }; + }; + + ld_ldd_pmx: ld_ldd@0 { + ld_ldd { + groups = "ld_ldd_grp"; + function = "ld_ldd"; + }; + }; + + ld_ldd_16bit_pmx: ld_ldd_16bit@0 { + ld_ldd_16bit { + groups = "ld_ldd_16bit_grp"; + function = "ld_ldd_16bit"; + }; + }; + + ld_ldd_fck_pmx: ld_ldd_fck@0 { + ld_ldd_fck { + groups = "ld_ldd_fck_grp"; + function = "ld_ldd_fck"; + }; + }; + + ld_ldd_lck_pmx: ld_ldd_lck@0 { + ld_ldd_lck { + groups = "ld_ldd_lck_grp"; + function = "ld_ldd_lck"; + }; + }; + + lr_lcdrom_pmx: lr_lcdrom@0 { + lr_lcdrom { + groups = "lr_lcdrom_grp"; + function = "lr_lcdrom"; + }; + }; + + lvds_analog_pmx: lvds_analog@0 { + lvds_analog { + groups = "lvds_analog_grp"; + function = "lvds_analog"; + }; + }; + + nd_df_pmx: nd_df@0 { + nd_df { + groups = "nd_df_grp"; + function = "nd_df"; + }; + }; + + nd_df_nowp_pmx: nd_df_nowp@0 { + nd_df_nowp { + groups = "nd_df_nowp_grp"; + function = "nd_df_nowp"; + }; + }; + + ps_pmx: ps@0 { + ps { + groups = "ps_grp"; + function = "ps"; + }; + }; + + pwc_core_on_pmx: pwc_core_on@0 { + pwc_core_on { + groups = "pwc_core_on_grp"; + function = "pwc_core_on"; + }; + }; + + pwc_ext_on_pmx: pwc_ext_on@0 { + pwc_ext_on { + groups = "pwc_ext_on_grp"; + function = "pwc_ext_on"; + }; + }; + + pwc_gpio3_clk_pmx: pwc_gpio3_clk@0 { + pwc_gpio3_clk { + groups = "pwc_gpio3_clk_grp"; + function = "pwc_gpio3_clk"; + }; + }; + + pwc_io_on_pmx: pwc_io_on@0 { + pwc_io_on { + groups = "pwc_io_on_grp"; + function = "pwc_io_on"; + }; + }; + + pwc_lowbatt_b_pmx0: pwc_lowbatt_b@0 { + pwc_lowbatt_b_0 { + groups = "pwc_lowbatt_b_grp0"; + function = "pwc_lowbatt_b_m0"; + }; + }; + + pwc_mem_on_pmx: pwc_mem_on@0 { + pwc_mem_on { + groups = "pwc_mem_on_grp"; + function = "pwc_mem_on"; + }; + }; + + pwc_on_key_b_pmx0: pwc_on_key_b@0 { + pwc_on_key_b_0 { + groups = "pwc_on_key_b_grp0"; + function = "pwc_on_key_b_m0"; + }; + }; + + pwc_wakeup_src0_pmx: pwc_wakeup_src0@0 { + pwc_wakeup_src0 { + groups = "pwc_wakeup_src0_grp"; + function = "pwc_wakeup_src0"; + }; + }; + + pwc_wakeup_src1_pmx: pwc_wakeup_src1@0 { + pwc_wakeup_src1 { + groups = "pwc_wakeup_src1_grp"; + function = "pwc_wakeup_src1"; + }; + }; + + pwc_wakeup_src2_pmx: pwc_wakeup_src2@0 { + pwc_wakeup_src2 { + groups = "pwc_wakeup_src2_grp"; + function = "pwc_wakeup_src2"; + }; + }; + + pwc_wakeup_src3_pmx: pwc_wakeup_src3@0 { + pwc_wakeup_src3 { + groups = "pwc_wakeup_src3_grp"; + function = "pwc_wakeup_src3"; + }; + }; + + pw_cko0_pmx0: pw_cko0@0 { + pw_cko0_0 { + groups = "pw_cko0_grp0"; + function = "pw_cko0_m0"; + }; + }; + + pw_cko0_pmx1: pw_cko0@1 { + pw_cko0_1 { + groups = "pw_cko0_grp1"; + function = "pw_cko0_m1"; + }; + }; + + pw_cko0_pmx2: pw_cko0@2 { + pw_cko0_2 { + groups = "pw_cko0_grp2"; + function = "pw_cko0_m2"; + }; + }; + + pw_cko1_pmx0: pw_cko1@0 { + pw_cko1_0 { + groups = "pw_cko1_grp0"; + function = "pw_cko1_m0"; + }; + }; + + pw_cko1_pmx1: pw_cko1@1 { + pw_cko1_1 { + groups = "pw_cko1_grp1"; + function = "pw_cko1_m1"; + }; + }; + + pw_i2s01_clk_pmx0: pw_i2s01_clk@0 { + pw_i2s01_clk_0 { + groups = "pw_i2s01_clk_grp0"; + function = "pw_i2s01_clk_m0"; + }; + }; + + pw_i2s01_clk_pmx1: pw_i2s01_clk@1 { + pw_i2s01_clk_1 { + groups = "pw_i2s01_clk_grp1"; + function = "pw_i2s01_clk_m1"; + }; + }; + + pw_pwm0_pmx: pw_pwm0@0 { + pw_pwm0 { + groups = "pw_pwm0_grp"; + function = "pw_pwm0"; + }; + }; + + pw_pwm1_pmx: pw_pwm1@0 { + pw_pwm1 { + groups = "pw_pwm1_grp"; + function = "pw_pwm1"; + }; + }; + + pw_pwm2_pmx0: pw_pwm2@0 { + pw_pwm2_0 { + groups = "pw_pwm2_grp0"; + function = "pw_pwm2_m0"; + }; + }; + + pw_pwm2_pmx1: pw_pwm2@1 { + pw_pwm2_1 { + groups = "pw_pwm2_grp1"; + function = "pw_pwm2_m1"; + }; + }; + + pw_pwm3_pmx0: pw_pwm3@0 { + pw_pwm3_0 { + groups = "pw_pwm3_grp0"; + function = "pw_pwm3_m0"; + }; + }; + + pw_pwm3_pmx1: pw_pwm3@1 { + pw_pwm3_1 { + groups = "pw_pwm3_grp1"; + function = "pw_pwm3_m1"; + }; + }; + + pw_pwm_cpu_vol_pmx0: pw_pwm_cpu_vol@0 { + pw_pwm_cpu_vol_0 { + groups = "pw_pwm_cpu_vol_grp0"; + function = "pw_pwm_cpu_vol_m0"; + }; + }; + + pw_pwm_cpu_vol_pmx1: pw_pwm_cpu_vol@1 { + pw_pwm_cpu_vol_1 { + groups = "pw_pwm_cpu_vol_grp1"; + function = "pw_pwm_cpu_vol_m1"; + }; + }; + + pw_backlight_pmx0: pw_backlight@0 { + pw_backlight_0 { + groups = "pw_backlight_grp0"; + function = "pw_backlight_m0"; + }; + }; + + pw_backlight_pmx1: pw_backlight@1 { + pw_backlight_1 { + groups = "pw_backlight_grp1"; + function = "pw_backlight_m1"; + }; + }; + + rg_eth_mac_pmx: rg_eth_mac@0 { + rg_eth_mac { + groups = "rg_eth_mac_grp"; + function = "rg_eth_mac"; + }; + }; + + rg_gmac_phy_intr_n_pmx: rg_gmac_phy_intr_n@0 { + rg_gmac_phy_intr_n { + groups = "rg_gmac_phy_intr_n_grp"; + function = "rg_gmac_phy_intr_n"; + }; + }; + + rg_rgmii_mac_pmx: rg_rgmii_mac@0 { + rg_rgmii_mac { + groups = "rg_rgmii_mac_grp"; + function = "rg_rgmii_mac"; + }; + }; + + rg_rgmii_phy_ref_clk_pmx0: rg_rgmii_phy_ref_clk@0 { + rg_rgmii_phy_ref_clk_0 { + groups = + "rg_rgmii_phy_ref_clk_grp0"; + function = + "rg_rgmii_phy_ref_clk_m0"; + }; + }; + + rg_rgmii_phy_ref_clk_pmx1: rg_rgmii_phy_ref_clk@1 { + rg_rgmii_phy_ref_clk_1 { + groups = + "rg_rgmii_phy_ref_clk_grp1"; + function = + "rg_rgmii_phy_ref_clk_m1"; + }; + }; + + sd0_pmx: sd0@0 { + sd0 { + groups = "sd0_grp"; + function = "sd0"; + }; + }; + + sd0_4bit_pmx: sd0_4bit@0 { + sd0_4bit { + groups = "sd0_4bit_grp"; + function = "sd0_4bit"; + }; + }; + + sd1_pmx: sd1@0 { + sd1 { + groups = "sd1_grp"; + function = "sd1"; + }; + }; + + sd1_4bit_pmx0: sd1_4bit@0 { + sd1_4bit_0 { + groups = "sd1_4bit_grp0"; + function = "sd1_4bit_m0"; + }; + }; + + sd1_4bit_pmx1: sd1_4bit@1 { + sd1_4bit_1 { + groups = "sd1_4bit_grp1"; + function = "sd1_4bit_m1"; + }; + }; + + sd2_pmx0: sd2@0 { + sd2_0 { + groups = "sd2_grp0"; + function = "sd2_m0"; + }; + }; + + sd2_no_cdb_pmx0: sd2_no_cdb@0 { + sd2_no_cdb_0 { + groups = "sd2_no_cdb_grp0"; + function = "sd2_no_cdb_m0"; + }; + }; + + sd3_pmx: sd3@0 { + sd3 { + groups = "sd3_grp"; + function = "sd3"; + }; + }; + + sd5_pmx: sd5@0 { + sd5 { + groups = "sd5_grp"; + function = "sd5"; + }; + }; + + sd6_pmx0: sd6@0 { + sd6_0 { + groups = "sd6_grp0"; + function = "sd6_m0"; + }; + }; + + sd6_pmx1: sd6@1 { + sd6_1 { + groups = "sd6_grp1"; + function = "sd6_m1"; + }; + }; + + sp0_ext_ldo_on_pmx: sp0_ext_ldo_on@0 { + sp0_ext_ldo_on { + groups = "sp0_ext_ldo_on_grp"; + function = "sp0_ext_ldo_on"; + }; + }; + + sp0_qspi_pmx: sp0_qspi@0 { + sp0_qspi { + groups = "sp0_qspi_grp"; + function = "sp0_qspi"; + }; + }; + + sp1_spi_pmx: sp1_spi@0 { + sp1_spi { + groups = "sp1_spi_grp"; + function = "sp1_spi"; + }; + }; + + tpiu_trace_pmx: tpiu_trace@0 { + tpiu_trace { + groups = "tpiu_trace_grp"; + function = "tpiu_trace"; + }; + }; + + uart0_pmx: uart0@0 { + uart0 { + groups = "uart0_grp"; + function = "uart0"; + }; + }; + + uart0_nopause_pmx: uart0_nopause@0 { + uart0_nopause { + groups = "uart0_nopause_grp"; + function = "uart0_nopause"; + }; + }; + + uart1_pmx: uart1@0 { + uart1 { + groups = "uart1_grp"; + function = "uart1"; + }; + }; + + uart2_pmx: uart2@0 { + uart2 { + groups = "uart2_grp"; + function = "uart2"; + }; + }; + + uart3_pmx0: uart3@0 { + uart3_0 { + groups = "uart3_grp0"; + function = "uart3_m0"; + }; + }; + + uart3_pmx1: uart3@1 { + uart3_1 { + groups = "uart3_grp1"; + function = "uart3_m1"; + }; + }; + + uart3_pmx2: uart3@2 { + uart3_2 { + groups = "uart3_grp2"; + function = "uart3_m2"; + }; + }; + + uart3_pmx3: uart3@3 { + uart3_3 { + groups = "uart3_grp3"; + function = "uart3_m3"; + }; + }; + + uart3_nopause_pmx0: uart3_nopause@0 { + uart3_nopause_0 { + groups = "uart3_nopause_grp0"; + function = "uart3_nopause_m0"; + }; + }; + + uart3_nopause_pmx1: uart3_nopause@1 { + uart3_nopause_1 { + groups = "uart3_nopause_grp1"; + function = "uart3_nopause_m1"; + }; + }; + + uart4_pmx0: uart4@0 { + uart4_0 { + groups = "uart4_grp0"; + function = "uart4_m0"; + }; + }; + + uart4_pmx1: uart4@1 { + uart4_1 { + groups = "uart4_grp1"; + function = "uart4_m1"; + }; + }; + + uart4_pmx2: uart4@2 { + uart4_2 { + groups = "uart4_grp2"; + function = "uart4_m2"; + }; + }; + + uart4_nopause_pmx: uart4_nopause@0 { + uart4_nopause { + groups = "uart4_nopause_grp"; + function = "uart4_nopause"; + }; + }; + + usb0_drvvbus_pmx: usb0_drvvbus@0 { + usb0_drvvbus { + groups = "usb0_drvvbus_grp"; + function = "usb0_drvvbus"; + }; + }; + + usb1_drvvbus_pmx: usb1_drvvbus@0 { + usb1_drvvbus { + groups = "usb1_drvvbus_grp"; + function = "usb1_drvvbus"; + }; + }; + + visbus_dout_pmx: visbus_dout@0 { + visbus_dout { + groups = "visbus_dout_grp"; + function = "visbus_dout"; + }; + }; + + vi_vip1_pmx: vi_vip1@0 { + vi_vip1 { + groups = "vi_vip1_grp"; + function = "vi_vip1"; + }; + }; + + vi_vip1_ext_pmx: vi_vip1_ext@0 { + vi_vip1_ext { + groups = "vi_vip1_ext_grp"; + function = "vi_vip1_ext"; + }; + }; + + vi_vip1_low8bit_pmx: vi_vip1_low8bit@0 { + vi_vip1_low8bit { + groups = "vi_vip1_low8bit_grp"; + function = "vi_vip1_low8bit"; + }; + }; + + vi_vip1_high8bit_pmx: vi_vip1_high8bit@0 { + vi_vip1_high8bit { + groups = "vi_vip1_high8bit_grp"; + function = "vi_vip1_high8bit"; + }; + }; }; pmipc { @@ -356,6 +1375,12 @@ clock-names = "gpio0_io"; gpio-controller; interrupt-controller; + + gpio-banks = <2>; + gpio-ranges = <&pinctrl 0 0 0>, + <&pinctrl 32 0 0>; + gpio-ranges-group-names = "lvds_gpio_grp", + "uart_nand_gpio_grp"; }; nand@17050000 { @@ -461,11 +1486,22 @@ #interrupt-cells = <2>; compatible = "sirf,atlas7-gpio"; reg = <0x13300000 0x1000>; - interrupts = <0 43 0>, <0 44 0>, <0 45 0>; + interrupts = <0 43 0>, <0 44 0>, + <0 45 0>, <0 46 0>; clocks = <&car 84>; clock-names = "gpio1_io"; gpio-controller; interrupt-controller; + + gpio-banks = <4>; + gpio-ranges = <&pinctrl 0 0 0>, + <&pinctrl 32 0 0>, + <&pinctrl 64 0 0>, + <&pinctrl 96 0 0>; + gpio-ranges-group-names = "gnss_gpio_grp", + "lcd_vip_gpio_grp", + "sdio_i2s_gpio_grp", + "sp_rgmii_gpio_grp"; }; sd2: sdhci@14200000 { @@ -744,6 +1780,10 @@ interrupts = <0 47 0>; gpio-controller; interrupt-controller; + + gpio-banks = <1>; + gpio-ranges = <&pinctrl 0 0 0>; + gpio-ranges-group-names = "rtc_gpio_grp"; }; rtc-iobg@18840000 { diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 107395c..17f63f7 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -150,6 +150,16 @@ interface-type = "ace"; reg = <0x5000 0x1000>; }; + + pmu@9000 { + compatible = "arm,cci-400-pmu,r0"; + reg = <0x9000 0x5000>; + interrupts = <0 105 4>, + <0 101 4>, + <0 102 4>, + <0 103 4>, + <0 104 4>; + }; }; memory-controller@7ffd0000 { @@ -187,11 +197,22 @@ <1 10 0xf08>; }; - pmu { + pmu_a15 { compatible = "arm,cortex-a15-pmu"; interrupts = <0 68 4>, <0 69 4>; - interrupt-affinity = <&cpu0>, <&cpu1>; + interrupt-affinity = <&cpu0>, + <&cpu1>; + }; + + pmu_a7 { + compatible = "arm,cortex-a7-pmu"; + interrupts = <0 128 4>, + <0 129 4>, + <0 130 4>; + interrupt-affinity = <&cpu2>, + <&cpu3>, + <&cpu4>; }; oscclk6a: oscclk6a { diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 5114b68..96dabcb 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c @@ -91,7 +91,7 @@ void it8152_init_irq(void) for (irq = IT8152_IRQ(0); irq <= IT8152_LAST_IRQ; irq++) { irq_set_chip_and_handler(irq, &it8152_irq_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } } diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index b55c362..304adea 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -138,9 +138,9 @@ static struct locomo_dev_info locomo_devices[] = { }, }; -static void locomo_handler(unsigned int irq, struct irq_desc *desc) +static void locomo_handler(unsigned int __irq, struct irq_desc *desc) { - struct locomo *lchip = irq_get_chip_data(irq); + struct locomo *lchip = irq_desc_get_chip_data(desc); int req, i; /* Acknowledge the parent IRQ */ @@ -150,6 +150,8 @@ static void locomo_handler(unsigned int irq, struct irq_desc *desc) req = locomo_readl(lchip->base + LOCOMO_ICR) & 0x0f00; if (req) { + unsigned int irq; + /* generate the next interrupt(s) */ irq = lchip->irq_base; for (i = 0; i <= 3; i++, irq++) { @@ -205,7 +207,7 @@ static void locomo_setup_irq(struct locomo *lchip) for ( ; irq <= lchip->irq_base + 3; irq++) { irq_set_chip_and_handler(irq, &locomo_chip, handle_level_irq); irq_set_chip_data(irq, lchip); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } } @@ -475,8 +477,7 @@ static void __locomo_remove(struct locomo *lchip) device_for_each_child(lchip->dev, NULL, locomo_remove_child); if (lchip->irq != NO_IRQ) { - irq_set_chained_handler(lchip->irq, NULL); - irq_set_handler_data(lchip->irq, NULL); + irq_set_chained_handler_and_data(lchip->irq, NULL, NULL); } iounmap(lchip->base); diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 93ee70d..4f29025 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -197,10 +197,11 @@ static struct sa1111_dev_info sa1111_devices[] = { * will call us again if there are more interrupts to process. */ static void -sa1111_irq_handler(unsigned int irq, struct irq_desc *desc) +sa1111_irq_handler(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq = irq_desc_get_irq(desc); unsigned int stat0, stat1, i; - struct sa1111 *sachip = irq_get_handler_data(irq); + struct sa1111 *sachip = irq_desc_get_handler_data(desc); void __iomem *mapbase = sachip->base + SA1111_INTC; stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0); @@ -486,7 +487,7 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) irq_set_chip_and_handler(irq, &sa1111_low_chip, handle_edge_irq); irq_set_chip_data(irq, sachip); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) { @@ -494,7 +495,7 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) irq_set_chip_and_handler(irq, &sa1111_high_chip, handle_edge_irq); irq_set_chip_data(irq, sachip); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } /* diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig deleted file mode 100644 index 5666e37..0000000 --- a/arch/arm/configs/armadillo800eva_defconfig +++ /dev/null @@ -1,162 +0,0 @@ -CONFIG_EXPERIMENTAL=y -CONFIG_SYSVIPC=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_UTS_NS is not set -# CONFIG_IPC_NS is not set -# CONFIG_PID_NS is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_PERF_EVENTS=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE_LEGACY=y -CONFIG_ARCH_R8A7740=y -CONFIG_MACH_ARMADILLO800EVA=y -# CONFIG_SH_TIMER_TMU is not set -CONFIG_ARM_THUMB=y -CONFIG_CACHE_L2X0=y -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y -CONFIG_PL310_ERRATA_588369=y -CONFIG_ARM_ERRATA_720789=y -CONFIG_PL310_ERRATA_727915=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_751472=y -CONFIG_PL310_ERRATA_753970=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_ARM_ERRATA_775420=y -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_FORCE_MAX_ZONEORDER=13 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ARM_APPENDED_DTB=y -CONFIG_KEXEC=y -CONFIG_VFP=y -CONFIG_NEON=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_PM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_MD=y -CONFIG_BLK_DEV_DM=y -CONFIG_NETDEVICES=y -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -CONFIG_SH_ETH=y -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_WLAN is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ST1232=y -# CONFIG_SERIO is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=9 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_GPIO=y -CONFIG_I2C_SH_MOBILE=y -# CONFIG_HWMON is not set -CONFIG_REGULATOR=y -CONFIG_REGULATOR_GPIO=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_DEV=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_MT9T112=y -CONFIG_VIDEO_SH_MOBILE_CEU=y -CONFIG_FB=y -CONFIG_FB_SH_MOBILE_LCDC=y -CONFIG_FB_SH_MOBILE_HDMI=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_BACKLIGHT_PWM=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_ARM is not set -CONFIG_SND_SOC_SH4_FSI=y -# CONFIG_HID_SUPPORT is not set -CONFIG_USB=y -CONFIG_USB_RENESAS_USBHS=y -CONFIG_USB_GADGET=y -CONFIG_USB_RENESAS_USBHS_UDC=y -CONFIG_USB_ETH=m -CONFIG_MMC=y -CONFIG_MMC_SDHI=y -CONFIG_MMC_SH_MMCIF=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_S35390A=y -CONFIG_DMADEVICES=y -CONFIG_SH_DMAE=y -CONFIG_UIO=y -CONFIG_UIO_PDRV_GENIRQ=y -CONFIG_PWM=y -CONFIG_PWM_RENESAS_TPU=y -# CONFIG_DNOTIFY is not set -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFS_V4_1=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_ARM_UNWIND is not set -CONFIG_CRYPTO=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_ANSI_CPRNG=y -CONFIG_XZ_DEC=y diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig deleted file mode 100644 index 23e8d14..0000000 --- a/arch/arm/configs/kzm9g_defconfig +++ /dev/null @@ -1,154 +0,0 @@ -# CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_EXPERIMENTAL=y -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_SYSVIPC=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -CONFIG_NAMESPACES=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_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_EMBEDDED=y -CONFIG_PERF_EVENTS=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE_LEGACY=y -CONFIG_ARCH_SH73A0=y -CONFIG_MACH_KZM9G=y -CONFIG_MEMORY_START=0x41000000 -CONFIG_MEMORY_SIZE=0x1f000000 -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_SMP=y -CONFIG_SCHED_MC=y -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_HIGHMEM=y -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ARM_APPENDED_DTB=y -CONFIG_KEXEC=y -CONFIG_VFP=y -CONFIG_NEON=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_PM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -CONFIG_IRDA=y -CONFIG_SH_IRDA=y -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_NETDEVICES=y -CONFIG_SMSC911X=y -# CONFIG_WLAN is not set -CONFIG_INPUT_SPARSEKMAP=y -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ST1232=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_ADXL34X=y -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=9 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_SH_MOBILE=y -CONFIG_GPIO_PCF857X=y -# CONFIG_HWMON is not set -CONFIG_MFD_AS3711=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_AS3711=y -CONFIG_FB=y -CONFIG_FB_SH_MOBILE_LCDC=y -CONFIG_BACKLIGHT_AS3711=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_LOGO=y -CONFIG_FB_SH_MOBILE_MERAM=y -CONFIG_SOUND=y -CONFIG_SND=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_ARM is not set -# CONFIG_SND_USB is not set -CONFIG_SND_SOC=y -CONFIG_SND_SOC_SH4_FSI=y -# CONFIG_HID_SUPPORT is not set -CONFIG_USB=y -CONFIG_USB_R8A66597_HCD=y -CONFIG_USB_RENESAS_USBHS=y -CONFIG_USB_STORAGE=y -CONFIG_USB_GADGET=y -CONFIG_USB_RENESAS_USBHS_UDC=y -CONFIG_USB_ETH=m -CONFIG_USB_MASS_STORAGE=m -CONFIG_MMC=y -# CONFIG_MMC_BLOCK_BOUNCE is not set -CONFIG_MMC_SDHI=y -CONFIG_MMC_SH_MMCIF=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_RS5C372=y -CONFIG_DMADEVICES=y -CONFIG_SH_DMAE=y -CONFIG_ASYNC_TX_DMA=y -CONFIG_STAGING=y -CONFIG_IIO=y -CONFIG_AK8975=y -# CONFIG_DNOTIFY is not set -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFS_V4_1=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_FTRACE is not set -# CONFIG_ARM_UNWIND is not set -CONFIG_CRYPTO=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_DES=y -CONFIG_CRC16=y diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6d83a1b..5fd8df6 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -353,7 +353,6 @@ CONFIG_POWER_RESET_AS3722=y CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_KEYSTONE=y -CONFIG_POWER_RESET_SUN6I=y CONFIG_POWER_RESET_RMOBILE=y CONFIG_SENSORS_LM90=y CONFIG_SENSORS_LM95245=y diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 8ecba00..7ebc346b 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -2,6 +2,7 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BLK_DEV_INITRD=y CONFIG_PERF_EVENTS=y +CONFIG_MODULES=y CONFIG_ARCH_SUNXI=y CONFIG_SMP=y CONFIG_NR_CPUS=8 @@ -77,7 +78,6 @@ CONFIG_SPI_SUN6I=y CONFIG_GPIO_SYSFS=y CONFIG_POWER_SUPPLY=y CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SUN6I=y CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y CONFIG_WATCHDOG=y @@ -87,6 +87,10 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_AXP20X=y CONFIG_REGULATOR_GPIO=y +CONFIG_FB=y +CONFIG_FB_SIMPLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 1c3938f..4859820 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -140,16 +140,11 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) * The _caller variety takes a __builtin_return_address(0) value for * /proc/vmalloc to use - and should only be used in non-inline functions. */ -extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long, - size_t, unsigned int, void *); extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int, void *); - extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); -extern void __iomem *__arm_ioremap(phys_addr_t, size_t, unsigned int); extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached); extern void __iounmap(volatile void __iomem *addr); -extern void __arm_iounmap(volatile void __iomem *addr); extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); @@ -321,21 +316,24 @@ extern void _memset_io(volatile void __iomem *, int, size_t); static inline void memset_io(volatile void __iomem *dst, unsigned c, size_t count) { - memset((void __force *)dst, c, count); + extern void mmioset(void *, unsigned int, size_t); + mmioset((void __force *)dst, c, count); } #define memset_io(dst,c,count) memset_io(dst,c,count) static inline void memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { - memcpy(to, (const void __force *)from, count); + extern void mmiocpy(void *, const void *, size_t); + mmiocpy(to, (const void __force *)from, count); } #define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count) static inline void memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { - memcpy((void __force *)to, from, count); + extern void mmiocpy(void *, const void *, size_t); + mmiocpy((void __force *)to, from, count); } #define memcpy_toio(to,from,count) memcpy_toio(to,from,count) @@ -348,18 +346,61 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, #endif /* readl */ /* - * ioremap and friends. + * ioremap() and friends. + * + * ioremap() takes a resource address, and size. Due to the ARM memory + * types, it is important to use the correct ioremap() function as each + * mapping has specific properties. + * + * Function Memory type Cacheability Cache hint + * ioremap() Device n/a n/a + * ioremap_nocache() Device n/a n/a + * ioremap_cache() Normal Writeback Read allocate + * ioremap_wc() Normal Non-cacheable n/a + * ioremap_wt() Normal Non-cacheable n/a + * + * All device mappings have the following properties: + * - no access speculation + * - no repetition (eg, on return from an exception) + * - number, order and size of accesses are maintained + * - unaligned accesses are "unpredictable" + * - writes may be delayed before they hit the endpoint device * - * ioremap takes a PCI memory address, as specified in - * Documentation/io-mapping.txt. + * ioremap_nocache() is the same as ioremap() as there are too many device + * drivers using this for device registers, and documentation which tells + * people to use it for such for this to be any different. This is not a + * safe fallback for memory-like mappings, or memory regions where the + * compiler may generate unaligned accesses - eg, via inlining its own + * memcpy. * + * All normal memory mappings have the following properties: + * - reads can be repeated with no side effects + * - repeated reads return the last value written + * - reads can fetch additional locations without side effects + * - writes can be repeated (in certain cases) with no side effects + * - writes can be merged before accessing the target + * - unaligned accesses can be supported + * - ordering is not guaranteed without explicit dependencies or barrier + * instructions + * - writes may be delayed before they hit the endpoint memory + * + * The cache hint is only a performance hint: CPUs may alias these hints. + * Eg, a CPU not implementing read allocate but implementing write allocate + * will provide a write allocate mapping instead. */ -#define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -#define ioremap_nocache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -#define ioremap_cache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) -#define ioremap_wc(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_WC) -#define ioremap_wt(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -#define iounmap __arm_iounmap +void __iomem *ioremap(resource_size_t res_cookie, size_t size); +#define ioremap ioremap +#define ioremap_nocache ioremap + +void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size); +#define ioremap_cache ioremap_cache + +void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size); +#define ioremap_wc ioremap_wc +#define ioremap_wt ioremap_wc + +void iounmap(volatile void __iomem *iomem_cookie); +#define iounmap iounmap /* * io{read,write}{16,32}be() macros diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 3a72d69..6f225ac 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -275,7 +275,7 @@ static inline void *phys_to_virt(phys_addr_t x) */ #define __pa(x) __virt_to_phys((unsigned long)(x)) #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) -#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) +#define pfn_to_kaddr(pfn) __va((phys_addr_t)(pfn) << PAGE_SHIFT) extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x); diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index bfd662e..aeddd28 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h @@ -129,7 +129,36 @@ /* * These are the memory types, defined to be compatible with - * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB + * pre-ARMv6 CPUs cacheable and bufferable bits: n/a,n/a,C,B + * ARMv6+ without TEX remapping, they are a table index. + * ARMv6+ with TEX remapping, they correspond to n/a,TEX(0),C,B + * + * MT type Pre-ARMv6 ARMv6+ type / cacheable status + * UNCACHED Uncached Strongly ordered + * BUFFERABLE Bufferable Normal memory / non-cacheable + * WRITETHROUGH Writethrough Normal memory / write through + * WRITEBACK Writeback Normal memory / write back, read alloc + * MINICACHE Minicache N/A + * WRITEALLOC Writeback Normal memory / write back, write alloc + * DEV_SHARED Uncached Device memory (shared) + * DEV_NONSHARED Uncached Device memory (non-shared) + * DEV_WC Bufferable Normal memory / non-cacheable + * DEV_CACHED Writeback Normal memory / write back, read alloc + * VECTORS Variable Normal memory / variable + * + * All normal memory mappings have the following properties: + * - reads can be repeated with no side effects + * - repeated reads return the last value written + * - reads can fetch additional locations without side effects + * - writes can be repeated (in certain cases) with no side effects + * - writes can be merged before accessing the target + * - unaligned accesses can be supported + * + * All device mappings have the following properties: + * - no access speculation + * - no repetition (eg, on return from an exception) + * - number, order and size of accesses are maintained + * - unaligned accesses are "unpredictable" */ #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index a88671c..5e5a51a 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -50,6 +50,9 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); +void mmioset(void *, unsigned int, size_t); +void mmiocpy(void *, const void *, size_t); + /* platform dependent support */ EXPORT_SYMBOL(arm_delay_ops); @@ -88,6 +91,9 @@ EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(__memzero); +EXPORT_SYMBOL(mmioset); +EXPORT_SYMBOL(mmiocpy); + #ifdef CONFIG_MMU EXPORT_SYMBOL(copy_page); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 7dac308..cb4fb1e 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -410,7 +410,7 @@ ENDPROC(__fiq_abt) zero_fp .if \trace -#ifdef CONFIG_IRQSOFF_TRACER +#ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off #endif ct_user_exit save = 0 diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 350f188..baf8ede 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -140,7 +140,7 @@ int __init arch_probe_nr_irqs(void) static bool migrate_one_irq(struct irq_desc *desc) { struct irq_data *d = irq_desc_get_irq_data(desc); - const struct cpumask *affinity = d->affinity; + const struct cpumask *affinity = irq_data_get_affinity_mask(d); struct irq_chip *c; bool ret = false; @@ -160,7 +160,7 @@ static bool migrate_one_irq(struct irq_desc *desc) if (!c->irq_set_affinity) pr_debug("IRQ%u: unable to set affinity\n", d->irq); else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret) - cpumask_copy(d->affinity, affinity); + cpumask_copy(irq_data_get_affinity_mask(d), affinity); return ret; } diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c index f90fdf4..2e60243 100644 --- a/arch/arm/kernel/psci.c +++ b/arch/arm/kernel/psci.c @@ -278,7 +278,7 @@ out_put_node: return err; } -static const struct of_device_id psci_of_match[] __initconst = { +static const struct of_device_id const psci_of_match[] __initconst = { { .compatible = "arm,psci", .data = psci_0_1_init}, { .compatible = "arm,psci-0.2", .data = psci_0_2_init}, {}, diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 90dfbed..3d6b782 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -578,7 +578,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) struct pt_regs *old_regs = set_irq_regs(regs); if ((unsigned)ipinr < NR_IPI) { - trace_ipi_entry(ipi_types[ipinr]); + trace_ipi_entry_rcuidle(ipi_types[ipinr]); __inc_irq_stat(cpu, ipi_irqs[ipinr]); } @@ -637,7 +637,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) } if ((unsigned)ipinr < NR_IPI) - trace_ipi_exit(ipi_types[ipinr]); + trace_ipi_exit_rcuidle(ipi_types[ipinr]); set_irq_regs(old_regs); } diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 172c6a05..e9035cd 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -36,29 +36,30 @@ static DEFINE_PER_CPU(bool, percpu_setup_called); static struct clock_event_device __percpu *twd_evt; static int twd_ppi; -static void twd_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) +static int twd_shutdown(struct clock_event_device *clk) { - unsigned long ctrl; - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE - | TWD_TIMER_CONTROL_PERIODIC; - writel_relaxed(DIV_ROUND_CLOSEST(twd_timer_rate, HZ), - twd_base + TWD_TIMER_LOAD); - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set, and timer enabled in 'next_event' hook */ - ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT; - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - default: - ctrl = 0; - } + writel_relaxed(0, twd_base + TWD_TIMER_CONTROL); + return 0; +} +static int twd_set_oneshot(struct clock_event_device *clk) +{ + /* period set, and timer enabled in 'next_event' hook */ + writel_relaxed(TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT, + twd_base + TWD_TIMER_CONTROL); + return 0; +} + +static int twd_set_periodic(struct clock_event_device *clk) +{ + unsigned long ctrl = TWD_TIMER_CONTROL_ENABLE | + TWD_TIMER_CONTROL_IT_ENABLE | + TWD_TIMER_CONTROL_PERIODIC; + + writel_relaxed(DIV_ROUND_CLOSEST(twd_timer_rate, HZ), + twd_base + TWD_TIMER_LOAD); writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); + return 0; } static int twd_set_next_event(unsigned long evt, @@ -94,7 +95,7 @@ static void twd_timer_stop(void) { struct clock_event_device *clk = raw_cpu_ptr(twd_evt); - twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); + twd_shutdown(clk); disable_percpu_irq(clk->irq); } @@ -296,7 +297,10 @@ static void twd_timer_setup(void) clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->rating = 350; - clk->set_mode = twd_set_mode; + clk->set_state_shutdown = twd_shutdown; + clk->set_state_periodic = twd_set_periodic; + clk->set_state_oneshot = twd_set_oneshot; + clk->tick_resume = twd_shutdown; clk->set_next_event = twd_set_next_event; clk->irq = twd_ppi; clk->cpumask = cpumask_of(cpu); diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index 7797e81..64111bd 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S @@ -61,8 +61,10 @@ /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ +ENTRY(mmiocpy) ENTRY(memcpy) #include "copy_template.S" ENDPROC(memcpy) +ENDPROC(mmiocpy) diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index a4ee97b..3c65e3b 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -16,6 +16,7 @@ .text .align 5 +ENTRY(mmioset) ENTRY(memset) UNWIND( .fnstart ) ands r3, r0, #3 @ 1 unaligned? @@ -133,3 +134,4 @@ UNWIND( .fnstart ) b 1b UNWIND( .fnend ) ENDPROC(memset) +ENDPROC(mmioset) diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index eaf58f8..82eec33 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -38,7 +38,7 @@ static void __init at91rm9200_dt_device_init(void) at91rm9200_pm_init(); } -static const char *at91rm9200_dt_board_compat[] __initconst = { +static const char *const at91rm9200_dt_board_compat[] __initconst = { "atmel,at91rm9200", NULL }; diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c index e47a209..7eb64f7 100644 --- a/arch/arm/mach-at91/at91sam9.c +++ b/arch/arm/mach-at91/at91sam9.c @@ -72,7 +72,7 @@ static void __init at91sam9_dt_device_init(void) at91sam9260_pm_init(); } -static const char *at91_dt_board_compat[] __initconst = { +static const char *const at91_dt_board_compat[] __initconst = { "atmel,at91sam9", NULL }; @@ -89,7 +89,7 @@ static void __init at91sam9g45_dt_device_init(void) at91sam9g45_pm_init(); } -static const char *at91sam9g45_board_compat[] __initconst = { +static const char *const at91sam9g45_board_compat[] __initconst = { "atmel,at91sam9g45", NULL }; @@ -106,7 +106,7 @@ static void __init at91sam9x5_dt_device_init(void) at91sam9x5_pm_init(); } -static const char *at91sam9x5_board_compat[] __initconst = { +static const char *const at91sam9x5_board_compat[] __initconst = { "atmel,at91sam9x5", "atmel,at91sam9n12", NULL diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index e24df77..265ffeb 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -311,7 +311,7 @@ static void at91sam9_sdram_standby(void) at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); } -static const struct of_device_id ramc_ids[] __initconst = { +static const struct of_device_id const ramc_ids[] __initconst = { { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c index 41d829d..8fc4763 100644 --- a/arch/arm/mach-at91/sama5.c +++ b/arch/arm/mach-at91/sama5.c @@ -52,7 +52,7 @@ static void __init sama5_dt_device_init(void) at91sam9x5_pm_init(); } -static const char *sama5_dt_board_compat[] __initconst = { +static const char *const sama5_dt_board_compat[] __initconst = { "atmel,sama5", NULL }; @@ -63,7 +63,7 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5") .dt_compat = sama5_dt_board_compat, MACHINE_END -static const char *sama5_alt_dt_board_compat[] __initconst = { +static const char *const sama5_alt_dt_board_compat[] __initconst = { "atmel,sama5d4", NULL }; diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 4fb0da4..1780a3f 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -39,10 +39,8 @@ obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o # BCM63XXx ifeq ($(CONFIG_ARCH_BCM_63XX),y) -CFLAGS_bcm63xx_headsmp.o += -march=armv7-a obj-y += bcm63xx.o -obj-$(CONFIG_SMP) += bcm63xx_smp.o bcm63xx_headsmp.o \ - bcm63xx_pmb.o +obj-$(CONFIG_SMP) += bcm63xx_smp.o bcm63xx_pmb.o endif ifeq ($(CONFIG_ARCH_BRCMSTB),y) diff --git a/arch/arm/mach-bcm/bcm63xx_headsmp.S b/arch/arm/mach-bcm/bcm63xx_headsmp.S deleted file mode 100644 index c7af397..0000000 --- a/arch/arm/mach-bcm/bcm63xx_headsmp.S +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2015, Broadcom Corporation - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/assembler.h> - -ENTRY(bcm63138_secondary_startup) - ARM_BE8(setend be) - /* - * L1 cache does have unpredictable contents at power-up clean its - * contents without flushing - */ - bl v7_invalidate_l1 - nop - - b secondary_startup -ENDPROC(bcm63138_secondary_startup) diff --git a/arch/arm/mach-bcm/bcm63xx_smp.c b/arch/arm/mach-bcm/bcm63xx_smp.c index 3f014f1..19be904 100644 --- a/arch/arm/mach-bcm/bcm63xx_smp.c +++ b/arch/arm/mach-bcm/bcm63xx_smp.c @@ -127,7 +127,7 @@ static int bcm63138_smp_boot_secondary(unsigned int cpu, } /* Locate the secondary CPU node */ - dn = of_get_cpu_node(cpu_logical_map(cpu), NULL); + dn = of_get_cpu_node(cpu, NULL); if (!dn) { pr_err("SMP: failed to locate secondary CPU%d node\n", cpu); ret = -ENODEV; @@ -135,7 +135,7 @@ static int bcm63138_smp_boot_secondary(unsigned int cpu, } /* Write the secondary init routine to the BootLUT reset vector */ - val = virt_to_phys(bcm63138_secondary_startup); + val = virt_to_phys(secondary_startup); writel_relaxed(val, bootlut_base + BOOTLUT_RESET_VECT); /* Power up the core, will jump straight to its reset vector when we diff --git a/arch/arm/mach-bcm/bcm63xx_smp.h b/arch/arm/mach-bcm/bcm63xx_smp.h index 50b7604..9c6d50e 100644 --- a/arch/arm/mach-bcm/bcm63xx_smp.h +++ b/arch/arm/mach-bcm/bcm63xx_smp.h @@ -3,7 +3,6 @@ struct device_node; -extern void bcm63138_secondary_startup(void); extern int bcm63xx_pmb_power_on_cpu(struct device_node *dn); #endif /* __BCM63XX_SMP_H */ diff --git a/arch/arm/mach-bcm/bcm_5301x.c b/arch/arm/mach-bcm/bcm_5301x.c index 7aef927..5478fe6 100644 --- a/arch/arm/mach-bcm/bcm_5301x.c +++ b/arch/arm/mach-bcm/bcm_5301x.c @@ -44,7 +44,7 @@ static void __init bcm5301x_init_early(void) "imprecise external abort"); } -static const char __initconst *bcm5301x_dt_compat[] = { +static const char *const bcm5301x_dt_compat[] __initconst = { "brcm,bcm4708", NULL, }; diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index a55a7ec..cf3f865 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -33,7 +33,7 @@ struct bcm_kona_smc_data { unsigned result; }; -static const struct of_device_id bcm_kona_smc_ids[] __initconst = { +static const struct of_device_id const bcm_kona_smc_ids[] __initconst = { {.compatible = "brcm,kona-smc"}, {.compatible = "bcm,kona-smc"}, /* deprecated name */ {}, diff --git a/arch/arm/mach-clps711x/board-autcpu12.c b/arch/arm/mach-clps711x/board-autcpu12.c index 45abf6b..c3d9642 100644 --- a/arch/arm/mach-clps711x/board-autcpu12.c +++ b/arch/arm/mach-clps711x/board-autcpu12.c @@ -160,7 +160,7 @@ static struct platform_device autcpu12_mmgpio_pdev __initdata = { }, }; -static const struct gpio autcpu12_gpios[] __initconst = { +static const struct gpio const autcpu12_gpios[] __initconst = { { AUTCPU12_DPOT_CS, GPIOF_OUT_INIT_HIGH, "DPOT CS" }, { AUTCPU12_DPOT_CLK, GPIOF_OUT_INIT_LOW, "DPOT CLK" }, { AUTCPU12_DPOT_UD, GPIOF_OUT_INIT_LOW, "DPOT UD" }, diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 4e9837d..9b1dc22 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -113,30 +113,33 @@ void cns3xxx_power_off(void) */ static void __iomem *cns3xxx_tmr1; -static void cns3xxx_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) +static int cns3xxx_shutdown(struct clock_event_device *clk) +{ + writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + return 0; +} + +static int cns3xxx_set_oneshot(struct clock_event_device *clk) +{ + unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + + /* period set, and timer enabled in 'next_event' hook */ + ctrl |= (1 << 2) | (1 << 9); + writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + return 0; +} + +static int cns3xxx_set_periodic(struct clock_event_device *clk) { unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); int pclk = cns3xxx_cpu_clock() / 8; int reload; - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - reload = pclk * 20 / (3 * HZ) * 0x25000; - writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET); - ctrl |= (1 << 0) | (1 << 2) | (1 << 9); - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set, and timer enabled in 'next_event' hook */ - ctrl |= (1 << 2) | (1 << 9); - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - default: - ctrl = 0; - } - + reload = pclk * 20 / (3 * HZ) * 0x25000; + writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET); + ctrl |= (1 << 0) | (1 << 2) | (1 << 9); writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + return 0; } static int cns3xxx_timer_set_next_event(unsigned long evt, @@ -151,12 +154,16 @@ static int cns3xxx_timer_set_next_event(unsigned long evt, } static struct clock_event_device cns3xxx_tmr1_clockevent = { - .name = "cns3xxx timer1", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = cns3xxx_timer_set_mode, - .set_next_event = cns3xxx_timer_set_next_event, - .rating = 350, - .cpumask = cpu_all_mask, + .name = "cns3xxx timer1", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = cns3xxx_shutdown, + .set_state_periodic = cns3xxx_set_periodic, + .set_state_oneshot = cns3xxx_set_oneshot, + .tick_resume = cns3xxx_shutdown, + .set_next_event = cns3xxx_timer_set_next_event, + .rating = 350, + .cpumask = cpu_all_mask, }; static void __init cns3xxx_clockevents_init(unsigned int timer_irq) @@ -339,7 +346,7 @@ static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = { .power_off = csn3xxx_usb_power_off, }; -static struct of_dev_auxdata cns3xxx_auxdata[] __initconst = { +static const struct of_dev_auxdata const cns3xxx_auxdata[] __initconst = { { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata }, { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata }, { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL }, @@ -392,7 +399,7 @@ static void __init cns3xxx_init(void) cns3xxx_auxdata, NULL); } -static const char *cns3xxx_dt_compat[] __initdata = { +static const char *const cns3xxx_dt_compat[] __initconst = { "cavium,cns3410", "cavium,cns3420", NULL, diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index 006dae8..bf12ce6 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c @@ -112,7 +112,7 @@ static int cp_intc_host_map(struct irq_domain *h, unsigned int virq, pr_debug("cp_intc_host_map(%d, 0x%lx)\n", virq, hw); irq_set_chip(virq, &cp_intc_irq_chip); - set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); + irq_set_probe(virq); irq_set_handler(virq, handle_edge_irq); return 0; } diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 3b8740c..6769978 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -715,7 +715,7 @@ const short da850_lcdcntl_pins[] __initconst = { -1 }; -const short da850_vpif_capture_pins[] __initdata = { +const short da850_vpif_capture_pins[] __initconst = { DA850_VPIF_DIN0, DA850_VPIF_DIN1, DA850_VPIF_DIN2, DA850_VPIF_DIN3, DA850_VPIF_DIN4, DA850_VPIF_DIN5, DA850_VPIF_DIN6, DA850_VPIF_DIN7, DA850_VPIF_DIN8, DA850_VPIF_DIN9, DA850_VPIF_DIN10, DA850_VPIF_DIN11, @@ -725,7 +725,7 @@ const short da850_vpif_capture_pins[] __initdata = { -1 }; -const short da850_vpif_display_pins[] __initdata = { +const short da850_vpif_display_pins[] __initconst = { DA850_VPIF_DOUT0, DA850_VPIF_DOUT1, DA850_VPIF_DOUT2, DA850_VPIF_DOUT3, DA850_VPIF_DOUT4, DA850_VPIF_DOUT5, DA850_VPIF_DOUT6, DA850_VPIF_DOUT7, DA850_VPIF_DOUT8, DA850_VPIF_DOUT9, DA850_VPIF_DOUT10, diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index 438f685..06b6451 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -20,7 +20,7 @@ #define DA8XX_NUM_UARTS 3 -static const struct of_device_id da8xx_irq_match[] __initconst = { +static const struct of_device_id const da8xx_irq_match[] __initconst = { { .compatible = "ti,cp-intc", .data = cp_intc_of_init, }, { } }; @@ -59,7 +59,7 @@ static void __init da850_init_machine(void) } -static const char *da850_boards_compat[] __initdata = { +static const char *const da850_boards_compat[] __initconst = { "enbw,cmc", "ti,da850-evm", "ti,da850", diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 160c960..6c18445 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -303,36 +303,42 @@ static int davinci_set_next_event(unsigned long cycles, return 0; } -static void davinci_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +static int davinci_shutdown(struct clock_event_device *evt) { struct timer_s *t = &timers[TID_CLOCKEVENT]; - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - t->period = davinci_clock_tick_rate / (HZ); - t->opts &= ~TIMER_OPTS_STATE_MASK; - t->opts |= TIMER_OPTS_PERIODIC; - timer32_config(t); - break; - case CLOCK_EVT_MODE_ONESHOT: - t->opts &= ~TIMER_OPTS_STATE_MASK; - t->opts |= TIMER_OPTS_ONESHOT; - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - t->opts &= ~TIMER_OPTS_STATE_MASK; - t->opts |= TIMER_OPTS_DISABLED; - break; - case CLOCK_EVT_MODE_RESUME: - break; - } + t->opts &= ~TIMER_OPTS_STATE_MASK; + t->opts |= TIMER_OPTS_DISABLED; + return 0; +} + +static int davinci_set_oneshot(struct clock_event_device *evt) +{ + struct timer_s *t = &timers[TID_CLOCKEVENT]; + + t->opts &= ~TIMER_OPTS_STATE_MASK; + t->opts |= TIMER_OPTS_ONESHOT; + return 0; +} + +static int davinci_set_periodic(struct clock_event_device *evt) +{ + struct timer_s *t = &timers[TID_CLOCKEVENT]; + + t->period = davinci_clock_tick_rate / (HZ); + t->opts &= ~TIMER_OPTS_STATE_MASK; + t->opts |= TIMER_OPTS_PERIODIC; + timer32_config(t); + return 0; } static struct clock_event_device clockevent_davinci = { - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = davinci_set_next_event, - .set_mode = davinci_set_mode, + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = davinci_set_next_event, + .set_state_shutdown = davinci_shutdown, + .set_state_periodic = davinci_set_periodic, + .set_state_oneshot = davinci_set_oneshot, }; diff --git a/arch/arm/mach-digicolor/digicolor.c b/arch/arm/mach-digicolor/digicolor.c index cfc88d1..4d62f1b 100644 --- a/arch/arm/mach-digicolor/digicolor.c +++ b/arch/arm/mach-digicolor/digicolor.c @@ -8,7 +8,7 @@ #include <asm/mach/arch.h> -static const char *digicolor_dt_compat[] __initconst = { +static const char *const digicolor_dt_compat[] __initconst = { "cnxt,cx92755", NULL, }; diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c index df0223f..305d7c6 100644 --- a/arch/arm/mach-dove/irq.c +++ b/arch/arm/mach-dove/irq.c @@ -69,8 +69,9 @@ static struct irq_chip pmu_irq_chip = { .irq_ack = pmu_irq_ack, }; -static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc) +static void pmu_irq_handler(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq = irq_desc_get_irq(desc); unsigned long cause = readl(PMU_INTERRUPT_CAUSE); cause &= readl(PMU_INTERRUPT_MASK); @@ -172,7 +173,7 @@ void __init dove_init_irq(void) for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) { irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq); irq_set_status_flags(i, IRQ_LEVEL); - set_irq_flags(i, IRQF_VALID); + irq_clear_status_flags(i, IRQ_NOREQUEST); } irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler); } diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 8254e71..688e5fe 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -65,7 +65,7 @@ static void __init ebsa110_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { irq_set_chip_and_handler(irq, &ebsa110_irq_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } } diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig index bec570a..61a75ca 100644 --- a/arch/arm/mach-ep93xx/Kconfig +++ b/arch/arm/mach-ep93xx/Kconfig @@ -15,45 +15,8 @@ config CRUNCH comment "EP93xx Platforms" -choice - prompt "EP93xx first SDRAM bank selection" - default EP93XX_SDCE3_SYNC_PHYS_OFFSET - -config EP93XX_SDCE3_SYNC_PHYS_OFFSET - bool "0x00000000 - SDCE3/SyncBoot" - help - Select this option if you want support for EP93xx boards with the - first SDRAM bank at 0x00000000. - -config EP93XX_SDCE0_PHYS_OFFSET - bool "0xc0000000 - SDCEO" - help - Select this option if you want support for EP93xx boards with the - first SDRAM bank at 0xc0000000. - -config EP93XX_SDCE1_PHYS_OFFSET - bool "0xd0000000 - SDCE1" - help - Select this option if you want support for EP93xx boards with the - first SDRAM bank at 0xd0000000. - -config EP93XX_SDCE2_PHYS_OFFSET - bool "0xe0000000 - SDCE2" - help - Select this option if you want support for EP93xx boards with the - first SDRAM bank at 0xe0000000. - -config EP93XX_SDCE3_ASYNC_PHYS_OFFSET - bool "0xf0000000 - SDCE3/AsyncBoot" - help - Select this option if you want support for EP93xx boards with the - first SDRAM bank at 0xf0000000. - -endchoice - config MACH_ADSSPHERE bool "Support ADS Sphere" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET help Say 'Y' here if you want your kernel to support the ADS Sphere board. @@ -63,7 +26,6 @@ config MACH_EDB93XX config MACH_EDB9301 bool "Support Cirrus Logic EDB9301" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus @@ -71,7 +33,6 @@ config MACH_EDB9301 config MACH_EDB9302 bool "Support Cirrus Logic EDB9302" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus @@ -79,7 +40,6 @@ config MACH_EDB9302 config MACH_EDB9302A bool "Support Cirrus Logic EDB9302A" - depends on EP93XX_SDCE0_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus @@ -87,7 +47,6 @@ config MACH_EDB9302A config MACH_EDB9307 bool "Support Cirrus Logic EDB9307" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus @@ -95,7 +54,6 @@ config MACH_EDB9307 config MACH_EDB9307A bool "Support Cirrus Logic EDB9307A" - depends on EP93XX_SDCE0_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus @@ -103,7 +61,6 @@ config MACH_EDB9307A config MACH_EDB9312 bool "Support Cirrus Logic EDB9312" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus @@ -111,7 +68,6 @@ config MACH_EDB9312 config MACH_EDB9315 bool "Support Cirrus Logic EDB9315" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus @@ -119,14 +75,12 @@ config MACH_EDB9315 config MACH_EDB9315A bool "Support Cirrus Logic EDB9315A" - depends on EP93XX_SDCE0_PHYS_OFFSET select MACH_EDB93XX help Say 'Y' here if you want your kernel to support the Cirrus Logic EDB9315A Evaluation Board. config MACH_GESBC9312 - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET bool "Support Glomation GESBC-9312-sx" help Say 'Y' here if you want your kernel to support the Glomation @@ -137,7 +91,6 @@ config MACH_MICRO9 config MACH_MICRO9H bool "Support Contec Micro9-High" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_MICRO9 help Say 'Y' here if you want your kernel to support the @@ -145,7 +98,6 @@ config MACH_MICRO9H config MACH_MICRO9M bool "Support Contec Micro9-Mid" - depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET select MACH_MICRO9 help Say 'Y' here if you want your kernel to support the @@ -153,7 +105,6 @@ config MACH_MICRO9M config MACH_MICRO9L bool "Support Contec Micro9-Lite" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_MICRO9 help Say 'Y' here if you want your kernel to support the @@ -161,7 +112,6 @@ config MACH_MICRO9L config MACH_MICRO9S bool "Support Contec Micro9-Slim" - depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET select MACH_MICRO9 help Say 'Y' here if you want your kernel to support the @@ -169,28 +119,24 @@ config MACH_MICRO9S config MACH_SIM_ONE bool "Support Simplemachines Sim.One board" - depends on EP93XX_SDCE0_PHYS_OFFSET help Say 'Y' here if you want your kernel to support the Simplemachines Sim.One board. config MACH_SNAPPER_CL15 bool "Support Bluewater Systems Snapper CL15 Module" - depends on EP93XX_SDCE0_PHYS_OFFSET help Say 'Y' here if you want your kernel to support the Bluewater Systems Snapper CL15 Module. config MACH_TS72XX bool "Support Technologic Systems TS-72xx SBC" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET help Say 'Y' here if you want your kernel to support the Technologic Systems TS-72xx board. config MACH_VISION_EP9307 bool "Support Vision Engraving Systems EP9307 SoM" - depends on EP93XX_SDCE0_PHYS_OFFSET help Say 'Y' here if you want your kernel to support the Vision Engraving Systems EP9307 SoM. diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index 78d427b..b7ae434 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux kernel. # -obj-y := core.o clock.o +obj-y := core.o clock.o timer-ep93xx.o obj-$(CONFIG_EP93XX_DMA) += dma.o diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot index d3113a7..ed82ed7 100644 --- a/arch/arm/mach-ep93xx/Makefile.boot +++ b/arch/arm/mach-ep93xx/Makefile.boot @@ -1,14 +1 @@ - zreladdr-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) += 0x00008000 -params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00000100 - - zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) += 0xc0008000 -params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0000100 - - zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) += 0xd0008000 -params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0000100 - - zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) += 0xe0008000 -params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0000100 - - zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) += 0xf0008000 -params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0000100 +# Empty file waiting for deletion once Makefile.boot isn't needed any more. diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 0e571f1..c393b1b 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -22,7 +22,6 @@ #include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/sys_soc.h> -#include <linux/timex.h> #include <linux/irq.h> #include <linux/io.h> #include <linux/gpio.h> @@ -38,6 +37,7 @@ #include <linux/irqchip/arm-vic.h> #include <linux/reboot.h> #include <linux/usb/ohci_pdriver.h> +#include <linux/random.h> #include <mach/hardware.h> #include <linux/platform_data/video-ep93xx.h> @@ -47,7 +47,6 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <asm/mach/time.h> #include "soc.h" @@ -73,113 +72,6 @@ void __init ep93xx_map_io(void) iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc)); } - -/************************************************************************* - * Timer handling for EP93xx - ************************************************************************* - * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and - * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate - * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz, - * is free-running, and can't generate interrupts. - * - * The 508 kHz timers are ideal for use for the timer interrupt, as the - * most common values of HZ divide 508 kHz nicely. We pick one of the 16 - * bit timers (timer 1) since we don't need more than 16 bits of reload - * value as long as HZ >= 8. - * - * The higher clock rate of timer 4 makes it a better choice than the - * other timers for use in gettimeoffset(), while the fact that it can't - * generate interrupts means we don't have to worry about not being able - * to use this timer for something else. We also use timer 4 for keeping - * track of lost jiffies. - */ -#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) -#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00) -#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04) -#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08) -#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7) -#define EP93XX_TIMER123_CONTROL_MODE (1 << 6) -#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3) -#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c) -#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) -#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) -#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) -#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) -#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60) -#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64) -#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8) -#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80) -#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84) -#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88) -#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c) - -#define EP93XX_TIMER123_CLOCK 508469 -#define EP93XX_TIMER4_CLOCK 983040 - -#define TIMER1_RELOAD ((EP93XX_TIMER123_CLOCK / HZ) - 1) -#define TIMER4_TICKS_PER_JIFFY DIV_ROUND_CLOSEST(EP93XX_TIMER4_CLOCK, HZ) - -static unsigned int last_jiffy_time; - -static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) -{ - /* Writing any value clears the timer interrupt */ - __raw_writel(1, EP93XX_TIMER1_CLEAR); - - /* Recover lost jiffies */ - while ((signed long) - (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time) - >= TIMER4_TICKS_PER_JIFFY) { - last_jiffy_time += TIMER4_TICKS_PER_JIFFY; - timer_tick(); - } - - return IRQ_HANDLED; -} - -static struct irqaction ep93xx_timer_irq = { - .name = "ep93xx timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = ep93xx_timer_interrupt, -}; - -static u32 ep93xx_gettimeoffset(void) -{ - int offset; - - offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time; - - /* - * Timer 4 is based on a 983.04 kHz reference clock, - * so dividing by 983040 gives the fraction of a second, - * so dividing by 0.983040 converts to uS. - * Refactor the calculation to avoid overflow. - * Finally, multiply by 1000 to give nS. - */ - return (offset + (53 * offset / 3072)) * 1000; -} - -void __init ep93xx_timer_init(void) -{ - u32 tmode = EP93XX_TIMER123_CONTROL_MODE | - EP93XX_TIMER123_CONTROL_CLKSEL; - - arch_gettimeoffset = ep93xx_gettimeoffset; - - /* Enable periodic HZ timer. */ - __raw_writel(tmode, EP93XX_TIMER1_CONTROL); - __raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD); - __raw_writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE, - EP93XX_TIMER1_CONTROL); - - /* Enable lost jiffy timer. */ - __raw_writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE, - EP93XX_TIMER4_VALUE_HIGH); - - setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq); -} - - /************************************************************************* * EP93xx IRQ handling *************************************************************************/ @@ -971,6 +863,12 @@ static const char __init *ep93xx_get_soc_id(void) if (id != id2) return "invalid"; + /* Toss the unique ID into the entropy pool */ + add_device_randomness(&id2, 4); + add_device_randomness(&id3, 4); + add_device_randomness(&id4, 4); + add_device_randomness(&id5, 4); + snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id), "%08x%08x%08x%08x", id2, id3, id4, id5); diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index 3c950f5..d0938a2 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -169,6 +169,7 @@ static struct spi_board_info simone_spi_devices[] __initdata = { static struct ep93xx_spi_info simone_spi_info __initdata = { .num_chipselect = ARRAY_SIZE(simone_spi_devices), + .use_dma = 1, }; static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = { diff --git a/arch/arm/mach-ep93xx/timer-ep93xx.c b/arch/arm/mach-ep93xx/timer-ep93xx.c new file mode 100644 index 0000000..ac48ac1 --- /dev/null +++ b/arch/arm/mach-ep93xx/timer-ep93xx.c @@ -0,0 +1,140 @@ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/sched_clock.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <asm/mach/time.h> +#include "soc.h" + +/************************************************************************* + * Timer handling for EP93xx + ************************************************************************* + * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and + * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate + * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz, + * is free-running, and can't generate interrupts. + * + * The 508 kHz timers are ideal for use for the timer interrupt, as the + * most common values of HZ divide 508 kHz nicely. We pick the 32 bit + * timer (timer 3) to get as long sleep intervals as possible when using + * CONFIG_NO_HZ. + * + * The higher clock rate of timer 4 makes it a better choice than the + * other timers for use as clock source and for sched_clock(), providing + * a stable 40 bit time base. + ************************************************************************* + */ +#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) +#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00) +#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04) +#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08) +#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7) +#define EP93XX_TIMER123_CONTROL_MODE (1 << 6) +#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3) +#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c) +#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) +#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) +#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) +#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) +#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60) +#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64) +#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8) +#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80) +#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84) +#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88) +#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c) + +#define EP93XX_TIMER123_RATE 508469 +#define EP93XX_TIMER4_RATE 983040 + +static u64 notrace ep93xx_read_sched_clock(void) +{ + u64 ret; + + ret = readl(EP93XX_TIMER4_VALUE_LOW); + ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32); + return ret; +} + +cycle_t ep93xx_clocksource_read(struct clocksource *c) +{ + u64 ret; + + ret = readl(EP93XX_TIMER4_VALUE_LOW); + ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32); + return (cycle_t) ret; +} + +static int ep93xx_clkevt_set_next_event(unsigned long next, + struct clock_event_device *evt) +{ + /* Default mode: periodic, off, 508 kHz */ + u32 tmode = EP93XX_TIMER123_CONTROL_MODE | + EP93XX_TIMER123_CONTROL_CLKSEL; + + /* Clear timer */ + writel(tmode, EP93XX_TIMER3_CONTROL); + + /* Set next event */ + writel(next, EP93XX_TIMER3_LOAD); + writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE, + EP93XX_TIMER3_CONTROL); + return 0; +} + + +static void ep93xx_clkevt_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + /* Disable timer */ + writel(0, EP93XX_TIMER3_CONTROL); +} + +static struct clock_event_device ep93xx_clockevent = { + .name = "timer1", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = ep93xx_clkevt_set_mode, + .set_next_event = ep93xx_clkevt_set_next_event, + .rating = 300, +}; + +static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + /* Writing any value clears the timer interrupt */ + writel(1, EP93XX_TIMER3_CLEAR); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction ep93xx_timer_irq = { + .name = "ep93xx timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = ep93xx_timer_interrupt, + .dev_id = &ep93xx_clockevent, +}; + +void __init ep93xx_timer_init(void) +{ + /* Enable and register clocksource and sched_clock on timer 4 */ + writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE, + EP93XX_TIMER4_VALUE_HIGH); + clocksource_mmio_init(NULL, "timer4", + EP93XX_TIMER4_RATE, 200, 40, + ep93xx_clocksource_read); + sched_clock_register(ep93xx_read_sched_clock, 40, + EP93XX_TIMER4_RATE); + + /* Set up clockevent on timer 3 */ + setup_irq(IRQ_EP93XX_TIMER3, &ep93xx_timer_irq); + clockevents_config_and_register(&ep93xx_clockevent, + EP93XX_TIMER123_RATE, + 1, + 0xffffffffU); +} diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c index 6bc1c18..ff22a6a 100644 --- a/arch/arm/mach-ep93xx/vision_ep9307.c +++ b/arch/arm/mach-ep93xx/vision_ep9307.c @@ -29,6 +29,8 @@ #include <linux/spi/mmc_spi.h> #include <linux/mmc/host.h> +#include <sound/cs4271.h> + #include <mach/hardware.h> #include <linux/platform_data/video-ep93xx.h> #include <linux/platform_data/spi-ep93xx.h> @@ -169,6 +171,35 @@ static struct i2c_board_info vision_i2c_info[] __initdata = { }; /************************************************************************* + * SPI CS4271 Audio Codec + *************************************************************************/ +static struct cs4271_platform_data vision_cs4271_data = { + .gpio_nreset = EP93XX_GPIO_LINE_H(2), +}; + +static int vision_cs4271_hw_setup(struct spi_device *spi) +{ + return gpio_request_one(EP93XX_GPIO_LINE_EGPIO6, + GPIOF_OUT_INIT_HIGH, spi->modalias); +} + +static void vision_cs4271_hw_cleanup(struct spi_device *spi) +{ + gpio_free(EP93XX_GPIO_LINE_EGPIO6); +} + +static void vision_cs4271_hw_cs_control(struct spi_device *spi, int value) +{ + gpio_set_value(EP93XX_GPIO_LINE_EGPIO6, value); +} + +static struct ep93xx_spi_chip_ops vision_cs4271_hw = { + .setup = vision_cs4271_hw_setup, + .cleanup = vision_cs4271_hw_cleanup, + .cs_control = vision_cs4271_hw_cs_control, +}; + +/************************************************************************* * SPI Flash *************************************************************************/ #define VISION_SPI_FLASH_CS EP93XX_GPIO_LINE_EGPIO7 @@ -262,12 +293,20 @@ static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = { *************************************************************************/ static struct spi_board_info vision_spi_board_info[] __initdata = { { + .modalias = "cs4271", + .platform_data = &vision_cs4271_data, + .controller_data = &vision_cs4271_hw, + .max_speed_hz = 6000000, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_3, + }, { .modalias = "sst25l", .platform_data = &vision_spi_flash_data, .controller_data = &vision_spi_flash_hw, .max_speed_hz = 20000000, .bus_num = 0, - .chip_select = 0, + .chip_select = 1, .mode = SPI_MODE_3, }, { .modalias = "mmc_spi", @@ -275,16 +314,31 @@ static struct spi_board_info vision_spi_board_info[] __initdata = { .controller_data = &vision_spi_mmc_hw, .max_speed_hz = 20000000, .bus_num = 0, - .chip_select = 1, + .chip_select = 2, .mode = SPI_MODE_3, }, }; static struct ep93xx_spi_info vision_spi_master __initdata = { - .num_chipselect = ARRAY_SIZE(vision_spi_board_info), + .num_chipselect = ARRAY_SIZE(vision_spi_board_info), + .use_dma = 1, }; /************************************************************************* + * I2S Audio + *************************************************************************/ +static struct platform_device vision_audio_device = { + .name = "edb93xx-audio", + .id = -1, +}; + +static void __init vision_register_i2s(void) +{ + ep93xx_register_i2s(); + platform_device_register(&vision_audio_device); +} + +/************************************************************************* * Machine Initialization *************************************************************************/ static void __init vision_init_machine(void) @@ -309,6 +363,7 @@ static void __init vision_init_machine(void) ARRAY_SIZE(vision_i2c_info)); ep93xx_register_spi(&vision_spi_master, vision_spi_board_info, ARRAY_SIZE(vision_spi_board_info)); + vision_register_i2s(); } MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307") diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index 9e8220e..0f0c9e0 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c @@ -106,7 +106,7 @@ static void __init __fb_init_irq(void) for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) { irq_set_chip_and_handler(irq, &fb_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } } diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index bf7aa7d..810edc7 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -57,34 +57,32 @@ static int ckevt_dc21285_set_next_event(unsigned long delta, return 0; } -static void ckevt_dc21285_set_mode(enum clock_event_mode mode, - struct clock_event_device *c) +static int ckevt_dc21285_shutdown(struct clock_event_device *c) { - switch (mode) { - case CLOCK_EVT_MODE_RESUME: - case CLOCK_EVT_MODE_PERIODIC: - *CSR_TIMER1_CLR = 0; - *CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ); - *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | - TIMER_CNTL_DIV16; - break; - - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - *CSR_TIMER1_CNTL = 0; - break; - } + *CSR_TIMER1_CNTL = 0; + return 0; +} + +static int ckevt_dc21285_set_periodic(struct clock_event_device *c) +{ + *CSR_TIMER1_CLR = 0; + *CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ); + *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | + TIMER_CNTL_DIV16; + return 0; } static struct clock_event_device ckevt_dc21285 = { - .name = "dc21285_timer1", - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .irq = IRQ_TIMER1, - .set_next_event = ckevt_dc21285_set_next_event, - .set_mode = ckevt_dc21285_set_mode, + .name = "dc21285_timer1", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .irq = IRQ_TIMER1, + .set_next_event = ckevt_dc21285_set_next_event, + .set_state_shutdown = ckevt_dc21285_shutdown, + .set_state_periodic = ckevt_dc21285_set_periodic, + .set_state_oneshot = ckevt_dc21285_shutdown, + .tick_resume = ckevt_dc21285_set_periodic, }; static irqreturn_t timer1_interrupt(int irq, void *dev_id) @@ -94,7 +92,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) *CSR_TIMER1_CLR = 0; /* Stop the timer if in one-shot mode */ - if (ce->mode == CLOCK_EVT_MODE_ONESHOT) + if (clockevent_state_oneshot(ce)) *CSR_TIMER1_CNTL = 0; ce->event_handler(ce); diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c index c3a0abb..fcd79bc 100644 --- a/arch/arm/mach-footbridge/isa-irq.c +++ b/arch/arm/mach-footbridge/isa-irq.c @@ -153,13 +153,13 @@ void __init isa_init_irq(unsigned int host_irq) for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) { irq_set_chip_and_handler(irq, &isa_lo_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) { irq_set_chip_and_handler(irq, &isa_hi_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } request_resource(&ioport_resource, &pic1_resource); @@ -175,8 +175,8 @@ void __init isa_init_irq(unsigned int host_irq) * resistor on this line. */ if (machine_is_netwinder()) - set_irq_flags(_ISA_IRQ(11), IRQF_VALID | - IRQF_PROBE | IRQF_NOAUTOEN); + irq_modify_status(_ISA_IRQ(11), + IRQ_NOREQUEST | IRQ_NOPROBE, IRQ_NOAUTOEN); } } diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c index 3292f2e..220333e 100644 --- a/arch/arm/mach-gemini/gpio.c +++ b/arch/arm/mach-gemini/gpio.c @@ -220,7 +220,7 @@ void __init gemini_gpio_init(void) j < GPIO_IRQ_BASE + (i + 1) * 32; j++) { irq_set_chip_and_handler(j, &gpio_irq_chip, handle_edge_irq); - set_irq_flags(j, IRQF_VALID); + irq_clear_status_flags(j, IRQ_NOREQUEST); } irq_set_chained_handler_and_data(IRQ_GPIO(i), gpio_irq_handler, diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c index 44f50dc..d929b3f 100644 --- a/arch/arm/mach-gemini/irq.c +++ b/arch/arm/mach-gemini/irq.c @@ -92,7 +92,7 @@ void __init gemini_init_irq(void) } else { irq_set_handler(i, handle_level_irq); } - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE); } /* Disable all interrupts */ diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c index 0a63c4d2..b57d367 100644 --- a/arch/arm/mach-gemini/time.c +++ b/arch/arm/mach-gemini/time.c @@ -59,49 +59,48 @@ static int gemini_timer_set_next_event(unsigned long cycles, return 0; } -static void gemini_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +static int gemini_timer_shutdown(struct clock_event_device *evt) +{ + u32 cr; + + /* + * Disable also for oneshot: the set_next() call will arm the timer + * instead. + */ + cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); + cr &= ~TIMER_2_CR_ENABLE; + cr &= ~TIMER_2_CR_INT; + writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); + return 0; +} + +static int gemini_timer_set_periodic(struct clock_event_device *evt) { u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); u32 cr; - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - /* Start the timer */ - writel(period, - TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE))); - writel(period, - TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE))); - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); - cr |= TIMER_2_CR_ENABLE; - cr |= TIMER_2_CR_INT; - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); - break; - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - /* - * Disable also for oneshot: the set_next() call will - * arm the timer instead. - */ - cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); - cr &= ~TIMER_2_CR_ENABLE; - cr &= ~TIMER_2_CR_INT; - writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); - break; - default: - break; - } + /* Start the timer */ + writel(period, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE))); + writel(period, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE))); + cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); + cr |= TIMER_2_CR_ENABLE; + cr |= TIMER_2_CR_INT; + writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); + return 0; } /* Use TIMER2 as clock event */ static struct clock_event_device gemini_clockevent = { - .name = "TIMER2", - .rating = 300, /* Reasonably fast and accurate clock event */ - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = gemini_timer_set_next_event, - .set_mode = gemini_timer_set_mode, + .name = "TIMER2", + /* Reasonably fast and accurate clock event */ + .rating = 300, + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = gemini_timer_set_next_event, + .set_state_shutdown = gemini_timer_shutdown, + .set_state_periodic = gemini_timer_set_periodic, + .set_state_oneshot = gemini_timer_shutdown, + .tick_resume = gemini_timer_shutdown, }; /* diff --git a/arch/arm/mach-imx/3ds_debugboard.c b/arch/arm/mach-imx/3ds_debugboard.c index 1343773..45903be 100644 --- a/arch/arm/mach-imx/3ds_debugboard.c +++ b/arch/arm/mach-imx/3ds_debugboard.c @@ -195,7 +195,7 @@ int __init mxc_expio_init(u32 base, u32 intr_gpio) for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) { irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID); + irq_clear_status_flags(i, IRQ_NOREQUEST); } irq_set_irq_type(p_irq, IRQF_TRIGGER_LOW); irq_set_chained_handler(p_irq, mxc_expio_irq_handler); diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c index 074b1a8..08ce2077 100644 --- a/arch/arm/mach-imx/epit.c +++ b/arch/arm/mach-imx/epit.c @@ -57,7 +57,6 @@ #include "hardware.h" static struct clock_event_device clockevent_epit; -static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED; static void __iomem *timer_base; @@ -106,8 +105,8 @@ static int epit_set_next_event(unsigned long evt, return 0; } -static void epit_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +/* Left event sources disabled, no more interrupts appear */ +static int epit_shutdown(struct clock_event_device *evt) { unsigned long flags; @@ -120,39 +119,41 @@ static void epit_set_mode(enum clock_event_mode mode, /* Disable interrupt in GPT module */ epit_irq_disable(); - if (mode != clockevent_mode) { - /* Set event time into far-far future */ - - /* Clear pending interrupt */ - epit_irq_acknowledge(); - } + /* Clear pending interrupt */ + epit_irq_acknowledge(); - /* Remember timer mode */ - clockevent_mode = mode; local_irq_restore(flags); - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - printk(KERN_ERR "epit_set_mode: Periodic mode is not " - "supported for i.MX EPIT\n"); - break; - case CLOCK_EVT_MODE_ONESHOT: + return 0; +} + +static int epit_set_oneshot(struct clock_event_device *evt) +{ + unsigned long flags; + + /* + * The timer interrupt generation is disabled at least + * for enough time to call epit_set_next_event() + */ + local_irq_save(flags); + + /* Disable interrupt in GPT module */ + epit_irq_disable(); + + /* Clear pending interrupt, only while switching mode */ + if (!clockevent_state_oneshot(evt)) + epit_irq_acknowledge(); + /* * Do not put overhead of interrupt enable/disable into * epit_set_next_event(), the core has about 4 minutes * to call epit_set_next_event() or shutdown clock after * mode switching */ - local_irq_save(flags); - epit_irq_enable(); - local_irq_restore(flags); - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_RESUME: - /* Left event sources disabled, no more interrupts appear */ - break; - } + epit_irq_enable(); + local_irq_restore(flags); + + return 0; } /* @@ -176,11 +177,13 @@ static struct irqaction epit_timer_irq = { }; static struct clock_event_device clockevent_epit = { - .name = "epit", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = epit_set_mode, - .set_next_event = epit_set_next_event, - .rating = 200, + .name = "epit", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = epit_shutdown, + .tick_resume = epit_shutdown, + .set_state_oneshot = epit_set_oneshot, + .set_next_event = epit_set_next_event, + .rating = 200, }; static int __init epit_clockevent_init(struct clk *timer_clk) diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c index 4d4a190..62f3437 100644 --- a/arch/arm/mach-imx/mach-imx7d.c +++ b/arch/arm/mach-imx/mach-imx7d.c @@ -31,7 +31,7 @@ static void __init imx7d_init_irq(void) irqchip_init(); } -static const char *imx7d_dt_compat[] __initconst = { +static const char *const imx7d_dt_compat[] __initconst = { "fsl,imx7d", NULL, }; diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index d08c37c..2c08535 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -238,7 +238,7 @@ static void __init mx31ads_init_expio(void) for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) { irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID); + irq_clear_status_flags(i, IRQ_NOREQUEST); } irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_4)); irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH); diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c index bc73970..623d85a 100644 --- a/arch/arm/mach-iop13xx/irq.c +++ b/arch/arm/mach-iop13xx/irq.c @@ -233,7 +233,7 @@ void __init iop13xx_init_irq(void) irq_set_chip(i, &iop13xx_irqchip4); irq_set_handler(i, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE); } iop13xx_msi_init(); diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c index d7ee278..2d1f69a 100644 --- a/arch/arm/mach-iop32x/irq.c +++ b/arch/arm/mach-iop32x/irq.c @@ -69,6 +69,6 @@ void __init iop32x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { irq_set_chip_and_handler(i, &ext_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE); } } diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c index f7f5d3e..c99ec8d 100644 --- a/arch/arm/mach-iop33x/irq.c +++ b/arch/arm/mach-iop33x/irq.c @@ -113,6 +113,6 @@ void __init iop33x_init_irq(void) irq_set_chip_and_handler(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2, handle_level_irq); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE); } } diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 8537d4c..1cb6f2f 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -296,7 +296,7 @@ void __init ixp4xx_init_irq(void) for(i = 0; i < NR_IRQS; i++) { irq_set_chip_and_handler(i, &ixp4xx_irq_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID); + irq_clear_status_flags(i, IRQ_NOREQUEST); } } @@ -521,43 +521,55 @@ static int ixp4xx_set_next_event(unsigned long evt, return 0; } -static void ixp4xx_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +static int ixp4xx_shutdown(struct clock_event_device *evt) { unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK; - opts = IXP4XX_OST_ENABLE; - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set by 'set next_event' */ - osrt = 0; - opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT; - break; - case CLOCK_EVT_MODE_SHUTDOWN: - opts &= ~IXP4XX_OST_ENABLE; - break; - case CLOCK_EVT_MODE_RESUME: - opts |= IXP4XX_OST_ENABLE; - break; - case CLOCK_EVT_MODE_UNUSED: - default: - osrt = opts = 0; - break; - } + opts &= ~IXP4XX_OST_ENABLE; + *IXP4XX_OSRT1 = osrt | opts; + return 0; +} +static int ixp4xx_set_oneshot(struct clock_event_device *evt) +{ + unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT; + unsigned long osrt = 0; + + /* period set by 'set next_event' */ *IXP4XX_OSRT1 = osrt | opts; + return 0; +} + +static int ixp4xx_set_periodic(struct clock_event_device *evt) +{ + unsigned long opts = IXP4XX_OST_ENABLE; + unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK; + + *IXP4XX_OSRT1 = osrt | opts; + return 0; +} + +static int ixp4xx_resume(struct clock_event_device *evt) +{ + unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; + unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; + + opts |= IXP4XX_OST_ENABLE; + *IXP4XX_OSRT1 = osrt | opts; + return 0; } static struct clock_event_device clockevent_ixp4xx = { - .name = "ixp4xx timer1", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_mode = ixp4xx_set_mode, - .set_next_event = ixp4xx_set_next_event, + .name = "ixp4xx timer1", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_state_shutdown = ixp4xx_shutdown, + .set_state_periodic = ixp4xx_set_periodic, + .set_state_oneshot = ixp4xx_set_oneshot, + .tick_resume = ixp4xx_resume, + .set_next_event = ixp4xx_set_next_event, }; static void __init ixp4xx_clockevent_init(void) diff --git a/arch/arm/mach-ks8695/irq.c b/arch/arm/mach-ks8695/irq.c index 76802aa..31439f2 100644 --- a/arch/arm/mach-ks8695/irq.c +++ b/arch/arm/mach-ks8695/irq.c @@ -172,6 +172,6 @@ void __init ks8695_init_irq(void) handle_edge_irq); } - set_irq_flags(irq, IRQF_VALID); + irq_clear_status_flags(irq, IRQ_NOREQUEST); } } diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c index a197874..18eb0fb 100644 --- a/arch/arm/mach-ks8695/time.c +++ b/arch/arm/mach-ks8695/time.c @@ -54,28 +54,25 @@ /* Timer0 Timeout Counter Register */ #define T0TC_WATCHDOG (0xff) /* Enable watchdog mode */ -static void ks8695_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +static int ks8695_set_periodic(struct clock_event_device *evt) { + u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ); + u32 half = DIV_ROUND_CLOSEST(rate, 2); u32 tmcon; - if (mode == CLOCK_EVT_FEAT_PERIODIC) { - u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ); - u32 half = DIV_ROUND_CLOSEST(rate, 2); - - /* Disable timer 1 */ - tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON); - tmcon &= ~TMCON_T1EN; - writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON); + /* Disable timer 1 */ + tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON); + tmcon &= ~TMCON_T1EN; + writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON); - /* Both registers need to count down */ - writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC); - writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD); + /* Both registers need to count down */ + writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC); + writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD); - /* Re-enable timer1 */ - tmcon |= TMCON_T1EN; - writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON); - } + /* Re-enable timer1 */ + tmcon |= TMCON_T1EN; + writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON); + return 0; } static int ks8695_set_next_event(unsigned long cycles, @@ -102,11 +99,13 @@ static int ks8695_set_next_event(unsigned long cycles, } static struct clock_event_device clockevent_ks8695 = { - .name = "ks8695_t1tc", - .rating = 300, /* Reasonably fast and accurate clock event */ - .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, - .set_next_event = ks8695_set_next_event, - .set_mode = ks8695_set_mode, + .name = "ks8695_t1tc", + /* Reasonably fast and accurate clock event */ + .rating = 300, + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC, + .set_next_event = ks8695_set_next_event, + .set_state_periodic = ks8695_set_periodic, }; /* diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c index d4f7dc8..cce4cef 100644 --- a/arch/arm/mach-lpc32xx/irq.c +++ b/arch/arm/mach-lpc32xx/irq.c @@ -283,25 +283,25 @@ static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type) case IRQ_TYPE_EDGE_RISING: /* Rising edge sensitive */ __lpc32xx_set_irq_type(d->hwirq, 1, 1); - __irq_set_handler_locked(d->irq, handle_edge_irq); + irq_set_handler_locked(d, handle_edge_irq); break; case IRQ_TYPE_EDGE_FALLING: /* Falling edge sensitive */ __lpc32xx_set_irq_type(d->hwirq, 0, 1); - __irq_set_handler_locked(d->irq, handle_edge_irq); + irq_set_handler_locked(d, handle_edge_irq); break; case IRQ_TYPE_LEVEL_LOW: /* Low level sensitive */ __lpc32xx_set_irq_type(d->hwirq, 0, 0); - __irq_set_handler_locked(d->irq, handle_level_irq); + irq_set_handler_locked(d, handle_level_irq); break; case IRQ_TYPE_LEVEL_HIGH: /* High level sensitive */ __lpc32xx_set_irq_type(d->hwirq, 1, 0); - __irq_set_handler_locked(d->irq, handle_level_irq); + irq_set_handler_locked(d, handle_level_irq); break; /* Other modes are not supported */ @@ -434,7 +434,7 @@ void __init lpc32xx_init_irq(void) for (i = 0; i < NR_IRQS; i++) { irq_set_chip_and_handler(i, &lpc32xx_irq_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID); + irq_clear_status_flags(i, IRQ_NOREQUEST); } /* Set default mappings */ diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 7858d5b..77d6b1b 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -212,7 +212,7 @@ static struct lpc32xx_mlc_platform_data lpc32xx_mlc_data = { .dma_filter = pl08x_filter_id, }; -static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = { +static const struct of_dev_auxdata const lpc32xx_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", NULL), OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", NULL), OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data), @@ -248,7 +248,7 @@ static void __init lpc3250_machine_init(void) lpc32xx_auxdata_lookup, NULL); } -static char const *lpc32xx_dt_compat[] __initdata = { +static const char *const lpc32xx_dt_compat[] __initconst = { "nxp,lpc3220", "nxp,lpc3230", "nxp,lpc3240", diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c index 4e583729..ff3499d 100644 --- a/arch/arm/mach-lpc32xx/timer.c +++ b/arch/arm/mach-lpc32xx/timer.c @@ -43,36 +43,24 @@ static int lpc32xx_clkevt_next_event(unsigned long delta, return 0; } -static void lpc32xx_clkevt_mode(enum clock_event_mode mode, - struct clock_event_device *dev) +static int lpc32xx_shutdown(struct clock_event_device *evt) { - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - WARN_ON(1); - break; - - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_SHUTDOWN: - /* - * Disable the timer. When using oneshot, we must also - * disable the timer to wait for the first call to - * set_next_event(). - */ - __raw_writel(0, LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE)); - break; - - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_RESUME: - break; - } + /* + * Disable the timer. When using oneshot, we must also + * disable the timer to wait for the first call to + * set_next_event(). + */ + __raw_writel(0, LPC32XX_TIMER_TCR(LPC32XX_TIMER0_BASE)); + return 0; } static struct clock_event_device lpc32xx_clkevt = { - .name = "lpc32xx_clkevt", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 300, - .set_next_event = lpc32xx_clkevt_next_event, - .set_mode = lpc32xx_clkevt_mode, + .name = "lpc32xx_clkevt", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .set_next_event = lpc32xx_clkevt_next_event, + .set_state_shutdown = lpc32xx_shutdown, + .set_state_oneshot = lpc32xx_shutdown, }; static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-mmp/mmp-dt.c b/arch/arm/mach-mmp/mmp-dt.c index b2296c9..6e155f0 100644 --- a/arch/arm/mach-mmp/mmp-dt.c +++ b/arch/arm/mach-mmp/mmp-dt.c @@ -20,12 +20,12 @@ extern void __init mmp_dt_init_timer(void); -static const char *pxa168_dt_board_compat[] __initdata = { +static const char *const pxa168_dt_board_compat[] __initconst = { "mrvl,pxa168-aspenite", NULL, }; -static const char *pxa910_dt_board_compat[] __initdata = { +static const char *const pxa910_dt_board_compat[] __initconst = { "mrvl,pxa910-dkb", NULL, }; diff --git a/arch/arm/mach-mmp/mmp2-dt.c b/arch/arm/mach-mmp/mmp2-dt.c index 998c0f5..0341359 100644 --- a/arch/arm/mach-mmp/mmp2-dt.c +++ b/arch/arm/mach-mmp/mmp2-dt.c @@ -30,7 +30,7 @@ static void __init mmp_init_time(void) of_clk_init(NULL); } -static const char *mmp2_dt_board_compat[] __initdata = { +static const char *const mmp2_dt_board_compat[] __initconst = { "mrvl,mmp2-brownstone", NULL, }; diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 10bfa03..dbc697b 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c @@ -124,32 +124,25 @@ static int timer_set_next_event(unsigned long delta, return 0; } -static void timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *dev) +static int timer_set_shutdown(struct clock_event_device *evt) { unsigned long flags; local_irq_save(flags); - switch (mode) { - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - /* disable the matching interrupt */ - __raw_writel(0x00, mmp_timer_base + TMR_IER(0)); - break; - case CLOCK_EVT_MODE_RESUME: - case CLOCK_EVT_MODE_PERIODIC: - break; - } + /* disable the matching interrupt */ + __raw_writel(0x00, mmp_timer_base + TMR_IER(0)); local_irq_restore(flags); + + return 0; } static struct clock_event_device ckevt = { - .name = "clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_next_event = timer_set_next_event, - .set_mode = timer_set_mode, + .name = "clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = timer_set_next_event, + .set_state_shutdown = timer_set_shutdown, + .set_state_oneshot = timer_set_shutdown, }; static cycle_t clksrc_read(struct clocksource *cs) diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index 4f4e222..e8fdb9c 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -415,7 +415,7 @@ static __init int armada_38x_cpuidle_init(void) void __iomem *mpsoc_base; u32 reg; - pr_warn("CPU idle is currently broken on Armada 38x: disabling"); + pr_warn("CPU idle is currently broken on Armada 38x: disabling\n"); return 0; np = of_find_compatible_node(NULL, NULL, @@ -486,7 +486,7 @@ static int __init mvebu_v7_cpu_pm_init(void) */ if (of_machine_is_compatible("marvell,armada380")) { cpu_hotplug_disable(); - pr_warn("CPU hotplug support is currently broken on Armada 38x: disabling"); + pr_warn("CPU hotplug support is currently broken on Armada 38x: disabling\n"); } if (of_machine_is_compatible("marvell,armadaxp")) diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 2e7cec8..f1ea470 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -282,7 +282,7 @@ static void __init apx4devkit_init(void) #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) -static const struct gpio tx28_gpios[] __initconst = { +static const struct gpio const tx28_gpios[] __initconst = { { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, @@ -528,7 +528,7 @@ static void mxs_restart(enum reboot_mode mode, const char *cmd) soft_restart(0); } -static const char *mxs_dt_compat[] __initdata = { +static const char *const mxs_dt_compat[] __initconst = { "fsl,imx28", "fsl,imx23", NULL, diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index db25b0c..6373e2b 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -174,7 +174,7 @@ void __init netx_init_irq(void) for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { irq_set_chip_and_handler(irq, &netx_hif_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); + irq_clear_status_flags(irq, IRQ_NOREQUEST); } writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN); diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 5fb2a59..054a8a6 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -34,40 +34,40 @@ #define TIMER_CLOCKEVENT 0 #define TIMER_CLOCKSOURCE 1 -static void netx_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) +static inline void timer_shutdown(struct clock_event_device *evt) { - u32 tmode; - /* disable timer */ writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); +} + +static int netx_shutdown(struct clock_event_device *evt) +{ + timer_shutdown(evt); + + return 0; +} + +static int netx_set_oneshot(struct clock_event_device *evt) +{ + u32 tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN; + + timer_shutdown(evt); + writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); + writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); - tmode = NETX_GPIO_COUNTER_CTRL_RST_EN | - NETX_GPIO_COUNTER_CTRL_IRQ_EN | - NETX_GPIO_COUNTER_CTRL_RUN; - break; - - case CLOCK_EVT_MODE_ONESHOT: - writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); - tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | - NETX_GPIO_COUNTER_CTRL_RUN; - break; - - default: - WARN(1, "%s: unhandled mode %d\n", __func__, mode); - /* fall through */ - - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_RESUME: - tmode = 0; - break; - } + return 0; +} +static int netx_set_periodic(struct clock_event_device *evt) +{ + u32 tmode = NETX_GPIO_COUNTER_CTRL_RST_EN | + NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN; + + timer_shutdown(evt); + writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); + + return 0; } static int netx_set_next_event(unsigned long evt, @@ -81,7 +81,10 @@ static struct clock_event_device netx_clockevent = { .name = "netx-timer" __stringify(TIMER_CLOCKEVENT), .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = netx_set_next_event, - .set_mode = netx_set_mode, + .set_state_shutdown = netx_shutdown, + .set_state_periodic = netx_set_periodic, + .set_state_oneshot = netx_set_oneshot, + .tick_resume = netx_shutdown, }; /* diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c index 3c0e422..dfec671 100644 --- a/arch/arm/mach-omap1/fpga.c +++ b/arch/arm/mach-omap1/fpga.c @@ -169,7 +169,7 @@ void omap1510_fpga_init_irq(void) } irq_set_handler(i, handle_edge_irq); - set_irq_flags(i, IRQF_VALID); + irq_clear_status_flags(i, IRQ_NOREQUEST); } /* diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index f4d346f..b11edc8 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -262,7 +262,7 @@ void __init omap1_init_irq(void) irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j); omap_irq_set_cfg(j, 0, 0, irq_trigger); - set_irq_flags(j, IRQF_VALID); + irq_clear_status_flags(j, IRQ_NOREQUEST); } omap_alloc_gc(irq_banks[i].va, irq_base + i * 32, 32); } diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index a7588cf..524977a 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -124,29 +124,26 @@ static int omap_mpu_set_next_event(unsigned long cycles, return 0; } -static void omap_mpu_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +static int omap_mpu_set_oneshot(struct clock_event_device *evt) { - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - omap_mpu_set_autoreset(0); - break; - case CLOCK_EVT_MODE_ONESHOT: - omap_mpu_timer_stop(0); - omap_mpu_remove_autoreset(0); - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - break; - } + omap_mpu_timer_stop(0); + omap_mpu_remove_autoreset(0); + return 0; +} + +static int omap_mpu_set_periodic(struct clock_event_device *evt) +{ + omap_mpu_set_autoreset(0); + return 0; } static struct clock_event_device clockevent_mpu_timer1 = { - .name = "mpu_timer1", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = omap_mpu_set_next_event, - .set_mode = omap_mpu_set_mode, + .name = "mpu_timer1", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = omap_mpu_set_next_event, + .set_state_periodic = omap_mpu_set_periodic, + .set_state_oneshot = omap_mpu_set_oneshot, }; static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index 36bf174..0ae6c52 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -114,29 +114,28 @@ static int omap_32k_timer_set_next_event(unsigned long delta, return 0; } -static void omap_32k_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +static int omap_32k_timer_shutdown(struct clock_event_device *evt) { omap_32k_timer_stop(); + return 0; +} - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); - break; - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - break; - case CLOCK_EVT_MODE_RESUME: - break; - } +static int omap_32k_timer_set_periodic(struct clock_event_device *evt) +{ + omap_32k_timer_stop(); + omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); + return 0; } static struct clock_event_device clockevent_32k_timer = { - .name = "32k-timer", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = omap_32k_timer_set_next_event, - .set_mode = omap_32k_timer_set_mode, + .name = "32k-timer", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = omap_32k_timer_set_next_event, + .set_state_shutdown = omap_32k_timer_shutdown, + .set_state_periodic = omap_32k_timer_set_periodic, + .set_state_oneshot = omap_32k_timer_shutdown, + .tick_resume = omap_32k_timer_shutdown, }; static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index ecc04ff..e68ad9f 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -177,26 +177,6 @@ config MACH_OMAP_LDP default y select OMAP_PACKAGE_CBB -config MACH_OMAP3530_LV_SOM - bool "OMAP3 Logic 3530 LV SOM board" - depends on ARCH_OMAP3 - default y - select OMAP_PACKAGE_CBB - help - Support for the LogicPD OMAP3530 SOM Development kit - for full description please see the products webpage at - http://www.logicpd.com/products/development-kits/texas-instruments-zoom%E2%84%A2-omap35x-development-kit - -config MACH_OMAP3_TORPEDO - bool "OMAP3 Logic 35x Torpedo board" - depends on ARCH_OMAP3 - default y - select OMAP_PACKAGE_CBB - help - Support for the LogicPD OMAP35x Torpedo Development kit - for full description please see the products webpage at - http://www.logicpd.com/products/development-kits/zoom-omap35x-torpedo-development-kit - config MACH_OMAP3517EVM bool "OMAP3517/ AM3517 EVM board" depends on ARCH_OMAP3 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 903c85b..9bb78a8 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -243,9 +243,6 @@ obj-$(CONFIG_SOC_OMAP2420) += msdi.o # Specific board support obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o pdata-quirks.o obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o -obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o -obj-$(CONFIG_MACH_OMAP3_TORPEDO) += board-omap3logic.o -obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o obj-$(CONFIG_MACH_NOKIA_N8X0) += board-n8x0.o obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o sdram-nokia.o obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51-peripherals.o diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c deleted file mode 100644 index 6049f60..0000000 --- a/arch/arm/mach-omap2/board-omap3logic.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/board-omap3logic.c - * - * Copyright (C) 2010 Li-Pro.Net - * Stephan Linz <linz@li-pro.net> - * - * Copyright (C) 2010-2012 Logic Product Development, Inc. - * Peter Barada <peter.barada@logicpd.com> - * Ashwin BIhari <ashwin.bihari@logicpd.com> - * - * Modified from Beagle, EVM, and RX51 - * - * 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/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/gpio.h> - -#include <linux/regulator/fixed.h> -#include <linux/regulator/machine.h> - -#include <linux/i2c/twl.h> -#include <linux/mmc/host.h> -#include <linux/usb/phy.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -#include "common.h" -#include "mux.h" -#include "hsmmc.h" -#include "control.h" -#include "common-board-devices.h" -#include "gpmc.h" -#include "gpmc-smsc911x.h" - -#define OMAP3LOGIC_SMSC911X_CS 1 - -#define OMAP3530_LV_SOM_MMC_GPIO_CD 110 -#define OMAP3530_LV_SOM_MMC_GPIO_WP 126 -#define OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ 152 - -#define OMAP3_TORPEDO_MMC_GPIO_CD 127 -#define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ 129 - -static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = { - REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), -}; - -/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ -static struct regulator_init_data omap3logic_vmmc1 = { - .constraints = { - .name = "VMMC1", - .min_uV = 1850000, - .max_uV = 3150000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(omap3logic_vmmc1_supply), - .consumer_supplies = omap3logic_vmmc1_supply, -}; - -static struct twl4030_gpio_platform_data omap3logic_gpio_data = { - .use_leds = true, - .pullups = BIT(1), - .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) - | BIT(13) | BIT(15) | BIT(16) | BIT(17), -}; - -static struct twl4030_usb_data omap3logic_usb_data = { - .usb_mode = T2_USB_MODE_ULPI, -}; - - -static struct twl4030_platform_data omap3logic_twldata = { - /* platform_data for children goes here */ - .gpio = &omap3logic_gpio_data, - .vmmc1 = &omap3logic_vmmc1, - .usb = &omap3logic_usb_data, -}; - -static int __init omap3logic_i2c_init(void) -{ - omap3_pmic_init("twl4030", &omap3logic_twldata); - return 0; -} - -static struct omap2_hsmmc_info __initdata board_mmc_info[] = { - { - .name = "external", - .mmc = 1, - .caps = MMC_CAP_4_BIT_DATA, - .gpio_cd = -EINVAL, - .gpio_wp = -EINVAL, - }, - {} /* Terminator */ -}; - -static void __init board_mmc_init(void) -{ - if (machine_is_omap3530_lv_som()) { - /* OMAP3530 LV SOM board */ - board_mmc_info[0].gpio_cd = OMAP3530_LV_SOM_MMC_GPIO_CD; - board_mmc_info[0].gpio_wp = OMAP3530_LV_SOM_MMC_GPIO_WP; - omap_mux_init_signal("gpio_110", OMAP_PIN_OUTPUT); - omap_mux_init_signal("gpio_126", OMAP_PIN_OUTPUT); - } else if (machine_is_omap3_torpedo()) { - /* OMAP3 Torpedo board */ - board_mmc_info[0].gpio_cd = OMAP3_TORPEDO_MMC_GPIO_CD; - omap_mux_init_signal("gpio_127", OMAP_PIN_OUTPUT); - } else { - /* unsupported board */ - printk(KERN_ERR "%s(): unknown machine type\n", __func__); - return; - } - - omap_hsmmc_init(board_mmc_info); -} - -static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = { - .cs = OMAP3LOGIC_SMSC911X_CS, - .gpio_irq = -EINVAL, - .gpio_reset = -EINVAL, -}; - -/* TODO/FIXME (comment by Peter Barada, LogicPD): - * Fix the PBIAS voltage for Torpedo MMC1 pins that - * are used for other needs (IRQs, etc). */ -static void omap3torpedo_fix_pbias_voltage(void) -{ - u16 control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; - u32 reg; - - if (machine_is_omap3_torpedo()) - { - /* Set the bias for the pin */ - reg = omap_ctrl_readl(control_pbias_offset); - - reg &= ~OMAP343X_PBIASLITEPWRDNZ1; - omap_ctrl_writel(reg, control_pbias_offset); - - /* 100ms delay required for PBIAS configuration */ - msleep(100); - - reg |= OMAP343X_PBIASLITEVMODE1; - reg |= OMAP343X_PBIASLITEPWRDNZ1; - omap_ctrl_writel(reg | 0x300, control_pbias_offset); - } -} - -static inline void __init board_smsc911x_init(void) -{ - if (machine_is_omap3530_lv_som()) { - /* OMAP3530 LV SOM board */ - board_smsc911x_data.gpio_irq = - OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ; - omap_mux_init_signal("gpio_152", OMAP_PIN_INPUT); - } else if (machine_is_omap3_torpedo()) { - /* OMAP3 Torpedo board */ - board_smsc911x_data.gpio_irq = OMAP3_TORPEDO_SMSC911X_GPIO_IRQ; - omap_mux_init_signal("gpio_129", OMAP_PIN_INPUT); - } else { - /* unsupported board */ - printk(KERN_ERR "%s(): unknown machine type\n", __func__); - return; - } - - gpmc_smsc911x_init(&board_smsc911x_data); -} - -#ifdef CONFIG_OMAP_MUX -static struct omap_board_mux board_mux[] __initdata = { - /* mUSB */ - OMAP3_MUX(HSUSB0_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_STP, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), - OMAP3_MUX(HSUSB0_DIR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_NXT, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - OMAP3_MUX(HSUSB0_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), - - { .reg_offset = OMAP_MUX_TERMINATOR }, -}; -#endif - -static struct regulator_consumer_supply dummy_supplies[] = { - REGULATOR_SUPPLY("vddvario", "smsc911x.0"), - REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), -}; - -static void __init omap3logic_init(void) -{ - regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); - omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); - omap3torpedo_fix_pbias_voltage(); - omap3logic_i2c_init(); - omap_serial_init(); - omap_sdrc_init(NULL, NULL); - board_mmc_init(); - board_smsc911x_init(); - - usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); - usb_musb_init(NULL); - - /* Ensure SDRC pins are mux'd for self-refresh */ - omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); - omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); -} - -MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board") - .atag_offset = 0x100, - .reserve = omap_reserve, - .map_io = omap3_map_io, - .init_early = omap35xx_init_early, - .init_irq = omap3_init_irq, - .init_machine = omap3logic_init, - .init_late = omap35xx_init_late, - .init_time = omap3_sync32k_timer_init, - .restart = omap3xxx_restart, -MACHINE_END - -MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board") - .atag_offset = 0x100, - .reserve = omap_reserve, - .map_io = omap3_map_io, - .init_early = omap35xx_init_early, - .init_irq = omap3_init_irq, - .init_machine = omap3logic_init, - .init_late = omap35xx_init_late, - .init_time = omap3_sync32k_timer_init, - .restart = omap3xxx_restart, -MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c deleted file mode 100644 index 969e100..0000000 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * board-omap3pandora.c (Pandora Handheld Console) - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> - -#include <linux/spi/spi.h> -#include <linux/regulator/machine.h> -#include <linux/i2c/twl.h> -#include <linux/omap-gpmc.h> -#include <linux/wl12xx.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/nand.h> -#include <linux/leds.h> -#include <linux/input.h> -#include <linux/input/matrix_keypad.h> -#include <linux/gpio.h> -#include <linux/gpio_keys.h> -#include <linux/mmc/host.h> -#include <linux/mmc/card.h> -#include <linux/regulator/fixed.h> -#include <linux/usb/phy.h> -#include <linux/platform_data/spi-omap2-mcspi.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -#include "common.h" -#include <video/omapdss.h> -#include <video/omap-panel-data.h> -#include <linux/platform_data/mtd-nand-omap2.h> - -#include "mux.h" -#include "sdram-micron-mt46h32m32lf-6.h" -#include "hsmmc.h" -#include "common-board-devices.h" - -#define PANDORA_WIFI_IRQ_GPIO 21 -#define PANDORA_WIFI_NRESET_GPIO 23 -#define OMAP3_PANDORA_TS_GPIO 94 - -static struct mtd_partition omap3pandora_nand_partitions[] = { - { - .name = "xloader", - .offset = 0, - .size = 4 * NAND_BLOCK_SIZE, - .mask_flags = MTD_WRITEABLE - }, { - .name = "uboot", - .offset = MTDPART_OFS_APPEND, - .size = 15 * NAND_BLOCK_SIZE, - }, { - .name = "uboot-env", - .offset = MTDPART_OFS_APPEND, - .size = 1 * NAND_BLOCK_SIZE, - }, { - .name = "boot", - .offset = MTDPART_OFS_APPEND, - .size = 80 * NAND_BLOCK_SIZE, - }, { - .name = "rootfs", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - }, -}; - -static struct omap_nand_platform_data pandora_nand_data = { - .cs = 0, - .devsize = NAND_BUSWIDTH_16, - .xfer_type = NAND_OMAP_PREFETCH_DMA, - .parts = omap3pandora_nand_partitions, - .nr_parts = ARRAY_SIZE(omap3pandora_nand_partitions), -}; - -static struct gpio_led pandora_gpio_leds[] = { - { - .name = "pandora::sd1", - .default_trigger = "mmc0", - .gpio = 128, - }, { - .name = "pandora::sd2", - .default_trigger = "mmc1", - .gpio = 129, - }, { - .name = "pandora::bluetooth", - .gpio = 158, - }, { - .name = "pandora::wifi", - .gpio = 159, - }, -}; - -static struct gpio_led_platform_data pandora_gpio_led_data = { - .leds = pandora_gpio_leds, - .num_leds = ARRAY_SIZE(pandora_gpio_leds), -}; - -static struct platform_device pandora_leds_gpio = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &pandora_gpio_led_data, - }, -}; - -static struct platform_device pandora_backlight = { - .name = "pandora-backlight", - .id = -1, -}; - -#define GPIO_BUTTON(gpio_num, ev_type, ev_code, act_low, descr) \ -{ \ - .gpio = gpio_num, \ - .type = ev_type, \ - .code = ev_code, \ - .active_low = act_low, \ - .debounce_interval = 4, \ - .desc = "btn " descr, \ -} - -#define GPIO_BUTTON_LOW(gpio_num, event_code, description) \ - GPIO_BUTTON(gpio_num, EV_KEY, event_code, 1, description) - -static struct gpio_keys_button pandora_gpio_keys[] = { - GPIO_BUTTON_LOW(110, KEY_UP, "up"), - GPIO_BUTTON_LOW(103, KEY_DOWN, "down"), - GPIO_BUTTON_LOW(96, KEY_LEFT, "left"), - GPIO_BUTTON_LOW(98, KEY_RIGHT, "right"), - GPIO_BUTTON_LOW(109, KEY_PAGEUP, "game 1"), - GPIO_BUTTON_LOW(111, KEY_END, "game 2"), - GPIO_BUTTON_LOW(106, KEY_PAGEDOWN, "game 3"), - GPIO_BUTTON_LOW(101, KEY_HOME, "game 4"), - GPIO_BUTTON_LOW(102, KEY_RIGHTSHIFT, "l"), - GPIO_BUTTON_LOW(97, KEY_KPPLUS, "l2"), - GPIO_BUTTON_LOW(105, KEY_RIGHTCTRL, "r"), - GPIO_BUTTON_LOW(107, KEY_KPMINUS, "r2"), - GPIO_BUTTON_LOW(104, KEY_LEFTCTRL, "ctrl"), - GPIO_BUTTON_LOW(99, KEY_MENU, "menu"), - GPIO_BUTTON_LOW(176, KEY_COFFEE, "hold"), - GPIO_BUTTON(100, EV_KEY, KEY_LEFTALT, 0, "alt"), - GPIO_BUTTON(108, EV_SW, SW_LID, 1, "lid"), -}; - -static struct gpio_keys_platform_data pandora_gpio_key_info = { - .buttons = pandora_gpio_keys, - .nbuttons = ARRAY_SIZE(pandora_gpio_keys), -}; - -static struct platform_device pandora_keys_gpio = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &pandora_gpio_key_info, - }, -}; - -static const uint32_t board_keymap[] = { - /* row, col, code */ - KEY(0, 0, KEY_9), - KEY(0, 1, KEY_8), - KEY(0, 2, KEY_I), - KEY(0, 3, KEY_J), - KEY(0, 4, KEY_N), - KEY(0, 5, KEY_M), - KEY(1, 0, KEY_0), - KEY(1, 1, KEY_7), - KEY(1, 2, KEY_U), - KEY(1, 3, KEY_H), - KEY(1, 4, KEY_B), - KEY(1, 5, KEY_SPACE), - KEY(2, 0, KEY_BACKSPACE), - KEY(2, 1, KEY_6), - KEY(2, 2, KEY_Y), - KEY(2, 3, KEY_G), - KEY(2, 4, KEY_V), - KEY(2, 5, KEY_FN), - KEY(3, 0, KEY_O), - KEY(3, 1, KEY_5), - KEY(3, 2, KEY_T), - KEY(3, 3, KEY_F), - KEY(3, 4, KEY_C), - KEY(4, 0, KEY_P), - KEY(4, 1, KEY_4), - KEY(4, 2, KEY_R), - KEY(4, 3, KEY_D), - KEY(4, 4, KEY_X), - KEY(5, 0, KEY_K), - KEY(5, 1, KEY_3), - KEY(5, 2, KEY_E), - KEY(5, 3, KEY_S), - KEY(5, 4, KEY_Z), - KEY(6, 0, KEY_L), - KEY(6, 1, KEY_2), - KEY(6, 2, KEY_W), - KEY(6, 3, KEY_A), - KEY(6, 4, KEY_DOT), - KEY(7, 0, KEY_ENTER), - KEY(7, 1, KEY_1), - KEY(7, 2, KEY_Q), - KEY(7, 3, KEY_LEFTSHIFT), - KEY(7, 4, KEY_COMMA), -}; - -static struct matrix_keymap_data board_map_data = { - .keymap = board_keymap, - .keymap_size = ARRAY_SIZE(board_keymap), -}; - -static struct twl4030_keypad_data pandora_kp_data = { - .keymap_data = &board_map_data, - .rows = 8, - .cols = 6, - .rep = 1, -}; - -static struct connector_atv_platform_data pandora_tv_pdata = { - .name = "tv", - .source = "venc.0", - .connector_type = OMAP_DSS_VENC_TYPE_SVIDEO, - .invert_polarity = false, -}; - -static struct platform_device pandora_tv_connector_device = { - .name = "connector-analog-tv", - .id = 0, - .dev.platform_data = &pandora_tv_pdata, -}; - -static struct omap_dss_board_info pandora_dss_data = { - .default_display_name = "lcd", -}; - -static void pandora_wl1251_init_card(struct mmc_card *card) -{ - /* - * We have TI wl1251 attached to MMC3. Pass this information to - * SDIO core because it can't be probed by normal methods. - */ - if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) { - card->quirks |= MMC_QUIRK_NONSTD_SDIO; - card->cccr.wide_bus = 1; - card->cis.vendor = 0x104c; - card->cis.device = 0x9066; - card->cis.blksize = 512; - card->cis.max_dtr = 20000000; - } -} - -static struct omap2_hsmmc_info omap3pandora_mmc[] = { - { - .mmc = 1, - .caps = MMC_CAP_4_BIT_DATA, - .gpio_cd = -EINVAL, - .gpio_wp = 126, - .ext_clock = 0, - .deferred = true, - }, - { - .mmc = 2, - .caps = MMC_CAP_4_BIT_DATA, - .gpio_cd = -EINVAL, - .gpio_wp = 127, - .ext_clock = 1, - .transceiver = true, - .deferred = true, - }, - { - .mmc = 3, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, - .gpio_cd = -EINVAL, - .gpio_wp = -EINVAL, - .init_card = pandora_wl1251_init_card, - }, - {} /* Terminator */ -}; - -static int omap3pandora_twl_gpio_setup(struct device *dev, - unsigned gpio, unsigned ngpio) -{ - int ret, gpio_32khz; - - /* gpio + {0,1} is "mmc{0,1}_cd" (input/IRQ) */ - omap3pandora_mmc[0].gpio_cd = gpio + 0; - omap3pandora_mmc[1].gpio_cd = gpio + 1; - omap_hsmmc_late_init(omap3pandora_mmc); - - /* gpio + 13 drives 32kHz buffer for wifi module */ - gpio_32khz = gpio + 13; - ret = gpio_request_one(gpio_32khz, GPIOF_OUT_INIT_HIGH, "wifi 32kHz"); - if (ret < 0) { - pr_err("Cannot get GPIO line %d, ret=%d\n", gpio_32khz, ret); - return -ENODEV; - } - - return 0; -} - -static struct twl4030_gpio_platform_data omap3pandora_gpio_data = { - .setup = omap3pandora_twl_gpio_setup, -}; - -static struct regulator_consumer_supply pandora_vmmc1_supply[] = { - REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), -}; - -static struct regulator_consumer_supply pandora_vmmc2_supply[] = { - REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1") -}; - -static struct regulator_consumer_supply pandora_vmmc3_supply[] = { - REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"), -}; - -static struct regulator_consumer_supply pandora_vdds_supplies[] = { - REGULATOR_SUPPLY("vdds_sdi", "omapdss"), - REGULATOR_SUPPLY("vdds_dsi", "omapdss"), - REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"), - REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), -}; - -static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = { - REGULATOR_SUPPLY("vcc", "spi1.1"), -}; - -static struct regulator_consumer_supply pandora_usb_phy_supply[] = { - REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"), /* hsusb port 2 */ -}; - -/* ads7846 on SPI and 2 nub controllers on I2C */ -static struct regulator_consumer_supply pandora_vaux4_supplies[] = { - REGULATOR_SUPPLY("vcc", "spi1.0"), - REGULATOR_SUPPLY("vcc", "3-0066"), - REGULATOR_SUPPLY("vcc", "3-0067"), -}; - -static struct regulator_consumer_supply pandora_adac_supply[] = { - REGULATOR_SUPPLY("vcc", "soc-audio"), -}; - -/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ -static struct regulator_init_data pandora_vmmc1 = { - .constraints = { - .min_uV = 1850000, - .max_uV = 3150000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_vmmc1_supply), - .consumer_supplies = pandora_vmmc1_supply, -}; - -/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */ -static struct regulator_init_data pandora_vmmc2 = { - .constraints = { - .min_uV = 1850000, - .max_uV = 3150000, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_vmmc2_supply), - .consumer_supplies = pandora_vmmc2_supply, -}; - -/* VAUX1 for LCD */ -static struct regulator_init_data pandora_vaux1 = { - .constraints = { - .min_uV = 3000000, - .max_uV = 3000000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_vcc_lcd_supply), - .consumer_supplies = pandora_vcc_lcd_supply, -}; - -/* VAUX2 for USB host PHY */ -static struct regulator_init_data pandora_vaux2 = { - .constraints = { - .min_uV = 1800000, - .max_uV = 1800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_usb_phy_supply), - .consumer_supplies = pandora_usb_phy_supply, -}; - -/* VAUX4 for ads7846 and nubs */ -static struct regulator_init_data pandora_vaux4 = { - .constraints = { - .min_uV = 2800000, - .max_uV = 2800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_vaux4_supplies), - .consumer_supplies = pandora_vaux4_supplies, -}; - -/* VSIM for audio DAC */ -static struct regulator_init_data pandora_vsim = { - .constraints = { - .min_uV = 2800000, - .max_uV = 2800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_adac_supply), - .consumer_supplies = pandora_adac_supply, -}; - -/* Fixed regulator internal to Wifi module */ -static struct regulator_init_data pandora_vmmc3 = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(pandora_vmmc3_supply), - .consumer_supplies = pandora_vmmc3_supply, -}; - -static struct fixed_voltage_config pandora_vwlan = { - .supply_name = "vwlan", - .microvolts = 1800000, /* 1.8V */ - .gpio = PANDORA_WIFI_NRESET_GPIO, - .startup_delay = 50000, /* 50ms */ - .enable_high = 1, - .enabled_at_boot = 0, - .init_data = &pandora_vmmc3, -}; - -static struct platform_device pandora_vwlan_device = { - .name = "reg-fixed-voltage", - .id = 1, - .dev = { - .platform_data = &pandora_vwlan, - }, -}; - -static struct twl4030_bci_platform_data pandora_bci_data; - -static struct twl4030_power_data pandora_power_data = { - .use_poweroff = true, -}; - -static struct twl4030_platform_data omap3pandora_twldata = { - .gpio = &omap3pandora_gpio_data, - .vmmc1 = &pandora_vmmc1, - .vmmc2 = &pandora_vmmc2, - .vaux1 = &pandora_vaux1, - .vaux2 = &pandora_vaux2, - .vaux4 = &pandora_vaux4, - .vsim = &pandora_vsim, - .keypad = &pandora_kp_data, - .bci = &pandora_bci_data, - .power = &pandora_power_data, -}; - -static struct i2c_board_info __initdata omap3pandora_i2c3_boardinfo[] = { - { - I2C_BOARD_INFO("bq27500", 0x55), - .flags = I2C_CLIENT_WAKE, - }, -}; - -static int __init omap3pandora_i2c_init(void) -{ - omap3_pmic_get_config(&omap3pandora_twldata, - TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO, - TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2); - - omap3pandora_twldata.vdac->constraints.apply_uV = true; - - omap3pandora_twldata.vpll2->constraints.apply_uV = true; - omap3pandora_twldata.vpll2->num_consumer_supplies = - ARRAY_SIZE(pandora_vdds_supplies); - omap3pandora_twldata.vpll2->consumer_supplies = pandora_vdds_supplies; - - omap3_pmic_init("tps65950", &omap3pandora_twldata); - /* i2c2 pins are not connected */ - omap_register_i2c_bus(3, 100, omap3pandora_i2c3_boardinfo, - ARRAY_SIZE(omap3pandora_i2c3_boardinfo)); - return 0; -} - -static struct panel_tpo_td043mtea1_platform_data pandora_lcd_pdata = { - .name = "lcd", - .source = "dpi.0", - - .data_lines = 24, - .nreset_gpio = 157, -}; - -static struct spi_board_info omap3pandora_spi_board_info[] __initdata = { - { - .modalias = "panel-tpo-td043mtea1", - .bus_num = 1, - .chip_select = 1, - .max_speed_hz = 375000, - .platform_data = &pandora_lcd_pdata, - } -}; - -static void __init pandora_wl1251_init(void) -{ - struct wl1251_platform_data pandora_wl1251_pdata; - int ret; - - memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata)); - - pandora_wl1251_pdata.power_gpio = -1; - - ret = gpio_request_one(PANDORA_WIFI_IRQ_GPIO, GPIOF_IN, "wl1251 irq"); - if (ret < 0) - goto fail; - - pandora_wl1251_pdata.irq = gpio_to_irq(PANDORA_WIFI_IRQ_GPIO); - if (pandora_wl1251_pdata.irq < 0) - goto fail_irq; - - pandora_wl1251_pdata.use_eeprom = true; - ret = wl1251_set_platform_data(&pandora_wl1251_pdata); - if (ret < 0) - goto fail_irq; - - return; - -fail_irq: - gpio_free(PANDORA_WIFI_IRQ_GPIO); -fail: - printk(KERN_ERR "wl1251 board initialisation failed\n"); -} - -static struct usbhs_phy_data phy_data[] __initdata = { - { - .port = 2, - .reset_gpio = 16, - .vcc_gpio = -EINVAL, - }, -}; - -static struct platform_device *omap3pandora_devices[] __initdata = { - &pandora_leds_gpio, - &pandora_keys_gpio, - &pandora_vwlan_device, - &pandora_backlight, - &pandora_tv_connector_device, -}; - -static struct usbhs_omap_platform_data usbhs_bdata __initdata = { - .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY, -}; - -#ifdef CONFIG_OMAP_MUX -static struct omap_board_mux board_mux[] __initdata = { - { .reg_offset = OMAP_MUX_TERMINATOR }, -}; -#endif - -static void __init omap3pandora_init(void) -{ - omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); - omap_hsmmc_init(omap3pandora_mmc); - omap3pandora_i2c_init(); - pandora_wl1251_init(); - platform_add_devices(omap3pandora_devices, - ARRAY_SIZE(omap3pandora_devices)); - omap_display_init(&pandora_dss_data); - omap_serial_init(); - omap_sdrc_init(mt46h32m32lf6_sdrc_params, - mt46h32m32lf6_sdrc_params); - spi_register_board_info(omap3pandora_spi_board_info, - ARRAY_SIZE(omap3pandora_spi_board_info)); - omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL); - - usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); - usbhs_init(&usbhs_bdata); - - usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); - usb_musb_init(NULL); - gpmc_nand_init(&pandora_nand_data, NULL); - - /* Ensure SDRC pins are mux'd for self-refresh */ - omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); - omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); -} - -MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console") - .atag_offset = 0x100, - .reserve = omap_reserve, - .map_io = omap3_map_io, - .init_early = omap35xx_init_early, - .init_irq = omap3_init_irq, - .init_machine = omap3pandora_init, - .init_late = omap35xx_init_late, - .init_time = omap3_sync32k_timer_init, - .restart = omap3xxx_restart, -MACHINE_END diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index e1a56d8..1ed4be1 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -117,7 +117,6 @@ static void omap2_show_dma_caps(void) u8 revision = dma_read(REVISION, 0) & 0xff; printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", revision >> 4, revision & 0xf); - return; } static unsigned configure_dma_errata(void) diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index 7add799..f62f832 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -705,7 +705,7 @@ static struct omap_prcm_init_data scrm_data __initdata = { }; #endif -static const struct of_device_id omap_prcm_dt_match_table[] __initconst = { +static const struct of_device_id const omap_prcm_dt_match_table[] __initconst = { #ifdef CONFIG_SOC_AM33XX { .compatible = "ti,am3-prcm", .data = &am3_prm_data }, #endif diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index cac46d8..16b37e7 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -102,38 +102,38 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles, return 0; } -static void omap2_gp_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) +static int omap2_gp_timer_shutdown(struct clock_event_device *evt) +{ + __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate); + return 0; +} + +static int omap2_gp_timer_set_periodic(struct clock_event_device *evt) { u32 period; __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate); - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - period = clkev.rate / HZ; - period -= 1; - /* Looks like we need to first set the load value separately */ - __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, - 0xffffffff - period, OMAP_TIMER_POSTED); - __omap_dm_timer_load_start(&clkev, - OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, - 0xffffffff - period, OMAP_TIMER_POSTED); - break; - case CLOCK_EVT_MODE_ONESHOT: - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - break; - } + period = clkev.rate / HZ; + period -= 1; + /* Looks like we need to first set the load value separately */ + __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, 0xffffffff - period, + OMAP_TIMER_POSTED); + __omap_dm_timer_load_start(&clkev, + OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, + 0xffffffff - period, OMAP_TIMER_POSTED); + return 0; } static struct clock_event_device clockevent_gpt = { - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .rating = 300, - .set_next_event = omap2_gp_timer_set_next_event, - .set_mode = omap2_gp_timer_set_mode, + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .set_next_event = omap2_gp_timer_set_next_event, + .set_state_shutdown = omap2_gp_timer_shutdown, + .set_state_periodic = omap2_gp_timer_set_periodic, + .set_state_oneshot = omap2_gp_timer_shutdown, + .tick_resume = omap2_gp_timer_shutdown, }; static struct property device_disabled = { diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c index 076fd20..e5a35f6 100644 --- a/arch/arm/mach-omap2/vc.c +++ b/arch/arm/mach-omap2/vc.c @@ -563,7 +563,7 @@ struct i2c_init_data { u8 hsscll_12; }; -static const __initdata struct i2c_init_data omap4_i2c_timing_data[] = { +static const struct i2c_init_data const omap4_i2c_timing_data[] __initconst = { { .load = 50, .loadbits = 0x3, diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c index 261bb7c..307676d 100644 --- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c +++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c @@ -95,7 +95,7 @@ static struct voltagedomain *voltagedomains_am35xx[] __initdata = { }; -static const char *sys_clk_name __initdata = "sys_ck"; +static const char *const sys_clk_name __initconst = "sys_ck"; void __init omap3xxx_voltagedomains_init(void) { diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c index 48b22a0..9b1f245 100644 --- a/arch/arm/mach-omap2/voltagedomains44xx_data.c +++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c @@ -92,7 +92,7 @@ static struct voltagedomain *voltagedomains_omap4[] __initdata = { NULL, }; -static const char *sys_clk_name __initdata = "sys_clkin_ck"; +static const char *const sys_clk_name __initconst = "sys_clkin_ck"; void __init omap44xx_voltagedomains_init(void) { diff --git a/arch/arm/mach-omap2/voltagedomains54xx_data.c b/arch/arm/mach-omap2/voltagedomains54xx_data.c index 33d22b8..af5ff64 100644 --- a/arch/arm/mach-omap2/voltagedomains54xx_data.c +++ b/arch/arm/mach-omap2/voltagedomains54xx_data.c @@ -78,7 +78,7 @@ static struct voltagedomain *voltagedomains_omap5[] __initdata = { NULL, }; -static const char *sys_clk_name __initdata = "sys_clkin"; +static const char *const sys_clk_name __initconst = "sys_clkin"; void __init omap54xx_voltagedomains_init(void) { diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 09d2a26..f267e58 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -236,9 +236,7 @@ static int __init dns323_read_mac_addr(void) } iounmap(mac_page); - printk("DNS-323: Found ethernet MAC address: "); - for (i = 0; i < 6; i++) - printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n"); + printk("DNS-323: Found ethernet MAC address: %pM\n", addr); memcpy(dns323_eth_data.mac_addr, addr, 6); diff --git a/arch/arm/mach-orion5x/tsx09-common.c b/arch/arm/mach-orion5x/tsx09-common.c index 7189827..24b2959 100644 --- a/arch/arm/mach-orion5x/tsx09-common.c +++ b/arch/arm/mach-orion5x/tsx09-common.c @@ -101,9 +101,7 @@ static int __init qnap_tsx09_check_mac_addr(const char *addr_str) addr[i] = byte; } - printk(KERN_INFO "tsx09: found ethernet mac address "); - for (i = 0; i < 6; i++) - printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n"); + printk(KERN_INFO "tsx09: found ethernet mac address %pM\n", addr); memcpy(qnap_tsx09_eth_data.mac_addr, addr, 6); diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig index e03d8b5..9ab8932 100644 --- a/arch/arm/mach-prima2/Kconfig +++ b/arch/arm/mach-prima2/Kconfig @@ -4,6 +4,7 @@ menuconfig ARCH_SIRF select ARCH_REQUIRE_GPIOLIB select GENERIC_IRQ_CHIP select NO_IOPORT_MAP + select REGMAP select PINCTRL select PINCTRL_SIRF help diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c index 8f66d8f..d4852d2 100644 --- a/arch/arm/mach-prima2/rtciobrg.c +++ b/arch/arm/mach-prima2/rtciobrg.c @@ -1,5 +1,5 @@ /* - * RTC I/O Bridge interfaces for CSR SiRFprimaII + * RTC I/O Bridge interfaces for CSR SiRFprimaII/atlas7 * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module * * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/io.h> +#include <linux/regmap.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> @@ -66,6 +67,7 @@ u32 sirfsoc_rtc_iobrg_readl(u32 addr) { unsigned long flags, val; + /* TODO: add hwspinlock to sync with M3 */ spin_lock_irqsave(&rtciobrg_lock, flags); val = __sirfsoc_rtc_iobrg_readl(addr); @@ -90,6 +92,7 @@ void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr) { unsigned long flags; + /* TODO: add hwspinlock to sync with M3 */ spin_lock_irqsave(&rtciobrg_lock, flags); sirfsoc_rtc_iobrg_pre_writel(val, addr); @@ -102,6 +105,45 @@ void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr) } EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel); + +static int regmap_iobg_regwrite(void *context, unsigned int reg, + unsigned int val) +{ + sirfsoc_rtc_iobrg_writel(val, reg); + return 0; +} + +static int regmap_iobg_regread(void *context, unsigned int reg, + unsigned int *val) +{ + *val = (u32)sirfsoc_rtc_iobrg_readl(reg); + return 0; +} + +static struct regmap_bus regmap_iobg = { + .reg_write = regmap_iobg_regwrite, + .reg_read = regmap_iobg_regread, +}; + +/** + * devm_regmap_init_iobg(): Initialise managed register map + * + * @iobg: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +struct regmap *devm_regmap_init_iobg(struct device *dev, + const struct regmap_config *config) +{ + const struct regmap_bus *bus = ®map_iobg; + + return devm_regmap_init(dev, bus, dev, config); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_iobg); + static const struct of_device_id rtciobrg_ids[] = { { .compatible = "sirf,prima2-rtciobg" }, {} @@ -132,7 +174,7 @@ static int __init sirfsoc_rtciobrg_init(void) } postcore_initcall(sirfsoc_rtciobrg_init); -MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>, " - "Barry Song <baohua.song@csr.com>"); +MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>"); +MODULE_AUTHOR("Barry Song <baohua.song@csr.com>"); MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge"); MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index d897292..70366b3 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -496,18 +496,18 @@ static struct irq_chip balloon3_irq_chip = { .irq_unmask = balloon3_unmask_irq, }; -static void balloon3_irq_handler(unsigned int irq, struct irq_desc *desc) +static void balloon3_irq_handler(unsigned int __irq, struct irq_desc *desc) { unsigned long pending = __raw_readl(BALLOON3_INT_CONTROL_REG) & balloon3_irq_enabled; do { - /* clear useless edge notification */ - if (desc->irq_data.chip->irq_ack) { - struct irq_data *d; + struct irq_data *d = irq_desc_get_irq_data(desc); + struct irq_chip *chip = irq_data_get_chip(d); + unsigned int irq; - d = irq_get_irq_data(BALLOON3_AUX_NIRQ); - desc->irq_data.chip->irq_ack(d); - } + /* clear useless edge notification */ + if (chip->irq_ack) + chip->irq_ack(d); while (pending) { irq = BALLOON3_IRQ(0) + __ffs(pending); @@ -528,7 +528,7 @@ static void __init balloon3_init_irq(void) for (irq = BALLOON3_IRQ(0); irq <= BALLOON3_IRQ(7); irq++) { irq_set_chip_and_handler(irq, &balloon3_irq_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } irq_set_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler); diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c index d8f816c..1fa79f1 100644 --- a/arch/arm/mach-pxa/cm-x2xx-pci.c +++ b/arch/arm/mach-pxa/cm-x2xx-pci.c @@ -29,8 +29,9 @@ void __iomem *it8152_base_address; static int cmx2xx_it8152_irq_gpio; -static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc) +static void cmx2xx_it8152_irq_demux(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq = irq_desc_get_irq(desc); /* clear our parent irq */ desc->irq_data.chip->irq_ack(&desc->irq_data); diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 98608c5..9c10248 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -133,7 +133,6 @@ static int pxa_irq_map(struct irq_domain *h, unsigned int virq, irq_set_chip_and_handler(virq, &pxa_internal_irq_chip, handle_level_irq); irq_set_chip_data(virq, base); - set_irq_flags(virq, IRQF_VALID); return 0; } diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index eaee2c2..b070167 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -120,8 +120,9 @@ static struct irq_chip lpd270_irq_chip = { .irq_unmask = lpd270_unmask_irq, }; -static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc) +static void lpd270_irq_handler(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq; unsigned long pending; pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled; @@ -151,7 +152,7 @@ static void __init lpd270_init_irq(void) for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) { irq_set_chip_and_handler(irq, &lpd270_irq_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), lpd270_irq_handler); irq_set_irq_type(PXA_GPIO_TO_IRQ(0), IRQ_TYPE_EDGE_FALLING); diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index 2897da2..9a0c8af 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -284,8 +284,9 @@ static struct irq_chip pcm990_irq_chip = { .irq_unmask = pcm990_unmask_irq, }; -static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc) +static void pcm990_irq_handler(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq; unsigned long pending; pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR); @@ -311,7 +312,7 @@ static void __init pcm990_init_irq(void) for (irq = PCM027_IRQ(0); irq <= PCM027_IRQ(3); irq++) { irq_set_chip_and_handler(irq, &pcm990_irq_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } /* disable all Interrupts */ diff --git a/arch/arm/mach-pxa/pxa-dt.c b/arch/arm/mach-pxa/pxa-dt.c index 7e0e5bd..8e0e62c 100644 --- a/arch/arm/mach-pxa/pxa-dt.c +++ b/arch/arm/mach-pxa/pxa-dt.c @@ -19,7 +19,7 @@ #include "generic.h" #ifdef CONFIG_PXA3xx -static const struct of_dev_auxdata pxa3xx_auxdata_lookup[] __initconst = { +static const struct of_dev_auxdata const pxa3xx_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("mrvl,pxa-uart", 0x40100000, "pxa2xx-uart.0", NULL), OF_DEV_AUXDATA("mrvl,pxa-uart", 0x40200000, "pxa2xx-uart.1", NULL), OF_DEV_AUXDATA("mrvl,pxa-uart", 0x40700000, "pxa2xx-uart.2", NULL), @@ -39,7 +39,7 @@ static void __init pxa3xx_dt_init(void) pxa3xx_auxdata_lookup, NULL); } -static const char *pxa3xx_dt_board_compat[] __initdata = { +static const char *const pxa3xx_dt_board_compat[] __initconst = { "marvell,pxa300", "marvell,pxa310", "marvell,pxa320", diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index bd4cbef..e1362c0 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -325,7 +325,7 @@ static void __init pxa_init_ext_wakeup_irq(int (*fn)(struct irq_data *, for (irq = IRQ_WAKEUP0; irq <= IRQ_WAKEUP1; irq++) { irq_set_chip_and_handler(irq, &pxa_ext_wakeup_chip, handle_edge_irq); - set_irq_flags(irq, IRQF_VALID); + irq_clear_status_flags(irq, IRQ_NOREQUEST); } pxa_ext_wakeup_chip.irq_set_wake = fn; diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index de3b080..4841d6c 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c @@ -276,8 +276,9 @@ static inline unsigned long viper_irq_pending(void) viper_irq_enabled_mask; } -static void viper_irq_handler(unsigned int irq, struct irq_desc *desc) +static void viper_irq_handler(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq; unsigned long pending; pending = viper_irq_pending(); @@ -313,7 +314,7 @@ static void __init viper_init_irq(void) isa_irq = viper_bit_to_irq(level); irq_set_chip_and_handler(isa_irq, &viper_irq_chip, handle_edge_irq); - set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(isa_irq, IRQ_NOREQUEST | IRQ_NOPROBE); } irq_set_chained_handler(gpio_to_irq(VIPER_CPLD_GPIO), diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index ac2ae5c..a55827b 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -105,8 +105,9 @@ static inline unsigned long zeus_irq_pending(void) return __raw_readw(ZEUS_CPLD_ISA_IRQ) & zeus_irq_enabled_mask; } -static void zeus_irq_handler(unsigned int irq, struct irq_desc *desc) +static void zeus_irq_handler(unsigned int __irq, struct irq_desc *desc) { + unsigned int irq; unsigned long pending; pending = zeus_irq_pending(); @@ -151,7 +152,7 @@ static void __init zeus_init_irq(void) isa_irq = zeus_bit_to_irq(level); irq_set_chip_and_handler(isa_irq, &zeus_irq_chip, handle_edge_irq); - set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(isa_irq, IRQ_NOREQUEST | IRQ_NOPROBE); } irq_set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING); diff --git a/arch/arm/mach-realview/realview-dt.c b/arch/arm/mach-realview/realview-dt.c index cc28b89..382cc1b 100644 --- a/arch/arm/mach-realview/realview-dt.c +++ b/arch/arm/mach-realview/realview-dt.c @@ -13,7 +13,7 @@ #include <asm/hardware/cache-l2x0.h> #include "core.h" -static const char *realview_dt_platform_compat[] __initconst = { +static const char *const realview_dt_platform_compat[] __initconst = { "arm,realview-eb", "arm,realview-pb1176", "arm,realview-pb11mp", diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c index fcb1d59..f726d4c 100644 --- a/arch/arm/mach-rpc/ecard.c +++ b/arch/arm/mach-rpc/ecard.c @@ -946,7 +946,7 @@ static int __init ecard_probe(int slot, unsigned irq, card_type_t type) irq_set_chip_and_handler(ec->irq, &ecard_chip, handle_level_irq); irq_set_chip_data(ec->irq, ec); - set_irq_flags(ec->irq, IRQF_VALID); + irq_clear_status_flags(ec->irq, IRQ_NOREQUEST); } #ifdef CONFIG_ARCH_RPC diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c index 3e4fa84..66502e6 100644 --- a/arch/arm/mach-rpc/irq.c +++ b/arch/arm/mach-rpc/irq.c @@ -117,7 +117,7 @@ extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end; void __init rpc_init_irq(void) { - unsigned int irq, flags; + unsigned int irq, clr, set = 0; iomd_writeb(0, IOMD_IRQMASKA); iomd_writeb(0, IOMD_IRQMASKB); @@ -128,37 +128,37 @@ void __init rpc_init_irq(void) &rpc_default_fiq_end - &rpc_default_fiq_start); for (irq = 0; irq < NR_IRQS; irq++) { - flags = IRQF_VALID; + clr = IRQ_NOREQUEST; if (irq <= 6 || (irq >= 9 && irq <= 15)) - flags |= IRQF_PROBE; + clr |= IRQ_NOPROBE; if (irq == 21 || (irq >= 16 && irq <= 19) || irq == IRQ_KEYBOARDTX) - flags |= IRQF_NOAUTOEN; + set |= IRQ_NOAUTOEN; switch (irq) { case 0 ... 7: irq_set_chip_and_handler(irq, &iomd_a_chip, handle_level_irq); - set_irq_flags(irq, flags); + irq_modify_status(irq, clr, set); break; case 8 ... 15: irq_set_chip_and_handler(irq, &iomd_b_chip, handle_level_irq); - set_irq_flags(irq, flags); + irq_modify_status(irq, clr, set); break; case 16 ... 21: irq_set_chip_and_handler(irq, &iomd_dma_chip, handle_level_irq); - set_irq_flags(irq, flags); + irq_modify_status(irq, clr, set); break; case 64 ... 71: irq_set_chip(irq, &iomd_fiq_chip); - set_irq_flags(irq, IRQF_VALID); + irq_modify_status(irq, clr, set); break; } } diff --git a/arch/arm/mach-s3c24xx/bast-irq.c b/arch/arm/mach-s3c24xx/bast-irq.c index cb1b791..ced1ab86 100644 --- a/arch/arm/mach-s3c24xx/bast-irq.c +++ b/arch/arm/mach-s3c24xx/bast-irq.c @@ -147,7 +147,7 @@ static __init int bast_irq_init(void) irq_set_chip_and_handler(irqno, &bast_pc104_chip, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); + irq_clear_status_flags(irqno, IRQ_NOREQUEST); } } diff --git a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c index f886478..5f028ff 100644 --- a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c +++ b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c @@ -39,7 +39,7 @@ static void __init s3c2416_dt_machine_init(void) s3c_pm_init(); } -static char const *s3c2416_dt_compat[] __initdata = { +static const char *const s3c2416_dt_compat[] __initconst = { "samsung,s3c2416", "samsung,s3c2450", NULL diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c index 16547f2..06ba943 100644 --- a/arch/arm/mach-s3c64xx/common.c +++ b/arch/arm/mach-s3c64xx/common.c @@ -420,7 +420,7 @@ static int __init s3c64xx_init_irq_eint(void) for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) { irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq); irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq)); - set_irq_flags(irq, IRQF_VALID); + irq_clear_status_flags(irq, IRQ_NOREQUEST); } irq_set_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3); diff --git a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c index 2fddf38..94e5bcf 100644 --- a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c +++ b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c @@ -61,7 +61,7 @@ static void s3c64xx_dt_restart(enum reboot_mode mode, const char *cmd) soft_restart(0); } -static char const *s3c64xx_dt_compat[] __initdata = { +static const char *const s3c64xx_dt_compat[] __initconst = { "samsung,s3c6400", "samsung,s3c6410", NULL diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index 99d9a3b..6d237b4 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -320,10 +320,10 @@ static int neponset_probe(struct platform_device *dev) irq_set_chip_and_handler(d->irq_base + NEP_IRQ_SMC91X, &nochip, handle_simple_irq); - set_irq_flags(d->irq_base + NEP_IRQ_SMC91X, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(d->irq_base + NEP_IRQ_SMC91X, IRQ_NOREQUEST | IRQ_NOPROBE); irq_set_chip_and_handler(d->irq_base + NEP_IRQ_USAR, &nochip, handle_simple_irq); - set_irq_flags(d->irq_base + NEP_IRQ_USAR, IRQF_VALID | IRQF_PROBE); + irq_clear_status_flags(d->irq_base + NEP_IRQ_USAR, IRQ_NOREQUEST | IRQ_NOPROBE); irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip); irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 1fe775c..26505d4 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -96,22 +96,6 @@ if ARCH_SHMOBILE_LEGACY comment "Renesas ARM SoCs System Type" -config ARCH_SH73A0 - bool "SH-Mobile AG5 (R8A73A00)" - select ARCH_RMOBILE - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_GIC - select I2C - select SH_INTC - select RENESAS_INTC_IRQPIN - -config ARCH_R8A7740 - bool "R-Mobile A1 (R8A77400)" - select ARCH_RMOBILE - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_GIC - select RENESAS_INTC_IRQPIN - config ARCH_R8A7778 bool "R-Car M1A (R8A77781)" select ARCH_RCAR_GEN1 @@ -126,15 +110,6 @@ config ARCH_R8A7779 comment "Renesas ARM SoCs Board Type" -config MACH_ARMADILLO800EVA - bool "Armadillo-800 EVA board" - depends on ARCH_R8A7740 - select ARCH_REQUIRE_GPIOLIB - select REGULATOR_FIXED_VOLTAGE if REGULATOR - select SMSC_PHY if SH_ETH - select SND_SOC_WM8978 if SND_SIMPLE_CARD && I2C - select USE_OF - config MACH_BOCKW bool "BOCK-W platform" depends on ARCH_R8A7778 @@ -157,14 +132,6 @@ config MACH_BOCKW_REFERENCE This is intended to aid developers -config MACH_KZM9G - bool "KZM-A9-GT board" - depends on ARCH_SH73A0 - select ARCH_REQUIRE_GPIOLIB - select REGULATOR_FIXED_VOLTAGE if REGULATOR - select SND_SOC_AK4642 if SND_SIMPLE_CARD - select USE_OF - comment "Renesas ARM SoCs System Configuration" config CPU_HAS_INTEVT diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 039445c..29687a7 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -6,9 +6,9 @@ obj-y := timer.o console.o # CPU objects -obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o pm-sh73a0.o +obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o obj-$(CONFIG_ARCH_R8A73A4) += setup-r8a73a4.o -obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o pm-r8a7740.o +obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o pm-r8a7779.o obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o @@ -20,8 +20,6 @@ obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o # Clock objects ifndef CONFIG_COMMON_CLK obj-y += clock.o -obj-$(CONFIG_ARCH_SH73A0) += clock-sh73a0.o -obj-$(CONFIG_ARCH_R8A7740) += clock-r8a7740.o obj-$(CONFIG_ARCH_R8A7778) += clock-r8a7778.o endif @@ -53,9 +51,6 @@ obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o ifndef CONFIG_ARCH_SHMOBILE_MULTI obj-$(CONFIG_MACH_BOCKW) += board-bockw.o obj-$(CONFIG_MACH_BOCKW_REFERENCE) += board-bockw-reference.o -obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o -obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o intc-sh73a0.o -endif # Framework support obj-$(CONFIG_SMP) += $(smp-y) diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot index 7e7e0f4..a489fe9 100644 --- a/arch/arm/mach-shmobile/Makefile.boot +++ b/arch/arm/mach-shmobile/Makefile.boot @@ -1,9 +1,7 @@ # per-board load address for uImage loadaddr-y := -loadaddr-$(CONFIG_MACH_ARMADILLO800EVA) += 0x40008000 loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000 loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000 -loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000 __ZRELADDR := $(sort $(loadaddr-y)) zreladdr-y += $(__ZRELADDR) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c deleted file mode 100644 index bf37e3c..0000000 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ /dev/null @@ -1,1365 +0,0 @@ -/* - * armadillo 800 eva board support - * - * Copyright (C) 2012 Renesas Solutions Corp. - * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - */ - -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/gpio.h> -#include <linux/gpio_keys.h> -#include <linux/i2c-gpio.h> -#include <linux/input.h> -#include <linux/irq.h> -#include <linux/kernel.h> -#include <linux/mfd/tmio.h> -#include <linux/mmc/host.h> -#include <linux/mmc/sh_mmcif.h> -#include <linux/mmc/sh_mobile_sdhi.h> -#include <linux/pinctrl/machine.h> -#include <linux/platform_data/st1232_pdata.h> -#include <linux/platform_device.h> -#include <linux/pwm.h> -#include <linux/pwm_backlight.h> -#include <linux/reboot.h> -#include <linux/regulator/driver.h> -#include <linux/regulator/fixed.h> -#include <linux/regulator/gpio-regulator.h> -#include <linux/regulator/machine.h> -#include <linux/sh_eth.h> -#include <linux/usb/renesas_usbhs.h> -#include <linux/videodev2.h> - -#include <asm/hardware/cache-l2x0.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/time.h> -#include <asm/page.h> -#include <media/mt9t112.h> -#include <media/sh_mobile_ceu.h> -#include <media/soc_camera.h> -#include <sound/sh_fsi.h> -#include <sound/simple_card.h> -#include <video/sh_mobile_hdmi.h> -#include <video/sh_mobile_lcdc.h> - -#include "common.h" -#include "irqs.h" -#include "pm-rmobile.h" -#include "r8a7740.h" -#include "sh-gpio.h" - -/* - * CON1 Camera Module - * CON2 Extension Bus - * CON3 HDMI Output - * CON4 Composite Video Output - * CON5 H-UDI JTAG - * CON6 ARM JTAG - * CON7 SD1 - * CON8 SD2 - * CON9 RTC BackUp - * CON10 Monaural Mic Input - * CON11 Stereo Headphone Output - * CON12 Audio Line Output(L) - * CON13 Audio Line Output(R) - * CON14 AWL13 Module - * CON15 Extension - * CON16 LCD1 - * CON17 LCD2 - * CON19 Power Input - * CON20 USB1 - * CON21 USB2 - * CON22 Serial - * CON23 LAN - * CON24 USB3 - * LED1 Camera LED(Yellow) - * LED2 Power LED (Green) - * ED3-LED6 User LED(Yellow) - * LED7 LAN link LED(Green) - * LED8 LAN activity LED(Yellow) - */ - -/* - * DipSwitch - * - * SW1 - * - * -12345678-+---------------+---------------------------- - * 1 | boot | hermit - * 0 | boot | OS auto boot - * -12345678-+---------------+---------------------------- - * 00 | boot device | eMMC - * 10 | boot device | SDHI0 (CON7) - * 01 | boot device | - - * 11 | boot device | Extension Buss (CS0) - * -12345678-+---------------+---------------------------- - * 0 | Extension Bus | D8-D15 disable, eMMC enable - * 1 | Extension Bus | D8-D15 enable, eMMC disable - * -12345678-+---------------+---------------------------- - * 0 | SDHI1 | COM8 disable, COM14 enable - * 1 | SDHI1 | COM8 enable, COM14 disable - * -12345678-+---------------+---------------------------- - * 0 | USB0 | COM20 enable, COM24 disable - * 1 | USB0 | COM20 disable, COM24 enable - * -12345678-+---------------+---------------------------- - * 00 | JTAG | SH-X2 - * 10 | JTAG | ARM - * 01 | JTAG | - - * 11 | JTAG | Boundary Scan - *-----------+---------------+---------------------------- - */ - -/* - * FSI-WM8978 - * - * this command is required when playback. - * - * # amixer set "Headphone" 50 - * - * this command is required when capture. - * - * # amixer set "Input PGA" 15 - * # amixer set "Left Input Mixer MicP" on - * # amixer set "Left Input Mixer MicN" on - * # amixer set "Right Input Mixer MicN" on - * # amixer set "Right Input Mixer MicP" on - */ - -/* - * USB function - * - * When you use USB Function, - * set SW1.6 ON, and connect cable to CN24. - * - * USBF needs workaround on R8A7740 chip. - * These are a little bit complex. - * see - * usbhsf_power_ctrl() - */ -#define IRQ7 irq_pin(7) -#define USBCR1 IOMEM(0xe605810a) -#define USBH 0xC6700000 -#define USBH_USBCTR 0x10834 - -struct usbhsf_private { - struct clk *phy; - struct clk *usb24; - struct clk *pci; - struct clk *func; - struct clk *host; - void __iomem *usbh_base; - struct renesas_usbhs_platform_info info; -}; - -#define usbhsf_get_priv(pdev) \ - container_of(renesas_usbhs_get_info(pdev), \ - struct usbhsf_private, info) - -static int usbhsf_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -static int usbhsf_power_ctrl(struct platform_device *pdev, - void __iomem *base, int enable) -{ - struct usbhsf_private *priv = usbhsf_get_priv(pdev); - - /* - * Work around for USB Function. - * It needs USB host clock, and settings - */ - if (enable) { - /* - * enable all the related usb clocks - * for usb workaround - */ - clk_enable(priv->usb24); - clk_enable(priv->pci); - clk_enable(priv->host); - clk_enable(priv->func); - clk_enable(priv->phy); - - /* - * set USBCR1 - * - * Port1 is driven by USB function, - * Port2 is driven by USB HOST - * One HOST (Port1 or Port2 is HOST) - * USB PLL input clock = 24MHz - */ - __raw_writew(0xd750, USBCR1); - mdelay(1); - - /* - * start USB Host - */ - __raw_writel(0x0000000c, priv->usbh_base + USBH_USBCTR); - __raw_writel(0x00000008, priv->usbh_base + USBH_USBCTR); - mdelay(10); - - /* - * USB PHY Power ON - */ - __raw_writew(0xd770, USBCR1); - __raw_writew(0x4000, base + 0x102); /* USBF :: SUSPMODE */ - - } else { - __raw_writel(0x0000010f, priv->usbh_base + USBH_USBCTR); - __raw_writew(0xd7c0, USBCR1); /* GPIO */ - - clk_disable(priv->phy); - clk_disable(priv->func); /* usb work around */ - clk_disable(priv->host); /* usb work around */ - clk_disable(priv->pci); /* usb work around */ - clk_disable(priv->usb24); /* usb work around */ - } - - return 0; -} - -static int usbhsf_get_vbus(struct platform_device *pdev) -{ - return gpio_get_value(209); -} - -static irqreturn_t usbhsf_interrupt(int irq, void *data) -{ - struct platform_device *pdev = data; - - renesas_usbhs_call_notify_hotplug(pdev); - - return IRQ_HANDLED; -} - -static int usbhsf_hardware_exit(struct platform_device *pdev) -{ - struct usbhsf_private *priv = usbhsf_get_priv(pdev); - - if (!IS_ERR(priv->phy)) - clk_put(priv->phy); - if (!IS_ERR(priv->usb24)) - clk_put(priv->usb24); - if (!IS_ERR(priv->pci)) - clk_put(priv->pci); - if (!IS_ERR(priv->host)) - clk_put(priv->host); - if (!IS_ERR(priv->func)) - clk_put(priv->func); - if (priv->usbh_base) - iounmap(priv->usbh_base); - - priv->phy = NULL; - priv->usb24 = NULL; - priv->pci = NULL; - priv->host = NULL; - priv->func = NULL; - priv->usbh_base = NULL; - - free_irq(IRQ7, pdev); - - return 0; -} - -static int usbhsf_hardware_init(struct platform_device *pdev) -{ - struct usbhsf_private *priv = usbhsf_get_priv(pdev); - int ret; - - priv->phy = clk_get(&pdev->dev, "phy"); - priv->usb24 = clk_get(&pdev->dev, "usb24"); - priv->pci = clk_get(&pdev->dev, "pci"); - priv->func = clk_get(&pdev->dev, "func"); - priv->host = clk_get(&pdev->dev, "host"); - priv->usbh_base = ioremap_nocache(USBH, 0x20000); - - if (IS_ERR(priv->phy) || - IS_ERR(priv->usb24) || - IS_ERR(priv->pci) || - IS_ERR(priv->host) || - IS_ERR(priv->func) || - !priv->usbh_base) { - dev_err(&pdev->dev, "USB clock setting failed\n"); - usbhsf_hardware_exit(pdev); - return -EIO; - } - - ret = request_irq(IRQ7, usbhsf_interrupt, IRQF_TRIGGER_NONE, - dev_name(&pdev->dev), pdev); - if (ret) { - dev_err(&pdev->dev, "request_irq err\n"); - return ret; - } - irq_set_irq_type(IRQ7, IRQ_TYPE_EDGE_BOTH); - - /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */ - clk_set_rate(priv->usb24, - clk_get_rate(clk_get_parent(priv->usb24))); - - return 0; -} - -static struct usbhsf_private usbhsf_private = { - .info = { - .platform_callback = { - .get_id = usbhsf_get_id, - .get_vbus = usbhsf_get_vbus, - .hardware_init = usbhsf_hardware_init, - .hardware_exit = usbhsf_hardware_exit, - .power_ctrl = usbhsf_power_ctrl, - }, - .driver_param = { - .buswait_bwait = 5, - .detection_delay = 5, - .d0_rx_id = SHDMA_SLAVE_USBHS_RX, - .d1_tx_id = SHDMA_SLAVE_USBHS_TX, - }, - } -}; - -static struct resource usbhsf_resources[] = { - { - .name = "USBHS", - .start = 0xe6890000, - .end = 0xe6890104 - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = gic_spi(51), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device usbhsf_device = { - .name = "renesas_usbhs", - .dev = { - .platform_data = &usbhsf_private.info, - }, - .id = -1, - .num_resources = ARRAY_SIZE(usbhsf_resources), - .resource = usbhsf_resources, -}; - -/* Ether */ -static struct sh_eth_plat_data sh_eth_platdata = { - .phy = 0x00, /* LAN8710A */ - .edmac_endian = EDMAC_LITTLE_ENDIAN, - .phy_interface = PHY_INTERFACE_MODE_MII, -}; - -static struct resource sh_eth_resources[] = { - { - .start = 0xe9a00000, - .end = 0xe9a00800 - 1, - .flags = IORESOURCE_MEM, - }, { - .start = 0xe9a01800, - .end = 0xe9a02000 - 1, - .flags = IORESOURCE_MEM, - }, { - .start = gic_spi(110), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device sh_eth_device = { - .name = "r8a7740-gether", - .id = -1, - .dev = { - .platform_data = &sh_eth_platdata, - .dma_mask = &sh_eth_device.dev.coherent_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, - .resource = sh_eth_resources, - .num_resources = ARRAY_SIZE(sh_eth_resources), -}; - -/* PWM */ -static struct resource pwm_resources[] = { - [0] = { - .start = 0xe6600000, - .end = 0xe66000ff, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device pwm_device = { - .name = "renesas-tpu-pwm", - .id = -1, - .num_resources = ARRAY_SIZE(pwm_resources), - .resource = pwm_resources, -}; - -static struct pwm_lookup pwm_lookup[] = { - PWM_LOOKUP("renesas-tpu-pwm", 2, "pwm-backlight.0", NULL, - 33333, PWM_POLARITY_INVERSED), -}; - -/* LCDC and backlight */ -static struct platform_pwm_backlight_data pwm_backlight_data = { - .lth_brightness = 50, - .max_brightness = 255, - .dft_brightness = 255, - .pwm_period_ns = 33333, /* 30kHz */ - .enable_gpio = 61, -}; - -static struct platform_device pwm_backlight_device = { - .name = "pwm-backlight", - .dev = { - .platform_data = &pwm_backlight_data, - }, -}; - -static struct fb_videomode lcdc0_mode = { - .name = "AMPIER/AM-800480", - .xres = 800, - .yres = 480, - .left_margin = 88, - .right_margin = 40, - .hsync_len = 128, - .upper_margin = 20, - .lower_margin = 5, - .vsync_len = 5, - .sync = 0, -}; - -static struct sh_mobile_lcdc_info lcdc0_info = { - .clock_source = LCDC_CLK_BUS, - .ch[0] = { - .chan = LCDC_CHAN_MAINLCD, - .fourcc = V4L2_PIX_FMT_RGB565, - .interface_type = RGB24, - .clock_divider = 5, - .flags = 0, - .lcd_modes = &lcdc0_mode, - .num_modes = 1, - .panel_cfg = { - .width = 111, - .height = 68, - }, - }, -}; - -static struct resource lcdc0_resources[] = { - [0] = { - .name = "LCD0", - .start = 0xfe940000, - .end = 0xfe943fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(177), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device lcdc0_device = { - .name = "sh_mobile_lcdc_fb", - .num_resources = ARRAY_SIZE(lcdc0_resources), - .resource = lcdc0_resources, - .id = 0, - .dev = { - .platform_data = &lcdc0_info, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -/* - * LCDC1/HDMI - */ -static struct sh_mobile_hdmi_info hdmi_info = { - .flags = HDMI_OUTPUT_PUSH_PULL | - HDMI_OUTPUT_POLARITY_HI | - HDMI_32BIT_REG | - HDMI_HAS_HTOP1 | - HDMI_SND_SRC_SPDIF, -}; - -static struct resource hdmi_resources[] = { - [0] = { - .name = "HDMI", - .start = 0xe6be0000, - .end = 0xe6be03ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(131), - .flags = IORESOURCE_IRQ, - }, - [2] = { - .name = "HDMI emma3pf", - .start = 0xe6be4000, - .end = 0xe6be43ff, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device hdmi_device = { - .name = "sh-mobile-hdmi", - .num_resources = ARRAY_SIZE(hdmi_resources), - .resource = hdmi_resources, - .id = -1, - .dev = { - .platform_data = &hdmi_info, - }, -}; - -static const struct fb_videomode lcdc1_mode = { - .name = "HDMI 720p", - .xres = 1280, - .yres = 720, - .pixclock = 13468, - .left_margin = 220, - .right_margin = 110, - .hsync_len = 40, - .upper_margin = 20, - .lower_margin = 5, - .vsync_len = 5, - .refresh = 60, - .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, -}; - -static struct sh_mobile_lcdc_info hdmi_lcdc_info = { - .clock_source = LCDC_CLK_PERIPHERAL, /* HDMI clock */ - .ch[0] = { - .chan = LCDC_CHAN_MAINLCD, - .fourcc = V4L2_PIX_FMT_RGB565, - .interface_type = RGB24, - .clock_divider = 1, - .flags = LCDC_FLAGS_DWPOL, - .lcd_modes = &lcdc1_mode, - .num_modes = 1, - .tx_dev = &hdmi_device, - .panel_cfg = { - .width = 1280, - .height = 720, - }, - }, -}; - -static struct resource hdmi_lcdc_resources[] = { - [0] = { - .name = "LCDC1", - .start = 0xfe944000, - .end = 0xfe948000 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(178), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device hdmi_lcdc_device = { - .name = "sh_mobile_lcdc_fb", - .num_resources = ARRAY_SIZE(hdmi_lcdc_resources), - .resource = hdmi_lcdc_resources, - .id = 1, - .dev = { - .platform_data = &hdmi_lcdc_info, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -/* LEDS */ -static struct gpio_led gpio_leds[] = { - { - .name = "LED3", - .gpio = 102, - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, { - .name = "LED4", - .gpio = 111, - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, { - .name = "LED5", - .gpio = 110, - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, { - .name = "LED6", - .gpio = 177, - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, -}; - -static struct gpio_led_platform_data leds_gpio_info = { - .leds = gpio_leds, - .num_leds = ARRAY_SIZE(gpio_leds), -}; - -static struct platform_device leds_gpio_device = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &leds_gpio_info, - }, -}; - -/* GPIO KEY */ -#define GPIO_KEY(c, g, d, ...) \ - { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ } - -static struct gpio_keys_button gpio_buttons[] = { - GPIO_KEY(KEY_POWER, 99, "SW3", .wakeup = 1), - GPIO_KEY(KEY_BACK, 100, "SW4"), - GPIO_KEY(KEY_MENU, 97, "SW5"), - GPIO_KEY(KEY_HOME, 98, "SW6"), -}; - -static struct gpio_keys_platform_data gpio_key_info = { - .buttons = gpio_buttons, - .nbuttons = ARRAY_SIZE(gpio_buttons), -}; - -static struct platform_device gpio_keys_device = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &gpio_key_info, - }, -}; - -/* Fixed 3.3V regulator to be used by SDHI1, MMCIF */ -static struct regulator_consumer_supply fixed3v3_power_consumers[] = { - REGULATOR_SUPPLY("vmmc", "sh_mmcif"), - REGULATOR_SUPPLY("vqmmc", "sh_mmcif"), -}; - -/* Fixed 3.3V regulator used by LCD backlight */ -static struct regulator_consumer_supply fixed5v0_power_consumers[] = { - REGULATOR_SUPPLY("power", "pwm-backlight.0"), -}; - -/* Fixed 3.3V regulator to be used by SDHI0 */ -static struct regulator_consumer_supply vcc_sdhi0_consumers[] = { - REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), -}; - -static struct regulator_init_data vcc_sdhi0_init_data = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi0_consumers), - .consumer_supplies = vcc_sdhi0_consumers, -}; - -static struct fixed_voltage_config vcc_sdhi0_info = { - .supply_name = "SDHI0 Vcc", - .microvolts = 3300000, - .gpio = 75, - .enable_high = 1, - .init_data = &vcc_sdhi0_init_data, -}; - -static struct platform_device vcc_sdhi0 = { - .name = "reg-fixed-voltage", - .id = 1, - .dev = { - .platform_data = &vcc_sdhi0_info, - }, -}; - -/* 1.8 / 3.3V SDHI0 VccQ regulator */ -static struct regulator_consumer_supply vccq_sdhi0_consumers[] = { - REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), -}; - -static struct regulator_init_data vccq_sdhi0_init_data = { - .constraints = { - .input_uV = 3300000, - .min_uV = 1800000, - .max_uV = 3300000, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | - REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(vccq_sdhi0_consumers), - .consumer_supplies = vccq_sdhi0_consumers, -}; - -static struct gpio vccq_sdhi0_gpios[] = { - {17, GPIOF_OUT_INIT_LOW, "vccq-sdhi0" }, -}; - -static struct gpio_regulator_state vccq_sdhi0_states[] = { - { .value = 3300000, .gpios = (0 << 0) }, - { .value = 1800000, .gpios = (1 << 0) }, -}; - -static struct gpio_regulator_config vccq_sdhi0_info = { - .supply_name = "vqmmc", - - .enable_gpio = 74, - .enable_high = 1, - .enabled_at_boot = 0, - - .gpios = vccq_sdhi0_gpios, - .nr_gpios = ARRAY_SIZE(vccq_sdhi0_gpios), - - .states = vccq_sdhi0_states, - .nr_states = ARRAY_SIZE(vccq_sdhi0_states), - - .type = REGULATOR_VOLTAGE, - .init_data = &vccq_sdhi0_init_data, -}; - -static struct platform_device vccq_sdhi0 = { - .name = "gpio-regulator", - .id = -1, - .dev = { - .platform_data = &vccq_sdhi0_info, - }, -}; - -/* Fixed 3.3V regulator to be used by SDHI1 */ -static struct regulator_consumer_supply vcc_sdhi1_consumers[] = { - REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), -}; - -static struct regulator_init_data vcc_sdhi1_init_data = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi1_consumers), - .consumer_supplies = vcc_sdhi1_consumers, -}; - -static struct fixed_voltage_config vcc_sdhi1_info = { - .supply_name = "SDHI1 Vcc", - .microvolts = 3300000, - .gpio = 16, - .enable_high = 1, - .init_data = &vcc_sdhi1_init_data, -}; - -static struct platform_device vcc_sdhi1 = { - .name = "reg-fixed-voltage", - .id = 2, - .dev = { - .platform_data = &vcc_sdhi1_info, - }, -}; - -/* SDHI0 */ -static struct tmio_mmc_data sdhi0_info = { - .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX, - .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX, - .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_POWER_OFF_CARD, - .flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD, - .cd_gpio = 167, -}; - -static struct resource sdhi0_resources[] = { - { - .name = "SDHI0", - .start = 0xe6850000, - .end = 0xe6850100 - 1, - .flags = IORESOURCE_MEM, - }, - /* - * no SH_MOBILE_SDHI_IRQ_CARD_DETECT here - */ - { - .name = SH_MOBILE_SDHI_IRQ_SDCARD, - .start = gic_spi(118), - .flags = IORESOURCE_IRQ, - }, - { - .name = SH_MOBILE_SDHI_IRQ_SDIO, - .start = gic_spi(119), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device sdhi0_device = { - .name = "sh_mobile_sdhi", - .id = 0, - .dev = { - .platform_data = &sdhi0_info, - }, - .num_resources = ARRAY_SIZE(sdhi0_resources), - .resource = sdhi0_resources, -}; - -/* SDHI1 */ -static struct tmio_mmc_data sdhi1_info = { - .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI1_TX, - .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI1_RX, - .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_POWER_OFF_CARD, - .flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD, - /* Port72 cannot generate IRQs, will be used in polling mode. */ - .cd_gpio = 72, -}; - -static struct resource sdhi1_resources[] = { - [0] = { - .name = "SDHI1", - .start = 0xe6860000, - .end = 0xe6860100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(121), - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = gic_spi(122), - .flags = IORESOURCE_IRQ, - }, - [3] = { - .start = gic_spi(123), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device sdhi1_device = { - .name = "sh_mobile_sdhi", - .id = 1, - .dev = { - .platform_data = &sdhi1_info, - }, - .num_resources = ARRAY_SIZE(sdhi1_resources), - .resource = sdhi1_resources, -}; - -static const struct pinctrl_map eva_sdhi1_pinctrl_map[] = { - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740", - "sdhi1_data4", "sdhi1"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740", - "sdhi1_ctrl", "sdhi1"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740", - "sdhi1_cd", "sdhi1"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740", - "sdhi1_wp", "sdhi1"), -}; - -/* MMCIF */ -static struct sh_mmcif_plat_data sh_mmcif_plat = { - .sup_pclk = 0, - .caps = MMC_CAP_4_BIT_DATA | - MMC_CAP_8_BIT_DATA | - MMC_CAP_NONREMOVABLE, - .ccs_unsupported = true, - .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, - .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, -}; - -static struct resource sh_mmcif_resources[] = { - [0] = { - .name = "MMCIF", - .start = 0xe6bd0000, - .end = 0xe6bd0100 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - /* MMC ERR */ - .start = gic_spi(56), - .flags = IORESOURCE_IRQ, - }, - [2] = { - /* MMC NOR */ - .start = gic_spi(57), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device sh_mmcif_device = { - .name = "sh_mmcif", - .id = -1, - .dev = { - .platform_data = &sh_mmcif_plat, - }, - .num_resources = ARRAY_SIZE(sh_mmcif_resources), - .resource = sh_mmcif_resources, -}; - -/* Camera */ -static int mt9t111_power(struct device *dev, int mode) -{ - struct clk *mclk = clk_get(NULL, "video1"); - - if (IS_ERR(mclk)) { - dev_err(dev, "can't get video1 clock\n"); - return -EINVAL; - } - - if (mode) { - /* video1 (= CON1 camera) expect 24MHz */ - clk_set_rate(mclk, clk_round_rate(mclk, 24000000)); - clk_enable(mclk); - gpio_set_value(158, 1); - } else { - gpio_set_value(158, 0); - clk_disable(mclk); - } - - clk_put(mclk); - - return 0; -} - -static struct i2c_board_info i2c_camera_mt9t111 = { - I2C_BOARD_INFO("mt9t112", 0x3d), -}; - -static struct mt9t112_camera_info mt9t111_info = { - .divider = { 16, 0, 0, 7, 0, 10, 14, 7, 7 }, -}; - -static struct soc_camera_link mt9t111_link = { - .i2c_adapter_id = 0, - .bus_id = 0, - .board_info = &i2c_camera_mt9t111, - .power = mt9t111_power, - .priv = &mt9t111_info, -}; - -static struct platform_device camera_device = { - .name = "soc-camera-pdrv", - .id = 0, - .dev = { - .platform_data = &mt9t111_link, - }, -}; - -/* CEU0 */ -static struct sh_mobile_ceu_info sh_mobile_ceu0_info = { - .flags = SH_CEU_FLAG_LOWER_8BIT, -}; - -static struct resource ceu0_resources[] = { - [0] = { - .name = "CEU", - .start = 0xfe910000, - .end = 0xfe91009f, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(160), - .flags = IORESOURCE_IRQ, - }, - [2] = { - /* place holder for contiguous memory */ - }, -}; - -static struct platform_device ceu0_device = { - .name = "sh_mobile_ceu", - .id = 0, - .num_resources = ARRAY_SIZE(ceu0_resources), - .resource = ceu0_resources, - .dev = { - .platform_data = &sh_mobile_ceu0_info, - .coherent_dma_mask = 0xffffffff, - }, -}; - -/* FSI */ -static struct sh_fsi_platform_info fsi_info = { - /* FSI-WM8978 */ - .port_a = { - .tx_id = SHDMA_SLAVE_FSIA_TX, - }, - /* FSI-HDMI */ - .port_b = { - .flags = SH_FSI_FMT_SPDIF | - SH_FSI_ENABLE_STREAM_MODE | - SH_FSI_CLK_CPG, - .tx_id = SHDMA_SLAVE_FSIB_TX, - } -}; - -static struct resource fsi_resources[] = { - [0] = { - .name = "FSI", - .start = 0xfe1f0000, - .end = 0xfe1f0400 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(9), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device fsi_device = { - .name = "sh_fsi2", - .id = -1, - .num_resources = ARRAY_SIZE(fsi_resources), - .resource = fsi_resources, - .dev = { - .platform_data = &fsi_info, - }, -}; - -/* FSI-WM8978 */ -static struct asoc_simple_card_info fsi_wm8978_info = { - .name = "wm8978", - .card = "FSI2A-WM8978", - .codec = "wm8978.0-001a", - .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, - .cpu_dai = { - .name = "fsia-dai", - }, - .codec_dai = { - .name = "wm8978-hifi", - .sysclk = 12288000, - }, -}; - -static struct platform_device fsi_wm8978_device = { - .name = "asoc-simple-card", - .id = 0, - .dev = { - .platform_data = &fsi_wm8978_info, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask, - }, -}; - -/* FSI-HDMI */ -static struct asoc_simple_card_info fsi2_hdmi_info = { - .name = "HDMI", - .card = "FSI2B-HDMI", - .codec = "sh-mobile-hdmi", - .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_CBS_CFS, - .cpu_dai = { - .name = "fsib-dai", - }, - .codec_dai = { - .name = "sh_mobile_hdmi-hifi", - }, -}; - -static struct platform_device fsi_hdmi_device = { - .name = "asoc-simple-card", - .id = 1, - .dev = { - .platform_data = &fsi2_hdmi_info, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask, - }, -}; - -/* RTC: RTC connects i2c-gpio. */ -static struct i2c_gpio_platform_data i2c_gpio_data = { - .sda_pin = 208, - .scl_pin = 91, - .udelay = 5, /* 100 kHz */ -}; - -static struct platform_device i2c_gpio_device = { - .name = "i2c-gpio", - .id = 2, - .dev = { - .platform_data = &i2c_gpio_data, - }, -}; - -/* I2C */ -static struct st1232_pdata st1232_i2c0_pdata = { - .reset_gpio = 166, -}; - -static struct i2c_board_info i2c0_devices[] = { - { - I2C_BOARD_INFO("st1232-ts", 0x55), - .irq = irq_pin(10), - .platform_data = &st1232_i2c0_pdata, - }, - { - I2C_BOARD_INFO("wm8978", 0x1a), - }, -}; - -static struct i2c_board_info i2c2_devices[] = { - { - I2C_BOARD_INFO("s35390a", 0x30), - .type = "s35390a", - }, -}; - -/* - * board devices - */ -static struct platform_device *eva_devices[] __initdata = { - &lcdc0_device, - &pwm_device, - &pwm_backlight_device, - &leds_gpio_device, - &gpio_keys_device, - &sh_eth_device, - &vcc_sdhi0, - &vccq_sdhi0, - &sdhi0_device, - &sh_mmcif_device, - &hdmi_device, - &hdmi_lcdc_device, - &camera_device, - &ceu0_device, - &fsi_device, - &fsi_wm8978_device, - &fsi_hdmi_device, - &i2c_gpio_device, -}; - -static const struct pinctrl_map eva_pinctrl_map[] = { - /* CEU0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740", - "ceu0_data_0_7", "ceu0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740", - "ceu0_clk_0", "ceu0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740", - "ceu0_sync", "ceu0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740", - "ceu0_field", "ceu0"), - /* FSIA */ - PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740", - "fsia_sclk_in", "fsia"), - PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740", - "fsia_mclk_out", "fsia"), - PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740", - "fsia_data_in_1", "fsia"), - PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740", - "fsia_data_out_0", "fsia"), - /* FSIB */ - PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.1", "pfc-r8a7740", - "fsib_mclk_in", "fsib"), - /* GETHER */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740", - "gether_mii", "gether"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740", - "gether_int", "gether"), - /* HDMI */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-mobile-hdmi", "pfc-r8a7740", - "hdmi", "hdmi"), - /* LCD0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740", - "lcd0_data24_0", "lcd0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740", - "lcd0_lclk_1", "lcd0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740", - "lcd0_sync", "lcd0"), - /* MMCIF */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a7740", - "mmc0_data8_1", "mmc0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a7740", - "mmc0_ctrl_1", "mmc0"), - /* SCIFA1 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.1", "pfc-r8a7740", - "scifa1_data", "scifa1"), - /* SDHI0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740", - "sdhi0_data4", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740", - "sdhi0_ctrl", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740", - "sdhi0_wp", "sdhi0"), - /* ST1232 */ - PIN_MAP_MUX_GROUP_DEFAULT("0-0055", "pfc-r8a7740", - "intc_irq10", "intc"), - /* TPU0 */ - PIN_MAP_MUX_GROUP_DEFAULT("renesas-tpu-pwm", "pfc-r8a7740", - "tpu0_to2_1", "tpu0"), - /* USBHS */ - PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7740", - "intc_irq7_1", "intc"), -}; - -static void __init eva_clock_init(void) -{ - struct clk *system = clk_get(NULL, "system_clk"); - struct clk *xtal1 = clk_get(NULL, "extal1"); - struct clk *usb24s = clk_get(NULL, "usb24s"); - struct clk *fsibck = clk_get(NULL, "fsibck"); - - if (IS_ERR(system) || - IS_ERR(xtal1) || - IS_ERR(usb24s) || - IS_ERR(fsibck)) { - pr_err("armadillo800eva board clock init failed\n"); - goto clock_error; - } - - /* armadillo 800 eva extal1 is 24MHz */ - clk_set_rate(xtal1, 24000000); - - /* usb24s use extal1 (= system) clock (= 24MHz) */ - clk_set_parent(usb24s, system); - - /* FSIBCK is 12.288MHz, and it is parent of FSI-B */ - clk_set_rate(fsibck, 12288000); - -clock_error: - if (!IS_ERR(system)) - clk_put(system); - if (!IS_ERR(xtal1)) - clk_put(xtal1); - if (!IS_ERR(usb24s)) - clk_put(usb24s); - if (!IS_ERR(fsibck)) - clk_put(fsibck); -} - -/* - * board init - */ -#define GPIO_PORT7CR IOMEM(0xe6050007) -#define GPIO_PORT8CR IOMEM(0xe6050008) -static void __init eva_init(void) -{ - static struct pm_domain_device domain_devices[] __initdata = { - { "A4LC", &lcdc0_device }, - { "A4LC", &hdmi_lcdc_device }, - { "A4MP", &hdmi_device }, - { "A4MP", &fsi_device }, - { "A4R", &ceu0_device }, - { "A4S", &sh_eth_device }, - { "A3SP", &pwm_device }, - { "A3SP", &sdhi0_device }, - { "A3SP", &sh_mmcif_device }, - }; - struct platform_device *usb = NULL, *sdhi1 = NULL; - - regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, - ARRAY_SIZE(fixed3v3_power_consumers), 3300000); - regulator_register_always_on(3, "fixed-5.0V", fixed5v0_power_consumers, - ARRAY_SIZE(fixed5v0_power_consumers), 5000000); - - pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map)); - pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup)); - - r8a7740_pinmux_init(); - r8a7740_meram_workaround(); - - /* GETHER */ - gpio_request_one(18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */ - - /* USB */ - gpio_request_one(159, GPIOF_IN, NULL); /* USB_DEVICE_MODE */ - - if (gpio_get_value(159)) { - /* USB Host */ - } else { - /* USB Func */ - /* - * The USBHS interrupt handlers needs to read the IRQ pin value - * (HI/LOW) to diffentiate USB connection and disconnection - * events (usbhsf_get_vbus()). We thus need to select both the - * intc_irq7_1 pin group and GPIO 209 here. - */ - gpio_request_one(209, GPIOF_IN, NULL); - - platform_device_register(&usbhsf_device); - usb = &usbhsf_device; - } - - /* CON1/CON15 Camera */ - gpio_request_one(173, GPIOF_OUT_INIT_LOW, NULL); /* STANDBY */ - gpio_request_one(172, GPIOF_OUT_INIT_HIGH, NULL); /* RST */ - /* see mt9t111_power() */ - gpio_request_one(158, GPIOF_OUT_INIT_LOW, NULL); /* CAM_PON */ - - /* FSI-WM8978 */ - gpio_request(7, NULL); - gpio_request(8, NULL); - gpio_direction_none(GPIO_PORT7CR); /* FSIAOBT needs no direction */ - gpio_direction_none(GPIO_PORT8CR); /* FSIAOLR needs no direction */ - - /* - * CAUTION - * - * DBGMD/LCDC0/FSIA MUX - * DBGMD_SELECT_B should be set after setting PFC Function. - */ - gpio_request_one(176, GPIOF_OUT_INIT_HIGH, NULL); - - /* - * We can switch CON8/CON14 by SW1.5, - * but it needs after DBGMD_SELECT_B - */ - gpio_request_one(6, GPIOF_IN, NULL); - if (gpio_get_value(6)) { - /* CON14 enable */ - } else { - /* CON8 (SDHI1) enable */ - pinctrl_register_mappings(eva_sdhi1_pinctrl_map, - ARRAY_SIZE(eva_sdhi1_pinctrl_map)); - - platform_device_register(&vcc_sdhi1); - platform_device_register(&sdhi1_device); - sdhi1 = &sdhi1_device; - } - - -#ifdef CONFIG_CACHE_L2X0 - /* Shared attribute override enable, 32K*8way */ - l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff); -#endif - - i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); - i2c_register_board_info(2, i2c2_devices, ARRAY_SIZE(i2c2_devices)); - - r8a7740_add_standard_devices(); - - platform_add_devices(eva_devices, - ARRAY_SIZE(eva_devices)); - - rmobile_add_devices_to_domains(domain_devices, - ARRAY_SIZE(domain_devices)); - if (usb) - rmobile_add_device_to_domain("A3SP", usb); - if (sdhi1) - rmobile_add_device_to_domain("A3SP", sdhi1); - - r8a7740_pm_init(); -} - -static void __init eva_earlytimer_init(void) -{ - r8a7740_clock_init(MD_CK0 | MD_CK2); - shmobile_earlytimer_init(); - - /* the rate of extal1 clock must be set before late_time_init */ - eva_clock_init(); -} - -#define RESCNT2 IOMEM(0xe6188020) -static void eva_restart(enum reboot_mode mode, const char *cmd) -{ - /* Do soft power on reset */ - writel((1 << 31), RESCNT2); -} - -static const char *eva_boards_compat_dt[] __initdata = { - "renesas,armadillo800eva", - NULL, -}; - -DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva") - .map_io = r8a7740_map_io, - .init_early = r8a7740_add_early_devices, - .init_irq = r8a7740_init_irq_of, - .init_machine = eva_init, - .init_late = shmobile_init_late, - .init_time = eva_earlytimer_init, - .dt_compat = eva_boards_compat_dt, - .restart = eva_restart, -MACHINE_END diff --git a/arch/arm/mach-shmobile/board-bockw-reference.c b/arch/arm/mach-shmobile/board-bockw-reference.c index 9a74efd..4f78296 100644 --- a/arch/arm/mach-shmobile/board-bockw-reference.c +++ b/arch/arm/mach-shmobile/board-bockw-reference.c @@ -72,7 +72,7 @@ static void __init bockw_init(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static const char *bockw_boards_compat_dt[] __initdata = { +static const char *const bockw_boards_compat_dt[] __initconst = { "renesas,bockw-reference", NULL, }; diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c index 25558d1..25a0e72 100644 --- a/arch/arm/mach-shmobile/board-bockw.c +++ b/arch/arm/mach-shmobile/board-bockw.c @@ -723,7 +723,7 @@ static void __init bockw_init_late(void) ADD_USB_FUNC_DEVICE_IF_POSSIBLE(); } -static const char *bockw_boards_compat_dt[] __initdata = { +static const char *const bockw_boards_compat_dt[] __initconst = { "renesas,bockw", NULL, }; diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c deleted file mode 100644 index 260d831..0000000 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ /dev/null @@ -1,916 +0,0 @@ -/* - * KZM-A9-GT board support - * - * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - */ - -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/gpio_keys.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/i2c.h> -#include <linux/i2c/pcf857x.h> -#include <linux/input.h> -#include <linux/irqchip/arm-gic.h> -#include <linux/mmc/host.h> -#include <linux/mmc/sh_mmcif.h> -#include <linux/mmc/sh_mobile_sdhi.h> -#include <linux/mfd/as3711.h> -#include <linux/mfd/tmio.h> -#include <linux/pinctrl/machine.h> -#include <linux/pinctrl/pinconf-generic.h> -#include <linux/platform_device.h> -#include <linux/reboot.h> -#include <linux/regulator/fixed.h> -#include <linux/regulator/machine.h> -#include <linux/smsc911x.h> -#include <linux/usb/r8a66597.h> -#include <linux/usb/renesas_usbhs.h> -#include <linux/videodev2.h> - -#include <sound/sh_fsi.h> -#include <sound/simple_card.h> -#include <asm/hardware/cache-l2x0.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <video/sh_mobile_lcdc.h> - -#include "common.h" -#include "intc.h" -#include "irqs.h" -#include "sh73a0.h" - -/* - * external GPIO - */ -#define GPIO_PCF8575_BASE (310) -#define GPIO_PCF8575_PORT10 (GPIO_PCF8575_BASE + 8) -#define GPIO_PCF8575_PORT11 (GPIO_PCF8575_BASE + 9) -#define GPIO_PCF8575_PORT12 (GPIO_PCF8575_BASE + 10) -#define GPIO_PCF8575_PORT13 (GPIO_PCF8575_BASE + 11) -#define GPIO_PCF8575_PORT14 (GPIO_PCF8575_BASE + 12) -#define GPIO_PCF8575_PORT15 (GPIO_PCF8575_BASE + 13) -#define GPIO_PCF8575_PORT16 (GPIO_PCF8575_BASE + 14) - -/* Dummy supplies, where voltage doesn't matter */ -static struct regulator_consumer_supply dummy_supplies[] = { - REGULATOR_SUPPLY("vddvario", "smsc911x.0"), - REGULATOR_SUPPLY("vdd33a", "smsc911x.0"), -}; - -/* - * FSI-AK4648 - * - * this command is required when playback. - * - * # amixer set "LINEOUT Mixer DACL" on - */ - -/* SMSC 9221 */ -static struct resource smsc9221_resources[] = { - [0] = { - .start = 0x10000000, /* CS4 */ - .end = 0x100000ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = irq_pin(3), /* IRQ3 */ - .flags = IORESOURCE_IRQ, - }, -}; - -static struct smsc911x_platform_config smsc9221_platdata = { - .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS, - .phy_interface = PHY_INTERFACE_MODE_MII, - .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, - .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, -}; - -static struct platform_device smsc_device = { - .name = "smsc911x", - .dev = { - .platform_data = &smsc9221_platdata, - }, - .resource = smsc9221_resources, - .num_resources = ARRAY_SIZE(smsc9221_resources), -}; - -/* USB external chip */ -static struct r8a66597_platdata usb_host_data = { - .on_chip = 0, - .xtal = R8A66597_PLATDATA_XTAL_48MHZ, -}; - -static struct resource usb_resources[] = { - [0] = { - .start = 0x10010000, - .end = 0x1001ffff - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = irq_pin(1), /* IRQ1 */ - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device usb_host_device = { - .name = "r8a66597_hcd", - .dev = { - .platform_data = &usb_host_data, - .dma_mask = NULL, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(usb_resources), - .resource = usb_resources, -}; - -/* USB Func CN17 */ -struct usbhs_private { - void __iomem *phy; - void __iomem *cr2; - struct renesas_usbhs_platform_info info; -}; - -#define IRQ15 irq_pin(15) -#define USB_PHY_MODE (1 << 4) -#define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) -#define USB_PHY_ON (1 << 1) -#define USB_PHY_OFF (1 << 0) -#define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) - -#define usbhs_get_priv(pdev) \ - container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info) - -static int usbhs_get_vbus(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - return !((1 << 7) & __raw_readw(priv->cr2)); -} - -static int usbhs_phy_reset(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - /* init phy */ - __raw_writew(0x8a0a, priv->cr2); - - return 0; -} - -static int usbhs_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -static irqreturn_t usbhs_interrupt(int irq, void *data) -{ - struct platform_device *pdev = data; - struct usbhs_private *priv = usbhs_get_priv(pdev); - - renesas_usbhs_call_notify_hotplug(pdev); - - /* clear status */ - __raw_writew(__raw_readw(priv->phy) | USB_PHY_INT_CLR, priv->phy); - - return IRQ_HANDLED; -} - -static int usbhs_hardware_init(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - int ret; - - /* clear interrupt status */ - __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy); - - ret = request_irq(IRQ15, usbhs_interrupt, IRQF_TRIGGER_HIGH, - dev_name(&pdev->dev), pdev); - if (ret) { - dev_err(&pdev->dev, "request_irq err\n"); - return ret; - } - - /* enable USB phy interrupt */ - __raw_writew(USB_PHY_MODE | USB_PHY_INT_EN, priv->phy); - - return 0; -} - -static int usbhs_hardware_exit(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - /* clear interrupt status */ - __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy); - - free_irq(IRQ15, pdev); - - return 0; -} - -static u32 usbhs_pipe_cfg[] = { - USB_ENDPOINT_XFER_CONTROL, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, -}; - -static struct usbhs_private usbhs_private = { - .phy = IOMEM(0xe60781e0), /* USBPHYINT */ - .cr2 = IOMEM(0xe605810c), /* USBCR2 */ - .info = { - .platform_callback = { - .hardware_init = usbhs_hardware_init, - .hardware_exit = usbhs_hardware_exit, - .get_id = usbhs_get_id, - .phy_reset = usbhs_phy_reset, - .get_vbus = usbhs_get_vbus, - }, - .driver_param = { - .buswait_bwait = 4, - .has_otg = 1, - .pipe_type = usbhs_pipe_cfg, - .pipe_size = ARRAY_SIZE(usbhs_pipe_cfg), - }, - }, -}; - -static struct resource usbhs_resources[] = { - [0] = { - .start = 0xE6890000, - .end = 0xE68900e6 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(62), - .end = gic_spi(62), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device usbhs_device = { - .name = "renesas_usbhs", - .id = -1, - .dev = { - .dma_mask = NULL, - .coherent_dma_mask = 0xffffffff, - .platform_data = &usbhs_private.info, - }, - .num_resources = ARRAY_SIZE(usbhs_resources), - .resource = usbhs_resources, -}; - -/* LCDC */ -static struct fb_videomode kzm_lcdc_mode = { - .name = "WVGA Panel", - .xres = 800, - .yres = 480, - .left_margin = 220, - .right_margin = 110, - .hsync_len = 70, - .upper_margin = 20, - .lower_margin = 5, - .vsync_len = 5, - .sync = 0, -}; - -static struct sh_mobile_lcdc_info lcdc_info = { - .clock_source = LCDC_CLK_BUS, - .ch[0] = { - .chan = LCDC_CHAN_MAINLCD, - .fourcc = V4L2_PIX_FMT_RGB565, - .interface_type = RGB24, - .lcd_modes = &kzm_lcdc_mode, - .num_modes = 1, - .clock_divider = 5, - .flags = 0, - .panel_cfg = { - .width = 152, - .height = 91, - }, - } -}; - -static struct resource lcdc_resources[] = { - [0] = { - .name = "LCDC", - .start = 0xfe940000, - .end = 0xfe943fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = intcs_evt2irq(0x580), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device lcdc_device = { - .name = "sh_mobile_lcdc_fb", - .num_resources = ARRAY_SIZE(lcdc_resources), - .resource = lcdc_resources, - .dev = { - .platform_data = &lcdc_info, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -/* Fixed 1.8V regulator to be used by MMCIF */ -static struct regulator_consumer_supply fixed1v8_power_consumers[] = -{ - REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"), - REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"), -}; - -/* MMCIF */ -static struct resource sh_mmcif_resources[] = { - [0] = { - .name = "MMCIF", - .start = 0xe6bd0000, - .end = 0xe6bd00ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(140), - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = gic_spi(141), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct sh_mmcif_plat_data sh_mmcif_platdata = { - .ocr = MMC_VDD_165_195, - .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, - .ccs_unsupported = true, - .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, - .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, -}; - -static struct platform_device mmc_device = { - .name = "sh_mmcif", - .dev = { - .dma_mask = NULL, - .coherent_dma_mask = 0xffffffff, - .platform_data = &sh_mmcif_platdata, - }, - .num_resources = ARRAY_SIZE(sh_mmcif_resources), - .resource = sh_mmcif_resources, -}; - -/* Fixed 3.3V regulators to be used by SDHI0 */ -static struct regulator_consumer_supply vcc_sdhi0_consumers[] = -{ - REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), -}; - -static struct regulator_init_data vcc_sdhi0_init_data = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi0_consumers), - .consumer_supplies = vcc_sdhi0_consumers, -}; - -static struct fixed_voltage_config vcc_sdhi0_info = { - .supply_name = "SDHI0 Vcc", - .microvolts = 3300000, - .gpio = 15, - .enable_high = 1, - .init_data = &vcc_sdhi0_init_data, -}; - -static struct platform_device vcc_sdhi0 = { - .name = "reg-fixed-voltage", - .id = 0, - .dev = { - .platform_data = &vcc_sdhi0_info, - }, -}; - -/* Fixed 3.3V regulators to be used by SDHI2 */ -static struct regulator_consumer_supply vcc_sdhi2_consumers[] = -{ - REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.2"), -}; - -static struct regulator_init_data vcc_sdhi2_init_data = { - .constraints = { - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi2_consumers), - .consumer_supplies = vcc_sdhi2_consumers, -}; - -static struct fixed_voltage_config vcc_sdhi2_info = { - .supply_name = "SDHI2 Vcc", - .microvolts = 3300000, - .gpio = 14, - .enable_high = 1, - .init_data = &vcc_sdhi2_init_data, -}; - -static struct platform_device vcc_sdhi2 = { - .name = "reg-fixed-voltage", - .id = 1, - .dev = { - .platform_data = &vcc_sdhi2_info, - }, -}; - -/* SDHI */ -static struct tmio_mmc_data sdhi0_info = { - .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX, - .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX, - .flags = TMIO_MMC_HAS_IDLE_WAIT, - .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_POWER_OFF_CARD, -}; - -static struct resource sdhi0_resources[] = { - [0] = { - .name = "SDHI0", - .start = 0xee100000, - .end = 0xee1000ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, - .start = gic_spi(83), - .flags = IORESOURCE_IRQ, - }, - [2] = { - .name = SH_MOBILE_SDHI_IRQ_SDCARD, - .start = gic_spi(84), - .flags = IORESOURCE_IRQ, - }, - [3] = { - .name = SH_MOBILE_SDHI_IRQ_SDIO, - .start = gic_spi(85), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device sdhi0_device = { - .name = "sh_mobile_sdhi", - .num_resources = ARRAY_SIZE(sdhi0_resources), - .resource = sdhi0_resources, - .dev = { - .platform_data = &sdhi0_info, - }, -}; - -/* Micro SD */ -static struct tmio_mmc_data sdhi2_info = { - .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI2_TX, - .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI2_RX, - .flags = TMIO_MMC_HAS_IDLE_WAIT | - TMIO_MMC_USE_GPIO_CD | - TMIO_MMC_WRPROTECT_DISABLE, - .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_POWER_OFF_CARD, - .cd_gpio = 13, -}; - -static struct resource sdhi2_resources[] = { - [0] = { - .name = "SDHI2", - .start = 0xee140000, - .end = 0xee1400ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, - .start = gic_spi(103), - .flags = IORESOURCE_IRQ, - }, - [2] = { - .name = SH_MOBILE_SDHI_IRQ_SDCARD, - .start = gic_spi(104), - .flags = IORESOURCE_IRQ, - }, - [3] = { - .name = SH_MOBILE_SDHI_IRQ_SDIO, - .start = gic_spi(105), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device sdhi2_device = { - .name = "sh_mobile_sdhi", - .id = 2, - .num_resources = ARRAY_SIZE(sdhi2_resources), - .resource = sdhi2_resources, - .dev = { - .platform_data = &sdhi2_info, - }, -}; - -/* KEY */ -#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } - -static struct gpio_keys_button gpio_buttons[] = { - GPIO_KEY(KEY_BACK, GPIO_PCF8575_PORT10, "SW3"), - GPIO_KEY(KEY_RIGHT, GPIO_PCF8575_PORT11, "SW2-R"), - GPIO_KEY(KEY_LEFT, GPIO_PCF8575_PORT12, "SW2-L"), - GPIO_KEY(KEY_ENTER, GPIO_PCF8575_PORT13, "SW2-P"), - GPIO_KEY(KEY_UP, GPIO_PCF8575_PORT14, "SW2-U"), - GPIO_KEY(KEY_DOWN, GPIO_PCF8575_PORT15, "SW2-D"), - GPIO_KEY(KEY_HOME, GPIO_PCF8575_PORT16, "SW1"), -}; - -static struct gpio_keys_platform_data gpio_key_info = { - .buttons = gpio_buttons, - .nbuttons = ARRAY_SIZE(gpio_buttons), -}; - -static struct platform_device gpio_keys_device = { - .name = "gpio-keys", - .dev = { - .platform_data = &gpio_key_info, - }, -}; - -/* FSI-AK4648 */ -static struct sh_fsi_platform_info fsi_info = { - .port_a = { - .tx_id = SHDMA_SLAVE_FSI2A_TX, - }, -}; - -static struct resource fsi_resources[] = { - [0] = { - .name = "FSI", - .start = 0xEC230000, - .end = 0xEC230400 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(146), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device fsi_device = { - .name = "sh_fsi2", - .id = -1, - .num_resources = ARRAY_SIZE(fsi_resources), - .resource = fsi_resources, - .dev = { - .platform_data = &fsi_info, - }, -}; - -static struct asoc_simple_card_info fsi2_ak4648_info = { - .name = "AK4648", - .card = "FSI2A-AK4648", - .codec = "ak4642-codec.0-0012", - .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, - .cpu_dai = { - .name = "fsia-dai", - }, - .codec_dai = { - .name = "ak4642-hifi", - .sysclk = 11289600, - }, -}; - -static struct platform_device fsi_ak4648_device = { - .name = "asoc-simple-card", - .dev = { - .platform_data = &fsi2_ak4648_info, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask, - }, -}; - -/* I2C */ - -/* StepDown1 is used to supply 1.315V to the CPU */ -static struct regulator_init_data as3711_sd1 = { - .constraints = { - .name = "1.315V CPU", - .boot_on = 1, - .always_on = 1, - .min_uV = 1315000, - .max_uV = 1335000, - }, -}; - -/* StepDown2 is used to supply 1.8V to the CPU and to the board */ -static struct regulator_init_data as3711_sd2 = { - .constraints = { - .name = "1.8V", - .boot_on = 1, - .always_on = 1, - .min_uV = 1800000, - .max_uV = 1800000, - }, -}; - -/* - * StepDown3 is switched in parallel with StepDown2, seems to be off, - * according to read-back pre-set register values - */ - -/* StepDown4 is used to supply 1.215V to the CPU and to the board */ -static struct regulator_init_data as3711_sd4 = { - .constraints = { - .name = "1.215V", - .boot_on = 1, - .always_on = 1, - .min_uV = 1215000, - .max_uV = 1235000, - }, -}; - -/* LDO1 is unused and unconnected */ - -/* LDO2 is used to supply 2.8V to the CPU */ -static struct regulator_init_data as3711_ldo2 = { - .constraints = { - .name = "2.8V CPU", - .boot_on = 1, - .always_on = 1, - .min_uV = 2800000, - .max_uV = 2800000, - }, -}; - -/* LDO3 is used to supply 3.0V to the CPU */ -static struct regulator_init_data as3711_ldo3 = { - .constraints = { - .name = "3.0V CPU", - .boot_on = 1, - .always_on = 1, - .min_uV = 3000000, - .max_uV = 3000000, - }, -}; - -/* LDO4 is used to supply 2.8V to the board */ -static struct regulator_init_data as3711_ldo4 = { - .constraints = { - .name = "2.8V", - .boot_on = 1, - .always_on = 1, - .min_uV = 2800000, - .max_uV = 2800000, - }, -}; - -/* LDO5 is switched parallel to LDO4, also set to 2.8V */ -static struct regulator_init_data as3711_ldo5 = { - .constraints = { - .name = "2.8V #2", - .boot_on = 1, - .always_on = 1, - .min_uV = 2800000, - .max_uV = 2800000, - }, -}; - -/* LDO6 is unused and unconnected */ - -/* LDO7 is used to supply 1.15V to the CPU */ -static struct regulator_init_data as3711_ldo7 = { - .constraints = { - .name = "1.15V CPU", - .boot_on = 1, - .always_on = 1, - .min_uV = 1150000, - .max_uV = 1150000, - }, -}; - -/* LDO8 is switched parallel to LDO7, also set to 1.15V */ -static struct regulator_init_data as3711_ldo8 = { - .constraints = { - .name = "1.15V CPU #2", - .boot_on = 1, - .always_on = 1, - .min_uV = 1150000, - .max_uV = 1150000, - }, -}; - -static struct as3711_platform_data as3711_pdata = { - .regulator = { - .init_data = { - [AS3711_REGULATOR_SD_1] = &as3711_sd1, - [AS3711_REGULATOR_SD_2] = &as3711_sd2, - [AS3711_REGULATOR_SD_4] = &as3711_sd4, - [AS3711_REGULATOR_LDO_2] = &as3711_ldo2, - [AS3711_REGULATOR_LDO_3] = &as3711_ldo3, - [AS3711_REGULATOR_LDO_4] = &as3711_ldo4, - [AS3711_REGULATOR_LDO_5] = &as3711_ldo5, - [AS3711_REGULATOR_LDO_7] = &as3711_ldo7, - [AS3711_REGULATOR_LDO_8] = &as3711_ldo8, - }, - }, - .backlight = { - .su2_fb = "sh_mobile_lcdc_fb.0", - .su2_max_uA = 36000, - .su2_feedback = AS3711_SU2_CURR_AUTO, - .su2_fbprot = AS3711_SU2_GPIO4, - .su2_auto_curr1 = true, - .su2_auto_curr2 = true, - .su2_auto_curr3 = true, - }, -}; - -static struct pcf857x_platform_data pcf8575_pdata = { - .gpio_base = GPIO_PCF8575_BASE, -}; - -static struct i2c_board_info i2c0_devices[] = { - { - I2C_BOARD_INFO("ak4648", 0x12), - }, - { - I2C_BOARD_INFO("r2025sd", 0x32), - }, - { - I2C_BOARD_INFO("ak8975", 0x0c), - .irq = irq_pin(28), /* IRQ28 */ - }, - { - I2C_BOARD_INFO("adxl34x", 0x1d), - .irq = irq_pin(26), /* IRQ26 */ - }, - { - I2C_BOARD_INFO("as3711", 0x40), - .irq = intcs_evt2irq(0x3300), /* IRQ24 */ - .platform_data = &as3711_pdata, - }, -}; - -static struct i2c_board_info i2c1_devices[] = { - { - I2C_BOARD_INFO("st1232-ts", 0x55), - .irq = irq_pin(8), /* IRQ8 */ - }, -}; - -static struct i2c_board_info i2c3_devices[] = { - { - I2C_BOARD_INFO("pcf8575", 0x20), - .irq = irq_pin(19), /* IRQ19 */ - .platform_data = &pcf8575_pdata, - }, -}; - -static struct platform_device *kzm_devices[] __initdata = { - &smsc_device, - &usb_host_device, - &usbhs_device, - &lcdc_device, - &mmc_device, - &vcc_sdhi0, - &vcc_sdhi2, - &sdhi0_device, - &sdhi2_device, - &gpio_keys_device, - &fsi_device, - &fsi_ak4648_device, -}; - -static unsigned long pin_pullup_conf[] = { - PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0), -}; - -static const struct pinctrl_map kzm_pinctrl_map[] = { - /* FSIA (AK4648) */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0", - "fsia_mclk_in", "fsia"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0", - "fsia_sclk_in", "fsia"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0", - "fsia_data_in", "fsia"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0", - "fsia_data_out", "fsia"), - /* I2C3 */ - PIN_MAP_MUX_GROUP_DEFAULT("i2c-sh_mobile.3", "pfc-sh73a0", - "i2c3_1", "i2c3"), - /* LCD */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh73a0", - "lcd_data24", "lcd"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh73a0", - "lcd_sync", "lcd"), - /* MMCIF */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0", - "mmc0_data8_0", "mmc0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0", - "mmc0_ctrl_0", "mmc0"), - PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mmcif.0", "pfc-sh73a0", - "PORT279", pin_pullup_conf), - PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0", - "mmc0_data8_0", pin_pullup_conf), - /* SCIFA4 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0", - "scifa4_data", "scifa4"), - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0", - "scifa4_ctrl", "scifa4"), - /* SDHI0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0", - "sdhi0_data4", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0", - "sdhi0_ctrl", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0", - "sdhi0_cd", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0", - "sdhi0_wp", "sdhi0"), - /* SDHI2 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh73a0", - "sdhi2_data4", "sdhi2"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh73a0", - "sdhi2_ctrl", "sdhi2"), - /* SMSC */ - PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0", - "bsc_cs4", "bsc"), - /* USB */ - PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-sh73a0", - "usb_vbus", "usb"), -}; - -static void __init kzm_init(void) -{ - regulator_register_always_on(2, "fixed-1.8V", fixed1v8_power_consumers, - ARRAY_SIZE(fixed1v8_power_consumers), 1800000); - regulator_register_fixed(3, dummy_supplies, ARRAY_SIZE(dummy_supplies)); - - pinctrl_register_mappings(kzm_pinctrl_map, ARRAY_SIZE(kzm_pinctrl_map)); - - sh73a0_pinmux_init(); - - /* SMSC */ - gpio_request_one(224, GPIOF_IN, NULL); /* IRQ3 */ - - /* LCDC */ - gpio_request_one(222, GPIOF_OUT_INIT_HIGH, NULL); /* LCDCDON */ - gpio_request_one(226, GPIOF_OUT_INIT_HIGH, NULL); /* SC */ - - /* Touchscreen */ - gpio_request_one(223, GPIOF_IN, NULL); /* IRQ8 */ - -#ifdef CONFIG_CACHE_L2X0 - /* Shared attribute override enable, 64K*8way */ - l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff); -#endif - - i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); - i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices)); - i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices)); - - sh73a0_add_standard_devices(); - platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices)); - - sh73a0_pm_init(); -} - -static void kzm9g_restart(enum reboot_mode mode, const char *cmd) -{ -#define RESCNT2 IOMEM(0xe6188020) - /* Do soft power on reset */ - writel((1 << 31), RESCNT2); -} - -static const char *kzm9g_boards_compat_dt[] __initdata = { - "renesas,kzm9g", - NULL, -}; - -DT_MACHINE_START(KZM9G_DT, "kzm9g") - .smp = smp_ops(sh73a0_smp_ops), - .map_io = sh73a0_map_io, - .init_early = sh73a0_add_early_devices, - .init_irq = sh73a0_init_irq, - .init_machine = kzm_init, - .init_late = shmobile_init_late, - .init_time = sh73a0_earlytimer_init, - .restart = kzm9g_restart, - .dt_compat = kzm9g_boards_compat_dt, -MACHINE_END diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c deleted file mode 100644 index 9cac824..0000000 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * R8A7740 processor support - * - * Copyright (C) 2011 Renesas Solutions Corp. - * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * 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. - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/sh_clk.h> -#include <linux/clkdev.h> - -#include "clock.h" -#include "common.h" -#include "r8a7740.h" - -/* - * | MDx | XTAL1/EXTAL1 | System | EXTALR | - * Clock |-------+-----------------+ clock | 32.768 | RCLK - * Mode | 2/1/0 | src MHz | source | KHz | source - * -------+-------+-----------------+-----------+--------+---------- - * 0 | 0 0 0 | External 20~50 | XTAL1 | O | EXTALR - * 1 | 0 0 1 | Crystal 20~30 | XTAL1 | O | EXTALR - * 2 | 0 1 0 | External 40~50 | XTAL1 / 2 | O | EXTALR - * 3 | 0 1 1 | Crystal 40~50 | XTAL1 / 2 | O | EXTALR - * 4 | 1 0 0 | External 20~50 | XTAL1 | x | XTAL1 / 1024 - * 5 | 1 0 1 | Crystal 20~30 | XTAL1 | x | XTAL1 / 1024 - * 6 | 1 1 0 | External 40~50 | XTAL1 / 2 | x | XTAL1 / 2048 - * 7 | 1 1 1 | Crystal 40~50 | XTAL1 / 2 | x | XTAL1 / 2048 - */ - -/* CPG registers */ -#define FRQCRA IOMEM(0xe6150000) -#define FRQCRB IOMEM(0xe6150004) -#define VCLKCR1 IOMEM(0xE6150008) -#define VCLKCR2 IOMEM(0xE615000c) -#define FRQCRC IOMEM(0xe61500e0) -#define FSIACKCR IOMEM(0xe6150018) -#define PLLC01CR IOMEM(0xe6150028) - -#define SUBCKCR IOMEM(0xe6150080) -#define USBCKCR IOMEM(0xe615008c) - -#define MSTPSR0 IOMEM(0xe6150030) -#define MSTPSR1 IOMEM(0xe6150038) -#define MSTPSR2 IOMEM(0xe6150040) -#define MSTPSR3 IOMEM(0xe6150048) -#define MSTPSR4 IOMEM(0xe615004c) -#define FSIBCKCR IOMEM(0xe6150090) -#define HDMICKCR IOMEM(0xe6150094) -#define SMSTPCR0 IOMEM(0xe6150130) -#define SMSTPCR1 IOMEM(0xe6150134) -#define SMSTPCR2 IOMEM(0xe6150138) -#define SMSTPCR3 IOMEM(0xe615013c) -#define SMSTPCR4 IOMEM(0xe6150140) - -#define FSIDIVA IOMEM(0xFE1F8000) -#define FSIDIVB IOMEM(0xFE1F8008) - -/* Fixed 32 KHz root clock from EXTALR pin */ -static struct clk extalr_clk = { - .rate = 32768, -}; - -/* - * 25MHz default rate for the EXTAL1 root input clock. - * If needed, reset this with clk_set_rate() from the platform code. - */ -static struct clk extal1_clk = { - .rate = 25000000, -}; - -/* - * 48MHz default rate for the EXTAL2 root input clock. - * If needed, reset this with clk_set_rate() from the platform code. - */ -static struct clk extal2_clk = { - .rate = 48000000, -}; - -/* - * 27MHz default rate for the DV_CLKI root input clock. - * If needed, reset this with clk_set_rate() from the platform code. - */ -static struct clk dv_clk = { - .rate = 27000000, -}; - -SH_CLK_RATIO(div2, 1, 2); -SH_CLK_RATIO(div1k, 1, 1024); - -SH_FIXED_RATIO_CLK(extal1_div2_clk, extal1_clk, div2); -SH_FIXED_RATIO_CLK(extal1_div1024_clk, extal1_clk, div1k); -SH_FIXED_RATIO_CLK(extal1_div2048_clk, extal1_div2_clk, div1k); -SH_FIXED_RATIO_CLK(extal2_div2_clk, extal2_clk, div2); - -static struct sh_clk_ops followparent_clk_ops = { - .recalc = followparent_recalc, -}; - -/* Main clock */ -static struct clk system_clk = { - .ops = &followparent_clk_ops, -}; - -SH_FIXED_RATIO_CLK(system_div2_clk, system_clk, div2); - -/* r_clk */ -static struct clk r_clk = { - .ops = &followparent_clk_ops, -}; - -/* PLLC0/PLLC1 */ -static unsigned long pllc01_recalc(struct clk *clk) -{ - unsigned long mult = 1; - - if (__raw_readl(PLLC01CR) & (1 << 14)) - mult = ((__raw_readl(clk->enable_reg) >> 24) & 0x7f) + 1; - - return clk->parent->rate * mult; -} - -static struct sh_clk_ops pllc01_clk_ops = { - .recalc = pllc01_recalc, -}; - -static struct clk pllc0_clk = { - .ops = &pllc01_clk_ops, - .flags = CLK_ENABLE_ON_INIT, - .parent = &system_clk, - .enable_reg = (void __iomem *)FRQCRC, -}; - -static struct clk pllc1_clk = { - .ops = &pllc01_clk_ops, - .flags = CLK_ENABLE_ON_INIT, - .parent = &system_div2_clk, - .enable_reg = (void __iomem *)FRQCRA, -}; - -/* PLLC1 / 2 */ -SH_FIXED_RATIO_CLK(pllc1_div2_clk, pllc1_clk, div2); - -/* USB clock */ -/* - * USBCKCR is controlling usb24 clock - * bit[7] : parent clock - * bit[6] : clock divide rate - * And this bit[7] is used as a "usb24s" from other devices. - * (Video clock / Sub clock / SPU clock) - * You can controll this clock as a below. - * - * struct clk *usb24 = clk_get(dev, "usb24"); - * struct clk *usb24s = clk_get(NULL, "usb24s"); - * struct clk *system = clk_get(NULL, "system_clk"); - * int rate = clk_get_rate(system); - * - * clk_set_parent(usb24s, system); // for bit[7] - * clk_set_rate(usb24, rate / 2); // for bit[6] - */ -static struct clk *usb24s_parents[] = { - [0] = &system_clk, - [1] = &extal2_clk -}; - -static int usb24s_enable(struct clk *clk) -{ - __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR); - - return 0; -} - -static void usb24s_disable(struct clk *clk) -{ - __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR); -} - -static int usb24s_set_parent(struct clk *clk, struct clk *parent) -{ - int i, ret; - u32 val; - - if (!clk->parent_table || !clk->parent_num) - return -EINVAL; - - /* Search the parent */ - for (i = 0; i < clk->parent_num; i++) - if (clk->parent_table[i] == parent) - break; - - if (i == clk->parent_num) - return -ENODEV; - - ret = clk_reparent(clk, parent); - if (ret < 0) - return ret; - - val = __raw_readl(USBCKCR); - val &= ~(1 << 7); - val |= i << 7; - __raw_writel(val, USBCKCR); - - return 0; -} - -static struct sh_clk_ops usb24s_clk_ops = { - .recalc = followparent_recalc, - .enable = usb24s_enable, - .disable = usb24s_disable, - .set_parent = usb24s_set_parent, -}; - -static struct clk usb24s_clk = { - .ops = &usb24s_clk_ops, - .parent_table = usb24s_parents, - .parent_num = ARRAY_SIZE(usb24s_parents), - .parent = &system_clk, -}; - -static unsigned long usb24_recalc(struct clk *clk) -{ - return clk->parent->rate / - ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2); -}; - -static int usb24_set_rate(struct clk *clk, unsigned long rate) -{ - u32 val; - - /* closer to which ? parent->rate or parent->rate/2 */ - val = __raw_readl(USBCKCR); - val &= ~(1 << 6); - val |= (rate > (clk->parent->rate / 4) * 3) << 6; - __raw_writel(val, USBCKCR); - - return 0; -} - -static struct sh_clk_ops usb24_clk_ops = { - .recalc = usb24_recalc, - .set_rate = usb24_set_rate, -}; - -static struct clk usb24_clk = { - .ops = &usb24_clk_ops, - .parent = &usb24s_clk, -}; - -/* External FSIACK/FSIBCK clock */ -static struct clk fsiack_clk = { -}; - -static struct clk fsibck_clk = { -}; - -static struct clk *main_clks[] = { - &extalr_clk, - &extal1_clk, - &extal2_clk, - &extal1_div2_clk, - &extal1_div1024_clk, - &extal1_div2048_clk, - &extal2_div2_clk, - &dv_clk, - &system_clk, - &system_div2_clk, - &r_clk, - &pllc0_clk, - &pllc1_clk, - &pllc1_div2_clk, - &usb24s_clk, - &usb24_clk, - &fsiack_clk, - &fsibck_clk, -}; - -/* DIV4 clocks */ -static void div4_kick(struct clk *clk) -{ - unsigned long value; - - /* set KICK bit in FRQCRB to update hardware setting */ - value = __raw_readl(FRQCRB); - value |= (1 << 31); - __raw_writel(value, FRQCRB); -} - -static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, - 24, 32, 36, 48, 0, 72, 96, 0 }; - -static struct clk_div_mult_table div4_div_mult_table = { - .divisors = divisors, - .nr_divisors = ARRAY_SIZE(divisors), -}; - -static struct clk_div4_table div4_table = { - .div_mult_table = &div4_div_mult_table, - .kick = div4_kick, -}; - -enum { - DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, - DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, - DIV4_NR -}; - -static struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_ZG] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_B] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), - [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), - [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), - [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), - [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), - [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), - [DIV4_CP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 0, 0x6fff, 0), -}; - -/* DIV6 reparent */ -enum { - DIV6_HDMI, - DIV6_VCLK1, DIV6_VCLK2, - DIV6_FSIA, DIV6_FSIB, - DIV6_REPARENT_NR, -}; - -static struct clk *hdmi_parent[] = { - [0] = &pllc1_div2_clk, - [1] = &system_clk, - [2] = &dv_clk -}; - -static struct clk *vclk_parents[8] = { - [0] = &pllc1_div2_clk, - [2] = &dv_clk, - [3] = &usb24s_clk, - [4] = &extal1_div2_clk, - [5] = &extalr_clk, -}; - -static struct clk *fsia_parents[] = { - [0] = &pllc1_div2_clk, - [1] = &fsiack_clk, /* external clock */ -}; - -static struct clk *fsib_parents[] = { - [0] = &pllc1_div2_clk, - [1] = &fsibck_clk, /* external clock */ -}; - -static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { - [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, - hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), - [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0, - vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), - [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, - vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), - [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0, - fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2), - [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0, - fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2), -}; - -/* DIV6 clocks */ -enum { - DIV6_SUB, - DIV6_NR -}; - -static struct clk div6_clks[DIV6_NR] = { - [DIV6_SUB] = SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0), -}; - -/* HDMI1/2 clock */ -static unsigned long hdmi12_recalc(struct clk *clk) -{ - u32 val = __raw_readl(HDMICKCR); - int shift = (int)clk->priv; - - val >>= shift; - val &= 0x3; - - return clk->parent->rate / (1 << val); -}; - -static int hdmi12_set_rate(struct clk *clk, unsigned long rate) -{ - u32 val, mask; - int i, shift; - - for (i = 0; i < 3; i++) - if (rate == clk->parent->rate / (1 << i)) - goto find; - return -ENODEV; - -find: - shift = (int)clk->priv; - - val = __raw_readl(HDMICKCR); - mask = ~(0x3 << shift); - val = (val & mask) | i << shift; - __raw_writel(val, HDMICKCR); - - return 0; -}; - -static struct sh_clk_ops hdmi12_clk_ops = { - .recalc = hdmi12_recalc, - .set_rate = hdmi12_set_rate, -}; - -static struct clk hdmi1_clk = { - .ops = &hdmi12_clk_ops, - .priv = (void *)9, - .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ -}; - -static struct clk hdmi2_clk = { - .ops = &hdmi12_clk_ops, - .priv = (void *)11, - .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ -}; - -static struct clk *late_main_clks[] = { - &hdmi1_clk, - &hdmi2_clk, -}; - -/* FSI DIV */ -enum { FSIDIV_A, FSIDIV_B, FSIDIV_REPARENT_NR }; - -static struct clk fsidivs[] = { - [FSIDIV_A] = SH_CLK_FSIDIV(FSIDIVA, &div6_reparent_clks[DIV6_FSIA]), - [FSIDIV_B] = SH_CLK_FSIDIV(FSIDIVB, &div6_reparent_clks[DIV6_FSIB]), -}; - -/* MSTP */ -enum { - MSTP128, MSTP127, MSTP125, - MSTP116, MSTP111, MSTP100, MSTP117, - - MSTP230, MSTP229, - MSTP222, - MSTP218, MSTP217, MSTP216, MSTP214, - MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, - - MSTP329, MSTP328, MSTP323, MSTP320, - MSTP314, MSTP313, MSTP312, - MSTP309, MSTP304, - - MSTP416, MSTP415, MSTP407, MSTP406, - - MSTP_NR -}; - -static struct clk mstp_clks[MSTP_NR] = { - [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 28, 0), /* CEU21 */ - [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 27, 0), /* CEU20 */ - [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */ - [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ - [MSTP116] = SH_CLK_MSTP32(&div4_clks[DIV4_HPP], SMSTPCR1, 16, 0), /* IIC0 */ - [MSTP111] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 11, 0), /* TMU1 */ - [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */ - - [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */ - [MSTP229] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 29, 0), /* INTCA */ - [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */ - [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */ - [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */ - [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */ - [MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */ - [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ - [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ - [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ - [MSTP203] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */ - [MSTP202] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */ - [MSTP201] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ - [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ - - [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ - [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ - [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ - [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ - [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ - [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ - [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */ - [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 9, 0), /* GEther */ - [MSTP304] = SH_CLK_MSTP32(&div4_clks[DIV4_CP], SMSTPCR3, 4, 0), /* TPU0 */ - - [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ - [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */ - [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ - [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ -}; - -static struct clk_lookup lookups[] = { - /* main clocks */ - CLKDEV_CON_ID("extalr", &extalr_clk), - CLKDEV_CON_ID("extal1", &extal1_clk), - CLKDEV_CON_ID("extal2", &extal2_clk), - CLKDEV_CON_ID("extal1_div2", &extal1_div2_clk), - CLKDEV_CON_ID("extal1_div1024", &extal1_div1024_clk), - CLKDEV_CON_ID("extal1_div2048", &extal1_div2048_clk), - CLKDEV_CON_ID("extal2_div2", &extal2_div2_clk), - CLKDEV_CON_ID("dv_clk", &dv_clk), - CLKDEV_CON_ID("system_clk", &system_clk), - CLKDEV_CON_ID("system_div2_clk", &system_div2_clk), - CLKDEV_CON_ID("r_clk", &r_clk), - CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), - CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), - CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), - CLKDEV_CON_ID("usb24s", &usb24s_clk), - CLKDEV_CON_ID("hdmi1", &hdmi1_clk), - CLKDEV_CON_ID("hdmi2", &hdmi2_clk), - CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]), - CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]), - CLKDEV_CON_ID("fsiack", &fsiack_clk), - CLKDEV_CON_ID("fsibck", &fsibck_clk), - - /* DIV4 clocks */ - CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), - CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]), - CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]), - CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]), - CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]), - CLKDEV_CON_ID("hpp_clk", &div4_clks[DIV4_HPP]), - CLKDEV_CON_ID("s_clk", &div4_clks[DIV4_S]), - CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]), - CLKDEV_CON_ID("m3_clk", &div4_clks[DIV4_M3]), - CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]), - - /* DIV6 clocks */ - CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), - - /* MSTP32 clocks */ - CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), - CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), - CLKDEV_DEV_ID("fff20000.i2c", &mstp_clks[MSTP116]), - CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), - CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), - CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]), - - CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), - CLKDEV_DEV_ID("e6c80000.serial", &mstp_clks[MSTP200]), - CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), - CLKDEV_DEV_ID("e6c70000.serial", &mstp_clks[MSTP201]), - CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), - CLKDEV_DEV_ID("e6c60000.serial", &mstp_clks[MSTP202]), - CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), - CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]), - CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), - CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]), - CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), - CLKDEV_DEV_ID("e6c30000.serial", &mstp_clks[MSTP206]), - CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), - CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]), - CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), - CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), - CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), - CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), - CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]), - CLKDEV_DEV_ID("e6cd0000.serial", &mstp_clks[MSTP222]), - CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP229]), - CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP229]), - CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP229]), - CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP229]), - CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), - CLKDEV_DEV_ID("e6cc0000.serial", &mstp_clks[MSTP230]), - - CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), - CLKDEV_DEV_ID("fe1f0000.sound", &mstp_clks[MSTP328]), - CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), - CLKDEV_DEV_ID("e6c20000.i2c", &mstp_clks[MSTP323]), - CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), - CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), - CLKDEV_DEV_ID("e6850000.sd", &mstp_clks[MSTP314]), - CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), - CLKDEV_DEV_ID("e6860000.sd", &mstp_clks[MSTP313]), - CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), - CLKDEV_DEV_ID("e6bd0000.mmc", &mstp_clks[MSTP312]), - CLKDEV_DEV_ID("r8a7740-gether", &mstp_clks[MSTP309]), - CLKDEV_DEV_ID("e9a00000.ethernet", &mstp_clks[MSTP309]), - CLKDEV_DEV_ID("renesas-tpu-pwm", &mstp_clks[MSTP304]), - CLKDEV_DEV_ID("e6600000.pwm", &mstp_clks[MSTP304]), - - CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), - CLKDEV_DEV_ID("e6870000.sd", &mstp_clks[MSTP415]), - - /* ICK */ - CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP111]), - CLKDEV_ICK_ID("fck", "fff90000.timer", &mstp_clks[MSTP111]), - CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]), - CLKDEV_ICK_ID("fck", "fff80000.timer", &mstp_clks[MSTP125]), - CLKDEV_ICK_ID("fck", "sh-cmt-48.1", &mstp_clks[MSTP329]), - CLKDEV_ICK_ID("fck", "e6138000.timer", &mstp_clks[MSTP329]), - CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), - CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]), - CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), - CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), - CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), - CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), - - CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), - CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), - CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]), - CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]), - CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk), - CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk), -}; - -void __init r8a7740_clock_init(u8 md_ck) -{ - int k, ret = 0; - - /* detect system clock parent */ - if (md_ck & MD_CK1) - system_clk.parent = &extal1_div2_clk; - else - system_clk.parent = &extal1_clk; - - /* detect RCLK parent */ - switch (md_ck & (MD_CK2 | MD_CK1)) { - case MD_CK2 | MD_CK1: - r_clk.parent = &extal1_div2048_clk; - break; - case MD_CK2: - r_clk.parent = &extal1_div1024_clk; - break; - case MD_CK1: - default: - r_clk.parent = &extalr_clk; - break; - } - - for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) - ret = clk_register(main_clks[k]); - - if (!ret) - ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); - - if (!ret) - ret = sh_clk_div6_register(div6_clks, DIV6_NR); - - if (!ret) - ret = sh_clk_div6_reparent_register(div6_reparent_clks, - DIV6_REPARENT_NR); - - if (!ret) - ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); - - for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) - ret = clk_register(late_main_clks[k]); - - if (!ret) - ret = sh_clk_fsidiv_register(fsidivs, FSIDIV_REPARENT_NR); - - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - - if (!ret) - shmobile_clk_init(); - else - panic("failed to setup r8a7740 clocks\n"); -} diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c deleted file mode 100644 index 3855fb0..0000000 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * sh73a0 clock framework support - * - * Copyright (C) 2010 Magnus Damm - * - * 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 - * - * 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. - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/sh_clk.h> -#include <linux/clkdev.h> -#include <asm/processor.h> -#include "clock.h" -#include "common.h" - -#define FRQCRA IOMEM(0xe6150000) -#define FRQCRB IOMEM(0xe6150004) -#define FRQCRD IOMEM(0xe61500e4) -#define VCLKCR1 IOMEM(0xe6150008) -#define VCLKCR2 IOMEM(0xe615000C) -#define VCLKCR3 IOMEM(0xe615001C) -#define ZBCKCR IOMEM(0xe6150010) -#define FLCKCR IOMEM(0xe6150014) -#define SD0CKCR IOMEM(0xe6150074) -#define SD1CKCR IOMEM(0xe6150078) -#define SD2CKCR IOMEM(0xe615007C) -#define FSIACKCR IOMEM(0xe6150018) -#define FSIBCKCR IOMEM(0xe6150090) -#define SUBCKCR IOMEM(0xe6150080) -#define SPUACKCR IOMEM(0xe6150084) -#define SPUVCKCR IOMEM(0xe6150094) -#define MSUCKCR IOMEM(0xe6150088) -#define HSICKCR IOMEM(0xe615008C) -#define MFCK1CR IOMEM(0xe6150098) -#define MFCK2CR IOMEM(0xe615009C) -#define DSITCKCR IOMEM(0xe6150060) -#define DSI0PCKCR IOMEM(0xe6150064) -#define DSI1PCKCR IOMEM(0xe6150068) -#define DSI0PHYCR 0xe615006C -#define DSI1PHYCR 0xe6150070 -#define PLLECR IOMEM(0xe61500d0) -#define PLL0CR IOMEM(0xe61500d8) -#define PLL1CR IOMEM(0xe6150028) -#define PLL2CR IOMEM(0xe615002c) -#define PLL3CR IOMEM(0xe61500dc) -#define SMSTPCR0 IOMEM(0xe6150130) -#define SMSTPCR1 IOMEM(0xe6150134) -#define SMSTPCR2 IOMEM(0xe6150138) -#define SMSTPCR3 IOMEM(0xe615013c) -#define SMSTPCR4 IOMEM(0xe6150140) -#define SMSTPCR5 IOMEM(0xe6150144) -#define CKSCR IOMEM(0xe61500c0) - -/* Fixed 32 KHz root clock from EXTALR pin */ -static struct clk r_clk = { - .rate = 32768, -}; - -/* - * 26MHz default rate for the EXTAL1 root input clock. - * If needed, reset this with clk_set_rate() from the platform code. - */ -struct clk sh73a0_extal1_clk = { - .rate = 26000000, -}; - -/* - * 48MHz default rate for the EXTAL2 root input clock. - * If needed, reset this with clk_set_rate() from the platform code. - */ -struct clk sh73a0_extal2_clk = { - .rate = 48000000, -}; - -static struct sh_clk_ops main_clk_ops = { - .recalc = followparent_recalc, -}; - -/* Main clock */ -static struct clk main_clk = { - /* .parent wll be set on sh73a0_clock_init() */ - .ops = &main_clk_ops, -}; - -/* PLL0, PLL1, PLL2, PLL3 */ -static unsigned long pll_recalc(struct clk *clk) -{ - unsigned long mult = 1; - - if (__raw_readl(PLLECR) & (1 << clk->enable_bit)) { - mult = (((__raw_readl(clk->enable_reg) >> 24) & 0x3f) + 1); - /* handle CFG bit for PLL1 and PLL2 */ - switch (clk->enable_bit) { - case 1: - case 2: - if (__raw_readl(clk->enable_reg) & (1 << 20)) - mult *= 2; - } - } - - return clk->parent->rate * mult; -} - -static struct sh_clk_ops pll_clk_ops = { - .recalc = pll_recalc, -}; - -static struct clk pll0_clk = { - .ops = &pll_clk_ops, - .flags = CLK_ENABLE_ON_INIT, - .parent = &main_clk, - .enable_reg = (void __iomem *)PLL0CR, - .enable_bit = 0, -}; - -static struct clk pll1_clk = { - .ops = &pll_clk_ops, - .flags = CLK_ENABLE_ON_INIT, - .parent = &main_clk, - .enable_reg = (void __iomem *)PLL1CR, - .enable_bit = 1, -}; - -static struct clk pll2_clk = { - .ops = &pll_clk_ops, - .flags = CLK_ENABLE_ON_INIT, - .parent = &main_clk, - .enable_reg = (void __iomem *)PLL2CR, - .enable_bit = 2, -}; - -static struct clk pll3_clk = { - .ops = &pll_clk_ops, - .flags = CLK_ENABLE_ON_INIT, - .parent = &main_clk, - .enable_reg = (void __iomem *)PLL3CR, - .enable_bit = 3, -}; - -/* A fixed divide block */ -SH_CLK_RATIO(div2, 1, 2); -SH_CLK_RATIO(div7, 1, 7); -SH_CLK_RATIO(div13, 1, 13); - -SH_FIXED_RATIO_CLK(extal1_div2_clk, sh73a0_extal1_clk, div2); -SH_FIXED_RATIO_CLK(extal2_div2_clk, sh73a0_extal2_clk, div2); -SH_FIXED_RATIO_CLK(main_div2_clk, main_clk, div2); -SH_FIXED_RATIO_CLK(pll1_div2_clk, pll1_clk, div2); -SH_FIXED_RATIO_CLK(pll1_div7_clk, pll1_clk, div7); -SH_FIXED_RATIO_CLK(pll1_div13_clk, pll1_clk, div13); - -/* External input clock */ -struct clk sh73a0_extcki_clk = { -}; - -struct clk sh73a0_extalr_clk = { -}; - -static struct clk *main_clks[] = { - &r_clk, - &sh73a0_extal1_clk, - &sh73a0_extal2_clk, - &extal1_div2_clk, - &extal2_div2_clk, - &main_clk, - &main_div2_clk, - &pll0_clk, - &pll1_clk, - &pll2_clk, - &pll3_clk, - &pll1_div2_clk, - &pll1_div7_clk, - &pll1_div13_clk, - &sh73a0_extcki_clk, - &sh73a0_extalr_clk, -}; - -static int frqcr_kick(void) -{ - int i; - - /* set KICK bit in FRQCRB to update hardware setting, check success */ - __raw_writel(__raw_readl(FRQCRB) | (1 << 31), FRQCRB); - for (i = 1000; i; i--) - if (__raw_readl(FRQCRB) & (1 << 31)) - cpu_relax(); - else - return i; - - return -ETIMEDOUT; -} - -static void div4_kick(struct clk *clk) -{ - frqcr_kick(); -} - -static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, - 24, 0, 36, 48, 7 }; - -static struct clk_div_mult_table div4_div_mult_table = { - .divisors = divisors, - .nr_divisors = ARRAY_SIZE(divisors), -}; - -static struct clk_div4_table div4_table = { - .div_mult_table = &div4_div_mult_table, - .kick = div4_kick, -}; - -enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2, - DIV4_Z, DIV4_ZX, DIV4_HP, DIV4_NR }; - -#define DIV4(_reg, _bit, _mask, _flags) \ - SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags) - -static struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT), - /* - * ZG clock is dividing PLL0 frequency to supply SGX. Make sure not to - * exceed maximum frequencies of 201.5MHz for VDD_DVFS=1.175 and - * 239.2MHz for VDD_DVFS=1.315V. - */ - [DIV4_ZG] = SH_CLK_DIV4(&pll0_clk, FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT), - [DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT), - [DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0), - [DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0), - [DIV4_Z] = SH_CLK_DIV4(&pll0_clk, FRQCRB, 24, 0x97f, 0), - [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0), - [DIV4_HP] = DIV4(FRQCRB, 4, 0xdff, 0), -}; - -static unsigned long twd_recalc(struct clk *clk) -{ - return clk_get_rate(clk->parent) / 4; -} - -static struct sh_clk_ops twd_clk_ops = { - .recalc = twd_recalc, -}; - -static struct clk twd_clk = { - .parent = &div4_clks[DIV4_Z], - .ops = &twd_clk_ops, -}; - -static struct sh_clk_ops zclk_ops, kicker_ops; -static const struct sh_clk_ops *div4_clk_ops; - -static int zclk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret; - - if (!clk->parent || !__clk_get(clk->parent)) - return -ENODEV; - - if (readl(FRQCRB) & (1 << 31)) - return -EBUSY; - - if (rate == clk_get_rate(clk->parent)) { - /* 1:1 - switch off divider */ - __raw_writel(__raw_readl(FRQCRB) & ~(1 << 28), FRQCRB); - /* nullify the divider to prepare for the next time */ - ret = div4_clk_ops->set_rate(clk, rate / 2); - if (!ret) - ret = frqcr_kick(); - if (ret > 0) - ret = 0; - } else { - /* Enable the divider */ - __raw_writel(__raw_readl(FRQCRB) | (1 << 28), FRQCRB); - - ret = frqcr_kick(); - if (ret >= 0) - /* - * set the divider - call the DIV4 method, it will kick - * FRQCRB too - */ - ret = div4_clk_ops->set_rate(clk, rate); - if (ret < 0) - goto esetrate; - } - -esetrate: - __clk_put(clk->parent); - return ret; -} - -static long zclk_round_rate(struct clk *clk, unsigned long rate) -{ - unsigned long div_freq = div4_clk_ops->round_rate(clk, rate), - parent_freq = clk_get_rate(clk->parent); - - if (rate > div_freq && abs(parent_freq - rate) < rate - div_freq) - return parent_freq; - - return div_freq; -} - -static unsigned long zclk_recalc(struct clk *clk) -{ - /* - * Must recalculate frequencies in case PLL0 has been changed, even if - * the divisor is unused ATM! - */ - unsigned long div_freq = div4_clk_ops->recalc(clk); - - if (__raw_readl(FRQCRB) & (1 << 28)) - return div_freq; - - return clk_get_rate(clk->parent); -} - -static int kicker_set_rate(struct clk *clk, unsigned long rate) -{ - if (__raw_readl(FRQCRB) & (1 << 31)) - return -EBUSY; - - return div4_clk_ops->set_rate(clk, rate); -} - -static void div4_clk_extend(void) -{ - int i; - - div4_clk_ops = div4_clks[0].ops; - - /* Add a kicker-busy check before changing the rate */ - kicker_ops = *div4_clk_ops; - /* We extend the DIV4 clock with a 1:1 pass-through case */ - zclk_ops = *div4_clk_ops; - - kicker_ops.set_rate = kicker_set_rate; - zclk_ops.set_rate = zclk_set_rate; - zclk_ops.round_rate = zclk_round_rate; - zclk_ops.recalc = zclk_recalc; - - for (i = 0; i < DIV4_NR; i++) - div4_clks[i].ops = i == DIV4_Z ? &zclk_ops : &kicker_ops; -} - -enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1, - DIV6_FLCTL, DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2, - DIV6_FSIA, DIV6_FSIB, DIV6_SUB, - DIV6_SPUA, DIV6_SPUV, DIV6_MSU, - DIV6_HSI, DIV6_MFG1, DIV6_MFG2, - DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P, - DIV6_NR }; - -static struct clk *vck_parent[8] = { - [0] = &pll1_div2_clk, - [1] = &pll2_clk, - [2] = &sh73a0_extcki_clk, - [3] = &sh73a0_extal2_clk, - [4] = &main_div2_clk, - [5] = &sh73a0_extalr_clk, - [6] = &main_clk, -}; - -static struct clk *pll_parent[4] = { - [0] = &pll1_div2_clk, - [1] = &pll2_clk, - [2] = &pll1_div13_clk, -}; - -static struct clk *hsi_parent[4] = { - [0] = &pll1_div2_clk, - [1] = &pll2_clk, - [2] = &pll1_div7_clk, -}; - -static struct clk *pll_extal2_parent[] = { - [0] = &pll1_div2_clk, - [1] = &pll2_clk, - [2] = &sh73a0_extal2_clk, - [3] = &sh73a0_extal2_clk, -}; - -static struct clk *dsi_parent[8] = { - [0] = &pll1_div2_clk, - [1] = &pll2_clk, - [2] = &main_clk, - [3] = &sh73a0_extal2_clk, - [4] = &sh73a0_extcki_clk, -}; - -static struct clk div6_clks[DIV6_NR] = { - [DIV6_VCK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0, - vck_parent, ARRAY_SIZE(vck_parent), 12, 3), - [DIV6_VCK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, - vck_parent, ARRAY_SIZE(vck_parent), 12, 3), - [DIV6_VCK3] = SH_CLK_DIV6_EXT(VCLKCR3, 0, - vck_parent, ARRAY_SIZE(vck_parent), 12, 3), - [DIV6_ZB1] = SH_CLK_DIV6_EXT(ZBCKCR, CLK_ENABLE_ON_INIT, - pll_parent, ARRAY_SIZE(pll_parent), 7, 1), - [DIV6_FLCTL] = SH_CLK_DIV6_EXT(FLCKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 7, 1), - [DIV6_SDHI0] = SH_CLK_DIV6_EXT(SD0CKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 6, 2), - [DIV6_SDHI1] = SH_CLK_DIV6_EXT(SD1CKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 6, 2), - [DIV6_SDHI2] = SH_CLK_DIV6_EXT(SD2CKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 6, 2), - [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 6, 1), - [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 6, 1), - [DIV6_SUB] = SH_CLK_DIV6_EXT(SUBCKCR, 0, - pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2), - [DIV6_SPUA] = SH_CLK_DIV6_EXT(SPUACKCR, 0, - pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2), - [DIV6_SPUV] = SH_CLK_DIV6_EXT(SPUVCKCR, 0, - pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2), - [DIV6_MSU] = SH_CLK_DIV6_EXT(MSUCKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 7, 1), - [DIV6_HSI] = SH_CLK_DIV6_EXT(HSICKCR, 0, - hsi_parent, ARRAY_SIZE(hsi_parent), 6, 2), - [DIV6_MFG1] = SH_CLK_DIV6_EXT(MFCK1CR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 7, 1), - [DIV6_MFG2] = SH_CLK_DIV6_EXT(MFCK2CR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 7, 1), - [DIV6_DSIT] = SH_CLK_DIV6_EXT(DSITCKCR, 0, - pll_parent, ARRAY_SIZE(pll_parent), 7, 1), - [DIV6_DSI0P] = SH_CLK_DIV6_EXT(DSI0PCKCR, 0, - dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3), - [DIV6_DSI1P] = SH_CLK_DIV6_EXT(DSI1PCKCR, 0, - dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3), -}; - -/* DSI DIV */ -static unsigned long dsiphy_recalc(struct clk *clk) -{ - u32 value; - - value = __raw_readl(clk->mapping->base); - - /* FIXME */ - if (!(value & 0x000B8000)) - return clk->parent->rate; - - value &= 0x3f; - value += 1; - - if ((value < 12) || - (value > 33)) { - pr_err("DSIPHY has wrong value (%d)", value); - return 0; - } - - return clk->parent->rate / value; -} - -static long dsiphy_round_rate(struct clk *clk, unsigned long rate) -{ - return clk_rate_mult_range_round(clk, 12, 33, rate); -} - -static void dsiphy_disable(struct clk *clk) -{ - u32 value; - - value = __raw_readl(clk->mapping->base); - value &= ~0x000B8000; - - __raw_writel(value , clk->mapping->base); -} - -static int dsiphy_enable(struct clk *clk) -{ - u32 value; - int multi; - - value = __raw_readl(clk->mapping->base); - multi = (value & 0x3f) + 1; - - if ((multi < 12) || (multi > 33)) - return -EIO; - - __raw_writel(value | 0x000B8000, clk->mapping->base); - - return 0; -} - -static int dsiphy_set_rate(struct clk *clk, unsigned long rate) -{ - u32 value; - int idx; - - idx = rate / clk->parent->rate; - if ((idx < 12) || (idx > 33)) - return -EINVAL; - - idx += -1; - - value = __raw_readl(clk->mapping->base); - value = (value & ~0x3f) + idx; - - __raw_writel(value, clk->mapping->base); - - return 0; -} - -static struct sh_clk_ops dsiphy_clk_ops = { - .recalc = dsiphy_recalc, - .round_rate = dsiphy_round_rate, - .set_rate = dsiphy_set_rate, - .enable = dsiphy_enable, - .disable = dsiphy_disable, -}; - -static struct clk_mapping dsi0phy_clk_mapping = { - .phys = DSI0PHYCR, - .len = 4, -}; - -static struct clk_mapping dsi1phy_clk_mapping = { - .phys = DSI1PHYCR, - .len = 4, -}; - -static struct clk dsi0phy_clk = { - .ops = &dsiphy_clk_ops, - .parent = &div6_clks[DIV6_DSI0P], /* late install */ - .mapping = &dsi0phy_clk_mapping, -}; - -static struct clk dsi1phy_clk = { - .ops = &dsiphy_clk_ops, - .parent = &div6_clks[DIV6_DSI1P], /* late install */ - .mapping = &dsi1phy_clk_mapping, -}; - -static struct clk *late_main_clks[] = { - &dsi0phy_clk, - &dsi1phy_clk, - &twd_clk, -}; - -enum { MSTP001, - MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP112, MSTP100, - MSTP219, MSTP218, MSTP217, - MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, - MSTP331, MSTP329, MSTP328, MSTP325, MSTP323, MSTP322, - MSTP314, MSTP313, MSTP312, MSTP311, - MSTP304, MSTP303, MSTP302, MSTP301, MSTP300, - MSTP411, MSTP410, MSTP403, - MSTP508, - MSTP_NR }; - -#define MSTP(_parent, _reg, _bit, _flags) \ - SH_CLK_MSTP32(_parent, _reg, _bit, _flags) - -static struct clk mstp_clks[MSTP_NR] = { - [MSTP001] = MSTP(&div4_clks[DIV4_HP], SMSTPCR0, 1, 0), /* IIC2 */ - [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* CEU1 */ - [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* CSI2-RX1 */ - [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU0 */ - [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2-RX0 */ - [MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */ - [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX0 */ - [MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */ - [MSTP112] = MSTP(&div4_clks[DIV4_ZG], SMSTPCR1, 12, 0), /* SGX */ - [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */ - [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */ - [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* SY-DMAC */ - [MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* MP-DMAC */ - [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ - [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ - [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ - [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */ - [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */ - [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ - [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ - [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */ - [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ - [MSTP328] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /*FSI*/ - [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */ - [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */ - [MSTP322] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 22, 0), /* USB */ - [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */ - [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */ - [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ - [MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */ - [MSTP304] = MSTP(&main_div2_clk, SMSTPCR3, 4, 0), /* TPU0 */ - [MSTP303] = MSTP(&main_div2_clk, SMSTPCR3, 3, 0), /* TPU1 */ - [MSTP302] = MSTP(&main_div2_clk, SMSTPCR3, 2, 0), /* TPU2 */ - [MSTP301] = MSTP(&main_div2_clk, SMSTPCR3, 1, 0), /* TPU3 */ - [MSTP300] = MSTP(&main_div2_clk, SMSTPCR3, 0, 0), /* TPU4 */ - [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ - [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ - [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ - [MSTP508] = MSTP(&div4_clks[DIV4_HP], SMSTPCR5, 8, 0), /* INTCA0 */ -}; - -/* The lookups structure below includes duplicate entries for some clocks - * with alternate names. - * - The traditional name used when a device is initialised with platform data - * - The name used when a device is initialised using device tree - * The longer-term aim is to remove these duplicates, and indeed the - * lookups table entirely, by describing clocks using device tree. - */ -static struct clk_lookup lookups[] = { - /* main clocks */ - CLKDEV_CON_ID("r_clk", &r_clk), - CLKDEV_DEV_ID("smp_twd", &twd_clk), /* smp_twd */ - - /* DIV4 clocks */ - CLKDEV_DEV_ID("cpu0", &div4_clks[DIV4_Z]), - - /* DIV6 clocks */ - CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]), - CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]), - CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), - CLKDEV_CON_ID("sdhi0_clk", &div6_clks[DIV6_SDHI0]), - CLKDEV_CON_ID("sdhi1_clk", &div6_clks[DIV6_SDHI1]), - CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]), - - /* MSTP32 clocks */ - CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ - CLKDEV_DEV_ID("e6824000.i2c", &mstp_clks[MSTP001]), /* I2C2 */ - CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP129]), /* CEU1 */ - CLKDEV_DEV_ID("sh-mobile-csi2.1", &mstp_clks[MSTP128]), /* CSI2-RX1 */ - CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */ - CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2-RX0 */ - CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ - CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */ - CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */ - CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */ - CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */ - CLKDEV_DEV_ID("e6cd0000.serial", &mstp_clks[MSTP219]), /* SCIFA7 */ - CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */ - CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* MP-DMAC */ - CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */ - CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]), /* SCIFA5 */ - CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */ - CLKDEV_DEV_ID("e6c3000.serial", &mstp_clks[MSTP206]), /* SCIFB */ - CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */ - CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]), /* SCIFA0 */ - CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */ - CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]), /* SCIFA1 */ - CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */ - CLKDEV_DEV_ID("e6c60000.serial", &mstp_clks[MSTP202]), /* SCIFA2 */ - CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ - CLKDEV_DEV_ID("e6c70000.serial", &mstp_clks[MSTP201]), /* SCIFA3 */ - CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ - CLKDEV_DEV_ID("e6c80000.serial", &mstp_clks[MSTP200]), /* SCIFA4 */ - CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ - CLKDEV_DEV_ID("e6cc0000.serial", &mstp_clks[MSTP331]), /* SCIFA6 */ - CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */ - CLKDEV_DEV_ID("ec230000.sound", &mstp_clks[MSTP328]), /* FSI */ - CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ - CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ - CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */ - CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */ - CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ - CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]), /* SDHI0 */ - CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ - CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]), /* SDHI1 */ - CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ - CLKDEV_DEV_ID("e6bd0000.mmc", &mstp_clks[MSTP312]), /* MMCIF0 */ - CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */ - CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP311]), /* SDHI2 */ - CLKDEV_DEV_ID("renesas-tpu-pwm.0", &mstp_clks[MSTP304]), /* TPU0 */ - CLKDEV_DEV_ID("renesas-tpu-pwm.1", &mstp_clks[MSTP303]), /* TPU1 */ - CLKDEV_DEV_ID("renesas-tpu-pwm.2", &mstp_clks[MSTP302]), /* TPU2 */ - CLKDEV_DEV_ID("renesas-tpu-pwm.3", &mstp_clks[MSTP301]), /* TPU3 */ - CLKDEV_DEV_ID("renesas-tpu-pwm.4", &mstp_clks[MSTP300]), /* TPU4 */ - CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */ - CLKDEV_DEV_ID("e6826000.i2c", &mstp_clks[MSTP411]), /* I2C3 */ - CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ - CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */ - CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ - CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP508]), /* INTCA0 */ - CLKDEV_DEV_ID("e6900000.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ - CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP508]), /* INTCA0 */ - CLKDEV_DEV_ID("e6900004.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ - CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP508]), /* INTCA0 */ - CLKDEV_DEV_ID("e6900008.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ - CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP508]), /* INTCA0 */ - CLKDEV_DEV_ID("e690000c.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ - - /* ICK */ - CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), - CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), - CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), - CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk), - CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk), - CLKDEV_ICK_ID("fck", "sh-cmt-48.1", &mstp_clks[MSTP329]), /* CMT1 */ - CLKDEV_ICK_ID("fck", "e6138000.timer", &mstp_clks[MSTP329]), /* CMT1 */ - CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]), /* TMU0 */ -}; - -void __init sh73a0_clock_init(void) -{ - int k, ret = 0; - - /* Set SDHI clocks to a known state */ - __raw_writel(0x108, SD0CKCR); - __raw_writel(0x108, SD1CKCR); - __raw_writel(0x108, SD2CKCR); - - /* detect main clock parent */ - switch ((__raw_readl(CKSCR) >> 28) & 0x03) { - case 0: - main_clk.parent = &sh73a0_extal1_clk; - break; - case 1: - main_clk.parent = &extal1_div2_clk; - break; - case 2: - main_clk.parent = &sh73a0_extal2_clk; - break; - case 3: - main_clk.parent = &extal2_div2_clk; - break; - } - - for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) - ret = clk_register(main_clks[k]); - - if (!ret) { - ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); - if (!ret) - div4_clk_extend(); - } - - if (!ret) - ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR); - - if (!ret) - ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); - - for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) - ret = clk_register(late_main_clks[k]); - - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - - if (!ret) - shmobile_clk_init(); - else - panic("failed to setup sh73a0 clocks\n"); -} diff --git a/arch/arm/mach-shmobile/dma-register.h b/arch/arm/mach-shmobile/dma-register.h deleted file mode 100644 index 52a2f66..0000000 --- a/arch/arm/mach-shmobile/dma-register.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * SH-ARM CPU-specific DMA definitions, used by both DMA drivers - * - * Copyright (C) 2012 Renesas Solutions Corp - * - * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * - * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h - * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> - * - * 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 DMA_REGISTER_H -#define DMA_REGISTER_H - -/* - * Direct Memory Access Controller - */ - -/* Transmit sizes and respective CHCR register values */ -enum { - XMIT_SZ_8BIT = 0, - XMIT_SZ_16BIT = 1, - XMIT_SZ_32BIT = 2, - XMIT_SZ_64BIT = 7, - XMIT_SZ_128BIT = 3, - XMIT_SZ_256BIT = 4, - XMIT_SZ_512BIT = 5, -}; - -/* log2(size / 8) - used to calculate number of transfers */ -static const unsigned int dma_ts_shift[] = { - [XMIT_SZ_8BIT] = 0, - [XMIT_SZ_16BIT] = 1, - [XMIT_SZ_32BIT] = 2, - [XMIT_SZ_64BIT] = 3, - [XMIT_SZ_128BIT] = 4, - [XMIT_SZ_256BIT] = 5, - [XMIT_SZ_512BIT] = 6, -}; - -#define TS_LOW_BIT 0x3 /* --xx */ -#define TS_HI_BIT 0xc /* xx-- */ - -#define TS_LOW_SHIFT (3) -#define TS_HI_SHIFT (20 - 2) /* 2 bits for shifted low TS */ - -#define TS_INDEX2VAL(i) \ - ((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\ - (((i) & TS_HI_BIT) << TS_HI_SHIFT)) - -#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL((xmit_sz))) -#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL((xmit_sz))) - - -/* - * USB High-Speed DMAC - */ -/* Transmit sizes and respective CHCR register values */ -enum { - USBTS_XMIT_SZ_8BYTE = 0, - USBTS_XMIT_SZ_16BYTE = 1, - USBTS_XMIT_SZ_32BYTE = 2, -}; - -/* log2(size / 8) - used to calculate number of transfers */ -static const unsigned int dma_usbts_shift[] = { - [USBTS_XMIT_SZ_8BYTE] = 3, - [USBTS_XMIT_SZ_16BYTE] = 4, - [USBTS_XMIT_SZ_32BYTE] = 5, -}; - -#define USBTS_LOW_BIT 0x3 /* --xx */ -#define USBTS_HI_BIT 0x0 /* ---- */ - -#define USBTS_LOW_SHIFT 6 -#define USBTS_HI_SHIFT 0 - -#define USBTS_INDEX2VAL(i) (((i) & 3) << 6) - -#endif /* DMA_REGISTER_H */ diff --git a/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt b/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt deleted file mode 100644 index 9531f46..0000000 --- a/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt +++ /dev/null @@ -1,410 +0,0 @@ -LIST "KZM9G low-level initialization routine." -LIST "Adapted from u-boot KZM9G support code." - -LIST "Copyright (C) 2013 Ulrich Hecht" - -LIST "This program is free software; you can redistribute it and/or modify" -LIST "it under the terms of the GNU General Public License version 2 as" -LIST "published by the Free Software Foundation." - -LIST "This program is distributed in the hope that it will be useful," -LIST "but WITHOUT ANY WARRANTY; without even the implied warranty of" -LIST "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" -LIST "GNU General Public License for more details." - - -LIST "Register definitions:" - -LIST "Secure control register" -#define LIFEC_SEC_SRC (0xE6110008) - -LIST "RWDT" -#define RWDT_BASE (0xE6020000) -#define RWTCSRA0 (RWDT_BASE + 0x04) - -LIST "HPB Semaphore Control Registers" -#define HPBSCR_BASE (0xE6000000) -#define HPBCTRL6 (HPBSCR_BASE + 0x1030) - -#define SBSC1_BASE (0xFE400000) -#define SDCR0A (SBSC1_BASE + 0x0008) -#define SDCR1A (SBSC1_BASE + 0x000C) -#define SDPCRA (SBSC1_BASE + 0x0010) -#define SDCR0SA (SBSC1_BASE + 0x0018) -#define SDCR1SA (SBSC1_BASE + 0x001C) -#define RTCSRA (SBSC1_BASE + 0x0020) -#define RTCORA (SBSC1_BASE + 0x0028) -#define RTCORHA (SBSC1_BASE + 0x002C) -#define SDWCRC0A (SBSC1_BASE + 0x0040) -#define SDWCRC1A (SBSC1_BASE + 0x0044) -#define SDWCR00A (SBSC1_BASE + 0x0048) -#define SDWCR01A (SBSC1_BASE + 0x004C) -#define SDWCR10A (SBSC1_BASE + 0x0050) -#define SDWCR11A (SBSC1_BASE + 0x0054) -#define SDWCR2A (SBSC1_BASE + 0x0060) -#define SDWCRC2A (SBSC1_BASE + 0x0064) -#define ZQCCRA (SBSC1_BASE + 0x0068) -#define SDMRACR0A (SBSC1_BASE + 0x0084) -#define SDMRTMPCRA (SBSC1_BASE + 0x008C) -#define SDMRTMPMSKA (SBSC1_BASE + 0x0094) -#define SDGENCNTA (SBSC1_BASE + 0x009C) -#define SDDRVCR0A (SBSC1_BASE + 0x00B4) -#define DLLCNT0A (SBSC1_BASE + 0x0354) - -#define SDMRA1 (0xFE500000) -#define SDMRA2 (0xFE5C0000) -#define SDMRA3 (0xFE504000) - -#define SBSC2_BASE (0xFB400000) -#define SDCR0B (SBSC2_BASE + 0x0008) -#define SDCR1B (SBSC2_BASE + 0x000C) -#define SDPCRB (SBSC2_BASE + 0x0010) -#define SDCR0SB (SBSC2_BASE + 0x0018) -#define SDCR1SB (SBSC2_BASE + 0x001C) -#define RTCSRB (SBSC2_BASE + 0x0020) -#define RTCORB (SBSC2_BASE + 0x0028) -#define RTCORHB (SBSC2_BASE + 0x002C) -#define SDWCRC0B (SBSC2_BASE + 0x0040) -#define SDWCRC1B (SBSC2_BASE + 0x0044) -#define SDWCR00B (SBSC2_BASE + 0x0048) -#define SDWCR01B (SBSC2_BASE + 0x004C) -#define SDWCR10B (SBSC2_BASE + 0x0050) -#define SDWCR11B (SBSC2_BASE + 0x0054) -#define SDPDCR0B (SBSC2_BASE + 0x0058) -#define SDWCR2B (SBSC2_BASE + 0x0060) -#define SDWCRC2B (SBSC2_BASE + 0x0064) -#define ZQCCRB (SBSC2_BASE + 0x0068) -#define SDMRACR0B (SBSC2_BASE + 0x0084) -#define SDMRTMPCRB (SBSC2_BASE + 0x008C) -#define SDMRTMPMSKB (SBSC2_BASE + 0x0094) -#define SDGENCNTB (SBSC2_BASE + 0x009C) -#define DPHYCNT0B (SBSC2_BASE + 0x00A0) -#define DPHYCNT1B (SBSC2_BASE + 0x00A4) -#define DPHYCNT2B (SBSC2_BASE + 0x00A8) -#define SDDRVCR0B (SBSC2_BASE + 0x00B4) -#define DLLCNT0B (SBSC2_BASE + 0x0354) - -#define SDMRB1 (0xFB500000) -#define SDMRB2 (0xFB5C0000) -#define SDMRB3 (0xFB504000) - -#define CPG_BASE (0xE6150000) -#define FRQCRA (CPG_BASE + 0x0000) -#define FRQCRB (CPG_BASE + 0x0004) -#define FRQCRD (CPG_BASE + 0x00E4) -#define VCLKCR1 (CPG_BASE + 0x0008) -#define VCLKCR2 (CPG_BASE + 0x000C) -#define VCLKCR3 (CPG_BASE + 0x001C) -#define ZBCKCR (CPG_BASE + 0x0010) -#define FLCKCR (CPG_BASE + 0x0014) -#define SD0CKCR (CPG_BASE + 0x0074) -#define SD1CKCR (CPG_BASE + 0x0078) -#define SD2CKCR (CPG_BASE + 0x007C) -#define FSIACKCR (CPG_BASE + 0x0018) -#define SUBCKCR (CPG_BASE + 0x0080) -#define SPUACKCR (CPG_BASE + 0x0084) -#define SPUVCKCR (CPG_BASE + 0x0094) -#define MSUCKCR (CPG_BASE + 0x0088) -#define HSICKCR (CPG_BASE + 0x008C) -#define FSIBCKCR (CPG_BASE + 0x0090) -#define MFCK1CR (CPG_BASE + 0x0098) -#define MFCK2CR (CPG_BASE + 0x009C) -#define DSITCKCR (CPG_BASE + 0x0060) -#define DSI0PCKCR (CPG_BASE + 0x0064) -#define DSI1PCKCR (CPG_BASE + 0x0068) -#define DSI0PHYCR (CPG_BASE + 0x006C) -#define DVFSCR3 (CPG_BASE + 0x0174) -#define DVFSCR4 (CPG_BASE + 0x0178) -#define DVFSCR5 (CPG_BASE + 0x017C) -#define MPMODE (CPG_BASE + 0x00CC) - -#define PLLECR (CPG_BASE + 0x00D0) -#define PLL0CR (CPG_BASE + 0x00D8) -#define PLL1CR (CPG_BASE + 0x0028) -#define PLL2CR (CPG_BASE + 0x002C) -#define PLL3CR (CPG_BASE + 0x00DC) -#define PLL0STPCR (CPG_BASE + 0x00F0) -#define PLL1STPCR (CPG_BASE + 0x00C8) -#define PLL2STPCR (CPG_BASE + 0x00F8) -#define PLL3STPCR (CPG_BASE + 0x00FC) -#define RMSTPCR0 (CPG_BASE + 0x0110) -#define RMSTPCR1 (CPG_BASE + 0x0114) -#define RMSTPCR2 (CPG_BASE + 0x0118) -#define RMSTPCR3 (CPG_BASE + 0x011C) -#define RMSTPCR4 (CPG_BASE + 0x0120) -#define RMSTPCR5 (CPG_BASE + 0x0124) -#define SMSTPCR0 (CPG_BASE + 0x0130) -#define SMSTPCR2 (CPG_BASE + 0x0138) -#define SMSTPCR3 (CPG_BASE + 0x013C) -#define CPGXXCR4 (CPG_BASE + 0x0150) -#define SRCR0 (CPG_BASE + 0x80A0) -#define SRCR2 (CPG_BASE + 0x80B0) -#define SRCR3 (CPG_BASE + 0x80A8) -#define VREFCR (CPG_BASE + 0x00EC) -#define PCLKCR (CPG_BASE + 0x1020) - -#define PORT32CR (0xE6051020) -#define PORT33CR (0xE6051021) -#define PORT34CR (0xE6051022) -#define PORT35CR (0xE6051023) - -LIST "DRAM initialization code:" - -EW RWTCSRA0, 0xA507 - -ED_AND LIFEC_SEC_SRC, 0xFFFF7FFF - -ED_AND SMSTPCR3,0xFFFF7FFF -ED_AND SRCR3, 0xFFFF7FFF -ED_AND SMSTPCR2,0xFFFBFFFF -ED_AND SRCR2, 0xFFFBFFFF -ED PLLECR, 0x00000000 - -WAIT_MASK PLLECR, 0x00000F00, 0x00000000 -WAIT_MASK FRQCRB, 0x80000000, 0x00000000 - -ED PLL0CR, 0x2D000000 -ED PLL1CR, 0x17100000 -ED FRQCRB, 0x96235880 -WAIT_MASK FRQCRB, 0x80000000, 0x00000000 - -ED FLCKCR, 0x0000000B -ED_AND SMSTPCR0, 0xFFFFFFFD - -ED_AND SRCR0, 0xFFFFFFFD -ED 0xE6001628, 0x514 -ED 0xE6001648, 0x514 -ED 0xE6001658, 0x514 -ED 0xE6001678, 0x514 - -ED DVFSCR4, 0x00092000 -ED DVFSCR5, 0x000000DC -ED PLLECR, 0x00000000 -WAIT_MASK PLLECR, 0x00000F00, 0x00000000 - -ED FRQCRA, 0x0012453C -ED FRQCRB, 0x80431350 -WAIT_MASK FRQCRB, 0x80000000, 0x00000000 -ED FRQCRD, 0x00000B0B -WAIT_MASK FRQCRD, 0x80000000, 0x00000000 - -ED PCLKCR, 0x00000003 -ED VCLKCR1, 0x0000012F -ED VCLKCR2, 0x00000119 -ED VCLKCR3, 0x00000119 -ED ZBCKCR, 0x00000002 -ED FLCKCR, 0x00000005 -ED SD0CKCR, 0x00000080 -ED SD1CKCR, 0x00000080 -ED SD2CKCR, 0x00000080 -ED FSIACKCR, 0x0000003F -ED FSIBCKCR, 0x0000003F -ED SUBCKCR, 0x00000080 -ED SPUACKCR, 0x0000000B -ED SPUVCKCR, 0x0000000B -ED MSUCKCR, 0x0000013F -ED HSICKCR, 0x00000080 -ED MFCK1CR, 0x0000003F -ED MFCK2CR, 0x0000003F -ED DSITCKCR, 0x00000107 -ED DSI0PCKCR, 0x00000313 -ED DSI1PCKCR, 0x0000130D -ED DSI0PHYCR, 0x2A800E0E -ED PLL0CR, 0x1E000000 -ED PLL0CR, 0x2D000000 -ED PLL1CR, 0x17100000 -ED PLL2CR, 0x27000080 -ED PLL3CR, 0x1D000000 -ED PLL0STPCR, 0x00080000 -ED PLL1STPCR, 0x000120C0 -ED PLL2STPCR, 0x00012000 -ED PLL3STPCR, 0x00000030 -ED PLLECR, 0x0000000B -WAIT_MASK PLLECR, 0x00000B00, 0x00000B00 - -ED DVFSCR3, 0x000120F0 -ED MPMODE, 0x00000020 -ED VREFCR, 0x0000028A -ED RMSTPCR0, 0xE4628087 -ED RMSTPCR1, 0xFFFFFFFF -ED RMSTPCR2, 0x53FFFFFF -ED RMSTPCR3, 0xFFFFFFFF -ED RMSTPCR4, 0x00800D3D -ED RMSTPCR5, 0xFFFFF3FF -ED SMSTPCR2, 0x00000000 -ED SRCR2, 0x00040000 -ED_AND PLLECR, 0xFFFFFFF7 -WAIT_MASK PLLECR, 0x00000800, 0x00000000 - -LIST "set SBSC operational" -ED HPBCTRL6, 0x00000001 -WAIT_MASK HPBCTRL6, 0x00000001, 0x00000001 - -LIST "set SBSC operating frequency" -ED FRQCRD, 0x00001414 -WAIT_MASK FRQCRD, 0x80000000, 0x00000000 -ED PLL3CR, 0x1D000000 -ED_OR PLLECR, 0x00000008 -WAIT_MASK PLLECR, 0x00000800, 0x00000800 - -LIST "enable DLL oscillation in DDRPHY" -ED_OR DLLCNT0A, 0x00000002 - -LIST "wait >= 100 ns" -ED SDGENCNTA, 0x00000005 -WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000 - -LIST "target LPDDR2 device settings" -ED SDCR0A, 0xACC90159 -ED SDCR1A, 0x00010059 -ED SDWCRC0A, 0x50874114 -ED SDWCRC1A, 0x33199B37 -ED SDWCRC2A, 0x008F2313 -ED SDWCR00A, 0x31020707 -ED SDWCR01A, 0x0017040A -ED SDWCR10A, 0x31020707 -ED SDWCR11A, 0x0017040A - -ED SDDRVCR0A, 0x055557ff - -ED SDWCR2A, 0x30000000 - -LIST "drive CKE high" -ED_OR SDPCRA, 0x00000080 -WAIT_MASK SDPCRA, 0x00000080, 0x00000080 - -LIST "wait >= 200 us" -ED SDGENCNTA, 0x00002710 -WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000 - -LIST "issue reset command to LPDDR2 device" -ED SDMRACR0A, 0x0000003F -ED SDMRA1, 0x00000000 - -LIST "wait >= 10 (or 1) us (docs inconsistent)" -ED SDGENCNTA, 0x000001F4 -WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000 - -LIST "MRW ZS initialization calibration command" -ED SDMRACR0A, 0x0000FF0A -ED SDMRA3, 0x00000000 - -LIST "wait >= 1 us" -ED SDGENCNTA, 0x00000032 -WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000 - -LIST "specify operating mode in LPDDR2" -ED SDMRACR0A, 0x00002201 -ED SDMRA1, 0x00000000 -ED SDMRACR0A, 0x00000402 -ED SDMRA1, 0x00000000 -ED SDMRACR0A, 0x00000203 -ED SDMRA1, 0x00000000 - -LIST "initialize DDR interface" -ED SDMRA2, 0x00000000 - -LIST "temperature sensor control" -ED SDMRTMPCRA, 0x88800004 -ED SDMRTMPMSKA,0x00000004 - -LIST "auto-refreshing control" -ED RTCORA, 0xA55A0032 -ED RTCORHA, 0xA55A000C -ED RTCSRA, 0xA55A2048 - -ED_OR SDCR0A, 0x00000800 -ED_OR SDCR1A, 0x00000400 - -LIST "auto ZQ calibration control" -ED ZQCCRA, 0xFFF20000 - -ED_OR DLLCNT0B, 0x00000002 -ED SDGENCNTB, 0x00000005 -WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000 - -ED SDCR0B, 0xACC90159 -ED SDCR1B, 0x00010059 -ED SDWCRC0B, 0x50874114 -ED SDWCRC1B, 0x33199B37 -ED SDWCRC2B, 0x008F2313 -ED SDWCR00B, 0x31020707 -ED SDWCR01B, 0x0017040A -ED SDWCR10B, 0x31020707 -ED SDWCR11B, 0x0017040A -ED SDDRVCR0B, 0x055557ff -ED SDWCR2B, 0x30000000 -ED_OR SDPCRB, 0x00000080 -WAIT_MASK SDPCRB, 0x00000080, 0x00000080 - -ED SDGENCNTB, 0x00002710 -WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000 -ED SDMRACR0B, 0x0000003F - -LIST "upstream u-boot writes to SDMRA1A for both SBSC 1 and 2, which does" -LIST "not seem to make a lot of sense..." -ED SDMRB1, 0x00000000 - -ED SDGENCNTB, 0x000001F4 -WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000 - -ED SDMRACR0B, 0x0000FF0A -ED SDMRB3, 0x00000000 -ED SDGENCNTB, 0x00000032 -WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000 - -ED SDMRACR0B, 0x00002201 -ED SDMRB1, 0x00000000 -ED SDMRACR0B, 0x00000402 -ED SDMRB1, 0x00000000 -ED SDMRACR0B, 0x00000203 -ED SDMRB1, 0x00000000 -ED SDMRB2, 0x00000000 -ED SDMRTMPCRB, 0x88800004 -ED SDMRTMPMSKB, 0x00000004 -ED RTCORB, 0xA55A0032 -ED RTCORHB, 0xA55A000C -ED RTCSRB, 0xA55A2048 -ED_OR SDCR0B, 0x00000800 -ED_OR SDCR1B, 0x00000400 -ED ZQCCRB, 0xFFF20000 -ED_OR SDPDCR0B, 0x00030000 -ED DPHYCNT1B, 0xA5390000 -ED DPHYCNT0B, 0x00001200 -ED DPHYCNT1B, 0x07CE0000 -ED DPHYCNT0B, 0x00001247 -WAIT_MASK DPHYCNT2B, 0xFFFFFFFF, 0x07CE0000 - -ED_AND SDPDCR0B, 0xFFFCFFFF - -ED FRQCRD, 0x00000B0B -WAIT_MASK FRQCRD, 0x80000000, 0x00000000 - -ED CPGXXCR4, 0xfffffffc - -LIST "Setup SCIF4 / workaround" -EB PORT32CR, 0x12 -EB PORT33CR, 0x22 -EB PORT34CR, 0x12 -EB PORT35CR, 0x22 - -EW 0xE6C80000, 0 -EB 0xE6C80004, 0x19 -EW 0xE6C80008, 0x0030 -EW 0xE6C80018, 0 -EW 0xE6C80030, 0x0014 - -LIST "Magic to avoid hangs and corruption on DRAM writes." - -LIST "It has been observed that the system would most often hang while" -LIST "decompressing the kernel, and if it didn't it would always write" -LIST "a corrupt image to DRAM." -LIST "This problem does not occur in u-boot, and the reason is that" -LIST "u-boot performs an additional cache invalidation after setting up" -LIST "the DRAM controller. Such an invalidation should not be necessary at" -LIST "this point, and attempts at removing parts of the routine to arrive" -LIST "at the minimal snippet of code necessary to avoid the DRAM stability" -LIST "problem yielded the following:" - -MRC p15, 0, r0, c1, c0, 0 -MCR p15, 0, r0, c1, c0, 0 diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h deleted file mode 100644 index 175ee05..0000000 --- a/arch/arm/mach-shmobile/include/mach/zboot.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ZBOOT_H -#define ZBOOT_H - -#include <mach/zboot_macros.h> - -/************************************************** - * - * board specific settings - * - **************************************************/ - -#ifdef CONFIG_MACH_KZM9G -#define MEMORY_START 0x43000000 -#include "mach/head-kzm9g.txt" -#else -#error "unsupported board." -#endif - -#endif /* ZBOOT_H */ diff --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h deleted file mode 100644 index 14fd3d5..0000000 --- a/arch/arm/mach-shmobile/include/mach/zboot_macros.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef __ZBOOT_MACRO_H -#define __ZBOOT_MACRO_H - -/* The LIST command is used to include comments in the script */ -.macro LIST comment -.endm - -/* The ED command is used to write a 32-bit word */ -.macro ED, addr, data - LDR r0, 1f - LDR r1, 2f - STR r1, [r0] - B 3f -1 : .long \addr -2 : .long \data -3 : -.endm - -/* The EW command is used to write a 16-bit word */ -.macro EW, addr, data - LDR r0, 1f - LDR r1, 2f - STRH r1, [r0] - B 3f -1 : .long \addr -2 : .long \data -3 : -.endm - -/* The EB command is used to write an 8-bit word */ -.macro EB, addr, data - LDR r0, 1f - LDR r1, 2f - STRB r1, [r0] - B 3f -1 : .long \addr -2 : .long \data -3 : -.endm - -/* The WAIT command is used to delay the execution */ -.macro WAIT, time, reg - LDR r1, 1f - LDR r0, 2f - STR r0, [r1] -10 : - LDR r0, [r1] - CMP r0, #0x00000000 - BNE 10b - NOP - B 3f -1 : .long \reg -2 : .long \time * 100 -3 : -.endm - -/* The DD command is used to read a 32-bit word */ -.macro DD, start, end - LDR r1, 1f - B 2f -1 : .long \start -2 : -.endm - -/* loop until a given value has been read (with mask) */ -.macro WAIT_MASK, addr, data, cmp - LDR r0, 2f - LDR r1, 3f - LDR r2, 4f -1: - LDR r3, [r0, #0] - AND r3, r1, r3 - CMP r2, r3 - BNE 1b - B 5f -2: .long \addr -3: .long \data -4: .long \cmp -5: -.endm - -/* read 32-bit value from addr, "or" an immediate and write back */ -.macro ED_OR, addr, data - LDR r4, 1f - LDR r5, 2f - LDR r6, [r4] - ORR r5, r6, r5 - STR r5, [r4] - B 3f -1: .long \addr -2: .long \data -3: -.endm - -/* read 32-bit value from addr, "and" an immediate and write back */ -.macro ED_AND, addr, data - LDR r4, 1f - LDR r5, 2f - LDR r6, [r4] - AND r5, r6, r5 - STR r5, [r4] - B 3f -1: .long \addr -2: .long \data -3: -.endm - -#endif /* __ZBOOT_MACRO_H */ diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c deleted file mode 100644 index fd63ae6..0000000 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * sh73a0 processor support - INTC hardware block - * - * Copyright (C) 2010 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/irqchip.h> -#include <linux/irqchip/arm-gic.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> - -#include "intc.h" -#include "irqs.h" -#include "sh73a0.h" - -enum { - UNUSED = 0, - - /* interrupt sources INTCS */ - PINTCS_PINT1, PINTCS_PINT2, - RTDMAC_0_DEI0, RTDMAC_0_DEI1, RTDMAC_0_DEI2, RTDMAC_0_DEI3, - CEU, MFI, BBIF2, VPU, TSIF1, _3DG_SGX543, _2DDMAC_2DDM0, - RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR, - KEYSC_KEY, VINT, MSIOF, - TMU0_TUNI00, TMU0_TUNI01, TMU0_TUNI02, - CMT0, TSIF0, CMT2, LMB, MSUG, MSU_MSU, MSU_MSU2, - CTI, RWDT0, ICB, PEP, ASA, JPU_JPEG, LCDC, LCRC, - RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9, - RTDMAC_3_DEI10, RTDMAC_3_DEI11, - FRC, GCU, LCDC1, CSIRX, - DSITX0_DSITX00, DSITX0_DSITX01, - SPU2_SPU0, SPU2_SPU1, FSI, - TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, - TSIF2, CMT4, MFIS2, CPORTS2R, TSG, DMASCH1, SCUW, - VIO60, VIO61, CEU21, CSI21, DSITX1_DSITX10, DSITX1_DSITX11, - DISP, DSRV, EMUX2_EMUX20I, EMUX2_EMUX21I, - MSTIF0_MST00I, MSTIF0_MST01I, MSTIF1_MST10I, MSTIF1_MST11I, - SPUV, - - /* interrupt groups INTCS */ - RTDMAC_0, RTDMAC_1, RTDMAC_2, RTDMAC_3, - DSITX0, SPU2, TMU1, MSU, -}; - -static struct intc_vect intcs_vectors[] = { - INTCS_VECT(PINTCS_PINT1, 0x0600), INTCS_VECT(PINTCS_PINT2, 0x0620), - INTCS_VECT(RTDMAC_0_DEI0, 0x0800), INTCS_VECT(RTDMAC_0_DEI1, 0x0820), - INTCS_VECT(RTDMAC_0_DEI2, 0x0840), INTCS_VECT(RTDMAC_0_DEI3, 0x0860), - INTCS_VECT(CEU, 0x0880), INTCS_VECT(MFI, 0x0900), - INTCS_VECT(BBIF2, 0x0960), INTCS_VECT(VPU, 0x0980), - INTCS_VECT(TSIF1, 0x09a0), INTCS_VECT(_3DG_SGX543, 0x09e0), - INTCS_VECT(_2DDMAC_2DDM0, 0x0a00), - INTCS_VECT(RTDMAC_1_DEI4, 0x0b80), INTCS_VECT(RTDMAC_1_DEI5, 0x0ba0), - INTCS_VECT(RTDMAC_1_DADERR, 0x0bc0), - INTCS_VECT(KEYSC_KEY, 0x0be0), INTCS_VECT(VINT, 0x0c80), - INTCS_VECT(MSIOF, 0x0d20), - INTCS_VECT(TMU0_TUNI00, 0x0e80), INTCS_VECT(TMU0_TUNI01, 0x0ea0), - INTCS_VECT(TMU0_TUNI02, 0x0ec0), - INTCS_VECT(CMT0, 0x0f00), INTCS_VECT(TSIF0, 0x0f20), - INTCS_VECT(CMT2, 0x0f40), INTCS_VECT(LMB, 0x0f60), - INTCS_VECT(MSUG, 0x0f80), - INTCS_VECT(MSU_MSU, 0x0fa0), INTCS_VECT(MSU_MSU2, 0x0fc0), - INTCS_VECT(CTI, 0x0400), INTCS_VECT(RWDT0, 0x0440), - INTCS_VECT(ICB, 0x0480), INTCS_VECT(PEP, 0x04a0), - INTCS_VECT(ASA, 0x04c0), INTCS_VECT(JPU_JPEG, 0x0560), - INTCS_VECT(LCDC, 0x0580), INTCS_VECT(LCRC, 0x05a0), - INTCS_VECT(RTDMAC_2_DEI6, 0x1300), INTCS_VECT(RTDMAC_2_DEI7, 0x1320), - INTCS_VECT(RTDMAC_2_DEI8, 0x1340), INTCS_VECT(RTDMAC_2_DEI9, 0x1360), - INTCS_VECT(RTDMAC_3_DEI10, 0x1380), INTCS_VECT(RTDMAC_3_DEI11, 0x13a0), - INTCS_VECT(FRC, 0x1700), INTCS_VECT(GCU, 0x1760), - INTCS_VECT(LCDC1, 0x1780), INTCS_VECT(CSIRX, 0x17a0), - INTCS_VECT(DSITX0_DSITX00, 0x17c0), INTCS_VECT(DSITX0_DSITX01, 0x17e0), - INTCS_VECT(SPU2_SPU0, 0x1800), INTCS_VECT(SPU2_SPU1, 0x1820), - INTCS_VECT(FSI, 0x1840), - INTCS_VECT(TMU1_TUNI10, 0x1900), INTCS_VECT(TMU1_TUNI11, 0x1920), - INTCS_VECT(TMU1_TUNI12, 0x1940), - INTCS_VECT(TSIF2, 0x1960), INTCS_VECT(CMT4, 0x1980), - INTCS_VECT(MFIS2, 0x1a00), INTCS_VECT(CPORTS2R, 0x1a20), - INTCS_VECT(TSG, 0x1ae0), INTCS_VECT(DMASCH1, 0x1b00), - INTCS_VECT(SCUW, 0x1b40), - INTCS_VECT(VIO60, 0x1b60), INTCS_VECT(VIO61, 0x1b80), - INTCS_VECT(CEU21, 0x1ba0), INTCS_VECT(CSI21, 0x1be0), - INTCS_VECT(DSITX1_DSITX10, 0x1c00), INTCS_VECT(DSITX1_DSITX11, 0x1c20), - INTCS_VECT(DISP, 0x1c40), INTCS_VECT(DSRV, 0x1c60), - INTCS_VECT(EMUX2_EMUX20I, 0x1c80), INTCS_VECT(EMUX2_EMUX21I, 0x1ca0), - INTCS_VECT(MSTIF0_MST00I, 0x1cc0), INTCS_VECT(MSTIF0_MST01I, 0x1ce0), - INTCS_VECT(MSTIF1_MST10I, 0x1d00), INTCS_VECT(MSTIF1_MST11I, 0x1d20), - INTCS_VECT(SPUV, 0x2300), -}; - -static struct intc_group intcs_groups[] __initdata = { - INTC_GROUP(RTDMAC_0, RTDMAC_0_DEI0, RTDMAC_0_DEI1, - RTDMAC_0_DEI2, RTDMAC_0_DEI3), - INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR), - INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI6, RTDMAC_2_DEI7, - RTDMAC_2_DEI8, RTDMAC_2_DEI9), - INTC_GROUP(RTDMAC_3, RTDMAC_3_DEI10, RTDMAC_3_DEI11), - INTC_GROUP(TMU1, TMU1_TUNI12, TMU1_TUNI11, TMU1_TUNI10), - INTC_GROUP(DSITX0, DSITX0_DSITX00, DSITX0_DSITX01), - INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1), - INTC_GROUP(MSU, MSU_MSU, MSU_MSU2), -}; - -static struct intc_mask_reg intcs_mask_registers[] = { - { 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */ - { 0, 0, 0, CEU, - 0, 0, 0, 0 } }, - { 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */ - { 0, 0, 0, VPU, - BBIF2, 0, 0, MFI } }, - { 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */ - { 0, 0, 0, _2DDMAC_2DDM0, - 0, ASA, PEP, ICB } }, - { 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */ - { 0, 0, 0, CTI, - JPU_JPEG, 0, LCRC, LCDC } }, - { 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */ - { KEYSC_KEY, RTDMAC_1_DADERR, RTDMAC_1_DEI5, RTDMAC_1_DEI4, - RTDMAC_0_DEI3, RTDMAC_0_DEI2, RTDMAC_0_DEI1, RTDMAC_0_DEI0 } }, - { 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */ - { 0, 0, MSIOF, 0, - _3DG_SGX543, 0, 0, 0 } }, - { 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */ - { 0, TMU0_TUNI02, TMU0_TUNI01, TMU0_TUNI00, - 0, 0, 0, 0 } }, - { 0xffd201a0, 0xffd201e0, 8, /* IMR8SA / IMCR8SA */ - { 0, 0, 0, 0, - 0, MSU_MSU, MSU_MSU2, MSUG } }, - { 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */ - { 0, RWDT0, CMT2, CMT0, - 0, 0, 0, 0 } }, - { 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */ - { 0, 0, 0, 0, - 0, TSIF1, LMB, TSIF0 } }, - { 0xffd201b0, 0xffd201f0, 8, /* IMR12SA / IMCR12SA */ - { 0, 0, 0, 0, - 0, 0, PINTCS_PINT2, PINTCS_PINT1 } }, - { 0xffd50180, 0xffd501c0, 8, /* IMR0SA3 / IMCR0SA3 */ - { RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9, - RTDMAC_3_DEI10, RTDMAC_3_DEI11, 0, 0 } }, - { 0xffd50190, 0xffd501d0, 8, /* IMR4SA3 / IMCR4SA3 */ - { FRC, 0, 0, GCU, - LCDC1, CSIRX, DSITX0_DSITX00, DSITX0_DSITX01 } }, - { 0xffd50194, 0xffd501d4, 8, /* IMR5SA3 / IMCR5SA3 */ - { SPU2_SPU0, SPU2_SPU1, FSI, 0, - 0, 0, 0, 0 } }, - { 0xffd50198, 0xffd501d8, 8, /* IMR6SA3 / IMCR6SA3 */ - { TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, 0, - TSIF2, CMT4, 0, 0 } }, - { 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */ - { MFIS2, CPORTS2R, 0, 0, - 0, 0, 0, TSG } }, - { 0xffd501a0, 0xffd501e0, 8, /* IMR8SA3 / IMCR8SA3 */ - { DMASCH1, 0, SCUW, VIO60, - VIO61, CEU21, 0, CSI21 } }, - { 0xffd501a4, 0xffd501e4, 8, /* IMR9SA3 / IMCR9SA3 */ - { DSITX1_DSITX10, DSITX1_DSITX11, DISP, DSRV, - EMUX2_EMUX20I, EMUX2_EMUX21I, MSTIF0_MST00I, MSTIF0_MST01I } }, - { 0xffd501a8, 0xffd501e8, 8, /* IMR10SA3 / IMCR10SA3 */ - { MSTIF0_MST00I, MSTIF0_MST01I, 0, 0, - 0, 0, 0, 0 } }, - { 0xffd60180, 0xffd601c0, 8, /* IMR0SA4 / IMCR0SA4 */ - { SPUV, 0, 0, 0, - 0, 0, 0, 0 } }, -}; - -/* Priority is needed for INTCA to receive the INTCS interrupt */ -static struct intc_prio_reg intcs_prio_registers[] = { - { 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, 0, _2DDMAC_2DDM0, ICB } }, - { 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU_JPEG, LCDC, 0, LCRC } }, - { 0xffd20008, 0, 16, 4, /* IPRCS */ { BBIF2, 0, 0, 0 } }, - { 0xffd2000c, 0, 16, 4, /* IPRDS */ { PINTCS_PINT1, PINTCS_PINT2, - 0, 0 } }, - { 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_0, CEU, MFI, VPU } }, - { 0xffd20014, 0, 16, 4, /* IPRFS */ { KEYSC_KEY, RTDMAC_1, - CMT2, CMT0 } }, - { 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU0_TUNI00, TMU0_TUNI01, - TMU0_TUNI02, TSIF1 } }, - { 0xffd2001c, 0, 16, 4, /* IPRHS */ { VINT, 0, 0, 0 } }, - { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, 0 } }, - { 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, _3DG_SGX543, MSUG, MSU } }, - { 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, ASA, LMB, PEP } }, - { 0xffd20030, 0, 16, 4, /* IPRMS */ { 0, 0, 0, RWDT0 } }, - { 0xffd50000, 0, 16, 4, /* IPRAS3 */ { RTDMAC_2, 0, 0, 0 } }, - { 0xffd50004, 0, 16, 4, /* IPRBS3 */ { RTDMAC_3, 0, 0, 0 } }, - { 0xffd50020, 0, 16, 4, /* IPRIS3 */ { FRC, 0, 0, 0 } }, - { 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, CSIRX, DSITX0, 0 } }, - { 0xffd50028, 0, 16, 4, /* IPRKS3 */ { SPU2, 0, FSI, 0 } }, - { 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, TSIF2 } }, - { 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, 0, 0, 0 } }, - { 0xffd50038, 0, 16, 4, /* IPROS3 */ { MFIS2, CPORTS2R, 0, 0 } }, - { 0xffd50040, 0, 16, 4, /* IPRQS3 */ { DMASCH1, 0, SCUW, VIO60 } }, - { 0xffd50044, 0, 16, 4, /* IPRRS3 */ { VIO61, CEU21, 0, CSI21 } }, - { 0xffd50048, 0, 16, 4, /* IPRSS3 */ { DSITX1_DSITX10, DSITX1_DSITX11, - DISP, DSRV } }, - { 0xffd5004c, 0, 16, 4, /* IPRTS3 */ { EMUX2_EMUX20I, EMUX2_EMUX21I, - MSTIF0_MST00I, MSTIF0_MST01I } }, - { 0xffd50050, 0, 16, 4, /* IPRUS3 */ { MSTIF1_MST10I, MSTIF1_MST11I, - 0, 0 } }, - { 0xffd60000, 0, 16, 4, /* IPRAS4 */ { SPUV, 0, 0, 0 } }, -}; - -static struct resource intcs_resources[] __initdata = { - [0] = { - .start = 0xffd20000, - .end = 0xffd201ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = 0xffd50000, - .end = 0xffd501ff, - .flags = IORESOURCE_MEM, - }, - [2] = { - .start = 0xffd60000, - .end = 0xffd601ff, - .flags = IORESOURCE_MEM, - } -}; - -static struct intc_desc intcs_desc __initdata = { - .name = "sh73a0-intcs", - .resource = intcs_resources, - .num_resources = ARRAY_SIZE(intcs_resources), - .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers, - intcs_prio_registers, NULL, NULL), -}; - -static struct irqaction sh73a0_intcs_cascade; - -static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id) -{ - unsigned int evtcodeas = ioread32((void __iomem *)dev_id); - - generic_handle_irq(intcs_evt2irq(evtcodeas)); - - return IRQ_HANDLED; -} - -#define PINTER0_PHYS 0xe69000a0 -#define PINTER1_PHYS 0xe69000a4 -#define PINTER0_VIRT IOMEM(0xe69000a0) -#define PINTER1_VIRT IOMEM(0xe69000a4) -#define PINTRR0 IOMEM(0xe69000d0) -#define PINTRR1 IOMEM(0xe69000d4) - -#define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq)) -#define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8)) -#define PINT0C_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 16)) -#define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24)) -#define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq)) - -INTC_PINT(intc_pint0, PINTER0_PHYS, 0xe69000b0, "sh73a0-pint0", \ - INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \ - INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ), \ - INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ), \ - INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \ - INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D)); - -INTC_PINT(intc_pint1, PINTER1_PHYS, 0xe69000c0, "sh73a0-pint1", \ - INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \ - INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE, \ - INTC_PINT_V_NONE, INTC_PINT_V_NONE, \ - INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E(E), \ - INTC_PINT_E(E), INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE); - -static struct irqaction sh73a0_pint0_cascade; -static struct irqaction sh73a0_pint1_cascade; - -static void pint_demux(void __iomem *rr, void __iomem *er, int base_irq) -{ - unsigned long value = ioread32(rr) & ioread32(er); - int k; - - for (k = 0; k < 32; k++) { - if (value & (1 << (31 - k))) { - generic_handle_irq(base_irq + k); - iowrite32(~(1 << (31 - k)), rr); - } - } -} - -static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id) -{ - pint_demux(PINTRR0, PINTER0_VIRT, SH73A0_PINT0_IRQ(0)); - return IRQ_HANDLED; -} - -static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id) -{ - pint_demux(PINTRR1, PINTER1_VIRT, SH73A0_PINT1_IRQ(0)); - return IRQ_HANDLED; -} - -void __init sh73a0_init_irq(void) -{ - void __iomem *gic_dist_base = IOMEM(0xf0001000); - void __iomem *gic_cpu_base = IOMEM(0xf0000100); - void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); - - gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE); - gic_init(0, 29, gic_dist_base, gic_cpu_base); - - register_intc_controller(&intcs_desc); - register_intc_controller(&intc_pint0_desc); - register_intc_controller(&intc_pint1_desc); - - /* demux using INTEVTSA */ - sh73a0_intcs_cascade.name = "INTCS cascade"; - sh73a0_intcs_cascade.handler = sh73a0_intcs_demux; - sh73a0_intcs_cascade.dev_id = intevtsa; - setup_irq(gic_spi(50), &sh73a0_intcs_cascade); - - /* PINT pins are sanely tied to the GIC as SPI */ - sh73a0_pint0_cascade.name = "PINT0 cascade"; - sh73a0_pint0_cascade.handler = sh73a0_pint0_demux; - setup_irq(gic_spi(33), &sh73a0_pint0_cascade); - - sh73a0_pint1_cascade.name = "PINT1 cascade"; - sh73a0_pint1_cascade.handler = sh73a0_pint1_demux; - setup_irq(gic_spi(34), &sh73a0_pint1_cascade); -} diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c index b0790fc..4e54512 100644 --- a/arch/arm/mach-shmobile/platsmp-apmu.c +++ b/arch/arm/mach-shmobile/platsmp-apmu.c @@ -46,7 +46,7 @@ static int __maybe_unused apmu_power_on(void __iomem *p, int bit) return 0; } -static int apmu_power_off(void __iomem *p, int bit) +static int __maybe_unused apmu_power_off(void __iomem *p, int bit) { /* request Core Standby for next WFI */ writel_relaxed(3, p + CPUNCR_OFFS(bit)); @@ -67,7 +67,7 @@ static int __maybe_unused apmu_power_off_poll(void __iomem *p, int bit) return 0; } -static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu)) +static int __maybe_unused apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu)) { void __iomem *p = apmu_cpus[cpu].iomem; diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c deleted file mode 100644 index 34608fc..0000000 --- a/arch/arm/mach-shmobile/pm-r8a7740.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * r8a7740 power management support - * - * Copyright (C) 2012 Renesas Solutions Corp. - * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/console.h> -#include <linux/io.h> -#include <linux/suspend.h> - -#include "common.h" -#include "pm-rmobile.h" - -#define SYSC_BASE IOMEM(0xe6180000) - -#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) -static int r8a7740_pd_a3sm_suspend(void) -{ - /* - * The A3SM domain contains the CPU core and therefore it should - * only be turned off if the CPU is not in use. - */ - return -EBUSY; -} - -static int r8a7740_pd_a3sp_suspend(void) -{ - /* - * Serial consoles make use of SCIF hardware located in A3SP, - * keep such power domain on if "no_console_suspend" is set. - */ - return console_suspend_enabled ? 0 : -EBUSY; -} - -static int r8a7740_pd_d4_suspend(void) -{ - /* - * The D4 domain contains the Coresight-ETM hardware block and - * therefore it should only be turned off if the debug module is - * not in use. - */ - return -EBUSY; -} - -static struct rmobile_pm_domain r8a7740_pm_domains[] = { - { - .genpd.name = "A4LC", - .base = SYSC_BASE, - .bit_shift = 1, - }, { - .genpd.name = "A4MP", - .base = SYSC_BASE, - .bit_shift = 2, - }, { - .genpd.name = "D4", - .base = SYSC_BASE, - .bit_shift = 3, - .gov = &pm_domain_always_on_gov, - .suspend = r8a7740_pd_d4_suspend, - }, { - .genpd.name = "A4R", - .base = SYSC_BASE, - .bit_shift = 5, - }, { - .genpd.name = "A3RV", - .base = SYSC_BASE, - .bit_shift = 6, - }, { - .genpd.name = "A4S", - .base = SYSC_BASE, - .bit_shift = 10, - .no_debug = true, - }, { - .genpd.name = "A3SP", - .base = SYSC_BASE, - .bit_shift = 11, - .gov = &pm_domain_always_on_gov, - .no_debug = true, - .suspend = r8a7740_pd_a3sp_suspend, - }, { - .genpd.name = "A3SM", - .base = SYSC_BASE, - .bit_shift = 12, - .gov = &pm_domain_always_on_gov, - .suspend = r8a7740_pd_a3sm_suspend, - }, { - .genpd.name = "A3SG", - .base = SYSC_BASE, - .bit_shift = 13, - }, { - .genpd.name = "A4SU", - .base = SYSC_BASE, - .bit_shift = 20, - }, -}; - -void __init r8a7740_init_pm_domains(void) -{ - rmobile_init_domains(r8a7740_pm_domains, ARRAY_SIZE(r8a7740_pm_domains)); - pm_genpd_add_subdomain_names("A4R", "A3RV"); - pm_genpd_add_subdomain_names("A4S", "A3SP"); - pm_genpd_add_subdomain_names("A4S", "A3SM"); - pm_genpd_add_subdomain_names("A4S", "A3SG"); -} -#endif /* CONFIG_PM && !CONFIG_ARCH_MULTIPLATFORM */ - -#ifdef CONFIG_SUSPEND -static int r8a7740_enter_suspend(suspend_state_t suspend_state) -{ - cpu_do_idle(); - return 0; -} - -static void r8a7740_suspend_init(void) -{ - shmobile_suspend_ops.enter = r8a7740_enter_suspend; -} -#else -static void r8a7740_suspend_init(void) {} -#endif - -void __init r8a7740_pm_init(void) -{ - r8a7740_suspend_init(); -} diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c index 44a74c4..47a862e 100644 --- a/arch/arm/mach-shmobile/pm-r8a7779.c +++ b/arch/arm/mach-shmobile/pm-r8a7779.c @@ -35,7 +35,8 @@ struct r8a7779_pm_domain { struct rcar_sysc_ch ch; }; -static inline struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d) +static inline +const struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d) { return &container_of(d, struct r8a7779_pm_domain, genpd)->ch; } @@ -83,7 +84,6 @@ static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd) { struct generic_pm_domain *genpd = &r8a7779_pd->genpd; - genpd->flags = GENPD_FLAG_PM_CLK; pm_genpd_init(genpd, NULL, false); genpd->dev_ops.active_wakeup = pd_active_wakeup; genpd->power_off = pd_power_down; diff --git a/arch/arm/mach-shmobile/pm-rcar.c b/arch/arm/mach-shmobile/pm-rcar.c index 00022ee..4092ad1 100644 --- a/arch/arm/mach-shmobile/pm-rcar.c +++ b/arch/arm/mach-shmobile/pm-rcar.c @@ -15,32 +15,58 @@ #include <asm/io.h> #include "pm-rcar.h" -/* SYSC */ -#define SYSCSR 0x00 -#define SYSCISR 0x04 -#define SYSCISCR 0x08 +/* SYSC Common */ +#define SYSCSR 0x00 /* SYSC Status Register */ +#define SYSCISR 0x04 /* Interrupt Status Register */ +#define SYSCISCR 0x08 /* Interrupt Status Clear Register */ +#define SYSCIER 0x0c /* Interrupt Enable Register */ +#define SYSCIMR 0x10 /* Interrupt Mask Register */ -#define PWRSR_OFFS 0x00 -#define PWROFFCR_OFFS 0x04 -#define PWRONCR_OFFS 0x0c -#define PWRER_OFFS 0x14 +/* SYSC Status Register */ +#define SYSCSR_PONENB 1 /* Ready for power resume requests */ +#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */ -#define SYSCSR_RETRIES 100 -#define SYSCSR_DELAY_US 1 +/* + * Power Control Register Offsets inside the register block for each domain + * Note: The "CR" registers for ARM cores exist on H1 only + * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2 + */ +#define PWRSR_OFFS 0x00 /* Power Status Register */ +#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */ +#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */ +#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */ +#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */ +#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */ + + +#define SYSCSR_RETRIES 100 +#define SYSCSR_DELAY_US 1 + +#define PWRER_RETRIES 100 +#define PWRER_DELAY_US 1 -#define SYSCISR_RETRIES 1000 -#define SYSCISR_DELAY_US 1 +#define SYSCISR_RETRIES 1000 +#define SYSCISR_DELAY_US 1 static void __iomem *rcar_sysc_base; static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */ -static int rcar_sysc_pwr_on_off(struct rcar_sysc_ch *sysc_ch, - int sr_bit, int reg_offs) +static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on) { + unsigned int sr_bit, reg_offs; int k; + if (on) { + sr_bit = SYSCSR_PONENB; + reg_offs = PWRONCR_OFFS; + } else { + sr_bit = SYSCSR_POFFENB; + reg_offs = PWROFFCR_OFFS; + } + + /* Wait until SYSC is ready to accept a power request */ for (k = 0; k < SYSCSR_RETRIES; k++) { - if (ioread32(rcar_sysc_base + SYSCSR) & (1 << sr_bit)) + if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit)) break; udelay(SYSCSR_DELAY_US); } @@ -48,27 +74,17 @@ static int rcar_sysc_pwr_on_off(struct rcar_sysc_ch *sysc_ch, if (k == SYSCSR_RETRIES) return -EAGAIN; - iowrite32(1 << sysc_ch->chan_bit, + /* Submit power shutoff or power resume request */ + iowrite32(BIT(sysc_ch->chan_bit), rcar_sysc_base + sysc_ch->chan_offs + reg_offs); return 0; } -static int rcar_sysc_pwr_off(struct rcar_sysc_ch *sysc_ch) -{ - return rcar_sysc_pwr_on_off(sysc_ch, 0, PWROFFCR_OFFS); -} - -static int rcar_sysc_pwr_on(struct rcar_sysc_ch *sysc_ch) +static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) { - return rcar_sysc_pwr_on_off(sysc_ch, 1, PWRONCR_OFFS); -} - -static int rcar_sysc_update(struct rcar_sysc_ch *sysc_ch, - int (*on_off_fn)(struct rcar_sysc_ch *)) -{ - unsigned int isr_mask = 1 << sysc_ch->isr_bit; - unsigned int chan_mask = 1 << sysc_ch->chan_bit; + unsigned int isr_mask = BIT(sysc_ch->isr_bit); + unsigned int chan_mask = BIT(sysc_ch->chan_bit); unsigned int status; unsigned long flags; int ret = 0; @@ -78,15 +94,26 @@ static int rcar_sysc_update(struct rcar_sysc_ch *sysc_ch, iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); - do { - ret = on_off_fn(sysc_ch); + /* Submit power shutoff or resume request until it was accepted */ + for (k = 0; k < PWRER_RETRIES; k++) { + ret = rcar_sysc_pwr_on_off(sysc_ch, on); if (ret) goto out; status = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRER_OFFS); - } while (status & chan_mask); + if (!(status & chan_mask)) + break; + + udelay(PWRER_DELAY_US); + } + + if (k == PWRER_RETRIES) { + ret = -EIO; + goto out; + } + /* Wait until the power shutoff or resume request has completed * */ for (k = 0; k < SYSCISR_RETRIES; k++) { if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask) break; @@ -106,22 +133,22 @@ static int rcar_sysc_update(struct rcar_sysc_ch *sysc_ch, return ret; } -int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch) +int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch) { - return rcar_sysc_update(sysc_ch, rcar_sysc_pwr_off); + return rcar_sysc_power(sysc_ch, false); } -int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch) +int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch) { - return rcar_sysc_update(sysc_ch, rcar_sysc_pwr_on); + return rcar_sysc_power(sysc_ch, true); } -bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch) +bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch) { unsigned int st; st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS); - if (st & (1 << sysc_ch->chan_bit)) + if (st & BIT(sysc_ch->chan_bit)) return true; return false; diff --git a/arch/arm/mach-shmobile/pm-rcar.h b/arch/arm/mach-shmobile/pm-rcar.h index ef3a1ef..1b901db4 100644 --- a/arch/arm/mach-shmobile/pm-rcar.h +++ b/arch/arm/mach-shmobile/pm-rcar.h @@ -2,14 +2,14 @@ #define PM_RCAR_H struct rcar_sysc_ch { - unsigned long chan_offs; - unsigned int chan_bit; - unsigned int isr_bit; + u16 chan_offs; + u8 chan_bit; + u8 isr_bit; }; -int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch); -int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch); -bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch); +int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch); +int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch); +bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch); void __iomem *rcar_sysc_init(phys_addr_t base); #endif /* PM_RCAR_H */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index 9501820..a5b96b9 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -34,6 +34,12 @@ #define PSTR_RETRIES 100 #define PSTR_DELAY_US 10 +static inline +struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) +{ + return container_of(d, struct rmobile_pm_domain, genpd); +} + static int rmobile_pd_power_down(struct generic_pm_domain *genpd) { struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); @@ -42,7 +48,7 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) if (rmobile_pd->bit_shift == ~0) return -EBUSY; - mask = 1 << rmobile_pd->bit_shift; + mask = BIT(rmobile_pd->bit_shift); if (rmobile_pd->suspend) { int ret = rmobile_pd->suspend(); @@ -79,7 +85,7 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, if (rmobile_pd->bit_shift == ~0) return 0; - mask = 1 << rmobile_pd->bit_shift; + mask = BIT(rmobile_pd->bit_shift); if (__raw_readl(rmobile_pd->base + PSTR) & mask) goto out; @@ -163,43 +169,6 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) __rmobile_pd_power_up(rmobile_pd, false); } -#ifdef CONFIG_ARCH_SHMOBILE_LEGACY - -void rmobile_init_domains(struct rmobile_pm_domain domains[], int num) -{ - int j; - - for (j = 0; j < num; j++) - rmobile_init_pm_domain(&domains[j]); -} - -void rmobile_add_device_to_domain_td(const char *domain_name, - struct platform_device *pdev, - struct gpd_timing_data *td) -{ - struct device *dev = &pdev->dev; - - __pm_genpd_name_add_device(domain_name, dev, td); -} - -void rmobile_add_devices_to_domains(struct pm_domain_device data[], - int size) -{ - struct gpd_timing_data latencies = { - .stop_latency_ns = DEFAULT_DEV_LATENCY_NS, - .start_latency_ns = DEFAULT_DEV_LATENCY_NS, - .save_state_latency_ns = DEFAULT_DEV_LATENCY_NS, - .restore_state_latency_ns = DEFAULT_DEV_LATENCY_NS, - }; - int j; - - for (j = 0; j < size; j++) - rmobile_add_device_to_domain_td(data[j].domain_name, - data[j].pdev, &latencies); -} - -#else /* !CONFIG_ARCH_SHMOBILE_LEGACY */ - static int rmobile_pd_suspend_busy(void) { /* @@ -430,5 +399,3 @@ static int __init rmobile_init_pm_domains(void) } core_initcall(rmobile_init_pm_domains); - -#endif /* !CONFIG_ARCH_SHMOBILE_LEGACY */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h index 5321978..30a4a42 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.h +++ b/arch/arm/mach-shmobile/pm-rmobile.h @@ -26,39 +26,9 @@ struct rmobile_pm_domain { bool no_debug; }; -static inline -struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct rmobile_pm_domain, genpd); -} - struct pm_domain_device { const char *domain_name; struct platform_device *pdev; }; -#if defined(CONFIG_PM_RMOBILE) && defined(CONFIG_ARCH_SHMOBILE_LEGACY) -extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num); -extern void rmobile_add_device_to_domain_td(const char *domain_name, - struct platform_device *pdev, - struct gpd_timing_data *td); - -static inline void rmobile_add_device_to_domain(const char *domain_name, - struct platform_device *pdev) -{ - rmobile_add_device_to_domain_td(domain_name, pdev, NULL); -} - -extern void rmobile_add_devices_to_domains(struct pm_domain_device data[], - int size); -#else - -#define rmobile_init_domains(domains, num) do { } while (0) -#define rmobile_add_device_to_domain_td(name, pdev, td) do { } while (0) -#define rmobile_add_device_to_domain(name, pdev) do { } while (0) - -static inline void rmobile_add_devices_to_domains(struct pm_domain_device d[], - int size) {} -#endif /* CONFIG_PM_RMOBILE */ - #endif /* PM_RMOBILE_H */ diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c deleted file mode 100644 index a7e4668..0000000 --- a/arch/arm/mach-shmobile/pm-sh73a0.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * sh73a0 Power management support - * - * Copyright (C) 2012 Bastian Hecht <hechtb+renesas@gmail.com> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include <linux/suspend.h> -#include "common.h" - -#ifdef CONFIG_SUSPEND -static int sh73a0_enter_suspend(suspend_state_t suspend_state) -{ - cpu_do_idle(); - return 0; -} - -static void sh73a0_suspend_init(void) -{ - shmobile_suspend_ops.enter = sh73a0_enter_suspend; -} -#else -static void sh73a0_suspend_init(void) {} -#endif - -void __init sh73a0_pm_init(void) -{ - sh73a0_suspend_init(); -} diff --git a/arch/arm/mach-shmobile/r8a7740.h b/arch/arm/mach-shmobile/r8a7740.h deleted file mode 100644 index ca7805a..0000000 --- a/arch/arm/mach-shmobile/r8a7740.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 Renesas Solutions Corp. - * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - */ - -#ifndef __ASM_R8A7740_H__ -#define __ASM_R8A7740_H__ - -/* - * MD_CKx pin - */ -#define MD_CK2 (1 << 2) -#define MD_CK1 (1 << 1) -#define MD_CK0 (1 << 0) - -/* DMA slave IDs */ -enum { - SHDMA_SLAVE_INVALID, - SHDMA_SLAVE_SDHI0_RX, - SHDMA_SLAVE_SDHI0_TX, - SHDMA_SLAVE_SDHI1_RX, - SHDMA_SLAVE_SDHI1_TX, - SHDMA_SLAVE_SDHI2_RX, - SHDMA_SLAVE_SDHI2_TX, - SHDMA_SLAVE_FSIA_RX, - SHDMA_SLAVE_FSIA_TX, - SHDMA_SLAVE_FSIB_TX, - SHDMA_SLAVE_USBHS_TX, - SHDMA_SLAVE_USBHS_RX, - SHDMA_SLAVE_MMCIF_TX, - SHDMA_SLAVE_MMCIF_RX, -}; - -extern void r8a7740_meram_workaround(void); -extern void r8a7740_init_irq_of(void); -extern void r8a7740_map_io(void); -extern void r8a7740_add_early_devices(void); -extern void r8a7740_add_standard_devices(void); -extern void r8a7740_clock_init(u8 md_ck); -extern void r8a7740_pinmux_init(void); -extern void r8a7740_pm_init(void); - -#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) -extern void __init r8a7740_init_pm_domains(void); -#else -static inline void r8a7740_init_pm_domains(void) {} -#endif /* CONFIG_PM && !CONFIG_ARCH_MULTIPLATFORM */ - -#endif /* __ASM_R8A7740_H__ */ diff --git a/arch/arm/mach-shmobile/setup-r7s72100.c b/arch/arm/mach-shmobile/setup-r7s72100.c index 1711747..d46639f 100644 --- a/arch/arm/mach-shmobile/setup-r7s72100.c +++ b/arch/arm/mach-shmobile/setup-r7s72100.c @@ -20,7 +20,7 @@ #include "common.h" -static const char *r7s72100_boards_compat_dt[] __initdata = { +static const char *const r7s72100_boards_compat_dt[] __initconst = { "renesas,r7s72100", NULL, }; diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c index 446cee6..20173c4 100644 --- a/arch/arm/mach-shmobile/setup-r8a73a4.c +++ b/arch/arm/mach-shmobile/setup-r8a73a4.c @@ -20,7 +20,7 @@ #include "common.h" -static const char *r8a73a4_boards_compat_dt[] __initdata = { +static const char *const r8a73a4_boards_compat_dt[] __initconst = { "renesas,r8a73a4", NULL, }; diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 00291cc..0c8f80c 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -13,31 +13,19 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> #include <linux/irqchip.h> #include <linux/irqchip/arm-gic.h> -#include <linux/platform_data/irq-renesas-intc-irqpin.h> -#include <linux/platform_device.h> #include <linux/of_platform.h> -#include <linux/serial_sci.h> -#include <linux/sh_dma.h> -#include <linux/sh_timer.h> -#include <linux/platform_data/sh_ipmmu.h> -#include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> #include <asm/hardware/cache-l2x0.h> #include "common.h" -#include "dma-register.h" -#include "irqs.h" -#include "pm-rmobile.h" -#include "r8a7740.h" static struct map_desc r8a7740_io_desc[] __initdata = { /* @@ -64,613 +52,12 @@ static struct map_desc r8a7740_io_desc[] __initdata = { #endif }; -void __init r8a7740_map_io(void) +static void __init r8a7740_map_io(void) { debug_ll_io_init(); iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc)); } -/* PFC */ -static const struct resource pfc_resources[] = { - DEFINE_RES_MEM(0xe6050000, 0x8000), - DEFINE_RES_MEM(0xe605800c, 0x0020), -}; - -void __init r8a7740_pinmux_init(void) -{ - platform_device_register_simple("pfc-r8a7740", -1, pfc_resources, - ARRAY_SIZE(pfc_resources)); -} - -static struct renesas_intc_irqpin_config irqpin0_platform_data = { - .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */ -}; - -static struct resource irqpin0_resources[] = { - DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */ - DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */ - DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */ - DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */ - DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ0 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ1 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ2 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ3 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ4 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ5 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ6 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ7 */ -}; - -static struct platform_device irqpin0_device = { - .name = "renesas_intc_irqpin", - .id = 0, - .resource = irqpin0_resources, - .num_resources = ARRAY_SIZE(irqpin0_resources), - .dev = { - .platform_data = &irqpin0_platform_data, - }, -}; - -static struct renesas_intc_irqpin_config irqpin1_platform_data = { - .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */ -}; - -static struct resource irqpin1_resources[] = { - DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */ - DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */ - DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */ - DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */ - DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ8 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ9 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ10 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ11 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ12 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ13 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ14 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ15 */ -}; - -static struct platform_device irqpin1_device = { - .name = "renesas_intc_irqpin", - .id = 1, - .resource = irqpin1_resources, - .num_resources = ARRAY_SIZE(irqpin1_resources), - .dev = { - .platform_data = &irqpin1_platform_data, - }, -}; - -static struct renesas_intc_irqpin_config irqpin2_platform_data = { - .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */ -}; - -static struct resource irqpin2_resources[] = { - DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */ - DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI30A */ - DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ30A */ - DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK30A */ - DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR30A */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ16 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ17 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ18 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ19 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ20 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ21 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ22 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ23 */ -}; - -static struct platform_device irqpin2_device = { - .name = "renesas_intc_irqpin", - .id = 2, - .resource = irqpin2_resources, - .num_resources = ARRAY_SIZE(irqpin2_resources), - .dev = { - .platform_data = &irqpin2_platform_data, - }, -}; - -static struct renesas_intc_irqpin_config irqpin3_platform_data = { - .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */ -}; - -static struct resource irqpin3_resources[] = { - DEFINE_RES_MEM(0xe690000c, 4), /* ICR3A */ - DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */ - DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */ - DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */ - DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ24 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ25 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ26 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ27 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ28 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ29 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ30 */ - DEFINE_RES_IRQ(gic_spi(149)), /* IRQ31 */ -}; - -static struct platform_device irqpin3_device = { - .name = "renesas_intc_irqpin", - .id = 3, - .resource = irqpin3_resources, - .num_resources = ARRAY_SIZE(irqpin3_resources), - .dev = { - .platform_data = &irqpin3_platform_data, - }, -}; - -/* SCIF */ -#define R8A7740_SCIF(scif_type, index, baseaddr, irq) \ -static struct plat_sci_port scif##index##_platform_data = { \ - .type = scif_type, \ - .flags = UPF_BOOT_AUTOCONF, \ - .scscr = SCSCR_RE | SCSCR_TE, \ -}; \ - \ -static struct resource scif##index##_resources[] = { \ - DEFINE_RES_MEM(baseaddr, 0x100), \ - DEFINE_RES_IRQ(irq), \ -}; \ - \ -static struct platform_device scif##index##_device = { \ - .name = "sh-sci", \ - .id = index, \ - .resource = scif##index##_resources, \ - .num_resources = ARRAY_SIZE(scif##index##_resources), \ - .dev = { \ - .platform_data = &scif##index##_platform_data, \ - }, \ -} - -R8A7740_SCIF(PORT_SCIFA, 0, 0xe6c40000, gic_spi(100)); -R8A7740_SCIF(PORT_SCIFA, 1, 0xe6c50000, gic_spi(101)); -R8A7740_SCIF(PORT_SCIFA, 2, 0xe6c60000, gic_spi(102)); -R8A7740_SCIF(PORT_SCIFA, 3, 0xe6c70000, gic_spi(103)); -R8A7740_SCIF(PORT_SCIFA, 4, 0xe6c80000, gic_spi(104)); -R8A7740_SCIF(PORT_SCIFA, 5, 0xe6cb0000, gic_spi(105)); -R8A7740_SCIF(PORT_SCIFA, 6, 0xe6cc0000, gic_spi(106)); -R8A7740_SCIF(PORT_SCIFA, 7, 0xe6cd0000, gic_spi(107)); -R8A7740_SCIF(PORT_SCIFB, 8, 0xe6c30000, gic_spi(108)); - -/* CMT */ -static struct sh_timer_config cmt1_platform_data = { - .channels_mask = 0x3f, -}; - -static struct resource cmt1_resources[] = { - DEFINE_RES_MEM(0xe6138000, 0x170), - DEFINE_RES_IRQ(gic_spi(58)), -}; - -static struct platform_device cmt1_device = { - .name = "sh-cmt-48", - .id = 1, - .dev = { - .platform_data = &cmt1_platform_data, - }, - .resource = cmt1_resources, - .num_resources = ARRAY_SIZE(cmt1_resources), -}; - -/* TMU */ -static struct sh_timer_config tmu0_platform_data = { - .channels_mask = 7, -}; - -static struct resource tmu0_resources[] = { - DEFINE_RES_MEM(0xfff80000, 0x2c), - DEFINE_RES_IRQ(gic_spi(198)), - DEFINE_RES_IRQ(gic_spi(199)), - DEFINE_RES_IRQ(gic_spi(200)), -}; - -static struct platform_device tmu0_device = { - .name = "sh-tmu", - .id = 0, - .dev = { - .platform_data = &tmu0_platform_data, - }, - .resource = tmu0_resources, - .num_resources = ARRAY_SIZE(tmu0_resources), -}; - -/* IPMMUI (an IPMMU module for ICB/LMB) */ -static struct resource ipmmu_resources[] = { - [0] = { - .name = "IPMMUI", - .start = 0xfe951000, - .end = 0xfe9510ff, - .flags = IORESOURCE_MEM, - }, -}; - -static const char * const ipmmu_dev_names[] = { - "sh_mobile_lcdc_fb.0", - "sh_mobile_lcdc_fb.1", - "sh_mobile_ceu.0", -}; - -static struct shmobile_ipmmu_platform_data ipmmu_platform_data = { - .dev_names = ipmmu_dev_names, - .num_dev_names = ARRAY_SIZE(ipmmu_dev_names), -}; - -static struct platform_device ipmmu_device = { - .name = "ipmmu", - .id = -1, - .dev = { - .platform_data = &ipmmu_platform_data, - }, - .resource = ipmmu_resources, - .num_resources = ARRAY_SIZE(ipmmu_resources), -}; - -static struct platform_device *r8a7740_early_devices[] __initdata = { - &scif0_device, - &scif1_device, - &scif2_device, - &scif3_device, - &scif4_device, - &scif5_device, - &scif6_device, - &scif7_device, - &scif8_device, - &irqpin0_device, - &irqpin1_device, - &irqpin2_device, - &irqpin3_device, - &tmu0_device, - &ipmmu_device, - &cmt1_device, -}; - -/* DMA */ -static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = { - { - .slave_id = SHDMA_SLAVE_SDHI0_TX, - .addr = 0xe6850030, - .chcr = CHCR_TX(XMIT_SZ_16BIT), - .mid_rid = 0xc1, - }, { - .slave_id = SHDMA_SLAVE_SDHI0_RX, - .addr = 0xe6850030, - .chcr = CHCR_RX(XMIT_SZ_16BIT), - .mid_rid = 0xc2, - }, { - .slave_id = SHDMA_SLAVE_SDHI1_TX, - .addr = 0xe6860030, - .chcr = CHCR_TX(XMIT_SZ_16BIT), - .mid_rid = 0xc9, - }, { - .slave_id = SHDMA_SLAVE_SDHI1_RX, - .addr = 0xe6860030, - .chcr = CHCR_RX(XMIT_SZ_16BIT), - .mid_rid = 0xca, - }, { - .slave_id = SHDMA_SLAVE_SDHI2_TX, - .addr = 0xe6870030, - .chcr = CHCR_TX(XMIT_SZ_16BIT), - .mid_rid = 0xcd, - }, { - .slave_id = SHDMA_SLAVE_SDHI2_RX, - .addr = 0xe6870030, - .chcr = CHCR_RX(XMIT_SZ_16BIT), - .mid_rid = 0xce, - }, { - .slave_id = SHDMA_SLAVE_FSIA_TX, - .addr = 0xfe1f0024, - .chcr = CHCR_TX(XMIT_SZ_32BIT), - .mid_rid = 0xb1, - }, { - .slave_id = SHDMA_SLAVE_FSIA_RX, - .addr = 0xfe1f0020, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0xb2, - }, { - .slave_id = SHDMA_SLAVE_FSIB_TX, - .addr = 0xfe1f0064, - .chcr = CHCR_TX(XMIT_SZ_32BIT), - .mid_rid = 0xb5, - }, { - .slave_id = SHDMA_SLAVE_MMCIF_TX, - .addr = 0xe6bd0034, - .chcr = CHCR_TX(XMIT_SZ_32BIT), - .mid_rid = 0xd1, - }, { - .slave_id = SHDMA_SLAVE_MMCIF_RX, - .addr = 0xe6bd0034, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0xd2, - }, -}; - -#define DMA_CHANNEL(a, b, c) \ -{ \ - .offset = a, \ - .dmars = b, \ - .dmars_bit = c, \ - .chclr_offset = (0x220 - 0x20) + a \ -} - -static const struct sh_dmae_channel r8a7740_dmae_channels[] = { - DMA_CHANNEL(0x00, 0, 0), - DMA_CHANNEL(0x10, 0, 8), - DMA_CHANNEL(0x20, 4, 0), - DMA_CHANNEL(0x30, 4, 8), - DMA_CHANNEL(0x50, 8, 0), - DMA_CHANNEL(0x60, 8, 8), -}; - -static struct sh_dmae_pdata dma_platform_data = { - .slave = r8a7740_dmae_slaves, - .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves), - .channel = r8a7740_dmae_channels, - .channel_num = ARRAY_SIZE(r8a7740_dmae_channels), - .ts_low_shift = TS_LOW_SHIFT, - .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, - .ts_high_shift = TS_HI_SHIFT, - .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, - .ts_shift = dma_ts_shift, - .ts_shift_num = ARRAY_SIZE(dma_ts_shift), - .dmaor_init = DMAOR_DME, - .chclr_present = 1, -}; - -/* Resource order important! */ -static struct resource r8a7740_dmae0_resources[] = { - { - /* Channel registers and DMAOR */ - .start = 0xfe008020, - .end = 0xfe00828f, - .flags = IORESOURCE_MEM, - }, - { - /* DMARSx */ - .start = 0xfe009000, - .end = 0xfe00900b, - .flags = IORESOURCE_MEM, - }, - { - .name = "error_irq", - .start = gic_spi(34), - .end = gic_spi(34), - .flags = IORESOURCE_IRQ, - }, - { - /* IRQ for channels 0-5 */ - .start = gic_spi(28), - .end = gic_spi(33), - .flags = IORESOURCE_IRQ, - }, -}; - -/* Resource order important! */ -static struct resource r8a7740_dmae1_resources[] = { - { - /* Channel registers and DMAOR */ - .start = 0xfe018020, - .end = 0xfe01828f, - .flags = IORESOURCE_MEM, - }, - { - /* DMARSx */ - .start = 0xfe019000, - .end = 0xfe01900b, - .flags = IORESOURCE_MEM, - }, - { - .name = "error_irq", - .start = gic_spi(41), - .end = gic_spi(41), - .flags = IORESOURCE_IRQ, - }, - { - /* IRQ for channels 0-5 */ - .start = gic_spi(35), - .end = gic_spi(40), - .flags = IORESOURCE_IRQ, - }, -}; - -/* Resource order important! */ -static struct resource r8a7740_dmae2_resources[] = { - { - /* Channel registers and DMAOR */ - .start = 0xfe028020, - .end = 0xfe02828f, - .flags = IORESOURCE_MEM, - }, - { - /* DMARSx */ - .start = 0xfe029000, - .end = 0xfe02900b, - .flags = IORESOURCE_MEM, - }, - { - .name = "error_irq", - .start = gic_spi(48), - .end = gic_spi(48), - .flags = IORESOURCE_IRQ, - }, - { - /* IRQ for channels 0-5 */ - .start = gic_spi(42), - .end = gic_spi(47), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device dma0_device = { - .name = "sh-dma-engine", - .id = 0, - .resource = r8a7740_dmae0_resources, - .num_resources = ARRAY_SIZE(r8a7740_dmae0_resources), - .dev = { - .platform_data = &dma_platform_data, - }, -}; - -static struct platform_device dma1_device = { - .name = "sh-dma-engine", - .id = 1, - .resource = r8a7740_dmae1_resources, - .num_resources = ARRAY_SIZE(r8a7740_dmae1_resources), - .dev = { - .platform_data = &dma_platform_data, - }, -}; - -static struct platform_device dma2_device = { - .name = "sh-dma-engine", - .id = 2, - .resource = r8a7740_dmae2_resources, - .num_resources = ARRAY_SIZE(r8a7740_dmae2_resources), - .dev = { - .platform_data = &dma_platform_data, - }, -}; - -/* USB-DMAC */ -static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = { - { - .offset = 0, - }, { - .offset = 0x20, - }, -}; - -static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = { - { - .slave_id = SHDMA_SLAVE_USBHS_TX, - .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), - }, { - .slave_id = SHDMA_SLAVE_USBHS_RX, - .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), - }, -}; - -static struct sh_dmae_pdata usb_dma_platform_data = { - .slave = r8a7740_usb_dma_slaves, - .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves), - .channel = r8a7740_usb_dma_channels, - .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels), - .ts_low_shift = USBTS_LOW_SHIFT, - .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT, - .ts_high_shift = USBTS_HI_SHIFT, - .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT, - .ts_shift = dma_usbts_shift, - .ts_shift_num = ARRAY_SIZE(dma_usbts_shift), - .dmaor_init = DMAOR_DME, - .chcr_offset = 0x14, - .chcr_ie_bit = 1 << 5, - .dmaor_is_32bit = 1, - .needs_tend_set = 1, - .no_dmars = 1, - .slave_only = 1, -}; - -static struct resource r8a7740_usb_dma_resources[] = { - { - /* Channel registers and DMAOR */ - .start = 0xe68a0020, - .end = 0xe68a0064 - 1, - .flags = IORESOURCE_MEM, - }, - { - /* VCR/SWR/DMICR */ - .start = 0xe68a0000, - .end = 0xe68a0014 - 1, - .flags = IORESOURCE_MEM, - }, - { - /* IRQ for channels */ - .start = gic_spi(49), - .end = gic_spi(49), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device usb_dma_device = { - .name = "sh-dma-engine", - .id = 3, - .resource = r8a7740_usb_dma_resources, - .num_resources = ARRAY_SIZE(r8a7740_usb_dma_resources), - .dev = { - .platform_data = &usb_dma_platform_data, - }, -}; - -/* I2C */ -static struct resource i2c0_resources[] = { - [0] = { - .name = "IIC0", - .start = 0xfff20000, - .end = 0xfff20425 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(201), - .end = gic_spi(204), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource i2c1_resources[] = { - [0] = { - .name = "IIC1", - .start = 0xe6c20000, - .end = 0xe6c20425 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = gic_spi(70), /* IIC1_ALI1 */ - .end = gic_spi(73), /* IIC1_DTEI1 */ - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device i2c0_device = { - .name = "i2c-sh_mobile", - .id = 0, - .resource = i2c0_resources, - .num_resources = ARRAY_SIZE(i2c0_resources), -}; - -static struct platform_device i2c1_device = { - .name = "i2c-sh_mobile", - .id = 1, - .resource = i2c1_resources, - .num_resources = ARRAY_SIZE(i2c1_resources), -}; - -static struct resource pmu_resources[] = { - [0] = { - .start = gic_spi(83), - .end = gic_spi(83), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pmu_device = { - .name = "armv7-pmu", - .id = -1, - .num_resources = ARRAY_SIZE(pmu_resources), - .resource = pmu_resources, -}; - -static struct platform_device *r8a7740_late_devices[] __initdata = { - &i2c0_device, - &i2c1_device, - &dma0_device, - &dma1_device, - &dma2_device, - &usb_dma_device, - &pmu_device, -}; - /* * r8a7740 chip has lasting errata on MERAM buffer. * this is work-around for it. @@ -678,7 +65,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = { * "Media RAM (MERAM)" on r8a7740 documentation */ #define MEBUFCNTR 0xFE950098 -void __init r8a7740_meram_workaround(void) +static void __init r8a7740_meram_workaround(void) { void __iomem *reg; @@ -689,70 +76,13 @@ void __init r8a7740_meram_workaround(void) } } -void __init r8a7740_add_standard_devices(void) -{ - static struct pm_domain_device domain_devices[] __initdata = { - { "A4R", &tmu0_device }, - { "A4R", &i2c0_device }, - { "A4S", &irqpin0_device }, - { "A4S", &irqpin1_device }, - { "A4S", &irqpin2_device }, - { "A4S", &irqpin3_device }, - { "A3SP", &scif0_device }, - { "A3SP", &scif1_device }, - { "A3SP", &scif2_device }, - { "A3SP", &scif3_device }, - { "A3SP", &scif4_device }, - { "A3SP", &scif5_device }, - { "A3SP", &scif6_device }, - { "A3SP", &scif7_device }, - { "A3SP", &scif8_device }, - { "A3SP", &i2c1_device }, - { "A3SP", &ipmmu_device }, - { "A3SP", &dma0_device }, - { "A3SP", &dma1_device }, - { "A3SP", &dma2_device }, - { "A3SP", &usb_dma_device }, - }; - - r8a7740_init_pm_domains(); - - /* add devices */ - platform_add_devices(r8a7740_early_devices, - ARRAY_SIZE(r8a7740_early_devices)); - platform_add_devices(r8a7740_late_devices, - ARRAY_SIZE(r8a7740_late_devices)); - - /* add devices to PM domain */ - rmobile_add_devices_to_domains(domain_devices, - ARRAY_SIZE(domain_devices)); -} - -void __init r8a7740_add_early_devices(void) -{ - early_platform_add_devices(r8a7740_early_devices, - ARRAY_SIZE(r8a7740_early_devices)); - - /* setup early console here as well */ - shmobile_setup_console(); -} - -#ifdef CONFIG_USE_OF - -void __init r8a7740_init_irq_of(void) +static void __init r8a7740_init_irq_of(void) { void __iomem *intc_prio_base = ioremap_nocache(0xe6900010, 0x10); void __iomem *intc_msk_base = ioremap_nocache(0xe6900040, 0x10); void __iomem *pfc_inta_ctrl = ioremap_nocache(0xe605807c, 0x4); -#ifdef CONFIG_ARCH_SHMOBILE_LEGACY - void __iomem *gic_dist_base = ioremap_nocache(0xc2800000, 0x1000); - void __iomem *gic_cpu_base = ioremap_nocache(0xc2000000, 0x1000); - - gic_init(0, 29, gic_dist_base, gic_cpu_base); -#else irqchip_init(); -#endif /* route signals to GIC */ iowrite32(0x0, pfc_inta_ctrl); @@ -787,7 +117,7 @@ static void __init r8a7740_generic_init(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static const char *r8a7740_boards_compat_dt[] __initdata = { +static const char *const r8a7740_boards_compat_dt[] __initconst = { "renesas,r8a7740", NULL, }; @@ -800,5 +130,3 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)") .init_late = shmobile_init_late, .dt_compat = r8a7740_boards_compat_dt, MACHINE_END - -#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index c49aa09..b9116c8 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c @@ -615,7 +615,7 @@ void __init r8a7778_init_irq_dt(void) iounmap(base); } -static const char *r8a7778_compat_dt[] __initdata = { +static const char *const r8a7778_compat_dt[] __initconst = { "renesas,r8a7778", NULL, }; diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index c18d85a..7ca8919 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -102,7 +102,7 @@ static void __init r8a7779_init_time(void) clocksource_of_init(); } -static const char *r8a7779_compat_dt[] __initdata = { +static const char *const r8a7779_compat_dt[] __initconst = { "renesas,r8a7779", NULL, }; diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c index ef8eb3a..3b8dbaf 100644 --- a/arch/arm/mach-shmobile/setup-r8a7791.c +++ b/arch/arm/mach-shmobile/setup-r8a7791.c @@ -23,7 +23,7 @@ #include "r8a7791.h" #include "rcar-gen2.h" -static const char *r8a7791_boards_compat_dt[] __initdata = { +static const char *const r8a7791_boards_compat_dt[] __initconst = { "renesas,r8a7791", NULL, }; diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 5d13595..aa33392 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -128,9 +128,7 @@ void __init rcar_gen2_timer_init(void) #endif /* CONFIG_ARM_ARCH_TIMER */ rcar_gen2_clocks_init(mode); -#ifdef CONFIG_ARCH_SHMOBILE_MULTI clocksource_of_init(); -#endif } struct memory_reserve_config { diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index fb2ab75..99a2004 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -18,28 +18,17 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/platform_device.h> #include <linux/of_platform.h> #include <linux/delay.h> #include <linux/input.h> -#include <linux/i2c/i2c-sh_mobile.h> #include <linux/io.h> -#include <linux/serial_sci.h> -#include <linux/sh_dma.h> -#include <linux/sh_timer.h> -#include <linux/platform_data/sh_ipmmu.h> -#include <linux/platform_data/irq-renesas-intc-irqpin.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> #include "common.h" -#include "dma-register.h" -#include "intc.h" -#include "irqs.h" #include "sh73a0.h" static struct map_desc sh73a0_io_desc[] __initdata = { @@ -54,737 +43,12 @@ static struct map_desc sh73a0_io_desc[] __initdata = { }, }; -void __init sh73a0_map_io(void) +static void __init sh73a0_map_io(void) { debug_ll_io_init(); iotable_init(sh73a0_io_desc, ARRAY_SIZE(sh73a0_io_desc)); } -/* PFC */ -static struct resource pfc_resources[] __initdata = { - DEFINE_RES_MEM(0xe6050000, 0x8000), - DEFINE_RES_MEM(0xe605801c, 0x000c), -}; - -void __init sh73a0_pinmux_init(void) -{ - platform_device_register_simple("pfc-sh73a0", -1, pfc_resources, - ARRAY_SIZE(pfc_resources)); -} - -/* SCIF */ -#define SH73A0_SCIF(scif_type, index, baseaddr, irq) \ -static struct plat_sci_port scif##index##_platform_data = { \ - .type = scif_type, \ - .flags = UPF_BOOT_AUTOCONF, \ - .scscr = SCSCR_RE | SCSCR_TE, \ -}; \ - \ -static struct resource scif##index##_resources[] = { \ - DEFINE_RES_MEM(baseaddr, 0x100), \ - DEFINE_RES_IRQ(irq), \ -}; \ - \ -static struct platform_device scif##index##_device = { \ - .name = "sh-sci", \ - .id = index, \ - .resource = scif##index##_resources, \ - .num_resources = ARRAY_SIZE(scif##index##_resources), \ - .dev = { \ - .platform_data = &scif##index##_platform_data, \ - }, \ -} - -SH73A0_SCIF(PORT_SCIFA, 0, 0xe6c40000, gic_spi(72)); -SH73A0_SCIF(PORT_SCIFA, 1, 0xe6c50000, gic_spi(73)); -SH73A0_SCIF(PORT_SCIFA, 2, 0xe6c60000, gic_spi(74)); -SH73A0_SCIF(PORT_SCIFA, 3, 0xe6c70000, gic_spi(75)); -SH73A0_SCIF(PORT_SCIFA, 4, 0xe6c80000, gic_spi(78)); -SH73A0_SCIF(PORT_SCIFA, 5, 0xe6cb0000, gic_spi(79)); -SH73A0_SCIF(PORT_SCIFA, 6, 0xe6cc0000, gic_spi(156)); -SH73A0_SCIF(PORT_SCIFA, 7, 0xe6cd0000, gic_spi(143)); -SH73A0_SCIF(PORT_SCIFB, 8, 0xe6c30000, gic_spi(80)); - -static struct sh_timer_config cmt1_platform_data = { - .channels_mask = 0x3f, -}; - -static struct resource cmt1_resources[] = { - DEFINE_RES_MEM(0xe6138000, 0x200), - DEFINE_RES_IRQ(gic_spi(65)), -}; - -static struct platform_device cmt1_device = { - .name = "sh-cmt-48", - .id = 1, - .dev = { - .platform_data = &cmt1_platform_data, - }, - .resource = cmt1_resources, - .num_resources = ARRAY_SIZE(cmt1_resources), -}; - -/* TMU */ -static struct sh_timer_config tmu0_platform_data = { - .channels_mask = 7, -}; - -static struct resource tmu0_resources[] = { - DEFINE_RES_MEM(0xfff60000, 0x2c), - DEFINE_RES_IRQ(intcs_evt2irq(0xe80)), - DEFINE_RES_IRQ(intcs_evt2irq(0xea0)), - DEFINE_RES_IRQ(intcs_evt2irq(0xec0)), -}; - -static struct platform_device tmu0_device = { - .name = "sh-tmu", - .id = 0, - .dev = { - .platform_data = &tmu0_platform_data, - }, - .resource = tmu0_resources, - .num_resources = ARRAY_SIZE(tmu0_resources), -}; - -static struct resource i2c0_resources[] = { - [0] = DEFINE_RES_MEM(0xe6820000, 0x426), - [1] = { - .start = gic_spi(167), - .end = gic_spi(170), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource i2c1_resources[] = { - [0] = DEFINE_RES_MEM(0xe6822000, 0x426), - [1] = { - .start = gic_spi(51), - .end = gic_spi(54), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource i2c2_resources[] = { - [0] = DEFINE_RES_MEM(0xe6824000, 0x426), - [1] = { - .start = gic_spi(171), - .end = gic_spi(174), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource i2c3_resources[] = { - [0] = DEFINE_RES_MEM(0xe6826000, 0x426), - [1] = { - .start = gic_spi(183), - .end = gic_spi(186), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource i2c4_resources[] = { - [0] = DEFINE_RES_MEM(0xe6828000, 0x426), - [1] = { - .start = gic_spi(187), - .end = gic_spi(190), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct i2c_sh_mobile_platform_data i2c_platform_data = { - .clks_per_count = 2, -}; - -static struct platform_device i2c0_device = { - .name = "i2c-sh_mobile", - .id = 0, - .resource = i2c0_resources, - .num_resources = ARRAY_SIZE(i2c0_resources), - .dev = { - .platform_data = &i2c_platform_data, - }, -}; - -static struct platform_device i2c1_device = { - .name = "i2c-sh_mobile", - .id = 1, - .resource = i2c1_resources, - .num_resources = ARRAY_SIZE(i2c1_resources), - .dev = { - .platform_data = &i2c_platform_data, - }, -}; - -static struct platform_device i2c2_device = { - .name = "i2c-sh_mobile", - .id = 2, - .resource = i2c2_resources, - .num_resources = ARRAY_SIZE(i2c2_resources), - .dev = { - .platform_data = &i2c_platform_data, - }, -}; - -static struct platform_device i2c3_device = { - .name = "i2c-sh_mobile", - .id = 3, - .resource = i2c3_resources, - .num_resources = ARRAY_SIZE(i2c3_resources), - .dev = { - .platform_data = &i2c_platform_data, - }, -}; - -static struct platform_device i2c4_device = { - .name = "i2c-sh_mobile", - .id = 4, - .resource = i2c4_resources, - .num_resources = ARRAY_SIZE(i2c4_resources), - .dev = { - .platform_data = &i2c_platform_data, - }, -}; - -static const struct sh_dmae_slave_config sh73a0_dmae_slaves[] = { - { - .slave_id = SHDMA_SLAVE_SCIF0_TX, - .addr = 0xe6c40020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x21, - }, { - .slave_id = SHDMA_SLAVE_SCIF0_RX, - .addr = 0xe6c40024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x22, - }, { - .slave_id = SHDMA_SLAVE_SCIF1_TX, - .addr = 0xe6c50020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x25, - }, { - .slave_id = SHDMA_SLAVE_SCIF1_RX, - .addr = 0xe6c50024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x26, - }, { - .slave_id = SHDMA_SLAVE_SCIF2_TX, - .addr = 0xe6c60020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x29, - }, { - .slave_id = SHDMA_SLAVE_SCIF2_RX, - .addr = 0xe6c60024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x2a, - }, { - .slave_id = SHDMA_SLAVE_SCIF3_TX, - .addr = 0xe6c70020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x2d, - }, { - .slave_id = SHDMA_SLAVE_SCIF3_RX, - .addr = 0xe6c70024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x2e, - }, { - .slave_id = SHDMA_SLAVE_SCIF4_TX, - .addr = 0xe6c80020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x39, - }, { - .slave_id = SHDMA_SLAVE_SCIF4_RX, - .addr = 0xe6c80024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x3a, - }, { - .slave_id = SHDMA_SLAVE_SCIF5_TX, - .addr = 0xe6cb0020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x35, - }, { - .slave_id = SHDMA_SLAVE_SCIF5_RX, - .addr = 0xe6cb0024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x36, - }, { - .slave_id = SHDMA_SLAVE_SCIF6_TX, - .addr = 0xe6cc0020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x1d, - }, { - .slave_id = SHDMA_SLAVE_SCIF6_RX, - .addr = 0xe6cc0024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x1e, - }, { - .slave_id = SHDMA_SLAVE_SCIF7_TX, - .addr = 0xe6cd0020, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x19, - }, { - .slave_id = SHDMA_SLAVE_SCIF7_RX, - .addr = 0xe6cd0024, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x1a, - }, { - .slave_id = SHDMA_SLAVE_SCIF8_TX, - .addr = 0xe6c30040, - .chcr = CHCR_TX(XMIT_SZ_8BIT), - .mid_rid = 0x3d, - }, { - .slave_id = SHDMA_SLAVE_SCIF8_RX, - .addr = 0xe6c30060, - .chcr = CHCR_RX(XMIT_SZ_8BIT), - .mid_rid = 0x3e, - }, { - .slave_id = SHDMA_SLAVE_SDHI0_TX, - .addr = 0xee100030, - .chcr = CHCR_TX(XMIT_SZ_16BIT), - .mid_rid = 0xc1, - }, { - .slave_id = SHDMA_SLAVE_SDHI0_RX, - .addr = 0xee100030, - .chcr = CHCR_RX(XMIT_SZ_16BIT), - .mid_rid = 0xc2, - }, { - .slave_id = SHDMA_SLAVE_SDHI1_TX, - .addr = 0xee120030, - .chcr = CHCR_TX(XMIT_SZ_16BIT), - .mid_rid = 0xc9, - }, { - .slave_id = SHDMA_SLAVE_SDHI1_RX, - .addr = 0xee120030, - .chcr = CHCR_RX(XMIT_SZ_16BIT), - .mid_rid = 0xca, - }, { - .slave_id = SHDMA_SLAVE_SDHI2_TX, - .addr = 0xee140030, - .chcr = CHCR_TX(XMIT_SZ_16BIT), - .mid_rid = 0xcd, - }, { - .slave_id = SHDMA_SLAVE_SDHI2_RX, - .addr = 0xee140030, - .chcr = CHCR_RX(XMIT_SZ_16BIT), - .mid_rid = 0xce, - }, { - .slave_id = SHDMA_SLAVE_MMCIF_TX, - .addr = 0xe6bd0034, - .chcr = CHCR_TX(XMIT_SZ_32BIT), - .mid_rid = 0xd1, - }, { - .slave_id = SHDMA_SLAVE_MMCIF_RX, - .addr = 0xe6bd0034, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0xd2, - }, -}; - -#define DMAE_CHANNEL(_offset) \ - { \ - .offset = _offset - 0x20, \ - .dmars = _offset - 0x20 + 0x40, \ - } - -static const struct sh_dmae_channel sh73a0_dmae_channels[] = { - DMAE_CHANNEL(0x8000), - DMAE_CHANNEL(0x8080), - DMAE_CHANNEL(0x8100), - DMAE_CHANNEL(0x8180), - DMAE_CHANNEL(0x8200), - DMAE_CHANNEL(0x8280), - DMAE_CHANNEL(0x8300), - DMAE_CHANNEL(0x8380), - DMAE_CHANNEL(0x8400), - DMAE_CHANNEL(0x8480), - DMAE_CHANNEL(0x8500), - DMAE_CHANNEL(0x8580), - DMAE_CHANNEL(0x8600), - DMAE_CHANNEL(0x8680), - DMAE_CHANNEL(0x8700), - DMAE_CHANNEL(0x8780), - DMAE_CHANNEL(0x8800), - DMAE_CHANNEL(0x8880), - DMAE_CHANNEL(0x8900), - DMAE_CHANNEL(0x8980), -}; - -static struct sh_dmae_pdata sh73a0_dmae_platform_data = { - .slave = sh73a0_dmae_slaves, - .slave_num = ARRAY_SIZE(sh73a0_dmae_slaves), - .channel = sh73a0_dmae_channels, - .channel_num = ARRAY_SIZE(sh73a0_dmae_channels), - .ts_low_shift = TS_LOW_SHIFT, - .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, - .ts_high_shift = TS_HI_SHIFT, - .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, - .ts_shift = dma_ts_shift, - .ts_shift_num = ARRAY_SIZE(dma_ts_shift), - .dmaor_init = DMAOR_DME, -}; - -static struct resource sh73a0_dmae_resources[] = { - DEFINE_RES_MEM(0xfe000020, 0x89e0), - { - .name = "error_irq", - .start = gic_spi(129), - .end = gic_spi(129), - .flags = IORESOURCE_IRQ, - }, - { - /* IRQ for channels 0-19 */ - .start = gic_spi(109), - .end = gic_spi(128), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device dma0_device = { - .name = "sh-dma-engine", - .id = 0, - .resource = sh73a0_dmae_resources, - .num_resources = ARRAY_SIZE(sh73a0_dmae_resources), - .dev = { - .platform_data = &sh73a0_dmae_platform_data, - }, -}; - -/* MPDMAC */ -static const struct sh_dmae_slave_config sh73a0_mpdma_slaves[] = { - { - .slave_id = SHDMA_SLAVE_FSI2A_RX, - .addr = 0xec230020, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0xd6, /* CHECK ME */ - }, { - .slave_id = SHDMA_SLAVE_FSI2A_TX, - .addr = 0xec230024, - .chcr = CHCR_TX(XMIT_SZ_32BIT), - .mid_rid = 0xd5, /* CHECK ME */ - }, { - .slave_id = SHDMA_SLAVE_FSI2C_RX, - .addr = 0xec230060, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0xda, /* CHECK ME */ - }, { - .slave_id = SHDMA_SLAVE_FSI2C_TX, - .addr = 0xec230064, - .chcr = CHCR_TX(XMIT_SZ_32BIT), - .mid_rid = 0xd9, /* CHECK ME */ - }, { - .slave_id = SHDMA_SLAVE_FSI2B_RX, - .addr = 0xec240020, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0x8e, /* CHECK ME */ - }, { - .slave_id = SHDMA_SLAVE_FSI2B_TX, - .addr = 0xec240024, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0x8d, /* CHECK ME */ - }, { - .slave_id = SHDMA_SLAVE_FSI2D_RX, - .addr = 0xec240060, - .chcr = CHCR_RX(XMIT_SZ_32BIT), - .mid_rid = 0x9a, /* CHECK ME */ - }, -}; - -#define MPDMA_CHANNEL(a, b, c) \ -{ \ - .offset = a, \ - .dmars = b, \ - .dmars_bit = c, \ - .chclr_offset = (0x220 - 0x20) + a \ -} - -static const struct sh_dmae_channel sh73a0_mpdma_channels[] = { - MPDMA_CHANNEL(0x00, 0, 0), - MPDMA_CHANNEL(0x10, 0, 8), - MPDMA_CHANNEL(0x20, 4, 0), - MPDMA_CHANNEL(0x30, 4, 8), - MPDMA_CHANNEL(0x50, 8, 0), - MPDMA_CHANNEL(0x70, 8, 8), -}; - -static struct sh_dmae_pdata sh73a0_mpdma_platform_data = { - .slave = sh73a0_mpdma_slaves, - .slave_num = ARRAY_SIZE(sh73a0_mpdma_slaves), - .channel = sh73a0_mpdma_channels, - .channel_num = ARRAY_SIZE(sh73a0_mpdma_channels), - .ts_low_shift = TS_LOW_SHIFT, - .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, - .ts_high_shift = TS_HI_SHIFT, - .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, - .ts_shift = dma_ts_shift, - .ts_shift_num = ARRAY_SIZE(dma_ts_shift), - .dmaor_init = DMAOR_DME, - .chclr_present = 1, -}; - -/* Resource order important! */ -static struct resource sh73a0_mpdma_resources[] = { - /* Channel registers and DMAOR */ - DEFINE_RES_MEM(0xec618020, 0x270), - /* DMARSx */ - DEFINE_RES_MEM(0xec619000, 0xc), - { - .name = "error_irq", - .start = gic_spi(181), - .end = gic_spi(181), - .flags = IORESOURCE_IRQ, - }, - { - /* IRQ for channels 0-5 */ - .start = gic_spi(175), - .end = gic_spi(180), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device mpdma0_device = { - .name = "sh-dma-engine", - .id = 1, - .resource = sh73a0_mpdma_resources, - .num_resources = ARRAY_SIZE(sh73a0_mpdma_resources), - .dev = { - .platform_data = &sh73a0_mpdma_platform_data, - }, -}; - -static struct resource pmu_resources[] = { - [0] = { - .start = gic_spi(55), - .end = gic_spi(55), - .flags = IORESOURCE_IRQ, - }, - [1] = { - .start = gic_spi(56), - .end = gic_spi(56), - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device pmu_device = { - .name = "armv7-pmu", - .id = -1, - .num_resources = ARRAY_SIZE(pmu_resources), - .resource = pmu_resources, -}; - -/* an IPMMU module for ICB */ -static struct resource ipmmu_resources[] = { - DEFINE_RES_MEM(0xfe951000, 0x100), -}; - -static const char * const ipmmu_dev_names[] = { - "sh_mobile_lcdc_fb.0", -}; - -static struct shmobile_ipmmu_platform_data ipmmu_platform_data = { - .dev_names = ipmmu_dev_names, - .num_dev_names = ARRAY_SIZE(ipmmu_dev_names), -}; - -static struct platform_device ipmmu_device = { - .name = "ipmmu", - .id = -1, - .dev = { - .platform_data = &ipmmu_platform_data, - }, - .resource = ipmmu_resources, - .num_resources = ARRAY_SIZE(ipmmu_resources), -}; - -static struct renesas_intc_irqpin_config irqpin0_platform_data = { - .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */ - .control_parent = true, -}; - -static struct resource irqpin0_resources[] = { - DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */ - DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */ - DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */ - DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */ - DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */ - DEFINE_RES_IRQ(gic_spi(1)), /* IRQ0 */ - DEFINE_RES_IRQ(gic_spi(2)), /* IRQ1 */ - DEFINE_RES_IRQ(gic_spi(3)), /* IRQ2 */ - DEFINE_RES_IRQ(gic_spi(4)), /* IRQ3 */ - DEFINE_RES_IRQ(gic_spi(5)), /* IRQ4 */ - DEFINE_RES_IRQ(gic_spi(6)), /* IRQ5 */ - DEFINE_RES_IRQ(gic_spi(7)), /* IRQ6 */ - DEFINE_RES_IRQ(gic_spi(8)), /* IRQ7 */ -}; - -static struct platform_device irqpin0_device = { - .name = "renesas_intc_irqpin", - .id = 0, - .resource = irqpin0_resources, - .num_resources = ARRAY_SIZE(irqpin0_resources), - .dev = { - .platform_data = &irqpin0_platform_data, - }, -}; - -static struct renesas_intc_irqpin_config irqpin1_platform_data = { - .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */ - .control_parent = true, /* Disable spurious IRQ10 */ -}; - -static struct resource irqpin1_resources[] = { - DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */ - DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */ - DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */ - DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */ - DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */ - DEFINE_RES_IRQ(gic_spi(9)), /* IRQ8 */ - DEFINE_RES_IRQ(gic_spi(10)), /* IRQ9 */ - DEFINE_RES_IRQ(gic_spi(11)), /* IRQ10 */ - DEFINE_RES_IRQ(gic_spi(12)), /* IRQ11 */ - DEFINE_RES_IRQ(gic_spi(13)), /* IRQ12 */ - DEFINE_RES_IRQ(gic_spi(14)), /* IRQ13 */ - DEFINE_RES_IRQ(gic_spi(15)), /* IRQ14 */ - DEFINE_RES_IRQ(gic_spi(16)), /* IRQ15 */ -}; - -static struct platform_device irqpin1_device = { - .name = "renesas_intc_irqpin", - .id = 1, - .resource = irqpin1_resources, - .num_resources = ARRAY_SIZE(irqpin1_resources), - .dev = { - .platform_data = &irqpin1_platform_data, - }, -}; - -static struct renesas_intc_irqpin_config irqpin2_platform_data = { - .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */ - .control_parent = true, -}; - -static struct resource irqpin2_resources[] = { - DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */ - DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI20A */ - DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ20A */ - DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK20A */ - DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR20A */ - DEFINE_RES_IRQ(gic_spi(17)), /* IRQ16 */ - DEFINE_RES_IRQ(gic_spi(18)), /* IRQ17 */ - DEFINE_RES_IRQ(gic_spi(19)), /* IRQ18 */ - DEFINE_RES_IRQ(gic_spi(20)), /* IRQ19 */ - DEFINE_RES_IRQ(gic_spi(21)), /* IRQ20 */ - DEFINE_RES_IRQ(gic_spi(22)), /* IRQ21 */ - DEFINE_RES_IRQ(gic_spi(23)), /* IRQ22 */ - DEFINE_RES_IRQ(gic_spi(24)), /* IRQ23 */ -}; - -static struct platform_device irqpin2_device = { - .name = "renesas_intc_irqpin", - .id = 2, - .resource = irqpin2_resources, - .num_resources = ARRAY_SIZE(irqpin2_resources), - .dev = { - .platform_data = &irqpin2_platform_data, - }, -}; - -static struct renesas_intc_irqpin_config irqpin3_platform_data = { - .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */ - .control_parent = true, -}; - -static struct resource irqpin3_resources[] = { - DEFINE_RES_MEM(0xe690000c, 4), /* ICR4A */ - DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */ - DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */ - DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */ - DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */ - DEFINE_RES_IRQ(gic_spi(25)), /* IRQ24 */ - DEFINE_RES_IRQ(gic_spi(26)), /* IRQ25 */ - DEFINE_RES_IRQ(gic_spi(27)), /* IRQ26 */ - DEFINE_RES_IRQ(gic_spi(28)), /* IRQ27 */ - DEFINE_RES_IRQ(gic_spi(29)), /* IRQ28 */ - DEFINE_RES_IRQ(gic_spi(30)), /* IRQ29 */ - DEFINE_RES_IRQ(gic_spi(31)), /* IRQ30 */ - DEFINE_RES_IRQ(gic_spi(32)), /* IRQ31 */ -}; - -static struct platform_device irqpin3_device = { - .name = "renesas_intc_irqpin", - .id = 3, - .resource = irqpin3_resources, - .num_resources = ARRAY_SIZE(irqpin3_resources), - .dev = { - .platform_data = &irqpin3_platform_data, - }, -}; - -static struct platform_device *sh73a0_early_devices[] __initdata = { - &scif0_device, - &scif1_device, - &scif2_device, - &scif3_device, - &scif4_device, - &scif5_device, - &scif6_device, - &scif7_device, - &scif8_device, - &tmu0_device, - &ipmmu_device, - &cmt1_device, -}; - -static struct platform_device *sh73a0_late_devices[] __initdata = { - &i2c0_device, - &i2c1_device, - &i2c2_device, - &i2c3_device, - &i2c4_device, - &dma0_device, - &mpdma0_device, - &pmu_device, - &irqpin0_device, - &irqpin1_device, - &irqpin2_device, - &irqpin3_device, -}; - -#define SRCR2 IOMEM(0xe61580b0) - -void __init sh73a0_add_standard_devices(void) -{ - /* Clear software reset bit on SY-DMAC module */ - __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2); - - platform_add_devices(sh73a0_early_devices, - ARRAY_SIZE(sh73a0_early_devices)); - platform_add_devices(sh73a0_late_devices, - ARRAY_SIZE(sh73a0_late_devices)); -} - -/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ -void __init __weak sh73a0_register_twd(void) { } - -void __init sh73a0_earlytimer_init(void) -{ - shmobile_init_delay(); -#ifndef CONFIG_COMMON_CLK - sh73a0_clock_init(); -#endif - shmobile_earlytimer_init(); - sh73a0_register_twd(); -} - -void __init sh73a0_add_early_devices(void) -{ - early_platform_add_devices(sh73a0_early_devices, - ARRAY_SIZE(sh73a0_early_devices)); - - /* setup early console here as well */ - shmobile_setup_console(); -} - -#ifdef CONFIG_USE_OF - static void __init sh73a0_generic_init(void) { #ifdef CONFIG_CACHE_L2X0 @@ -794,7 +58,7 @@ static void __init sh73a0_generic_init(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static const char *sh73a0_boards_compat_dt[] __initdata = { +static const char *const sh73a0_boards_compat_dt[] __initconst = { "renesas,sh73a0", NULL, }; @@ -807,4 +71,3 @@ DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)") .init_late = shmobile_init_late, .dt_compat = sh73a0_boards_compat_dt, MACHINE_END -#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/sh73a0.h b/arch/arm/mach-shmobile/sh73a0.h index 5a80f18..3964680 100644 --- a/arch/arm/mach-shmobile/sh73a0.h +++ b/arch/arm/mach-shmobile/sh73a0.h @@ -1,89 +1,6 @@ #ifndef __ASM_SH73A0_H__ #define __ASM_SH73A0_H__ -/* DMA slave IDs */ -enum { - SHDMA_SLAVE_INVALID, - SHDMA_SLAVE_SCIF0_TX, - SHDMA_SLAVE_SCIF0_RX, - SHDMA_SLAVE_SCIF1_TX, - SHDMA_SLAVE_SCIF1_RX, - SHDMA_SLAVE_SCIF2_TX, - SHDMA_SLAVE_SCIF2_RX, - SHDMA_SLAVE_SCIF3_TX, - SHDMA_SLAVE_SCIF3_RX, - SHDMA_SLAVE_SCIF4_TX, - SHDMA_SLAVE_SCIF4_RX, - SHDMA_SLAVE_SCIF5_TX, - SHDMA_SLAVE_SCIF5_RX, - SHDMA_SLAVE_SCIF6_TX, - SHDMA_SLAVE_SCIF6_RX, - SHDMA_SLAVE_SCIF7_TX, - SHDMA_SLAVE_SCIF7_RX, - SHDMA_SLAVE_SCIF8_TX, - SHDMA_SLAVE_SCIF8_RX, - SHDMA_SLAVE_SDHI0_TX, - SHDMA_SLAVE_SDHI0_RX, - SHDMA_SLAVE_SDHI1_TX, - SHDMA_SLAVE_SDHI1_RX, - SHDMA_SLAVE_SDHI2_TX, - SHDMA_SLAVE_SDHI2_RX, - SHDMA_SLAVE_MMCIF_TX, - SHDMA_SLAVE_MMCIF_RX, - SHDMA_SLAVE_FSI2A_TX, - SHDMA_SLAVE_FSI2A_RX, - SHDMA_SLAVE_FSI2B_TX, - SHDMA_SLAVE_FSI2B_RX, - SHDMA_SLAVE_FSI2C_TX, - SHDMA_SLAVE_FSI2C_RX, - SHDMA_SLAVE_FSI2D_RX, -}; - -/* - * SH73A0 IRQ LOCATION TABLE - * - * 416 ----------------------------------------- - * IRQ0-IRQ15 - * 431 ----------------------------------------- - * ... - * 448 ----------------------------------------- - * sh73a0-intcs - * sh73a0-intca-irq-pins - * 680 ----------------------------------------- - * ... - * 700 ----------------------------------------- - * sh73a0-pint0 - * 731 ----------------------------------------- - * 732 ----------------------------------------- - * sh73a0-pint1 - * 739 ----------------------------------------- - * ... - * 800 ----------------------------------------- - * IRQ16-IRQ31 - * 815 ----------------------------------------- - * ... - * 928 ----------------------------------------- - * sh73a0-intca-irq-pins - * 943 ----------------------------------------- - */ - -/* PINT interrupts are located at Linux IRQ 700 and up */ -#define SH73A0_PINT0_IRQ(irq) ((irq) + 700) -#define SH73A0_PINT1_IRQ(irq) ((irq) + 732) - -extern void sh73a0_init_irq(void); -extern void sh73a0_init_irq_dt(void); -extern void sh73a0_map_io(void); -extern void sh73a0_earlytimer_init(void); -extern void sh73a0_add_early_devices(void); -extern void sh73a0_add_standard_devices(void); -extern void sh73a0_clock_init(void); -extern void sh73a0_pinmux_init(void); -extern void sh73a0_pm_init(void); -extern struct clk sh73a0_extal1_clk; -extern struct clk sh73a0_extal2_clk; -extern struct clk sh73a0_extcki_clk; -extern struct clk sh73a0_extalr_clk; extern struct smp_operations sh73a0_smp_ops; #endif /* __ASM_SH73A0_H__ */ diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 6756ada..353562b8 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -31,25 +31,25 @@ #define AVECR IOMEM(0xfe700040) #define R8A7779_SCU_BASE 0xf0000000 -static struct rcar_sysc_ch r8a7779_ch_cpu1 = { +static const struct rcar_sysc_ch r8a7779_ch_cpu1 = { .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */ .chan_bit = 1, /* ARM1 */ .isr_bit = 1, /* ARM1 */ }; -static struct rcar_sysc_ch r8a7779_ch_cpu2 = { +static const struct rcar_sysc_ch r8a7779_ch_cpu2 = { .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */ .chan_bit = 2, /* ARM2 */ .isr_bit = 2, /* ARM2 */ }; -static struct rcar_sysc_ch r8a7779_ch_cpu3 = { +static const struct rcar_sysc_ch r8a7779_ch_cpu3 = { .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */ .chan_bit = 3, /* ARM3 */ .isr_bit = 3, /* ARM3 */ }; -static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = { +static const struct rcar_sysc_ch * const r8a7779_ch_cpu[4] = { [1] = &r8a7779_ch_cpu1, [2] = &r8a7779_ch_cpu2, [3] = &r8a7779_ch_cpu3, @@ -57,7 +57,7 @@ static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = { static int r8a7779_platform_cpu_kill(unsigned int cpu) { - struct rcar_sysc_ch *ch = NULL; + const struct rcar_sysc_ch *ch = NULL; int ret = -EIO; cpu = cpu_logical_map(cpu); @@ -73,7 +73,7 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu) static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) { - struct rcar_sysc_ch *ch = NULL; + const struct rcar_sysc_ch *ch = NULL; unsigned int lcpu = cpu_logical_map(cpu); int ret; diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c index 930f45c..2ef0054 100644 --- a/arch/arm/mach-shmobile/smp-r8a7790.c +++ b/arch/arm/mach-shmobile/smp-r8a7790.c @@ -26,12 +26,12 @@ #include "rcar-gen2.h" #include "r8a7790.h" -static struct rcar_sysc_ch r8a7790_ca15_scu = { +static const struct rcar_sysc_ch r8a7790_ca15_scu = { .chan_offs = 0x180, /* PWRSR5 .. PWRER5 */ .isr_bit = 12, /* CA15-SCU */ }; -static struct rcar_sysc_ch r8a7790_ca7_scu = { +static const struct rcar_sysc_ch r8a7790_ca7_scu = { .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */ .isr_bit = 21, /* CA7-SCU */ }; diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 2106d6b..d03aa11 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -33,14 +33,6 @@ #define SH73A0_SCU_BASE 0xf0000000 -#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM) -static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29); -void __init sh73a0_register_twd(void) -{ - twd_local_timer_register(&twd_local_timer); -} -#endif - static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned int lcpu = cpu_logical_map(cpu); diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index 0edf2a6..f1d027a 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c @@ -70,18 +70,6 @@ void __init shmobile_init_delay(void) if (!max_freq) return; -#ifdef CONFIG_ARCH_SHMOBILE_LEGACY - /* Non-multiplatform r8a73a4 SoC cannot use arch timer due - * to GIC being initialized from C and arch timer via DT */ - if (of_machine_is_compatible("renesas,r8a73a4")) - has_arch_timer = false; - - /* Non-multiplatform r8a7790 SoC cannot use arch timer due - * to GIC being initialized from C and arch timer via DT */ - if (of_machine_is_compatible("renesas,r8a7790")) - has_arch_timer = false; -#endif - if (!has_arch_timer || !IS_ENABLED(CONFIG_ARM_ARCH_TIMER)) { if (is_a7_a8_a9) shmobile_setup_delay_hz(max_freq, 1, 3); diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c index 26fda4e..9ccffc1 100644 --- a/arch/arm/mach-spear/time.c +++ b/arch/arm/mach-spear/time.c @@ -66,8 +66,6 @@ static __iomem void *gpt_base; static struct clk *gpt_clk; -static void clockevent_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk_event_dev); static int clockevent_next_event(unsigned long evt, struct clock_event_device *clk_event_dev); @@ -95,54 +93,67 @@ static void __init spear_clocksource_init(void) 200, 16, clocksource_mmio_readw_up); } -static struct clock_event_device clkevt = { - .name = "tmr0", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = clockevent_set_mode, - .set_next_event = clockevent_next_event, - .shift = 0, /* to be computed */ -}; +static inline void timer_shutdown(struct clock_event_device *evt) +{ + u16 val = readw(gpt_base + CR(CLKEVT)); + + /* stop the timer */ + val &= ~CTRL_ENABLE; + writew(val, gpt_base + CR(CLKEVT)); +} + +static int spear_shutdown(struct clock_event_device *evt) +{ + timer_shutdown(evt); + + return 0; +} + +static int spear_set_oneshot(struct clock_event_device *evt) +{ + u16 val; -static void clockevent_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk_event_dev) + /* stop the timer */ + timer_shutdown(evt); + + val = readw(gpt_base + CR(CLKEVT)); + val |= CTRL_ONE_SHOT; + writew(val, gpt_base + CR(CLKEVT)); + + return 0; +} + +static int spear_set_periodic(struct clock_event_device *evt) { u32 period; u16 val; /* stop the timer */ + timer_shutdown(evt); + + period = clk_get_rate(gpt_clk) / HZ; + period >>= CTRL_PRESCALER16; + writew(period, gpt_base + LOAD(CLKEVT)); + val = readw(gpt_base + CR(CLKEVT)); - val &= ~CTRL_ENABLE; + val &= ~CTRL_ONE_SHOT; + val |= CTRL_ENABLE | CTRL_INT_ENABLE; writew(val, gpt_base + CR(CLKEVT)); - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - period = clk_get_rate(gpt_clk) / HZ; - period >>= CTRL_PRESCALER16; - writew(period, gpt_base + LOAD(CLKEVT)); - - val = readw(gpt_base + CR(CLKEVT)); - val &= ~CTRL_ONE_SHOT; - val |= CTRL_ENABLE | CTRL_INT_ENABLE; - writew(val, gpt_base + CR(CLKEVT)); - - break; - case CLOCK_EVT_MODE_ONESHOT: - val = readw(gpt_base + CR(CLKEVT)); - val |= CTRL_ONE_SHOT; - writew(val, gpt_base + CR(CLKEVT)); - - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - - break; - default: - pr_err("Invalid mode requested\n"); - break; - } + return 0; } +static struct clock_event_device clkevt = { + .name = "tmr0", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = spear_shutdown, + .set_state_periodic = spear_set_periodic, + .set_state_oneshot = spear_set_oneshot, + .tick_resume = spear_shutdown, + .set_next_event = clockevent_next_event, + .shift = 0, /* to be computed */ +}; + static int clockevent_next_event(unsigned long cycles, struct clock_event_device *clk_event_dev) { @@ -193,7 +204,7 @@ static void __init spear_clockevent_init(int irq) setup_irq(irq, &spear_timer_irq); } -const static struct of_device_id timer_of_match[] __initconst = { +static const struct of_device_id const timer_of_match[] __initconst = { { .compatible = "st,spear-timer", }, { }, }; diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c index b373aca..ae10fb2 100644 --- a/arch/arm/mach-sti/board-dt.c +++ b/arch/arm/mach-sti/board-dt.c @@ -14,7 +14,7 @@ #include "smp.h" -static const char *stih41x_dt_match[] __initdata = { +static const char *const stih41x_dt_match[] __initconst = { "st,stih415", "st,stih416", "st,stih407", diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 81502b9..4efe2d4 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -35,7 +35,7 @@ config MACH_SUN7I select SUN5I_HSTIMER config MACH_SUN8I - bool "Allwinner A23 (sun8i) SoCs support" + bool "Allwinner sun8i Family SoCs support" default ARCH_SUNXI select ARM_GIC select MFD_SUN6I_PRCM diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 1bc811a..65bab28 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -67,10 +67,13 @@ MACHINE_END static const char * const sun8i_board_dt_compat[] = { "allwinner,sun8i-a23", + "allwinner,sun8i-a33", + "allwinner,sun8i-h3", NULL, }; -DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family") +DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family") + .init_time = sun6i_timer_init, .dt_compat = sun8i_board_dt_compat, .init_late = sunxi_dt_cpufreq_init, MACHINE_END diff --git a/arch/arm/mach-w90x900/irq.c b/arch/arm/mach-w90x900/irq.c index d66d43a..491b317 100644 --- a/arch/arm/mach-w90x900/irq.c +++ b/arch/arm/mach-w90x900/irq.c @@ -211,6 +211,6 @@ void __init nuc900_init_irq(void) for (irqno = IRQ_WDT; irqno <= IRQ_ADC; irqno++) { irq_set_chip_and_handler(irqno, &nuc900_irq_chip, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); + irq_clear_status_flags(irqno, IRQ_NOREQUEST); } } diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index 9230d37..cd1966e 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -48,31 +48,32 @@ static unsigned int timer0_load; -static void nuc900_clockevent_setmode(enum clock_event_mode mode, - struct clock_event_device *clk) +static int nuc900_clockevent_shutdown(struct clock_event_device *evt) { - unsigned int val; + unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27); - val = __raw_readl(REG_TCSR0); - val &= ~(0x03 << 27); + __raw_writel(val, REG_TCSR0); + return 0; +} + +static int nuc900_clockevent_set_oneshot(struct clock_event_device *evt) +{ + unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27); - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - __raw_writel(timer0_load, REG_TICR0); - val |= (PERIOD | COUNTEN | INTEN | PRESCALE); - break; + val |= (ONESHOT | COUNTEN | INTEN | PRESCALE); - case CLOCK_EVT_MODE_ONESHOT: - val |= (ONESHOT | COUNTEN | INTEN | PRESCALE); - break; + __raw_writel(val, REG_TCSR0); + return 0; +} - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - break; - } +static int nuc900_clockevent_set_periodic(struct clock_event_device *evt) +{ + unsigned int val = __raw_readl(REG_TCSR0) & ~(0x03 << 27); + __raw_writel(timer0_load, REG_TICR0); + val |= (PERIOD | COUNTEN | INTEN | PRESCALE); __raw_writel(val, REG_TCSR0); + return 0; } static int nuc900_clockevent_setnextevent(unsigned long evt, @@ -90,11 +91,15 @@ static int nuc900_clockevent_setnextevent(unsigned long evt, } static struct clock_event_device nuc900_clockevent_device = { - .name = "nuc900-timer0", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = nuc900_clockevent_setmode, - .set_next_event = nuc900_clockevent_setnextevent, - .rating = 300, + .name = "nuc900-timer0", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = nuc900_clockevent_shutdown, + .set_state_periodic = nuc900_clockevent_set_periodic, + .set_state_oneshot = nuc900_clockevent_set_oneshot, + .tick_resume = nuc900_clockevent_shutdown, + .set_next_event = nuc900_clockevent_setnextevent, + .rating = 300, }; /*IRQ handler for the timer*/ diff --git a/arch/arm/mach-zx/zx296702.c b/arch/arm/mach-zx/zx296702.c index 60bb1a8..a041e13 100644 --- a/arch/arm/mach-zx/zx296702.c +++ b/arch/arm/mach-zx/zx296702.c @@ -13,7 +13,7 @@ #include <linux/of_address.h> #include <linux/of_platform.h> -static const char *zx296702_dt_compat[] __initconst = { +static const char *const zx296702_dt_compat[] __initconst = { "zte,zx296702", NULL, }; diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index d1e5ad7..0c81056 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -255,7 +255,7 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, } #endif -void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, +static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, size_t size, unsigned int mtype, void *caller) { const struct mem_type *type; @@ -363,7 +363,7 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, unsigned int mtype) { return __arm_ioremap_pfn_caller(pfn, offset, size, mtype, - __builtin_return_address(0)); + __builtin_return_address(0)); } EXPORT_SYMBOL(__arm_ioremap_pfn); @@ -371,13 +371,26 @@ void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *) = __arm_ioremap_caller; -void __iomem * -__arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype) +void __iomem *ioremap(resource_size_t res_cookie, size_t size) +{ + return arch_ioremap_caller(res_cookie, size, MT_DEVICE, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap); + +void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) +{ + return arch_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_cache); + +void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) { - return arch_ioremap_caller(phys_addr, size, mtype, - __builtin_return_address(0)); + return arch_ioremap_caller(res_cookie, size, MT_DEVICE_WC, + __builtin_return_address(0)); } -EXPORT_SYMBOL(__arm_ioremap); +EXPORT_SYMBOL(ioremap_wc); /* * Remap an arbitrary physical address space into the kernel virtual @@ -431,11 +444,11 @@ void __iounmap(volatile void __iomem *io_addr) void (*arch_iounmap)(volatile void __iomem *) = __iounmap; -void __arm_iounmap(volatile void __iomem *io_addr) +void iounmap(volatile void __iomem *cookie) { - arch_iounmap(io_addr); + arch_iounmap(cookie); } -EXPORT_SYMBOL(__arm_iounmap); +EXPORT_SYMBOL(iounmap); #ifdef CONFIG_PCI static int pci_ioremap_mem_type = MT_DEVICE; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6ca7d9a..870838a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1072,6 +1072,7 @@ void __init sanity_check_meminfo(void) int highmem = 0; phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; struct memblock_region *reg; + bool should_use_highmem = false; for_each_memblock(memory, reg) { phys_addr_t block_start = reg->base; @@ -1090,6 +1091,7 @@ void __init sanity_check_meminfo(void) pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", &block_start, &block_end); memblock_remove(reg->base, reg->size); + should_use_highmem = true; continue; } @@ -1100,6 +1102,7 @@ void __init sanity_check_meminfo(void) &block_start, &block_end, &vmalloc_limit); memblock_remove(vmalloc_limit, overlap_size); block_end = vmalloc_limit; + should_use_highmem = true; } } @@ -1134,6 +1137,9 @@ void __init sanity_check_meminfo(void) } } + if (should_use_highmem) + pr_notice("Consider using a HIGHMEM enabled kernel.\n"); + high_memory = __va(arm_lowmem_limit - 1) + 1; /* @@ -1494,6 +1500,7 @@ void __init paging_init(const struct machine_desc *mdesc) build_mem_type_table(); prepare_page_table(); map_lowmem(); + memblock_set_current_limit(arm_lowmem_limit); dma_contiguous_remap(); devicemaps_init(mdesc); kmap_init(); diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index afd7e05..1dd1093 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -351,30 +351,43 @@ void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, } EXPORT_SYMBOL(__arm_ioremap_pfn); -void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, - size_t size, unsigned int mtype, void *caller) +void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller) { - return __arm_ioremap_pfn(pfn, offset, size, mtype); + return (void __iomem *)phys_addr; } -void __iomem *__arm_ioremap(phys_addr_t phys_addr, size_t size, - unsigned int mtype) +void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); + +void __iomem *ioremap(resource_size_t res_cookie, size_t size) { - return (void __iomem *)phys_addr; + return __arm_ioremap_caller(res_cookie, size, MT_DEVICE, + __builtin_return_address(0)); } -EXPORT_SYMBOL(__arm_ioremap); +EXPORT_SYMBOL(ioremap); -void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); +void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) +{ + return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_cache); -void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, - unsigned int mtype, void *caller) +void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) +{ + return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_WC, + __builtin_return_address(0)); +} +EXPORT_SYMBOL(ioremap_wc); + +void __iounmap(volatile void __iomem *addr) { - return __arm_ioremap(phys_addr, size, mtype); } +EXPORT_SYMBOL(__iounmap); void (*arch_iounmap)(volatile void __iomem *); -void __arm_iounmap(volatile void __iomem *addr) +void iounmap(volatile void __iomem *addr) { } -EXPORT_SYMBOL(__arm_iounmap); +EXPORT_SYMBOL(iounmap); diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 6ad65d8..101e8f2 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -77,41 +77,57 @@ static int iop_set_next_event(unsigned long delta, static unsigned long ticks_per_jiffy; -static void iop_set_mode(enum clock_event_mode mode, - struct clock_event_device *unused) +static int iop_set_periodic(struct clock_event_device *evt) { u32 tmr = read_tmr0(); - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - write_tmr0(tmr & ~IOP_TMR_EN); - write_tcr0(ticks_per_jiffy - 1); - write_trr0(ticks_per_jiffy - 1); - tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN); - break; - case CLOCK_EVT_MODE_ONESHOT: - /* ->set_next_event sets period and enables timer */ - tmr &= ~(IOP_TMR_RELOAD | IOP_TMR_EN); - break; - case CLOCK_EVT_MODE_RESUME: - tmr |= IOP_TMR_EN; - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - default: - tmr &= ~IOP_TMR_EN; - break; - } + write_tmr0(tmr & ~IOP_TMR_EN); + write_tcr0(ticks_per_jiffy - 1); + write_trr0(ticks_per_jiffy - 1); + tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN); write_tmr0(tmr); + return 0; +} + +static int iop_set_oneshot(struct clock_event_device *evt) +{ + u32 tmr = read_tmr0(); + + /* ->set_next_event sets period and enables timer */ + tmr &= ~(IOP_TMR_RELOAD | IOP_TMR_EN); + write_tmr0(tmr); + return 0; +} + +static int iop_shutdown(struct clock_event_device *evt) +{ + u32 tmr = read_tmr0(); + + tmr &= ~IOP_TMR_EN; + write_tmr0(tmr); + return 0; +} + +static int iop_resume(struct clock_event_device *evt) +{ + u32 tmr = read_tmr0(); + + tmr |= IOP_TMR_EN; + write_tmr0(tmr); + return 0; } static struct clock_event_device iop_clockevent = { - .name = "iop_timer0", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .rating = 300, - .set_next_event = iop_set_next_event, - .set_mode = iop_set_mode, + .name = "iop_timer0", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .set_next_event = iop_set_next_event, + .set_state_shutdown = iop_shutdown, + .set_state_periodic = iop_set_periodic, + .tick_resume = iop_resume, + .set_state_oneshot = iop_set_oneshot, }; static irqreturn_t diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index 5168a52..79c33ec 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -407,9 +407,9 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type) return 0; } -static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) +static void gpio_irq_handler(unsigned __irq, struct irq_desc *desc) { - struct orion_gpio_chip *ochip = irq_get_handler_data(irq); + struct orion_gpio_chip *ochip = irq_desc_get_handler_data(desc); u32 cause, type; int i; @@ -582,8 +582,9 @@ void __init orion_gpio_init(struct device_node *np, for (i = 0; i < 4; i++) { if (irqs[i]) { - irq_set_handler_data(irqs[i], ochip); - irq_set_chained_handler(irqs[i], gpio_irq_handler); + irq_set_chained_handler_and_data(irqs[i], + gpio_irq_handler, + ochip); } } diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 261258f..8085a8a 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -106,60 +106,63 @@ orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) return 0; } -static void -orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) +static int orion_clkevt_shutdown(struct clock_event_device *evt) { unsigned long flags; u32 u; local_irq_save(flags); - if (mode == CLOCK_EVT_MODE_PERIODIC) { - /* - * Setup timer to fire at 1/HZ intervals. - */ - writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF); - writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF); - - /* - * Enable timer interrupt. - */ - u = readl(bridge_base + BRIDGE_MASK_OFF); - writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF); - - /* - * Enable timer. - */ - u = readl(timer_base + TIMER_CTRL_OFF); - writel(u | TIMER1_EN | TIMER1_RELOAD_EN, - timer_base + TIMER_CTRL_OFF); - } else { - /* - * Disable timer. - */ - u = readl(timer_base + TIMER_CTRL_OFF); - writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF); - - /* - * Disable timer interrupt. - */ - u = readl(bridge_base + BRIDGE_MASK_OFF); - writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF); - - /* - * ACK pending timer interrupt. - */ - writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF); - - } + + /* Disable timer */ + u = readl(timer_base + TIMER_CTRL_OFF); + writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF); + + /* Disable timer interrupt */ + u = readl(bridge_base + BRIDGE_MASK_OFF); + writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF); + + /* ACK pending timer interrupt */ + writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF); + + local_irq_restore(flags); + + return 0; +} + +static int orion_clkevt_set_periodic(struct clock_event_device *evt) +{ + unsigned long flags; + u32 u; + + local_irq_save(flags); + + /* Setup timer to fire at 1/HZ intervals */ + writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF); + writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF); + + /* Enable timer interrupt */ + u = readl(bridge_base + BRIDGE_MASK_OFF); + writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF); + + /* Enable timer */ + u = readl(timer_base + TIMER_CTRL_OFF); + writel(u | TIMER1_EN | TIMER1_RELOAD_EN, timer_base + TIMER_CTRL_OFF); + local_irq_restore(flags); + + return 0; } static struct clock_event_device orion_clkevt = { - .name = "orion_tick", - .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, - .rating = 300, - .set_next_event = orion_clkevt_next_event, - .set_mode = orion_clkevt_mode, + .name = "orion_tick", + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC, + .rating = 300, + .set_next_event = orion_clkevt_next_event, + .set_state_shutdown = orion_clkevt_shutdown, + .set_state_periodic = orion_clkevt_set_periodic, + .set_state_oneshot = orion_clkevt_shutdown, + .tick_resume = orion_clkevt_shutdown, }; static irqreturn_t orion_timer_interrupt(int irq, void *dev_id) diff --git a/arch/arm/vdso/vdsomunge.c b/arch/arm/vdso/vdsomunge.c index 9005b07..aedec81 100644 --- a/arch/arm/vdso/vdsomunge.c +++ b/arch/arm/vdso/vdsomunge.c @@ -45,13 +45,11 @@ * it does. */ -#define _GNU_SOURCE - #include <byteswap.h> #include <elf.h> #include <errno.h> -#include <error.h> #include <fcntl.h> +#include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -82,11 +80,25 @@ #define EF_ARM_ABI_FLOAT_HARD 0x400 #endif +static int failed; +static const char *argv0; static const char *outfile; +static void fail(const char *fmt, ...) +{ + va_list ap; + + failed = 1; + fprintf(stderr, "%s: ", argv0); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + static void cleanup(void) { - if (error_message_count > 0 && outfile != NULL) + if (failed && outfile != NULL) unlink(outfile); } @@ -119,68 +131,66 @@ int main(int argc, char **argv) int infd; atexit(cleanup); + argv0 = argv[0]; if (argc != 3) - error(EXIT_FAILURE, 0, "Usage: %s [infile] [outfile]", argv[0]); + fail("Usage: %s [infile] [outfile]\n", argv[0]); infile = argv[1]; outfile = argv[2]; infd = open(infile, O_RDONLY); if (infd < 0) - error(EXIT_FAILURE, errno, "Cannot open %s", infile); + fail("Cannot open %s: %s\n", infile, strerror(errno)); if (fstat(infd, &stat) != 0) - error(EXIT_FAILURE, errno, "Failed stat for %s", infile); + fail("Failed stat for %s: %s\n", infile, strerror(errno)); inbuf = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, infd, 0); if (inbuf == MAP_FAILED) - error(EXIT_FAILURE, errno, "Failed to map %s", infile); + fail("Failed to map %s: %s\n", infile, strerror(errno)); close(infd); inhdr = inbuf; if (memcmp(&inhdr->e_ident, ELFMAG, SELFMAG) != 0) - error(EXIT_FAILURE, 0, "Not an ELF file"); + fail("Not an ELF file\n"); if (inhdr->e_ident[EI_CLASS] != ELFCLASS32) - error(EXIT_FAILURE, 0, "Unsupported ELF class"); + fail("Unsupported ELF class\n"); swap = inhdr->e_ident[EI_DATA] != HOST_ORDER; if (read_elf_half(inhdr->e_type, swap) != ET_DYN) - error(EXIT_FAILURE, 0, "Not a shared object"); + fail("Not a shared object\n"); - if (read_elf_half(inhdr->e_machine, swap) != EM_ARM) { - error(EXIT_FAILURE, 0, "Unsupported architecture %#x", - inhdr->e_machine); - } + if (read_elf_half(inhdr->e_machine, swap) != EM_ARM) + fail("Unsupported architecture %#x\n", inhdr->e_machine); e_flags = read_elf_word(inhdr->e_flags, swap); if (EF_ARM_EABI_VERSION(e_flags) != EF_ARM_EABI_VER5) { - error(EXIT_FAILURE, 0, "Unsupported EABI version %#x", - EF_ARM_EABI_VERSION(e_flags)); + fail("Unsupported EABI version %#x\n", + EF_ARM_EABI_VERSION(e_flags)); } if (e_flags & EF_ARM_ABI_FLOAT_HARD) - error(EXIT_FAILURE, 0, - "Unexpected hard-float flag set in e_flags"); + fail("Unexpected hard-float flag set in e_flags\n"); clear_soft_float = !!(e_flags & EF_ARM_ABI_FLOAT_SOFT); outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (outfd < 0) - error(EXIT_FAILURE, errno, "Cannot open %s", outfile); + fail("Cannot open %s: %s\n", outfile, strerror(errno)); if (ftruncate(outfd, stat.st_size) != 0) - error(EXIT_FAILURE, errno, "Cannot truncate %s", outfile); + fail("Cannot truncate %s: %s\n", outfile, strerror(errno)); outbuf = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, outfd, 0); if (outbuf == MAP_FAILED) - error(EXIT_FAILURE, errno, "Failed to map %s", outfile); + fail("Failed to map %s: %s\n", outfile, strerror(errno)); close(outfd); @@ -195,7 +205,7 @@ int main(int argc, char **argv) } if (msync(outbuf, stat.st_size, MS_SYNC) != 0) - error(EXIT_FAILURE, errno, "Failed to sync %s", outfile); + fail("Failed to sync %s: %s\n", outfile, strerror(errno)); return EXIT_SUCCESS; } diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0f6edb1..318175f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -23,9 +23,9 @@ config ARM64 select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS select COMMON_CLK - select EDAC_SUPPORT select CPU_PM if (SUSPEND || CPU_IDLE) select DCACHE_WORD_ACCESS + select EDAC_SUPPORT select GENERIC_ALLOCATOR select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST if SMP diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts index 83578e7..4c55833 100644 --- a/arch/arm64/boot/dts/apm/apm-mustang.dts +++ b/arch/arm64/boot/dts/apm/apm-mustang.dts @@ -23,6 +23,16 @@ device_type = "memory"; reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */ }; + + gpio-keys { + compatible = "gpio-keys"; + button@1 { + label = "POWER"; + linux,code = <116>; + linux,input-type = <0x1>; + interrupts = <0x0 0x2d 0x1>; + }; + }; }; &pcie0clk { diff --git a/arch/arm64/boot/dts/arm/Makefile b/arch/arm64/boot/dts/arm/Makefile index c5c98b9..bb3c072 100644 --- a/arch/arm64/boot/dts/arm/Makefile +++ b/arch/arm64/boot/dts/arm/Makefile @@ -1,6 +1,7 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += foundation-v8.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb juno-r1.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb +dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2f-1xv7-ca53x2.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts new file mode 100644 index 0000000..5b1d018 --- /dev/null +++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts @@ -0,0 +1,191 @@ +/* + * ARM Ltd. Versatile Express + * + * LogicTile Express 20MG + * V2F-1XV7 + * + * Cortex-A53 (2 cores) Soft Macrocell Model + * + * HBI-0247C + */ + +/dts-v1/; + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + model = "V2F-1XV7 Cortex-A53x2 SMM"; + arm,hbi = <0x247>; + arm,vexpress,site = <0xf>; + compatible = "arm,vexpress,v2f-1xv7,ca53x2", "arm,vexpress,v2f-1xv7", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + stdout-path = "serial0:38400n8"; + }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + i2c0 = &v2m_i2c_dvi; + i2c1 = &v2m_i2c_pcie; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0>; + next-level-cache = <&L2_0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 1>; + next-level-cache = <&L2_0>; + }; + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0 0x80000000 0 0x80000000>; /* 2GB @ 2GB */ + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x2c001000 0 0x1000>, + <0 0x2c002000 0 0x2000>, + <0 0x2c004000 0 0x2000>, + <0 0x2c006000 0 0x2000>; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + }; + + dcc { + compatible = "arm,vexpress,config-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + smbclk: osc@4 { + /* SMC clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 4>; + freq-range = <40000000 40000000>; + #clock-cells = <0>; + clock-output-names = "smclk"; + }; + + volt@0 { + /* VIO to expansion board above */ + compatible = "arm,vexpress-volt"; + arm,vexpress-sysreg,func = <2 0>; + regulator-name = "VIO_UP"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + volt@1 { + /* 12V from power connector J6 */ + compatible = "arm,vexpress-volt"; + arm,vexpress-sysreg,func = <2 1>; + regulator-name = "12"; + regulator-always-on; + }; + + temp@0 { + /* FPGA temperature */ + compatible = "arm,vexpress-temp"; + arm,vexpress-sysreg,func = <4 0>; + label = "FPGA"; + }; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, + <0 0 1 &gic GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, + <0 0 2 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, + <0 0 3 &gic GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, + <0 0 4 &gic GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, + <0 0 5 &gic GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, + <0 0 6 &gic GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, + <0 0 7 &gic GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, + <0 0 8 &gic GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <0 0 9 &gic GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <0 0 10 &gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, + <0 0 11 &gic GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <0 0 12 &gic GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <0 0 13 &gic GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, + <0 0 14 &gic GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>, + <0 0 15 &gic GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>, + <0 0 16 &gic GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>, + <0 0 17 &gic GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>, + <0 0 18 &gic GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>, + <0 0 19 &gic GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, + <0 0 20 &gic GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>, + <0 0 21 &gic GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>, + <0 0 22 &gic GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>, + <0 0 23 &gic GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>, + <0 0 24 &gic GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>, + <0 0 25 &gic GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>, + <0 0 26 &gic GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>, + <0 0 27 &gic GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>, + <0 0 28 &gic GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>, + <0 0 29 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>, + <0 0 30 &gic GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>, + <0 0 31 &gic GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>, + <0 0 32 &gic GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>, + <0 0 33 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>, + <0 0 34 &gic GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>, + <0 0 35 &gic GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>, + <0 0 36 &gic GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>, + <0 0 37 &gic GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, + <0 0 38 &gic GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>, + <0 0 39 &gic GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, + <0 0 40 &gic GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, + <0 0 41 &gic GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>, + <0 0 42 &gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + + /include/ "../../../../arm/boot/dts/vexpress-v2m-rs1.dtsi" + }; +}; diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi index d8c0bdc..9cb7cf94 100644 --- a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi +++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi @@ -376,10 +376,19 @@ gic0: interrupt-controller@8010,00000000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; interrupt-controller; reg = <0x8010 0x00000000 0x0 0x010000>, /* GICD */ <0x8010 0x80000000 0x0 0x600000>; /* GICR */ interrupts = <1 9 0xf04>; + + its: gic-its@8010,00020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x8010 0x20000 0x0 0x200000>; + }; }; uaa0: serial@87e0,24000000 { diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f38c94f..4e17e7e 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -83,6 +83,7 @@ CONFIG_BLK_DEV_SD=y CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_CEVA=y CONFIG_AHCI_XGENE=y CONFIG_PATA_PLATFORM=y CONFIG_PATA_OF_PLATFORM=y diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 39248d3..406485e 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -19,6 +19,14 @@ #include <asm/psci.h> #include <asm/smp_plat.h> +/* Macros for consistency checks of the GICC subtable of MADT */ +#define ACPI_MADT_GICC_LENGTH \ + (acpi_gbl_FADT.header.revision < 6 ? 76 : 80) + +#define BAD_MADT_GICC_ENTRY(entry, end) \ + (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) || \ + (entry)->header.length != ACPI_MADT_GICC_LENGTH) + /* Basic configuration for ACPI */ #ifdef CONFIG_ACPI /* ACPI table mapping after acpi_gbl_permanent_mmap is set */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a7691a3..f860bfd 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -352,8 +352,8 @@ el1_inv: // TODO: add support for undefined instructions in kernel mode enable_dbg mov x0, sp + mov x2, x1 mov x1, #BAD_SYNC - mrs x2, esr_el1 b bad_mode ENDPROC(el1_sync) @@ -553,7 +553,7 @@ el0_inv: ct_user_exit mov x0, sp mov x1, #BAD_SYNC - mrs x2, esr_el1 + mov x2, x25 bl bad_mode b ret_to_user ENDPROC(el0_sync) diff --git a/arch/arm64/kernel/entry32.S b/arch/arm64/kernel/entry32.S index bd9bfaa..f332d5d 100644 --- a/arch/arm64/kernel/entry32.S +++ b/arch/arm64/kernel/entry32.S @@ -32,13 +32,11 @@ ENTRY(compat_sys_sigreturn_wrapper) mov x0, sp - mov x27, #0 // prevent syscall restart handling (why) b compat_sys_sigreturn ENDPROC(compat_sys_sigreturn_wrapper) ENTRY(compat_sys_rt_sigreturn_wrapper) mov x0, sp - mov x27, #0 // prevent syscall restart handling (why) b compat_sys_rt_sigreturn ENDPROC(compat_sys_rt_sigreturn_wrapper) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 695801a..50fb469 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -438,7 +438,7 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header, struct acpi_madt_generic_interrupt *processor; processor = (struct acpi_madt_generic_interrupt *)header; - if (BAD_MADT_ENTRY(processor, end)) + if (BAD_MADT_GICC_ENTRY(processor, end)) return -EINVAL; acpi_table_print_madt_entry(header); diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index 9d84feb..773d37a 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile @@ -4,5 +4,3 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ context.o proc.o pageattr.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_ARM64_PTDUMP) += dump.o - -CFLAGS_mmu.o := -I$(srctree)/scripts/dtc/libfdt/ diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index 4dda9bd..e989cee 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c @@ -1464,7 +1464,7 @@ static inline void handle_rx_packet(struct sync_port *port) if (port->write_ts_idx == NBR_IN_DESCR) port->write_ts_idx = 0; idx = port->write_ts_idx++; - do_posix_clock_monotonic_gettime(&port->timestamp[idx]); + ktime_get_ts(&port->timestamp[idx]); port->in_buffer_len += port->inbufchunk; } spin_unlock_irqrestore(&port->lock, flags); diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2a14585..aab7e46 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2231,7 +2231,7 @@ config MIPS_CMP config MIPS_CPS bool "MIPS Coherent Processing System support" - depends on SYS_SUPPORTS_MIPS_CPS && !64BIT + depends on SYS_SUPPORTS_MIPS_CPS select MIPS_CM select MIPS_CPC select MIPS_CPS_PM if HOTPLUG_CPU diff --git a/arch/mips/include/asm/mach-loongson64/mmzone.h b/arch/mips/include/asm/mach-loongson64/mmzone.h index 37c08a2..c9f7e23 100644 --- a/arch/mips/include/asm/mach-loongson64/mmzone.h +++ b/arch/mips/include/asm/mach-loongson64/mmzone.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & - * Insititute of Computing Technology + * Institute of Computing Technology * Author: Xiang Gao, gaoxiang@ict.ac.cn * Huacai Chen, chenhc@lemote.com * Xiaofu Meng, Shuangshuang Zhang diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 2b25d1b..16f1ea9 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -23,6 +23,7 @@ extern int smp_num_siblings; extern cpumask_t cpu_sibling_map[]; extern cpumask_t cpu_core_map[]; +extern cpumask_t cpu_foreign_map; #define raw_smp_processor_id() (current_thread_info()->cpu) diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index c0c5e59..d8f9b35 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -600,7 +600,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, break; case blezl_op: /* not really i_format */ - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) goto sigill_r6; case blez_op: /* @@ -635,7 +635,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, break; case bgtzl_op: - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) goto sigill_r6; case bgtz_op: /* diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 55b759a..1b6ca63 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -60,7 +60,7 @@ LEAF(mips_cps_core_entry) nop /* This is an NMI */ - la k0, nmi_handler + PTR_LA k0, nmi_handler jr k0 nop @@ -107,10 +107,10 @@ not_nmi: mul t1, t1, t0 mul t1, t1, t2 - li a0, KSEG0 - add a1, a0, t1 + li a0, CKSEG0 + PTR_ADD a1, a0, t1 1: cache Index_Store_Tag_I, 0(a0) - add a0, a0, t0 + PTR_ADD a0, a0, t0 bne a0, a1, 1b nop icache_done: @@ -134,12 +134,12 @@ icache_done: mul t1, t1, t0 mul t1, t1, t2 - li a0, KSEG0 - addu a1, a0, t1 - subu a1, a1, t0 + li a0, CKSEG0 + PTR_ADDU a1, a0, t1 + PTR_SUBU a1, a1, t0 1: cache Index_Store_Tag_D, 0(a0) bne a0, a1, 1b - add a0, a0, t0 + PTR_ADD a0, a0, t0 dcache_done: /* Set Kseg0 CCA to that in s0 */ @@ -152,11 +152,11 @@ dcache_done: /* Enter the coherent domain */ li t0, 0xff - sw t0, GCR_CL_COHERENCE_OFS(v1) + PTR_S t0, GCR_CL_COHERENCE_OFS(v1) ehb /* Jump to kseg0 */ - la t0, 1f + PTR_LA t0, 1f jr t0 nop @@ -178,9 +178,9 @@ dcache_done: nop /* Off we go! */ - lw t1, VPEBOOTCFG_PC(v0) - lw gp, VPEBOOTCFG_GP(v0) - lw sp, VPEBOOTCFG_SP(v0) + PTR_L t1, VPEBOOTCFG_PC(v0) + PTR_L gp, VPEBOOTCFG_GP(v0) + PTR_L sp, VPEBOOTCFG_SP(v0) jr t1 nop END(mips_cps_core_entry) @@ -217,7 +217,7 @@ LEAF(excep_intex) .org 0x480 LEAF(excep_ejtag) - la k0, ejtag_debug_handler + PTR_LA k0, ejtag_debug_handler jr k0 nop END(excep_ejtag) @@ -229,7 +229,7 @@ LEAF(mips_cps_core_init) nop .set push - .set mips32r2 + .set mips64r2 .set mt /* Only allow 1 TC per VPE to execute... */ @@ -237,7 +237,7 @@ LEAF(mips_cps_core_init) /* ...and for the moment only 1 VPE */ dvpe - la t1, 1f + PTR_LA t1, 1f jr.hb t1 nop @@ -250,25 +250,25 @@ LEAF(mips_cps_core_init) mfc0 t0, CP0_MVPCONF0 srl t0, t0, MVPCONF0_PVPE_SHIFT andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT) - addiu t7, t0, 1 + addiu ta3, t0, 1 /* If there's only 1, we're done */ beqz t0, 2f nop /* Loop through each VPE within this core */ - li t5, 1 + li ta1, 1 1: /* Operate on the appropriate TC */ - mtc0 t5, CP0_VPECONTROL + mtc0 ta1, CP0_VPECONTROL ehb /* Bind TC to VPE (1:1 TC:VPE mapping) */ - mttc0 t5, CP0_TCBIND + mttc0 ta1, CP0_TCBIND /* Set exclusive TC, non-active, master */ li t0, VPECONF0_MVP - sll t1, t5, VPECONF0_XTC_SHIFT + sll t1, ta1, VPECONF0_XTC_SHIFT or t0, t0, t1 mttc0 t0, CP0_VPECONF0 @@ -280,8 +280,8 @@ LEAF(mips_cps_core_init) mttc0 t0, CP0_TCHALT /* Next VPE */ - addiu t5, t5, 1 - slt t0, t5, t7 + addiu ta1, ta1, 1 + slt t0, ta1, ta3 bnez t0, 1b nop @@ -298,19 +298,19 @@ LEAF(mips_cps_core_init) LEAF(mips_cps_boot_vpes) /* Retrieve CM base address */ - la t0, mips_cm_base - lw t0, 0(t0) + PTR_LA t0, mips_cm_base + PTR_L t0, 0(t0) /* Calculate a pointer to this cores struct core_boot_config */ - lw t0, GCR_CL_ID_OFS(t0) + PTR_L t0, GCR_CL_ID_OFS(t0) li t1, COREBOOTCFG_SIZE mul t0, t0, t1 - la t1, mips_cps_core_bootcfg - lw t1, 0(t1) - addu t0, t0, t1 + PTR_LA t1, mips_cps_core_bootcfg + PTR_L t1, 0(t1) + PTR_ADDU t0, t0, t1 /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ - has_mt t6, 1f + has_mt ta2, 1f li t9, 0 /* Find the number of VPEs present in the core */ @@ -334,24 +334,24 @@ LEAF(mips_cps_boot_vpes) 1: /* Calculate a pointer to this VPEs struct vpe_boot_config */ li t1, VPEBOOTCFG_SIZE mul v0, t9, t1 - lw t7, COREBOOTCFG_VPECONFIG(t0) - addu v0, v0, t7 + PTR_L ta3, COREBOOTCFG_VPECONFIG(t0) + PTR_ADDU v0, v0, ta3 #ifdef CONFIG_MIPS_MT /* If the core doesn't support MT then return */ - bnez t6, 1f + bnez ta2, 1f nop jr ra nop .set push - .set mips32r2 + .set mips64r2 .set mt 1: /* Enter VPE configuration state */ dvpe - la t1, 1f + PTR_LA t1, 1f jr.hb t1 nop 1: mfc0 t1, CP0_MVPCONTROL @@ -360,12 +360,12 @@ LEAF(mips_cps_boot_vpes) ehb /* Loop through each VPE */ - lw t6, COREBOOTCFG_VPEMASK(t0) - move t8, t6 - li t5, 0 + PTR_L ta2, COREBOOTCFG_VPEMASK(t0) + move t8, ta2 + li ta1, 0 /* Check whether the VPE should be running. If not, skip it */ -1: andi t0, t6, 1 +1: andi t0, ta2, 1 beqz t0, 2f nop @@ -373,7 +373,7 @@ LEAF(mips_cps_boot_vpes) mfc0 t0, CP0_VPECONTROL ori t0, t0, VPECONTROL_TARGTC xori t0, t0, VPECONTROL_TARGTC - or t0, t0, t5 + or t0, t0, ta1 mtc0 t0, CP0_VPECONTROL ehb @@ -384,8 +384,8 @@ LEAF(mips_cps_boot_vpes) /* Calculate a pointer to the VPEs struct vpe_boot_config */ li t0, VPEBOOTCFG_SIZE - mul t0, t0, t5 - addu t0, t0, t7 + mul t0, t0, ta1 + addu t0, t0, ta3 /* Set the TC restart PC */ lw t1, VPEBOOTCFG_PC(t0) @@ -423,9 +423,9 @@ LEAF(mips_cps_boot_vpes) mttc0 t0, CP0_VPECONF0 /* Next VPE */ -2: srl t6, t6, 1 - addiu t5, t5, 1 - bnez t6, 1b +2: srl ta2, ta2, 1 + addiu ta1, ta1, 1 + bnez ta2, 1b nop /* Leave VPE configuration state */ @@ -445,7 +445,7 @@ LEAF(mips_cps_boot_vpes) /* This VPE should be offline, halt the TC */ li t0, TCHALT_H mtc0 t0, CP0_TCHALT - la t0, 1f + PTR_LA t0, 1f 1: jr.hb t0 nop @@ -466,10 +466,10 @@ LEAF(mips_cps_boot_vpes) .set noat lw $1, TI_CPU(gp) sll $1, $1, LONGLOG - la \dest, __per_cpu_offset + PTR_LA \dest, __per_cpu_offset addu $1, $1, \dest lw $1, 0($1) - la \dest, cps_cpu_state + PTR_LA \dest, cps_cpu_state addu \dest, \dest, $1 .set pop .endm diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 6e8de80..4cc1350 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -73,10 +73,11 @@ NESTED(handle_sys, PT_SIZE, sp) .set noreorder .set nomacro -1: user_lw(t5, 16(t0)) # argument #5 from usp -4: user_lw(t6, 20(t0)) # argument #6 from usp -3: user_lw(t7, 24(t0)) # argument #7 from usp -2: user_lw(t8, 28(t0)) # argument #8 from usp +load_a4: user_lw(t5, 16(t0)) # argument #5 from usp +load_a5: user_lw(t6, 20(t0)) # argument #6 from usp +load_a6: user_lw(t7, 24(t0)) # argument #7 from usp +load_a7: user_lw(t8, 28(t0)) # argument #8 from usp +loads_done: sw t5, 16(sp) # argument #5 to ksp sw t6, 20(sp) # argument #6 to ksp @@ -85,10 +86,10 @@ NESTED(handle_sys, PT_SIZE, sp) .set pop .section __ex_table,"a" - PTR 1b,bad_stack - PTR 2b,bad_stack - PTR 3b,bad_stack - PTR 4b,bad_stack + PTR load_a4, bad_stack_a4 + PTR load_a5, bad_stack_a5 + PTR load_a6, bad_stack_a6 + PTR load_a7, bad_stack_a7 .previous lw t0, TI_FLAGS($28) # syscall tracing enabled? @@ -153,8 +154,8 @@ syscall_trace_entry: /* ------------------------------------------------------------------------ */ /* - * The stackpointer for a call with more than 4 arguments is bad. - * We probably should handle this case a bit more drastic. + * Our open-coded access area sanity test for the stack pointer + * failed. We probably should handle this case a bit more drastic. */ bad_stack: li v0, EFAULT @@ -163,6 +164,22 @@ bad_stack: sw t0, PT_R7(sp) j o32_syscall_exit +bad_stack_a4: + li t5, 0 + b load_a5 + +bad_stack_a5: + li t6, 0 + b load_a6 + +bad_stack_a6: + li t7, 0 + b load_a7 + +bad_stack_a7: + li t8, 0 + b loads_done + /* * The system call does not exist in this kernel */ diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d07b210..f543ff4 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -69,16 +69,17 @@ NESTED(handle_sys, PT_SIZE, sp) daddu t1, t0, 32 bltz t1, bad_stack -1: lw a4, 16(t0) # argument #5 from usp -2: lw a5, 20(t0) # argument #6 from usp -3: lw a6, 24(t0) # argument #7 from usp -4: lw a7, 28(t0) # argument #8 from usp (for indirect syscalls) +load_a4: lw a4, 16(t0) # argument #5 from usp +load_a5: lw a5, 20(t0) # argument #6 from usp +load_a6: lw a6, 24(t0) # argument #7 from usp +load_a7: lw a7, 28(t0) # argument #8 from usp +loads_done: .section __ex_table,"a" - PTR 1b, bad_stack - PTR 2b, bad_stack - PTR 3b, bad_stack - PTR 4b, bad_stack + PTR load_a4, bad_stack_a4 + PTR load_a5, bad_stack_a5 + PTR load_a6, bad_stack_a6 + PTR load_a7, bad_stack_a7 .previous li t1, _TIF_WORK_SYSCALL_ENTRY @@ -167,6 +168,22 @@ bad_stack: sd t0, PT_R7(sp) j o32_syscall_exit +bad_stack_a4: + li a4, 0 + b load_a5 + +bad_stack_a5: + li a5, 0 + b load_a6 + +bad_stack_a6: + li a6, 0 + b load_a7 + +bad_stack_a7: + li a7, 0 + b loads_done + not_o32_scall: /* * This is not an o32 compatibility syscall, pass it on @@ -383,7 +400,7 @@ EXPORT(sys32_call_table) PTR sys_connect /* 4170 */ PTR sys_getpeername PTR sys_getsockname - PTR sys_getsockopt + PTR compat_sys_getsockopt PTR sys_listen PTR compat_sys_recv /* 4175 */ PTR compat_sys_recvfrom diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index be73c49..008b337 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -337,6 +337,11 @@ static void __init bootmem_init(void) min_low_pfn = start; if (end <= reserved_end) continue; +#ifdef CONFIG_BLK_DEV_INITRD + /* mapstart should be after initrd_end */ + if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end))) + continue; +#endif if (start >= mapstart) continue; mapstart = max(reserved_end, start); @@ -366,14 +371,6 @@ static void __init bootmem_init(void) max_low_pfn = PFN_DOWN(HIGHMEM_START); } -#ifdef CONFIG_BLK_DEV_INITRD - /* - * mapstart should be after initrd_end - */ - if (initrd_end) - mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end))); -#endif - /* * Initialize the boot-time allocator with low memory only. */ diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 4251d39..c889377 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -133,7 +133,7 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) /* * Patch the start of mips_cps_core_entry to provide: * - * v0 = CM base address + * v1 = CM base address * s0 = kseg0 CCA */ entry_code = (u32 *)&mips_cps_core_entry; @@ -369,7 +369,7 @@ void play_dead(void) static void wait_for_sibling_halt(void *ptr_cpu) { - unsigned cpu = (unsigned)ptr_cpu; + unsigned cpu = (unsigned long)ptr_cpu; unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); unsigned halted; unsigned long flags; @@ -430,7 +430,7 @@ static void cps_cpu_die(unsigned int cpu) */ err = smp_call_function_single(cpu_death_sibling, wait_for_sibling_halt, - (void *)cpu, 1); + (void *)(unsigned long)cpu, 1); if (err) panic("Failed to call remote sibling CPU\n"); } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index faa46eb..d0744cc 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -63,6 +63,13 @@ EXPORT_SYMBOL(cpu_sibling_map); cpumask_t cpu_core_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_core_map); +/* + * A logcal cpu mask containing only one VPE per core to + * reduce the number of IPIs on large MT systems. + */ +cpumask_t cpu_foreign_map __read_mostly; +EXPORT_SYMBOL(cpu_foreign_map); + /* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; @@ -103,6 +110,29 @@ static inline void set_cpu_core_map(int cpu) } } +/* + * Calculate a new cpu_foreign_map mask whenever a + * new cpu appears or disappears. + */ +static inline void calculate_cpu_foreign_map(void) +{ + int i, k, core_present; + cpumask_t temp_foreign_map; + + /* Re-calculate the mask */ + for_each_online_cpu(i) { + core_present = 0; + for_each_cpu(k, &temp_foreign_map) + if (cpu_data[i].package == cpu_data[k].package && + cpu_data[i].core == cpu_data[k].core) + core_present = 1; + if (!core_present) + cpumask_set_cpu(i, &temp_foreign_map); + } + + cpumask_copy(&cpu_foreign_map, &temp_foreign_map); +} + struct plat_smp_ops *mp_ops; EXPORT_SYMBOL(mp_ops); @@ -146,6 +176,8 @@ asmlinkage void start_secondary(void) set_cpu_sibling_map(cpu); set_cpu_core_map(cpu); + calculate_cpu_foreign_map(); + cpumask_set_cpu(cpu, &cpu_callin_map); synchronise_count_slave(cpu); @@ -173,9 +205,18 @@ void __irq_entry smp_call_function_interrupt(void) static void stop_this_cpu(void *dummy) { /* - * Remove this CPU: + * Remove this CPU. Be a bit slow here and + * set the bits for every online CPU so we don't miss + * any IPI whilst taking this VPE down. */ + + cpumask_copy(&cpu_foreign_map, cpu_online_mask); + + /* Make it visible to every other CPU */ + smp_mb(); + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); local_irq_disable(); while (1); } @@ -197,6 +238,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) mp_ops->prepare_cpus(max_cpus); set_cpu_sibling_map(0); set_cpu_core_map(0); + calculate_cpu_foreign_map(); #ifndef CONFIG_HOTPLUG_CPU init_cpu_present(cpu_possible_mask); #endif diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 2a7b38e..e207a43 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2130,10 +2130,10 @@ void per_cpu_trap_init(bool is_boot_cpu) BUG_ON(current->mm); enter_lazy_tlb(&init_mm, current); - /* Boot CPU's cache setup in setup_arch(). */ - if (!is_boot_cpu) - cpu_cache_init(); - tlb_init(); + /* Boot CPU's cache setup in setup_arch(). */ + if (!is_boot_cpu) + cpu_cache_init(); + tlb_init(); TLBMISS_HANDLER_SETUP(); } diff --git a/arch/mips/loongson64/common/bonito-irq.c b/arch/mips/loongson64/common/bonito-irq.c index cc0e4fd..4e116d2 100644 --- a/arch/mips/loongson64/common/bonito-irq.c +++ b/arch/mips/loongson64/common/bonito-irq.c @@ -3,7 +3,7 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c index 72fed00..01fbed1 100644 --- a/arch/mips/loongson64/common/cmdline.c +++ b/arch/mips/loongson64/common/cmdline.c @@ -6,7 +6,7 @@ * Copyright 2003 ICT CAS * Author: Michael Guo <guoyi@ict.ac.cn> * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * Copyright (C) 2009 Lemote Inc. diff --git a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c index 12c75db..8750370 100644 --- a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c @@ -1,7 +1,7 @@ /* * CS5536 General timer functions * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Yanhua, yanh@lemote.com * * Copyright (C) 2009 Lemote Inc. diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c index 22f04ca..f6c44dd 100644 --- a/arch/mips/loongson64/common/env.c +++ b/arch/mips/loongson64/common/env.c @@ -6,7 +6,7 @@ * Copyright 2003 ICT CAS * Author: Michael Guo <guoyi@ict.ac.cn> * - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * Copyright (C) 2009 Lemote Inc. diff --git a/arch/mips/loongson64/common/irq.c b/arch/mips/loongson64/common/irq.c index 687003b..d36d969 100644 --- a/arch/mips/loongson64/common/irq.c +++ b/arch/mips/loongson64/common/irq.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/common/setup.c b/arch/mips/loongson64/common/setup.c index d477dd6..2dc5122 100644 --- a/arch/mips/loongson64/common/setup.c +++ b/arch/mips/loongson64/common/setup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/fuloong-2e/irq.c b/arch/mips/loongson64/fuloong-2e/irq.c index ef5ec8f..892963f8 100644 --- a/arch/mips/loongson64/fuloong-2e/irq.c +++ b/arch/mips/loongson64/fuloong-2e/irq.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * * This program is free software; you can redistribute it and/or modify it diff --git a/arch/mips/loongson64/lemote-2f/clock.c b/arch/mips/loongson64/lemote-2f/clock.c index 462e34d..a78fb65 100644 --- a/arch/mips/loongson64/lemote-2f/clock.c +++ b/arch/mips/loongson64/lemote-2f/clock.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2006 - 2008 Lemote Inc. & Institute of Computing Technology * Author: Yanhua, yanh@lemote.com * * This file is subject to the terms and conditions of the GNU General Public @@ -15,7 +15,7 @@ #include <linux/spinlock.h> #include <asm/clock.h> -#include <asm/mach-loongson/loongson.h> +#include <asm/mach-loongson64/loongson.h> static LIST_HEAD(clock_list); static DEFINE_SPINLOCK(clock_lock); diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c index 12d14ed..6f9e010 100644 --- a/arch/mips/loongson64/loongson-3/numa.c +++ b/arch/mips/loongson64/loongson-3/numa.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & - * Insititute of Computing Technology + * Institute of Computing Technology * Author: Xiang Gao, gaoxiang@ict.ac.cn * Huacai Chen, chenhc@lemote.com * Xiaofu Meng, Shuangshuang Zhang diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 22b9b2c..712f17a 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -451,7 +451,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, /* Fall through */ case jr_op: /* For R6, JR already emulated in jalr_op */ - if (NO_R6EMU && insn.r_format.opcode == jr_op) + if (NO_R6EMU && insn.r_format.func == jr_op) break; *contpc = regs->regs[insn.r_format.rs]; return 1; @@ -551,7 +551,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.next_pc_inc; return 1; case blezl_op: - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) break; case blez_op: @@ -588,7 +588,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.next_pc_inc; return 1; case bgtzl_op: - if (NO_R6EMU) + if (!insn.i_format.rt && NO_R6EMU) break; case bgtz_op: /* diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 7f660dc..fbea443 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -37,6 +37,7 @@ #include <asm/cacheflush.h> /* for run_uncached() */ #include <asm/traps.h> #include <asm/dma-coherence.h> +#include <asm/mips-cm.h> /* * Special Variant of smp_call_function for use by cache functions: @@ -51,9 +52,16 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info) { preempt_disable(); -#ifndef CONFIG_MIPS_MT_SMP - smp_call_function(func, info, 1); -#endif + /* + * The Coherent Manager propagates address-based cache ops to other + * cores but not index-based ops. However, r4k_on_each_cpu is used + * in both cases so there is no easy way to tell what kind of op is + * executed to the other cores. The best we can probably do is + * to restrict that call when a CM is not present because both + * CM-based SMP protocols (CMP & CPS) restrict index-based cache ops. + */ + if (!mips_cm_present()) + smp_call_function_many(&cpu_foreign_map, func, info, 1); func(info); preempt_enable(); } @@ -937,7 +945,9 @@ static void b5k_instruction_hazard(void) } static char *way_string[] = { NULL, "direct mapped", "2-way", - "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" + "3-way", "4-way", "5-way", "6-way", "7-way", "8-way", + "9-way", "10-way", "11-way", "12-way", + "13-way", "14-way", "15-way", "16-way", }; static void probe_pcache(void) diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 185e682..5625b19 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -119,18 +119,24 @@ void read_persistent_clock(struct timespec *ts) int get_c0_fdc_int(void) { - int mips_cpu_fdc_irq; + /* + * Some cores claim the FDC is routable through the GIC, but it doesn't + * actually seem to be connected for those Malta bitstreams. + */ + switch (current_cpu_type()) { + case CPU_INTERAPTIV: + case CPU_PROAPTIV: + return -1; + }; if (cpu_has_veic) - mips_cpu_fdc_irq = -1; + return -1; else if (gic_present) - mips_cpu_fdc_irq = gic_get_c0_fdc_int(); + return gic_get_c0_fdc_int(); else if (cp0_fdc_irq >= 0) - mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq; + return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; else - mips_cpu_fdc_irq = -1; - - return mips_cpu_fdc_irq; + return -1; } int get_c0_perfcount_int(void) diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c index d2dc836..8bd8ebb 100644 --- a/arch/mips/pistachio/init.c +++ b/arch/mips/pistachio/init.c @@ -63,13 +63,19 @@ void __init plat_mem_setup(void) plat_setup_iocoherency(); } -#define DEFAULT_CPC_BASE_ADDR 0x1bde0000 +#define DEFAULT_CPC_BASE_ADDR 0x1bde0000 +#define DEFAULT_CDMM_BASE_ADDR 0x1bdd0000 phys_addr_t mips_cpc_default_phys_base(void) { return DEFAULT_CPC_BASE_ADDR; } +phys_addr_t mips_cdmm_phys_base(void) +{ + return DEFAULT_CDMM_BASE_ADDR; +} + static void __init mips_nmi_setup(void) { void *base; diff --git a/arch/mips/pistachio/time.c b/arch/mips/pistachio/time.c index 67889fc..7c73fcb 100644 --- a/arch/mips/pistachio/time.c +++ b/arch/mips/pistachio/time.c @@ -27,6 +27,11 @@ int get_c0_perfcount_int(void) return gic_get_c0_perfcount_int(); } +int get_c0_fdc_int(void) +{ + return gic_get_c0_fdc_int(); +} + void __init plat_time_init(void) { struct device_node *np; diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 0a18375..f93c4a4 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -16,7 +16,7 @@ #include <asm/processor.h> #include <asm/cache.h> -extern spinlock_t pa_dbit_lock; +extern spinlock_t pa_tlb_lock; /* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel @@ -33,6 +33,19 @@ extern spinlock_t pa_dbit_lock; */ #define kern_addr_valid(addr) (1) +/* Purge data and instruction TLB entries. Must be called holding + * the pa_tlb_lock. The TLB purge instructions are slow on SMP + * machines since the purge must be broadcast to all CPUs. + */ + +static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) +{ + mtsp(mm->context, 1); + pdtlb(addr); + if (unlikely(split_tlb)) + pitlb(addr); +} + /* Certain architectures need to do special things when PTEs * within a page table are directly modified. Thus, the following * hook is made available. @@ -42,15 +55,20 @@ extern spinlock_t pa_dbit_lock; *(pteptr) = (pteval); \ } while(0) -extern void purge_tlb_entries(struct mm_struct *, unsigned long); +#define pte_inserted(x) \ + ((pte_val(x) & (_PAGE_PRESENT|_PAGE_ACCESSED)) \ + == (_PAGE_PRESENT|_PAGE_ACCESSED)) -#define set_pte_at(mm, addr, ptep, pteval) \ - do { \ +#define set_pte_at(mm, addr, ptep, pteval) \ + do { \ + pte_t old_pte; \ unsigned long flags; \ - spin_lock_irqsave(&pa_dbit_lock, flags); \ - set_pte(ptep, pteval); \ - purge_tlb_entries(mm, addr); \ - spin_unlock_irqrestore(&pa_dbit_lock, flags); \ + spin_lock_irqsave(&pa_tlb_lock, flags); \ + old_pte = *ptep; \ + set_pte(ptep, pteval); \ + if (pte_inserted(old_pte)) \ + purge_tlb_entries(mm, addr); \ + spin_unlock_irqrestore(&pa_tlb_lock, flags); \ } while (0) #endif /* !__ASSEMBLY__ */ @@ -268,7 +286,7 @@ extern unsigned long *empty_zero_page; #define pte_none(x) (pte_val(x) == 0) #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) -#define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) +#define pte_clear(mm, addr, xp) set_pte_at(mm, addr, xp, __pte(0)) #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) #define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT) @@ -435,15 +453,15 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned if (!pte_young(*ptep)) return 0; - spin_lock_irqsave(&pa_dbit_lock, flags); + spin_lock_irqsave(&pa_tlb_lock, flags); pte = *ptep; if (!pte_young(pte)) { - spin_unlock_irqrestore(&pa_dbit_lock, flags); + spin_unlock_irqrestore(&pa_tlb_lock, flags); return 0; } set_pte(ptep, pte_mkold(pte)); purge_tlb_entries(vma->vm_mm, addr); - spin_unlock_irqrestore(&pa_dbit_lock, flags); + spin_unlock_irqrestore(&pa_tlb_lock, flags); return 1; } @@ -453,11 +471,12 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t old_pte; unsigned long flags; - spin_lock_irqsave(&pa_dbit_lock, flags); + spin_lock_irqsave(&pa_tlb_lock, flags); old_pte = *ptep; - pte_clear(mm,addr,ptep); - purge_tlb_entries(mm, addr); - spin_unlock_irqrestore(&pa_dbit_lock, flags); + set_pte(ptep, __pte(0)); + if (pte_inserted(old_pte)) + purge_tlb_entries(mm, addr); + spin_unlock_irqrestore(&pa_tlb_lock, flags); return old_pte; } @@ -465,10 +484,10 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { unsigned long flags; - spin_lock_irqsave(&pa_dbit_lock, flags); + spin_lock_irqsave(&pa_tlb_lock, flags); set_pte(ptep, pte_wrprotect(*ptep)); purge_tlb_entries(mm, addr); - spin_unlock_irqrestore(&pa_dbit_lock, flags); + spin_unlock_irqrestore(&pa_tlb_lock, flags); } #define pte_same(A,B) (pte_val(A) == pte_val(B)) diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index 9d086a5..e84b964 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h @@ -13,6 +13,9 @@ * active at any one time on the Merced bus. This tlb purge * synchronisation is fairly lightweight and harmless so we activate * it on all systems not just the N class. + + * It is also used to ensure PTE updates are atomic and consistent + * with the TLB. */ extern spinlock_t pa_tlb_lock; @@ -24,20 +27,24 @@ extern void flush_tlb_all_local(void *); #define smp_flush_tlb_all() flush_tlb_all() +int __flush_tlb_range(unsigned long sid, + unsigned long start, unsigned long end); + +#define flush_tlb_range(vma, start, end) \ + __flush_tlb_range((vma)->vm_mm->context, start, end) + +#define flush_tlb_kernel_range(start, end) \ + __flush_tlb_range(0, start, end) + /* * flush_tlb_mm() * - * XXX This code is NOT valid for HP-UX compatibility processes, - * (although it will probably work 99% of the time). HP-UX - * processes are free to play with the space id's and save them - * over long periods of time, etc. so we have to preserve the - * space and just flush the entire tlb. We need to check the - * personality in order to do that, but the personality is not - * currently being set correctly. - * - * Of course, Linux processes could do the same thing, but - * we don't support that (and the compilers, dynamic linker, - * etc. do not do that). + * The code to switch to a new context is NOT valid for processes + * which play with the space id's. Thus, we have to preserve the + * space and just flush the entire tlb. However, the compilers, + * dynamic linker, etc, do not manipulate space id's, so there + * could be a significant performance benefit in switching contexts + * and not flushing the whole tlb. */ static inline void flush_tlb_mm(struct mm_struct *mm) @@ -45,10 +52,18 @@ static inline void flush_tlb_mm(struct mm_struct *mm) BUG_ON(mm == &init_mm); /* Should never happen */ #if 1 || defined(CONFIG_SMP) + /* Except for very small threads, flushing the whole TLB is + * faster than using __flush_tlb_range. The pdtlb and pitlb + * instructions are very slow because of the TLB broadcast. + * It might be faster to do local range flushes on all CPUs + * on PA 2.0 systems. + */ flush_tlb_all(); #else /* FIXME: currently broken, causing space id and protection ids - * to go out of sync, resulting in faults on userspace accesses. + * to go out of sync, resulting in faults on userspace accesses. + * This approach needs further investigation since running many + * small applications (e.g., GCC testsuite) is faster on HP-UX. */ if (mm) { if (mm->context != 0) @@ -65,22 +80,12 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, { unsigned long flags, sid; - /* For one page, it's not worth testing the split_tlb variable */ - - mb(); sid = vma->vm_mm->context; purge_tlb_start(flags); mtsp(sid, 1); pdtlb(addr); - pitlb(addr); + if (unlikely(split_tlb)) + pitlb(addr); purge_tlb_end(flags); } - -void __flush_tlb_range(unsigned long sid, - unsigned long start, unsigned long end); - -#define flush_tlb_range(vma,start,end) __flush_tlb_range((vma)->vm_mm->context,start,end) - -#define flush_tlb_kernel_range(start, end) __flush_tlb_range(0,start,end) - #endif diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index f6448c7..cda6dbb 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -342,12 +342,15 @@ EXPORT_SYMBOL(flush_data_cache_local); EXPORT_SYMBOL(flush_kernel_icache_range_asm); #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ -int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; +static unsigned long parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; + +#define FLUSH_TLB_THRESHOLD (2*1024*1024) /* 2MB initial TLB threshold */ +static unsigned long parisc_tlb_flush_threshold __read_mostly = FLUSH_TLB_THRESHOLD; void __init parisc_setup_cache_timing(void) { unsigned long rangetime, alltime; - unsigned long size; + unsigned long size, start; alltime = mfctl(16); flush_data_cache(); @@ -364,14 +367,43 @@ void __init parisc_setup_cache_timing(void) /* Racy, but if we see an intermediate value, it's ok too... */ parisc_cache_flush_threshold = size * alltime / rangetime; - parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1); + parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold); if (!parisc_cache_flush_threshold) parisc_cache_flush_threshold = FLUSH_THRESHOLD; if (parisc_cache_flush_threshold > cache_info.dc_size) parisc_cache_flush_threshold = cache_info.dc_size; - printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); + printk(KERN_INFO "Setting cache flush threshold to %lu kB\n", + parisc_cache_flush_threshold/1024); + + /* calculate TLB flush threshold */ + + alltime = mfctl(16); + flush_tlb_all(); + alltime = mfctl(16) - alltime; + + size = PAGE_SIZE; + start = (unsigned long) _text; + rangetime = mfctl(16); + while (start < (unsigned long) _end) { + flush_tlb_kernel_range(start, start + PAGE_SIZE); + start += PAGE_SIZE; + size += PAGE_SIZE; + } + rangetime = mfctl(16) - rangetime; + + printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n", + alltime, size, rangetime); + + parisc_tlb_flush_threshold = size * alltime / rangetime; + parisc_tlb_flush_threshold *= num_online_cpus(); + parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold); + if (!parisc_tlb_flush_threshold) + parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; + + printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n", + parisc_tlb_flush_threshold/1024); } extern void purge_kernel_dcache_page_asm(unsigned long); @@ -403,48 +435,45 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, } EXPORT_SYMBOL(copy_user_page); -void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) -{ - unsigned long flags; - - /* Note: purge_tlb_entries can be called at startup with - no context. */ - - purge_tlb_start(flags); - mtsp(mm->context, 1); - pdtlb(addr); - pitlb(addr); - purge_tlb_end(flags); -} -EXPORT_SYMBOL(purge_tlb_entries); - -void __flush_tlb_range(unsigned long sid, unsigned long start, - unsigned long end) +/* __flush_tlb_range() + * + * returns 1 if all TLBs were flushed. + */ +int __flush_tlb_range(unsigned long sid, unsigned long start, + unsigned long end) { - unsigned long npages; + unsigned long flags, size; - npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */ + size = (end - start); + if (size >= parisc_tlb_flush_threshold) { flush_tlb_all(); - else { - unsigned long flags; + return 1; + } + /* Purge TLB entries for small ranges using the pdtlb and + pitlb instructions. These instructions execute locally + but cause a purge request to be broadcast to other TLBs. */ + if (likely(!split_tlb)) { + while (start < end) { + purge_tlb_start(flags); + mtsp(sid, 1); + pdtlb(start); + purge_tlb_end(flags); + start += PAGE_SIZE; + } + return 0; + } + + /* split TLB case */ + while (start < end) { purge_tlb_start(flags); mtsp(sid, 1); - if (split_tlb) { - while (npages--) { - pdtlb(start); - pitlb(start); - start += PAGE_SIZE; - } - } else { - while (npages--) { - pdtlb(start); - start += PAGE_SIZE; - } - } + pdtlb(start); + pitlb(start); purge_tlb_end(flags); + start += PAGE_SIZE; } + return 0; } static void cacheflush_h_tmp_function(void *dummy) diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 7581961..c5ef408 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -45,7 +45,7 @@ .level 2.0 #endif - .import pa_dbit_lock,data + .import pa_tlb_lock,data /* space_to_prot macro creates a prot id from a space id */ @@ -420,8 +420,8 @@ SHLREG %r9,PxD_VALUE_SHIFT,\pmd extru \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */ - shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd - LDREG %r0(\pmd),\pte /* pmd is now pte */ + shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */ + LDREG %r0(\pmd),\pte bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault .endm @@ -453,57 +453,53 @@ L2_ptep \pgd,\pte,\index,\va,\fault .endm - /* Acquire pa_dbit_lock lock. */ - .macro dbit_lock spc,tmp,tmp1 + /* Acquire pa_tlb_lock lock and recheck page is still present. */ + .macro tlb_lock spc,ptp,pte,tmp,tmp1,fault #ifdef CONFIG_SMP cmpib,COND(=),n 0,\spc,2f - load32 PA(pa_dbit_lock),\tmp + load32 PA(pa_tlb_lock),\tmp 1: LDCW 0(\tmp),\tmp1 cmpib,COND(=) 0,\tmp1,1b nop + LDREG 0(\ptp),\pte + bb,<,n \pte,_PAGE_PRESENT_BIT,2f + b \fault + stw \spc,0(\tmp) 2: #endif .endm - /* Release pa_dbit_lock lock without reloading lock address. */ - .macro dbit_unlock0 spc,tmp + /* Release pa_tlb_lock lock without reloading lock address. */ + .macro tlb_unlock0 spc,tmp #ifdef CONFIG_SMP or,COND(=) %r0,\spc,%r0 stw \spc,0(\tmp) #endif .endm - /* Release pa_dbit_lock lock. */ - .macro dbit_unlock1 spc,tmp + /* Release pa_tlb_lock lock. */ + .macro tlb_unlock1 spc,tmp #ifdef CONFIG_SMP - load32 PA(pa_dbit_lock),\tmp - dbit_unlock0 \spc,\tmp + load32 PA(pa_tlb_lock),\tmp + tlb_unlock0 \spc,\tmp #endif .endm /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and * don't needlessly dirty the cache line if it was already set */ - .macro update_ptep spc,ptep,pte,tmp,tmp1 -#ifdef CONFIG_SMP - or,COND(=) %r0,\spc,%r0 - LDREG 0(\ptep),\pte -#endif + .macro update_accessed ptp,pte,tmp,tmp1 ldi _PAGE_ACCESSED,\tmp1 or \tmp1,\pte,\tmp and,COND(<>) \tmp1,\pte,%r0 - STREG \tmp,0(\ptep) + STREG \tmp,0(\ptp) .endm /* Set the dirty bit (and accessed bit). No need to be * clever, this is only used from the dirty fault */ - .macro update_dirty spc,ptep,pte,tmp -#ifdef CONFIG_SMP - or,COND(=) %r0,\spc,%r0 - LDREG 0(\ptep),\pte -#endif + .macro update_dirty ptp,pte,tmp ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp or \tmp,\pte,\pte - STREG \pte,0(\ptep) + STREG \pte,0(\ptp) .endm /* bitshift difference between a PFN (based on kernel's PAGE_SIZE) @@ -1148,14 +1144,14 @@ dtlb_miss_20w: L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20w + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1174,14 +1170,14 @@ nadtlb_miss_20w: L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20w + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1202,20 +1198,20 @@ dtlb_miss_11: L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_11 + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1235,21 +1231,20 @@ nadtlb_miss_11: L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_11 + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1269,16 +1264,16 @@ dtlb_miss_20: L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20 + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 idtlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1297,16 +1292,16 @@ nadtlb_miss_20: L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20 + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 - idtlbt pte,prot - dbit_unlock1 spc,t0 + idtlbt pte,prot + tlb_unlock1 spc,t0 rfir nop @@ -1406,14 +1401,14 @@ itlb_miss_20w: L3_ptep ptp,pte,t0,va,itlb_fault - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1430,14 +1425,14 @@ naitlb_miss_20w: L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20w + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1458,20 +1453,20 @@ itlb_miss_11: L2_ptep ptp,pte,t0,va,itlb_fault - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 iitlba pte,(%sr1,va) iitlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1482,20 +1477,20 @@ naitlb_miss_11: L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_11 + update_accessed ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot - mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 iitlba pte,(%sr1,va) iitlbp prot,(%sr1,va) - mtsp t0, %sr1 /* Restore sr1 */ - dbit_unlock1 spc,t0 + mtsp t1, %sr1 /* Restore sr1 */ + tlb_unlock1 spc,t0 rfir nop @@ -1516,16 +1511,16 @@ itlb_miss_20: L2_ptep ptp,pte,t0,va,itlb_fault - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,itlb_fault + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1536,16 +1531,16 @@ naitlb_miss_20: L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 - dbit_lock spc,t0,t1 - update_ptep spc,ptp,pte,t0,t1 + tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20 + update_accessed ptp,pte,t0,t1 make_insert_tlb spc,pte,prot - f_extend pte,t0 + f_extend pte,t1 iitlbt pte,prot - dbit_unlock1 spc,t0 + tlb_unlock1 spc,t0 rfir nop @@ -1568,14 +1563,14 @@ dbit_trap_20w: L3_ptep ptp,pte,t0,va,dbit_fault - dbit_lock spc,t0,t1 - update_dirty spc,ptp,pte,t1 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault + update_dirty ptp,pte,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot - dbit_unlock0 spc,t0 + tlb_unlock0 spc,t0 rfir nop #else @@ -1588,8 +1583,8 @@ dbit_trap_11: L2_ptep ptp,pte,t0,va,dbit_fault - dbit_lock spc,t0,t1 - update_dirty spc,ptp,pte,t1 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault + update_dirty ptp,pte,t1 make_insert_tlb_11 spc,pte,prot @@ -1600,8 +1595,8 @@ dbit_trap_11: idtlbp prot,(%sr1,va) mtsp t1, %sr1 /* Restore sr1 */ - dbit_unlock0 spc,t0 + tlb_unlock0 spc,t0 rfir nop @@ -1612,16 +1607,16 @@ dbit_trap_20: L2_ptep ptp,pte,t0,va,dbit_fault - dbit_lock spc,t0,t1 - update_dirty spc,ptp,pte,t1 + tlb_lock spc,ptp,pte,t0,t1,dbit_fault + update_dirty ptp,pte,t1 make_insert_tlb spc,pte,prot f_extend pte,t1 - idtlbt pte,prot - dbit_unlock0 spc,t0 + idtlbt pte,prot + tlb_unlock0 spc,t0 rfir nop #endif diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 6548fd1..b99b39f 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -43,10 +43,6 @@ #include "../math-emu/math-emu.h" /* for handle_fpe() */ -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) -DEFINE_SPINLOCK(pa_dbit_lock); -#endif - static void parisc_show_stack(struct task_struct *task, unsigned long *sp, struct pt_regs *regs); diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index ccde8f0..112ccf4 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S @@ -52,6 +52,22 @@ .text /* + * Used by threads when the lock bit of core_idle_state is set. + * Threads will spin in HMT_LOW until the lock bit is cleared. + * r14 - pointer to core_idle_state + * r15 - used to load contents of core_idle_state + */ + +core_idle_lock_held: + HMT_LOW +3: lwz r15,0(r14) + andi. r15,r15,PNV_CORE_IDLE_LOCK_BIT + bne 3b + HMT_MEDIUM + lwarx r15,0,r14 + blr + +/* * Pass requested state in r3: * r3 - PNV_THREAD_NAP/SLEEP/WINKLE * @@ -150,6 +166,10 @@ power7_enter_nap_mode: ld r14,PACA_CORE_IDLE_STATE_PTR(r13) lwarx_loop1: lwarx r15,0,r14 + + andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT + bnel core_idle_lock_held + andc r15,r15,r7 /* Clear thread bit */ andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS @@ -294,7 +314,7 @@ lwarx_loop2: * workaround undo code or resyncing timebase or restoring context * In either case loop until the lock bit is cleared. */ - bne core_idle_lock_held + bnel core_idle_lock_held cmpwi cr2,r15,0 lbz r4,PACA_SUBCORE_SIBLING_MASK(r13) @@ -319,15 +339,6 @@ lwarx_loop2: isync b common_exit -core_idle_lock_held: - HMT_LOW -core_idle_lock_loop: - lwz r15,0(14) - andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT - bne core_idle_lock_loop - HMT_MEDIUM - b lwarx_loop2 - first_thread_in_subcore: /* First thread in subcore to wakeup */ ori r15,r15,PNV_CORE_IDLE_LOCK_BIT diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6530f1b..37de90f 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -297,6 +297,8 @@ long machine_check_early(struct pt_regs *regs) __this_cpu_inc(irq_stat.mce_exceptions); + add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); + if (cur_cpu_spec && cur_cpu_spec->machine_check_early) handled = cur_cpu_spec->machine_check_early(regs); return handled; diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 6d53597..a67c6d7 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -529,6 +529,10 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) printk(KERN_ALERT "Unable to handle kernel paging request for " "instruction fetch\n"); break; + case 0x600: + printk(KERN_ALERT "Unable to handle kernel paging request for " + "unaligned access at address 0x%08lx\n", regs->dar); + break; default: printk(KERN_ALERT "Unable to handle kernel paging request for " "unknown fault\n"); diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index ec2eb20..df95629 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c @@ -320,6 +320,8 @@ static struct attribute *device_str_attr_create_(char *name, char *str) if (!attr) return NULL; + sysfs_attr_init(&attr->attr.attr); + attr->var = str; attr->attr.attr.name = name; attr->attr.attr.mode = 0444; diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c index 4949ef0..37f959b 100644 --- a/arch/powerpc/platforms/powernv/opal-elog.c +++ b/arch/powerpc/platforms/powernv/opal-elog.c @@ -237,7 +237,7 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type) return elog; } -static void elog_work_fn(struct work_struct *work) +static irqreturn_t elog_event(int irq, void *data) { __be64 size; __be64 id; @@ -251,7 +251,7 @@ static void elog_work_fn(struct work_struct *work) rc = opal_get_elog_size(&id, &size, &type); if (rc != OPAL_SUCCESS) { pr_err("ELOG: OPAL log info read failed\n"); - return; + return IRQ_HANDLED; } elog_size = be64_to_cpu(size); @@ -270,16 +270,10 @@ static void elog_work_fn(struct work_struct *work) * entries. */ if (kset_find_obj(elog_kset, name)) - return; + return IRQ_HANDLED; create_elog_obj(log_id, elog_size, elog_type); -} - -static DECLARE_WORK(elog_work, elog_work_fn); -static irqreturn_t elog_event(int irq, void *data) -{ - schedule_work(&elog_work); return IRQ_HANDLED; } @@ -304,8 +298,8 @@ int __init opal_elog_init(void) return irq; } - rc = request_irq(irq, elog_event, - IRQ_TYPE_LEVEL_HIGH, "opal-elog", NULL); + rc = request_threaded_irq(irq, NULL, elog_event, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "opal-elog", NULL); if (rc) { pr_err("%s: Can't request OPAL event irq (%d)\n", __func__, rc); diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c index 46cb3fe..4ece8e4 100644 --- a/arch/powerpc/platforms/powernv/opal-prd.c +++ b/arch/powerpc/platforms/powernv/opal-prd.c @@ -112,6 +112,7 @@ static int opal_prd_open(struct inode *inode, struct file *file) static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma) { size_t addr, size; + pgprot_t page_prot; int rc; pr_devel("opal_prd_mmap(0x%016lx, 0x%016lx, 0x%lx, 0x%lx)\n", @@ -125,13 +126,11 @@ static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma) if (!opal_prd_range_is_valid(addr, size)) return -EINVAL; - vma->vm_page_prot = __pgprot(pgprot_val(phys_mem_access_prot(file, - vma->vm_pgoff, - size, vma->vm_page_prot)) - | _PAGE_SPECIAL); + page_prot = phys_mem_access_prot(file, vma->vm_pgoff, + size, vma->vm_page_prot); rc = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size, - vma->vm_page_prot); + page_prot); return rc; } diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c index 2bc3367..87f9623 100644 --- a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c @@ -18,6 +18,7 @@ #include <linux/pci.h> #include <linux/semaphore.h> #include <asm/msi_bitmap.h> +#include <asm/ppc-pci.h> struct ppc4xx_hsta_msi { struct device *dev; diff --git a/arch/tile/lib/memcpy_user_64.c b/arch/tile/lib/memcpy_user_64.c index 88c7016..97bbb60 100644 --- a/arch/tile/lib/memcpy_user_64.c +++ b/arch/tile/lib/memcpy_user_64.c @@ -28,7 +28,7 @@ #define _ST(p, inst, v) \ ({ \ asm("1: " #inst " %0, %1;" \ - ".pushsection .coldtext.memcpy,\"ax\";" \ + ".pushsection .coldtext,\"ax\";" \ "2: { move r0, %2; jrp lr };" \ ".section __ex_table,\"a\";" \ ".align 8;" \ @@ -41,7 +41,7 @@ ({ \ unsigned long __v; \ asm("1: " #inst " %0, %1;" \ - ".pushsection .coldtext.memcpy,\"ax\";" \ + ".pushsection .coldtext,\"ax\";" \ "2: { move r0, %2; jrp lr };" \ ".section __ex_table,\"a\";" \ ".align 8;" \ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 55bced1..3dbb7e7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -254,6 +254,11 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING config ARCH_SUPPORTS_DEBUG_PAGEALLOC def_bool y +config KASAN_SHADOW_OFFSET + hex + depends on KASAN + default 0xdffffc0000000000 + config HAVE_INTEL_TXT def_bool y depends on INTEL_IOMMU && ACPI @@ -2015,7 +2020,7 @@ config CMDLINE_BOOL To compile command line arguments into the kernel, set this option to 'Y', then fill in the - the boot arguments in CONFIG_CMDLINE. + boot arguments in CONFIG_CMDLINE. Systems with fully functional boot loaders (i.e. non-embedded) should leave this option set to 'N'. diff --git a/arch/x86/include/asm/espfix.h b/arch/x86/include/asm/espfix.h index 99efebb..ca3ce9a 100644 --- a/arch/x86/include/asm/espfix.h +++ b/arch/x86/include/asm/espfix.h @@ -9,7 +9,7 @@ DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack); DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); extern void init_espfix_bsp(void); -extern void init_espfix_ap(void); +extern void init_espfix_ap(int cpu); #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h index 8b22422..74a2a8d 100644 --- a/arch/x86/include/asm/kasan.h +++ b/arch/x86/include/asm/kasan.h @@ -14,15 +14,11 @@ #ifndef __ASSEMBLY__ -extern pte_t kasan_zero_pte[]; -extern pte_t kasan_zero_pmd[]; -extern pte_t kasan_zero_pud[]; - #ifdef CONFIG_KASAN -void __init kasan_map_early_shadow(pgd_t *pgd); +void __init kasan_early_init(void); void __init kasan_init(void); #else -static inline void kasan_map_early_shadow(pgd_t *pgd) { } +static inline void kasan_early_init(void) { } static inline void kasan_init(void) { } #endif diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 28eba2d..f813261 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -409,12 +409,6 @@ static void __setup_vector_irq(int cpu) int irq, vector; struct apic_chip_data *data; - /* - * vector_lock will make sure that we don't run into irq vector - * assignments that might be happening on another cpu in parallel, - * while we setup our initial vector to irq mappings. - */ - raw_spin_lock(&vector_lock); /* Mark the inuse vectors */ for_each_active_irq(irq) { data = apic_chip_data(irq_get_irq_data(irq)); @@ -436,16 +430,16 @@ static void __setup_vector_irq(int cpu) if (!cpumask_test_cpu(cpu, data->domain)) per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; } - raw_spin_unlock(&vector_lock); } /* - * Setup the vector to irq mappings. + * Setup the vector to irq mappings. Must be called with vector_lock held. */ void setup_vector_irq(int cpu) { int irq; + lockdep_assert_held(&vector_lock); /* * On most of the platforms, legacy PIC delivers the interrupts on the * boot cpu. But there are certain platforms where PIC interrupts are diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 89427d8..eec40f5 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -175,7 +175,9 @@ static __init void early_serial_init(char *s) } if (*s) { - if (kstrtoul(s, 0, &baud) < 0 || baud == 0) + baud = simple_strtoull(s, &e, 0); + + if (baud == 0 || s == e) baud = DEFAULT_BAUD; } diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c index f5d0730..ce95676 100644 --- a/arch/x86/kernel/espfix_64.c +++ b/arch/x86/kernel/espfix_64.c @@ -131,25 +131,24 @@ void __init init_espfix_bsp(void) init_espfix_random(); /* The rest is the same as for any other processor */ - init_espfix_ap(); + init_espfix_ap(0); } -void init_espfix_ap(void) +void init_espfix_ap(int cpu) { - unsigned int cpu, page; + unsigned int page; unsigned long addr; pud_t pud, *pud_p; pmd_t pmd, *pmd_p; pte_t pte, *pte_p; - int n; + int n, node; void *stack_page; pteval_t ptemask; /* We only have to do this once... */ - if (likely(this_cpu_read(espfix_stack))) + if (likely(per_cpu(espfix_stack, cpu))) return; /* Already initialized */ - cpu = smp_processor_id(); addr = espfix_base_addr(cpu); page = cpu/ESPFIX_STACKS_PER_PAGE; @@ -165,12 +164,15 @@ void init_espfix_ap(void) if (stack_page) goto unlock_done; + node = cpu_to_node(cpu); ptemask = __supported_pte_mask; pud_p = &espfix_pud_page[pud_index(addr)]; pud = *pud_p; if (!pud_present(pud)) { - pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP); + struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); + + pmd_p = (pmd_t *)page_address(page); pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); for (n = 0; n < ESPFIX_PUD_CLONES; n++) @@ -180,7 +182,9 @@ void init_espfix_ap(void) pmd_p = pmd_offset(&pud, addr); pmd = *pmd_p; if (!pmd_present(pmd)) { - pte_p = (pte_t *)__get_free_page(PGALLOC_GFP); + struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); + + pte_p = (pte_t *)page_address(page); pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); for (n = 0; n < ESPFIX_PMD_CLONES; n++) @@ -188,7 +192,7 @@ void init_espfix_ap(void) } pte_p = pte_offset_kernel(&pmd, addr); - stack_page = (void *)__get_free_page(GFP_KERNEL); + stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0)); pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); for (n = 0; n < ESPFIX_PTE_CLONES; n++) set_pte(&pte_p[n*PTE_STRIDE], pte); @@ -199,7 +203,7 @@ void init_espfix_ap(void) unlock_done: mutex_unlock(&espfix_init_mutex); done: - this_cpu_write(espfix_stack, addr); - this_cpu_write(espfix_waddr, (unsigned long)stack_page - + (addr & ~PAGE_MASK)); + per_cpu(espfix_stack, cpu) = addr; + per_cpu(espfix_waddr, cpu) = (unsigned long)stack_page + + (addr & ~PAGE_MASK); } diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 5a46681..f129a9a 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -161,11 +161,12 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) /* Kill off the identity-map trampoline */ reset_early_page_tables(); - kasan_map_early_shadow(early_level4_pgt); - - /* clear bss before set_intr_gate with early_idt_handler */ clear_bss(); + clear_page(init_level4_pgt); + + kasan_early_init(); + for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) set_intr_gate(i, early_idt_handler_array[i]); load_idt((const struct desc_ptr *)&idt_descr); @@ -177,12 +178,9 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) */ load_ucode_bsp(); - clear_page(init_level4_pgt); /* set init_level4_pgt kernel high mapping*/ init_level4_pgt[511] = early_level4_pgt[511]; - kasan_map_early_shadow(init_level4_pgt); - x86_64_start_reservations(real_mode_data); } diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index e5c27f7..1d40ca8 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -516,38 +516,9 @@ ENTRY(phys_base) /* This must match the first entry in level2_kernel_pgt */ .quad 0x0000000000000000 -#ifdef CONFIG_KASAN -#define FILL(VAL, COUNT) \ - .rept (COUNT) ; \ - .quad (VAL) ; \ - .endr - -NEXT_PAGE(kasan_zero_pte) - FILL(kasan_zero_page - __START_KERNEL_map + _KERNPG_TABLE, 512) -NEXT_PAGE(kasan_zero_pmd) - FILL(kasan_zero_pte - __START_KERNEL_map + _KERNPG_TABLE, 512) -NEXT_PAGE(kasan_zero_pud) - FILL(kasan_zero_pmd - __START_KERNEL_map + _KERNPG_TABLE, 512) - -#undef FILL -#endif - - #include "../../x86/xen/xen-head.S" __PAGE_ALIGNED_BSS NEXT_PAGE(empty_zero_page) .skip PAGE_SIZE -#ifdef CONFIG_KASAN -/* - * This page used as early shadow. We don't use empty_zero_page - * at early stages, stack instrumentation could write some garbage - * to this page. - * Latter we reuse it as zero shadow for large ranges of memory - * that allowed to access, but not instrumented by kasan - * (vmalloc/vmemmap ...). - */ -NEXT_PAGE(kasan_zero_page) - .skip PAGE_SIZE -#endif diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 88b36648..c7dfe1b 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -347,14 +347,22 @@ int check_irq_vectors_for_cpu_disable(void) if (!desc) continue; + /* + * Protect against concurrent action removal, + * affinity changes etc. + */ + raw_spin_lock(&desc->lock); data = irq_desc_get_irq_data(desc); cpumask_copy(&affinity_new, data->affinity); cpumask_clear_cpu(this_cpu, &affinity_new); /* Do not count inactive or per-cpu irqs. */ - if (!irq_has_action(irq) || irqd_is_per_cpu(data)) + if (!irq_has_action(irq) || irqd_is_per_cpu(data)) { + raw_spin_unlock(&desc->lock); continue; + } + raw_spin_unlock(&desc->lock); /* * A single irq may be mapped to multiple * cpu's vector_irq[] (for example IOAPIC cluster @@ -385,6 +393,9 @@ int check_irq_vectors_for_cpu_disable(void) * vector. If the vector is marked in the used vectors * bitmap or an irq is assigned to it, we don't count * it as available. + * + * As this is an inaccurate snapshot anyway, we can do + * this w/o holding vector_lock. */ for (vector = FIRST_EXTERNAL_VECTOR; vector < first_system_vector; vector++) { @@ -486,6 +497,11 @@ void fixup_irqs(void) */ mdelay(1); + /* + * We can walk the vector array of this cpu without holding + * vector_lock because the cpu is already marked !online, so + * nothing else will touch it. + */ for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { unsigned int irr; @@ -497,9 +513,9 @@ void fixup_irqs(void) irq = __this_cpu_read(vector_irq[vector]); desc = irq_to_desc(irq); + raw_spin_lock(&desc->lock); data = irq_desc_get_irq_data(desc); chip = irq_data_get_irq_chip(data); - raw_spin_lock(&desc->lock); if (chip->irq_retrigger) { chip->irq_retrigger(data); __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 8add66b..d3010aa 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -171,11 +171,6 @@ static void smp_callin(void) apic_ap_setup(); /* - * Need to setup vector mappings before we enable interrupts. - */ - setup_vector_irq(smp_processor_id()); - - /* * Save our processor parameters. Note: this information * is needed for clock calibration. */ @@ -239,18 +234,13 @@ static void notrace start_secondary(void *unused) check_tsc_sync_target(); /* - * Enable the espfix hack for this CPU - */ -#ifdef CONFIG_X86_ESPFIX64 - init_espfix_ap(); -#endif - - /* - * We need to hold vector_lock so there the set of online cpus - * does not change while we are assigning vectors to cpus. Holding - * this lock ensures we don't half assign or remove an irq from a cpu. + * Lock vector_lock and initialize the vectors on this cpu + * before setting the cpu online. We must set it online with + * vector_lock held to prevent a concurrent setup/teardown + * from seeing a half valid vector space. */ lock_vector_lock(); + setup_vector_irq(smp_processor_id()); set_cpu_online(smp_processor_id(), true); unlock_vector_lock(); cpu_set_state_online(smp_processor_id()); @@ -854,6 +844,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) initial_code = (unsigned long)start_secondary; stack_start = idle->thread.sp; + /* + * Enable the espfix hack for this CPU + */ +#ifdef CONFIG_X86_ESPFIX64 + init_espfix_ap(cpu); +#endif + /* So we see what's up */ announce_cpu(cpu, apicid); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 5054497..7437b41 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -598,10 +598,19 @@ static unsigned long quick_pit_calibrate(void) if (!pit_expect_msb(0xff-i, &delta, &d2)) break; + delta -= tsc; + + /* + * Extrapolate the error and fail fast if the error will + * never be below 500 ppm. + */ + if (i == 1 && + d1 + d2 >= (delta * MAX_QUICK_PIT_ITERATIONS) >> 11) + return 0; + /* * Iterate until the error is less than 500 ppm */ - delta -= tsc; if (d1+d2 >= delta >> 11) continue; diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index ddf9ecb..e342586 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -20,7 +20,7 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) unsigned long ret; if (__range_not_ok(from, n, TASK_SIZE)) - return 0; + return n; /* * Even though this function is typically called from NMI/IRQ context diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c index 4860906..e1840f3 100644 --- a/arch/x86/mm/kasan_init_64.c +++ b/arch/x86/mm/kasan_init_64.c @@ -1,3 +1,4 @@ +#define pr_fmt(fmt) "kasan: " fmt #include <linux/bootmem.h> #include <linux/kasan.h> #include <linux/kdebug.h> @@ -11,7 +12,19 @@ extern pgd_t early_level4_pgt[PTRS_PER_PGD]; extern struct range pfn_mapped[E820_X_MAX]; -extern unsigned char kasan_zero_page[PAGE_SIZE]; +static pud_t kasan_zero_pud[PTRS_PER_PUD] __page_aligned_bss; +static pmd_t kasan_zero_pmd[PTRS_PER_PMD] __page_aligned_bss; +static pte_t kasan_zero_pte[PTRS_PER_PTE] __page_aligned_bss; + +/* + * This page used as early shadow. We don't use empty_zero_page + * at early stages, stack instrumentation could write some garbage + * to this page. + * Latter we reuse it as zero shadow for large ranges of memory + * that allowed to access, but not instrumented by kasan + * (vmalloc/vmemmap ...). + */ +static unsigned char kasan_zero_page[PAGE_SIZE] __page_aligned_bss; static int __init map_range(struct range *range) { @@ -36,7 +49,7 @@ static void __init clear_pgds(unsigned long start, pgd_clear(pgd_offset_k(start)); } -void __init kasan_map_early_shadow(pgd_t *pgd) +static void __init kasan_map_early_shadow(pgd_t *pgd) { int i; unsigned long start = KASAN_SHADOW_START; @@ -73,7 +86,7 @@ static int __init zero_pmd_populate(pud_t *pud, unsigned long addr, while (IS_ALIGNED(addr, PMD_SIZE) && addr + PMD_SIZE <= end) { WARN_ON(!pmd_none(*pmd)); set_pmd(pmd, __pmd(__pa_nodebug(kasan_zero_pte) - | __PAGE_KERNEL_RO)); + | _KERNPG_TABLE)); addr += PMD_SIZE; pmd = pmd_offset(pud, addr); } @@ -99,7 +112,7 @@ static int __init zero_pud_populate(pgd_t *pgd, unsigned long addr, while (IS_ALIGNED(addr, PUD_SIZE) && addr + PUD_SIZE <= end) { WARN_ON(!pud_none(*pud)); set_pud(pud, __pud(__pa_nodebug(kasan_zero_pmd) - | __PAGE_KERNEL_RO)); + | _KERNPG_TABLE)); addr += PUD_SIZE; pud = pud_offset(pgd, addr); } @@ -124,7 +137,7 @@ static int __init zero_pgd_populate(unsigned long addr, unsigned long end) while (IS_ALIGNED(addr, PGDIR_SIZE) && addr + PGDIR_SIZE <= end) { WARN_ON(!pgd_none(*pgd)); set_pgd(pgd, __pgd(__pa_nodebug(kasan_zero_pud) - | __PAGE_KERNEL_RO)); + | _KERNPG_TABLE)); addr += PGDIR_SIZE; pgd = pgd_offset_k(addr); } @@ -166,6 +179,26 @@ static struct notifier_block kasan_die_notifier = { }; #endif +void __init kasan_early_init(void) +{ + int i; + pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL; + pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE; + pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE; + + for (i = 0; i < PTRS_PER_PTE; i++) + kasan_zero_pte[i] = __pte(pte_val); + + for (i = 0; i < PTRS_PER_PMD; i++) + kasan_zero_pmd[i] = __pmd(pmd_val); + + for (i = 0; i < PTRS_PER_PUD; i++) + kasan_zero_pud[i] = __pud(pud_val); + + kasan_map_early_shadow(early_level4_pgt); + kasan_map_early_shadow(init_level4_pgt); +} + void __init kasan_init(void) { int i; @@ -176,6 +209,7 @@ void __init kasan_init(void) memcpy(early_level4_pgt, init_level4_pgt, sizeof(early_level4_pgt)); load_cr3(early_level4_pgt); + __flush_tlb_all(); clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END); @@ -202,5 +236,8 @@ void __init kasan_init(void) memset(kasan_zero_page, 0, PAGE_SIZE); load_cr3(init_level4_pgt); + __flush_tlb_all(); init_task.kasan_depth = 0; + + pr_info("Kernel address sanitizer initialized\n"); } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 569ee09..46b58ab 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -352,13 +352,16 @@ static int acpi_lpss_create_device(struct acpi_device *adev, pdata->mmio_size = resource_size(rentry->res); pdata->mmio_base = ioremap(rentry->res->start, pdata->mmio_size); - if (!pdata->mmio_base) - goto err_out; break; } acpi_dev_free_resource_list(&resource_list); + if (!pdata->mmio_base) { + ret = -ENOMEM; + goto err_out; + } + pdata->dev_desc = dev_desc; if (dev_desc->setup) diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index 2161fa1..628a42c 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c @@ -18,6 +18,7 @@ #include <linux/list.h> #include <linux/acpi.h> #include <linux/sort.h> +#include <linux/pmem.h> #include <linux/io.h> #include "nfit.h" @@ -305,6 +306,23 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc, return true; } +static bool add_flush(struct acpi_nfit_desc *acpi_desc, + struct acpi_nfit_flush_address *flush) +{ + struct device *dev = acpi_desc->dev; + struct nfit_flush *nfit_flush = devm_kzalloc(dev, sizeof(*nfit_flush), + GFP_KERNEL); + + if (!nfit_flush) + return false; + INIT_LIST_HEAD(&nfit_flush->list); + nfit_flush->flush = flush; + list_add_tail(&nfit_flush->list, &acpi_desc->flushes); + dev_dbg(dev, "%s: nfit_flush handle: %d hint_count: %d\n", __func__, + flush->device_handle, flush->hint_count); + return true; +} + static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, const void *end) { @@ -338,7 +356,8 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, return err; break; case ACPI_NFIT_TYPE_FLUSH_ADDRESS: - dev_dbg(dev, "%s: flush\n", __func__); + if (!add_flush(acpi_desc, table)) + return err; break; case ACPI_NFIT_TYPE_SMBIOS: dev_dbg(dev, "%s: smbios\n", __func__); @@ -389,6 +408,7 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, { u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; struct nfit_memdev *nfit_memdev; + struct nfit_flush *nfit_flush; struct nfit_dcr *nfit_dcr; struct nfit_bdw *nfit_bdw; struct nfit_idt *nfit_idt; @@ -442,6 +462,14 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, nfit_mem->idt_bdw = nfit_idt->idt; break; } + + list_for_each_entry(nfit_flush, &acpi_desc->flushes, list) { + if (nfit_flush->flush->device_handle != + nfit_memdev->memdev->device_handle) + continue; + nfit_mem->nfit_flush = nfit_flush; + break; + } break; } @@ -978,6 +1006,24 @@ static u64 to_interleave_offset(u64 offset, struct nfit_blk_mmio *mmio) return mmio->base_offset + line_offset + table_offset + sub_line_offset; } +static void wmb_blk(struct nfit_blk *nfit_blk) +{ + + if (nfit_blk->nvdimm_flush) { + /* + * The first wmb() is needed to 'sfence' all previous writes + * such that they are architecturally visible for the platform + * buffer flush. Note that we've already arranged for pmem + * writes to avoid the cache via arch_memcpy_to_pmem(). The + * final wmb() ensures ordering for the NVDIMM flush write. + */ + wmb(); + writeq(1, nfit_blk->nvdimm_flush); + wmb(); + } else + wmb_pmem(); +} + static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw) { struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR]; @@ -1012,7 +1058,10 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw, offset = to_interleave_offset(offset, mmio); writeq(cmd, mmio->base + offset); - /* FIXME: conditionally perform read-back if mandated by firmware */ + wmb_blk(nfit_blk); + + if (nfit_blk->dimm_flags & ND_BLK_DCR_LATCH) + readq(mmio->base + offset); } static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, @@ -1026,7 +1075,6 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, base_offset = nfit_blk->bdw_offset + dpa % L1_CACHE_BYTES + lane * mmio->size; - /* TODO: non-temporal access, flush hints, cache management etc... */ write_blk_ctl(nfit_blk, lane, dpa, len, rw); while (len) { unsigned int c; @@ -1045,13 +1093,19 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, } if (rw) - memcpy(mmio->aperture + offset, iobuf + copied, c); + memcpy_to_pmem(mmio->aperture + offset, + iobuf + copied, c); else - memcpy(iobuf + copied, mmio->aperture + offset, c); + memcpy_from_pmem(iobuf + copied, + mmio->aperture + offset, c); copied += c; len -= c; } + + if (rw) + wmb_blk(nfit_blk); + rc = read_blk_stat(nfit_blk, lane) ? -EIO : 0; return rc; } @@ -1124,7 +1178,7 @@ static void nfit_spa_unmap(struct acpi_nfit_desc *acpi_desc, } static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, - struct acpi_nfit_system_address *spa) + struct acpi_nfit_system_address *spa, enum spa_map_type type) { resource_size_t start = spa->address; resource_size_t n = spa->length; @@ -1152,8 +1206,15 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, if (!res) goto err_mem; - /* TODO: cacheability based on the spa type */ - spa_map->iomem = ioremap_nocache(start, n); + if (type == SPA_MAP_APERTURE) { + /* + * TODO: memremap_pmem() support, but that requires cache + * flushing when the aperture is moved. + */ + spa_map->iomem = ioremap_wc(start, n); + } else + spa_map->iomem = ioremap_nocache(start, n); + if (!spa_map->iomem) goto err_map; @@ -1171,6 +1232,7 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, * nfit_spa_map - interleave-aware managed-mappings of acpi_nfit_system_address ranges * @nvdimm_bus: NFIT-bus that provided the spa table entry * @nfit_spa: spa table to map + * @type: aperture or control region * * In the case where block-data-window apertures and * dimm-control-regions are interleaved they will end up sharing a @@ -1180,12 +1242,12 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, * unbound. */ static void __iomem *nfit_spa_map(struct acpi_nfit_desc *acpi_desc, - struct acpi_nfit_system_address *spa) + struct acpi_nfit_system_address *spa, enum spa_map_type type) { void __iomem *iomem; mutex_lock(&acpi_desc->spa_map_mutex); - iomem = __nfit_spa_map(acpi_desc, spa); + iomem = __nfit_spa_map(acpi_desc, spa, type); mutex_unlock(&acpi_desc->spa_map_mutex); return iomem; @@ -1206,12 +1268,35 @@ static int nfit_blk_init_interleave(struct nfit_blk_mmio *mmio, return 0; } +static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc, + struct nvdimm *nvdimm, struct nfit_blk *nfit_blk) +{ + struct nd_cmd_dimm_flags flags; + int rc; + + memset(&flags, 0, sizeof(flags)); + rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_DIMM_FLAGS, &flags, + sizeof(flags)); + + if (rc >= 0 && flags.status == 0) + nfit_blk->dimm_flags = flags.flags; + else if (rc == -ENOTTY) { + /* fall back to a conservative default */ + nfit_blk->dimm_flags = ND_BLK_DCR_LATCH; + rc = 0; + } else + rc = -ENXIO; + + return rc; +} + static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, struct device *dev) { struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus); struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); struct nd_blk_region *ndbr = to_nd_blk_region(dev); + struct nfit_flush *nfit_flush; struct nfit_blk_mmio *mmio; struct nfit_blk *nfit_blk; struct nfit_mem *nfit_mem; @@ -1223,8 +1308,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) { dev_dbg(dev, "%s: missing%s%s%s\n", __func__, nfit_mem ? "" : " nfit_mem", - nfit_mem->dcr ? "" : " dcr", - nfit_mem->bdw ? "" : " bdw"); + (nfit_mem && nfit_mem->dcr) ? "" : " dcr", + (nfit_mem && nfit_mem->bdw) ? "" : " bdw"); return -ENXIO; } @@ -1237,7 +1322,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, /* map block aperture memory */ nfit_blk->bdw_offset = nfit_mem->bdw->offset; mmio = &nfit_blk->mmio[BDW]; - mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw); + mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw, + SPA_MAP_APERTURE); if (!mmio->base) { dev_dbg(dev, "%s: %s failed to map bdw\n", __func__, nvdimm_name(nvdimm)); @@ -1259,7 +1345,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, nfit_blk->cmd_offset = nfit_mem->dcr->command_offset; nfit_blk->stat_offset = nfit_mem->dcr->status_offset; mmio = &nfit_blk->mmio[DCR]; - mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr); + mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr, + SPA_MAP_CONTROL); if (!mmio->base) { dev_dbg(dev, "%s: %s failed to map dcr\n", __func__, nvdimm_name(nvdimm)); @@ -1277,6 +1364,24 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, return rc; } + rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk); + if (rc < 0) { + dev_dbg(dev, "%s: %s failed get DIMM flags\n", + __func__, nvdimm_name(nvdimm)); + return rc; + } + + nfit_flush = nfit_mem->nfit_flush; + if (nfit_flush && nfit_flush->flush->hint_count != 0) { + nfit_blk->nvdimm_flush = devm_ioremap_nocache(dev, + nfit_flush->flush->hint_address[0], 8); + if (!nfit_blk->nvdimm_flush) + return -ENOMEM; + } + + if (!arch_has_pmem_api() && !nfit_blk->nvdimm_flush) + dev_warn(dev, "unable to guarantee persistence of writes\n"); + if (mmio->line_size == 0) return 0; @@ -1459,6 +1564,7 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz) INIT_LIST_HEAD(&acpi_desc->dcrs); INIT_LIST_HEAD(&acpi_desc->bdws); INIT_LIST_HEAD(&acpi_desc->idts); + INIT_LIST_HEAD(&acpi_desc->flushes); INIT_LIST_HEAD(&acpi_desc->memdevs); INIT_LIST_HEAD(&acpi_desc->dimms); mutex_init(&acpi_desc->spa_map_mutex); diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h index 81f2e8c5..79b6d83 100644 --- a/drivers/acpi/nfit.h +++ b/drivers/acpi/nfit.h @@ -40,6 +40,10 @@ enum nfit_uuids { NFIT_UUID_MAX, }; +enum { + ND_BLK_DCR_LATCH = 2, +}; + struct nfit_spa { struct acpi_nfit_system_address *spa; struct list_head list; @@ -60,6 +64,11 @@ struct nfit_idt { struct list_head list; }; +struct nfit_flush { + struct acpi_nfit_flush_address *flush; + struct list_head list; +}; + struct nfit_memdev { struct acpi_nfit_memory_map *memdev; struct list_head list; @@ -77,6 +86,7 @@ struct nfit_mem { struct acpi_nfit_system_address *spa_bdw; struct acpi_nfit_interleave *idt_dcr; struct acpi_nfit_interleave *idt_bdw; + struct nfit_flush *nfit_flush; struct list_head list; struct acpi_device *adev; unsigned long dsm_mask; @@ -88,6 +98,7 @@ struct acpi_nfit_desc { struct mutex spa_map_mutex; struct list_head spa_maps; struct list_head memdevs; + struct list_head flushes; struct list_head dimms; struct list_head spas; struct list_head dcrs; @@ -109,7 +120,7 @@ struct nfit_blk { struct nfit_blk_mmio { union { void __iomem *base; - void *aperture; + void __pmem *aperture; }; u64 size; u64 base_offset; @@ -123,6 +134,13 @@ struct nfit_blk { u64 bdw_offset; /* post interleave offset */ u64 stat_offset; u64 cmd_offset; + void __iomem *nvdimm_flush; + u32 dimm_flags; +}; + +enum spa_map_type { + SPA_MAP_CONTROL, + SPA_MAP_APERTURE, }; struct nfit_spa_mapping { diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c262e4a..3b8963f 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -175,10 +175,14 @@ static void __init acpi_request_region (struct acpi_generic_address *gas, if (!addr || !length) return; - acpi_reserve_region(addr, length, gas->space_id, 0, desc); + /* Resources are never freed */ + if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) + request_region(addr, length, desc); + else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + request_mem_region(addr, length, desc); } -static void __init acpi_reserve_resources(void) +static int __init acpi_reserve_resources(void) { acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, "ACPI PM1a_EVT_BLK"); @@ -207,7 +211,10 @@ static void __init acpi_reserve_resources(void) if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) acpi_request_region(&acpi_gbl_FADT.xgpe1_block, acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); + + return 0; } +fs_initcall_sync(acpi_reserve_resources); void acpi_os_printf(const char *fmt, ...) { @@ -1862,7 +1869,6 @@ acpi_status __init acpi_os_initialize(void) acpi_status __init acpi_os_initialize1(void) { - acpi_reserve_resources(); kacpid_wq = alloc_workqueue("kacpid", 0, 1); kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 10561ce..8244f01 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -26,7 +26,6 @@ #include <linux/device.h> #include <linux/export.h> #include <linux/ioport.h> -#include <linux/list.h> #include <linux/slab.h> #ifdef CONFIG_X86 @@ -622,164 +621,3 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares, return (type & types) ? 0 : 1; } EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); - -struct reserved_region { - struct list_head node; - u64 start; - u64 end; -}; - -static LIST_HEAD(reserved_io_regions); -static LIST_HEAD(reserved_mem_regions); - -static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags, - char *desc) -{ - unsigned int length = end - start + 1; - struct resource *res; - - res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ? - request_region(start, length, desc) : - request_mem_region(start, length, desc); - if (!res) - return -EIO; - - res->flags &= ~flags; - return 0; -} - -static int add_region_before(u64 start, u64 end, u8 space_id, - unsigned long flags, char *desc, - struct list_head *head) -{ - struct reserved_region *reg; - int error; - - reg = kmalloc(sizeof(*reg), GFP_KERNEL); - if (!reg) - return -ENOMEM; - - error = request_range(start, end, space_id, flags, desc); - if (error) { - kfree(reg); - return error; - } - - reg->start = start; - reg->end = end; - list_add_tail(®->node, head); - return 0; -} - -/** - * acpi_reserve_region - Reserve an I/O or memory region as a system resource. - * @start: Starting address of the region. - * @length: Length of the region. - * @space_id: Identifier of address space to reserve the region from. - * @flags: Resource flags to clear for the region after requesting it. - * @desc: Region description (for messages). - * - * Reserve an I/O or memory region as a system resource to prevent others from - * using it. If the new region overlaps with one of the regions (in the given - * address space) already reserved by this routine, only the non-overlapping - * parts of it will be reserved. - * - * Returned is either 0 (success) or a negative error code indicating a resource - * reservation problem. It is the code of the first encountered error, but the - * routine doesn't abort until it has attempted to request all of the parts of - * the new region that don't overlap with other regions reserved previously. - * - * The resources requested by this routine are never released. - */ -int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, - unsigned long flags, char *desc) -{ - struct list_head *regions; - struct reserved_region *reg; - u64 end = start + length - 1; - int ret = 0, error = 0; - - if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) - regions = &reserved_io_regions; - else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) - regions = &reserved_mem_regions; - else - return -EINVAL; - - if (list_empty(regions)) - return add_region_before(start, end, space_id, flags, desc, regions); - - list_for_each_entry(reg, regions, node) - if (reg->start == end + 1) { - /* The new region can be prepended to this one. */ - ret = request_range(start, end, space_id, flags, desc); - if (!ret) - reg->start = start; - - return ret; - } else if (reg->start > end) { - /* No overlap. Add the new region here and get out. */ - return add_region_before(start, end, space_id, flags, - desc, ®->node); - } else if (reg->end == start - 1) { - goto combine; - } else if (reg->end >= start) { - goto overlap; - } - - /* The new region goes after the last existing one. */ - return add_region_before(start, end, space_id, flags, desc, regions); - - overlap: - /* - * The new region overlaps an existing one. - * - * The head part of the new region immediately preceding the existing - * overlapping one can be combined with it right away. - */ - if (reg->start > start) { - error = request_range(start, reg->start - 1, space_id, flags, desc); - if (error) - ret = error; - else - reg->start = start; - } - - combine: - /* - * The new region is adjacent to an existing one. If it extends beyond - * that region all the way to the next one, it is possible to combine - * all three of them. - */ - while (reg->end < end) { - struct reserved_region *next = NULL; - u64 a = reg->end + 1, b = end; - - if (!list_is_last(®->node, regions)) { - next = list_next_entry(reg, node); - if (next->start <= end) - b = next->start - 1; - } - error = request_range(a, b, space_id, flags, desc); - if (!error) { - if (next && next->start == b + 1) { - reg->end = next->end; - list_del(&next->node); - kfree(next); - } else { - reg->end = end; - break; - } - } else if (next) { - if (!ret) - ret = error; - - reg = next; - } else { - break; - } - } - - return ret ? ret : error; -} -EXPORT_SYMBOL_GPL(acpi_reserve_region); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2649a06..ec25635 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1019,6 +1019,29 @@ static bool acpi_of_match_device(struct acpi_device *adev, return false; } +static bool __acpi_match_device_cls(const struct acpi_device_id *id, + struct acpi_hardware_id *hwid) +{ + int i, msk, byte_shift; + char buf[3]; + + if (!id->cls) + return false; + + /* Apply class-code bitmask, before checking each class-code byte */ + for (i = 1; i <= 3; i++) { + byte_shift = 8 * (3 - i); + msk = (id->cls_msk >> byte_shift) & 0xFF; + if (!msk) + continue; + + sprintf(buf, "%02x", (id->cls >> byte_shift) & msk); + if (strncmp(buf, &hwid->id[(i - 1) * 2], 2)) + return false; + } + return true; +} + static const struct acpi_device_id *__acpi_match_device( struct acpi_device *device, const struct acpi_device_id *ids, @@ -1036,9 +1059,12 @@ static const struct acpi_device_id *__acpi_match_device( list_for_each_entry(hwid, &device->pnp.ids, list) { /* First, check the ACPI/PNP IDs provided by the caller. */ - for (id = ids; id->id[0]; id++) - if (!strcmp((char *) id->id, hwid->id)) + for (id = ids; id->id[0] || id->cls; id++) { + if (id->id[0] && !strcmp((char *) id->id, hwid->id)) return id; + else if (id->cls && __acpi_match_device_cls(id, hwid)) + return id; + } /* * Next, check ACPI_DT_NAMESPACE_HID and try to match the @@ -2101,6 +2127,8 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, if (info->valid & ACPI_VALID_UID) pnp->unique_id = kstrdup(info->unique_id.string, GFP_KERNEL); + if (info->valid & ACPI_VALID_CLS) + acpi_add_id(pnp, info->class_code.string); kfree(info); diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 6d17a3b..15e40ee 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -48,7 +48,7 @@ config ATA_VERBOSE_ERROR config ATA_ACPI bool "ATA ACPI Support" - depends on ACPI && PCI + depends on ACPI default y help This option adds support for ATA-related ACPI objects. diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 614c78f..1befb11 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -20,6 +20,8 @@ #include <linux/platform_device.h> #include <linux/libata.h> #include <linux/ahci_platform.h> +#include <linux/acpi.h> +#include <linux/pci_ids.h> #include "ahci.h" #define DRV_NAME "ahci" @@ -79,12 +81,19 @@ static const struct of_device_id ahci_of_match[] = { }; MODULE_DEVICE_TABLE(of, ahci_of_match); +static const struct acpi_device_id ahci_acpi_match[] = { + { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); + static struct platform_driver ahci_driver = { .probe = ahci_probe, .remove = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_of_match, + .acpi_match_table = ahci_acpi_match, .pm = &ahci_pm_ops, }, }; diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 9c42883..894bda1 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -563,10 +563,8 @@ static void fw_dev_release(struct device *dev) kfree(fw_priv); } -static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) +static int do_firmware_uevent(struct firmware_priv *fw_priv, struct kobj_uevent_env *env) { - struct firmware_priv *fw_priv = to_firmware_priv(dev); - if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id)) return -ENOMEM; if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) @@ -577,6 +575,18 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct firmware_priv *fw_priv = to_firmware_priv(dev); + int err = 0; + + mutex_lock(&fw_lock); + if (fw_priv->buf) + err = do_firmware_uevent(fw_priv, env); + mutex_unlock(&fw_lock); + return err; +} + static struct class firmware_class = { .name = "firmware", .class_attrs = firmware_class_attrs, diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index cdd547b..0ee43c1 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -6,6 +6,7 @@ * This file is released under the GPLv2. */ +#include <linux/delay.h> #include <linux/kernel.h> #include <linux/io.h> #include <linux/platform_device.h> @@ -19,6 +20,8 @@ #include <linux/suspend.h> #include <linux/export.h> +#define GENPD_RETRY_MAX_MS 250 /* Approximate */ + #define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \ ({ \ type (*__routine)(struct device *__d); \ @@ -2131,6 +2134,7 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider); static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + unsigned int i; int ret = 0; pd = pm_genpd_lookup_dev(dev); @@ -2139,10 +2143,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); - while (1) { + for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { ret = pm_genpd_remove_device(pd, dev); if (ret != -EAGAIN) break; + + mdelay(i); cond_resched(); } @@ -2183,6 +2189,7 @@ int genpd_dev_pm_attach(struct device *dev) { struct of_phandle_args pd_args; struct generic_pm_domain *pd; + unsigned int i; int ret; if (!dev->of_node) @@ -2218,10 +2225,12 @@ int genpd_dev_pm_attach(struct device *dev) dev_dbg(dev, "adding to PM domain %s\n", pd->name); - while (1) { + for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { ret = pm_genpd_add_device(pd, dev); if (ret != -EAGAIN) break; + + mdelay(i); cond_resched(); } diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index 7470004..eb6e674 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -45,14 +45,12 @@ static int dev_pm_attach_wake_irq(struct device *dev, int irq, return -EEXIST; } - dev->power.wakeirq = wirq; - spin_unlock_irqrestore(&dev->power.lock, flags); - err = device_wakeup_attach_irq(dev, wirq); - if (err) - return err; + if (!err) + dev->power.wakeirq = wirq; - return 0; + spin_unlock_irqrestore(&dev->power.lock, flags); + return err; } /** @@ -105,10 +103,10 @@ void dev_pm_clear_wake_irq(struct device *dev) return; spin_lock_irqsave(&dev->power.lock, flags); + device_wakeup_detach_irq(dev); dev->power.wakeirq = NULL; spin_unlock_irqrestore(&dev->power.lock, flags); - device_wakeup_detach_irq(dev); if (wirq->dedicated_irq) free_irq(wirq->irq, wirq); kfree(wirq); diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 40f7160..51f15bc 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -281,32 +281,25 @@ EXPORT_SYMBOL_GPL(device_wakeup_enable); * Attach a device wakeirq to the wakeup source so the device * wake IRQ can be configured automatically for suspend and * resume. + * + * Call under the device's power.lock lock. */ int device_wakeup_attach_irq(struct device *dev, struct wake_irq *wakeirq) { struct wakeup_source *ws; - int ret = 0; - spin_lock_irq(&dev->power.lock); ws = dev->power.wakeup; if (!ws) { dev_err(dev, "forgot to call call device_init_wakeup?\n"); - ret = -EINVAL; - goto unlock; + return -EINVAL; } - if (ws->wakeirq) { - ret = -EEXIST; - goto unlock; - } + if (ws->wakeirq) + return -EEXIST; ws->wakeirq = wakeirq; - -unlock: - spin_unlock_irq(&dev->power.lock); - - return ret; + return 0; } /** @@ -314,20 +307,16 @@ unlock: * @dev: Device to handle * * Removes a device wakeirq from the wakeup source. + * + * Call under the device's power.lock lock. */ void device_wakeup_detach_irq(struct device *dev) { struct wakeup_source *ws; - spin_lock_irq(&dev->power.lock); ws = dev->power.wakeup; - if (!ws) - goto unlock; - - ws->wakeirq = NULL; - -unlock: - spin_unlock_irq(&dev->power.lock); + if (ws) + ws->wakeirq = NULL; } /** diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c index 152dcb3..61566bc 100644 --- a/drivers/clk/at91/clk-h32mx.c +++ b/drivers/clk/at91/clk-h32mx.c @@ -116,8 +116,10 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, h32mxclk->pmc = pmc; clk = clk_register(NULL, &h32mxclk->hw); - if (!clk) + if (!clk) { + kfree(h32mxclk); return; + } of_clk_add_provider(np, of_clk_src_simple_get, clk); } diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index c240045..27dfa96 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -171,8 +171,10 @@ at91_clk_register_main_osc(struct at91_pmc *pmc, irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); ret = request_irq(osc->irq, clk_main_osc_irq_handler, IRQF_TRIGGER_HIGH, name, osc); - if (ret) + if (ret) { + kfree(osc); return ERR_PTR(ret); + } if (bypass) pmc_write(pmc, AT91_CKGR_MOR, diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index f98eafe..5b3ded5 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -165,12 +165,16 @@ at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, irq_set_status_flags(master->irq, IRQ_NOAUTOEN); ret = request_irq(master->irq, clk_master_irq_handler, IRQF_TRIGGER_HIGH, "clk-master", master); - if (ret) + if (ret) { + kfree(master); return ERR_PTR(ret); + } clk = clk_register(NULL, &master->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(master->irq, master); kfree(master); + } return clk; } diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index cbbe403..18b60f4 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -346,12 +346,16 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, id ? "clk-pllb" : "clk-plla", pll); - if (ret) + if (ret) { + kfree(pll); return ERR_PTR(ret); + } clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(pll->irq, pll); kfree(pll); + } return clk; } diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index a76d03f..58008b3 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c @@ -130,13 +130,17 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name, irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); ret = request_irq(sys->irq, clk_system_irq_handler, IRQF_TRIGGER_HIGH, name, sys); - if (ret) + if (ret) { + kfree(sys); return ERR_PTR(ret); + } } clk = clk_register(NULL, &sys->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(sys->irq, sys); kfree(sys); + } return clk; } diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index ae3263b..30dd697 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -118,12 +118,16 @@ at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); ret = request_irq(utmi->irq, clk_utmi_irq_handler, IRQF_TRIGGER_HIGH, "clk-utmi", utmi); - if (ret) + if (ret) { + kfree(utmi); return ERR_PTR(ret); + } clk = clk_register(NULL, &utmi->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(utmi->irq, utmi); kfree(utmi); + } return clk; } diff --git a/drivers/clk/bcm/clk-iproc-asiu.c b/drivers/clk/bcm/clk-iproc-asiu.c index e19c09c..f630e1b 100644 --- a/drivers/clk/bcm/clk-iproc-asiu.c +++ b/drivers/clk/bcm/clk-iproc-asiu.c @@ -222,10 +222,6 @@ void __init iproc_asiu_setup(struct device_node *node, struct iproc_asiu_clk *asiu_clk; const char *clk_name; - clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); - if (WARN_ON(!clk_name)) - goto err_clk_register; - ret = of_property_read_string_index(node, "clock-output-names", i, &clk_name); if (WARN_ON(ret)) @@ -259,7 +255,7 @@ void __init iproc_asiu_setup(struct device_node *node, err_clk_register: for (i = 0; i < num_clks; i++) - kfree(asiu->clks[i].name); + clk_unregister(asiu->clk_data.clks[i]); iounmap(asiu->gate_base); err_iomap_gate: diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index 46fb84b..2dda4e8 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c @@ -366,7 +366,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, val = readl(pll->pll_base + ctrl->ndiv_int.offset); ndiv_int = (val >> ctrl->ndiv_int.shift) & bit_mask(ctrl->ndiv_int.width); - ndiv = ndiv_int << ctrl->ndiv_int.shift; + ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift; if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { val = readl(pll->pll_base + ctrl->ndiv_frac.offset); @@ -374,7 +374,8 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, bit_mask(ctrl->ndiv_frac.width); if (ndiv_frac != 0) - ndiv = (ndiv_int << ctrl->ndiv_int.shift) | ndiv_frac; + ndiv = ((u64)ndiv_int << ctrl->ndiv_int.shift) | + ndiv_frac; } val = readl(pll->pll_base + ctrl->pdiv.offset); @@ -655,10 +656,6 @@ void __init iproc_pll_clk_setup(struct device_node *node, memset(&init, 0, sizeof(init)); parent_name = node->name; - clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); - if (WARN_ON(!clk_name)) - goto err_clk_register; - ret = of_property_read_string_index(node, "clock-output-names", i, &clk_name); if (WARN_ON(ret)) @@ -690,10 +687,8 @@ void __init iproc_pll_clk_setup(struct device_node *node, return; err_clk_register: - for (i = 0; i < num_clks; i++) { - kfree(pll->clks[i].name); + for (i = 0; i < num_clks; i++) clk_unregister(pll->clk_data.clks[i]); - } err_pll_register: if (pll->asiu_base) diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index b9b12a7..3f6f7ad 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -268,7 +268,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) memcpy(table, stm32f42xx_gate_map, sizeof(table)); /* only bits set in table can be used as indices */ - if (WARN_ON(secondary > 8 * sizeof(table) || + if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) || 0 == (table[BIT_ULL_WORD(secondary)] & BIT_ULL_MASK(secondary)))) return -EINVAL; diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 4b9e04c..8b6523d 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -700,6 +700,22 @@ static const struct mtk_composite peri_clks[] __initconst = { MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), }; +static struct clk_onecell_data *mt8173_top_clk_data __initdata; +static struct clk_onecell_data *mt8173_pll_clk_data __initdata; + +static void __init mtk_clk_enable_critical(void) +{ + if (!mt8173_top_clk_data || !mt8173_pll_clk_data) + return; + + clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA15PLL]); + clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA7PLL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_MEM_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_CCI400_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_RTC_SEL]); +} + static void __init mtk_topckgen_init(struct device_node *node) { struct clk_onecell_data *clk_data; @@ -712,19 +728,19 @@ static void __init mtk_topckgen_init(struct device_node *node) return; } - clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt8173_clk_lock, clk_data); - clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); + + mtk_clk_enable_critical(); } CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); @@ -818,13 +834,13 @@ static void __init mtk_apmixedsys_init(struct device_node *node) { struct clk_onecell_data *clk_data; - clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); if (!clk_data) return; mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]); + mtk_clk_enable_critical(); } CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", mtk_apmixedsys_init); diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index b95d17f..92936f0 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -530,19 +530,16 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate, struct clk_rcg2 *rcg = to_clk_rcg2(hw); struct freq_tbl f = *rcg->freq_tbl; const struct frac_entry *frac = frac_table_pixel; - unsigned long request, src_rate; + unsigned long request; int delta = 100000; u32 mask = BIT(rcg->hid_width) - 1; u32 hid_div; - int index = qcom_find_src_index(hw, rcg->parent_map, f.src); - struct clk *parent = clk_get_parent_by_index(hw->clk, index); for (; frac->num; frac++) { request = (rate * frac->den) / frac->num; - src_rate = __clk_round_rate(parent, request); - if ((src_rate < (request - delta)) || - (src_rate > (request + delta))) + if ((parent_rate < (request - delta)) || + (parent_rate > (request + delta))) continue; regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 657ca14..8dd8cce 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c @@ -190,7 +190,7 @@ static struct clk *clk_register_flexgen(const char *name, init.name = name; init.ops = &flexgen_ops; - init.flags = CLK_IS_BASIC | flexgen_flags; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE | flexgen_flags; init.parent_names = parent_names; init.num_parents = num_parents; @@ -303,6 +303,8 @@ static void __init st_of_flexgen_setup(struct device_node *np) if (!rlock) goto err; + spin_lock_init(rlock); + for (i = 0; i < clk_data->clk_num; i++) { struct clk *clk; const char *clk_name; diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index e94197f..d9eb2e1 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -340,7 +340,7 @@ static const struct clkgen_quadfs_data st_fs660c32_C_407 = { CLKGEN_FIELD(0x30c, 0xf, 20), CLKGEN_FIELD(0x310, 0xf, 20) }, .lockstatus_present = true, - .lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24), + .lock_status = CLKGEN_FIELD(0x2f0, 0x1, 24), .powerup_polarity = 1, .standby_polarity = 1, .pll_ops = &st_quadfs_pll_c32_ops, @@ -489,7 +489,7 @@ static int quadfs_pll_is_enabled(struct clk_hw *hw) struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); u32 npda = CLKGEN_READ(pll, npda); - return !!npda; + return pll->data->powerup_polarity ? !npda : !!npda; } static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs, @@ -635,7 +635,7 @@ static struct clk * __init st_clk_register_quadfs_pll( init.name = name; init.ops = quadfs->pll_ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = &parent_name; init.num_parents = 1; @@ -774,7 +774,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw) if (fs->lock) spin_lock_irqsave(fs->lock, flags); - CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity); + CLKGEN_WRITE(fs, nsb[fs->chan], fs->data->standby_polarity); if (fs->lock) spin_unlock_irqrestore(fs->lock, flags); @@ -1082,10 +1082,6 @@ static const struct of_device_id quadfs_of_match[] = { .compatible = "st,stih407-quadfs660-D", .data = &st_fs660c32_D_407 }, - { - .compatible = "st,stih407-quadfs660-D", - .data = (void *)&st_fs660c32_D_407 - }, {} }; diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c index 4fbe6e0..717c4a9 100644 --- a/drivers/clk/st/clkgen-mux.c +++ b/drivers/clk/st/clkgen-mux.c @@ -237,7 +237,7 @@ static struct clk *clk_register_genamux(const char *name, init.name = name; init.ops = &clkgena_divmux_ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = parent_names; init.num_parents = num_parents; @@ -513,7 +513,8 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np) 0, &clk_name)) return; - clk = clk_register_divider_table(NULL, clk_name, parent_name, 0, + clk = clk_register_divider_table(NULL, clk_name, parent_name, + CLK_GET_RATE_NOCACHE, reg + data->offset, data->shift, 1, 0, data->table, NULL); if (IS_ERR(clk)) @@ -582,7 +583,7 @@ static struct clkgen_mux_data stih416_a9_mux_data = { }; static struct clkgen_mux_data stih407_a9_mux_data = { .offset = 0x1a4, - .shift = 1, + .shift = 0, .width = 2, }; @@ -786,7 +787,8 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np) &mux->hw, &clk_mux_ops, &div->hw, &clk_divider_ops, &gate->hw, &clk_gate_ops, - data->clk_flags); + data->clk_flags | + CLK_GET_RATE_NOCACHE); if (IS_ERR(clk)) { kfree(gate); kfree(div); diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 1065322..72d1c27 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -406,7 +406,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name, init.name = clk_name; init.ops = pll_data->ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = &parent_name; init.num_parents = 1; diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 9a82f17..abf7b37 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -1391,6 +1391,7 @@ static void __init sun6i_init_clocks(struct device_node *node) CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks); CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); +CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks); static void __init sun9i_init_clocks(struct device_node *node) { diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index 879c784..2d59038 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c @@ -529,6 +529,7 @@ static void __init imx6dl_timer_init_dt(struct device_node *np) CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index fc897ba..e362860 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -3,7 +3,7 @@ * * The 2E revision of loongson processor not support this feature. * - * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2006 - 2008 Lemote Inc. & Institute of Computing Technology * Author: Yanhua, yanh@lemote.com * * This file is subject to the terms and conditions of the GNU General Public diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 975edb1..ae43b58 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -352,7 +352,7 @@ unsigned long amdgpu_gem_timeout(uint64_t timeout_ns) if (((int64_t)timeout_ns) < 0) return MAX_SCHEDULE_TIMEOUT; - timeout = ktime_sub_ns(ktime_get(), timeout_ns); + timeout = ktime_sub(ns_to_ktime(timeout_ns), ktime_get()); if (ktime_to_ns(timeout) < 0) return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 5cde635..6e77964 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -3403,19 +3403,25 @@ static int dce_v10_0_crtc_irq(struct amdgpu_device *adev, switch (entry->src_data) { case 0: /* vblank */ - if (disp_int & interrupt_status_offsets[crtc].vblank) { + if (disp_int & interrupt_status_offsets[crtc].vblank) dce_v10_0_crtc_vblank_int_ack(adev, crtc); - if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); - } - DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(adev->ddev, crtc); } + DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + break; case 1: /* vline */ - if (disp_int & interrupt_status_offsets[crtc].vline) { + if (disp_int & interrupt_status_offsets[crtc].vline) dce_v10_0_crtc_vline_int_ack(adev, crtc); - DRM_DEBUG("IH: D%d vline\n", crtc + 1); - } + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + DRM_DEBUG("IH: D%d vline\n", crtc + 1); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 95efd98..7f7abb0 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3402,19 +3402,25 @@ static int dce_v11_0_crtc_irq(struct amdgpu_device *adev, switch (entry->src_data) { case 0: /* vblank */ - if (disp_int & interrupt_status_offsets[crtc].vblank) { + if (disp_int & interrupt_status_offsets[crtc].vblank) dce_v11_0_crtc_vblank_int_ack(adev, crtc); - if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); - } - DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(adev->ddev, crtc); } + DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + break; case 1: /* vline */ - if (disp_int & interrupt_status_offsets[crtc].vline) { + if (disp_int & interrupt_status_offsets[crtc].vline) dce_v11_0_crtc_vline_int_ack(adev, crtc); - DRM_DEBUG("IH: D%d vline\n", crtc + 1); - } + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + DRM_DEBUG("IH: D%d vline\n", crtc + 1); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index aaca8d6..08387dfd 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -3237,19 +3237,25 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev, switch (entry->src_data) { case 0: /* vblank */ - if (disp_int & interrupt_status_offsets[crtc].vblank) { + if (disp_int & interrupt_status_offsets[crtc].vblank) WREG32(mmLB_VBLANK_STATUS + crtc_offsets[crtc], LB_VBLANK_STATUS__VBLANK_ACK_MASK); - if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); - } - DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(adev->ddev, crtc); } + DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + break; case 1: /* vline */ - if (disp_int & interrupt_status_offsets[crtc].vline) { + if (disp_int & interrupt_status_offsets[crtc].vline) WREG32(mmLB_VLINE_STATUS + crtc_offsets[crtc], LB_VLINE_STATUS__VLINE_ACK_MASK); - DRM_DEBUG("IH: D%d vline\n", crtc + 1); - } + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + DRM_DEBUG("IH: D%d vline\n", crtc + 1); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 8a1f999..9be0070 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -420,6 +420,12 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) pqm_uninit(&p->pqm); pdd = kfd_get_process_device_data(dev, p); + + if (!pdd) { + mutex_unlock(&p->mutex); + return; + } + if (pdd->reset_wavefronts) { dbgdev_wave_reset_wavefronts(pdd->dev, p); pdd->reset_wavefronts = false; @@ -431,8 +437,7 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) * We don't call amd_iommu_unbind_pasid() here * because the IOMMU called us. */ - if (pdd) - pdd->bound = false; + pdd->bound = false; mutex_unlock(&p->mutex); } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 8867818..d65cbe6 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -157,9 +157,7 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) struct drm_i915_gem_object *obj; int ret; - obj = i915_gem_object_create_stolen(dev, size); - if (obj == NULL) - obj = i915_gem_alloc_object(dev, size); + obj = i915_gem_alloc_object(dev, size); if (obj == NULL) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9daa288..dcc6a88 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2546,6 +2546,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; struct i915_address_space *vm; + struct i915_vma *vma; + bool flush; i915_check_and_clear_faults(dev); @@ -2555,16 +2557,23 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) dev_priv->gtt.base.total, true); + /* Cache flush objects bound into GGTT and rebind them. */ + vm = &dev_priv->gtt.base; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { - struct i915_vma *vma = i915_gem_obj_to_vma(obj, - &dev_priv->gtt.base); - if (!vma) - continue; + flush = false; + list_for_each_entry(vma, &obj->vma_list, vma_link) { + if (vma->vm != vm) + continue; - i915_gem_clflush_object(obj, obj->pin_display); - WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); - } + WARN_ON(i915_vma_bind(vma, obj->cache_level, + PIN_UPDATE)); + flush = true; + } + + if (flush) + i915_gem_clflush_object(obj, obj->pin_display); + } if (INTEL_INFO(dev)->gen >= 8) { if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 633bd1f..d61e74a 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -183,8 +183,18 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) if (IS_GEN4(dev)) { uint32_t ddc2 = I915_READ(DCC2); - if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE)) + if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE)) { + /* Since the swizzling may vary within an + * object, we have no idea what the swizzling + * is for any page in particular. Thus we + * cannot migrate tiled pages using the GPU, + * nor can we tell userspace what the exact + * swizzling is for any object. + */ dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES; + swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; + swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; + } } if (dcc == 0xffffffff) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1b61f98..647b140 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4854,6 +4854,9 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc) struct intel_plane *intel_plane; int pipe = intel_crtc->pipe; + if (!intel_crtc->active) + return; + intel_crtc_wait_for_pending_flips(crtc); intel_pre_disable_primary(crtc); @@ -7887,7 +7890,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, int pipe = pipe_config->cpu_transcoder; enum dpio_channel port = vlv_pipe_to_channel(pipe); intel_clock_t clock; - u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2; + u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3; int refclk = 100000; mutex_lock(&dev_priv->sb_lock); @@ -7895,10 +7898,13 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port)); pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port)); pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port)); + pll_dw3 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port)); mutex_unlock(&dev_priv->sb_lock); clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0; - clock.m2 = ((pll_dw0 & 0xff) << 22) | (pll_dw2 & 0x3fffff); + clock.m2 = (pll_dw0 & 0xff) << 22; + if (pll_dw3 & DPIO_CHV_FRAC_DIV_EN) + clock.m2 |= pll_dw2 & 0x3fffff; clock.n = (pll_dw1 >> DPIO_CHV_N_DIV_SHIFT) & 0xf; clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7; clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f; diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index f2daad8..7841970 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -285,7 +285,7 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait) if (wait) { if (!wait_for_completion_timeout(&engine->compl, - msecs_to_jiffies(1))) { + msecs_to_jiffies(100))) { dev_err(dmm->dev, "timed out waiting for done\n"); ret = -ETIMEDOUT; } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index ae2df41..12081e6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -177,7 +177,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p); int omap_framebuffer_pin(struct drm_framebuffer *fb); -int omap_framebuffer_unpin(struct drm_framebuffer *fb); +void omap_framebuffer_unpin(struct drm_framebuffer *fb); void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, struct omap_drm_window *win, struct omap_overlay_info *info); struct drm_connector *omap_framebuffer_get_next_connector( @@ -211,7 +211,7 @@ void omap_gem_dma_sync(struct drm_gem_object *obj, enum dma_data_direction dir); int omap_gem_get_paddr(struct drm_gem_object *obj, dma_addr_t *paddr, bool remap); -int omap_gem_put_paddr(struct drm_gem_object *obj); +void omap_gem_put_paddr(struct drm_gem_object *obj); int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, bool remap); int omap_gem_put_pages(struct drm_gem_object *obj); @@ -236,7 +236,7 @@ static inline int align_pitch(int pitch, int width, int bpp) /* PVR needs alignment to 8 pixels.. right now that is the most * restrictive stride requirement.. */ - return ALIGN(pitch, 8 * bytespp); + return roundup(pitch, 8 * bytespp); } /* map crtc to vblank mask */ diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 0b967e7..51b1219 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -287,10 +287,10 @@ fail: } /* unpin, no longer being scanned out: */ -int omap_framebuffer_unpin(struct drm_framebuffer *fb) +void omap_framebuffer_unpin(struct drm_framebuffer *fb) { struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); - int ret, i, n = drm_format_num_planes(fb->pixel_format); + int i, n = drm_format_num_planes(fb->pixel_format); mutex_lock(&omap_fb->lock); @@ -298,24 +298,16 @@ int omap_framebuffer_unpin(struct drm_framebuffer *fb) if (omap_fb->pin_count > 0) { mutex_unlock(&omap_fb->lock); - return 0; + return; } for (i = 0; i < n; i++) { struct plane *plane = &omap_fb->planes[i]; - ret = omap_gem_put_paddr(plane->bo); - if (ret) - goto fail; + omap_gem_put_paddr(plane->bo); plane->paddr = 0; } mutex_unlock(&omap_fb->lock); - - return 0; - -fail: - mutex_unlock(&omap_fb->lock); - return ret; } struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p) diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 23b5a84..720d16b 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -135,7 +135,7 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled; if (fbdev->ywrap_enabled) { /* need to align pitch to page size if using DMM scrolling */ - mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE); + mode_cmd.pitches[0] = PAGE_ALIGN(mode_cmd.pitches[0]); } /* allocate backing bo */ diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 2ab7780..7ed08fdc 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -808,10 +808,10 @@ fail: /* Release physical address, when DMA is no longer being performed.. this * could potentially unpin and unmap buffers from TILER */ -int omap_gem_put_paddr(struct drm_gem_object *obj) +void omap_gem_put_paddr(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); - int ret = 0; + int ret; mutex_lock(&obj->dev->struct_mutex); if (omap_obj->paddr_cnt > 0) { @@ -821,7 +821,6 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) if (ret) { dev_err(obj->dev->dev, "could not unpin pages: %d\n", ret); - goto fail; } ret = tiler_release(omap_obj->block); if (ret) { @@ -832,9 +831,8 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) omap_obj->block = NULL; } } -fail: + mutex_unlock(&obj->dev->struct_mutex); - return ret; } /* Get rotated scanout address (only valid if already pinned), at the @@ -1378,11 +1376,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL); if (!omap_obj) - goto fail; - - spin_lock(&priv->list_lock); - list_add(&omap_obj->mm_list, &priv->obj_list); - spin_unlock(&priv->list_lock); + return NULL; obj = &omap_obj->base; @@ -1392,11 +1386,19 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, */ omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size, &omap_obj->paddr, GFP_KERNEL); - if (omap_obj->vaddr) - flags |= OMAP_BO_DMA; + if (!omap_obj->vaddr) { + kfree(omap_obj); + + return NULL; + } + flags |= OMAP_BO_DMA; } + spin_lock(&priv->list_lock); + list_add(&omap_obj->mm_list, &priv->obj_list); + spin_unlock(&priv->list_lock); + omap_obj->flags = flags; if (flags & OMAP_BO_TILED) { diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index cfa8276..0989046 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -17,6 +17,7 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_plane_helper.h> @@ -153,9 +154,34 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, dispc_ovl_enable(omap_plane->id, false); } +static int omap_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_crtc_state *crtc_state; + + if (!state->crtc) + return 0; + + crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + if (state->crtc_x < 0 || state->crtc_y < 0) + return -EINVAL; + + if (state->crtc_x + state->crtc_w > crtc_state->adjusted_mode.hdisplay) + return -EINVAL; + + if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay) + return -EINVAL; + + return 0; +} + static const struct drm_plane_helper_funcs omap_plane_helper_funcs = { .prepare_fb = omap_plane_prepare_fb, .cleanup_fb = omap_plane_cleanup_fb, + .atomic_check = omap_plane_atomic_check, .atomic_update = omap_plane_atomic_update, .atomic_disable = omap_plane_atomic_disable, }; diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 4ecf5ca..248953d 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7964,23 +7964,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -7990,23 +7994,27 @@ restart_ih: case 2: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D2 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8016,23 +8024,27 @@ restart_ih: case 3: /* D3 vblank/vline */ switch (src_data) { case 0: /* D3 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[2]) { - drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_vblank(rdev, 2); - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D3 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_vblank(rdev, 2); + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + break; case 1: /* D3 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; - DRM_DEBUG("IH: D3 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8042,23 +8054,27 @@ restart_ih: case 4: /* D4 vblank/vline */ switch (src_data) { case 0: /* D4 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[3]) { - drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_vblank(rdev, 3); - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D4 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_vblank(rdev, 3); + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + break; case 1: /* D4 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; - DRM_DEBUG("IH: D4 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8068,23 +8084,27 @@ restart_ih: case 5: /* D5 vblank/vline */ switch (src_data) { case 0: /* D5 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[4]) { - drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_vblank(rdev, 4); - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D5 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_vblank(rdev, 4); + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + break; case 1: /* D5 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; - DRM_DEBUG("IH: D5 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8094,23 +8114,27 @@ restart_ih: case 6: /* D6 vblank/vline */ switch (src_data) { case 0: /* D6 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[5]) { - drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_vblank(rdev, 5); - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D6 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_vblank(rdev, 5); + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + break; case 1: /* D6 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; - DRM_DEBUG("IH: D6 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8130,88 +8154,112 @@ restart_ih: case 42: /* HPD hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + break; case 1: - if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + break; case 2: - if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + break; case 3: - if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + break; case 4: - if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + break; case 5: - if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + break; case 6: - if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 1\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 1\n"); + break; case 7: - if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 2\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 2\n"); + break; case 8: - if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 3\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 3\n"); + break; case 9: - if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 4\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 4\n"); + break; case 10: - if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 5\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 5\n"); + break; case 11: - if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 6\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 6\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 3a6d483..0acde19 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4924,7 +4924,7 @@ restart_ih: return IRQ_NONE; rptr = rdev->ih.rptr; - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + DRM_DEBUG("evergreen_irq_process start: rptr %d, wptr %d\n", rptr, wptr); /* Order reading of wptr vs. reading of IH ring data */ rmb(); @@ -4942,23 +4942,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4968,23 +4972,27 @@ restart_ih: case 2: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D2 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4994,23 +5002,27 @@ restart_ih: case 3: /* D3 vblank/vline */ switch (src_data) { case 0: /* D3 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[2]) { - drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_vblank(rdev, 2); - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D3 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D3 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_vblank(rdev, 2); + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + break; case 1: /* D3 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; - DRM_DEBUG("IH: D3 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D3 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5020,23 +5032,27 @@ restart_ih: case 4: /* D4 vblank/vline */ switch (src_data) { case 0: /* D4 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[3]) { - drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_vblank(rdev, 3); - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D4 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D4 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_vblank(rdev, 3); + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + break; case 1: /* D4 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; - DRM_DEBUG("IH: D4 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D4 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5046,23 +5062,27 @@ restart_ih: case 5: /* D5 vblank/vline */ switch (src_data) { case 0: /* D5 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[4]) { - drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_vblank(rdev, 4); - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D5 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D5 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_vblank(rdev, 4); + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + break; case 1: /* D5 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; - DRM_DEBUG("IH: D5 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D5 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5072,23 +5092,27 @@ restart_ih: case 6: /* D6 vblank/vline */ switch (src_data) { case 0: /* D6 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[5]) { - drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_vblank(rdev, 5); - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D6 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D6 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_vblank(rdev, 5); + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + break; case 1: /* D6 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; - DRM_DEBUG("IH: D6 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D6 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5108,88 +5132,100 @@ restart_ih: case 42: /* HPD hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); break; case 1: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); break; case 2: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); break; case 3: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); break; case 4: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); break; case 5: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); break; case 6: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 1\n"); break; case 7: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 2\n"); break; case 8: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 3\n"); break; case 9: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 4\n"); break; case 10: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 5\n"); break; case 11: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 6\n"); break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5199,46 +5235,52 @@ restart_ih: case 44: /* hdmi */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI0\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI0\n"); break; case 1: - if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI1\n"); break; case 2: - if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI2\n"); break; case 3: - if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI3\n"); break; case 4: - if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI4\n"); break; case 5: - if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI5\n"); break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8e5aeeb..158872e 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -2162,18 +2162,20 @@ static int cayman_startup(struct radeon_device *rdev) DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); } - ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; - if (ring->ring_size) - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); + if (rdev->family == CHIP_ARUBA) { + ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; + if (ring->ring_size) + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); - ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; - if (ring->ring_size) - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); + ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; + if (ring->ring_size) + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); - if (!r) - r = vce_v1_0_init(rdev); - else if (r != -ENOENT) - DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); + if (!r) + r = vce_v1_0_init(rdev); + if (r) + DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); + } r = radeon_ib_pool_init(rdev); if (r) { @@ -2396,7 +2398,8 @@ void cayman_fini(struct radeon_device *rdev) radeon_irq_kms_fini(rdev); uvd_v1_0_fini(rdev); radeon_uvd_fini(rdev); - radeon_vce_fini(rdev); + if (rdev->family == CHIP_ARUBA) + radeon_vce_fini(rdev); cayman_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 35dafd7..4ea5b10 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -4086,23 +4086,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4112,23 +4116,27 @@ restart_ih: case 5: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4148,46 +4156,53 @@ restart_ih: case 19: /* HPD/DAC hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: HPD1 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); break; case 1: - if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: HPD2 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); break; case 4: - if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: HPD3 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); break; case 5: - if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: HPD4 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); break; case 10: - if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: HPD5 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); break; case 12: - if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: HPD6 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4197,18 +4212,22 @@ restart_ih: case 21: /* hdmi */ switch (src_data) { case 4: - if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI0\n"); - } + if (!(rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: HDMI0 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI0\n"); + break; case 5: - if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI1\n"); - } + if (!(rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: HDMI1 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI1\n"); + break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index 09e3f39..98f9ada 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c @@ -2483,7 +2483,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev, struct drm_buf *buf; u32 *buffer; const u8 __user *data; - int size, pass_size; + unsigned int size, pass_size; u64 src_offset, dst_offset; if (!radeon_check_offset(dev_priv, tex->offset)) { diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 45e5406..afaf346 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -91,15 +91,34 @@ static void radeon_show_cursor(struct drm_crtc *crtc) struct radeon_device *rdev = crtc->dev->dev_private; if (ASIC_IS_DCE4(rdev)) { + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(radeon_crtc->cursor_addr)); + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + lower_32_bits(radeon_crtc->cursor_addr)); WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); } else if (ASIC_IS_AVIVO(rdev)) { + if (rdev->family >= CHIP_RV770) { + if (radeon_crtc->crtc_id) + WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, + upper_32_bits(radeon_crtc->cursor_addr)); + else + WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, + upper_32_bits(radeon_crtc->cursor_addr)); + } + + WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + lower_32_bits(radeon_crtc->cursor_addr)); WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); } else { + /* offset is from DISP(2)_BASE_ADDRESS */ + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, + radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr); + switch (radeon_crtc->crtc_id) { case 0: WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); @@ -205,8 +224,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y) | (x << 16) | y)); /* offset is from DISP(2)_BASE_ADDRESS */ - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + - (yorigin * 256))); + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, + radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr + + yorigin * 256); } radeon_crtc->cursor_x = x; @@ -227,53 +247,6 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, return ret; } -static int radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj) -{ - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct radeon_device *rdev = crtc->dev->dev_private; - struct radeon_bo *robj = gem_to_radeon_bo(obj); - uint64_t gpu_addr; - int ret; - - ret = radeon_bo_reserve(robj, false); - if (unlikely(ret != 0)) - goto fail; - /* Only 27 bit offset for legacy cursor */ - ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, - ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, - &gpu_addr); - radeon_bo_unreserve(robj); - if (ret) - goto fail; - - if (ASIC_IS_DCE4(rdev)) { - WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, - upper_32_bits(gpu_addr)); - WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, - gpu_addr & 0xffffffff); - } else if (ASIC_IS_AVIVO(rdev)) { - if (rdev->family >= CHIP_RV770) { - if (radeon_crtc->crtc_id) - WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); - else - WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); - } - WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, - gpu_addr & 0xffffffff); - } else { - radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; - /* offset is from DISP(2)_BASE_ADDRESS */ - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); - } - - return 0; - -fail: - drm_gem_object_unreference_unlocked(obj); - - return ret; -} - int radeon_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, @@ -283,7 +256,9 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, int32_t hot_y) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; struct drm_gem_object *obj; + struct radeon_bo *robj; int ret; if (!handle) { @@ -305,6 +280,23 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, return -ENOENT; } + robj = gem_to_radeon_bo(obj); + ret = radeon_bo_reserve(robj, false); + if (ret != 0) { + drm_gem_object_unreference_unlocked(obj); + return ret; + } + /* Only 27 bit offset for legacy cursor */ + ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, + &radeon_crtc->cursor_addr); + radeon_bo_unreserve(robj); + if (ret) { + DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret); + drm_gem_object_unreference_unlocked(obj); + return ret; + } + radeon_crtc->cursor_width = width; radeon_crtc->cursor_height = height; @@ -323,13 +315,7 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, radeon_crtc->cursor_hot_y = hot_y; } - ret = radeon_set_cursor(crtc, obj); - - if (ret) - DRM_ERROR("radeon_set_cursor returned %d, not changing cursor\n", - ret); - else - radeon_show_cursor(crtc); + radeon_show_cursor(crtc); radeon_lock_cursor(crtc, false); @@ -341,8 +327,7 @@ unpin: radeon_bo_unpin(robj); radeon_bo_unreserve(robj); } - if (radeon_crtc->cursor_bo != obj) - drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); + drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); } radeon_crtc->cursor_bo = obj; @@ -360,7 +345,6 @@ unpin: void radeon_cursor_reset(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - int ret; if (radeon_crtc->cursor_bo) { radeon_lock_cursor(crtc, true); @@ -368,12 +352,7 @@ void radeon_cursor_reset(struct drm_crtc *crtc) radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x, radeon_crtc->cursor_y); - ret = radeon_set_cursor(crtc, radeon_crtc->cursor_bo); - if (ret) - DRM_ERROR("radeon_set_cursor returned %d, not showing " - "cursor\n", ret); - else - radeon_show_cursor(crtc); + radeon_show_cursor(crtc); radeon_lock_cursor(crtc, false); } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 2593b11..d8319da 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1080,6 +1080,22 @@ static bool radeon_check_pot_argument(int arg) } /** + * Determine a sensible default GART size according to ASIC family. + * + * @family ASIC family name + */ +static int radeon_gart_size_auto(enum radeon_family family) +{ + /* default to a larger gart size on newer asics */ + if (family >= CHIP_TAHITI) + return 2048; + else if (family >= CHIP_RV770) + return 1024; + else + return 512; +} + +/** * radeon_check_arguments - validate module params * * @rdev: radeon_device pointer @@ -1097,27 +1113,17 @@ static void radeon_check_arguments(struct radeon_device *rdev) } if (radeon_gart_size == -1) { - /* default to a larger gart size on newer asics */ - if (rdev->family >= CHIP_RV770) - radeon_gart_size = 1024; - else - radeon_gart_size = 512; + radeon_gart_size = radeon_gart_size_auto(rdev->family); } /* gtt size must be power of two and greater or equal to 32M */ if (radeon_gart_size < 32) { dev_warn(rdev->dev, "gart size (%d) too small\n", radeon_gart_size); - if (rdev->family >= CHIP_RV770) - radeon_gart_size = 1024; - else - radeon_gart_size = 512; + radeon_gart_size = radeon_gart_size_auto(rdev->family); } else if (!radeon_check_pot_argument(radeon_gart_size)) { dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", radeon_gart_size); - if (rdev->family >= CHIP_RV770) - radeon_gart_size = 1024; - else - radeon_gart_size = 512; + radeon_gart_size = radeon_gart_size_auto(rdev->family); } rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; @@ -1572,11 +1578,21 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); } - /* unpin the front buffers */ + /* unpin the front buffers and cursors */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb); struct radeon_bo *robj; + if (radeon_crtc->cursor_bo) { + struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); + r = radeon_bo_reserve(robj, false); + if (r == 0) { + radeon_bo_unpin(robj); + radeon_bo_unreserve(robj); + } + } + if (rfb == NULL || rfb->obj == NULL) { continue; } @@ -1639,6 +1655,7 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) { struct drm_connector *connector; struct radeon_device *rdev = dev->dev_private; + struct drm_crtc *crtc; int r; if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) @@ -1678,6 +1695,27 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) radeon_restore_bios_scratch_regs(rdev); + /* pin cursors */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + if (radeon_crtc->cursor_bo) { + struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); + r = radeon_bo_reserve(robj, false); + if (r == 0) { + /* Only 27 bit offset for legacy cursor */ + r = radeon_bo_pin_restricted(robj, + RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? + 0 : 1 << 27, + &radeon_crtc->cursor_addr); + if (r != 0) + DRM_ERROR("Failed to pin cursor BO (%d)\n", r); + radeon_bo_unreserve(robj); + } + } + } + /* init dig PHYs, disp eng pll */ if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 634793e..aeb6767 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -257,6 +257,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, } info->par = rfbdev; + info->skip_vt_switch = true; ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); if (ret) { diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index ac3c131..013ec71 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -428,7 +428,6 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_busy *args = data; struct drm_gem_object *gobj; struct radeon_bo *robj; @@ -440,10 +439,16 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, return -ENOENT; } robj = gem_to_radeon_bo(gobj); - r = radeon_bo_wait(robj, &cur_placement, true); + + r = reservation_object_test_signaled_rcu(robj->tbo.resv, true); + if (r == 0) + r = -EBUSY; + else + r = 0; + + cur_placement = ACCESS_ONCE(robj->tbo.mem.mem_type); args->domain = radeon_mem_type_to_domain(cur_placement); drm_gem_object_unreference_unlocked(gobj); - r = radeon_gem_handle_lockup(rdev, r); return r; } @@ -471,6 +476,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, r = ret; /* Flush HDP cache via MMIO if necessary */ + cur_placement = ACCESS_ONCE(robj->tbo.mem.mem_type); if (rdev->asic->mmio_hdp_flush && radeon_mem_type_to_domain(cur_placement) == RADEON_GEM_DOMAIN_VRAM) robj->rdev->asic->mmio_hdp_flush(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 6de5459..07909d8 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -343,7 +343,6 @@ struct radeon_crtc { int max_cursor_width; int max_cursor_height; uint32_t legacy_display_base_addr; - uint32_t legacy_cursor_offset; enum radeon_rmx_type rmx_type; u8 h_border; u8 v_border; diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index ec10533..48d97c0 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -493,38 +493,35 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, } if (bo_va->it.start || bo_va->it.last) { - spin_lock(&vm->status_lock); - if (list_empty(&bo_va->vm_status)) { - /* add a clone of the bo_va to clear the old address */ - struct radeon_bo_va *tmp; - spin_unlock(&vm->status_lock); - tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); - if (!tmp) { - mutex_unlock(&vm->mutex); - r = -ENOMEM; - goto error_unreserve; - } - tmp->it.start = bo_va->it.start; - tmp->it.last = bo_va->it.last; - tmp->vm = vm; - tmp->bo = radeon_bo_ref(bo_va->bo); - spin_lock(&vm->status_lock); - list_add(&tmp->vm_status, &vm->freed); + /* add a clone of the bo_va to clear the old address */ + struct radeon_bo_va *tmp; + tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); + if (!tmp) { + mutex_unlock(&vm->mutex); + r = -ENOMEM; + goto error_unreserve; } - spin_unlock(&vm->status_lock); + tmp->it.start = bo_va->it.start; + tmp->it.last = bo_va->it.last; + tmp->vm = vm; + tmp->bo = radeon_bo_ref(bo_va->bo); interval_tree_remove(&bo_va->it, &vm->va); + spin_lock(&vm->status_lock); bo_va->it.start = 0; bo_va->it.last = 0; + list_del_init(&bo_va->vm_status); + list_add(&tmp->vm_status, &vm->freed); + spin_unlock(&vm->status_lock); } if (soffset || eoffset) { + spin_lock(&vm->status_lock); bo_va->it.start = soffset; bo_va->it.last = eoffset - 1; - interval_tree_insert(&bo_va->it, &vm->va); - spin_lock(&vm->status_lock); list_add(&bo_va->vm_status, &vm->cleared); spin_unlock(&vm->status_lock); + interval_tree_insert(&bo_va->it, &vm->va); } bo_va->flags = flags; @@ -1158,7 +1155,8 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, list_for_each_entry(bo_va, &bo->va, bo_list) { spin_lock(&bo_va->vm->status_lock); - if (list_empty(&bo_va->vm_status)) + if (list_empty(&bo_va->vm_status) && + (bo_va->it.start || bo_va->it.last)) list_add(&bo_va->vm_status, &bo_va->vm->invalidated); spin_unlock(&bo_va->vm->status_lock); } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 26388b5..07037e3 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6466,23 +6466,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6492,23 +6496,27 @@ restart_ih: case 2: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D2 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6518,23 +6526,27 @@ restart_ih: case 3: /* D3 vblank/vline */ switch (src_data) { case 0: /* D3 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[2]) { - drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_vblank(rdev, 2); - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D3 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_vblank(rdev, 2); + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + break; case 1: /* D3 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; - DRM_DEBUG("IH: D3 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6544,23 +6556,27 @@ restart_ih: case 4: /* D4 vblank/vline */ switch (src_data) { case 0: /* D4 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[3]) { - drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_vblank(rdev, 3); - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D4 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_vblank(rdev, 3); + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + break; case 1: /* D4 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; - DRM_DEBUG("IH: D4 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6570,23 +6586,27 @@ restart_ih: case 5: /* D5 vblank/vline */ switch (src_data) { case 0: /* D5 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[4]) { - drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_vblank(rdev, 4); - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D5 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_vblank(rdev, 4); + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + break; case 1: /* D5 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; - DRM_DEBUG("IH: D5 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6596,23 +6616,27 @@ restart_ih: case 6: /* D6 vblank/vline */ switch (src_data) { case 0: /* D6 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[5]) { - drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_vblank(rdev, 5); - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D6 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_vblank(rdev, 5); + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + break; case 1: /* D6 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; - DRM_DEBUG("IH: D6 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6632,88 +6656,112 @@ restart_ih: case 42: /* HPD hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + break; case 1: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + break; case 2: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + break; case 3: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + break; case 4: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + break; case 5: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + break; case 6: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 1\n"); + break; case 7: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 2\n"); + break; case 8: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 3\n"); + break; case 9: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 4\n"); + break; case 10: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 5\n"); + break; case 11: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 6\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 35ac237..577d58d 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -633,6 +633,7 @@ config I2C_MPC config I2C_MT65XX tristate "MediaTek I2C adapter" depends on ARCH_MEDIATEK || COMPILE_TEST + depends on HAS_DMA help This selects the MediaTek(R) Integrated Inter Circuit bus driver for MT65xx and MT81xx. diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index 19b2d68..f325663 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -764,12 +764,15 @@ static int jz4780_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c->clk)) return PTR_ERR(i2c->clk); - clk_prepare_enable(i2c->clk); + ret = clk_prepare_enable(i2c->clk); + if (ret) + return ret; - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &clk_freq)) { + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &clk_freq); + if (ret) { dev_err(&pdev->dev, "clock-frequency not specified in DT"); - return clk_freq; + goto err; } i2c->speed = clk_freq / 1000; @@ -790,10 +793,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev) i2c->irq = platform_get_irq(pdev, 0); ret = devm_request_irq(&pdev->dev, i2c->irq, jz4780_i2c_irq, 0, dev_name(&pdev->dev), i2c); - if (ret) { - ret = -ENODEV; + if (ret) goto err; - } ret = i2c_add_adapter(&i2c->adap); if (ret < 0) { diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index dcca707..1c9cb65 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -419,6 +419,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) rc = i2c_add_adapter(adapter); if (rc) { dev_err(&pdev->dev, "Adapter registeration failed\n"); + mbox_free_channel(ctx->mbox_chan); return rc; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 069a41f..e6d4935 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1012,6 +1012,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device); */ void i2c_unregister_device(struct i2c_client *client) { + if (client->dev.of_node) + of_node_clear_flag(client->dev.of_node, OF_POPULATED); device_unregister(&client->dev); } EXPORT_SYMBOL_GPL(i2c_unregister_device); @@ -1320,8 +1322,11 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); - for_each_available_child_of_node(adap->dev.of_node, node) + for_each_available_child_of_node(adap->dev.of_node, node) { + if (of_node_test_and_set_flag(node, OF_POPULATED)) + continue; of_i2c_register_device(adap, node); + } } static int of_dev_node_match(struct device *dev, void *data) @@ -1853,6 +1858,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, if (adap == NULL) return NOTIFY_OK; /* not for us */ + if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) { + put_device(&adap->dev); + return NOTIFY_OK; + } + client = of_i2c_register_device(adap, rd->dn); put_device(&adap->dev); @@ -1863,6 +1873,10 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, } break; case OF_RECONFIG_CHANGE_REMOVE: + /* already depopulated? */ + if (!of_node_check_flag(rd->dn, OF_POPULATED)) + return NOTIFY_OK; + /* find our device by node */ client = of_find_i2c_device_by_node(rd->dn); if (client == NULL) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 62641f2..5b5f403 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -771,7 +771,7 @@ static const struct attribute_group *elan_sysfs_groups[] = { */ static void elan_report_contact(struct elan_tp_data *data, int contact_num, bool contact_valid, - bool hover_event, u8 *finger_data) + u8 *finger_data) { struct input_dev *input = data->input; unsigned int pos_x, pos_y; @@ -815,9 +815,7 @@ static void elan_report_contact(struct elan_tp_data *data, input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, pos_x); input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); - input_report_abs(input, ABS_MT_DISTANCE, hover_event); - input_report_abs(input, ABS_MT_PRESSURE, - hover_event ? 0 : scaled_pressure); + input_report_abs(input, ABS_MT_PRESSURE, scaled_pressure); input_report_abs(input, ABS_TOOL_WIDTH, mk_x); input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); @@ -839,14 +837,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) hover_event = hover_info & 0x40; for (i = 0; i < ETP_MAX_FINGERS; i++) { contact_valid = tp_info & (1U << (3 + i)); - elan_report_contact(data, i, contact_valid, hover_event, - finger_data); + elan_report_contact(data, i, contact_valid, finger_data); if (contact_valid) finger_data += ETP_FINGER_DATA_LEN; } input_report_key(input, BTN_LEFT, tp_info & 0x01); + input_report_abs(input, ABS_DISTANCE, hover_event != 0); input_mt_report_pointer_emulation(input, true); input_sync(input); } @@ -922,6 +920,7 @@ static int elan_setup_input_device(struct elan_tp_data *data) input_abs_set_res(input, ABS_Y, data->y_res); input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0); input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0); + input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0); /* And MT parameters */ input_set_abs_params(input, ABS_MT_POSITION_X, 0, data->max_x, 0, 0); @@ -934,7 +933,6 @@ static int elan_setup_input_device(struct elan_tp_data *data) ETP_FINGER_WIDTH * max_width, 0, 0); input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, ETP_FINGER_WIDTH * min_width, 0, 0); - input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0); data->input = input; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 35c8d0c..3a32caf 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1199,7 +1199,7 @@ static void set_input_params(struct psmouse *psmouse, ABS_MT_POSITION_Y); /* Image sensors can report per-contact pressure */ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); - input_mt_init_slots(dev, 3, INPUT_MT_POINTER | INPUT_MT_TRACK); + input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK); /* Image sensors can signal 4 and 5 finger clicks */ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 8d7e1c8..4dd8826 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1055,7 +1055,7 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, processor = (struct acpi_madt_generic_interrupt *)header; - if (BAD_MADT_ENTRY(processor, end)) + if (BAD_MADT_GICC_ENTRY(processor, end)) return -EINVAL; /* diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 4400edd..b7d54d4 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -257,16 +257,6 @@ int gic_get_c0_fdc_int(void) return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; } - /* - * Some cores claim the FDC is routable but it doesn't actually seem to - * be connected. - */ - switch (current_cpu_type()) { - case CPU_INTERAPTIV: - case CPU_PROAPTIV: - return -1; - } - return irq_create_mapping(gic_irq_domain, GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); } diff --git a/drivers/irqchip/irq-sa11x0.c b/drivers/irqchip/irq-sa11x0.c index 46df287..61bb28d 100644 --- a/drivers/irqchip/irq-sa11x0.c +++ b/drivers/irqchip/irq-sa11x0.c @@ -70,7 +70,6 @@ static int sa1100_normal_irqdomain_map(struct irq_domain *d, { irq_set_chip_and_handler(irq, &sa1100_normal_chip, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); return 0; } diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 8911e51..3a27a84 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -2074,14 +2074,8 @@ static int gpmc_probe_dt(struct platform_device *pdev) ret = gpmc_probe_nand_child(pdev, child); else if (of_node_cmp(child->name, "onenand") == 0) ret = gpmc_probe_onenand_child(pdev, child); - else if (of_node_cmp(child->name, "ethernet") == 0 || - of_node_cmp(child->name, "nor") == 0 || - of_node_cmp(child->name, "uart") == 0) + else ret = gpmc_probe_generic_child(pdev, child); - - if (WARN(ret < 0, "%s: probing gpmc child %s failed\n", - __func__, child->full_name)) - of_node_put(child); } return 0; diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 0c77240..729e085 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -23,6 +23,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) afu = cxl_pci_to_afu(dev); + get_device(&afu->dev); ctx = cxl_context_alloc(); if (IS_ERR(ctx)) return ctx; @@ -31,6 +32,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) rc = cxl_context_init(ctx, afu, false, NULL); if (rc) { kfree(ctx); + put_device(&afu->dev); return ERR_PTR(-ENOMEM); } cxl_assign_psn_space(ctx); @@ -60,6 +62,8 @@ int cxl_release_context(struct cxl_context *ctx) if (ctx->status != CLOSED) return -EBUSY; + put_device(&ctx->afu->dev); + cxl_context_free(ctx); return 0; @@ -159,7 +163,6 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, } ctx->status = STARTED; - get_device(&ctx->afu->dev); out: mutex_unlock(&ctx->status_mutex); return rc; @@ -175,12 +178,7 @@ EXPORT_SYMBOL_GPL(cxl_process_element); /* Stop a context. Returns 0 on success, otherwise -Errno */ int cxl_stop_context(struct cxl_context *ctx) { - int rc; - - rc = __detach_context(ctx); - if (!rc) - put_device(&ctx->afu->dev); - return rc; + return __detach_context(ctx); } EXPORT_SYMBOL_GPL(cxl_stop_context); diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c index 2a4c80a..1287148 100644 --- a/drivers/misc/cxl/context.c +++ b/drivers/misc/cxl/context.c @@ -113,11 +113,11 @@ static int cxl_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { area = ctx->afu->psn_phys; - if (offset > ctx->afu->adapter->ps_size) + if (offset >= ctx->afu->adapter->ps_size) return VM_FAULT_SIGBUS; } else { area = ctx->psn_phys; - if (offset > ctx->psn_size) + if (offset >= ctx->psn_size) return VM_FAULT_SIGBUS; } @@ -145,8 +145,16 @@ static const struct vm_operations_struct cxl_mmap_vmops = { */ int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma) { + u64 start = vma->vm_pgoff << PAGE_SHIFT; u64 len = vma->vm_end - vma->vm_start; - len = min(len, ctx->psn_size); + + if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { + if (start + len > ctx->afu->adapter->ps_size) + return -EINVAL; + } else { + if (start + len > ctx->psn_size) + return -EINVAL; + } if (ctx->afu->current_mode != CXL_MODE_DEDICATED) { /* make sure there is a valid per process space for this AFU */ diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 833348e..4a164ab 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c @@ -73,7 +73,7 @@ static inline void cxl_slbia_core(struct mm_struct *mm) spin_lock(&adapter->afu_list_lock); for (slice = 0; slice < adapter->slices; slice++) { afu = adapter->afu[slice]; - if (!afu->enabled) + if (!afu || !afu->enabled) continue; rcu_read_lock(); idr_for_each_entry(&afu->contexts_idr, ctx, id) diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index c68ef58..32ad097 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -539,7 +539,7 @@ err: static void cxl_unmap_slice_regs(struct cxl_afu *afu) { - if (afu->p1n_mmio) + if (afu->p2n_mmio) iounmap(afu->p2n_mmio); if (afu->p1n_mmio) iounmap(afu->p1n_mmio); diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c index b1d1983a..2eba002 100644 --- a/drivers/misc/cxl/vphb.c +++ b/drivers/misc/cxl/vphb.c @@ -112,9 +112,10 @@ static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn, unsigned long addr; phb = pci_bus_to_host(bus); - afu = (struct cxl_afu *)phb->private_data; if (phb == NULL) return PCIBIOS_DEVICE_NOT_FOUND; + afu = (struct cxl_afu *)phb->private_data; + if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num) return PCIBIOS_DEVICE_NOT_FOUND; if (offset >= (unsigned long)phb->cfg_data) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 357b6ae..458aa5a 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -552,22 +552,6 @@ void mei_cl_bus_rx_event(struct mei_cl *cl) schedule_work(&device->event_work); } -void mei_cl_bus_remove_devices(struct mei_device *dev) -{ - struct mei_cl *cl, *next; - - mutex_lock(&dev->device_lock); - list_for_each_entry_safe(cl, next, &dev->device_list, device_link) { - if (cl->device) - mei_cl_remove_device(cl->device); - - list_del(&cl->device_link); - mei_cl_unlink(cl); - kfree(cl); - } - mutex_unlock(&dev->device_lock); -} - int __init mei_cl_bus_init(void) { return bus_register(&mei_cl_bus_type); diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 94514b2..00c3865 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -333,8 +333,6 @@ void mei_stop(struct mei_device *dev) mei_nfc_host_exit(dev); - mei_cl_bus_remove_devices(dev); - mutex_lock(&dev->device_lock); mei_wd_stop(dev); diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c index b983c4e..290ef30 100644 --- a/drivers/misc/mei/nfc.c +++ b/drivers/misc/mei/nfc.c @@ -402,11 +402,12 @@ void mei_nfc_host_exit(struct mei_device *dev) cldev->priv_data = NULL; - mutex_lock(&dev->device_lock); /* Need to remove the device here * since mei_nfc_free will unlink the clients */ mei_cl_remove_device(cldev); + + mutex_lock(&dev->device_lock); mei_nfc_free(ndev); mutex_unlock(&dev->device_lock); } diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 8eb22c0..7e2c43f 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -535,8 +535,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, __func__, dimm_name, cmd_name, i); return -ENXIO; } - if (!access_ok(VERIFY_READ, p + in_len, in_size)) - return -EFAULT; if (in_len < sizeof(in_env)) copy = min_t(u32, sizeof(in_env) - in_len, in_size); else @@ -557,8 +555,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, __func__, dimm_name, cmd_name, i); return -EFAULT; } - if (!access_ok(VERIFY_WRITE, p + in_len + out_len, out_size)) - return -EFAULT; if (out_len < sizeof(out_env)) copy = min_t(u32, sizeof(out_env) - out_len, out_size); else @@ -570,9 +566,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, } buf_len = out_len + in_len; - if (!access_ok(VERIFY_WRITE, p, sizeof(buf_len))) - return -EFAULT; - if (buf_len > ND_IOCTL_MAX_BUFLEN) { dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__, dimm_name, cmd_name, buf_len, @@ -706,8 +699,10 @@ int __init nvdimm_bus_init(void) nvdimm_major = rc; nd_class = class_create(THIS_MODULE, "nd"); - if (IS_ERR(nd_class)) + if (IS_ERR(nd_class)) { + rc = PTR_ERR(nd_class); goto err_class; + } return 0; diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 515f338..49c1720 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -7,7 +7,6 @@ * Bjorn Helgaas <bjorn.helgaas@hp.com> */ -#include <linux/acpi.h> #include <linux/pnp.h> #include <linux/device.h> #include <linux/init.h> @@ -23,41 +22,25 @@ static const struct pnp_device_id pnp_dev_table[] = { {"", 0} }; -#ifdef CONFIG_ACPI -static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) -{ - u8 space_id = io ? ACPI_ADR_SPACE_SYSTEM_IO : ACPI_ADR_SPACE_SYSTEM_MEMORY; - return !acpi_reserve_region(start, length, space_id, IORESOURCE_BUSY, desc); -} -#else -static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) -{ - struct resource *res; - - res = io ? request_region(start, length, desc) : - request_mem_region(start, length, desc); - if (res) { - res->flags &= ~IORESOURCE_BUSY; - return true; - } - return false; -} -#endif - static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) { char *regionid; const char *pnpid = dev_name(&dev->dev); resource_size_t start = r->start, end = r->end; - bool reserved; + struct resource *res; regionid = kmalloc(16, GFP_KERNEL); if (!regionid) return; snprintf(regionid, 16, "pnp %s", pnpid); - reserved = __reserve_range(start, end - start + 1, !!port, regionid); - if (!reserved) + if (port) + res = request_region(start, end - start + 1, regionid); + else + res = request_mem_region(start, end - start + 1, regionid); + if (res) + res->flags &= ~IORESOURCE_BUSY; + else kfree(regionid); /* @@ -66,7 +49,7 @@ static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) * have double reservations. */ dev_info(&dev->dev, "%pR %s reserved\n", r, - reserved ? "has been" : "could not be"); + res ? "has been" : "could not be"); } static void reserve_resources_of_dev(struct pnp_dev *dev) diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 86621fa..735355b 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -121,6 +121,7 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS]; #define REG_3 0x0004a0 #define REG_4 0x000600 #define REG_6 0x000800 +#define REG_7 0x000804 #define REG_8 0x000820 #define REG_9 0x000a04 #define REG_10 0x018000 @@ -135,6 +136,8 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS]; #define REG_21 0x200218 #define REG_22 0x0005a0 #define REG_23 0x0005c0 +#define REG_24 0x000808 +#define REG_25 0x000b00 #define REG_26 0x200118 #define REG_27 0x200308 #define REG_32 0x21003c @@ -429,6 +432,9 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) #define SET_LENXY_START_RECFILL(fb, lenxy) \ WRITE_WORD(lenxy, fb, REG_9) +#define SETUP_COPYAREA(fb) \ + WRITE_BYTE(0, fb, REG_16b1) + static void HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) { @@ -1004,6 +1010,36 @@ stifb_blank(int blank_mode, struct fb_info *info) return 0; } +static void +stifb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct stifb_info *fb = container_of(info, struct stifb_info, info); + + SETUP_COPYAREA(fb); + + SETUP_HW(fb); + if (fb->info.var.bits_per_pixel == 32) { + WRITE_WORD(0xBBA0A000, fb, REG_10); + + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff); + } else { + WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10); + + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff); + } + + NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, + IBOvals(RopSrc, MaskAddrOffset(0), + BitmapExtent08, StaticReg(1), + DataDynamic, MaskOtc, BGx(0), FGx(0))); + + WRITE_WORD(((area->sx << 16) | area->sy), fb, REG_24); + WRITE_WORD(((area->width << 16) | area->height), fb, REG_7); + WRITE_WORD(((area->dx << 16) | area->dy), fb, REG_25); + + SETUP_FB(fb); +} + static void __init stifb_init_display(struct stifb_info *fb) { @@ -1069,7 +1105,7 @@ static struct fb_ops stifb_ops = { .fb_setcolreg = stifb_setcolreg, .fb_blank = stifb_blank, .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, + .fb_copyarea = stifb_copyarea, .fb_imageblit = cfb_imageblit, }; @@ -1258,7 +1294,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) info->fbops = &stifb_ops; info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); info->screen_size = fix->smem_len; - info->flags = FBINFO_DEFAULT; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA; info->pseudo_palette = &fb->pseudo_palette; /* This has to be done !!! */ diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 510040b..b1dc518 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -540,8 +540,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, unlock_new_inode(inode); return inode; error: - unlock_new_inode(inode); - iput(inode); + iget_failed(inode); return ERR_PTR(retval); } diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 09e44337..e8aa57d 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -149,8 +149,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, unlock_new_inode(inode); return inode; error: - unlock_new_inode(inode); - iput(inode); + iget_failed(inode); return ERR_PTR(retval); } diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 0ef5cc1..81220b2 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -44,6 +44,8 @@ #define BTRFS_INODE_IN_DELALLOC_LIST 9 #define BTRFS_INODE_READDIO_NEED_LOCK 10 #define BTRFS_INODE_HAS_PROPS 11 +/* DIO is ready to submit */ +#define BTRFS_INODE_DIO_READY 12 /* * The following 3 bits are meant only for the btree inode. * When any of them is set, it means an error happened while writing an diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 80a9aef..aac314e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1778,6 +1778,7 @@ struct btrfs_fs_info { spinlock_t unused_bgs_lock; struct list_head unused_bgs; struct mutex unused_bg_unpin_mutex; + struct mutex delete_unused_bgs_mutex; /* For btrfs to record security options */ struct security_mnt_opts security_opts; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3f43bfea..a9aadb2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1751,6 +1751,7 @@ static int cleaner_kthread(void *arg) { struct btrfs_root *root = arg; int again; + struct btrfs_trans_handle *trans; do { again = 0; @@ -1772,7 +1773,6 @@ static int cleaner_kthread(void *arg) } btrfs_run_delayed_iputs(root); - btrfs_delete_unused_bgs(root->fs_info); again = btrfs_clean_one_deleted_snapshot(root); mutex_unlock(&root->fs_info->cleaner_mutex); @@ -1781,6 +1781,16 @@ static int cleaner_kthread(void *arg) * needn't do anything special here. */ btrfs_run_defrag_inodes(root->fs_info); + + /* + * Acquires fs_info->delete_unused_bgs_mutex to avoid racing + * with relocation (btrfs_relocate_chunk) and relocation + * acquires fs_info->cleaner_mutex (btrfs_relocate_block_group) + * after acquiring fs_info->delete_unused_bgs_mutex. So we + * can't hold, nor need to, fs_info->cleaner_mutex when deleting + * unused block groups. + */ + btrfs_delete_unused_bgs(root->fs_info); sleep: if (!try_to_freeze() && !again) { set_current_state(TASK_INTERRUPTIBLE); @@ -1789,6 +1799,34 @@ sleep: __set_current_state(TASK_RUNNING); } } while (!kthread_should_stop()); + + /* + * Transaction kthread is stopped before us and wakes us up. + * However we might have started a new transaction and COWed some + * tree blocks when deleting unused block groups for example. So + * make sure we commit the transaction we started to have a clean + * shutdown when evicting the btree inode - if it has dirty pages + * when we do the final iput() on it, eviction will trigger a + * writeback for it which will fail with null pointer dereferences + * since work queues and other resources were already released and + * destroyed by the time the iput/eviction/writeback is made. + */ + trans = btrfs_attach_transaction(root); + if (IS_ERR(trans)) { + if (PTR_ERR(trans) != -ENOENT) + btrfs_err(root->fs_info, + "cleaner transaction attach returned %ld", + PTR_ERR(trans)); + } else { + int ret; + + ret = btrfs_commit_transaction(trans, root); + if (ret) + btrfs_err(root->fs_info, + "cleaner open transaction commit returned %d", + ret); + } + return 0; } @@ -2492,6 +2530,7 @@ int open_ctree(struct super_block *sb, spin_lock_init(&fs_info->unused_bgs_lock); rwlock_init(&fs_info->tree_mod_log_lock); mutex_init(&fs_info->unused_bg_unpin_mutex); + mutex_init(&fs_info->delete_unused_bgs_mutex); mutex_init(&fs_info->reloc_mutex); mutex_init(&fs_info->delalloc_root_mutex); seqlock_init(&fs_info->profiles_lock); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 38b76cc..1c2bd17 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -9889,6 +9889,8 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) } spin_unlock(&fs_info->unused_bgs_lock); + mutex_lock(&root->fs_info->delete_unused_bgs_mutex); + /* Don't want to race with allocators so take the groups_sem */ down_write(&space_info->groups_sem); spin_lock(&block_group->lock); @@ -9983,6 +9985,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) end_trans: btrfs_end_transaction(trans, root); next: + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); btrfs_put_block_group(block_group); spin_lock(&fs_info->unused_bgs_lock); } diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index f6a596d..d4a582a 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -246,6 +246,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) { struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; struct rb_root *rbroot = &root->free_ino_pinned->free_space_offset; + spinlock_t *rbroot_lock = &root->free_ino_pinned->tree_lock; struct btrfs_free_space *info; struct rb_node *n; u64 count; @@ -254,24 +255,30 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) return; while (1) { + bool add_to_ctl = true; + + spin_lock(rbroot_lock); n = rb_first(rbroot); - if (!n) + if (!n) { + spin_unlock(rbroot_lock); break; + } info = rb_entry(n, struct btrfs_free_space, offset_index); BUG_ON(info->bitmap); /* Logic error */ if (info->offset > root->ino_cache_progress) - goto free; + add_to_ctl = false; else if (info->offset + info->bytes > root->ino_cache_progress) count = root->ino_cache_progress - info->offset + 1; else count = info->bytes; - __btrfs_add_free_space(ctl, info->offset, count); -free: rb_erase(&info->offset_index, rbroot); - kfree(info); + spin_unlock(rbroot_lock); + if (add_to_ctl) + __btrfs_add_free_space(ctl, info->offset, count); + kmem_cache_free(btrfs_free_space_cachep, info); } } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 855935f..b33c0cf 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4989,8 +4989,9 @@ static void evict_inode_truncate_pages(struct inode *inode) /* * Keep looping until we have no more ranges in the io tree. * We can have ongoing bios started by readpages (called from readahead) - * that didn't get their end io callbacks called yet or they are still - * in progress ((extent_io.c:end_bio_extent_readpage()). This means some + * that have their endio callback (extent_io.c:end_bio_extent_readpage) + * still in progress (unlocked the pages in the bio but did not yet + * unlocked the ranges in the io tree). Therefore this means some * ranges can still be locked and eviction started because before * submitting those bios, which are executed by a separate task (work * queue kthread), inode references (inode->i_count) were not taken @@ -7546,6 +7547,7 @@ unlock: current->journal_info = outstanding_extents; btrfs_free_reserved_data_space(inode, len); + set_bit(BTRFS_INODE_DIO_READY, &BTRFS_I(inode)->runtime_flags); } /* @@ -7871,8 +7873,6 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) struct bio *dio_bio; int ret; - if (err) - goto out_done; again: ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, &ordered_offset, @@ -7895,7 +7895,6 @@ out_test: ordered = NULL; goto again; } -out_done: dio_bio = dip->dio_bio; kfree(dip); @@ -8163,9 +8162,8 @@ out_err: static void btrfs_submit_direct(int rw, struct bio *dio_bio, struct inode *inode, loff_t file_offset) { - struct btrfs_root *root = BTRFS_I(inode)->root; - struct btrfs_dio_private *dip; - struct bio *io_bio; + struct btrfs_dio_private *dip = NULL; + struct bio *io_bio = NULL; struct btrfs_io_bio *btrfs_bio; int skip_sum; int write = rw & REQ_WRITE; @@ -8182,7 +8180,7 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, dip = kzalloc(sizeof(*dip), GFP_NOFS); if (!dip) { ret = -ENOMEM; - goto free_io_bio; + goto free_ordered; } dip->private = dio_bio->bi_private; @@ -8210,25 +8208,55 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, if (btrfs_bio->end_io) btrfs_bio->end_io(btrfs_bio, ret); -free_io_bio: - bio_put(io_bio); free_ordered: /* - * If this is a write, we need to clean up the reserved space and kill - * the ordered extent. + * If we arrived here it means either we failed to submit the dip + * or we either failed to clone the dio_bio or failed to allocate the + * dip. If we cloned the dio_bio and allocated the dip, we can just + * call bio_endio against our io_bio so that we get proper resource + * cleanup if we fail to submit the dip, otherwise, we must do the + * same as btrfs_endio_direct_[write|read] because we can't call these + * callbacks - they require an allocated dip and a clone of dio_bio. */ - if (write) { - struct btrfs_ordered_extent *ordered; - ordered = btrfs_lookup_ordered_extent(inode, file_offset); - if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) && - !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) - btrfs_free_reserved_extent(root, ordered->start, - ordered->disk_len, 1); - btrfs_put_ordered_extent(ordered); - btrfs_put_ordered_extent(ordered); + if (io_bio && dip) { + bio_endio(io_bio, ret); + /* + * The end io callbacks free our dip, do the final put on io_bio + * and all the cleanup and final put for dio_bio (through + * dio_end_io()). + */ + dip = NULL; + io_bio = NULL; + } else { + if (write) { + struct btrfs_ordered_extent *ordered; + + ordered = btrfs_lookup_ordered_extent(inode, + file_offset); + set_bit(BTRFS_ORDERED_IOERR, &ordered->flags); + /* + * Decrements our ref on the ordered extent and removes + * the ordered extent from the inode's ordered tree, + * doing all the proper resource cleanup such as for the + * reserved space and waking up any waiters for this + * ordered extent (through btrfs_remove_ordered_extent). + */ + btrfs_finish_ordered_io(ordered); + } else { + unlock_extent(&BTRFS_I(inode)->io_tree, file_offset, + file_offset + dio_bio->bi_iter.bi_size - 1); + } + clear_bit(BIO_UPTODATE, &dio_bio->bi_flags); + /* + * Releases and cleans up our dio_bio, no need to bio_put() + * nor bio_endio()/bio_io_error() against dio_bio. + */ + dio_end_io(dio_bio, ret); } - bio_endio(dio_bio, ret); + if (io_bio) + bio_put(io_bio); + kfree(dip); } static ssize_t check_direct_IO(struct btrfs_root *root, struct kiocb *iocb, @@ -8330,9 +8358,18 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, btrfs_submit_direct, flags); if (iov_iter_rw(iter) == WRITE) { current->journal_info = NULL; - if (ret < 0 && ret != -EIOCBQUEUED) - btrfs_delalloc_release_space(inode, count); - else if (ret >= 0 && (size_t)ret < count) + if (ret < 0 && ret != -EIOCBQUEUED) { + /* + * If the error comes from submitting stage, + * btrfs_get_blocsk_direct() has free'd data space, + * and metadata space will be handled by + * finish_ordered_fn, don't do that again to make + * sure bytes_may_use is correct. + */ + if (!test_and_clear_bit(BTRFS_INODE_DIO_READY, + &BTRFS_I(inode)->runtime_flags)) + btrfs_delalloc_release_space(inode, count); + } else if (ret >= 0 && (size_t)ret < count) btrfs_delalloc_release_space(inode, count - (size_t)ret); } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c86b835..5d91776 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -87,7 +87,8 @@ struct btrfs_ioctl_received_subvol_args_32 { static int btrfs_clone(struct inode *src, struct inode *inode, - u64 off, u64 olen, u64 olen_aligned, u64 destoff); + u64 off, u64 olen, u64 olen_aligned, u64 destoff, + int no_time_update); /* Mask out flags that are inappropriate for the given type of inode. */ static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) @@ -2765,14 +2766,11 @@ out: return ret; } -static struct page *extent_same_get_page(struct inode *inode, u64 off) +static struct page *extent_same_get_page(struct inode *inode, pgoff_t index) { struct page *page; - pgoff_t index; struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; - index = off >> PAGE_CACHE_SHIFT; - page = grab_cache_page(inode->i_mapping, index); if (!page) return NULL; @@ -2793,6 +2791,20 @@ static struct page *extent_same_get_page(struct inode *inode, u64 off) return page; } +static int gather_extent_pages(struct inode *inode, struct page **pages, + int num_pages, u64 off) +{ + int i; + pgoff_t index = off >> PAGE_CACHE_SHIFT; + + for (i = 0; i < num_pages; i++) { + pages[i] = extent_same_get_page(inode, index + i); + if (!pages[i]) + return -ENOMEM; + } + return 0; +} + static inline void lock_extent_range(struct inode *inode, u64 off, u64 len) { /* do any pending delalloc/csum calc on src, one way or @@ -2818,52 +2830,120 @@ static inline void lock_extent_range(struct inode *inode, u64 off, u64 len) } } -static void btrfs_double_unlock(struct inode *inode1, u64 loff1, - struct inode *inode2, u64 loff2, u64 len) +static void btrfs_double_inode_unlock(struct inode *inode1, struct inode *inode2) { - unlock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1); - unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1); - mutex_unlock(&inode1->i_mutex); mutex_unlock(&inode2->i_mutex); } -static void btrfs_double_lock(struct inode *inode1, u64 loff1, - struct inode *inode2, u64 loff2, u64 len) +static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2) +{ + if (inode1 < inode2) + swap(inode1, inode2); + + mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); + if (inode1 != inode2) + mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); +} + +static void btrfs_double_extent_unlock(struct inode *inode1, u64 loff1, + struct inode *inode2, u64 loff2, u64 len) +{ + unlock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1); + unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1); +} + +static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1, + struct inode *inode2, u64 loff2, u64 len) { if (inode1 < inode2) { swap(inode1, inode2); swap(loff1, loff2); } - - mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); lock_extent_range(inode1, loff1, len); - if (inode1 != inode2) { - mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); + if (inode1 != inode2) lock_extent_range(inode2, loff2, len); +} + +struct cmp_pages { + int num_pages; + struct page **src_pages; + struct page **dst_pages; +}; + +static void btrfs_cmp_data_free(struct cmp_pages *cmp) +{ + int i; + struct page *pg; + + for (i = 0; i < cmp->num_pages; i++) { + pg = cmp->src_pages[i]; + if (pg) + page_cache_release(pg); + pg = cmp->dst_pages[i]; + if (pg) + page_cache_release(pg); + } + kfree(cmp->src_pages); + kfree(cmp->dst_pages); +} + +static int btrfs_cmp_data_prepare(struct inode *src, u64 loff, + struct inode *dst, u64 dst_loff, + u64 len, struct cmp_pages *cmp) +{ + int ret; + int num_pages = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; + struct page **src_pgarr, **dst_pgarr; + + /* + * We must gather up all the pages before we initiate our + * extent locking. We use an array for the page pointers. Size + * of the array is bounded by len, which is in turn bounded by + * BTRFS_MAX_DEDUPE_LEN. + */ + src_pgarr = kzalloc(num_pages * sizeof(struct page *), GFP_NOFS); + dst_pgarr = kzalloc(num_pages * sizeof(struct page *), GFP_NOFS); + if (!src_pgarr || !dst_pgarr) { + kfree(src_pgarr); + kfree(dst_pgarr); + return -ENOMEM; } + cmp->num_pages = num_pages; + cmp->src_pages = src_pgarr; + cmp->dst_pages = dst_pgarr; + + ret = gather_extent_pages(src, cmp->src_pages, cmp->num_pages, loff); + if (ret) + goto out; + + ret = gather_extent_pages(dst, cmp->dst_pages, cmp->num_pages, dst_loff); + +out: + if (ret) + btrfs_cmp_data_free(cmp); + return 0; } static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst, - u64 dst_loff, u64 len) + u64 dst_loff, u64 len, struct cmp_pages *cmp) { int ret = 0; + int i; struct page *src_page, *dst_page; unsigned int cmp_len = PAGE_CACHE_SIZE; void *addr, *dst_addr; + i = 0; while (len) { if (len < PAGE_CACHE_SIZE) cmp_len = len; - src_page = extent_same_get_page(src, loff); - if (!src_page) - return -EINVAL; - dst_page = extent_same_get_page(dst, dst_loff); - if (!dst_page) { - page_cache_release(src_page); - return -EINVAL; - } + BUG_ON(i >= cmp->num_pages); + + src_page = cmp->src_pages[i]; + dst_page = cmp->dst_pages[i]; + addr = kmap_atomic(src_page); dst_addr = kmap_atomic(dst_page); @@ -2875,15 +2955,12 @@ static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst, kunmap_atomic(addr); kunmap_atomic(dst_addr); - page_cache_release(src_page); - page_cache_release(dst_page); if (ret) break; - loff += cmp_len; - dst_loff += cmp_len; len -= cmp_len; + i++; } return ret; @@ -2914,27 +2991,62 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen, { int ret; u64 len = olen; + struct cmp_pages cmp; + int same_inode = 0; + u64 same_lock_start = 0; + u64 same_lock_len = 0; - /* - * btrfs_clone() can't handle extents in the same file - * yet. Once that works, we can drop this check and replace it - * with a check for the same inode, but overlapping extents. - */ if (src == dst) - return -EINVAL; + same_inode = 1; if (len == 0) return 0; - btrfs_double_lock(src, loff, dst, dst_loff, len); + if (same_inode) { + mutex_lock(&src->i_mutex); - ret = extent_same_check_offsets(src, loff, &len, olen); - if (ret) - goto out_unlock; + ret = extent_same_check_offsets(src, loff, &len, olen); + if (ret) + goto out_unlock; - ret = extent_same_check_offsets(dst, dst_loff, &len, olen); - if (ret) - goto out_unlock; + /* + * Single inode case wants the same checks, except we + * don't want our length pushed out past i_size as + * comparing that data range makes no sense. + * + * extent_same_check_offsets() will do this for an + * unaligned length at i_size, so catch it here and + * reject the request. + * + * This effectively means we require aligned extents + * for the single-inode case, whereas the other cases + * allow an unaligned length so long as it ends at + * i_size. + */ + if (len != olen) { + ret = -EINVAL; + goto out_unlock; + } + + /* Check for overlapping ranges */ + if (dst_loff + len > loff && dst_loff < loff + len) { + ret = -EINVAL; + goto out_unlock; + } + + same_lock_start = min_t(u64, loff, dst_loff); + same_lock_len = max_t(u64, loff, dst_loff) + len - same_lock_start; + } else { + btrfs_double_inode_lock(src, dst); + + ret = extent_same_check_offsets(src, loff, &len, olen); + if (ret) + goto out_unlock; + + ret = extent_same_check_offsets(dst, dst_loff, &len, olen); + if (ret) + goto out_unlock; + } /* don't make the dst file partly checksummed */ if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != @@ -2943,12 +3055,32 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen, goto out_unlock; } - ret = btrfs_cmp_data(src, loff, dst, dst_loff, len); + ret = btrfs_cmp_data_prepare(src, loff, dst, dst_loff, olen, &cmp); + if (ret) + goto out_unlock; + + if (same_inode) + lock_extent_range(src, same_lock_start, same_lock_len); + else + btrfs_double_extent_lock(src, loff, dst, dst_loff, len); + + /* pass original length for comparison so we stay within i_size */ + ret = btrfs_cmp_data(src, loff, dst, dst_loff, olen, &cmp); if (ret == 0) - ret = btrfs_clone(src, dst, loff, olen, len, dst_loff); + ret = btrfs_clone(src, dst, loff, olen, len, dst_loff, 1); + + if (same_inode) + unlock_extent(&BTRFS_I(src)->io_tree, same_lock_start, + same_lock_start + same_lock_len - 1); + else + btrfs_double_extent_unlock(src, loff, dst, dst_loff, len); + btrfs_cmp_data_free(&cmp); out_unlock: - btrfs_double_unlock(src, loff, dst, dst_loff, len); + if (same_inode) + mutex_unlock(&src->i_mutex); + else + btrfs_double_inode_unlock(src, dst); return ret; } @@ -3100,13 +3232,15 @@ static int clone_finish_inode_update(struct btrfs_trans_handle *trans, struct inode *inode, u64 endoff, const u64 destoff, - const u64 olen) + const u64 olen, + int no_time_update) { struct btrfs_root *root = BTRFS_I(inode)->root; int ret; inode_inc_iversion(inode); - inode->i_mtime = inode->i_ctime = CURRENT_TIME; + if (!no_time_update) + inode->i_mtime = inode->i_ctime = CURRENT_TIME; /* * We round up to the block size at eof when determining which * extents to clone above, but shouldn't round up the file size. @@ -3191,13 +3325,13 @@ static void clone_update_extent_map(struct inode *inode, * @inode: Inode to clone to * @off: Offset within source to start clone from * @olen: Original length, passed by user, of range to clone - * @olen_aligned: Block-aligned value of olen, extent_same uses - * identical values here + * @olen_aligned: Block-aligned value of olen * @destoff: Offset within @inode to start clone + * @no_time_update: Whether to update mtime/ctime on the target inode */ static int btrfs_clone(struct inode *src, struct inode *inode, const u64 off, const u64 olen, const u64 olen_aligned, - const u64 destoff) + const u64 destoff, int no_time_update) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_path *path = NULL; @@ -3521,7 +3655,8 @@ process_slot: root->sectorsize); ret = clone_finish_inode_update(trans, inode, last_dest_end, - destoff, olen); + destoff, olen, + no_time_update); if (ret) goto out; if (new_key.offset + datal >= destoff + len) @@ -3559,7 +3694,7 @@ process_slot: clone_update_extent_map(inode, trans, NULL, last_dest_end, destoff + len - last_dest_end); ret = clone_finish_inode_update(trans, inode, destoff + len, - destoff, olen); + destoff, olen, no_time_update); } out: @@ -3696,7 +3831,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, lock_extent_range(inode, destoff, len); } - ret = btrfs_clone(src, inode, off, olen, len, destoff); + ret = btrfs_clone(src, inode, off, olen, len, destoff, 0); if (same_inode) { u64 lock_start = min_t(u64, off, destoff); diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 89656d7..52170cf 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -552,6 +552,10 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) trace_btrfs_ordered_extent_put(entry->inode, entry); if (atomic_dec_and_test(&entry->refs)) { + ASSERT(list_empty(&entry->log_list)); + ASSERT(list_empty(&entry->trans_list)); + ASSERT(list_empty(&entry->root_extent_list)); + ASSERT(RB_EMPTY_NODE(&entry->rb_node)); if (entry->inode) btrfs_add_delayed_iput(entry->inode); while (!list_empty(&entry->list)) { @@ -579,6 +583,7 @@ void btrfs_remove_ordered_extent(struct inode *inode, spin_lock_irq(&tree->lock); node = &entry->rb_node; rb_erase(node, &tree->tree); + RB_CLEAR_NODE(node); if (tree->last == node) tree->last = NULL; set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index d5f1f03..e9ace09 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1349,6 +1349,11 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, struct btrfs_root *quota_root; struct btrfs_qgroup *qgroup; int ret = 0; + /* Sometimes we would want to clear the limit on this qgroup. + * To meet this requirement, we treat the -1 as a special value + * which tell kernel to clear the limit on this qgroup. + */ + const u64 CLEAR_VALUE = -1; mutex_lock(&fs_info->qgroup_ioctl_lock); quota_root = fs_info->quota_root; @@ -1364,14 +1369,42 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, } spin_lock(&fs_info->qgroup_lock); - if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_RFER) - qgroup->max_rfer = limit->max_rfer; - if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) - qgroup->max_excl = limit->max_excl; - if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_RFER) - qgroup->rsv_rfer = limit->rsv_rfer; - if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_EXCL) - qgroup->rsv_excl = limit->rsv_excl; + if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_RFER) { + if (limit->max_rfer == CLEAR_VALUE) { + qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER; + limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER; + qgroup->max_rfer = 0; + } else { + qgroup->max_rfer = limit->max_rfer; + } + } + if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) { + if (limit->max_excl == CLEAR_VALUE) { + qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL; + limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL; + qgroup->max_excl = 0; + } else { + qgroup->max_excl = limit->max_excl; + } + } + if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_RFER) { + if (limit->rsv_rfer == CLEAR_VALUE) { + qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER; + limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER; + qgroup->rsv_rfer = 0; + } else { + qgroup->rsv_rfer = limit->rsv_rfer; + } + } + if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_EXCL) { + if (limit->rsv_excl == CLEAR_VALUE) { + qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL; + limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL; + qgroup->rsv_excl = 0; + } else { + qgroup->rsv_excl = limit->rsv_excl; + } + } qgroup->lim_flags |= limit->flags; spin_unlock(&fs_info->qgroup_lock); diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 827951f..88cbb59 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -4049,7 +4049,7 @@ restart: if (trans && progress && err == -ENOSPC) { ret = btrfs_force_chunk_alloc(trans, rc->extent_root, rc->block_group->flags); - if (ret == 0) { + if (ret == 1) { err = 0; progress = 0; goto restart; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 9f2feab..94db0fa 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -3571,7 +3571,6 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx, static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info, int is_dev_replace) { - int ret = 0; unsigned int flags = WQ_FREEZABLE | WQ_UNBOUND; int max_active = fs_info->thread_pool_size; @@ -3584,34 +3583,36 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info, fs_info->scrub_workers = btrfs_alloc_workqueue("btrfs-scrub", flags, max_active, 4); - if (!fs_info->scrub_workers) { - ret = -ENOMEM; - goto out; - } + if (!fs_info->scrub_workers) + goto fail_scrub_workers; + fs_info->scrub_wr_completion_workers = btrfs_alloc_workqueue("btrfs-scrubwrc", flags, max_active, 2); - if (!fs_info->scrub_wr_completion_workers) { - ret = -ENOMEM; - goto out; - } + if (!fs_info->scrub_wr_completion_workers) + goto fail_scrub_wr_completion_workers; + fs_info->scrub_nocow_workers = btrfs_alloc_workqueue("btrfs-scrubnc", flags, 1, 0); - if (!fs_info->scrub_nocow_workers) { - ret = -ENOMEM; - goto out; - } + if (!fs_info->scrub_nocow_workers) + goto fail_scrub_nocow_workers; fs_info->scrub_parity_workers = btrfs_alloc_workqueue("btrfs-scrubparity", flags, max_active, 2); - if (!fs_info->scrub_parity_workers) { - ret = -ENOMEM; - goto out; - } + if (!fs_info->scrub_parity_workers) + goto fail_scrub_parity_workers; } ++fs_info->scrub_workers_refcnt; -out: - return ret; + return 0; + +fail_scrub_parity_workers: + btrfs_destroy_workqueue(fs_info->scrub_nocow_workers); +fail_scrub_nocow_workers: + btrfs_destroy_workqueue(fs_info->scrub_wr_completion_workers); +fail_scrub_wr_completion_workers: + btrfs_destroy_workqueue(fs_info->scrub_workers); +fail_scrub_workers: + return -ENOMEM; } static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1ce80c1..9c45431 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4117,6 +4117,187 @@ static int logged_inode_size(struct btrfs_root *log, struct inode *inode, return 0; } +/* + * At the moment we always log all xattrs. This is to figure out at log replay + * time which xattrs must have their deletion replayed. If a xattr is missing + * in the log tree and exists in the fs/subvol tree, we delete it. This is + * because if a xattr is deleted, the inode is fsynced and a power failure + * happens, causing the log to be replayed the next time the fs is mounted, + * we want the xattr to not exist anymore (same behaviour as other filesystems + * with a journal, ext3/4, xfs, f2fs, etc). + */ +static int btrfs_log_all_xattrs(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct inode *inode, + struct btrfs_path *path, + struct btrfs_path *dst_path) +{ + int ret; + struct btrfs_key key; + const u64 ino = btrfs_ino(inode); + int ins_nr = 0; + int start_slot = 0; + + key.objectid = ino; + key.type = BTRFS_XATTR_ITEM_KEY; + key.offset = 0; + + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) + return ret; + + while (true) { + int slot = path->slots[0]; + struct extent_buffer *leaf = path->nodes[0]; + int nritems = btrfs_header_nritems(leaf); + + if (slot >= nritems) { + if (ins_nr > 0) { + u64 last_extent = 0; + + ret = copy_items(trans, inode, dst_path, path, + &last_extent, start_slot, + ins_nr, 1, 0); + /* can't be 1, extent items aren't processed */ + ASSERT(ret <= 0); + if (ret < 0) + return ret; + ins_nr = 0; + } + ret = btrfs_next_leaf(root, path); + if (ret < 0) + return ret; + else if (ret > 0) + break; + continue; + } + + btrfs_item_key_to_cpu(leaf, &key, slot); + if (key.objectid != ino || key.type != BTRFS_XATTR_ITEM_KEY) + break; + + if (ins_nr == 0) + start_slot = slot; + ins_nr++; + path->slots[0]++; + cond_resched(); + } + if (ins_nr > 0) { + u64 last_extent = 0; + + ret = copy_items(trans, inode, dst_path, path, + &last_extent, start_slot, + ins_nr, 1, 0); + /* can't be 1, extent items aren't processed */ + ASSERT(ret <= 0); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * If the no holes feature is enabled we need to make sure any hole between the + * last extent and the i_size of our inode is explicitly marked in the log. This + * is to make sure that doing something like: + * + * 1) create file with 128Kb of data + * 2) truncate file to 64Kb + * 3) truncate file to 256Kb + * 4) fsync file + * 5) <crash/power failure> + * 6) mount fs and trigger log replay + * + * Will give us a file with a size of 256Kb, the first 64Kb of data match what + * the file had in its first 64Kb of data at step 1 and the last 192Kb of the + * file correspond to a hole. The presence of explicit holes in a log tree is + * what guarantees that log replay will remove/adjust file extent items in the + * fs/subvol tree. + * + * Here we do not need to care about holes between extents, that is already done + * by copy_items(). We also only need to do this in the full sync path, where we + * lookup for extents from the fs/subvol tree only. In the fast path case, we + * lookup the list of modified extent maps and if any represents a hole, we + * insert a corresponding extent representing a hole in the log tree. + */ +static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct inode *inode, + struct btrfs_path *path) +{ + int ret; + struct btrfs_key key; + u64 hole_start; + u64 hole_size; + struct extent_buffer *leaf; + struct btrfs_root *log = root->log_root; + const u64 ino = btrfs_ino(inode); + const u64 i_size = i_size_read(inode); + + if (!btrfs_fs_incompat(root->fs_info, NO_HOLES)) + return 0; + + key.objectid = ino; + key.type = BTRFS_EXTENT_DATA_KEY; + key.offset = (u64)-1; + + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + ASSERT(ret != 0); + if (ret < 0) + return ret; + + ASSERT(path->slots[0] > 0); + path->slots[0]--; + leaf = path->nodes[0]; + btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); + + if (key.objectid != ino || key.type != BTRFS_EXTENT_DATA_KEY) { + /* inode does not have any extents */ + hole_start = 0; + hole_size = i_size; + } else { + struct btrfs_file_extent_item *extent; + u64 len; + + /* + * If there's an extent beyond i_size, an explicit hole was + * already inserted by copy_items(). + */ + if (key.offset >= i_size) + return 0; + + extent = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_file_extent_item); + + if (btrfs_file_extent_type(leaf, extent) == + BTRFS_FILE_EXTENT_INLINE) { + len = btrfs_file_extent_inline_len(leaf, + path->slots[0], + extent); + ASSERT(len == i_size); + return 0; + } + + len = btrfs_file_extent_num_bytes(leaf, extent); + /* Last extent goes beyond i_size, no need to log a hole. */ + if (key.offset + len > i_size) + return 0; + hole_start = key.offset + len; + hole_size = i_size - hole_start; + } + btrfs_release_path(path); + + /* Last extent ends at i_size. */ + if (hole_size == 0) + return 0; + + hole_size = ALIGN(hole_size, root->sectorsize); + ret = btrfs_insert_file_extent(trans, log, ino, hole_start, 0, 0, + hole_size, 0, hole_size, 0, 0, 0); + return ret; +} + /* log a single inode in the tree log. * At least one parent directory for this inode must exist in the tree * or be logged already. @@ -4155,6 +4336,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, u64 ino = btrfs_ino(inode); struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; u64 logged_isize = 0; + bool need_log_inode_item = true; path = btrfs_alloc_path(); if (!path) @@ -4263,11 +4445,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, } else { if (inode_only == LOG_INODE_ALL) fast_search = true; - ret = log_inode_item(trans, log, dst_path, inode); - if (ret) { - err = ret; - goto out_unlock; - } goto log_extents; } @@ -4290,6 +4467,28 @@ again: if (min_key.type > max_key.type) break; + if (min_key.type == BTRFS_INODE_ITEM_KEY) + need_log_inode_item = false; + + /* Skip xattrs, we log them later with btrfs_log_all_xattrs() */ + if (min_key.type == BTRFS_XATTR_ITEM_KEY) { + if (ins_nr == 0) + goto next_slot; + ret = copy_items(trans, inode, dst_path, path, + &last_extent, ins_start_slot, + ins_nr, inode_only, logged_isize); + if (ret < 0) { + err = ret; + goto out_unlock; + } + ins_nr = 0; + if (ret) { + btrfs_release_path(path); + continue; + } + goto next_slot; + } + src = path->nodes[0]; if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) { ins_nr++; @@ -4357,9 +4556,26 @@ next_slot: ins_nr = 0; } + btrfs_release_path(path); + btrfs_release_path(dst_path); + err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path); + if (err) + goto out_unlock; + if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) { + btrfs_release_path(path); + btrfs_release_path(dst_path); + err = btrfs_log_trailing_hole(trans, root, inode, path); + if (err) + goto out_unlock; + } log_extents: btrfs_release_path(path); btrfs_release_path(dst_path); + if (need_log_inode_item) { + err = log_inode_item(trans, log, dst_path, inode); + if (err) + goto out_unlock; + } if (fast_search) { /* * Some ordered extents started by fsync might have completed diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 4b438b4..fbe7c10 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2766,6 +2766,20 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, root = root->fs_info->chunk_root; extent_root = root->fs_info->extent_root; + /* + * Prevent races with automatic removal of unused block groups. + * After we relocate and before we remove the chunk with offset + * chunk_offset, automatic removal of the block group can kick in, + * resulting in a failure when calling btrfs_remove_chunk() below. + * + * Make sure to acquire this mutex before doing a tree search (dev + * or chunk trees) to find chunks. Otherwise the cleaner kthread might + * call btrfs_remove_chunk() (through btrfs_delete_unused_bgs()) after + * we release the path used to search the chunk/dev tree and before + * the current task acquires this mutex and calls us. + */ + ASSERT(mutex_is_locked(&root->fs_info->delete_unused_bgs_mutex)); + ret = btrfs_can_relocate(extent_root, chunk_offset); if (ret) return -ENOSPC; @@ -2814,13 +2828,18 @@ again: key.type = BTRFS_CHUNK_ITEM_KEY; while (1) { + mutex_lock(&root->fs_info->delete_unused_bgs_mutex); ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); - if (ret < 0) + if (ret < 0) { + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); goto error; + } BUG_ON(ret == 0); /* Corruption */ ret = btrfs_previous_item(chunk_root, path, key.objectid, key.type); + if (ret) + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); if (ret < 0) goto error; if (ret > 0) @@ -2843,6 +2862,7 @@ again: else BUG_ON(ret); } + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); if (found_key.offset == 0) break; @@ -3299,9 +3319,12 @@ again: goto error; } + mutex_lock(&fs_info->delete_unused_bgs_mutex); ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); - if (ret < 0) + if (ret < 0) { + mutex_unlock(&fs_info->delete_unused_bgs_mutex); goto error; + } /* * this shouldn't happen, it means the last relocate @@ -3313,6 +3336,7 @@ again: ret = btrfs_previous_item(chunk_root, path, 0, BTRFS_CHUNK_ITEM_KEY); if (ret) { + mutex_unlock(&fs_info->delete_unused_bgs_mutex); ret = 0; break; } @@ -3321,8 +3345,10 @@ again: slot = path->slots[0]; btrfs_item_key_to_cpu(leaf, &found_key, slot); - if (found_key.objectid != key.objectid) + if (found_key.objectid != key.objectid) { + mutex_unlock(&fs_info->delete_unused_bgs_mutex); break; + } chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); @@ -3335,10 +3361,13 @@ again: ret = should_balance_chunk(chunk_root, leaf, chunk, found_key.offset); btrfs_release_path(path); - if (!ret) + if (!ret) { + mutex_unlock(&fs_info->delete_unused_bgs_mutex); goto loop; + } if (counting) { + mutex_unlock(&fs_info->delete_unused_bgs_mutex); spin_lock(&fs_info->balance_lock); bctl->stat.expected++; spin_unlock(&fs_info->balance_lock); @@ -3348,6 +3377,7 @@ again: ret = btrfs_relocate_chunk(chunk_root, found_key.objectid, found_key.offset); + mutex_unlock(&fs_info->delete_unused_bgs_mutex); if (ret && ret != -ENOSPC) goto error; if (ret == -ENOSPC) { @@ -4087,11 +4117,16 @@ again: key.type = BTRFS_DEV_EXTENT_KEY; do { + mutex_lock(&root->fs_info->delete_unused_bgs_mutex); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); - if (ret < 0) + if (ret < 0) { + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); goto done; + } ret = btrfs_previous_item(root, path, 0, key.type); + if (ret) + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); if (ret < 0) goto done; if (ret) { @@ -4105,6 +4140,7 @@ again: btrfs_item_key_to_cpu(l, &key, path->slots[0]); if (key.objectid != device->devid) { + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); btrfs_release_path(path); break; } @@ -4113,6 +4149,7 @@ again: length = btrfs_dev_extent_length(l, dev_extent); if (key.offset + length <= new_size) { + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); btrfs_release_path(path); break; } @@ -4122,6 +4159,7 @@ again: btrfs_release_path(path); ret = btrfs_relocate_chunk(root, chunk_objectid, chunk_offset); + mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); if (ret && ret != -ENOSPC) goto done; if (ret == -ENOSPC) @@ -5715,7 +5753,6 @@ static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int e static void btrfs_end_bio(struct bio *bio, int err) { struct btrfs_bio *bbio = bio->bi_private; - struct btrfs_device *dev = bbio->stripes[0].dev; int is_orig_bio = 0; if (err) { @@ -5723,6 +5760,7 @@ static void btrfs_end_bio(struct bio *bio, int err) if (err == -EIO || err == -EREMOTEIO) { unsigned int stripe_index = btrfs_io_bio(bio)->stripe_index; + struct btrfs_device *dev; BUG_ON(stripe_index >= bbio->num_stripes); dev = bbio->stripes[stripe_index].dev; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 6b8e2f0..48851f6 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -896,6 +896,7 @@ COMPATIBLE_IOCTL(FIGETBSZ) /* 'X' - originally XFS but some now in the VFS */ COMPATIBLE_IOCTL(FIFREEZE) COMPATIBLE_IOCTL(FITHAW) +COMPATIBLE_IOCTL(FITRIM) COMPATIBLE_IOCTL(KDGETKEYCODE) COMPATIBLE_IOCTL(KDSETKEYCODE) COMPATIBLE_IOCTL(KDGKBTYPE) diff --git a/fs/dcache.c b/fs/dcache.c index 7a3f3e5..5c8ea15 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -642,7 +642,7 @@ static inline bool fast_dput(struct dentry *dentry) /* * If we have a d_op->d_delete() operation, we sould not - * let the dentry count go to zero, so use "put__or_lock". + * let the dentry count go to zero, so use "put_or_lock". */ if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) return lockref_put_or_lock(&dentry->d_lockref); @@ -697,7 +697,7 @@ static inline bool fast_dput(struct dentry *dentry) */ smp_rmb(); d_flags = ACCESS_ONCE(dentry->d_flags); - d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST; + d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED; /* Nothing to do? Dropping the reference was all we needed? */ if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) @@ -776,6 +776,9 @@ repeat: if (unlikely(d_unhashed(dentry))) goto kill_it; + if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) + goto kill_it; + if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) { if (dentry->d_op->d_delete(dentry)) goto kill_it; diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 72afcc6..feef8a9 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -325,7 +325,6 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return rc; switch (cmd) { - case FITRIM: case FS_IOC32_GETFLAGS: case FS_IOC32_SETFLAGS: case FS_IOC32_GETVERSION: diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index aadb728..2553aa8 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -504,7 +504,7 @@ __read_extent_tree_block(const char *function, unsigned int line, struct buffer_head *bh; int err; - bh = sb_getblk(inode->i_sb, pblk); + bh = sb_getblk_gfp(inode->i_sb, pblk, __GFP_MOVABLE | GFP_NOFS); if (unlikely(!bh)) return ERR_PTR(-ENOMEM); @@ -1089,7 +1089,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, err = -EIO; goto cleanup; } - bh = sb_getblk(inode->i_sb, newblock); + bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); if (unlikely(!bh)) { err = -ENOMEM; goto cleanup; @@ -1283,7 +1283,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, if (newblock == 0) return err; - bh = sb_getblk(inode->i_sb, newblock); + bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); if (unlikely(!bh)) return -ENOMEM; lock_buffer(bh); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 41f8e55..cecf9aa 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1323,7 +1323,7 @@ static void ext4_da_page_release_reservation(struct page *page, unsigned int offset, unsigned int length) { - int to_release = 0; + int to_release = 0, contiguous_blks = 0; struct buffer_head *head, *bh; unsigned int curr_off = 0; struct inode *inode = page->mapping->host; @@ -1344,14 +1344,23 @@ static void ext4_da_page_release_reservation(struct page *page, if ((offset <= curr_off) && (buffer_delay(bh))) { to_release++; + contiguous_blks++; clear_buffer_delay(bh); + } else if (contiguous_blks) { + lblk = page->index << + (PAGE_CACHE_SHIFT - inode->i_blkbits); + lblk += (curr_off >> inode->i_blkbits) - + contiguous_blks; + ext4_es_remove_extent(inode, lblk, contiguous_blks); + contiguous_blks = 0; } curr_off = next_off; } while ((bh = bh->b_this_page) != head); - if (to_release) { + if (contiguous_blks) { lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); - ext4_es_remove_extent(inode, lblk, to_release); + lblk += (curr_off >> inode->i_blkbits) - contiguous_blks; + ext4_es_remove_extent(inode, lblk, contiguous_blks); } /* If we have released all the blocks belonging to a cluster, then we @@ -4344,7 +4353,12 @@ static void ext4_update_other_inodes_time(struct super_block *sb, int inode_size = EXT4_INODE_SIZE(sb); oi.orig_ino = orig_ino; - ino = (orig_ino & ~(inodes_per_block - 1)) + 1; + /* + * Calculate the first inode in the inode table block. Inode + * numbers are one-based. That is, the first inode in a block + * (assuming 4k blocks and 256 byte inodes) is (n*16 + 1). + */ + ino = ((orig_ino - 1) & ~(inodes_per_block - 1)) + 1; for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { if (ino == orig_ino) continue; diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index cb84512..1346cfa 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -755,7 +755,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; } case EXT4_IOC_MOVE_EXT: - case FITRIM: case EXT4_IOC_RESIZE_FS: case EXT4_IOC_PRECACHE_EXTENTS: case EXT4_IOC_SET_ENCRYPTION_POLICY: diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index f6aedf8..34b610e 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4816,18 +4816,12 @@ do_more: /* * blocks being freed are metadata. these blocks shouldn't * be used until this transaction is committed + * + * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed + * to fail. */ - retry: - new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); - if (!new_entry) { - /* - * We use a retry loop because - * ext4_free_blocks() is not allowed to fail. - */ - cond_resched(); - congestion_wait(BLK_RW_ASYNC, HZ/50); - goto retry; - } + new_entry = kmem_cache_alloc(ext4_free_data_cachep, + GFP_NOFS|__GFP_NOFAIL); new_entry->efd_start_cluster = bit; new_entry->efd_group = block_group; new_entry->efd_count = count_clusters; diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b52374e..6163ad2 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -620,6 +620,7 @@ int ext4_ind_migrate(struct inode *inode) struct ext4_inode_info *ei = EXT4_I(inode); struct ext4_extent *ex; unsigned int i, len; + ext4_lblk_t start, end; ext4_fsblk_t blk; handle_t *handle; int ret; @@ -633,6 +634,14 @@ int ext4_ind_migrate(struct inode *inode) EXT4_FEATURE_RO_COMPAT_BIGALLOC)) return -EOPNOTSUPP; + /* + * In order to get correct extent info, force all delayed allocation + * blocks to be allocated, otherwise delayed allocation blocks may not + * be reflected and bypass the checks on extent header. + */ + if (test_opt(inode->i_sb, DELALLOC)) + ext4_alloc_da_blocks(inode); + handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -650,11 +659,13 @@ int ext4_ind_migrate(struct inode *inode) goto errout; } if (eh->eh_entries == 0) - blk = len = 0; + blk = len = start = end = 0; else { len = le16_to_cpu(ex->ee_len); blk = ext4_ext_pblock(ex); - if (len > EXT4_NDIR_BLOCKS) { + start = le32_to_cpu(ex->ee_block); + end = start + len - 1; + if (end >= EXT4_NDIR_BLOCKS) { ret = -EOPNOTSUPP; goto errout; } @@ -662,7 +673,7 @@ int ext4_ind_migrate(struct inode *inode) ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); memset(ei->i_data, 0, sizeof(ei->i_data)); - for (i=0; i < len; i++) + for (i = start; i <= end; i++) ei->i_data[i] = cpu_to_le32(blk++); ext4_mark_inode_dirty(handle, inode); errout: diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index f005046..d6a4b55 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c @@ -484,3 +484,98 @@ struct anode *hpfs_alloc_anode(struct super_block *s, secno near, anode_secno *a a->btree.first_free = cpu_to_le16(8); return a; } + +static unsigned find_run(__le32 *bmp, unsigned *idx) +{ + unsigned len; + while (tstbits(bmp, *idx, 1)) { + (*idx)++; + if (unlikely(*idx >= 0x4000)) + return 0; + } + len = 1; + while (!tstbits(bmp, *idx + len, 1)) + len++; + return len; +} + +static int do_trim(struct super_block *s, secno start, unsigned len, secno limit_start, secno limit_end, unsigned minlen, unsigned *result) +{ + int err; + secno end; + if (fatal_signal_pending(current)) + return -EINTR; + end = start + len; + if (start < limit_start) + start = limit_start; + if (end > limit_end) + end = limit_end; + if (start >= end) + return 0; + if (end - start < minlen) + return 0; + err = sb_issue_discard(s, start, end - start, GFP_NOFS, 0); + if (err) + return err; + *result += end - start; + return 0; +} + +int hpfs_trim_fs(struct super_block *s, u64 start, u64 end, u64 minlen, unsigned *result) +{ + int err = 0; + struct hpfs_sb_info *sbi = hpfs_sb(s); + unsigned idx, len, start_bmp, end_bmp; + __le32 *bmp; + struct quad_buffer_head qbh; + + *result = 0; + if (!end || end > sbi->sb_fs_size) + end = sbi->sb_fs_size; + if (start >= sbi->sb_fs_size) + return 0; + if (minlen > 0x4000) + return 0; + if (start < sbi->sb_dirband_start + sbi->sb_dirband_size && end > sbi->sb_dirband_start) { + hpfs_lock(s); + if (s->s_flags & MS_RDONLY) { + err = -EROFS; + goto unlock_1; + } + if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) { + err = -EIO; + goto unlock_1; + } + idx = 0; + while ((len = find_run(bmp, &idx)) && !err) { + err = do_trim(s, sbi->sb_dirband_start + idx * 4, len * 4, start, end, minlen, result); + idx += len; + } + hpfs_brelse4(&qbh); +unlock_1: + hpfs_unlock(s); + } + start_bmp = start >> 14; + end_bmp = (end + 0x3fff) >> 14; + while (start_bmp < end_bmp && !err) { + hpfs_lock(s); + if (s->s_flags & MS_RDONLY) { + err = -EROFS; + goto unlock_2; + } + if (!(bmp = hpfs_map_bitmap(s, start_bmp, &qbh, "trim"))) { + err = -EIO; + goto unlock_2; + } + idx = 0; + while ((len = find_run(bmp, &idx)) && !err) { + err = do_trim(s, (start_bmp << 14) + idx, len, start, end, minlen, result); + idx += len; + } + hpfs_brelse4(&qbh); +unlock_2: + hpfs_unlock(s); + start_bmp++; + } + return err; +} diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 2a8e074..dc540bf 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -327,4 +327,5 @@ const struct file_operations hpfs_dir_ops = .iterate = hpfs_readdir, .release = hpfs_dir_release, .fsync = hpfs_file_fsync, + .unlocked_ioctl = hpfs_ioctl, }; diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 6d8cfe9..7ca28d6 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -203,6 +203,7 @@ const struct file_operations hpfs_file_ops = .release = hpfs_file_release, .fsync = hpfs_file_fsync, .splice_read = generic_file_splice_read, + .unlocked_ioctl = hpfs_ioctl, }; const struct inode_operations hpfs_file_iops = diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index bb04b58..c4867b5 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h @@ -18,6 +18,8 @@ #include <linux/pagemap.h> #include <linux/buffer_head.h> #include <linux/slab.h> +#include <linux/sched.h> +#include <linux/blkdev.h> #include <asm/unaligned.h> #include "hpfs.h" @@ -200,6 +202,7 @@ void hpfs_free_dnode(struct super_block *, secno); struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *); struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **); struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **); +int hpfs_trim_fs(struct super_block *, u64, u64, u64, unsigned *); /* anode.c */ @@ -318,6 +321,7 @@ __printf(2, 3) void hpfs_error(struct super_block *, const char *, ...); int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *); unsigned hpfs_get_free_dnodes(struct super_block *); +long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg); /* * local time (HPFS) to GMT (Unix) diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 7cd00d3..68a9bed0 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -52,17 +52,20 @@ static void unmark_dirty(struct super_block *s) } /* Filesystem error... */ -static char err_buf[1024]; - void hpfs_error(struct super_block *s, const char *fmt, ...) { + struct va_format vaf; va_list args; va_start(args, fmt); - vsnprintf(err_buf, sizeof(err_buf), fmt, args); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_err("filesystem error: %pV", &vaf); + va_end(args); - pr_err("filesystem error: %s", err_buf); if (!hpfs_sb(s)->sb_was_error) { if (hpfs_sb(s)->sb_err == 2) { pr_cont("; crashing the system because you wanted it\n"); @@ -196,12 +199,39 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } + +long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + switch (cmd) { + case FITRIM: { + struct fstrim_range range; + secno n_trimmed; + int r; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range))) + return -EFAULT; + r = hpfs_trim_fs(file_inode(file)->i_sb, range.start >> 9, (range.start + range.len) >> 9, (range.minlen + 511) >> 9, &n_trimmed); + if (r) + return r; + range.len = (u64)n_trimmed << 9; + if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range))) + return -EFAULT; + return 0; + } + default: { + return -ENOIOCTLCMD; + } + } +} + + static struct kmem_cache * hpfs_inode_cachep; static struct inode *hpfs_alloc_inode(struct super_block *sb) { struct hpfs_inode_info *ei; - ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS); + ei = kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS); if (!ei) return NULL; ei->vfs_inode.i_version = 1; @@ -424,11 +454,14 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) int o; struct hpfs_sb_info *sbi = hpfs_sb(s); char *new_opts = kstrdup(data, GFP_KERNEL); - + + if (!new_opts) + return -ENOMEM; + sync_filesystem(s); *flags |= MS_NOATIME; - + hpfs_lock(s); uid = sbi->sb_uid; gid = sbi->sb_gid; umask = 0777 & ~sbi->sb_mode; diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index 93a1232..8db8b7d 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c @@ -180,9 +180,6 @@ long jfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case JFS_IOC_SETFLAGS32: cmd = JFS_IOC_SETFLAGS; break; - case FITRIM: - cmd = FITRIM; - break; } return jfs_ioctl(filp, cmd, arg); } diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 9a20e51..aba4381 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -1369,7 +1369,6 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case NILFS_IOCTL_SYNC: case NILFS_IOCTL_RESIZE: case NILFS_IOCTL_SET_ALLOC_RANGE: - case FITRIM: break; default: return -ENOIOCTLCMD; diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 53e6c40..3cb097c 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -980,7 +980,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) case OCFS2_IOC_GROUP_EXTEND: case OCFS2_IOC_GROUP_ADD: case OCFS2_IOC_GROUP_ADD64: - case FITRIM: break; case OCFS2_IOC_REFLINK: if (copy_from_user(&args, argp, sizeof(args))) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index f140e3db..d9da5a4 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -343,6 +343,9 @@ struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) struct path realpath; enum ovl_path_type type; + if (d_is_dir(dentry)) + return d_backing_inode(dentry); + type = ovl_path_real(dentry, &realpath); if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { err = ovl_want_write(dentry); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index c471dfc..d2445fa 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -58,6 +58,19 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) acpi_fwnode_handle(adev) : NULL) #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) +/** + * ACPI_DEVICE_CLASS - macro used to describe an ACPI device with + * the PCI-defined class-code information + * + * @_cls : the class, subclass, prog-if triple for this device + * @_msk : the class mask for this device + * + * This macro is used to create a struct acpi_device_id that matches a + * specific PCI class. The .id and .driver_data fields will be left + * initialized with the default value. + */ +#define ACPI_DEVICE_CLASS(_cls, _msk) .cls = (_cls), .cls_msk = (_msk), + static inline bool has_acpi_companion(struct device *dev) { return is_acpi_node(dev->fwnode); @@ -309,9 +322,6 @@ int acpi_check_region(resource_size_t start, resource_size_t n, int acpi_resources_are_enforced(void); -int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, - unsigned long flags, char *desc); - #ifdef CONFIG_HIBERNATION void __init acpi_no_s4_hw_signature(void); #endif @@ -446,6 +456,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *); #define ACPI_COMPANION(dev) (NULL) #define ACPI_COMPANION_SET(dev, adev) do { } while (0) #define ACPI_HANDLE(dev) (NULL) +#define ACPI_DEVICE_CLASS(_cls, _msk) .cls = (0), .cls_msk = (0), struct fwnode_handle; @@ -507,13 +518,6 @@ static inline int acpi_check_region(resource_size_t start, resource_size_t n, return 0; } -static inline int acpi_reserve_region(u64 start, unsigned int length, - u8 space_id, unsigned long flags, - char *desc) -{ - return -ENXIO; -} - struct acpi_table_header; static inline int acpi_table_parse(char *id, int (*handler)(struct acpi_table_header *)) diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 73b4522..e6797de 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -317,6 +317,13 @@ sb_getblk(struct super_block *sb, sector_t block) return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE); } + +static inline struct buffer_head * +sb_getblk_gfp(struct super_block *sb, sector_t block, gfp_t gfp) +{ + return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, gfp); +} + static inline struct buffer_head * sb_find_get_block(struct super_block *sb, sector_t block) { diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index e154994..3775327 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -8,6 +8,7 @@ #include <linux/radix-tree.h> #include <linux/uio.h> #include <linux/workqueue.h> +#include <net/net_namespace.h> #include <linux/ceph/types.h> #include <linux/ceph/buffer.h> @@ -56,6 +57,7 @@ struct ceph_messenger { struct ceph_entity_addr my_enc_addr; atomic_t stopping; + possible_net_t net; bool nocrc; bool tcp_nodelay; @@ -267,6 +269,7 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, u64 required_features, bool nocrc, bool tcp_nodelay); +extern void ceph_messenger_fini(struct ceph_messenger *msgr); extern void ceph_con_init(struct ceph_connection *con, void *private, const struct ceph_connection_operations *ops, diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 7f8ad95..e08a6ae 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -17,11 +17,11 @@ # define __release(x) __context__(x,-1) # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) # define __percpu __attribute__((noderef, address_space(3))) +# define __pmem __attribute__((noderef, address_space(5))) #ifdef CONFIG_SPARSE_RCU_POINTER # define __rcu __attribute__((noderef, address_space(4))) #else # define __rcu -# define __pmem __attribute__((noderef, address_space(5))) #endif extern void __chk_user_ptr(const volatile void __user *); extern void __chk_io_ptr(const volatile void __iomem *); diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 624a668..fcea4e4 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -87,7 +87,12 @@ struct irq_desc { const char *name; } ____cacheline_internodealigned_in_smp; -#ifndef CONFIG_SPARSE_IRQ +#ifdef CONFIG_SPARSE_IRQ +extern void irq_lock_sparse(void); +extern void irq_unlock_sparse(void); +#else +static inline void irq_lock_sparse(void) { } +static inline void irq_unlock_sparse(void) { } extern struct irq_desc irq_desc[NR_IRQS]; #endif diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 8183d66..34f25b7 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -189,6 +189,8 @@ struct css_device_id { struct acpi_device_id { __u8 id[ACPI_ID_LEN]; kernel_ulong_t driver_data; + __u32 cls; + __u32 cls_msk; }; #define PNP_ID_LEN 8 diff --git a/include/linux/rtc/sirfsoc_rtciobrg.h b/include/linux/rtc/sirfsoc_rtciobrg.h index 2c92e1c..aefd997 100644 --- a/include/linux/rtc/sirfsoc_rtciobrg.h +++ b/include/linux/rtc/sirfsoc_rtciobrg.h @@ -9,10 +9,14 @@ #ifndef _SIRFSOC_RTC_IOBRG_H_ #define _SIRFSOC_RTC_IOBRG_H_ +struct regmap_config; + extern void sirfsoc_rtc_iobrg_besyncing(void); extern u32 sirfsoc_rtc_iobrg_readl(u32 addr); extern void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr); +struct regmap *devm_regmap_init_iobg(struct device *dev, + const struct regmap_config *config); #endif diff --git a/include/linux/tick.h b/include/linux/tick.h index 3741ba1..edbfc9a 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -67,10 +67,13 @@ extern void tick_broadcast_control(enum tick_broadcast_mode mode); static inline void tick_broadcast_control(enum tick_broadcast_mode mode) { } #endif /* BROADCAST */ -#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT) +#ifdef CONFIG_GENERIC_CLOCKEVENTS extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state); #else -static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { return 0; } +static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) +{ + return 0; +} #endif static inline void tick_broadcast_enable(void) diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 3aa72e6..6e191e4 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -145,7 +145,6 @@ static inline void getboottime(struct timespec *ts) } #endif -#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) #define ktime_get_real_ts64(ts) getnstimeofday64(ts) /* diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 09c6564..e85bdfd 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1021,8 +1021,7 @@ static int audit_log_single_execve_arg(struct audit_context *context, * for strings that are too long, we should not have created * any. */ - if (unlikely((len == 0) || len > MAX_ARG_STRLEN - 1)) { - WARN_ON(1); + if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) { send_sig(SIGKILL, current, 0); return -1; } diff --git a/kernel/cpu.c b/kernel/cpu.c index 9c9c9fa..6a37454 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -21,6 +21,7 @@ #include <linux/suspend.h> #include <linux/lockdep.h> #include <linux/tick.h> +#include <linux/irq.h> #include <trace/events/power.h> #include "smpboot.h" @@ -392,13 +393,19 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) smpboot_park_threads(cpu); /* - * So now all preempt/rcu users must observe !cpu_active(). + * Prevent irq alloc/free while the dying cpu reorganizes the + * interrupt affinities. */ + irq_lock_sparse(); + /* + * So now all preempt/rcu users must observe !cpu_active(). + */ err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { /* CPU didn't die: tell everyone. Can't complain. */ cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); + irq_unlock_sparse(); goto out_release; } BUG_ON(cpu_online(cpu)); @@ -415,6 +422,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */ per_cpu(cpu_dead_idle, cpu) = false; + /* Interrupts are moved away from the dying cpu, reenable alloc/free */ + irq_unlock_sparse(); + hotplug_cpu__broadcast_tick_pull(cpu); /* This actually kills the CPU. */ __cpu_die(cpu); @@ -517,8 +527,18 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) goto out_notify; } + /* + * Some architectures have to walk the irq descriptors to + * setup the vector space for the cpu which comes online. + * Prevent irq alloc/free across the bringup. + */ + irq_lock_sparse(); + /* Arch-specific enabling code. */ ret = __cpu_up(cpu, idle); + + irq_unlock_sparse(); + if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); diff --git a/kernel/events/core.c b/kernel/events/core.c index e965cfa..d3dae34 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4358,14 +4358,6 @@ static void ring_buffer_wakeup(struct perf_event *event) rcu_read_unlock(); } -static void rb_free_rcu(struct rcu_head *rcu_head) -{ - struct ring_buffer *rb; - - rb = container_of(rcu_head, struct ring_buffer, rcu_head); - rb_free(rb); -} - struct ring_buffer *ring_buffer_get(struct perf_event *event) { struct ring_buffer *rb; diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 2deb24c..2bbad9c 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -11,6 +11,7 @@ struct ring_buffer { atomic_t refcount; struct rcu_head rcu_head; + struct irq_work irq_work; #ifdef CONFIG_PERF_USE_VMALLOC struct work_struct work; int page_order; /* allocation order */ @@ -55,6 +56,15 @@ struct ring_buffer { }; extern void rb_free(struct ring_buffer *rb); + +static inline void rb_free_rcu(struct rcu_head *rcu_head) +{ + struct ring_buffer *rb; + + rb = container_of(rcu_head, struct ring_buffer, rcu_head); + rb_free(rb); +} + extern struct ring_buffer * rb_alloc(int nr_pages, long watermark, int cpu, int flags); extern void perf_event_wakeup(struct perf_event *event); diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 9647282..b2be01b 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -221,6 +221,8 @@ void perf_output_end(struct perf_output_handle *handle) rcu_read_unlock(); } +static void rb_irq_work(struct irq_work *work); + static void ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) { @@ -241,6 +243,16 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) INIT_LIST_HEAD(&rb->event_list); spin_lock_init(&rb->event_lock); + init_irq_work(&rb->irq_work, rb_irq_work); +} + +static void ring_buffer_put_async(struct ring_buffer *rb) +{ + if (!atomic_dec_and_test(&rb->refcount)) + return; + + rb->rcu_head.next = (void *)rb; + irq_work_queue(&rb->irq_work); } /* @@ -319,7 +331,7 @@ err_put: rb_free_aux(rb); err: - ring_buffer_put(rb); + ring_buffer_put_async(rb); handle->event = NULL; return NULL; @@ -370,7 +382,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, local_set(&rb->aux_nest, 0); rb_free_aux(rb); - ring_buffer_put(rb); + ring_buffer_put_async(rb); } /* @@ -557,7 +569,18 @@ static void __rb_free_aux(struct ring_buffer *rb) void rb_free_aux(struct ring_buffer *rb) { if (atomic_dec_and_test(&rb->aux_refcount)) + irq_work_queue(&rb->irq_work); +} + +static void rb_irq_work(struct irq_work *work) +{ + struct ring_buffer *rb = container_of(work, struct ring_buffer, irq_work); + + if (!atomic_read(&rb->aux_refcount)) __rb_free_aux(rb); + + if (rb->rcu_head.next == (void *)rb) + call_rcu(&rb->rcu_head, rb_free_rcu); } #ifndef CONFIG_PERF_USE_VMALLOC diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 4834ee8..61008b8 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -76,12 +76,8 @@ extern void unmask_threaded_irq(struct irq_desc *desc); #ifdef CONFIG_SPARSE_IRQ static inline void irq_mark_irq(unsigned int irq) { } -extern void irq_lock_sparse(void); -extern void irq_unlock_sparse(void); #else extern void irq_mark_irq(unsigned int irq); -static inline void irq_lock_sparse(void) { } -static inline void irq_unlock_sparse(void) { } #endif extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); diff --git a/kernel/module.c b/kernel/module.c index 3e0e197..4d2b82e 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3557,6 +3557,7 @@ static int load_module(struct load_info *info, const char __user *uargs, mutex_lock(&module_mutex); /* Unlink carefully: kallsyms could be walking list. */ list_del_rcu(&mod->list); + mod_tree_remove(mod); wake_up_all(&module_wq); /* Wait for RCU-sched synchronizing before releasing mod->list. */ synchronize_sched(); diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 08ccc3d..50eb107 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -120,19 +120,25 @@ static int __clockevents_switch_state(struct clock_event_device *dev, /* The clockevent device is getting replaced. Shut it down. */ case CLOCK_EVT_STATE_SHUTDOWN: - return dev->set_state_shutdown(dev); + if (dev->set_state_shutdown) + return dev->set_state_shutdown(dev); + return 0; case CLOCK_EVT_STATE_PERIODIC: /* Core internal bug */ if (!(dev->features & CLOCK_EVT_FEAT_PERIODIC)) return -ENOSYS; - return dev->set_state_periodic(dev); + if (dev->set_state_periodic) + return dev->set_state_periodic(dev); + return 0; case CLOCK_EVT_STATE_ONESHOT: /* Core internal bug */ if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT)) return -ENOSYS; - return dev->set_state_oneshot(dev); + if (dev->set_state_oneshot) + return dev->set_state_oneshot(dev); + return 0; case CLOCK_EVT_STATE_ONESHOT_STOPPED: /* Core internal bug */ @@ -471,18 +477,6 @@ static int clockevents_sanity_check(struct clock_event_device *dev) if (dev->features & CLOCK_EVT_FEAT_DUMMY) return 0; - /* New state-specific callbacks */ - if (!dev->set_state_shutdown) - return -EINVAL; - - if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) && - !dev->set_state_periodic) - return -EINVAL; - - if ((dev->features & CLOCK_EVT_FEAT_ONESHOT) && - !dev->set_state_oneshot) - return -EINVAL; - return 0; } diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index d39f32c..52b9e19 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -159,7 +159,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { struct clock_event_device *bc = tick_broadcast_device.evtdev; unsigned long flags; - int ret; + int ret = 0; raw_spin_lock_irqsave(&tick_broadcast_lock, flags); @@ -221,13 +221,14 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) * If we kept the cpu in the broadcast mask, * tell the caller to leave the per cpu device * in shutdown state. The periodic interrupt - * is delivered by the broadcast device. + * is delivered by the broadcast device, if + * the broadcast device exists and is not + * hrtimer based. */ - ret = cpumask_test_cpu(cpu, tick_broadcast_mask); + if (bc && !(bc->features & CLOCK_EVT_FEAT_HRTIMER)) + ret = cpumask_test_cpu(cpu, tick_broadcast_mask); break; default: - /* Nothing to do */ - ret = 0; break; } } @@ -265,8 +266,22 @@ static bool tick_do_broadcast(struct cpumask *mask) * Check, if the current cpu is in the mask */ if (cpumask_test_cpu(cpu, mask)) { + struct clock_event_device *bc = tick_broadcast_device.evtdev; + cpumask_clear_cpu(cpu, mask); - local = true; + /* + * We only run the local handler, if the broadcast + * device is not hrtimer based. Otherwise we run into + * a hrtimer recursion. + * + * local timer_interrupt() + * local_handler() + * expire_hrtimers() + * bc_handler() + * local_handler() + * expire_hrtimers() + */ + local = !(bc->features & CLOCK_EVT_FEAT_HRTIMER); } if (!cpumask_empty(mask)) { @@ -301,6 +316,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) bool bc_local; raw_spin_lock(&tick_broadcast_lock); + + /* Handle spurious interrupts gracefully */ + if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { + raw_spin_unlock(&tick_broadcast_lock); + return; + } + bc_local = tick_do_periodic_broadcast(); if (clockevent_state_oneshot(dev)) { @@ -359,8 +381,16 @@ void tick_broadcast_control(enum tick_broadcast_mode mode) case TICK_BROADCAST_ON: cpumask_set_cpu(cpu, tick_broadcast_on); if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { - if (tick_broadcast_device.mode == - TICKDEV_MODE_PERIODIC) + /* + * Only shutdown the cpu local device, if: + * + * - the broadcast device exists + * - the broadcast device is not a hrtimer based one + * - the broadcast device is in periodic mode to + * avoid a hickup during switch to oneshot mode + */ + if (bc && !(bc->features & CLOCK_EVT_FEAT_HRTIMER) && + tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) clockevents_shutdown(dev); } break; @@ -379,14 +409,16 @@ void tick_broadcast_control(enum tick_broadcast_mode mode) break; } - if (cpumask_empty(tick_broadcast_mask)) { - if (!bc_stopped) - clockevents_shutdown(bc); - } else if (bc_stopped) { - if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) - tick_broadcast_start_periodic(bc); - else - tick_broadcast_setup_oneshot(bc); + if (bc) { + if (cpumask_empty(tick_broadcast_mask)) { + if (!bc_stopped) + clockevents_shutdown(bc); + } else if (bc_stopped) { + if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) + tick_broadcast_start_periodic(bc); + else + tick_broadcast_setup_oneshot(bc); + } } raw_spin_unlock(&tick_broadcast_lock); } @@ -662,71 +694,82 @@ static void broadcast_shutdown_local(struct clock_event_device *bc, clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); } -/** - * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode - * @state: The target state (enter/exit) - * - * The system enters/leaves a state, where affected devices might stop - * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups. - * - * Called with interrupts disabled, so clockevents_lock is not - * required here because the local clock event device cannot go away - * under us. - */ -int tick_broadcast_oneshot_control(enum tick_broadcast_state state) +int __tick_broadcast_oneshot_control(enum tick_broadcast_state state) { struct clock_event_device *bc, *dev; - struct tick_device *td; int cpu, ret = 0; ktime_t now; /* - * Periodic mode does not care about the enter/exit of power - * states + * If there is no broadcast device, tell the caller not to go + * into deep idle. */ - if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) - return 0; + if (!tick_broadcast_device.evtdev) + return -EBUSY; - /* - * We are called with preemtion disabled from the depth of the - * idle code, so we can't be moved away. - */ - td = this_cpu_ptr(&tick_cpu_device); - dev = td->evtdev; - - if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) - return 0; + dev = this_cpu_ptr(&tick_cpu_device)->evtdev; raw_spin_lock(&tick_broadcast_lock); bc = tick_broadcast_device.evtdev; cpu = smp_processor_id(); if (state == TICK_BROADCAST_ENTER) { + /* + * If the current CPU owns the hrtimer broadcast + * mechanism, it cannot go deep idle and we do not add + * the CPU to the broadcast mask. We don't have to go + * through the EXIT path as the local timer is not + * shutdown. + */ + ret = broadcast_needs_cpu(bc, cpu); + if (ret) + goto out; + + /* + * If the broadcast device is in periodic mode, we + * return. + */ + if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { + /* If it is a hrtimer based broadcast, return busy */ + if (bc->features & CLOCK_EVT_FEAT_HRTIMER) + ret = -EBUSY; + goto out; + } + if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) { WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask)); + + /* Conditionally shut down the local timer. */ broadcast_shutdown_local(bc, dev); + /* * We only reprogram the broadcast timer if we * did not mark ourself in the force mask and * if the cpu local event is earlier than the * broadcast event. If the current CPU is in * the force mask, then we are going to be - * woken by the IPI right away. + * woken by the IPI right away; we return + * busy, so the CPU does not try to go deep + * idle. */ - if (!cpumask_test_cpu(cpu, tick_broadcast_force_mask) && - dev->next_event.tv64 < bc->next_event.tv64) + if (cpumask_test_cpu(cpu, tick_broadcast_force_mask)) { + ret = -EBUSY; + } else if (dev->next_event.tv64 < bc->next_event.tv64) { tick_broadcast_set_event(bc, cpu, dev->next_event); + /* + * In case of hrtimer broadcasts the + * programming might have moved the + * timer to this cpu. If yes, remove + * us from the broadcast mask and + * return busy. + */ + ret = broadcast_needs_cpu(bc, cpu); + if (ret) { + cpumask_clear_cpu(cpu, + tick_broadcast_oneshot_mask); + } + } } - /* - * If the current CPU owns the hrtimer broadcast - * mechanism, it cannot go deep idle and we remove the - * CPU from the broadcast mask. We don't have to go - * through the EXIT path as the local timer is not - * shutdown. - */ - ret = broadcast_needs_cpu(bc, cpu); - if (ret) - cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask); } else { if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) { clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT); @@ -938,6 +981,16 @@ bool tick_broadcast_oneshot_available(void) return bc ? bc->features & CLOCK_EVT_FEAT_ONESHOT : false; } +#else +int __tick_broadcast_oneshot_control(enum tick_broadcast_state state) +{ + struct clock_event_device *bc = tick_broadcast_device.evtdev; + + if (!bc || (bc->features & CLOCK_EVT_FEAT_HRTIMER)) + return -EBUSY; + + return 0; +} #endif void __init tick_broadcast_init(void) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 76446cb..55e13ef 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -343,6 +343,27 @@ out_bc: tick_install_broadcast_device(newdev); } +/** + * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode + * @state: The target state (enter/exit) + * + * The system enters/leaves a state, where affected devices might stop + * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups. + * + * Called with interrupts disabled, so clockevents_lock is not + * required here because the local clock event device cannot go away + * under us. + */ +int tick_broadcast_oneshot_control(enum tick_broadcast_state state) +{ + struct tick_device *td = this_cpu_ptr(&tick_cpu_device); + + if (!(td->evtdev->features & CLOCK_EVT_FEAT_C3STOP)) + return 0; + + return __tick_broadcast_oneshot_control(state); +} + #ifdef CONFIG_HOTPLUG_CPU /* * Transfer the do_timer job away from a dying cpu. diff --git a/kernel/time/tick-sched.h b/kernel/time/tick-sched.h index 42fdf49..a4a8d4e 100644 --- a/kernel/time/tick-sched.h +++ b/kernel/time/tick-sched.h @@ -71,4 +71,14 @@ extern void tick_cancel_sched_timer(int cpu); static inline void tick_cancel_sched_timer(int cpu) { } #endif +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST +extern int __tick_broadcast_oneshot_control(enum tick_broadcast_state state); +#else +static inline int +__tick_broadcast_oneshot_control(enum tick_broadcast_state state) +{ + return -EBUSY; +} +#endif + #endif diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index 777eda7..39f24d6 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -18,10 +18,6 @@ config KASAN For better error detection enable CONFIG_STACKTRACE, and add slub_debug=U to boot cmdline. -config KASAN_SHADOW_OFFSET - hex - default 0xdffffc0000000000 if X86_64 - choice prompt "Instrumentation type" depends on KASAN diff --git a/mm/memory.c b/mm/memory.c index a84fbb7..388dcf9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2670,6 +2670,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, pte_unmap(page_table); + /* File mapping without ->vm_ops ? */ + if (vma->vm_flags & VM_SHARED) + return VM_FAULT_SIGBUS; + /* Check if we need to add a guard page to the stack */ if (check_stack_guard_page(vma, address) < 0) return VM_FAULT_SIGSEGV; @@ -3099,6 +3103,9 @@ static int do_fault(struct mm_struct *mm, struct vm_area_struct *vma, - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; pte_unmap(page_table); + /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ + if (!vma->vm_ops->fault) + return VM_FAULT_SIGBUS; if (!(flags & FAULT_FLAG_WRITE)) return do_read_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); @@ -3244,13 +3251,12 @@ static int handle_pte_fault(struct mm_struct *mm, barrier(); if (!pte_present(entry)) { if (pte_none(entry)) { - if (vma->vm_ops) { - if (likely(vma->vm_ops->fault)) - return do_fault(mm, vma, address, pte, - pmd, flags, entry); - } - return do_anonymous_page(mm, vma, address, - pte, pmd, flags); + if (vma->vm_ops) + return do_fault(mm, vma, address, pte, pmd, + flags, entry); + + return do_anonymous_page(mm, vma, address, pte, pmd, + flags); } return do_swap_page(mm, vma, address, pte, pmd, flags, entry); diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index cb7db32..f30329f 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -9,6 +9,7 @@ #include <keys/ceph-type.h> #include <linux/module.h> #include <linux/mount.h> +#include <linux/nsproxy.h> #include <linux/parser.h> #include <linux/sched.h> #include <linux/seq_file.h> @@ -16,8 +17,6 @@ #include <linux/statfs.h> #include <linux/string.h> #include <linux/vmalloc.h> -#include <linux/nsproxy.h> -#include <net/net_namespace.h> #include <linux/ceph/ceph_features.h> @@ -131,6 +130,13 @@ int ceph_compare_options(struct ceph_options *new_opt, int i; int ret; + /* + * Don't bother comparing options if network namespaces don't + * match. + */ + if (!net_eq(current->nsproxy->net_ns, read_pnet(&client->msgr.net))) + return -1; + ret = memcmp(opt1, opt2, ofs); if (ret) return ret; @@ -335,9 +341,6 @@ ceph_parse_options(char *options, const char *dev_name, int err = -ENOMEM; substring_t argstr[MAX_OPT_ARGS]; - if (current->nsproxy->net_ns != &init_net) - return ERR_PTR(-EINVAL); - opt = kzalloc(sizeof(*opt), GFP_KERNEL); if (!opt) return ERR_PTR(-ENOMEM); @@ -608,6 +611,7 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, fail_monc: ceph_monc_stop(&client->monc); fail: + ceph_messenger_fini(&client->msgr); kfree(client); return ERR_PTR(err); } @@ -621,8 +625,8 @@ void ceph_destroy_client(struct ceph_client *client) /* unmount */ ceph_osdc_stop(&client->osdc); - ceph_monc_stop(&client->monc); + ceph_messenger_fini(&client->msgr); ceph_debugfs_client_cleanup(client); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1679f47..e3be1d22 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -6,6 +6,7 @@ #include <linux/inet.h> #include <linux/kthread.h> #include <linux/net.h> +#include <linux/nsproxy.h> #include <linux/slab.h> #include <linux/socket.h> #include <linux/string.h> @@ -479,7 +480,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) int ret; BUG_ON(con->sock); - ret = sock_create_kern(&init_net, con->peer_addr.in_addr.ss_family, + ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family, SOCK_STREAM, IPPROTO_TCP, &sock); if (ret) return ret; @@ -1731,17 +1732,17 @@ static int verify_hello(struct ceph_connection *con) static bool addr_is_blank(struct sockaddr_storage *ss) { + struct in_addr *addr = &((struct sockaddr_in *)ss)->sin_addr; + struct in6_addr *addr6 = &((struct sockaddr_in6 *)ss)->sin6_addr; + switch (ss->ss_family) { case AF_INET: - return ((struct sockaddr_in *)ss)->sin_addr.s_addr == 0; + return addr->s_addr == htonl(INADDR_ANY); case AF_INET6: - return - ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[0] == 0 && - ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[1] == 0 && - ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[2] == 0 && - ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[3] == 0; + return ipv6_addr_any(addr6); + default: + return true; } - return false; } static int addr_port(struct sockaddr_storage *ss) @@ -2944,11 +2945,18 @@ void ceph_messenger_init(struct ceph_messenger *msgr, msgr->tcp_nodelay = tcp_nodelay; atomic_set(&msgr->stopping, 0); + write_pnet(&msgr->net, get_net(current->nsproxy->net_ns)); dout("%s %p\n", __func__, msgr); } EXPORT_SYMBOL(ceph_messenger_init); +void ceph_messenger_fini(struct ceph_messenger *msgr) +{ + put_net(read_pnet(&msgr->net)); +} +EXPORT_SYMBOL(ceph_messenger_fini); + static void clear_standby(struct ceph_connection *con) { /* come back from STANDBY? */ diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index eff7de1..e70fcd1 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -63,6 +63,8 @@ int main(void) DEVID(acpi_device_id); DEVID_FIELD(acpi_device_id, id); + DEVID_FIELD(acpi_device_id, cls); + DEVID_FIELD(acpi_device_id, cls_msk); DEVID(pnp_device_id); DEVID_FIELD(pnp_device_id, id); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 84c86f3..5f20882 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -523,12 +523,40 @@ static int do_serio_entry(const char *filename, } ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry); -/* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */ +/* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or + * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if) + * + * NOTE: Each driver should use one of the following : _HID, _CIDs + * or _CLS. Also, bb, ss, and pp can be substituted with ?? + * as don't care byte. + */ static int do_acpi_entry(const char *filename, void *symval, char *alias) { DEF_FIELD_ADDR(symval, acpi_device_id, id); - sprintf(alias, "acpi*:%s:*", *id); + DEF_FIELD_ADDR(symval, acpi_device_id, cls); + DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk); + + if (id && strlen((const char *)*id)) + sprintf(alias, "acpi*:%s:*", *id); + else if (cls) { + int i, byte_shift, cnt = 0; + unsigned int msk; + + sprintf(&alias[cnt], "acpi*:"); + cnt = 6; + for (i = 1; i <= 3; i++) { + byte_shift = 8 * (3-i); + msk = (*cls_msk >> byte_shift) & 0xFF; + if (msk) + sprintf(&alias[cnt], "%02x", + (*cls >> byte_shift) & 0xFF); + else + sprintf(&alias[cnt], "??"); + cnt += 2; + } + sprintf(&alias[cnt], ":*"); + } return 1; } ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry); diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 91ee1b2..12d3db3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -886,7 +886,8 @@ static void check_section(const char *modname, struct elf_info *elf, #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \ ".kprobes.text" #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ - ".fixup", ".entry.text", ".exception.text", ".text.*" + ".fixup", ".entry.text", ".exception.text", ".text.*", \ + ".coldtext" #define INIT_SECTIONS ".init.*" #define MEM_INIT_SECTIONS ".meminit.*" diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6231081..564079c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3283,7 +3283,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared int rc = 0; if (default_noexec && - (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { + (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) || + (!shared && (prot & PROT_WRITE)))) { /* * We are making executable an anonymous mapping or a * private file mapping that will also be writable. diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index afe6a26..57644b1 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -153,6 +153,12 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, if (offset == (u32)-1) return 0; + /* don't waste ebitmap space if the netlabel bitmap is empty */ + if (bitmap == 0) { + offset += EBITMAP_UNIT_SIZE; + continue; + } + if (e_iter == NULL || offset >= e_iter->startbit + EBITMAP_SIZE) { e_prev = e_iter; diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h index f0e7267..9098083 100644 --- a/tools/include/linux/compiler.h +++ b/tools/include/linux/compiler.h @@ -41,4 +41,62 @@ #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) +#include <linux/types.h> + +static __always_inline void __read_once_size(const volatile void *p, void *res, int size) +{ + switch (size) { + case 1: *(__u8 *)res = *(volatile __u8 *)p; break; + case 2: *(__u16 *)res = *(volatile __u16 *)p; break; + case 4: *(__u32 *)res = *(volatile __u32 *)p; break; + case 8: *(__u64 *)res = *(volatile __u64 *)p; break; + default: + barrier(); + __builtin_memcpy((void *)res, (const void *)p, size); + barrier(); + } +} + +static __always_inline void __write_once_size(volatile void *p, void *res, int size) +{ + switch (size) { + case 1: *(volatile __u8 *)p = *(__u8 *)res; break; + case 2: *(volatile __u16 *)p = *(__u16 *)res; break; + case 4: *(volatile __u32 *)p = *(__u32 *)res; break; + case 8: *(volatile __u64 *)p = *(__u64 *)res; break; + default: + barrier(); + __builtin_memcpy((void *)p, (const void *)res, size); + barrier(); + } +} + +/* + * Prevent the compiler from merging or refetching reads or writes. The + * compiler is also forbidden from reordering successive instances of + * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the + * compiler is aware of some particular ordering. One way to make the + * compiler aware of ordering is to put the two invocations of READ_ONCE, + * WRITE_ONCE or ACCESS_ONCE() in different C statements. + * + * In contrast to ACCESS_ONCE these two macros will also work on aggregate + * data types like structs or unions. If the size of the accessed data + * type exceeds the word size of the machine (e.g., 32 bits or 64 bits) + * READ_ONCE() and WRITE_ONCE() will fall back to memcpy and print a + * compile-time warning. + * + * Their two major use cases are: (1) Mediating communication between + * process-level code and irq/NMI handlers, all running on the same CPU, + * and (2) Ensuring that the compiler does not fold, spindle, or otherwise + * mutilate accesses that either do not require ordering or that interact + * with an explicit memory barrier or atomic instruction that provides the + * required ordering. + */ + +#define READ_ONCE(x) \ + ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) + +#define WRITE_ONCE(x, val) \ + ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) + #endif /* _TOOLS_LINUX_COMPILER_H */ diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h deleted file mode 100644 index d07e586..0000000 --- a/tools/include/linux/export.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _TOOLS_LINUX_EXPORT_H_ -#define _TOOLS_LINUX_EXPORT_H_ - -#define EXPORT_SYMBOL(sym) -#define EXPORT_SYMBOL_GPL(sym) -#define EXPORT_SYMBOL_GPL_FUTURE(sym) -#define EXPORT_UNUSED_SYMBOL(sym) -#define EXPORT_UNUSED_SYMBOL_GPL(sym) - -#endif diff --git a/tools/include/linux/rbtree.h b/tools/include/linux/rbtree.h new file mode 100644 index 0000000..1125822 --- /dev/null +++ b/tools/include/linux/rbtree.h @@ -0,0 +1,104 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli <andrea@suse.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/include/linux/rbtree.h + + To use rbtrees you'll have to implement your own insert and search cores. + This will avoid us to use callbacks and to drop drammatically performances. + I know it's not the cleaner way, but in C (not in C++) to get + performances and genericity... + + See Documentation/rbtree.txt for documentation and samples. +*/ + +#ifndef __TOOLS_LINUX_PERF_RBTREE_H +#define __TOOLS_LINUX_PERF_RBTREE_H + +#include <linux/kernel.h> +#include <linux/stddef.h> + +struct rb_node { + unsigned long __rb_parent_color; + struct rb_node *rb_right; + struct rb_node *rb_left; +} __attribute__((aligned(sizeof(long)))); + /* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root { + struct rb_node *rb_node; +}; + + +#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) + +#define RB_ROOT (struct rb_root) { NULL, } +#define rb_entry(ptr, type, member) container_of(ptr, type, member) + +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) + +/* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ +#define RB_EMPTY_NODE(node) \ + ((node)->__rb_parent_color == (unsigned long)(node)) +#define RB_CLEAR_NODE(node) \ + ((node)->__rb_parent_color = (unsigned long)(node)) + + +extern void rb_insert_color(struct rb_node *, struct rb_root *); +extern void rb_erase(struct rb_node *, struct rb_root *); + + +/* Find logical next and previous nodes in a tree */ +extern struct rb_node *rb_next(const struct rb_node *); +extern struct rb_node *rb_prev(const struct rb_node *); +extern struct rb_node *rb_first(const struct rb_root *); +extern struct rb_node *rb_last(const struct rb_root *); + +/* Postorder iteration - always visit the parent after its children */ +extern struct rb_node *rb_first_postorder(const struct rb_root *); +extern struct rb_node *rb_next_postorder(const struct rb_node *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root); + +static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, + struct rb_node **rb_link) +{ + node->__rb_parent_color = (unsigned long)parent; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} + +#define rb_entry_safe(ptr, type, member) \ + ({ typeof(ptr) ____ptr = (ptr); \ + ____ptr ? rb_entry(____ptr, type, member) : NULL; \ + }) + + +/* + * Handy for checking that we are not deleting an entry that is + * already in a list, found in block/{blk-throttle,cfq-iosched}.c, + * probably should be moved to lib/rbtree.c... + */ +static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) +{ + rb_erase(n, root); + RB_CLEAR_NODE(n); +} +#endif /* __TOOLS_LINUX_PERF_RBTREE_H */ diff --git a/tools/include/linux/rbtree_augmented.h b/tools/include/linux/rbtree_augmented.h new file mode 100644 index 0000000..43be941 --- /dev/null +++ b/tools/include/linux/rbtree_augmented.h @@ -0,0 +1,245 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli <andrea@suse.de> + (C) 2002 David Woodhouse <dwmw2@infradead.org> + (C) 2012 Michel Lespinasse <walken@google.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 + + tools/linux/include/linux/rbtree_augmented.h + + Copied from: + linux/include/linux/rbtree_augmented.h +*/ + +#ifndef _TOOLS_LINUX_RBTREE_AUGMENTED_H +#define _TOOLS_LINUX_RBTREE_AUGMENTED_H + +#include <linux/compiler.h> +#include <linux/rbtree.h> + +/* + * Please note - only struct rb_augment_callbacks and the prototypes for + * rb_insert_augmented() and rb_erase_augmented() are intended to be public. + * The rest are implementation details you are not expected to depend on. + * + * See Documentation/rbtree.txt for documentation and samples. + */ + +struct rb_augment_callbacks { + void (*propagate)(struct rb_node *node, struct rb_node *stop); + void (*copy)(struct rb_node *old, struct rb_node *new); + void (*rotate)(struct rb_node *old, struct rb_node *new); +}; + +extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); +/* + * Fixup the rbtree and update the augmented information when rebalancing. + * + * On insertion, the user must update the augmented information on the path + * leading to the inserted node, then call rb_link_node() as usual and + * rb_augment_inserted() instead of the usual rb_insert_color() call. + * If rb_augment_inserted() rebalances the rbtree, it will callback into + * a user provided function to update the augmented information on the + * affected subtrees. + */ +static inline void +rb_insert_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) +{ + __rb_insert_augmented(node, root, augment->rotate); +} + +#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ + rbtype, rbaugmented, rbcompute) \ +static inline void \ +rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \ +{ \ + while (rb != stop) { \ + rbstruct *node = rb_entry(rb, rbstruct, rbfield); \ + rbtype augmented = rbcompute(node); \ + if (node->rbaugmented == augmented) \ + break; \ + node->rbaugmented = augmented; \ + rb = rb_parent(&node->rbfield); \ + } \ +} \ +static inline void \ +rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ +{ \ + rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ + rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ + new->rbaugmented = old->rbaugmented; \ +} \ +static void \ +rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ +{ \ + rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ + rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ + new->rbaugmented = old->rbaugmented; \ + old->rbaugmented = rbcompute(old); \ +} \ +rbstatic const struct rb_augment_callbacks rbname = { \ + rbname ## _propagate, rbname ## _copy, rbname ## _rotate \ +}; + + +#define RB_RED 0 +#define RB_BLACK 1 + +#define __rb_parent(pc) ((struct rb_node *)(pc & ~3)) + +#define __rb_color(pc) ((pc) & 1) +#define __rb_is_black(pc) __rb_color(pc) +#define __rb_is_red(pc) (!__rb_color(pc)) +#define rb_color(rb) __rb_color((rb)->__rb_parent_color) +#define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color) +#define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color) + +static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->__rb_parent_color = rb_color(rb) | (unsigned long)p; +} + +static inline void rb_set_parent_color(struct rb_node *rb, + struct rb_node *p, int color) +{ + rb->__rb_parent_color = (unsigned long)p | color; +} + +static inline void +__rb_change_child(struct rb_node *old, struct rb_node *new, + struct rb_node *parent, struct rb_root *root) +{ + if (parent) { + if (parent->rb_left == old) + parent->rb_left = new; + else + parent->rb_right = new; + } else + root->rb_node = new; +} + +extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); + +static __always_inline struct rb_node * +__rb_erase_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) +{ + struct rb_node *child = node->rb_right, *tmp = node->rb_left; + struct rb_node *parent, *rebalance; + unsigned long pc; + + if (!tmp) { + /* + * Case 1: node to erase has no more than 1 child (easy!) + * + * Note that if there is one child it must be red due to 5) + * and node must be black due to 4). We adjust colors locally + * so as to bypass __rb_erase_color() later on. + */ + pc = node->__rb_parent_color; + parent = __rb_parent(pc); + __rb_change_child(node, child, parent, root); + if (child) { + child->__rb_parent_color = pc; + rebalance = NULL; + } else + rebalance = __rb_is_black(pc) ? parent : NULL; + tmp = parent; + } else if (!child) { + /* Still case 1, but this time the child is node->rb_left */ + tmp->__rb_parent_color = pc = node->__rb_parent_color; + parent = __rb_parent(pc); + __rb_change_child(node, tmp, parent, root); + rebalance = NULL; + tmp = parent; + } else { + struct rb_node *successor = child, *child2; + tmp = child->rb_left; + if (!tmp) { + /* + * Case 2: node's successor is its right child + * + * (n) (s) + * / \ / \ + * (x) (s) -> (x) (c) + * \ + * (c) + */ + parent = successor; + child2 = successor->rb_right; + augment->copy(node, successor); + } else { + /* + * Case 3: node's successor is leftmost under + * node's right child subtree + * + * (n) (s) + * / \ / \ + * (x) (y) -> (x) (y) + * / / + * (p) (p) + * / / + * (s) (c) + * \ + * (c) + */ + do { + parent = successor; + successor = tmp; + tmp = tmp->rb_left; + } while (tmp); + parent->rb_left = child2 = successor->rb_right; + successor->rb_right = child; + rb_set_parent(child, successor); + augment->copy(node, successor); + augment->propagate(parent, successor); + } + + successor->rb_left = tmp = node->rb_left; + rb_set_parent(tmp, successor); + + pc = node->__rb_parent_color; + tmp = __rb_parent(pc); + __rb_change_child(node, successor, tmp, root); + if (child2) { + successor->__rb_parent_color = pc; + rb_set_parent_color(child2, parent, RB_BLACK); + rebalance = NULL; + } else { + unsigned long pc2 = successor->__rb_parent_color; + successor->__rb_parent_color = pc; + rebalance = __rb_is_black(pc2) ? parent : NULL; + } + tmp = successor; + } + + augment->propagate(tmp, NULL); + return rebalance; +} + +static __always_inline void +rb_erase_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) +{ + struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); + if (rebalance) + __rb_erase_color(rebalance, root, augment->rotate); +} + +#endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */ diff --git a/tools/lib/rbtree.c b/tools/lib/rbtree.c new file mode 100644 index 0000000..17c2b59 --- /dev/null +++ b/tools/lib/rbtree.c @@ -0,0 +1,548 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli <andrea@suse.de> + (C) 2002 David Woodhouse <dwmw2@infradead.org> + (C) 2012 Michel Lespinasse <walken@google.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 + + linux/lib/rbtree.c +*/ + +#include <linux/rbtree_augmented.h> + +/* + * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree + * + * 1) A node is either red or black + * 2) The root is black + * 3) All leaves (NULL) are black + * 4) Both children of every red node are black + * 5) Every simple path from root to leaves contains the same number + * of black nodes. + * + * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two + * consecutive red nodes in a path and every red node is therefore followed by + * a black. So if B is the number of black nodes on every simple path (as per + * 5), then the longest possible path due to 4 is 2B. + * + * We shall indicate color with case, where black nodes are uppercase and red + * nodes will be lowercase. Unknown color nodes shall be drawn as red within + * parentheses and have some accompanying text comment. + */ + +static inline void rb_set_black(struct rb_node *rb) +{ + rb->__rb_parent_color |= RB_BLACK; +} + +static inline struct rb_node *rb_red_parent(struct rb_node *red) +{ + return (struct rb_node *)red->__rb_parent_color; +} + +/* + * Helper function for rotations: + * - old's parent and color get assigned to new + * - old gets assigned new as a parent and 'color' as a color. + */ +static inline void +__rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, + struct rb_root *root, int color) +{ + struct rb_node *parent = rb_parent(old); + new->__rb_parent_color = old->__rb_parent_color; + rb_set_parent_color(old, new, color); + __rb_change_child(old, new, parent, root); +} + +static __always_inline void +__rb_insert(struct rb_node *node, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; + + while (true) { + /* + * Loop invariant: node is red + * + * If there is a black parent, we are done. + * Otherwise, take some corrective action as we don't + * want a red root or two consecutive red nodes. + */ + if (!parent) { + rb_set_parent_color(node, NULL, RB_BLACK); + break; + } else if (rb_is_black(parent)) + break; + + gparent = rb_red_parent(parent); + + tmp = gparent->rb_right; + if (parent != tmp) { /* parent == gparent->rb_left */ + if (tmp && rb_is_red(tmp)) { + /* + * Case 1 - color flips + * + * G g + * / \ / \ + * p u --> P U + * / / + * n n + * + * However, since g's parent might be red, and + * 4) does not allow this, we need to recurse + * at g. + */ + rb_set_parent_color(tmp, gparent, RB_BLACK); + rb_set_parent_color(parent, gparent, RB_BLACK); + node = gparent; + parent = rb_parent(node); + rb_set_parent_color(node, parent, RB_RED); + continue; + } + + tmp = parent->rb_right; + if (node == tmp) { + /* + * Case 2 - left rotate at parent + * + * G G + * / \ / \ + * p U --> n U + * \ / + * n p + * + * This still leaves us in violation of 4), the + * continuation into Case 3 will fix that. + */ + parent->rb_right = tmp = node->rb_left; + node->rb_left = parent; + if (tmp) + rb_set_parent_color(tmp, parent, + RB_BLACK); + rb_set_parent_color(parent, node, RB_RED); + augment_rotate(parent, node); + parent = node; + tmp = node->rb_right; + } + + /* + * Case 3 - right rotate at gparent + * + * G P + * / \ / \ + * p U --> n g + * / \ + * n U + */ + gparent->rb_left = tmp; /* == parent->rb_right */ + parent->rb_right = gparent; + if (tmp) + rb_set_parent_color(tmp, gparent, RB_BLACK); + __rb_rotate_set_parents(gparent, parent, root, RB_RED); + augment_rotate(gparent, parent); + break; + } else { + tmp = gparent->rb_left; + if (tmp && rb_is_red(tmp)) { + /* Case 1 - color flips */ + rb_set_parent_color(tmp, gparent, RB_BLACK); + rb_set_parent_color(parent, gparent, RB_BLACK); + node = gparent; + parent = rb_parent(node); + rb_set_parent_color(node, parent, RB_RED); + continue; + } + + tmp = parent->rb_left; + if (node == tmp) { + /* Case 2 - right rotate at parent */ + parent->rb_left = tmp = node->rb_right; + node->rb_right = parent; + if (tmp) + rb_set_parent_color(tmp, parent, + RB_BLACK); + rb_set_parent_color(parent, node, RB_RED); + augment_rotate(parent, node); + parent = node; + tmp = node->rb_left; + } + + /* Case 3 - left rotate at gparent */ + gparent->rb_right = tmp; /* == parent->rb_left */ + parent->rb_left = gparent; + if (tmp) + rb_set_parent_color(tmp, gparent, RB_BLACK); + __rb_rotate_set_parents(gparent, parent, root, RB_RED); + augment_rotate(gparent, parent); + break; + } + } +} + +/* + * Inline version for rb_erase() use - we want to be able to inline + * and eliminate the dummy_rotate callback there + */ +static __always_inline void +____rb_erase_color(struct rb_node *parent, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; + + while (true) { + /* + * Loop invariants: + * - node is black (or NULL on first iteration) + * - node is not the root (parent is not NULL) + * - All leaf paths going through parent and node have a + * black node count that is 1 lower than other leaf paths. + */ + sibling = parent->rb_right; + if (node != sibling) { /* node == parent->rb_left */ + if (rb_is_red(sibling)) { + /* + * Case 1 - left rotate at parent + * + * P S + * / \ / \ + * N s --> p Sr + * / \ / \ + * Sl Sr N Sl + */ + parent->rb_right = tmp1 = sibling->rb_left; + sibling->rb_left = parent; + rb_set_parent_color(tmp1, parent, RB_BLACK); + __rb_rotate_set_parents(parent, sibling, root, + RB_RED); + augment_rotate(parent, sibling); + sibling = tmp1; + } + tmp1 = sibling->rb_right; + if (!tmp1 || rb_is_black(tmp1)) { + tmp2 = sibling->rb_left; + if (!tmp2 || rb_is_black(tmp2)) { + /* + * Case 2 - sibling color flip + * (p could be either color here) + * + * (p) (p) + * / \ / \ + * N S --> N s + * / \ / \ + * Sl Sr Sl Sr + * + * This leaves us violating 5) which + * can be fixed by flipping p to black + * if it was red, or by recursing at p. + * p is red when coming from Case 1. + */ + rb_set_parent_color(sibling, parent, + RB_RED); + if (rb_is_red(parent)) + rb_set_black(parent); + else { + node = parent; + parent = rb_parent(node); + if (parent) + continue; + } + break; + } + /* + * Case 3 - right rotate at sibling + * (p could be either color here) + * + * (p) (p) + * / \ / \ + * N S --> N Sl + * / \ \ + * sl Sr s + * \ + * Sr + */ + sibling->rb_left = tmp1 = tmp2->rb_right; + tmp2->rb_right = sibling; + parent->rb_right = tmp2; + if (tmp1) + rb_set_parent_color(tmp1, sibling, + RB_BLACK); + augment_rotate(sibling, tmp2); + tmp1 = sibling; + sibling = tmp2; + } + /* + * Case 4 - left rotate at parent + color flips + * (p and sl could be either color here. + * After rotation, p becomes black, s acquires + * p's color, and sl keeps its color) + * + * (p) (s) + * / \ / \ + * N S --> P Sr + * / \ / \ + * (sl) sr N (sl) + */ + parent->rb_right = tmp2 = sibling->rb_left; + sibling->rb_left = parent; + rb_set_parent_color(tmp1, sibling, RB_BLACK); + if (tmp2) + rb_set_parent(tmp2, parent); + __rb_rotate_set_parents(parent, sibling, root, + RB_BLACK); + augment_rotate(parent, sibling); + break; + } else { + sibling = parent->rb_left; + if (rb_is_red(sibling)) { + /* Case 1 - right rotate at parent */ + parent->rb_left = tmp1 = sibling->rb_right; + sibling->rb_right = parent; + rb_set_parent_color(tmp1, parent, RB_BLACK); + __rb_rotate_set_parents(parent, sibling, root, + RB_RED); + augment_rotate(parent, sibling); + sibling = tmp1; + } + tmp1 = sibling->rb_left; + if (!tmp1 || rb_is_black(tmp1)) { + tmp2 = sibling->rb_right; + if (!tmp2 || rb_is_black(tmp2)) { + /* Case 2 - sibling color flip */ + rb_set_parent_color(sibling, parent, + RB_RED); + if (rb_is_red(parent)) + rb_set_black(parent); + else { + node = parent; + parent = rb_parent(node); + if (parent) + continue; + } + break; + } + /* Case 3 - right rotate at sibling */ + sibling->rb_right = tmp1 = tmp2->rb_left; + tmp2->rb_left = sibling; + parent->rb_left = tmp2; + if (tmp1) + rb_set_parent_color(tmp1, sibling, + RB_BLACK); + augment_rotate(sibling, tmp2); + tmp1 = sibling; + sibling = tmp2; + } + /* Case 4 - left rotate at parent + color flips */ + parent->rb_left = tmp2 = sibling->rb_right; + sibling->rb_right = parent; + rb_set_parent_color(tmp1, sibling, RB_BLACK); + if (tmp2) + rb_set_parent(tmp2, parent); + __rb_rotate_set_parents(parent, sibling, root, + RB_BLACK); + augment_rotate(parent, sibling); + break; + } + } +} + +/* Non-inline version for rb_erase_augmented() use */ +void __rb_erase_color(struct rb_node *parent, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + ____rb_erase_color(parent, root, augment_rotate); +} + +/* + * Non-augmented rbtree manipulation functions. + * + * We use dummy augmented callbacks here, and have the compiler optimize them + * out of the rb_insert_color() and rb_erase() function definitions. + */ + +static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {} +static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} +static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} + +static const struct rb_augment_callbacks dummy_callbacks = { + dummy_propagate, dummy_copy, dummy_rotate +}; + +void rb_insert_color(struct rb_node *node, struct rb_root *root) +{ + __rb_insert(node, root, dummy_rotate); +} + +void rb_erase(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *rebalance; + rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); + if (rebalance) + ____rb_erase_color(rebalance, root, dummy_rotate); +} + +/* + * Augmented rbtree manipulation functions. + * + * This instantiates the same __always_inline functions as in the non-augmented + * case, but this time with user-defined callbacks. + */ + +void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + __rb_insert(node, root, augment_rotate); +} + +/* + * This function returns the first node (in sort order) of the tree. + */ +struct rb_node *rb_first(const struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_left) + n = n->rb_left; + return n; +} + +struct rb_node *rb_last(const struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_right) + n = n->rb_right; + return n; +} + +struct rb_node *rb_next(const struct rb_node *node) +{ + struct rb_node *parent; + + if (RB_EMPTY_NODE(node)) + return NULL; + + /* + * If we have a right-hand child, go down and then left as far + * as we can. + */ + if (node->rb_right) { + node = node->rb_right; + while (node->rb_left) + node=node->rb_left; + return (struct rb_node *)node; + } + + /* + * No right-hand children. Everything down and left is smaller than us, + * so any 'next' node must be in the general direction of our parent. + * Go up the tree; any time the ancestor is a right-hand child of its + * parent, keep going up. First time it's a left-hand child of its + * parent, said parent is our 'next' node. + */ + while ((parent = rb_parent(node)) && node == parent->rb_right) + node = parent; + + return parent; +} + +struct rb_node *rb_prev(const struct rb_node *node) +{ + struct rb_node *parent; + + if (RB_EMPTY_NODE(node)) + return NULL; + + /* + * If we have a left-hand child, go down and then right as far + * as we can. + */ + if (node->rb_left) { + node = node->rb_left; + while (node->rb_right) + node=node->rb_right; + return (struct rb_node *)node; + } + + /* + * No left-hand children. Go up till we find an ancestor which + * is a right-hand child of its parent. + */ + while ((parent = rb_parent(node)) && node == parent->rb_left) + node = parent; + + return parent; +} + +void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root) +{ + struct rb_node *parent = rb_parent(victim); + + /* Set the surrounding nodes to point to the replacement */ + __rb_change_child(victim, new, parent, root); + if (victim->rb_left) + rb_set_parent(victim->rb_left, new); + if (victim->rb_right) + rb_set_parent(victim->rb_right, new); + + /* Copy the pointers/colour from the victim to the replacement */ + *new = *victim; +} + +static struct rb_node *rb_left_deepest_node(const struct rb_node *node) +{ + for (;;) { + if (node->rb_left) + node = node->rb_left; + else if (node->rb_right) + node = node->rb_right; + else + return (struct rb_node *)node; + } +} + +struct rb_node *rb_next_postorder(const struct rb_node *node) +{ + const struct rb_node *parent; + if (!node) + return NULL; + parent = rb_parent(node); + + /* If we're sitting on node, we've already seen our children */ + if (parent && node == parent->rb_left && parent->rb_right) { + /* If we are the parent's left node, go to the parent's right + * node then all the way down to the left */ + return rb_left_deepest_node(parent->rb_right); + } else + /* Otherwise we are the parent's right node, and the parent + * should be next */ + return (struct rb_node *)parent; +} + +struct rb_node *rb_first_postorder(const struct rb_root *root) +{ + if (!root->rb_node) + return NULL; + + return rb_left_deepest_node(root->rb_node); +} diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index fe50a1b..09dc0aa 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST @@ -18,6 +18,7 @@ tools/arch/x86/include/asm/atomic.h tools/arch/x86/include/asm/rmwcc.h tools/lib/traceevent tools/lib/api +tools/lib/rbtree.c tools/lib/symbol/kallsyms.c tools/lib/symbol/kallsyms.h tools/lib/util/find_next_bit.c @@ -44,6 +45,8 @@ tools/include/linux/kernel.h tools/include/linux/list.h tools/include/linux/log2.h tools/include/linux/poison.h +tools/include/linux/rbtree.h +tools/include/linux/rbtree_augmented.h tools/include/linux/types.h include/asm-generic/bitops/arch_hweight.h include/asm-generic/bitops/const_hweight.h @@ -51,12 +54,10 @@ include/asm-generic/bitops/fls64.h include/asm-generic/bitops/__fls.h include/asm-generic/bitops/fls.h include/linux/perf_event.h -include/linux/rbtree.h include/linux/list.h include/linux/hash.h include/linux/stringify.h lib/hweight.c -lib/rbtree.c include/linux/swab.h arch/*/include/asm/unistd*.h arch/*/include/uapi/asm/unistd*.h @@ -65,7 +66,6 @@ arch/*/lib/memcpy*.S arch/*/lib/memset*.S include/linux/poison.h include/linux/hw_breakpoint.h -include/linux/rbtree_augmented.h include/uapi/linux/perf_event.h include/uapi/linux/const.h include/uapi/linux/swab.h diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 586a59d..601d114 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -139,7 +139,7 @@ $(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) -$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c FORCE +$(OUTPUT)util/rbtree.o: ../lib/rbtree.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h deleted file mode 100644 index f06d89f..0000000 --- a/tools/perf/util/include/linux/rbtree.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __TOOLS_LINUX_PERF_RBTREE_H -#define __TOOLS_LINUX_PERF_RBTREE_H -#include <stdbool.h> -#include "../../../../include/linux/rbtree.h" - -/* - * Handy for checking that we are not deleting an entry that is - * already in a list, found in block/{blk-throttle,cfq-iosched}.c, - * probably should be moved to lib/rbtree.c... - */ -static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) -{ - rb_erase(n, root); - RB_CLEAR_NODE(n); -} -#endif /* __TOOLS_LINUX_PERF_RBTREE_H */ diff --git a/tools/perf/util/include/linux/rbtree_augmented.h b/tools/perf/util/include/linux/rbtree_augmented.h deleted file mode 100644 index 9d6fcdf..0000000 --- a/tools/perf/util/include/linux/rbtree_augmented.h +++ /dev/null @@ -1,2 +0,0 @@ -#include <stdbool.h> -#include "../../../../include/linux/rbtree_augmented.h" diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index 8e9b645..f56914c 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild @@ -1,3 +1,6 @@ +ldflags-y += --wrap=ioremap_wt +ldflags-y += --wrap=ioremap_wc +ldflags-y += --wrap=devm_ioremap_nocache ldflags-y += --wrap=ioremap_cache ldflags-y += --wrap=ioremap_nocache ldflags-y += --wrap=iounmap diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c index c85a6f6..64bfaa5 100644 --- a/tools/testing/nvdimm/test/iomap.c +++ b/tools/testing/nvdimm/test/iomap.c @@ -65,6 +65,21 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, return fallback_fn(offset, size); } +void __iomem *__wrap_devm_ioremap_nocache(struct device *dev, + resource_size_t offset, unsigned long size) +{ + struct nfit_test_resource *nfit_res; + + rcu_read_lock(); + nfit_res = get_nfit_res(offset); + rcu_read_unlock(); + if (nfit_res) + return (void __iomem *) nfit_res->buf + offset + - nfit_res->res->start; + return devm_ioremap_nocache(dev, offset, size); +} +EXPORT_SYMBOL(__wrap_devm_ioremap_nocache); + void __iomem *__wrap_ioremap_cache(resource_size_t offset, unsigned long size) { return __nfit_test_ioremap(offset, size, ioremap_cache); @@ -77,6 +92,18 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size) } EXPORT_SYMBOL(__wrap_ioremap_nocache); +void __iomem *__wrap_ioremap_wt(resource_size_t offset, unsigned long size) +{ + return __nfit_test_ioremap(offset, size, ioremap_wt); +} +EXPORT_SYMBOL(__wrap_ioremap_wt); + +void __iomem *__wrap_ioremap_wc(resource_size_t offset, unsigned long size) +{ + return __nfit_test_ioremap(offset, size, ioremap_wc); +} +EXPORT_SYMBOL(__wrap_ioremap_wc); + void __wrap_iounmap(volatile void __iomem *addr) { struct nfit_test_resource *nfit_res; diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 4b69b83..d0bdae4 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -128,6 +128,8 @@ struct nfit_test { int num_pm; void **dimm; dma_addr_t *dimm_dma; + void **flush; + dma_addr_t *flush_dma; void **label; dma_addr_t *label_dma; void **spa_set; @@ -155,7 +157,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, int i, rc; if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) - return -ENXIO; + return -ENOTTY; /* lookup label space for the given dimm */ for (i = 0; i < ARRAY_SIZE(handle); i++) @@ -331,7 +333,8 @@ static int nfit_test0_alloc(struct nfit_test *t) + sizeof(struct acpi_nfit_system_address) * NUM_SPA + sizeof(struct acpi_nfit_memory_map) * NUM_MEM + sizeof(struct acpi_nfit_control_region) * NUM_DCR - + sizeof(struct acpi_nfit_data_region) * NUM_BDW; + + sizeof(struct acpi_nfit_data_region) * NUM_BDW + + sizeof(struct acpi_nfit_flush_address) * NUM_DCR; int i; t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); @@ -356,6 +359,10 @@ static int nfit_test0_alloc(struct nfit_test *t) if (!t->label[i]) return -ENOMEM; sprintf(t->label[i], "label%d", i); + + t->flush[i] = test_alloc(t, 8, &t->flush_dma[i]); + if (!t->flush[i]) + return -ENOMEM; } for (i = 0; i < NUM_DCR; i++) { @@ -408,6 +415,7 @@ static void nfit_test0_setup(struct nfit_test *t) struct acpi_nfit_system_address *spa; struct acpi_nfit_control_region *dcr; struct acpi_nfit_data_region *bdw; + struct acpi_nfit_flush_address *flush; unsigned int offset; nfit_test_init_header(nfit_buf, size); @@ -831,6 +839,39 @@ static void nfit_test0_setup(struct nfit_test *t) bdw->capacity = DIMM_SIZE; bdw->start_address = 0; + offset = offset + sizeof(struct acpi_nfit_data_region) * 4; + /* flush0 (dimm0) */ + flush = nfit_buf + offset; + flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; + flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->device_handle = handle[0]; + flush->hint_count = 1; + flush->hint_address[0] = t->flush_dma[0]; + + /* flush1 (dimm1) */ + flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 1; + flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; + flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->device_handle = handle[1]; + flush->hint_count = 1; + flush->hint_address[0] = t->flush_dma[1]; + + /* flush2 (dimm2) */ + flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 2; + flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; + flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->device_handle = handle[2]; + flush->hint_count = 1; + flush->hint_address[0] = t->flush_dma[2]; + + /* flush3 (dimm3) */ + flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 3; + flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; + flush->header.length = sizeof(struct acpi_nfit_flush_address); + flush->device_handle = handle[3]; + flush->hint_count = 1; + flush->hint_address[0] = t->flush_dma[3]; + acpi_desc = &t->acpi_desc; set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); @@ -933,6 +974,10 @@ static int nfit_test_probe(struct platform_device *pdev) GFP_KERNEL); nfit_test->dimm_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t), GFP_KERNEL); + nfit_test->flush = devm_kcalloc(dev, num, sizeof(void *), + GFP_KERNEL); + nfit_test->flush_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t), + GFP_KERNEL); nfit_test->label = devm_kcalloc(dev, num, sizeof(void *), GFP_KERNEL); nfit_test->label_dma = devm_kcalloc(dev, num, @@ -943,7 +988,8 @@ static int nfit_test_probe(struct platform_device *pdev) sizeof(dma_addr_t), GFP_KERNEL); if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label && nfit_test->label_dma && nfit_test->dcr - && nfit_test->dcr_dma) + && nfit_test->dcr_dma && nfit_test->flush + && nfit_test->flush_dma) /* pass */; else return -ENOMEM; |