Merge tag 'at91-cleanup3' of git://git.kernel.org/pub/scm/linux/kernel/git/nferre...
authorOlof Johansson <olof@lixom.net>
Tue, 27 Jan 2015 02:40:58 +0000 (18:40 -0800)
committerOlof Johansson <olof@lixom.net>
Tue, 27 Jan 2015 02:40:58 +0000 (18:40 -0800)
Merge "at91: cleanup/soc for 3.20 #3 (bis) from Nicolas Ferre:

Third batch of cleanup/soc for 3.20:
- several fixes and adjustments following the last cleanup batch
- removal of some unused Kconfig options
- slight PM and pm_idle rework to ease future rework
- removal of unneeded mach/system_rev.h

* tag 'at91-cleanup3' of git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91:
  ARM: at91: pm: remove warning to remove SOC_AT91SAM9263 usage
  ARM: at91: remove unused mach/system_rev.h
  ARM: at91: stop using HAVE_AT91_DBGUx
  ARM: at91: fix ordering of SRAM and PM initialization
  ARM: at91: sam9: set arm_pm_idle from sam9_dt_device_init
  ARM: at91: fix sam9n12 and sam9x5 arm_pm_idle
  ARM: at91: mark const init data with __initconst instead of __initdata
  ARM: at91: fix PM initialization for newer SoCs
  ARM: at91: fix Kconfig.debug by adding DEBUG_AT91_UART option

Signed-off-by: Olof Johansson <olof@lixom.net>
69 files changed:
Documentation/arm/sti/stih418-overview.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/fsl.txt
Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/sti.txt
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
MAINTAINERS
arch/arm/Kconfig.debug
arch/arm/boot/dts/tegra124-jetson-tk1.dts
arch/arm/include/debug/msm.S
arch/arm/include/debug/sirf.S
arch/arm/mach-bcm/platsmp-brcmstb.c
arch/arm/mach-hisi/Kconfig
arch/arm/mach-hisi/core.h
arch/arm/mach-hisi/headsmp.S
arch/arm/mach-hisi/hisilicon.c
arch/arm/mach-hisi/hotplug.c
arch/arm/mach-hisi/platsmp.c
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clk-gate2.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/clk-pllv3.c
arch/arm/mach-imx/clk-vf610.c
arch/arm/mach-imx/clk.h
arch/arm/mach-imx/common.h
arch/arm/mach-imx/cpuidle-imx6sx.c [new file with mode: 0644]
arch/arm/mach-imx/cpuidle.h
arch/arm/mach-imx/gpc.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-imx6sx.c
arch/arm/mach-imx/mach-vf610.c
arch/arm/mach-imx/pm-imx6.c
arch/arm/mach-mediatek/Kconfig
arch/arm/mach-mvebu/coherency.c
arch/arm/mach-mvebu/mvebu-soc-id.h
arch/arm/mach-prima2/Kconfig
arch/arm/mach-prima2/Makefile
arch/arm/mach-prima2/common.c
arch/arm/mach-prima2/lluart.c [deleted file]
arch/arm/mach-prima2/platsmp.c
arch/arm/mach-prima2/rstc.c
arch/arm/mach-prima2/rtciobrg.c
arch/arm/mach-qcom/Kconfig
arch/arm/mach-qcom/scm-boot.c
arch/arm/mach-qcom/scm-boot.h
arch/arm/mach-qcom/scm.c
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/pm.c [new file with mode: 0644]
arch/arm/mach-rockchip/pm.h [new file with mode: 0644]
arch/arm/mach-rockchip/rockchip.c
arch/arm/mach-rockchip/sleep.S [new file with mode: 0644]
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-shmobile/pm-r8a7740.c
arch/arm/mach-shmobile/pm-rmobile.c
arch/arm/mach-shmobile/pm-rmobile.h
arch/arm/mach-shmobile/pm-sh7372.c
arch/arm/mach-shmobile/setup-rcar-gen2.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-sti/board-dt.c
arch/arm/mach-tegra/Kconfig
drivers/bus/mvebu-mbus.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/fuse/fuse-tegra30.c
drivers/soc/tegra/pmc.c
include/dt-bindings/clock/vf610-clock.h
include/soc/tegra/fuse.h
include/soc/tegra/pm.h

diff --git a/Documentation/arm/sti/stih418-overview.txt b/Documentation/arm/sti/stih418-overview.txt
new file mode 100644 (file)
index 0000000..1cd8fc8
--- /dev/null
@@ -0,0 +1,20 @@
+                       STiH418 Overview
+                       ================
+
+Introduction
+------------
+
+    The STiH418 is the new generation of SoC for UHDp60 set-top boxes
+    and server/connected client application for satellite, cable, terrestrial
+    and IP-STB markets.
+
+    Features
+    - ARM Cortex-A9 1.5 GHz quad core CPU (28nm)
+    - SATA2, USB 3.0, PCIe, Gbit Ethernet
+    - HEVC L5.1 Main 10
+    - VP9
+
+  Document Author
+  ---------------
+
+  Maxime Coquelin <maxime.coquelin@st.com>, (c) 2015 ST Microelectronics
index 4e8b7df..c830b5b 100644 (file)
@@ -75,6 +75,18 @@ i.MX6q generic board
 Required root node properties:
     - compatible = "fsl,imx6q";
 
+Freescale Vybrid Platform Device Tree Bindings
+----------------------------------------------
+
+For the Vybrid SoC familiy all variants with DDR controller are supported,
+which is the VF5xx and VF6xx series. Out of historical reasons, in most
+places the kernel uses vf610 to refer to the whole familiy.
+
+Required root node compatible property (one of them):
+    - compatible = "fsl,vf500";
+    - compatible = "fsl,vf510";
+    - compatible = "fsl,vf600";
+    - compatible = "fsl,vf610";
 
 Freescale LS1021A Platform Device Tree Bindings
 ------------------------------------------------
diff --git a/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt b/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt
new file mode 100644 (file)
index 0000000..6b42fda
--- /dev/null
@@ -0,0 +1,16 @@
+Rockchip SRAM for pmu:
+------------------------------
+
+The sram of pmu is used to store the function of resume from maskrom(the 1st
+level loader). This is a common use of the "pmu-sram" because it keeps power
+even in low power states in the system.
+
+Required node properties:
+- compatible : should be "rockchip,rk3288-pmu-sram"
+- reg : physical base address and the size of the registers window
+
+Example:
+       sram@ff720000 {
+               compatible = "rockchip,rk3288-pmu-sram", "mmio-sram";
+               reg = <0xff720000 0x1000>;
+       };
index 92f16c7..d70ec35 100644 (file)
@@ -13,3 +13,7 @@ Boards with the ST STiH407 SoC shall have the following properties:
 Required root node property:
 compatible = "st,stih407";
 
+Boards with the ST STiH418 SoC shall have the following properties:
+Required root node property:
+compatible = "st,stih418";
+
index 68ac65f..2fd5051 100644 (file)
@@ -47,6 +47,23 @@ Required properties when nvidia,suspend-mode=<0>:
   sleep mode, the warm boot code will restore some PLLs, clocks and then
   bring up CPU0 for resuming the system.
 
+Hardware-triggered thermal reset:
+On Tegra30, Tegra114 and Tegra124, if the 'i2c-thermtrip' subnode exists,
+hardware-triggered thermal reset will be enabled.
+
+Required properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'):
+- nvidia,i2c-controller-id : ID of I2C controller to send poweroff command to. Valid values are
+                             described in section 9.2.148 "APBDEV_PMC_SCRATCH53_0" of the
+                             Tegra K1 Technical Reference Manual.
+- nvidia,bus-addr : Bus address of the PMU on the I2C bus
+- nvidia,reg-addr : I2C register address to write poweroff command to
+- nvidia,reg-data : Poweroff command to write to PMU
+
+Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'):
+- nvidia,pinmux-id : Pinmux used by the hardware when issuing poweroff command.
+                     Defaults to 0. Valid values are described in section 12.5.2
+                     "Pinmux Support" of the Tegra4 Technical Reference Manual.
+
 Example:
 
 / SoC dts including file
@@ -68,6 +85,15 @@ pmc@7000f400 {
 
 / Tegra board dts file
 {
+       ...
+       pmc@7000f400 {
+               i2c-thermtrip {
+                       nvidia,i2c-controller-id = <4>;
+                       nvidia,bus-addr = <0x40>;
+                       nvidia,reg-addr = <0x36>;
+                       nvidia,reg-data = <0x2>;
+               };
+       };
        ...
        clocks {
                compatible = "simple-bus";
index 8c25979..a087a6d 100644 (file)
@@ -1291,10 +1291,13 @@ S:      Maintained
 
 ARM/QUALCOMM SUPPORT
 M:     Kumar Gala <galak@codeaurora.org>
+M:     Andy Gross <agross@codeaurora.org>
 M:     David Brown <davidb@codeaurora.org>
 L:     linux-arm-msm@vger.kernel.org
+L:     linux-soc@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-qcom/
+F:     drivers/soc/qcom/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
 
 ARM/RADISYS ENP2611 MACHINE SUPPORT
index 575db67..453ae2f 100644 (file)
@@ -278,6 +278,14 @@ choice
                  Say Y here if you want the debug print routines to direct
                  their output to the UART on Highbank based devices.
 
+       config DEBUG_HIP01_UART
+               bool "Hisilicon Hip01 Debug UART"
+               depends on ARCH_HIP01
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 on HIP01 UART.
+
        config DEBUG_HIP04_UART
                bool "Hisilicon HiP04 Debug UART"
                depends on ARCH_HIP04
@@ -433,7 +441,7 @@ choice
                  Say Y here if you want the debug print routines to direct
                  their output to the serial port on MSM devices.
 
-                 ARCH                DEBUG_UART_PHYS   DEBUG_UART_BASE   #
+                 ARCH                DEBUG_UART_PHYS   DEBUG_UART_VIRT   #
                  MSM7X00A, QSD8X50   0xa9a00000        0xe1000000        UART1
                  MSM7X00A, QSD8X50   0xa9b00000        0xe1000000        UART2
                  MSM7X00A, QSD8X50   0xa9c00000        0xe1000000        UART3
@@ -452,7 +460,8 @@ choice
                  Say Y here if you want the debug print routines to direct
                  their output to the serial port on Qualcomm devices.
 
-                 ARCH      DEBUG_UART_PHYS   DEBUG_UART_BASE
+                 ARCH      DEBUG_UART_PHYS   DEBUG_UART_VIRT
+                 APQ8064   0x16640000        0xf0040000
                  APQ8084   0xf995e000        0xfa75e000
                  MSM8X60   0x19c40000        0xf0040000
                  MSM8960   0x16440000        0xf0040000
@@ -461,13 +470,13 @@ choice
                  Please adjust DEBUG_UART_PHYS and DEBUG_UART_BASE configuration
                  options based on your needs.
 
-       config DEBUG_MVEBU_UART
-               bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)"
+       config DEBUG_MVEBU_UART0
+               bool "Kernel low-level debugging messages via MVEBU UART0 (old bootloaders)"
                depends on ARCH_MVEBU
                select DEBUG_UART_8250
                help
                  Say Y here if you want kernel low-level debugging support
-                 on MVEBU based platforms.
+                 on MVEBU based platforms on UART0.
 
                  This option should be used with the old bootloaders
                  that left the internal registers mapped at
@@ -480,13 +489,28 @@ choice
                  when u-boot hands over to the kernel, the system
                  silently crashes, with no serial output at all.
 
-       config DEBUG_MVEBU_UART_ALTERNATE
-               bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)"
+       config DEBUG_MVEBU_UART0_ALTERNATE
+               bool "Kernel low-level debugging messages via MVEBU UART0 (new bootloaders)"
                depends on ARCH_MVEBU
                select DEBUG_UART_8250
                help
                  Say Y here if you want kernel low-level debugging support
-                 on MVEBU based platforms.
+                 on MVEBU based platforms on UART0.
+
+                 This option should be used with the new bootloaders
+                 that remap the internal registers at 0xf1000000.
+
+                 If the wrong DEBUG_MVEBU_UART* option is selected,
+                 when u-boot hands over to the kernel, the system
+                 silently crashes, with no serial output at all.
+
+       config DEBUG_MVEBU_UART1_ALTERNATE
+               bool "Kernel low-level debugging messages via MVEBU UART1 (new bootloaders)"
+               depends on ARCH_MVEBU
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 on MVEBU based platforms on UART1.
 
                  This option should be used with the new bootloaders
                  that remap the internal registers at 0xf1000000.
@@ -922,16 +946,28 @@ choice
        config DEBUG_SIRFPRIMA2_UART1
                bool "Kernel low-level debugging messages via SiRFprimaII UART1"
                depends on ARCH_PRIMA2
+               select DEBUG_SIRFSOC_UART
                help
                  Say Y here if you want the debug print routines to direct
                  their output to the uart1 port on SiRFprimaII devices.
 
-       config DEBUG_SIRFMARCO_UART1
-               bool "Kernel low-level debugging messages via SiRFmarco UART1"
-               depends on ARCH_MARCO
+       config DEBUG_SIRFATLAS7_UART0
+               bool "Kernel low-level debugging messages via SiRFatlas7 UART0"
+               depends on ARCH_ATLAS7
+               select DEBUG_SIRFSOC_UART
                help
                  Say Y here if you want the debug print routines to direct
-                 their output to the uart1 port on SiRFmarco devices.
+                 their output to the uart0 port on SiRFATLAS7 devices.The uart0
+                 is used on SiRFATLAS7 as a extra debug port.sometimes an extra
+                 debug port can be very useful.
+
+       config DEBUG_SIRFATLAS7_UART1
+               bool "Kernel low-level debugging messages via SiRFatlas7 UART1"
+               depends on ARCH_ATLAS7
+               select DEBUG_SIRFSOC_UART
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to the uart1 port on SiRFATLAS7 devices.
 
        config STIH41X_DEBUG_ASC2
                bool "Use StiH415/416 ASC2 UART for low-level debug"
@@ -979,7 +1015,7 @@ choice
                  for Mediatek mt6589 based platforms on UART0.
 
        config DEBUG_MT8127_UART0
-               bool "Mediatek mt8127 UART0"
+               bool "Mediatek mt8127/mt6592 UART0"
                depends on ARCH_MEDIATEK
                select DEBUG_UART_8250
                help
@@ -1171,6 +1207,10 @@ config DEBUG_STI_UART
        bool
        depends on ARCH_STI
 
+config DEBUG_SIRFSOC_UART
+       bool
+       depends on ARCH_SIRF
+
 config DEBUG_LL_INCLUDE
        string
        default "debug/sa1100.S" if DEBUG_SA1100
@@ -1206,7 +1246,7 @@ config DEBUG_LL_INCLUDE
        default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA4
        default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART
        default "debug/s5pv210.S" if DEBUG_S5PV210_UART
-       default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
+       default "debug/sirf.S" if DEBUG_SIRFSOC_UART
        default "debug/sti.S" if DEBUG_STI_UART
        default "debug/tegra.S" if DEBUG_TEGRA_UART
        default "debug/ux500.S" if DEBUG_UX500_UART
@@ -1262,7 +1302,10 @@ config DEBUG_UART_PHYS
        default 0x11009000 if DEBUG_MT8135_UART3
        default 0x16000000 if ARCH_INTEGRATOR
        default 0x18000300 if DEBUG_BCM_5301X
+       default 0x18010000 if DEBUG_SIRFATLAS7_UART0
+       default 0x18020000 if DEBUG_SIRFATLAS7_UART1
        default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1
+       default 0x20001000 if DEBUG_HIP01_UART
        default 0x20060000 if DEBUG_RK29_UART0
        default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
        default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
@@ -1288,12 +1331,13 @@ config DEBUG_UART_PHYS
        default 0x808c0000 if ARCH_EP93XX
        default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
        default 0xa9a00000 if DEBUG_MSM_UART
+       default 0xb0060000 if DEBUG_SIRFPRIMA2_UART1
        default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX
        default 0xc0013000 if DEBUG_U300_UART
        default 0xc8000000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN
        default 0xc8000003 if ARCH_IXP4XX && CPU_BIG_ENDIAN
        default 0xd0000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
-       default 0xd0012000 if DEBUG_MVEBU_UART
+       default 0xd0012000 if DEBUG_MVEBU_UART0
        default 0xc81004c0 if DEBUG_MESON_UARTAO
        default 0xd4017000 if DEBUG_MMP_UART2
        default 0xd4018000 if DEBUG_MMP_UART3
@@ -1307,7 +1351,8 @@ config DEBUG_UART_PHYS
        default 0xe8008000 if DEBUG_R7S72100_SCIF2
        default 0xf0000be0 if ARCH_EBSA110
        default 0xf040ab00 if DEBUG_BRCMSTB_UART
-       default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
+       default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE
+       default 0xf1012100 if DEBUG_MVEBU_UART1_ALTERNATE
        default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \
                                ARCH_ORION5X
        default 0xf7fc9000 if DEBUG_BERLIN_UART
@@ -1331,7 +1376,8 @@ config DEBUG_UART_PHYS
                DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
                DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
                DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
-               DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
+               DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
+               DEBUG_SIRFSOC_UART
 
 config DEBUG_UART_VIRT
        hex "Virtual base address of debug UART"
@@ -1388,8 +1434,12 @@ config DEBUG_UART_VIRT
        default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
        default 0xfeb31000 if DEBUG_KEYSTONE_UART1
        default 0xfec02000 if DEBUG_SOCFPGA_UART
-       default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
+       default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE
+       default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE
+       default 0xfec10000 if DEBUG_SIRFATLAS7_UART0
        default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
+       default 0xfec20000 if DEBUG_SIRFATLAS7_UART1
+       default 0xfec60000 if DEBUG_SIRFPRIMA2_UART1
        default 0xfec90000 if DEBUG_RK32_UART2
        default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1
        default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2
@@ -1405,11 +1455,12 @@ config DEBUG_UART_VIRT
        default 0xfef36000 if DEBUG_HIGHBANK_UART
        default 0xfefff700 if ARCH_IOP33X
        default 0xff003000 if DEBUG_U300_UART
+       default 0xffd01000 if DEBUG_HIP01_UART
        default DEBUG_UART_PHYS if !MMU
        depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
                DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
                DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
-               DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
+               DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || DEBUG_SIRFSOC_UART
 
 config DEBUG_UART_8250_SHIFT
        int "Register offset shift for the 8250 debug UART"
index 4eb540b..dbfaba0 100644 (file)
                nvidia,core-pwr-off-time = <61036>;
                nvidia,core-power-req-active-high;
                nvidia,sys-clock-req-active-high;
+
+               i2c-thermtrip {
+                       nvidia,i2c-controller-id = <4>;
+                       nvidia,bus-addr = <0x40>;
+                       nvidia,reg-addr = <0x36>;
+                       nvidia,reg-data = <0x2>;
+               };
        };
 
        /* Serial ATA */
index 9ef5761..e55a942 100644 (file)
@@ -23,6 +23,7 @@
        .endm
 
        .macro  senduart, rd, rx
+ARM_BE8(rev    \rd, \rd )
 #ifdef CONFIG_DEBUG_QCOM_UARTDM
        @ Write the 1 character to UARTDM_TF
        str     \rd, [\rx, #0x70]
 #ifdef CONFIG_DEBUG_QCOM_UARTDM
        @ check for TX_EMT in UARTDM_SR
        ldr     \rd, [\rx, #0x08]
+ARM_BE8(rev     \rd, \rd )
        tst     \rd, #0x08
        bne     1002f
        @ wait for TXREADY in UARTDM_ISR
 1001:  ldr     \rd, [\rx, #0x14]
+ARM_BE8(rev     \rd, \rd )
        tst     \rd, #0x80
        beq     1001b
 1002:
        @ Clear TX_READY by writing to the UARTDM_CR register
        mov     \rd, #0x300
+ARM_BE8(rev     \rd, \rd )
        str     \rd, [\rx, #0x10]
        @ Write 0x1 to NCF register
        mov     \rd, #0x1
+ARM_BE8(rev     \rd, \rd )
        str     \rd, [\rx, #0x40]
        @ UARTDM reg. Read to induce delay
        ldr     \rd, [\rx, #0x08]
 #else
        @ wait for TX_READY
 1001:  ldr     \rd, [\rx, #0x08]
+ARM_BE8(rev     \rd, \rd )
        tst     \rd, #0x04
        beq     1001b
 #endif
index dbf250c..630f231 100644 (file)
@@ -6,37 +6,33 @@
  * Licensed under GPLv2 or later.
  */
 
-#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
-#define SIRFSOC_UART1_PA_BASE          0xb0060000
-#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
-#define SIRFSOC_UART1_PA_BASE          0xcc060000
-#else
-#define SIRFSOC_UART1_PA_BASE          0
-#endif
+#define SIRF_LLUART_TXFIFO_STATUS      0x0114
+#define SIRF_LLUART_TXFIFO_DATA        0x0118
 
-#define SIRFSOC_UART1_VA_BASE          0xFEC60000
+#define SIRF_LLUART_TXFIFO_FULL                       (1 << 5)
 
-#define SIRFSOC_UART_TXFIFO_STATUS     0x0114
-#define SIRFSOC_UART_TXFIFO_DATA       0x0118
+#ifdef CONFIG_DEBUG_SIRFATLAS7_UART0
+#define SIRF_LLUART_TXFIFO_EMPTY                       (1 << 8)
+#else
+#define SIRF_LLUART_TXFIFO_EMPTY                       (1 << 6)
+#endif
 
-#define SIRFSOC_UART1_TXFIFO_FULL                       (1 << 5)
-#define SIRFSOC_UART1_TXFIFO_EMPTY                     (1 << 6)
 
        .macro  addruart, rp, rv, tmp
-       ldr     \rp, =SIRFSOC_UART1_PA_BASE             @ physical
-       ldr     \rv, =SIRFSOC_UART1_VA_BASE             @ virtual
+       ldr     \rp, =CONFIG_DEBUG_UART_PHYS            @ physical
+       ldr     \rv, =CONFIG_DEBUG_UART_VIRT            @ virtual
        .endm
 
        .macro  senduart,rd,rx
-       str     \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
+       str     \rd, [\rx, #SIRF_LLUART_TXFIFO_DATA]
        .endm
 
        .macro  busyuart,rd,rx
        .endm
 
        .macro  waituart,rd,rx
-1001:  ldr     \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
-       tst     \rd, #SIRFSOC_UART1_TXFIFO_EMPTY
+1001:  ldr     \rd, [\rx, #SIRF_LLUART_TXFIFO_STATUS]
+       tst     \rd, #SIRF_LLUART_TXFIFO_EMPTY
        beq     1001b
        .endm
 
index 31c87a2..e209e6f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/jiffies.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/printk.h>
@@ -94,10 +95,35 @@ static u32 pwr_ctrl_rd(u32 cpu)
        return readl_relaxed(base);
 }
 
-static void pwr_ctrl_wr(u32 cpu, u32 val)
+static void pwr_ctrl_set(unsigned int cpu, u32 val, u32 mask)
 {
        void __iomem *base = pwr_ctrl_get_base(cpu);
-       writel(val, base);
+       writel((readl(base) & mask) | val, base);
+}
+
+static void pwr_ctrl_clr(unsigned int cpu, u32 val, u32 mask)
+{
+       void __iomem *base = pwr_ctrl_get_base(cpu);
+       writel((readl(base) & mask) & ~val, base);
+}
+
+#define POLL_TMOUT_MS 500
+static int pwr_ctrl_wait_tmout(unsigned int cpu, u32 set, u32 mask)
+{
+       const unsigned long timeo = jiffies + msecs_to_jiffies(POLL_TMOUT_MS);
+       u32 tmp;
+
+       do {
+               tmp = pwr_ctrl_rd(cpu) & mask;
+               if (!set == !tmp)
+                       return 0;
+       } while (time_before(jiffies, timeo));
+
+       tmp = pwr_ctrl_rd(cpu) & mask;
+       if (!set == !tmp)
+               return 0;
+
+       return -ETIMEDOUT;
 }
 
 static void cpu_rst_cfg_set(u32 cpu, int set)
@@ -139,15 +165,22 @@ static void brcmstb_cpu_power_on(u32 cpu)
         * The secondary cores power was cut, so we must go through
         * power-on initialization.
         */
-       u32 tmp;
+       pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, 0xffffff00);
+       pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1);
+       pwr_ctrl_set(cpu, ZONE_RESERVED_1_MASK, -1);
 
-       /* Request zone power up */
-       pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
+       pwr_ctrl_set(cpu, ZONE_MAN_MEM_PWR_MASK, -1);
 
-       /* Wait for the power up FSM to complete */
-       do {
-               tmp = pwr_ctrl_rd(cpu);
-       } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
+       if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_MEM_PWR_STATE_MASK))
+               panic("ZONE_MEM_PWR_STATE_MASK set timeout");
+
+       pwr_ctrl_set(cpu, ZONE_MAN_CLKEN_MASK, -1);
+
+       if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_DPG_PWR_STATE_MASK))
+               panic("ZONE_DPG_PWR_STATE_MASK set timeout");
+
+       pwr_ctrl_clr(cpu, ZONE_MAN_ISO_CNTL_MASK, -1);
+       pwr_ctrl_set(cpu, ZONE_MAN_RESET_CNTL_MASK, -1);
 }
 
 static int brcmstb_cpu_get_power_state(u32 cpu)
@@ -174,25 +207,33 @@ static void brcmstb_cpu_die(u32 cpu)
 
 static int brcmstb_cpu_kill(u32 cpu)
 {
-       u32 tmp;
+       /*
+        * Ordinarily, the hardware forbids power-down of CPU0 (which is good
+        * because it is the boot CPU), but this is not true when using BPCM
+        * manual mode.  Consequently, we must avoid turning off CPU0 here to
+        * ensure that TI2C master reset will work.
+        */
+       if (cpu == 0) {
+               pr_warn("SMP: refusing to power off CPU0\n");
+               return 1;
+       }
 
        while (per_cpu_sw_state_rd(cpu))
                ;
 
-       /* Program zone reset */
-       pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
-                             ZONE_PWR_DN_REQ_MASK);
+       pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1);
+       pwr_ctrl_clr(cpu, ZONE_MAN_RESET_CNTL_MASK, -1);
+       pwr_ctrl_clr(cpu, ZONE_MAN_CLKEN_MASK, -1);
+       pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, -1);
+       pwr_ctrl_clr(cpu, ZONE_MAN_MEM_PWR_MASK, -1);
 
-       /* Verify zone reset */
-       tmp = pwr_ctrl_rd(cpu);
-       if (!(tmp & ZONE_RESET_STATE_MASK))
-               pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
-                       __func__, cpu);
+       if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_MEM_PWR_STATE_MASK))
+               panic("ZONE_MEM_PWR_STATE_MASK clear timeout");
 
-       /* Wait for power down */
-       do {
-               tmp = pwr_ctrl_rd(cpu);
-       } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
+       pwr_ctrl_clr(cpu, ZONE_RESERVED_1_MASK, -1);
+
+       if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_DPG_PWR_STATE_MASK))
+               panic("ZONE_DPG_PWR_STATE_MASK clear timeout");
 
        /* Flush pipeline before resetting CPU */
        mb();
index cd19433..83061ad 100644 (file)
@@ -22,6 +22,14 @@ config ARCH_HI3xxx
        help
          Support for Hisilicon Hi36xx SoC family
 
+config ARCH_HIP01
+       bool "Hisilicon HIP01 family" if ARCH_MULTI_V7
+       select HAVE_ARM_SCU if SMP
+       select HAVE_ARM_TWD if SMP
+       select ARM_GLOBAL_TIMER
+       help
+         Support for Hisilicon HIP01 SoC family
+
 config ARCH_HIP04
        bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7
        select ARM_ERRATA_798181 if SMP
index 88b1f48..92a682d 100644 (file)
@@ -12,9 +12,12 @@ extern void hi3xxx_cpu_die(unsigned int cpu);
 extern int hi3xxx_cpu_kill(unsigned int cpu);
 extern void hi3xxx_set_cpu(int cpu, bool enable);
 
-extern void hix5hd2_secondary_startup(void);
+extern void hisi_secondary_startup(void);
 extern struct smp_operations hix5hd2_smp_ops;
 extern void hix5hd2_set_cpu(int cpu, bool enable);
 extern void hix5hd2_cpu_die(unsigned int cpu);
 
+extern struct smp_operations hip01_smp_ops;
+extern void hip01_set_cpu(int cpu, bool enable);
+extern void hip01_cpu_die(unsigned int cpu);
 #endif
index 278889c..81e35b1 100644 (file)
@@ -11,6 +11,6 @@
 
        __CPUINIT
 
-ENTRY(hix5hd2_secondary_startup)
+ENTRY(hisi_secondary_startup)
        bl      v7_invalidate_l1
        b       secondary_startup
index 7744c35..76b9070 100644 (file)
@@ -72,3 +72,13 @@ static const char *hip04_compat[] __initconst = {
 DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)")
        .dt_compat      = hip04_compat,
 MACHINE_END
+
+static const char *hip01_compat[] __initconst = {
+       "hisilicon,hip01",
+       "hisilicon,hip01-ca9x2",
+       NULL,
+};
+
+DT_MACHINE_START(HIP01, "Hisilicon HIP01 (Flattened Device Tree)")
+       .dt_compat      = hip01_compat,
+MACHINE_END
index 84e6919..a129aae 100644 (file)
@@ -65,6 +65,9 @@
 #define PMC0_CPU1_PMC_ENABLE           (1 << 7)
 #define PMC0_CPU1_POWERDOWN            (1 << 3)
 
+#define HIP01_PERI9                    0x50
+#define PERI9_CPU1_RESET               (1 << 1)
+
 enum {
        HI3620_CTRL,
        ERROR_CTRL,
@@ -209,6 +212,34 @@ void hix5hd2_set_cpu(int cpu, bool enable)
        }
 }
 
+void hip01_set_cpu(int cpu, bool enable)
+{
+       unsigned int temp;
+       struct device_node *np;
+
+       if (!ctrl_base) {
+               np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
+               if (np)
+                       ctrl_base = of_iomap(np, 0);
+               else
+                       BUG();
+       }
+
+       if (enable) {
+               /* reset on CPU1  */
+               temp = readl_relaxed(ctrl_base + HIP01_PERI9);
+               temp |= PERI9_CPU1_RESET;
+               writel_relaxed(temp, ctrl_base + HIP01_PERI9);
+
+               udelay(50);
+
+               /* unreset on CPU1 */
+               temp = readl_relaxed(ctrl_base + HIP01_PERI9);
+               temp &= ~PERI9_CPU1_RESET;
+               writel_relaxed(temp, ctrl_base + HIP01_PERI9);
+       }
+}
+
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
index 575dd82..8880c8e 100644 (file)
 #include <linux/smp.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
+#include <linux/delay.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
+#include <asm/mach/map.h>
 
 #include "core.h"
 
@@ -96,7 +98,7 @@ struct smp_operations hi3xxx_smp_ops __initdata = {
 #endif
 };
 
-static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus)
+static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus)
 {
        hisi_enable_scu_a9();
 }
@@ -116,7 +118,7 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        phys_addr_t jumpaddr;
 
-       jumpaddr = virt_to_phys(hix5hd2_secondary_startup);
+       jumpaddr = virt_to_phys(hisi_secondary_startup);
        hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
        hix5hd2_set_cpu(cpu, true);
        arch_send_wakeup_ipi_mask(cpumask_of(cpu));
@@ -125,12 +127,60 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 
 struct smp_operations hix5hd2_smp_ops __initdata = {
-       .smp_prepare_cpus       = hix5hd2_smp_prepare_cpus,
+       .smp_prepare_cpus       = hisi_common_smp_prepare_cpus,
        .smp_boot_secondary     = hix5hd2_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_die                = hix5hd2_cpu_die,
 #endif
 };
 
+
+#define SC_SCTL_REMAP_CLR      0x00000100
+#define HIP01_BOOT_ADDRESS     0x80000000
+#define REG_SC_CTRL            0x000
+
+void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
+{
+       void __iomem *virt;
+
+       virt = phys_to_virt(start_addr);
+
+       writel_relaxed(0xe51ff004, virt);
+       writel_relaxed(jump_addr, virt + 4);
+}
+
+static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       phys_addr_t jumpaddr;
+       unsigned int remap_reg_value = 0;
+       struct device_node *node;
+
+
+       jumpaddr = virt_to_phys(hisi_secondary_startup);
+       hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr);
+
+       node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
+       if (WARN_ON(!node))
+               return -1;
+       ctrl_base = of_iomap(node, 0);
+
+       /* set the secondary core boot from DDR */
+       remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL);
+       barrier();
+       remap_reg_value |= SC_SCTL_REMAP_CLR;
+       barrier();
+       writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL);
+
+       hip01_set_cpu(cpu, true);
+
+       return 0;
+}
+
+struct smp_operations hip01_smp_ops __initdata = {
+       .smp_prepare_cpus       = hisi_common_smp_prepare_cpus,
+       .smp_boot_secondary     = hip01_boot_secondary,
+};
+
 CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
 CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
+CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops);
index f5ac685..8d1b101 100644 (file)
@@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
 obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
-# i.MX6SX reuses i.MX6Q cpuidle driver
-obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o
+obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
 endif
 
 ifdef CONFIG_SND_IMX_SOC
index 5a75cdc..8935bff 100644 (file)
@@ -96,15 +96,30 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)
 {
        struct clk_gate2 *gate = to_clk_gate2(hw);
 
-       if (gate->share_count)
-               return !!__clk_get_enable_count(hw->clk);
-       else
-               return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
+       return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
+}
+
+static void clk_gate2_disable_unused(struct clk_hw *hw)
+{
+       struct clk_gate2 *gate = to_clk_gate2(hw);
+       unsigned long flags = 0;
+       u32 reg;
+
+       spin_lock_irqsave(gate->lock, flags);
+
+       if (!gate->share_count || *gate->share_count == 0) {
+               reg = readl(gate->reg);
+               reg &= ~(3 << gate->bit_idx);
+               writel(reg, gate->reg);
+       }
+
+       spin_unlock_irqrestore(gate->lock, flags);
 }
 
 static struct clk_ops clk_gate2_ops = {
        .enable = clk_gate2_enable,
        .disable = clk_gate2_disable,
+       .disable_unused = clk_gate2_disable_unused,
        .is_enabled = clk_gate2_is_enabled,
 };
 
index 5951660..108b80b 100644 (file)
@@ -386,7 +386,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5",        "ecspi_root",        base + 0x6c, 8);
        clk[IMX6QDL_CLK_ENET]         = imx_clk_gate2("enet",          "ipg",               base + 0x6c, 10);
        clk[IMX6QDL_CLK_ESAI_EXTAL]   = imx_clk_gate2_shared("esai_extal",   "esai_podf",   base + 0x6c, 16, &share_count_esai);
-       clk[IMX6QDL_CLK_ESAI_IPG]     = imx_clk_gate2_shared("esai_ipg",   "ipg",           base + 0x6c, 16, &share_count_esai);
+       clk[IMX6QDL_CLK_ESAI_IPG]     = imx_clk_gate2_shared("esai_ipg",   "ahb",           base + 0x6c, 16, &share_count_esai);
        clk[IMX6QDL_CLK_ESAI_MEM]     = imx_clk_gate2_shared("esai_mem", "ahb",             base + 0x6c, 16, &share_count_esai);
        clk[IMX6QDL_CLK_GPT_IPG]      = imx_clk_gate2("gpt_ipg",       "ipg",               base + 0x6c, 20);
        clk[IMX6QDL_CLK_GPT_IPG_PER]  = imx_clk_gate2("gpt_ipg_per",   "ipg_per",           base + 0x6c, 22);
index 0ad6e54..641ebc5 100644 (file)
@@ -31,6 +31,7 @@
  * @base:       base address of PLL registers
  * @powerup_set: set POWER bit to power up the PLL
  * @div_mask:   mask of divider bits
+ * @div_shift:  shift of divider bits
  *
  * IMX PLL clock version 3, found on i.MX6 series.  Divider for pllv3
  * is actually a multiplier, and always sits at bit 0.
@@ -40,6 +41,7 @@ struct clk_pllv3 {
        void __iomem    *base;
        bool            powerup_set;
        u32             div_mask;
+       u32             div_shift;
 };
 
 #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
@@ -97,7 +99,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
                                           unsigned long parent_rate)
 {
        struct clk_pllv3 *pll = to_clk_pllv3(hw);
-       u32 div = readl_relaxed(pll->base)  & pll->div_mask;
+       u32 div = (readl_relaxed(pll->base) >> pll->div_shift)  & pll->div_mask;
 
        return (div == 1) ? parent_rate * 22 : parent_rate * 20;
 }
@@ -125,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
                return -EINVAL;
 
        val = readl_relaxed(pll->base);
-       val &= ~pll->div_mask;
-       val |= div;
+       val &= ~(pll->div_mask << pll->div_shift);
+       val |= (div << pll->div_shift);
        writel_relaxed(val, pll->base);
 
        return clk_pllv3_wait_lock(pll);
@@ -295,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
        case IMX_PLLV3_SYS:
                ops = &clk_pllv3_sys_ops;
                break;
+       case IMX_PLLV3_USB_VF610:
+               pll->div_shift = 1;
        case IMX_PLLV3_USB:
                ops = &clk_pllv3_ops;
                pll->powerup_set = true;
index 5937dde..61876ed 100644 (file)
@@ -172,11 +172,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
 
        clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
        clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
-       clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1);
+       clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610,     "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
        clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
        clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
        clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f);
-       clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1);
+       clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610,     "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2);
 
        clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
        clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
@@ -267,6 +267,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8));
        clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9));
        clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10));
+       clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9));
+       clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10));
 
        clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6));
        clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7));
@@ -380,6 +382,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
        clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
 
+       clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
+
        imx_check_clocks(clk, ARRAY_SIZE(clk));
 
        clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]);
index 5ef82e2..6a07903 100644 (file)
@@ -20,6 +20,7 @@ enum imx_pllv3_type {
        IMX_PLLV3_GENERIC,
        IMX_PLLV3_SYS,
        IMX_PLLV3_USB,
+       IMX_PLLV3_USB_VF610,
        IMX_PLLV3_AV,
        IMX_PLLV3_ENET,
 };
index cfcdb62..1028b6c 100644 (file)
@@ -70,6 +70,10 @@ void imx_set_soc_revision(unsigned int rev);
 unsigned int imx_get_soc_revision(void);
 void imx_init_revision_from_anatop(void);
 struct device *imx_soc_device_init(void);
+void imx6_enable_rbc(bool enable);
+void imx_gpc_set_arm_power_in_lpm(bool power_off);
+void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
+void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
 
 enum mxc_cpu_pwr_mode {
        WAIT_CLOCKED,           /* wfi only */
diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c
new file mode 100644 (file)
index 0000000..5a36722
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * 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/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/module.h>
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+
+#include "common.h"
+#include "cpuidle.h"
+
+static int imx6sx_idle_finish(unsigned long val)
+{
+       cpu_do_idle();
+
+       return 0;
+}
+
+static int imx6sx_enter_wait(struct cpuidle_device *dev,
+                           struct cpuidle_driver *drv, int index)
+{
+       imx6q_set_lpm(WAIT_UNCLOCKED);
+
+       switch (index) {
+       case 1:
+               cpu_do_idle();
+               break;
+       case 2:
+               imx6_enable_rbc(true);
+               imx_gpc_set_arm_power_in_lpm(true);
+               imx_set_cpu_jump(0, v7_cpu_resume);
+               /* Need to notify there is a cpu pm operation. */
+               cpu_pm_enter();
+               cpu_cluster_pm_enter();
+
+               cpu_suspend(0, imx6sx_idle_finish);
+
+               cpu_cluster_pm_exit();
+               cpu_pm_exit();
+               imx_gpc_set_arm_power_in_lpm(false);
+               imx6_enable_rbc(false);
+               break;
+       default:
+               break;
+       }
+
+       imx6q_set_lpm(WAIT_CLOCKED);
+
+       return index;
+}
+
+static struct cpuidle_driver imx6sx_cpuidle_driver = {
+       .name = "imx6sx_cpuidle",
+       .owner = THIS_MODULE,
+       .states = {
+               /* WFI */
+               ARM_CPUIDLE_WFI_STATE,
+               /* WAIT */
+               {
+                       .exit_latency = 50,
+                       .target_residency = 75,
+                       .flags = CPUIDLE_FLAG_TIMER_STOP,
+                       .enter = imx6sx_enter_wait,
+                       .name = "WAIT",
+                       .desc = "Clock off",
+               },
+               /* WAIT + ARM power off  */
+               {
+                       /*
+                        * ARM gating 31us * 5 + RBC clear 65us
+                        * and some margin for SW execution, here set it
+                        * to 300us.
+                        */
+                       .exit_latency = 300,
+                       .target_residency = 500,
+                       .enter = imx6sx_enter_wait,
+                       .name = "LOW-POWER-IDLE",
+                       .desc = "ARM power off",
+               },
+       },
+       .state_count = 3,
+       .safe_state_index = 0,
+};
+
+int __init imx6sx_cpuidle_init(void)
+{
+       imx6_enable_rbc(false);
+       /*
+        * set ARM power up/down timing to the fastest,
+        * sw2iso and sw can be set to one 32K cycle = 31us
+        * except for power up sw2iso which need to be
+        * larger than LDO ramp up time.
+        */
+       imx_gpc_set_arm_power_up_timing(2, 1);
+       imx_gpc_set_arm_power_down_timing(1, 1);
+
+       return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
+}
index 24e3367..f914012 100644 (file)
@@ -14,6 +14,7 @@
 extern int imx5_cpuidle_init(void);
 extern int imx6q_cpuidle_init(void);
 extern int imx6sl_cpuidle_init(void);
+extern int imx6sx_cpuidle_init(void);
 #else
 static inline int imx5_cpuidle_init(void)
 {
@@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void)
 {
        return 0;
 }
+static inline int imx6sx_cpuidle_init(void)
+{
+       return 0;
+}
 #endif
index 5f3602e..745caa1 100644 (file)
 
 #define GPC_IMR1               0x008
 #define GPC_PGC_CPU_PDN                0x2a0
+#define GPC_PGC_CPU_PUPSCR     0x2a4
+#define GPC_PGC_CPU_PDNSCR     0x2a8
+#define GPC_PGC_SW2ISO_SHIFT   0x8
+#define GPC_PGC_SW_SHIFT       0x0
 
 #define IMR_NUM                        4
 
@@ -27,6 +31,23 @@ static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
 static u32 gpc_saved_imrs[IMR_NUM];
 
+void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw)
+{
+       writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
+               (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR);
+}
+
+void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw)
+{
+       writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
+               (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR);
+}
+
+void imx_gpc_set_arm_power_in_lpm(bool power_off)
+{
+       writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN);
+}
+
 void imx_gpc_pre_suspend(bool arm_power_off)
 {
        void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
@@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off)
 
        /* Tell GPC to power off ARM core when suspend */
        if (arm_power_off)
-               writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+               imx_gpc_set_arm_power_in_lpm(arm_power_off);
 
        for (i = 0; i < IMR_NUM; i++) {
                gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
@@ -48,7 +69,7 @@ void imx_gpc_post_resume(void)
        int i;
 
        /* Keep ARM core powered on for other low-power modes */
-       writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+       imx_gpc_set_arm_power_in_lpm(false);
 
        for (i = 0; i < IMR_NUM; i++)
                writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
index 5057d61..4ad6e47 100644 (file)
@@ -329,7 +329,7 @@ static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
                        if (dev_pm_opp_disable(cpu_dev, 852000000))
                                pr_warn("failed to disable 852 MHz OPP\n");
        }
-
+       iounmap(base);
 put_node:
        of_node_put(np);
 }
index 7a96c65..66988eb 100644 (file)
@@ -90,7 +90,7 @@ static void __init imx6sx_init_irq(void)
 
 static void __init imx6sx_init_late(void)
 {
-       imx6q_cpuidle_init();
+       imx6sx_cpuidle_init();
 
        if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
                platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
index c11ab6a..2e7c75b 100644 (file)
 #include <asm/hardware/cache-l2x0.h>
 
 static const char * const vf610_dt_compat[] __initconst = {
+       "fsl,vf500",
+       "fsl,vf510",
+       "fsl,vf600",
        "fsl,vf610",
        NULL,
 };
 
-DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)")
+DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF5xx/VF6xx (Device Tree)")
        .l2c_aux_val    = 0,
        .l2c_aux_mask   = ~0,
        .dt_compat      = vf610_dt_compat,
index 5d2c1bd..46fd695 100644 (file)
@@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable)
        writel_relaxed(val, ccm_base + CGPR);
 }
 
-static void imx6q_enable_rbc(bool enable)
+void imx6_enable_rbc(bool enable)
 {
        u32 val;
 
@@ -359,17 +359,16 @@ static int imx6q_pm_enter(suspend_state_t state)
                 * RBC setting, so we do NOT need to do that here.
                 */
                if (!imx6_suspend_in_ocram_fn)
-                       imx6q_enable_rbc(true);
+                       imx6_enable_rbc(true);
                imx_gpc_pre_suspend(true);
                imx_anatop_pre_suspend();
-               imx_set_cpu_jump(0, v7_cpu_resume);
                /* Zzz ... */
                cpu_suspend(0, imx6q_suspend_finish);
                if (cpu_is_imx6q() || cpu_is_imx6dl())
                        imx_smp_prepare();
                imx_anatop_post_resume();
                imx_gpc_post_resume();
-               imx6q_enable_rbc(false);
+               imx6_enable_rbc(false);
                imx6q_enable_wb(false);
                imx6q_set_int_mem_clk_lpm(true);
                imx6q_set_lpm(WAIT_CLOCKED);
index f73f588..f7e463c 100644 (file)
@@ -1,6 +1,26 @@
-config ARCH_MEDIATEK
+menuconfig ARCH_MEDIATEK
        bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
        select ARM_GIC
        select MTK_TIMER
        help
          Support for Mediatek MT65xx & MT81xx SoCs
+
+if ARCH_MEDIATEK
+
+config MACH_MT6589
+       bool "MediaTek MT6589 SoCs support"
+       default ARCH_MEDIATEK
+
+config MACH_MT6592
+       bool "MediaTek MT6592 SoCs support"
+       default ARCH_MEDIATEK
+
+config MACH_MT8127
+       bool "MediaTek MT8127 SoCs support"
+       default ARCH_MEDIATEK
+
+config MACH_MT8135
+       bool "MediaTek MT8135 SoCs support"
+       default ARCH_MEDIATEK
+
+endif
index 3585cb3..440799b 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
 #include <asm/mach/map.h>
+#include <asm/dma-mapping.h>
 #include "coherency.h"
 #include "mvebu-soc-id.h"
 
@@ -76,54 +77,6 @@ int set_cpu_coherent(void)
        return ll_enable_coherency();
 }
 
-static inline void mvebu_hwcc_sync_io_barrier(void)
-{
-       writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
-       while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
-}
-
-static dma_addr_t mvebu_hwcc_dma_map_page(struct device *dev, struct page *page,
-                                 unsigned long offset, size_t size,
-                                 enum dma_data_direction dir,
-                                 struct dma_attrs *attrs)
-{
-       if (dir != DMA_TO_DEVICE)
-               mvebu_hwcc_sync_io_barrier();
-       return pfn_to_dma(dev, page_to_pfn(page)) + offset;
-}
-
-
-static void mvebu_hwcc_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
-                             size_t size, enum dma_data_direction dir,
-                             struct dma_attrs *attrs)
-{
-       if (dir != DMA_TO_DEVICE)
-               mvebu_hwcc_sync_io_barrier();
-}
-
-static void mvebu_hwcc_dma_sync(struct device *dev, dma_addr_t dma_handle,
-                       size_t size, enum dma_data_direction dir)
-{
-       if (dir != DMA_TO_DEVICE)
-               mvebu_hwcc_sync_io_barrier();
-}
-
-static struct dma_map_ops mvebu_hwcc_dma_ops = {
-       .alloc                  = arm_dma_alloc,
-       .free                   = arm_dma_free,
-       .mmap                   = arm_dma_mmap,
-       .map_page               = mvebu_hwcc_dma_map_page,
-       .unmap_page             = mvebu_hwcc_dma_unmap_page,
-       .get_sgtable            = arm_dma_get_sgtable,
-       .map_sg                 = arm_dma_map_sg,
-       .unmap_sg               = arm_dma_unmap_sg,
-       .sync_single_for_cpu    = mvebu_hwcc_dma_sync,
-       .sync_single_for_device = mvebu_hwcc_dma_sync,
-       .sync_sg_for_cpu        = arm_dma_sync_sg_for_cpu,
-       .sync_sg_for_device     = arm_dma_sync_sg_for_device,
-       .set_dma_mask           = arm_dma_set_mask,
-};
-
 static int mvebu_hwcc_notifier(struct notifier_block *nb,
                               unsigned long event, void *__dev)
 {
@@ -131,7 +84,7 @@ static int mvebu_hwcc_notifier(struct notifier_block *nb,
 
        if (event != BUS_NOTIFY_ADD_DEVICE)
                return NOTIFY_DONE;
-       set_dma_ops(dev, &mvebu_hwcc_dma_ops);
+       set_dma_ops(dev, &arm_coherent_dma_ops);
 
        return NOTIFY_OK;
 }
index c16bb68..e124a0b 100644 (file)
 #define MV78XX0_A0_REV     0x1
 #define MV78XX0_B0_REV     0x2
 
+/* Amada 370 ID */
+#define ARMADA_370_DEV_ID   0x6710
+
+/* Amada 370 Revision */
+#define ARMADA_370_A1_REV   0x1
+
+/* Armada 375 ID */
+#define ARMADA_375_DEV_ID   0x6720
+
 /* Armada 375 */
 #define ARMADA_375_Z1_REV   0x0
 #define ARMADA_375_A0_REV   0x3
 
+/* Armada 38x ID */
+#define ARMADA_380_DEV_ID   0x6810
+#define ARMADA_385_DEV_ID   0x6820
+#define ARMADA_388_DEV_ID   0x6828
+
+/* Armada 38x Revision */
+#define ARMADA_38x_Z1_REV   0x0
+#define ARMADA_38x_A0_REV   0x4
+
 #ifdef CONFIG_ARCH_MVEBU
 int mvebu_get_soc_id(u32 *dev, u32 *rev);
 #else
index 042f693..a219dc3 100644 (file)
@@ -11,7 +11,7 @@ menuconfig ARCH_SIRF
 
 if ARCH_SIRF
 
-comment "CSR SiRF atlas6/primaII/Marco/Polo Specific Features"
+comment "CSR SiRF atlas6/primaII/Atlas7 Specific Features"
 
 config ARCH_ATLAS6
        bool "CSR SiRFSoC ATLAS6 ARM Cortex A9 Platform"
@@ -20,6 +20,17 @@ config ARCH_ATLAS6
        help
           Support for CSR SiRFSoC ARM Cortex A9 Platform
 
+config ARCH_ATLAS7
+       bool "CSR SiRFSoC ATLAS7 ARM Cortex A7 Platform"
+       default y
+       select ARM_GIC
+       select CPU_V7
+       select HAVE_ARM_SCU if SMP
+       select HAVE_SMP
+       select SMP_ON_UP if SMP
+       help
+          Support for CSR SiRFSoC ARM Cortex A7 Platform
+
 config ARCH_PRIMA2
        bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
        default y
@@ -28,15 +39,6 @@ config ARCH_PRIMA2
        help
           Support for CSR SiRFSoC ARM Cortex A9 Platform
 
-config ARCH_MARCO
-       bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform"
-       default y
-       select ARM_GIC
-       select HAVE_ARM_SCU if SMP
-       select SMP_ON_UP if SMP
-       help
-          Support for CSR SiRFSoC ARM Cortex A9 Platform
-
 config SIRF_IRQ
        bool
 
index 8846e7d..d7d02b0 100644 (file)
@@ -1,7 +1,6 @@
 obj-y += rstc.o
 obj-y += common.o
 obj-y += rtciobrg.o
-obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_SUSPEND) += pm.o sleep.o
 obj-$(CONFIG_SMP) += platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)  += hotplug.o
index a860ea2..0c819bb 100644 (file)
@@ -20,12 +20,6 @@ static void __init sirfsoc_init_late(void)
        sirfsoc_pm_init();
 }
 
-static __init void sirfsoc_map_io(void)
-{
-       sirfsoc_map_lluart();
-       sirfsoc_map_scu();
-}
-
 #ifdef CONFIG_ARCH_ATLAS6
 static const char *atlas6_dt_match[] __initconst = {
        "sirf,atlas6",
@@ -36,7 +30,6 @@ DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
        .l2c_aux_val    = 0,
        .l2c_aux_mask   = ~0,
-       .map_io         = sirfsoc_map_io,
        .init_late      = sirfsoc_init_late,
        .dt_compat      = atlas6_dt_match,
 MACHINE_END
@@ -52,26 +45,21 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
        .l2c_aux_val    = 0,
        .l2c_aux_mask   = ~0,
-       .map_io         = sirfsoc_map_io,
        .dma_zone_size  = SZ_256M,
        .init_late      = sirfsoc_init_late,
        .dt_compat      = prima2_dt_match,
 MACHINE_END
 #endif
 
-#ifdef CONFIG_ARCH_MARCO
-static const char *marco_dt_match[] __initconst = {
-       "sirf,marco",
+#ifdef CONFIG_ARCH_ATLAS7
+static const char *atlas7_dt_match[] __initdata = {
+       "sirf,atlas7",
        NULL
 };
 
-DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
+DT_MACHINE_START(ATLAS7_DT, "Generic ATLAS7 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
-       .l2c_aux_val    = 0,
-       .l2c_aux_mask   = ~0,
        .smp            = smp_ops(sirfsoc_smp_ops),
-       .map_io         = sirfsoc_map_io,
-       .init_late      = sirfsoc_init_late,
-       .dt_compat      = marco_dt_match,
+       .dt_compat      = atlas7_dt_match,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-prima2/lluart.c b/arch/arm/mach-prima2/lluart.c
deleted file mode 100644 (file)
index 99c0c92..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Static memory mapping for DEBUG_LL
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/kernel.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include "common.h"
-
-#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
-#define SIRFSOC_UART1_PA_BASE          0xb0060000
-#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
-#define SIRFSOC_UART1_PA_BASE          0xcc060000
-#else
-#define SIRFSOC_UART1_PA_BASE          0
-#endif
-
-#define SIRFSOC_UART1_VA_BASE          SIRFSOC_VA(0x060000)
-#define SIRFSOC_UART1_SIZE             SZ_4K
-
-void __init sirfsoc_map_lluart(void)
-{
-       struct map_desc sirfsoc_lluart_map = {
-               .virtual        = SIRFSOC_UART1_VA_BASE,
-               .pfn            = __phys_to_pfn(SIRFSOC_UART1_PA_BASE),
-               .length         = SIRFSOC_UART1_SIZE,
-               .type           = MT_DEVICE,
-       };
-
-       iotable_init(&sirfsoc_lluart_map, 1);
-}
index 335c12e..fc2b03c 100644 (file)
 
 #include "common.h"
 
-static void __iomem *scu_base;
-static void __iomem *rsc_base;
+static void __iomem *clk_base;
 
 static DEFINE_SPINLOCK(boot_lock);
 
-static struct map_desc scu_io_desc __initdata = {
-       .length         = SZ_4K,
-       .type           = MT_DEVICE,
-};
-
-void __init sirfsoc_map_scu(void)
-{
-       unsigned long base;
-
-       /* Get SCU base */
-       asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
-
-       scu_io_desc.virtual = SIRFSOC_VA(base);
-       scu_io_desc.pfn = __phys_to_pfn(base);
-       iotable_init(&scu_io_desc, 1);
-
-       scu_base = (void __iomem *)SIRFSOC_VA(base);
-}
-
 static void sirfsoc_secondary_init(unsigned int cpu)
 {
        /*
@@ -60,8 +40,8 @@ static void sirfsoc_secondary_init(unsigned int cpu)
        spin_unlock(&boot_lock);
 }
 
-static struct of_device_id rsc_ids[]  = {
-       { .compatible = "sirf,marco-rsc" },
+static struct of_device_id clk_ids[]  = {
+       { .compatible = "sirf,atlas7-clkc" },
        {},
 };
 
@@ -70,27 +50,27 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
        unsigned long timeout;
        struct device_node *np;
 
-       np = of_find_matching_node(NULL, rsc_ids);
+       np = of_find_matching_node(NULL, clk_ids);
        if (!np)
                return -ENODEV;
 
-       rsc_base = of_iomap(np, 0);
-       if (!rsc_base)
+       clk_base = of_iomap(np, 0);
+       if (!clk_base)
                return -ENOMEM;
 
        /*
-        * write the address of secondary startup into the sram register
-        * at offset 0x2C, then write the magic number 0x3CAF5D62 to the
-        * RSC register at offset 0x28, which is what boot rom code is
+        * write the address of secondary startup into the clkc register
+        * at offset 0x2bC, then write the magic number 0x3CAF5D62 to the
+        * clkc register at offset 0x2b8, which is what boot rom code is
         * waiting for. This would wake up the secondary core from WFE
         */
-#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2C
+#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2bc
        __raw_writel(virt_to_phys(sirfsoc_secondary_startup),
-               rsc_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
+               clk_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
 
-#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x28
+#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x2b8
        __raw_writel(0x3CAF5D62,
-               rsc_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
+               clk_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
 
        /* make sure write buffer is drained */
        mb();
@@ -132,13 +112,7 @@ static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
        return pen_release != -1 ? -ENOSYS : 0;
 }
 
-static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus)
-{
-       scu_enable(scu_base);
-}
-
 struct smp_operations sirfsoc_smp_ops __initdata = {
-       .smp_prepare_cpus       = sirfsoc_smp_prepare_cpus,
        .smp_secondary_init     = sirfsoc_secondary_init,
        .smp_boot_secondary     = sirfsoc_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
index e1f1f86..7c251eb 100644 (file)
@@ -34,36 +34,20 @@ static int sirfsoc_reset_module(struct reset_controller_dev *rcdev,
 
        mutex_lock(&rstc_lock);
 
-       if (of_device_is_compatible(rcdev->of_node, "sirf,prima2-rstc")) {
-               /*
-                * Writing 1 to this bit resets corresponding block.
-                * Writing 0 to this bit de-asserts reset signal of the
-                * corresponding block. datasheet doesn't require explicit
-                * delay between the set and clear of reset bit. it could
-                * be shorter if tests pass.
-                */
-               writel(readl(sirfsoc_rstc_base +
+       /*
+        * Writing 1 to this bit resets corresponding block.
+        * Writing 0 to this bit de-asserts reset signal of the
+        * corresponding block. datasheet doesn't require explicit
+        * delay between the set and clear of reset bit. it could
+        * be shorter if tests pass.
+        */
+       writel(readl(sirfsoc_rstc_base +
                        (reset_bit / 32) * 4) | (1 << reset_bit),
-                       sirfsoc_rstc_base + (reset_bit / 32) * 4);
-               msleep(20);
-               writel(readl(sirfsoc_rstc_base +
+               sirfsoc_rstc_base + (reset_bit / 32) * 4);
+       msleep(20);
+       writel(readl(sirfsoc_rstc_base +
                        (reset_bit / 32) * 4) & ~(1 << reset_bit),
-                       sirfsoc_rstc_base + (reset_bit / 32) * 4);
-       } else {
-               /*
-                * For MARCO and POLO
-                * Writing 1 to SET register resets corresponding block.
-                * Writing 1 to CLEAR register de-asserts reset signal of the
-                * corresponding block.
-                * datasheet doesn't require explicit delay between the set and
-                * clear of reset bit. it could be shorter if tests pass.
-                */
-               writel(1 << reset_bit,
-                       sirfsoc_rstc_base + (reset_bit / 32) * 8);
-               msleep(20);
-               writel(1 << reset_bit,
-                       sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4);
-       }
+               sirfsoc_rstc_base + (reset_bit / 32) * 4);
 
        mutex_unlock(&rstc_lock);
 
@@ -106,7 +90,6 @@ static int sirfsoc_rstc_probe(struct platform_device *pdev)
 
 static const struct of_device_id rstc_ids[]  = {
        { .compatible = "sirf,prima2-rstc" },
-       { .compatible = "sirf,marco-rstc" },
        {},
 };
 
index 70a0b47..8f66d8f 100644 (file)
@@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
 
 static const struct of_device_id rtciobrg_ids[] = {
        { .compatible = "sirf,prima2-rtciobg" },
-       { .compatible = "sirf,marco-rtciobg" },
        {}
 };
 
index ee5697b..48003ea 100644 (file)
@@ -1,9 +1,8 @@
 menuconfig ARCH_QCOM
        bool "Qualcomm Support" if ARCH_MULTI_V7
-       select ARCH_REQUIRE_GPIOLIB
+       select ARCH_SUPPORTS_BIG_ENDIAN
        select ARM_GIC
        select ARM_AMBA
-       select CLKSRC_OF
        select PINCTRL
        select QCOM_SCM if SMP
        help
index 45cee3e..e8ff7be 100644 (file)
 /*
  * Set the cold/warm boot address for one of the CPU cores.
  */
-int scm_set_boot_addr(phys_addr_t addr, int flags)
+int scm_set_boot_addr(u32 addr, int flags)
 {
        struct {
-               unsigned int flags;
-               phys_addr_t  addr;
+               __le32 flags;
+               __le32 addr;
        } cmd;
 
-       cmd.addr = addr;
-       cmd.flags = flags;
+       cmd.addr = cpu_to_le32(addr);
+       cmd.flags = cpu_to_le32(flags);
        return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
                        &cmd, sizeof(cmd), NULL, 0);
 }
index 6aabb24..3e210fb 100644 (file)
@@ -18,7 +18,9 @@
 #define SCM_FLAG_COLDBOOT_CPU3         0x20
 #define SCM_FLAG_WARMBOOT_CPU0         0x04
 #define SCM_FLAG_WARMBOOT_CPU1         0x02
+#define SCM_FLAG_WARMBOOT_CPU2         0x10
+#define SCM_FLAG_WARMBOOT_CPU3         0x40
 
-int scm_set_boot_addr(phys_addr_t addr, int flags);
+int scm_set_boot_addr(u32 addr, int flags);
 
 #endif
index c536fd6..1d9cf18 100644 (file)
 #include <linux/errno.h>
 #include <linux/err.h>
 
+#include <asm/outercache.h>
 #include <asm/cacheflush.h>
 
 #include "scm.h"
 
-/* Cache line size for msm8x60 */
-#define CACHELINESIZE 32
-
 #define SCM_ENOMEM             -5
 #define SCM_EOPNOTSUPP         -4
 #define SCM_EINVAL_ADDR                -3
@@ -63,11 +61,11 @@ static DEFINE_MUTEX(scm_lock);
  * to access the buffers in a safe manner.
  */
 struct scm_command {
-       u32     len;
-       u32     buf_offset;
-       u32     resp_hdr_offset;
-       u32     id;
-       u32     buf[0];
+       __le32 len;
+       __le32 buf_offset;
+       __le32 resp_hdr_offset;
+       __le32 id;
+       __le32 buf[0];
 };
 
 /**
@@ -77,9 +75,9 @@ struct scm_command {
  * @is_complete: indicates if the command has finished processing
  */
 struct scm_response {
-       u32     len;
-       u32     buf_offset;
-       u32     is_complete;
+       __le32 len;
+       __le32 buf_offset;
+       __le32 is_complete;
 };
 
 /**
@@ -97,12 +95,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
        struct scm_command *cmd;
        size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
                resp_size;
+       u32 offset;
 
        cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
        if (cmd) {
-               cmd->len = len;
-               cmd->buf_offset = offsetof(struct scm_command, buf);
-               cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
+               cmd->len = cpu_to_le32(len);
+               offset = offsetof(struct scm_command, buf);
+               cmd->buf_offset = cpu_to_le32(offset);
+               cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
        }
        return cmd;
 }
@@ -127,7 +127,7 @@ static inline void free_scm_command(struct scm_command *cmd)
 static inline struct scm_response *scm_command_to_response(
                const struct scm_command *cmd)
 {
-       return (void *)cmd + cmd->resp_hdr_offset;
+       return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
 }
 
 /**
@@ -149,11 +149,12 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd)
  */
 static inline void *scm_get_response_buffer(const struct scm_response *rsp)
 {
-       return (void *)rsp + rsp->buf_offset;
+       return (void *)rsp + le32_to_cpu(rsp->buf_offset);
 }
 
 static int scm_remap_error(int err)
 {
+       pr_err("scm_call failed with error code %d\n", err);
        switch (err) {
        case SCM_ERROR:
                return -EIO;
@@ -198,11 +199,12 @@ static int __scm_call(const struct scm_command *cmd)
        u32 cmd_addr = virt_to_phys(cmd);
 
        /*
-        * Flush the entire cache here so callers don't have to remember
-        * to flush the cache when passing physical addresses to the secure
-        * side in the buffer.
+        * Flush the command buffer so that the secure world sees
+        * the correct data.
         */
-       flush_cache_all();
+       __cpuc_flush_dcache_area((void *)cmd, cmd->len);
+       outer_flush_range(cmd_addr, cmd_addr + cmd->len);
+
        ret = smc(cmd_addr);
        if (ret < 0)
                ret = scm_remap_error(ret);
@@ -210,6 +212,25 @@ static int __scm_call(const struct scm_command *cmd)
        return ret;
 }
 
+static void scm_inv_range(unsigned long start, unsigned long end)
+{
+       u32 cacheline_size, ctr;
+
+       asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
+       cacheline_size = 4 << ((ctr >> 16) & 0xf);
+
+       start = round_down(start, cacheline_size);
+       end = round_up(end, cacheline_size);
+       outer_inv_range(start, end);
+       while (start < end) {
+               asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
+                    : "memory");
+               start += cacheline_size;
+       }
+       dsb();
+       isb();
+}
+
 /**
  * scm_call() - Send an SCM command
  * @svc_id: service identifier
@@ -220,6 +241,13 @@ static int __scm_call(const struct scm_command *cmd)
  * @resp_len: length of the response buffer
  *
  * Sends a command to the SCM and waits for the command to finish processing.
+ *
+ * A note on cache maintenance:
+ * Note that any buffers that are expected to be accessed by the secure world
+ * must be flushed before invoking scm_call and invalidated in the cache
+ * immediately after scm_call returns. Cache maintenance on the command and
+ * response buffers is taken care of by scm_call; however, callers are
+ * responsible for any other cached buffers passed over to the secure world.
  */
 int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
                void *resp_buf, size_t resp_len)
@@ -227,12 +255,13 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
        int ret;
        struct scm_command *cmd;
        struct scm_response *rsp;
+       unsigned long start, end;
 
        cmd = alloc_scm_command(cmd_len, resp_len);
        if (!cmd)
                return -ENOMEM;
 
-       cmd->id = (svc_id << 10) | cmd_id;
+       cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
        if (cmd_buf)
                memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
 
@@ -243,17 +272,15 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
                goto out;
 
        rsp = scm_command_to_response(cmd);
+       start = (unsigned long)rsp;
+
        do {
-               u32 start = (u32)rsp;
-               u32 end = (u32)scm_get_response_buffer(rsp) + resp_len;
-               start &= ~(CACHELINESIZE - 1);
-               while (start < end) {
-                       asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
-                            : "memory");
-                       start += CACHELINESIZE;
-               }
+               scm_inv_range(start, start + sizeof(*rsp));
        } while (!rsp->is_complete);
 
+       end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;
+       scm_inv_range(start, end);
+
        if (resp_buf)
                memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
 out:
index b29d8ea..5c3a9b2 100644 (file)
@@ -1,4 +1,5 @@
 CFLAGS_platsmp.o := -march=armv7-a
 
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
+obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
new file mode 100644 (file)
index 0000000..50cb781
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <tony.xie@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/suspend.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regulator/machine.h>
+
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/suspend.h>
+
+#include "pm.h"
+
+/* These enum are option of low power mode */
+enum {
+       ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
+       ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
+};
+
+struct rockchip_pm_data {
+       const struct platform_suspend_ops *ops;
+       int (*init)(struct device_node *np);
+};
+
+static void __iomem *rk3288_bootram_base;
+static phys_addr_t rk3288_bootram_phy;
+
+static struct regmap *pmu_regmap;
+static struct regmap *sgrf_regmap;
+
+static u32 rk3288_pmu_pwr_mode_con;
+static u32 rk3288_sgrf_soc_con0;
+
+static inline u32 rk3288_l2_config(void)
+{
+       u32 l2ctlr;
+
+       asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr));
+       return l2ctlr;
+}
+
+static void rk3288_config_bootdata(void)
+{
+       rkpm_bootdata_cpusp = rk3288_bootram_phy + (SZ_4K - 8);
+       rkpm_bootdata_cpu_code = virt_to_phys(cpu_resume);
+
+       rkpm_bootdata_l2ctlr_f  = 1;
+       rkpm_bootdata_l2ctlr = rk3288_l2_config();
+}
+
+static void rk3288_slp_mode_set(int level)
+{
+       u32 mode_set, mode_set1;
+
+       regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0);
+
+       regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON,
+                   &rk3288_pmu_pwr_mode_con);
+
+       /* set bit 8 so that system will resume to FAST_BOOT_ADDR */
+       regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0,
+                    SGRF_FAST_BOOT_EN | SGRF_FAST_BOOT_EN_WRITE);
+
+       /* booting address of resuming system is from this register value */
+       regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR,
+                    rk3288_bootram_phy);
+
+       regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1,
+                    PMU_ARMINT_WAKEUP_EN);
+
+       mode_set = BIT(PMU_GLOBAL_INT_DISABLE) | BIT(PMU_L2FLUSH_EN) |
+                  BIT(PMU_SREF0_ENTER_EN) | BIT(PMU_SREF1_ENTER_EN) |
+                  BIT(PMU_DDR0_GATING_EN) | BIT(PMU_DDR1_GATING_EN) |
+                  BIT(PMU_PWR_MODE_EN) | BIT(PMU_CHIP_PD_EN) |
+                  BIT(PMU_SCU_EN);
+
+       mode_set1 = BIT(PMU_CLR_CORE) | BIT(PMU_CLR_CPUP);
+
+       if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
+               /* arm off, logic deep sleep */
+               mode_set |= BIT(PMU_BUS_PD_EN) |
+                           BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) |
+                           BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) |
+                           BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN);
+
+               mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) |
+                            BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA);
+       } else {
+               /*
+                * arm off, logic normal
+                * if pmu_clk_core_src_gate_en is not set,
+                * wakeup will be error
+                */
+               mode_set |= BIT(PMU_CLK_CORE_SRC_GATE_EN);
+       }
+
+       regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, mode_set);
+       regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON1, mode_set1);
+}
+
+static void rk3288_slp_mode_set_resume(void)
+{
+       regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON,
+                    rk3288_pmu_pwr_mode_con);
+
+       regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0,
+                    rk3288_sgrf_soc_con0 | SGRF_FAST_BOOT_EN_WRITE);
+}
+
+static int rockchip_lpmode_enter(unsigned long arg)
+{
+       flush_cache_all();
+
+       cpu_do_idle();
+
+       pr_err("%s: Failed to suspend\n", __func__);
+
+       return 1;
+}
+
+static int rk3288_suspend_enter(suspend_state_t state)
+{
+       local_fiq_disable();
+
+       rk3288_slp_mode_set(ROCKCHIP_ARM_OFF_LOGIC_NORMAL);
+
+       cpu_suspend(0, rockchip_lpmode_enter);
+
+       rk3288_slp_mode_set_resume();
+
+       local_fiq_enable();
+
+       return 0;
+}
+
+static int rk3288_suspend_prepare(void)
+{
+       return regulator_suspend_prepare(PM_SUSPEND_MEM);
+}
+
+static void rk3288_suspend_finish(void)
+{
+       if (regulator_suspend_finish())
+               pr_err("%s: Suspend finish failed\n", __func__);
+}
+
+static int rk3288_suspend_init(struct device_node *np)
+{
+       struct device_node *sram_np;
+       struct resource res;
+       int ret;
+
+       pmu_regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(pmu_regmap)) {
+               pr_err("%s: could not find pmu regmap\n", __func__);
+               return PTR_ERR(pmu_regmap);
+       }
+
+       sgrf_regmap = syscon_regmap_lookup_by_compatible(
+                               "rockchip,rk3288-sgrf");
+       if (IS_ERR(sgrf_regmap)) {
+               pr_err("%s: could not find sgrf regmap\n", __func__);
+               return PTR_ERR(pmu_regmap);
+       }
+
+       sram_np = of_find_compatible_node(NULL, NULL,
+                                         "rockchip,rk3288-pmu-sram");
+       if (!sram_np) {
+               pr_err("%s: could not find bootram dt node\n", __func__);
+               return -ENODEV;
+       }
+
+       rk3288_bootram_base = of_iomap(sram_np, 0);
+       if (!rk3288_bootram_base) {
+               pr_err("%s: could not map bootram base\n", __func__);
+               return -ENOMEM;
+       }
+
+       ret = of_address_to_resource(sram_np, 0, &res);
+       if (ret) {
+               pr_err("%s: could not get bootram phy addr\n", __func__);
+               return ret;
+       }
+       rk3288_bootram_phy = res.start;
+
+       of_node_put(sram_np);
+
+       rk3288_config_bootdata();
+
+       /* copy resume code and data to bootsram */
+       memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume,
+              rk3288_bootram_sz);
+
+       return 0;
+}
+
+static const struct platform_suspend_ops rk3288_suspend_ops = {
+       .enter   = rk3288_suspend_enter,
+       .valid   = suspend_valid_only_mem,
+       .prepare = rk3288_suspend_prepare,
+       .finish  = rk3288_suspend_finish,
+};
+
+static const struct rockchip_pm_data rk3288_pm_data __initconst = {
+       .ops = &rk3288_suspend_ops,
+       .init = rk3288_suspend_init,
+};
+
+static const struct of_device_id rockchip_pmu_of_device_ids[] __initconst = {
+       {
+               .compatible = "rockchip,rk3288-pmu",
+               .data = &rk3288_pm_data,
+       },
+       { /* sentinel */ },
+};
+
+void __init rockchip_suspend_init(void)
+{
+       const struct rockchip_pm_data *pm_data;
+       const struct of_device_id *match;
+       struct device_node *np;
+       int ret;
+
+       np = of_find_matching_node_and_match(NULL, rockchip_pmu_of_device_ids,
+                                            &match);
+       if (!match) {
+               pr_err("Failed to find PMU node\n");
+               return;
+       }
+       pm_data = (struct rockchip_pm_data *) match->data;
+
+       if (pm_data->init) {
+               ret = pm_data->init(np);
+
+               if (ret) {
+                       pr_err("%s: matches init error %d\n", __func__, ret);
+                       return;
+               }
+       }
+
+       suspend_set_ops(pm_data->ops);
+}
diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h
new file mode 100644 (file)
index 0000000..7d752ff
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <tony.xie@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 __MACH_ROCKCHIP_PM_H
+#define __MACH_ROCKCHIP_PM_H
+
+extern unsigned long rkpm_bootdata_cpusp;
+extern unsigned long rkpm_bootdata_cpu_code;
+extern unsigned long rkpm_bootdata_l2ctlr_f;
+extern unsigned long rkpm_bootdata_l2ctlr;
+extern unsigned long rkpm_bootdata_ddr_code;
+extern unsigned long rkpm_bootdata_ddr_data;
+extern unsigned long rk3288_bootram_sz;
+
+void rockchip_slp_cpu_resume(void);
+void __init rockchip_suspend_init(void);
+
+/****** following is rk3288 defined **********/
+#define RK3288_PMU_WAKEUP_CFG0         0x00
+#define RK3288_PMU_WAKEUP_CFG1         0x04
+#define RK3288_PMU_PWRMODE_CON         0x18
+#define RK3288_PMU_OSC_CNT             0x20
+#define RK3288_PMU_PLL_CNT             0x24
+#define RK3288_PMU_STABL_CNT           0x28
+#define RK3288_PMU_DDR0IO_PWRON_CNT    0x2c
+#define RK3288_PMU_DDR1IO_PWRON_CNT    0x30
+#define RK3288_PMU_CORE_PWRDWN_CNT     0x34
+#define RK3288_PMU_CORE_PWRUP_CNT      0x38
+#define RK3288_PMU_GPU_PWRDWN_CNT      0x3c
+#define RK3288_PMU_GPU_PWRUP_CNT       0x40
+#define RK3288_PMU_WAKEUP_RST_CLR_CNT  0x44
+#define RK3288_PMU_PWRMODE_CON1                0x90
+
+#define RK3288_SGRF_SOC_CON0           (0x0000)
+#define RK3288_SGRF_FAST_BOOT_ADDR     (0x0120)
+#define SGRF_FAST_BOOT_EN              BIT(8)
+#define SGRF_FAST_BOOT_EN_WRITE                BIT(24)
+
+#define RK3288_CRU_MODE_CON            0x50
+#define RK3288_CRU_SEL0_CON            0x60
+#define RK3288_CRU_SEL1_CON            0x64
+#define RK3288_CRU_SEL10_CON           0x88
+#define RK3288_CRU_SEL33_CON           0xe4
+#define RK3288_CRU_SEL37_CON           0xf4
+
+/* PMU_WAKEUP_CFG1 bits */
+#define PMU_ARMINT_WAKEUP_EN           BIT(0)
+
+enum rk3288_pwr_mode_con {
+       PMU_PWR_MODE_EN = 0,
+       PMU_CLK_CORE_SRC_GATE_EN,
+       PMU_GLOBAL_INT_DISABLE,
+       PMU_L2FLUSH_EN,
+       PMU_BUS_PD_EN,
+       PMU_A12_0_PD_EN,
+       PMU_SCU_EN,
+       PMU_PLL_PD_EN,
+       PMU_CHIP_PD_EN, /* POWER OFF PIN ENABLE */
+       PMU_PWROFF_COMB,
+       PMU_ALIVE_USE_LF,
+       PMU_PMU_USE_LF,
+       PMU_OSC_24M_DIS,
+       PMU_INPUT_CLAMP_EN,
+       PMU_WAKEUP_RESET_EN,
+       PMU_SREF0_ENTER_EN,
+       PMU_SREF1_ENTER_EN,
+       PMU_DDR0IO_RET_EN,
+       PMU_DDR1IO_RET_EN,
+       PMU_DDR0_GATING_EN,
+       PMU_DDR1_GATING_EN,
+       PMU_DDR0IO_RET_DE_REQ,
+       PMU_DDR1IO_RET_DE_REQ
+};
+
+enum rk3288_pwr_mode_con1 {
+       PMU_CLR_BUS = 0,
+       PMU_CLR_CORE,
+       PMU_CLR_CPUP,
+       PMU_CLR_ALIVE,
+       PMU_CLR_DMA,
+       PMU_CLR_PERI,
+       PMU_CLR_GPU,
+       PMU_CLR_VIDEO,
+       PMU_CLR_HEVC,
+       PMU_CLR_VIO,
+};
+
+#endif /* __MACH_ROCKCHIP_PM_H */
index d226b71..f708611 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/hardware/cache-l2x0.h>
 #include "core.h"
+#include "pm.h"
 
 static void __init rockchip_dt_init(void)
 {
+       rockchip_suspend_init();
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
        platform_device_register_simple("cpufreq-dt", 0, NULL, 0);
 }
@@ -39,7 +41,7 @@ static const char * const rockchip_board_dt_compat[] = {
        NULL,
 };
 
-DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
+DT_MACHINE_START(ROCKCHIP_DT, "Rockchip (Device Tree)")
        .l2c_aux_val    = 0,
        .l2c_aux_mask   = ~0,
        .dt_compat      = rockchip_board_dt_compat,
diff --git a/arch/arm/mach-rockchip/sleep.S b/arch/arm/mach-rockchip/sleep.S
new file mode 100644 (file)
index 0000000..2eec9a3
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Tony Xie <tony.xie@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+
+.data
+/*
+ * this code will be copied from
+ * ddr to sram for system resumeing.
+ * so it is ".data section".
+ */
+.align
+
+ENTRY(rockchip_slp_cpu_resume)
+       setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set svc, irqs off
+       mrc     p15, 0, r1, c0, c0, 5
+       and     r1, r1, #0xf
+       cmp     r1, #0
+       /* olny cpu0 can continue to run, the others is halt here */
+       beq     cpu0run
+secondary_loop:
+       wfe
+       b       secondary_loop
+cpu0run:
+       ldr     r3, rkpm_bootdata_l2ctlr_f
+       cmp     r3, #0
+       beq     sp_set
+       ldr     r3, rkpm_bootdata_l2ctlr
+       mcr     p15, 1, r3, c9, c0, 2
+sp_set:
+       ldr     sp, rkpm_bootdata_cpusp
+       ldr     r1, rkpm_bootdata_cpu_code
+       bx      r1
+ENDPROC(rockchip_slp_cpu_resume)
+
+/* Parameters filled in by the kernel */
+
+/* Flag for whether to restore L2CTLR on resume */
+       .global rkpm_bootdata_l2ctlr_f
+rkpm_bootdata_l2ctlr_f:
+       .long 0
+
+/* Saved L2CTLR to restore on resume */
+       .global rkpm_bootdata_l2ctlr
+rkpm_bootdata_l2ctlr:
+       .long 0
+
+/* CPU resume SP addr */
+       .globl rkpm_bootdata_cpusp
+rkpm_bootdata_cpusp:
+       .long 0
+
+/* CPU resume function (physical address) */
+       .globl rkpm_bootdata_cpu_code
+rkpm_bootdata_cpu_code:
+       .long 0
+
+ENTRY(rk3288_bootram_sz)
+        .word   . - rockchip_slp_cpu_resume
index 1b4fafe..894c687 100644 (file)
@@ -7,6 +7,7 @@ config PM_RCAR
 
 config PM_RMOBILE
        bool
+       select PM_GENERIC_DOMAINS
 
 config ARCH_RCAR_GEN1
        bool
@@ -23,7 +24,7 @@ config ARCH_RCAR_GEN2
 
 config ARCH_RMOBILE
        bool
-       select PM_RMOBILE if PM && !ARCH_SHMOBILE_MULTI
+       select PM_RMOBILE if PM
        select SYS_SUPPORTS_SH_CMT
        select SYS_SUPPORTS_SH_TMU
 
@@ -51,6 +52,11 @@ config ARCH_R7S72100
        bool "RZ/A1H (R7S72100)"
        select SYS_SUPPORTS_SH_MTU2
 
+config ARCH_R8A73A4
+       bool "R-Mobile APE6 (R8A73A40)"
+       select ARCH_RMOBILE
+       select RENESAS_IRQC
+
 config ARCH_R8A7740
        bool "R-Mobile A1 (R8A77400)"
        select ARCH_RMOBILE
index 6b4c1f3..3855fb0 100644 (file)
@@ -553,6 +553,7 @@ enum { MSTP001,
        MSTP314, MSTP313, MSTP312, MSTP311,
        MSTP304, MSTP303, MSTP302, MSTP301, MSTP300,
        MSTP411, MSTP410, MSTP403,
+       MSTP508,
        MSTP_NR };
 
 #define MSTP(_parent, _reg, _bit, _flags) \
@@ -597,6 +598,7 @@ static struct clk mstp_clks[MSTP_NR] = {
        [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
@@ -677,6 +679,14 @@ static struct clk_lookup lookups[] = {
        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]),
index ac2eecd..34608fc 100644 (file)
@@ -9,10 +9,14 @@
  * 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)
 {
@@ -45,41 +49,51 @@ static int r8a7740_pd_d4_suspend(void)
 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,
        },
 };
index 6f7d56e..9501820 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2012  Renesas Solutions Corp.
  * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2014  Glider bvba
  *
  * based on pm-sh7372.c
  *  Copyright (C) 2011 Magnus Damm
  */
 #include <linux/console.h>
 #include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/pm_clock.h>
+#include <linux/slab.h>
+
 #include <asm/io.h>
+
 #include "pm-rmobile.h"
 
 /* SYSC */
-#define SPDCR          IOMEM(0xe6180008)
-#define SWUCR          IOMEM(0xe6180014)
-#define PSTR           IOMEM(0xe6180080)
+#define SPDCR          0x08    /* SYS Power Down Control Register */
+#define SWUCR          0x14    /* SYS Wakeup Control Register */
+#define PSTR           0x80    /* Power Status Register */
 
 #define PSTR_RETRIES   100
 #define PSTR_DELAY_US  10
 static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
 {
        struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
-       unsigned int mask = 1 << rmobile_pd->bit_shift;
+       unsigned int mask;
+
+       if (rmobile_pd->bit_shift == ~0)
+               return -EBUSY;
 
+       mask = 1 << rmobile_pd->bit_shift;
        if (rmobile_pd->suspend) {
                int ret = rmobile_pd->suspend();
 
@@ -39,12 +50,12 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
                        return ret;
        }
 
-       if (__raw_readl(PSTR) & mask) {
+       if (__raw_readl(rmobile_pd->base + PSTR) & mask) {
                unsigned int retry_count;
-               __raw_writel(mask, SPDCR);
+               __raw_writel(mask, rmobile_pd->base + SPDCR);
 
                for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
-                       if (!(__raw_readl(SPDCR) & mask))
+                       if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask))
                                break;
                        cpu_relax();
                }
@@ -52,7 +63,8 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
 
        if (!rmobile_pd->no_debug)
                pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
-                        genpd->name, mask, __raw_readl(PSTR));
+                        genpd->name, mask,
+                        __raw_readl(rmobile_pd->base + PSTR));
 
        return 0;
 }
@@ -60,17 +72,21 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
 static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
                                 bool do_resume)
 {
-       unsigned int mask = 1 << rmobile_pd->bit_shift;
+       unsigned int mask;
        unsigned int retry_count;
        int ret = 0;
 
-       if (__raw_readl(PSTR) & mask)
+       if (rmobile_pd->bit_shift == ~0)
+               return 0;
+
+       mask = 1 << rmobile_pd->bit_shift;
+       if (__raw_readl(rmobile_pd->base + PSTR) & mask)
                goto out;
 
-       __raw_writel(mask, SWUCR);
+       __raw_writel(mask, rmobile_pd->base + SWUCR);
 
        for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
-               if (!(__raw_readl(SWUCR) & mask))
+               if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask))
                        break;
                if (retry_count > PSTR_RETRIES)
                        udelay(PSTR_DELAY_US);
@@ -82,7 +98,8 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
 
        if (!rmobile_pd->no_debug)
                pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
-                        rmobile_pd->genpd.name, mask, __raw_readl(PSTR));
+                        rmobile_pd->genpd.name, mask,
+                        __raw_readl(rmobile_pd->base + PSTR));
 
 out:
        if (ret == 0 && rmobile_pd->resume && do_resume)
@@ -101,6 +118,36 @@ static bool rmobile_pd_active_wakeup(struct device *dev)
        return true;
 }
 
+static int rmobile_pd_attach_dev(struct generic_pm_domain *domain,
+                                struct device *dev)
+{
+       int error;
+
+       error = pm_clk_create(dev);
+       if (error) {
+               dev_err(dev, "pm_clk_create failed %d\n", error);
+               return error;
+       }
+
+       error = pm_clk_add(dev, NULL);
+       if (error) {
+               dev_err(dev, "pm_clk_add failed %d\n", error);
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       pm_clk_destroy(dev);
+       return error;
+}
+
+static void rmobile_pd_detach_dev(struct generic_pm_domain *domain,
+                                 struct device *dev)
+{
+       pm_clk_destroy(dev);
+}
+
 static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
 {
        struct generic_pm_domain *genpd = &rmobile_pd->genpd;
@@ -111,9 +158,13 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
        genpd->dev_ops.active_wakeup    = rmobile_pd_active_wakeup;
        genpd->power_off                = rmobile_pd_power_down;
        genpd->power_on                 = rmobile_pd_power_up;
+       genpd->attach_dev               = rmobile_pd_attach_dev;
+       genpd->detach_dev               = rmobile_pd_detach_dev;
        __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;
@@ -129,8 +180,6 @@ void rmobile_add_device_to_domain_td(const char *domain_name,
        struct device *dev = &pdev->dev;
 
        __pm_genpd_name_add_device(domain_name, dev, td);
-       if (pm_clk_no_clocks(dev))
-               pm_clk_add(dev, NULL);
 }
 
 void rmobile_add_devices_to_domains(struct pm_domain_device data[],
@@ -148,3 +197,238 @@ void rmobile_add_devices_to_domains(struct pm_domain_device data[],
                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)
+{
+       /*
+        * This domain should not be turned off.
+        */
+       return -EBUSY;
+}
+
+static int rmobile_pd_suspend_console(void)
+{
+       /*
+        * Serial consoles make use of SCIF hardware located in this domain,
+        * hence keep the power domain on if "no_console_suspend" is set.
+        */
+       return console_suspend_enabled ? 0 : -EBUSY;
+}
+
+enum pd_types {
+       PD_NORMAL,
+       PD_CPU,
+       PD_CONSOLE,
+       PD_DEBUG,
+       PD_MEMCTL,
+};
+
+#define MAX_NUM_SPECIAL_PDS    16
+
+static struct special_pd {
+       struct device_node *pd;
+       enum pd_types type;
+} special_pds[MAX_NUM_SPECIAL_PDS] __initdata;
+
+static unsigned int num_special_pds __initdata;
+
+static const struct of_device_id special_ids[] __initconst = {
+       { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG },
+       { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, },
+       { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, },
+       { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, },
+       { /* sentinel */ },
+};
+
+static void __init add_special_pd(struct device_node *np, enum pd_types type)
+{
+       unsigned int i;
+       struct device_node *pd;
+
+       pd = of_parse_phandle(np, "power-domains", 0);
+       if (!pd)
+               return;
+
+       for (i = 0; i < num_special_pds; i++)
+               if (pd == special_pds[i].pd && type == special_pds[i].type) {
+                       of_node_put(pd);
+                       return;
+               }
+
+       if (num_special_pds == ARRAY_SIZE(special_pds)) {
+               pr_warn("Too many special PM domains\n");
+               of_node_put(pd);
+               return;
+       }
+
+       pr_debug("Special PM domain %s type %d for %s\n", pd->name, type,
+                np->full_name);
+
+       special_pds[num_special_pds].pd = pd;
+       special_pds[num_special_pds].type = type;
+       num_special_pds++;
+}
+
+static void __init get_special_pds(void)
+{
+       struct device_node *np;
+       const struct of_device_id *id;
+
+       /* PM domains containing CPUs */
+       for_each_node_by_type(np, "cpu")
+               add_special_pd(np, PD_CPU);
+
+       /* PM domain containing console */
+       if (of_stdout)
+               add_special_pd(of_stdout, PD_CONSOLE);
+
+       /* PM domains containing other special devices */
+       for_each_matching_node_and_match(np, special_ids, &id)
+               add_special_pd(np, (enum pd_types)id->data);
+}
+
+static void __init put_special_pds(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_special_pds; i++)
+               of_node_put(special_pds[i].pd);
+}
+
+static enum pd_types __init pd_type(const struct device_node *pd)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_special_pds; i++)
+               if (pd == special_pds[i].pd)
+                       return special_pds[i].type;
+
+       return PD_NORMAL;
+}
+
+static void __init rmobile_setup_pm_domain(struct device_node *np,
+                                          struct rmobile_pm_domain *pd)
+{
+       const char *name = pd->genpd.name;
+
+       switch (pd_type(np)) {
+       case PD_CPU:
+               /*
+                * This domain contains the CPU core and therefore it should
+                * only be turned off if the CPU is not in use.
+                */
+               pr_debug("PM domain %s contains CPU\n", name);
+               pd->gov = &pm_domain_always_on_gov;
+               pd->suspend = rmobile_pd_suspend_busy;
+               break;
+
+       case PD_CONSOLE:
+               pr_debug("PM domain %s contains serial console\n", name);
+               pd->gov = &pm_domain_always_on_gov;
+               pd->suspend = rmobile_pd_suspend_console;
+               break;
+
+       case PD_DEBUG:
+               /*
+                * This domain contains the Coresight-ETM hardware block and
+                * therefore it should only be turned off if the debug module
+                * is not in use.
+                */
+               pr_debug("PM domain %s contains Coresight-ETM\n", name);
+               pd->gov = &pm_domain_always_on_gov;
+               pd->suspend = rmobile_pd_suspend_busy;
+               break;
+
+       case PD_MEMCTL:
+               /*
+                * This domain contains a memory-controller and therefore it
+                * should only be turned off if memory is not in use.
+                */
+               pr_debug("PM domain %s contains MEMCTL\n", name);
+               pd->gov = &pm_domain_always_on_gov;
+               pd->suspend = rmobile_pd_suspend_busy;
+               break;
+
+       case PD_NORMAL:
+               break;
+       }
+
+       rmobile_init_pm_domain(pd);
+}
+
+static int __init rmobile_add_pm_domains(void __iomem *base,
+                                        struct device_node *parent,
+                                        struct generic_pm_domain *genpd_parent)
+{
+       struct device_node *np;
+
+       for_each_child_of_node(parent, np) {
+               struct rmobile_pm_domain *pd;
+               u32 idx = ~0;
+
+               if (of_property_read_u32(np, "reg", &idx)) {
+                       /* always-on domain */
+               }
+
+               pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+               if (!pd)
+                       return -ENOMEM;
+
+               pd->genpd.name = np->name;
+               pd->base = base;
+               pd->bit_shift = idx;
+
+               rmobile_setup_pm_domain(np, pd);
+               if (genpd_parent)
+                       pm_genpd_add_subdomain(genpd_parent, &pd->genpd);
+               of_genpd_add_provider_simple(np, &pd->genpd);
+
+               rmobile_add_pm_domains(base, np, &pd->genpd);
+       }
+       return 0;
+}
+
+static int __init rmobile_init_pm_domains(void)
+{
+       struct device_node *np, *pmd;
+       bool scanned = false;
+       void __iomem *base;
+       int ret = 0;
+
+       for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") {
+               base = of_iomap(np, 0);
+               if (!base) {
+                       pr_warn("%s cannot map reg 0\n", np->full_name);
+                       continue;
+               }
+
+               pmd = of_get_child_by_name(np, "pm-domains");
+               if (!pmd) {
+                       pr_warn("%s lacks pm-domains node\n", np->full_name);
+                       continue;
+               }
+
+               if (!scanned) {
+                       /* Find PM domains containing special blocks */
+                       get_special_pds();
+                       scanned = true;
+               }
+
+               ret = rmobile_add_pm_domains(base, pmd, NULL);
+               of_node_put(pmd);
+               if (ret) {
+                       of_node_put(np);
+                       break;
+               }
+       }
+
+       put_special_pds();
+
+       return ret;
+}
+
+core_initcall(rmobile_init_pm_domains);
+
+#endif /* !CONFIG_ARCH_SHMOBILE_LEGACY */
index 8f66b34..5321978 100644 (file)
@@ -21,6 +21,7 @@ struct rmobile_pm_domain {
        struct dev_power_governor *gov;
        int (*suspend)(void);
        void (*resume)(void);
+       void __iomem *base;
        unsigned int bit_shift;
        bool no_debug;
 };
@@ -36,7 +37,7 @@ struct pm_domain_device {
        struct platform_device *pdev;
 };
 
-#ifdef CONFIG_PM_RMOBILE
+#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,
index 0e37da6..c0293ae 100644 (file)
@@ -45,6 +45,8 @@
 #define PLLC01STPCR IOMEM(0xe61500c8)
 
 /* SYSC */
+#define SYSC_BASE IOMEM(0xe6180000)
+
 #define SBAR IOMEM(0xe6180020)
 #define WUPRMSK IOMEM(0xe6180028)
 #define WUPSMSK IOMEM(0xe618002c)
@@ -118,24 +120,28 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
                .genpd.name = "A4LC",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 1,
        },
        {
                .genpd.name = "A4MP",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 2,
        },
        {
                .genpd.name = "D4",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 3,
        },
        {
                .genpd.name = "A4R",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 5,
                .suspend = sh7372_a4r_pd_suspend,
                .resume = sh7372_intcs_resume,
@@ -144,18 +150,21 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
                .genpd.name = "A3RV",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 6,
        },
        {
                .genpd.name = "A3RI",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 8,
        },
        {
                .genpd.name = "A4S",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 10,
                .gov = &pm_domain_always_on_gov,
                .no_debug = true,
@@ -166,6 +175,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
                .genpd.name = "A3SP",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 11,
                .gov = &pm_domain_always_on_gov,
                .no_debug = true,
@@ -175,6 +185,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = {
                .genpd.name = "A3SG",
                .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
                .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+               .base = SYSC_BASE,
                .bit_shift = 13,
        },
 };
index 3dd6edd..c35b91d 100644 (file)
@@ -52,15 +52,13 @@ void __init rcar_gen2_timer_init(void)
 {
 #if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK)
        u32 mode = rcar_gen2_read_mode_pins();
-       bool is_e2 = (bool)of_find_compatible_node(NULL, NULL,
-               "renesas,r8a7794");
 #endif
 #ifdef CONFIG_ARM_ARCH_TIMER
        void __iomem *base;
        int extal_mhz = 0;
        u32 freq;
 
-       if (is_e2) {
+       if (of_machine_is_compatible("renesas,r8a7794")) {
                freq = 260000000 / 8;   /* ZS / 8 */
                /* CNTVOFF has to be initialized either from non-secure
                 * Hypervisor mode or secure Monitor mode with SCR.NS==1.
index 3f761f8..9fc280e 100644 (file)
@@ -56,7 +56,7 @@ static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = {
        [3] = &r8a7779_ch_cpu3,
 };
 
-#ifdef CONFIG_HAVE_ARM_TWD
+#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM)
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29);
 void __init r8a7779_register_twd(void)
 {
index 3cf6ef8..b067390 100644 (file)
@@ -18,6 +18,7 @@ static const char *stih41x_dt_match[] __initdata = {
        "st,stih415",
        "st,stih416",
        "st,stih407",
+       "st,stih418",
        NULL
 };
 
index d0be9a1..5d1a318 100644 (file)
@@ -27,6 +27,7 @@ config ARCH_TEGRA_2x_SOC
        select PINCTRL_TEGRA20
        select PL310_ERRATA_727915 if CACHE_L2X0
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra AP20 and T20 processors, based on the
          ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -37,6 +38,7 @@ config ARCH_TEGRA_3x_SOC
        select ARM_ERRATA_764369 if SMP
        select PINCTRL_TEGRA30
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T30 processor family, based on the
          ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -47,6 +49,7 @@ config ARCH_TEGRA_114_SOC
        select ARM_L1_CACHE_SHIFT_6
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA114
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T114 processor family, based on the
          ARM CortexA15MP CPU
@@ -56,6 +59,7 @@ config ARCH_TEGRA_124_SOC
        select ARM_L1_CACHE_SHIFT_6
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA124
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T124 processor family, based on the
          ARM CortexA15MP CPU
index eb7682d..fb9ec62 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/debugfs.h>
 #include <linux/log2.h>
 #include <linux/syscore_ops.h>
+#include <linux/memblock.h>
 
 /*
  * DDR target is the same on all platforms.
@@ -69,6 +70,7 @@
  */
 #define WIN_CTRL_OFF           0x0000
 #define   WIN_CTRL_ENABLE       BIT(0)
+#define   WIN_CTRL_SYNCBARRIER  BIT(1)
 #define   WIN_CTRL_TGT_MASK     0xf0
 #define   WIN_CTRL_TGT_SHIFT    4
 #define   WIN_CTRL_ATTR_MASK    0xff00
@@ -82,6 +84,9 @@
 #define   WIN_REMAP_LOW         0xffff0000
 #define WIN_REMAP_HI_OFF       0x000c
 
+#define UNIT_SYNC_BARRIER_OFF   0x84
+#define   UNIT_SYNC_BARRIER_ALL 0xFFFF
+
 #define ATTR_HW_COHERENCY      (0x1 << 4)
 
 #define DDR_BASE_CS_OFF(n)     (0x0000 + ((n) << 3))
 
 /* Relative to mbusbridge_base */
 #define MBUS_BRIDGE_CTRL_OFF   0x0
+#define  MBUS_BRIDGE_SIZE_MASK  0xffff0000
 #define MBUS_BRIDGE_BASE_OFF   0x4
+#define  MBUS_BRIDGE_BASE_MASK  0xffff0000
 
 /* Maximum number of windows, for all known platforms */
 #define MBUS_WINS_MAX           20
@@ -106,9 +113,9 @@ struct mvebu_mbus_state;
 
 struct mvebu_mbus_soc_data {
        unsigned int num_wins;
-       unsigned int num_remappable_wins;
        bool has_mbus_bridge;
        unsigned int (*win_cfg_offset)(const int win);
+       unsigned int (*win_remap_offset)(const int win);
        void (*setup_cpu_target)(struct mvebu_mbus_state *s);
        int (*save_cpu_target)(struct mvebu_mbus_state *s,
                               u32 *store_addr);
@@ -154,6 +161,13 @@ const struct mbus_dram_target_info *mv_mbus_dram_info(void)
 }
 EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
 
+/* Checks whether the given window has remap capability */
+static bool mvebu_mbus_window_is_remappable(struct mvebu_mbus_state *mbus,
+                                           const int win)
+{
+       return mbus->soc->win_remap_offset(win) != MVEBU_MBUS_NO_REMAP;
+}
+
 /*
  * Functions to manipulate the address decoding windows
  */
@@ -185,9 +199,12 @@ static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus,
                *attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT;
 
        if (remap) {
-               if (win < mbus->soc->num_remappable_wins) {
-                       u32 remap_low = readl(addr + WIN_REMAP_LO_OFF);
-                       u32 remap_hi  = readl(addr + WIN_REMAP_HI_OFF);
+               if (mvebu_mbus_window_is_remappable(mbus, win)) {
+                       u32 remap_low, remap_hi;
+                       void __iomem *addr_rmp = mbus->mbuswins_base +
+                               mbus->soc->win_remap_offset(win);
+                       remap_low = readl(addr_rmp + WIN_REMAP_LO_OFF);
+                       remap_hi  = readl(addr_rmp + WIN_REMAP_HI_OFF);
                        *remap = ((u64)remap_hi << 32) | remap_low;
                } else
                        *remap = 0;
@@ -200,22 +217,25 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
        void __iomem *addr;
 
        addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win);
-
        writel(0, addr + WIN_BASE_OFF);
        writel(0, addr + WIN_CTRL_OFF);
-       if (win < mbus->soc->num_remappable_wins) {
+
+       if (mvebu_mbus_window_is_remappable(mbus, win)) {
+               addr = mbus->mbuswins_base + mbus->soc->win_remap_offset(win);
                writel(0, addr + WIN_REMAP_LO_OFF);
                writel(0, addr + WIN_REMAP_HI_OFF);
        }
 }
 
 /* Checks whether the given window number is available */
+
 static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
                                     const int win)
 {
        void __iomem *addr = mbus->mbuswins_base +
                mbus->soc->win_cfg_offset(win);
        u32 ctrl = readl(addr + WIN_CTRL_OFF);
+
        return !(ctrl & WIN_CTRL_ENABLE);
 }
 
@@ -303,17 +323,22 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
        ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
                (attr << WIN_CTRL_ATTR_SHIFT)    |
                (target << WIN_CTRL_TGT_SHIFT)   |
+               WIN_CTRL_SYNCBARRIER             |
                WIN_CTRL_ENABLE;
 
        writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF);
        writel(ctrl, addr + WIN_CTRL_OFF);
-       if (win < mbus->soc->num_remappable_wins) {
+
+       if (mvebu_mbus_window_is_remappable(mbus, win)) {
+               void __iomem *addr_rmp = mbus->mbuswins_base +
+                       mbus->soc->win_remap_offset(win);
+
                if (remap == MVEBU_MBUS_NO_REMAP)
                        remap_addr = base;
                else
                        remap_addr = remap;
-               writel(remap_addr & WIN_REMAP_LOW, addr + WIN_REMAP_LO_OFF);
-               writel(0, addr + WIN_REMAP_HI_OFF);
+               writel(remap_addr & WIN_REMAP_LOW, addr_rmp + WIN_REMAP_LO_OFF);
+               writel(0, addr_rmp + WIN_REMAP_HI_OFF);
        }
 
        return 0;
@@ -327,19 +352,27 @@ static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus,
        int win;
 
        if (remap == MVEBU_MBUS_NO_REMAP) {
-               for (win = mbus->soc->num_remappable_wins;
-                    win < mbus->soc->num_wins; win++)
+               for (win = 0; win < mbus->soc->num_wins; win++) {
+                       if (mvebu_mbus_window_is_remappable(mbus, win))
+                               continue;
+
                        if (mvebu_mbus_window_is_free(mbus, win))
                                return mvebu_mbus_setup_window(mbus, win, base,
                                                               size, remap,
                                                               target, attr);
+               }
        }
 
+       for (win = 0; win < mbus->soc->num_wins; win++) {
+               /* Skip window if need remap but is not supported */
+               if ((remap != MVEBU_MBUS_NO_REMAP) &&
+                   !mvebu_mbus_window_is_remappable(mbus, win))
+                       continue;
 
-       for (win = 0; win < mbus->soc->num_wins; win++)
                if (mvebu_mbus_window_is_free(mbus, win))
                        return mvebu_mbus_setup_window(mbus, win, base, size,
                                                       remap, target, attr);
+       }
 
        return -ENOMEM;
 }
@@ -451,7 +484,7 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
                    ((wbase & (u64)(wsize - 1)) != 0))
                        seq_puts(seq, " (Invalid base/size!!)");
 
-               if (win < mbus->soc->num_remappable_wins) {
+               if (mvebu_mbus_window_is_remappable(mbus, win)) {
                        seq_printf(seq, " (remap %016llx)\n",
                                   (unsigned long long)wremap);
                } else
@@ -477,12 +510,12 @@ static const struct file_operations mvebu_devs_debug_fops = {
  * SoC-specific functions and definitions
  */
 
-static unsigned int orion_mbus_win_offset(int win)
+static unsigned int generic_mbus_win_cfg_offset(int win)
 {
        return win << 4;
 }
 
-static unsigned int armada_370_xp_mbus_win_offset(int win)
+static unsigned int armada_370_xp_mbus_win_cfg_offset(int win)
 {
        /* The register layout is a bit annoying and the below code
         * tries to cope with it.
@@ -502,7 +535,7 @@ static unsigned int armada_370_xp_mbus_win_offset(int win)
                return 0x90 + ((win - 8) << 3);
 }
 
-static unsigned int mv78xx0_mbus_win_offset(int win)
+static unsigned int mv78xx0_mbus_win_cfg_offset(int win)
 {
        if (win < 8)
                return win << 4;
@@ -510,36 +543,140 @@ static unsigned int mv78xx0_mbus_win_offset(int win)
                return 0x900 + ((win - 8) << 4);
 }
 
+static unsigned int generic_mbus_win_remap_2_offset(int win)
+{
+       if (win < 2)
+               return generic_mbus_win_cfg_offset(win);
+       else
+               return MVEBU_MBUS_NO_REMAP;
+}
+
+static unsigned int generic_mbus_win_remap_4_offset(int win)
+{
+       if (win < 4)
+               return generic_mbus_win_cfg_offset(win);
+       else
+               return MVEBU_MBUS_NO_REMAP;
+}
+
+static unsigned int generic_mbus_win_remap_8_offset(int win)
+{
+       if (win < 8)
+               return generic_mbus_win_cfg_offset(win);
+       else
+               return MVEBU_MBUS_NO_REMAP;
+}
+
+static unsigned int armada_xp_mbus_win_remap_offset(int win)
+{
+       if (win < 8)
+               return generic_mbus_win_cfg_offset(win);
+       else if (win == 13)
+               return 0xF0 - WIN_REMAP_LO_OFF;
+       else
+               return MVEBU_MBUS_NO_REMAP;
+}
+
+/*
+ * Use the memblock information to find the MBus bridge hole in the
+ * physical address space.
+ */
+static void __init
+mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end)
+{
+       struct memblock_region *r;
+       uint64_t s = 0;
+
+       for_each_memblock(memory, r) {
+               /*
+                * This part of the memory is above 4 GB, so we don't
+                * care for the MBus bridge hole.
+                */
+               if (r->base >= 0x100000000)
+                       continue;
+
+               /*
+                * The MBus bridge hole is at the end of the RAM under
+                * the 4 GB limit.
+                */
+               if (r->base + r->size > s)
+                       s = r->base + r->size;
+       }
+
+       *start = s;
+       *end = 0x100000000;
+}
+
 static void __init
 mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
 {
        int i;
        int cs;
+       uint64_t mbus_bridge_base, mbus_bridge_end;
 
        mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
 
+       mvebu_mbus_find_bridge_hole(&mbus_bridge_base, &mbus_bridge_end);
+
        for (i = 0, cs = 0; i < 4; i++) {
-               u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
-               u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
+               u64 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
+               u64 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
+               u64 end;
+               struct mbus_dram_window *w;
+
+               /* Ignore entries that are not enabled */
+               if (!(size & DDR_SIZE_ENABLED))
+                       continue;
 
                /*
-                * We only take care of entries for which the chip
-                * select is enabled, and that don't have high base
-                * address bits set (devices can only access the first
-                * 32 bits of the memory).
+                * Ignore entries whose base address is above 2^32,
+                * since devices cannot DMA to such high addresses
                 */
-               if ((size & DDR_SIZE_ENABLED) &&
-                   !(base & DDR_BASE_CS_HIGH_MASK)) {
-                       struct mbus_dram_window *w;
+               if (base & DDR_BASE_CS_HIGH_MASK)
+                       continue;
 
-                       w = &mvebu_mbus_dram_info.cs[cs++];
-                       w->cs_index = i;
-                       w->mbus_attr = 0xf & ~(1 << i);
-                       if (mbus->hw_io_coherency)
-                               w->mbus_attr |= ATTR_HW_COHERENCY;
-                       w->base = base & DDR_BASE_CS_LOW_MASK;
-                       w->size = (size | ~DDR_SIZE_MASK) + 1;
+               base = base & DDR_BASE_CS_LOW_MASK;
+               size = (size | ~DDR_SIZE_MASK) + 1;
+               end = base + size;
+
+               /*
+                * Adjust base/size of the current CS to make sure it
+                * doesn't overlap with the MBus bridge hole. This is
+                * particularly important for devices that do DMA from
+                * DRAM to a SRAM mapped in a MBus window, such as the
+                * CESA cryptographic engine.
+                */
+
+               /*
+                * The CS is fully enclosed inside the MBus bridge
+                * area, so ignore it.
+                */
+               if (base >= mbus_bridge_base && end <= mbus_bridge_end)
+                       continue;
+
+               /*
+                * Beginning of CS overlaps with end of MBus, raise CS
+                * base address, and shrink its size.
+                */
+               if (base >= mbus_bridge_base && end > mbus_bridge_end) {
+                       size -= mbus_bridge_end - base;
+                       base = mbus_bridge_end;
                }
+
+               /*
+                * End of CS overlaps with beginning of MBus, shrink
+                * CS size.
+                */
+               if (base < mbus_bridge_base && end > mbus_bridge_base)
+                       size -= end - mbus_bridge_base;
+
+               w = &mvebu_mbus_dram_info.cs[cs++];
+               w->cs_index = i;
+               w->mbus_attr = 0xf & ~(1 << i);
+               if (mbus->hw_io_coherency)
+                       w->mbus_attr |= ATTR_HW_COHERENCY;
+               w->base = base;
+               w->size = size;
        }
        mvebu_mbus_dram_info.num_cs = cs;
 }
@@ -619,30 +756,40 @@ int mvebu_mbus_save_cpu_target(u32 *store_addr)
        return mbus_state.soc->save_cpu_target(&mbus_state, store_addr);
 }
 
-static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = {
+static const struct mvebu_mbus_soc_data armada_370_mbus_data = {
        .num_wins            = 20,
-       .num_remappable_wins = 8,
        .has_mbus_bridge     = true,
-       .win_cfg_offset      = armada_370_xp_mbus_win_offset,
+       .win_cfg_offset      = armada_370_xp_mbus_win_cfg_offset,
+       .win_remap_offset    = generic_mbus_win_remap_8_offset,
+       .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
+       .show_cpu_target     = mvebu_sdram_debug_show_orion,
        .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
+};
+
+static const struct mvebu_mbus_soc_data armada_xp_mbus_data = {
+       .num_wins            = 20,
+       .has_mbus_bridge     = true,
+       .win_cfg_offset      = armada_370_xp_mbus_win_cfg_offset,
+       .win_remap_offset    = armada_xp_mbus_win_remap_offset,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
+       .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
 };
 
 static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
        .num_wins            = 8,
-       .num_remappable_wins = 4,
-       .win_cfg_offset      = orion_mbus_win_offset,
+       .win_cfg_offset      = generic_mbus_win_cfg_offset,
        .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
+       .win_remap_offset    = generic_mbus_win_remap_4_offset,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
 
 static const struct mvebu_mbus_soc_data dove_mbus_data = {
        .num_wins            = 8,
-       .num_remappable_wins = 4,
-       .win_cfg_offset      = orion_mbus_win_offset,
+       .win_cfg_offset      = generic_mbus_win_cfg_offset,
        .save_cpu_target     = mvebu_mbus_dove_save_cpu_target,
+       .win_remap_offset    = generic_mbus_win_remap_4_offset,
        .setup_cpu_target    = mvebu_mbus_dove_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_dove,
 };
@@ -653,36 +800,40 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = {
  */
 static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
        .num_wins            = 8,
-       .num_remappable_wins = 4,
-       .win_cfg_offset      = orion_mbus_win_offset,
+       .win_cfg_offset      = generic_mbus_win_cfg_offset,
        .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
+       .win_remap_offset    = generic_mbus_win_remap_4_offset,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
 
 static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
        .num_wins            = 8,
-       .num_remappable_wins = 2,
-       .win_cfg_offset      = orion_mbus_win_offset,
+       .win_cfg_offset      = generic_mbus_win_cfg_offset,
        .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
+       .win_remap_offset    = generic_mbus_win_remap_2_offset,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
 
 static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
        .num_wins            = 14,
-       .num_remappable_wins = 8,
-       .win_cfg_offset      = mv78xx0_mbus_win_offset,
+       .win_cfg_offset      = mv78xx0_mbus_win_cfg_offset,
        .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
+       .win_remap_offset    = generic_mbus_win_remap_8_offset,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
 
 static const struct of_device_id of_mvebu_mbus_ids[] = {
        { .compatible = "marvell,armada370-mbus",
-         .data = &armada_370_xp_mbus_data, },
+         .data = &armada_370_mbus_data, },
+       { .compatible = "marvell,armada375-mbus",
+         .data = &armada_xp_mbus_data, },
+       { .compatible = "marvell,armada380-mbus",
+         .data = &armada_xp_mbus_data, },
        { .compatible = "marvell,armadaxp-mbus",
-         .data = &armada_370_xp_mbus_data, },
+         .data = &armada_xp_mbus_data, },
        { .compatible = "marvell,kirkwood-mbus",
          .data = &kirkwood_mbus_data, },
        { .compatible = "marvell,dove-mbus",
@@ -789,15 +940,19 @@ static int mvebu_mbus_suspend(void)
        for (win = 0; win < s->soc->num_wins; win++) {
                void __iomem *addr = s->mbuswins_base +
                        s->soc->win_cfg_offset(win);
+               void __iomem *addr_rmp;
 
                s->wins[win].base = readl(addr + WIN_BASE_OFF);
                s->wins[win].ctrl = readl(addr + WIN_CTRL_OFF);
 
-               if (win >= s->soc->num_remappable_wins)
+               if (!mvebu_mbus_window_is_remappable(s, win))
                        continue;
 
-               s->wins[win].remap_lo = readl(addr + WIN_REMAP_LO_OFF);
-               s->wins[win].remap_hi = readl(addr + WIN_REMAP_HI_OFF);
+               addr_rmp = s->mbuswins_base +
+                       s->soc->win_remap_offset(win);
+
+               s->wins[win].remap_lo = readl(addr_rmp + WIN_REMAP_LO_OFF);
+               s->wins[win].remap_hi = readl(addr_rmp + WIN_REMAP_HI_OFF);
        }
 
        s->mbus_bridge_ctrl = readl(s->mbusbridge_base +
@@ -821,15 +976,19 @@ static void mvebu_mbus_resume(void)
        for (win = 0; win < s->soc->num_wins; win++) {
                void __iomem *addr = s->mbuswins_base +
                        s->soc->win_cfg_offset(win);
+               void __iomem *addr_rmp;
 
                writel(s->wins[win].base, addr + WIN_BASE_OFF);
                writel(s->wins[win].ctrl, addr + WIN_CTRL_OFF);
 
-               if (win >= s->soc->num_remappable_wins)
+               if (!mvebu_mbus_window_is_remappable(s, win))
                        continue;
 
-               writel(s->wins[win].remap_lo, addr + WIN_REMAP_LO_OFF);
-               writel(s->wins[win].remap_hi, addr + WIN_REMAP_HI_OFF);
+               addr_rmp = s->mbuswins_base +
+                       s->soc->win_remap_offset(win);
+
+               writel(s->wins[win].remap_lo, addr_rmp + WIN_REMAP_LO_OFF);
+               writel(s->wins[win].remap_hi, addr_rmp + WIN_REMAP_HI_OFF);
        }
 }
 
@@ -844,7 +1003,8 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
                                         phys_addr_t sdramwins_phys_base,
                                         size_t sdramwins_size,
                                         phys_addr_t mbusbridge_phys_base,
-                                        size_t mbusbridge_size)
+                                        size_t mbusbridge_size,
+                                        bool is_coherent)
 {
        int win;
 
@@ -876,6 +1036,10 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
 
        mbus->soc->setup_cpu_target(mbus);
 
+       if (is_coherent)
+               writel(UNIT_SYNC_BARRIER_ALL,
+                      mbus->mbuswins_base + UNIT_SYNC_BARRIER_OFF);
+
        register_syscore_ops(&mvebu_mbus_syscore_ops);
 
        return 0;
@@ -903,7 +1067,7 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
                        mbuswins_phys_base,
                        mbuswins_size,
                        sdramwins_phys_base,
-                       sdramwins_size, 0, 0);
+                       sdramwins_size, 0, 0, false);
 }
 
 #ifdef CONFIG_OF
@@ -1105,7 +1269,8 @@ int __init mvebu_mbus_dt_init(bool is_coherent)
                                     sdramwins_res.start,
                                     resource_size(&sdramwins_res),
                                     mbusbridge_res.start,
-                                    resource_size(&mbusbridge_res));
+                                    resource_size(&mbusbridge_res),
+                                    is_coherent);
        if (ret)
                return ret;
 
index fc01ec2..c062b61 100644 (file)
@@ -47,6 +47,9 @@ config SUN5I_HSTIMER
        select CLKSRC_MMIO
        bool
 
+config TEGRA_TIMER
+       bool
+
 config VT8500_TIMER
        bool
 
index 94d90b2..ba9ebd8 100644 (file)
@@ -27,7 +27,7 @@ obj-$(CONFIG_ARCH_U300)               += timer-u300.o
 obj-$(CONFIG_SUN4I_TIMER)      += sun4i_timer.o
 obj-$(CONFIG_SUN5I_HSTIMER)    += timer-sun5i.o
 obj-$(CONFIG_MESON6_TIMER)     += meson6_timer.o
-obj-$(CONFIG_ARCH_TEGRA)       += tegra20_timer.o
+obj-$(CONFIG_TEGRA_TIMER)      += tegra20_timer.o
 obj-$(CONFIG_VT8500_TIMER)     += vt8500_timer.o
 obj-$(CONFIG_ARCH_NSPIRE)      += zevio-timer.o
 obj-$(CONFIG_ARCH_BCM_MOBILE)  += bcm_kona_timer.o
index 011a336..c0d660f 100644 (file)
@@ -81,6 +81,7 @@ static const struct of_device_id car_match[] __initconst = {
        { .compatible = "nvidia,tegra30-car", },
        { .compatible = "nvidia,tegra114-car", },
        { .compatible = "nvidia,tegra124-car", },
+       { .compatible = "nvidia,tegra132-car", },
        {},
 };
 
index 8646fa9..4d2f71b 100644 (file)
@@ -56,7 +56,7 @@ struct tegra_fuse_info {
 
 static void __iomem *fuse_base;
 static struct clk *fuse_clk;
-static struct tegra_fuse_info *fuse_info;
+static const struct tegra_fuse_info *fuse_info;
 
 u32 tegra30_fuse_readl(const unsigned int offset)
 {
@@ -78,18 +78,18 @@ u32 tegra30_fuse_readl(const unsigned int offset)
        return val;
 }
 
-static struct tegra_fuse_info tegra30_info = {
+static const struct tegra_fuse_info tegra30_info = {
        .size                   = 0x2a4,
        .spare_bit              = 0x144,
        .speedo_idx             = SPEEDO_TEGRA30,
 };
 
-static struct tegra_fuse_info tegra114_info = {
+static const struct tegra_fuse_info tegra114_info = {
        .size                   = 0x2a0,
        .speedo_idx             = SPEEDO_TEGRA114,
 };
 
-static struct tegra_fuse_info tegra124_info = {
+static const struct tegra_fuse_info tegra124_info = {
        .size                   = 0x300,
        .speedo_idx             = SPEEDO_TEGRA124,
 };
@@ -182,6 +182,7 @@ static void __init legacy_fuse_init(void)
                fuse_info = &tegra114_info;
                break;
        case TEGRA124:
+       case TEGRA132:
                fuse_info = &tegra124_info;
                break;
        default:
index a2c0ceb..c956395 100644 (file)
 
 #define PMC_SCRATCH41                  0x140
 
+#define PMC_SENSOR_CTRL                        0x1b0
+#define PMC_SENSOR_CTRL_SCRATCH_WRITE  (1 << 2)
+#define PMC_SENSOR_CTRL_ENABLE_RST     (1 << 1)
+
 #define IO_DPD_REQ                     0x1b8
 #define  IO_DPD_REQ_CODE_IDLE          (0 << 30)
 #define  IO_DPD_REQ_CODE_OFF           (1 << 30)
 #define IO_DPD2_STATUS                 0x1c4
 #define SEL_DPD_TIM                    0x1c8
 
+#define PMC_SCRATCH54                  0x258
+#define PMC_SCRATCH54_DATA_SHIFT       8
+#define PMC_SCRATCH54_ADDR_SHIFT       0
+
+#define PMC_SCRATCH55                  0x25c
+#define PMC_SCRATCH55_RESET_TEGRA      (1 << 31)
+#define PMC_SCRATCH55_CNTRL_ID_SHIFT   27
+#define PMC_SCRATCH55_PINMUX_SHIFT     24
+#define PMC_SCRATCH55_16BITOP          (1 << 15)
+#define PMC_SCRATCH55_CHECKSUM_SHIFT   16
+#define PMC_SCRATCH55_I2CSLV1_SHIFT    0
+
 #define GPU_RG_CNTRL                   0x2d4
 
 struct tegra_pmc_soc {
@@ -88,6 +104,9 @@ struct tegra_pmc_soc {
        const char *const *powergates;
        unsigned int num_cpu_powergates;
        const u8 *cpu_powergates;
+
+       bool has_tsense_reset;
+       bool has_gpu_clamps;
 };
 
 /**
@@ -110,6 +129,7 @@ struct tegra_pmc_soc {
  * @powergates_lock: mutex for power gate register access
  */
 struct tegra_pmc {
+       struct device *dev;
        void __iomem *base;
        struct clk *clk;
 
@@ -225,11 +245,11 @@ int tegra_powergate_remove_clamping(int id)
                return -EINVAL;
 
        /*
-        * The Tegra124 GPU has a separate register (with different semantics)
-        * to remove clamps.
+        * On Tegra124 and later, the clamps for the GPU are controlled by a
+        * separate register (with different semantics).
         */
-       if (tegra_get_chip_id() == TEGRA124) {
-               if (id == TEGRA_POWERGATE_3D) {
+       if (id == TEGRA_POWERGATE_3D) {
+               if (pmc->soc->has_gpu_clamps) {
                        tegra_pmc_writel(0, GPU_RG_CNTRL);
                        return 0;
                }
@@ -703,6 +723,83 @@ static void tegra_pmc_init(struct tegra_pmc *pmc)
        tegra_pmc_writel(value, PMC_CNTRL);
 }
 
+void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
+{
+       static const char disabled[] = "emergency thermal reset disabled";
+       u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux;
+       struct device *dev = pmc->dev;
+       struct device_node *np;
+       u32 value, checksum;
+
+       if (!pmc->soc->has_tsense_reset)
+               goto out;
+
+       np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip");
+       if (!np) {
+               dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) {
+               dev_err(dev, "I2C controller ID missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,bus-addr", &pmu_addr)) {
+               dev_err(dev, "nvidia,bus-addr missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,reg-addr", &reg_addr)) {
+               dev_err(dev, "nvidia,reg-addr missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,reg-data", &reg_data)) {
+               dev_err(dev, "nvidia,reg-data missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
+               pinmux = 0;
+
+       value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+       value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
+       tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+
+       value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
+               (reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
+       tegra_pmc_writel(value, PMC_SCRATCH54);
+
+       value = PMC_SCRATCH55_RESET_TEGRA;
+       value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
+       value |= pinmux << PMC_SCRATCH55_PINMUX_SHIFT;
+       value |= pmu_addr << PMC_SCRATCH55_I2CSLV1_SHIFT;
+
+       /*
+        * Calculate checksum of SCRATCH54, SCRATCH55 fields. Bits 23:16 will
+        * contain the checksum and are currently zero, so they are not added.
+        */
+       checksum = reg_addr + reg_data + (value & 0xff) + ((value >> 8) & 0xff)
+               + ((value >> 24) & 0xff);
+       checksum &= 0xff;
+       checksum = 0x100 - checksum;
+
+       value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
+
+       tegra_pmc_writel(value, PMC_SCRATCH55);
+
+       value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+       value |= PMC_SENSOR_CTRL_ENABLE_RST;
+       tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+
+       dev_info(pmc->dev, "emergency thermal reset enabled\n");
+
+out:
+       of_node_put(np);
+       return;
+}
+
 static int tegra_pmc_probe(struct platform_device *pdev)
 {
        void __iomem *base = pmc->base;
@@ -728,8 +825,12 @@ static int tegra_pmc_probe(struct platform_device *pdev)
                return err;
        }
 
+       pmc->dev = &pdev->dev;
+
        tegra_pmc_init(pmc);
 
+       tegra_pmc_init_tsense_reset(pmc);
+
        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
                err = tegra_powergate_debugfs_init();
                if (err < 0)
@@ -739,7 +840,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
 static int tegra_pmc_suspend(struct device *dev)
 {
        tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
@@ -753,10 +854,11 @@ static int tegra_pmc_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
 
+#endif
+
 static const char * const tegra20_powergates[] = {
        [TEGRA_POWERGATE_CPU] = "cpu",
        [TEGRA_POWERGATE_3D] = "3d",
@@ -772,6 +874,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
        .powergates = tegra20_powergates,
        .num_cpu_powergates = 0,
        .cpu_powergates = NULL,
+       .has_tsense_reset = false,
+       .has_gpu_clamps = false,
 };
 
 static const char * const tegra30_powergates[] = {
@@ -803,6 +907,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
        .powergates = tegra30_powergates,
        .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
        .cpu_powergates = tegra30_cpu_powergates,
+       .has_tsense_reset = true,
+       .has_gpu_clamps = false,
 };
 
 static const char * const tegra114_powergates[] = {
@@ -838,6 +944,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
        .powergates = tegra114_powergates,
        .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
        .cpu_powergates = tegra114_cpu_powergates,
+       .has_tsense_reset = true,
+       .has_gpu_clamps = false,
 };
 
 static const char * const tegra124_powergates[] = {
@@ -879,6 +987,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
        .powergates = tegra124_powergates,
        .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
        .cpu_powergates = tegra124_cpu_powergates,
+       .has_tsense_reset = true,
+       .has_gpu_clamps = true,
 };
 
 static const struct of_device_id tegra_pmc_match[] = {
@@ -894,7 +1004,9 @@ static struct platform_driver tegra_pmc_driver = {
                .name = "tegra-pmc",
                .suppress_bind_attrs = true,
                .of_match_table = tegra_pmc_match,
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
                .pm = &tegra_pmc_pm_ops,
+#endif
        },
        .probe = tegra_pmc_probe,
 };
index 801c0ac..979d24a 100644 (file)
 #define VF610_PLL5_BYPASS              179
 #define VF610_PLL6_BYPASS              180
 #define VF610_PLL7_BYPASS              181
-#define VF610_CLK_END                  182
+#define VF610_CLK_SNVS                 182
+#define VF610_CLK_END                  183
 
 #endif /* __DT_BINDINGS_CLOCK_VF610_H */
index 8e12494..b5f7b5f 100644 (file)
@@ -21,6 +21,7 @@
 #define TEGRA30                0x30
 #define TEGRA114       0x35
 #define TEGRA124       0x40
+#define TEGRA132       0x13
 
 #define TEGRA_FUSE_SKU_CALIB_0 0xf0
 #define TEGRA30_FUSE_SATA_CALIB        0x124
index 30fe207..0390910 100644 (file)
@@ -17,7 +17,7 @@ enum tegra_suspend_mode {
        TEGRA_MAX_SUSPEND_MODE,
 };
 
-#ifdef CONFIG_PM_SLEEP
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
 enum tegra_suspend_mode
 tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);