diff options
78 files changed, 1558 insertions, 774 deletions
diff --git a/Documentation/arm/Marvell/README b/Documentation/arm/Marvell/README index 5a930c1..963ec44 100644 --- a/Documentation/arm/Marvell/README +++ b/Documentation/arm/Marvell/README @@ -83,14 +83,24 @@ EBU Armada family 88F6710 88F6707 88F6W11 + Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf + + Armada 375 Flavors: + 88F6720 + Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA_375_SoC-01_product_brief.pdf + + Armada 380/385 Flavors: + 88F6810 + 88F6820 + 88F6828 Armada XP Flavors: MV78230 MV78260 MV78460 NOTE: not to be confused with the non-SMP 78xx0 SoCs + Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf - Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf No public datasheet available. Core: Sheeva ARMv7 compatible diff --git a/Documentation/devicetree/bindings/arm/armada-375.txt b/Documentation/devicetree/bindings/arm/armada-375.txt new file mode 100644 index 0000000..867d0b8 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/armada-375.txt @@ -0,0 +1,9 @@ +Marvell Armada 375 Platforms Device Tree Bindings +------------------------------------------------- + +Boards with a SoC of the Marvell Armada 375 family shall have the +following property: + +Required root node property: + +compatible: must contain "marvell,armada375" diff --git a/Documentation/devicetree/bindings/arm/armada-38x.txt b/Documentation/devicetree/bindings/arm/armada-38x.txt new file mode 100644 index 0000000..11f2330 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/armada-38x.txt @@ -0,0 +1,10 @@ +Marvell Armada 38x Platforms Device Tree Bindings +------------------------------------------------- + +Boards with a SoC of the Marvell Armada 38x family shall have the +following property: + +Required root node property: + + - compatible: must contain either "marvell,armada380" or + "marvell,armada385" depending on the variant of the SoC being used. diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 9130435..333f4ae 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -180,7 +180,11 @@ nodes to be present and contain the properties described below. be one of: "spin-table" "psci" - # On ARM 32-bit systems this property is optional. + # On ARM 32-bit systems this property is optional and + can be one of: + "qcom,gcc-msm8660" + "qcom,kpss-acc-v1" + "qcom,kpss-acc-v2" - cpu-release-addr Usage: required for systems that have an "enable-method" @@ -191,6 +195,21 @@ nodes to be present and contain the properties described below. property identifying a 64-bit zero-initialised memory location. + - qcom,saw + Usage: required for systems that have an "enable-method" + property value of "qcom,kpss-acc-v1" or + "qcom,kpss-acc-v2" + Value type: <phandle> + Definition: Specifies the SAW[1] node associated with this CPU. + + - qcom,acc + Usage: required for systems that have an "enable-method" + property value of "qcom,kpss-acc-v1" or + "qcom,kpss-acc-v2" + Value type: <phandle> + Definition: Specifies the ACC[2] node associated with this CPU. + + Example 1 (dual-cluster big.LITTLE system 32-bit): cpus { @@ -382,3 +401,7 @@ cpus { cpu-release-addr = <0 0x20000000>; }; }; + +-- +[1] arm/msm/qcom,saw2.txt +[2] arm/msm/qcom,kpss-acc.txt diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt new file mode 100644 index 0000000..1333db9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt @@ -0,0 +1,30 @@ +Krait Processor Sub-system (KPSS) Application Clock Controller (ACC) + +The KPSS ACC provides clock, power domain, and reset control to a Krait CPU. +There is one ACC register region per CPU within the KPSS remapped region as +well as an alias register region that remaps accesses to the ACC associated +with the CPU accessing the region. + +PROPERTIES + +- compatible: + Usage: required + Value type: <string> + Definition: should be one of: + "qcom,kpss-acc-v1" + "qcom,kpss-acc-v2" + +- reg: + Usage: required + Value type: <prop-encoded-array> + Definition: the first element specifies the base address and size of + the register region. An optional second element specifies + the base address and size of the alias register region. + +Example: + + clock-controller@2088000 { + compatible = "qcom,kpss-acc-v2"; + reg = <0x02088000 0x1000>, + <0x02008000 0x1000>; + }; diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt b/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt new file mode 100644 index 0000000..1505fb8 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt @@ -0,0 +1,35 @@ +SPM AVS Wrapper 2 (SAW2) + +The SAW2 is a wrapper around the Subsystem Power Manager (SPM) and the +Adaptive Voltage Scaling (AVS) hardware. The SPM is a programmable +micro-controller that transitions a piece of hardware (like a processor or +subsystem) into and out of low power modes via a direct connection to +the PMIC. It can also be wired up to interact with other processors in the +system, notifying them when a low power state is entered or exited. + +PROPERTIES + +- compatible: + Usage: required + Value type: <string> + Definition: shall contain "qcom,saw2". A more specific value should be + one of: + "qcom,saw2-v1" + "qcom,saw2-v1.1" + "qcom,saw2-v2" + "qcom,saw2-v2.1" + +- reg: + Usage: required + Value type: <prop-encoded-array> + Definition: the first element specifies the base address and size of + the register region. An optional second element specifies + the base address and size of the alias register region. + + +Example: + + regulator@2099000 { + compatible = "qcom,saw2"; + reg = <0x02099000 0x1000>, <0x02009000 0x1000>; + }; diff --git a/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt b/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt index 081c6a7..d24ab2e 100644 --- a/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt @@ -1,12 +1,13 @@ MVEBU System Controller ----------------------- -MVEBU (Marvell SOCs: Armada 370/XP, Dove, mv78xx0, Kirkwood, Orion5x) +MVEBU (Marvell SOCs: Armada 370/375/XP, Dove, mv78xx0, Kirkwood, Orion5x) Required properties: - compatible: one of: - "marvell,orion-system-controller" - "marvell,armada-370-xp-system-controller" + - "marvell,armada-375-system-controller" - reg: Should contain system controller registers location and length. Example: diff --git a/Documentation/devicetree/bindings/arm/rockchip/pmu.txt b/Documentation/devicetree/bindings/arm/rockchip/pmu.txt new file mode 100644 index 0000000..3ee9b42 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/rockchip/pmu.txt @@ -0,0 +1,16 @@ +Rockchip power-management-unit: +------------------------------- + +The pmu is used to turn off and on different power domains of the SoCs +This includes the power to the CPU cores. + +Required node properties: +- compatible value : = "rockchip,rk3066-pmu"; +- reg : physical base address and the size of the registers window + +Example: + + pmu@20004000 { + compatible = "rockchip,rk3066-pmu"; + reg = <0x20004000 0x100>; + }; diff --git a/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt b/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt new file mode 100644 index 0000000..d9416fb --- /dev/null +++ b/Documentation/devicetree/bindings/arm/rockchip/smp-sram.txt @@ -0,0 +1,30 @@ +Rockchip SRAM for smp bringup: +------------------------------ + +Rockchip's smp-capable SoCs use the first part of the sram for the bringup +of the cores. Once the core gets powered up it executes the code that is +residing at the very beginning of the sram. + +Therefore a reserved section sub-node has to be added to the mmio-sram +declaration. + +Required sub-node properties: +- compatible : should be "rockchip,rk3066-smp-sram" + +The rest of the properties should follow the generic mmio-sram discription +found in ../../misc/sram.txt + +Example: + + sram: sram@10080000 { + compatible = "mmio-sram"; + reg = <0x10080000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + smp-sram@10080000 { + compatible = "rockchip,rk3066-smp-sram"; + reg = <0x10080000 0x50>; + }; + }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/cirrus,clps711x-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/cirrus,clps711x-intc.txt new file mode 100644 index 0000000..759339c --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/cirrus,clps711x-intc.txt @@ -0,0 +1,41 @@ +Cirrus Logic CLPS711X Interrupt Controller + +Required properties: + +- compatible: Should be "cirrus,clps711x-intc". +- reg: Specifies base physical address of the registers set. +- interrupt-controller: Identifies the node as an interrupt controller. +- #interrupt-cells: Specifies the number of cells needed to encode an + interrupt source. The value shall be 1. + +The interrupt sources are as follows: +ID Name Description +--------------------------- +1: BLINT Battery low (FIQ) +3: MCINT Media changed (FIQ) +4: CSINT CODEC sound +5: EINT1 External 1 +6: EINT2 External 2 +7: EINT3 External 3 +8: TC1OI TC1 under flow +9: TC2OI TC2 under flow +10: RTCMI RTC compare match +11: TINT 64Hz tick +12: UTXINT1 UART1 transmit FIFO half empty +13: URXINT1 UART1 receive FIFO half full +14: UMSINT UART1 modem status changed +15: SSEOTI SSI1 end of transfer +16: KBDINT Keyboard +17: SS2RX SSI2 receive FIFO half or greater full +18: SS2TX SSI2 transmit FIFO less than half empty +28: UTXINT2 UART2 transmit FIFO half empty +29: URXINT2 UART2 receive FIFO half full +32: DAIINT DAI interface (FIQ) + +Example: + intc: interrupt-controller { + compatible = "cirrus,clps711x-intc"; + reg = <0x80000000 0x4000>; + interrupt-controller; + #interrupt-cells = <1>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 85b3dd8..e4812f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1167,6 +1167,14 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained +ARM/QUALCOMM SUPPORT +M: Kumar Gala <galak@codeaurora.org> +M: David Brown <davidb@codeaurora.org> +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: arch/arm/mach-qcom/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git + ARM/RADISYS ENP2611 MACHINE SUPPORT M: Lennert Buytenhek <kernel@wantstofly.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 25a6b53..cbee116 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -390,8 +390,6 @@ config ARCH_CLPS711X select CPU_ARM720T select GENERIC_CLOCKEVENTS select MFD_SYSCON - select MULTI_IRQ_HANDLER - select SPARSE_IRQ help Support for Cirrus Logic 711x/721x/731x based boards. @@ -659,9 +657,8 @@ config ARCH_PXA help Support for Intel/Marvell's PXA2xx/PXA3xx processor line. -config ARCH_MSM_NODT - bool "Qualcomm MSM" - select ARCH_MSM +config ARCH_MSM + bool "Qualcomm MSM (non-multiplatform)" select ARCH_REQUIRE_GPIOLIB select COMMON_CLK select GENERIC_CLOCKEVENTS @@ -1016,6 +1013,8 @@ source "arch/arm/plat-pxa/Kconfig" source "arch/arm/mach-mmp/Kconfig" +source "arch/arm/mach-qcom/Kconfig" + source "arch/arm/mach-realview/Kconfig" source "arch/arm/mach-rockchip/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 0531da8..4491c7b 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -956,7 +956,7 @@ config DEBUG_STI_UART config DEBUG_MSM_UART bool - depends on ARCH_MSM + depends on ARCH_MSM || ARCH_QCOM config DEBUG_LL_INCLUDE string diff --git a/arch/arm/Makefile b/arch/arm/Makefile index a3c06dd..dd1bd7e 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -180,6 +180,7 @@ machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 machine-$(CONFIG_ARCH_ORION5X) += orion5x machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell machine-$(CONFIG_ARCH_PXA) += pxa +machine-$(CONFIG_ARCH_QCOM) += qcom machine-$(CONFIG_ARCH_REALVIEW) += realview machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip machine-$(CONFIG_ARCH_RPC) += rpc diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 0320303..4a89023 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -119,9 +119,6 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-cloudbox.dtb \ kirkwood-ts219-6282.dtb dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb -dtb-$(CONFIG_ARCH_MSM) += qcom-msm8660-surf.dtb \ - qcom-msm8960-cdp.dtb \ - qcom-apq8074-dragonboard.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \ armada-370-mirabox.dtb \ armada-370-netgear-rn102.dtb \ @@ -234,6 +231,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ dra7-evm.dtb dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb +dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \ + qcom-msm8960-cdp.dtb \ + qcom-apq8074-dragonboard.dtb dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ ste-hrefprev60-stuib.dtb \ ste-hrefprev60-tvk.dtb \ diff --git a/arch/arm/boot/dts/qcom-msm8660-surf.dts b/arch/arm/boot/dts/qcom-msm8660-surf.dts index 68a72f5..169bad9 100644 --- a/arch/arm/boot/dts/qcom-msm8660-surf.dts +++ b/arch/arm/boot/dts/qcom-msm8660-surf.dts @@ -1,63 +1,6 @@ -/dts-v1/; - -/include/ "skeleton.dtsi" - -#include <dt-bindings/clock/qcom,gcc-msm8660.h> +#include "qcom-msm8660.dtsi" / { model = "Qualcomm MSM8660 SURF"; compatible = "qcom,msm8660-surf", "qcom,msm8660"; - interrupt-parent = <&intc>; - - intc: interrupt-controller@2080000 { - compatible = "qcom,msm-8660-qgic"; - interrupt-controller; - #interrupt-cells = <3>; - reg = < 0x02080000 0x1000 >, - < 0x02081000 0x1000 >; - }; - - timer@2000000 { - compatible = "qcom,scss-timer", "qcom,msm-timer"; - interrupts = <1 0 0x301>, - <1 1 0x301>, - <1 2 0x301>; - reg = <0x02000000 0x100>; - clock-frequency = <27000000>, - <32768>; - cpu-offset = <0x40000>; - }; - - msmgpio: gpio@800000 { - compatible = "qcom,msm-gpio"; - reg = <0x00800000 0x4000>; - gpio-controller; - #gpio-cells = <2>; - ngpio = <173>; - interrupts = <0 16 0x4>; - interrupt-controller; - #interrupt-cells = <2>; - }; - - gcc: clock-controller@900000 { - compatible = "qcom,gcc-msm8660"; - #clock-cells = <1>; - #reset-cells = <1>; - reg = <0x900000 0x4000>; - }; - - serial@19c40000 { - compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; - reg = <0x19c40000 0x1000>, - <0x19c00000 0x1000>; - interrupts = <0 195 0x0>; - clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>; - clock-names = "core", "iface"; - }; - - qcom,ssbi@500000 { - compatible = "qcom,ssbi"; - reg = <0x500000 0x1000>; - qcom,controller-type = "pmic-arbiter"; - }; }; diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi new file mode 100644 index 0000000..69d6c4e --- /dev/null +++ b/arch/arm/boot/dts/qcom-msm8660.dtsi @@ -0,0 +1,63 @@ +/dts-v1/; + +/include/ "skeleton.dtsi" + +#include <dt-bindings/clock/qcom,gcc-msm8660.h> + +/ { + model = "Qualcomm MSM8660"; + compatible = "qcom,msm8660"; + interrupt-parent = <&intc>; + + intc: interrupt-controller@2080000 { + compatible = "qcom,msm-8660-qgic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = < 0x02080000 0x1000 >, + < 0x02081000 0x1000 >; + }; + + timer@2000000 { + compatible = "qcom,scss-timer", "qcom,msm-timer"; + interrupts = <1 0 0x301>, + <1 1 0x301>, + <1 2 0x301>; + reg = <0x02000000 0x100>; + clock-frequency = <27000000>, + <32768>; + cpu-offset = <0x40000>; + }; + + msmgpio: gpio@800000 { + compatible = "qcom,msm-gpio"; + reg = <0x00800000 0x4000>; + gpio-controller; + #gpio-cells = <2>; + ngpio = <173>; + interrupts = <0 16 0x4>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gcc: clock-controller@900000 { + compatible = "qcom,gcc-msm8660"; + #clock-cells = <1>; + #reset-cells = <1>; + reg = <0x900000 0x4000>; + }; + + serial@19c40000 { + compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; + reg = <0x19c40000 0x1000>, + <0x19c00000 0x1000>; + interrupts = <0 195 0x0>; + clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>; + clock-names = "core", "iface"; + }; + + qcom,ssbi@500000 { + compatible = "qcom,ssbi"; + reg = <0x500000 0x1000>; + qcom,controller-type = "pmic-arbiter"; + }; +}; diff --git a/arch/arm/boot/dts/qcom-msm8960-cdp.dts b/arch/arm/boot/dts/qcom-msm8960-cdp.dts index 7c30de4..a58fb88 100644 --- a/arch/arm/boot/dts/qcom-msm8960-cdp.dts +++ b/arch/arm/boot/dts/qcom-msm8960-cdp.dts @@ -1,70 +1,6 @@ -/dts-v1/; - -/include/ "skeleton.dtsi" - -#include <dt-bindings/clock/qcom,gcc-msm8960.h> +#include "qcom-msm8960.dtsi" / { model = "Qualcomm MSM8960 CDP"; compatible = "qcom,msm8960-cdp", "qcom,msm8960"; - interrupt-parent = <&intc>; - - intc: interrupt-controller@2000000 { - compatible = "qcom,msm-qgic2"; - interrupt-controller; - #interrupt-cells = <3>; - reg = < 0x02000000 0x1000 >, - < 0x02002000 0x1000 >; - }; - - timer@200a000 { - compatible = "qcom,kpss-timer", "qcom,msm-timer"; - interrupts = <1 1 0x301>, - <1 2 0x301>, - <1 3 0x301>; - reg = <0x0200a000 0x100>; - clock-frequency = <27000000>, - <32768>; - cpu-offset = <0x80000>; - }; - - msmgpio: gpio@800000 { - compatible = "qcom,msm-gpio"; - gpio-controller; - #gpio-cells = <2>; - ngpio = <150>; - interrupts = <0 16 0x4>; - interrupt-controller; - #interrupt-cells = <2>; - reg = <0x800000 0x4000>; - }; - - gcc: clock-controller@900000 { - compatible = "qcom,gcc-msm8960"; - #clock-cells = <1>; - #reset-cells = <1>; - reg = <0x900000 0x4000>; - }; - - clock-controller@4000000 { - compatible = "qcom,mmcc-msm8960"; - reg = <0x4000000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - - serial@16440000 { - compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; - reg = <0x16440000 0x1000>, - <0x16400000 0x1000>; - interrupts = <0 154 0x0>; - clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>; - clock-names = "core", "iface"; - }; - - qcom,ssbi@500000 { - compatible = "qcom,ssbi"; - reg = <0x500000 0x1000>; - qcom,controller-type = "pmic-arbiter"; - }; }; diff --git a/arch/arm/boot/dts/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom-msm8960.dtsi new file mode 100644 index 0000000..3a9c3ca --- /dev/null +++ b/arch/arm/boot/dts/qcom-msm8960.dtsi @@ -0,0 +1,76 @@ +/dts-v1/; + +/include/ "skeleton.dtsi" + +#include <dt-bindings/clock/qcom,gcc-msm8960.h> + +/ { + model = "Qualcomm MSM8960"; + compatible = "qcom,msm8960"; + interrupt-parent = <&intc>; + + cpu-pmu { + compatible = "qcom,krait-pmu"; + interrupts = <1 10 0x304>; + qcom,no-pc-write; + }; + + intc: interrupt-controller@2000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <3>; + reg = < 0x02000000 0x1000 >, + < 0x02002000 0x1000 >; + }; + + timer@200a000 { + compatible = "qcom,kpss-timer", "qcom,msm-timer"; + interrupts = <1 1 0x301>, + <1 2 0x301>, + <1 3 0x301>; + reg = <0x0200a000 0x100>; + clock-frequency = <27000000>, + <32768>; + cpu-offset = <0x80000>; + }; + + msmgpio: gpio@800000 { + compatible = "qcom,msm-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpio = <150>; + interrupts = <0 16 0x4>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x800000 0x4000>; + }; + + gcc: clock-controller@900000 { + compatible = "qcom,gcc-msm8960"; + #clock-cells = <1>; + #reset-cells = <1>; + reg = <0x900000 0x4000>; + }; + + clock-controller@4000000 { + compatible = "qcom,mmcc-msm8960"; + reg = <0x4000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + serial@16440000 { + compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; + reg = <0x16440000 0x1000>, + <0x16400000 0x1000>; + interrupts = <0 154 0x0>; + clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>; + clock-names = "core", "iface"; + }; + + qcom,ssbi@500000 { + compatible = "qcom,ssbi"; + reg = <0x500000 0x1000>; + qcom,controller-type = "pmic-arbiter"; + }; +}; diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index 9e5dadb..1eff413 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -9,6 +9,11 @@ compatible = "qcom,msm8974"; interrupt-parent = <&intc>; + cpu-pmu { + compatible = "qcom,krait-pmu"; + interrupts = <1 7 0xf04>; + }; + soc: soc { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi index be5d2b0..4d4dfbb 100644 --- a/arch/arm/boot/dts/rk3066a.dtsi +++ b/arch/arm/boot/dts/rk3066a.dtsi @@ -64,6 +64,19 @@ clock-names = "timer", "pclk"; }; + sram: sram@10080000 { + compatible = "mmio-sram"; + reg = <0x10080000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x10080000 0x10000>; + + smp-sram@0 { + compatible = "rockchip,rk3066-smp-sram"; + reg = <0x0 0x50>; + }; + }; + pinctrl@20008000 { compatible = "rockchip,rk3066a-pinctrl"; reg = <0x20008000 0x150>; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 1a26b03..bb36596 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -60,6 +60,19 @@ interrupts = <GIC_PPI 13 0xf04>; }; + sram: sram@10080000 { + compatible = "mmio-sram"; + reg = <0x10080000 0x8000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x10080000 0x8000>; + + smp-sram@0 { + compatible = "rockchip,rk3066-smp-sram"; + reg = <0x0 0x50>; + }; + }; + pinctrl@20008000 { compatible = "rockchip,rk3188-pinctrl"; reg = <0x20008000 0xa0>, diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi index 0fcbcfd..26e5a96 100644 --- a/arch/arm/boot/dts/rk3xxx.dtsi +++ b/arch/arm/boot/dts/rk3xxx.dtsi @@ -26,6 +26,16 @@ compatible = "simple-bus"; ranges; + scu@1013c000 { + compatible = "arm,cortex-a9-scu"; + reg = <0x1013c000 0x100>; + }; + + pmu@20004000 { + compatible = "rockchip,rk3066-pmu"; + reg = <0x20004000 0x100>; + }; + gic: interrupt-controller@1013d000 { compatible = "arm,cortex-a9-gic"; interrupt-controller; diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 3a0b53d..364ba38 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -28,6 +28,7 @@ CONFIG_ARCH_OMAP3=y CONFIG_ARCH_OMAP4=y CONFIG_SOC_OMAP5=y CONFIG_SOC_AM33XX=y +CONFIG_SOC_AM43XX=y CONFIG_SOC_DRA7XX=y CONFIG_ARM_THUMBEE=y CONFIG_ARM_ERRATA_411920=y diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 22a3b9b..772435b 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -114,6 +114,15 @@ struct smp_operations { #endif }; +struct of_cpu_method { + const char *method; + struct smp_operations *ops; +}; + +#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \ + static const struct of_cpu_method __cpu_method_of_table_##name \ + __used __section(__cpu_method_of_table) \ + = { .method = _method, .ops = _ops } /* * set platform specific SMP operations */ diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index f751714..c7419a5 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -18,6 +18,7 @@ #include <linux/of_fdt.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/smp.h> #include <asm/cputype.h> #include <asm/setup.h> @@ -63,6 +64,34 @@ void __init arm_dt_memblock_reserve(void) } } +#ifdef CONFIG_SMP +extern struct of_cpu_method __cpu_method_of_table_begin[]; +extern struct of_cpu_method __cpu_method_of_table_end[]; + +static int __init set_smp_ops_by_method(struct device_node *node) +{ + const char *method; + struct of_cpu_method *m = __cpu_method_of_table_begin; + + if (of_property_read_string(node, "enable-method", &method)) + return 0; + + for (; m < __cpu_method_of_table_end; m++) + if (!strcmp(m->method, method)) { + smp_set_ops(m->ops); + return 1; + } + + return 0; +} +#else +static inline int set_smp_ops_by_method(struct device_node *node) +{ + return 1; +} +#endif + + /* * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree * and builds the cpu logical map array containing MPIDR values related to @@ -79,6 +108,7 @@ void __init arm_dt_init_cpu_maps(void) * read as 0. */ struct device_node *cpu, *cpus; + int found_method = 0; u32 i, j, cpuidx = 1; u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0; @@ -150,8 +180,18 @@ void __init arm_dt_init_cpu_maps(void) } tmp_map[i] = hwid; + + if (!found_method) + found_method = set_smp_ops_by_method(cpu); } + /* + * Fallback to an enable-method in the cpus node if nothing found in + * a cpu node. + */ + if (!found_method) + set_smp_ops_by_method(cpus); + if (!bootcpu_valid) { pr_warn("DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n"); return; diff --git a/arch/arm/mach-clps711x/board-autcpu12.c b/arch/arm/mach-clps711x/board-autcpu12.c index f8d71a8..eb945b2 100644 --- a/arch/arm/mach-clps711x/board-autcpu12.c +++ b/arch/arm/mach-clps711x/board-autcpu12.c @@ -265,14 +265,12 @@ static void __init autcpu12_init_late(void) MACHINE_START(AUTCPU12, "autronix autcpu12") /* Maintainer: Thomas Gleixner */ .atag_offset = 0x20000, - .nr_irqs = CLPS711X_NR_IRQS, .map_io = clps711x_map_io, .init_early = clps711x_init_early, .init_irq = clps711x_init_irq, .init_time = clps711x_timer_init, .init_machine = autcpu12_init, .init_late = autcpu12_init_late, - .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, MACHINE_END diff --git a/arch/arm/mach-clps711x/board-cdb89712.c b/arch/arm/mach-clps711x/board-cdb89712.c index a9e38c6..e261a47 100644 --- a/arch/arm/mach-clps711x/board-cdb89712.c +++ b/arch/arm/mach-clps711x/board-cdb89712.c @@ -139,12 +139,10 @@ static void __init cdb89712_init(void) MACHINE_START(CDB89712, "Cirrus-CDB89712") /* Maintainer: Ray Lehtiniemi */ .atag_offset = 0x100, - .nr_irqs = CLPS711X_NR_IRQS, .map_io = clps711x_map_io, .init_early = clps711x_init_early, .init_irq = clps711x_init_irq, .init_time = clps711x_timer_init, .init_machine = cdb89712_init, - .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, MACHINE_END diff --git a/arch/arm/mach-clps711x/board-clep7312.c b/arch/arm/mach-clps711x/board-clep7312.c index b476424..221b9de 100644 --- a/arch/arm/mach-clps711x/board-clep7312.c +++ b/arch/arm/mach-clps711x/board-clep7312.c @@ -36,12 +36,10 @@ fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi) MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") /* Maintainer: Nobody */ .atag_offset = 0x0100, - .nr_irqs = CLPS711X_NR_IRQS, .fixup = fixup_clep7312, .map_io = clps711x_map_io, .init_early = clps711x_init_early, .init_irq = clps711x_init_irq, .init_time = clps711x_timer_init, - .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, MACHINE_END diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c index fe6184e..0776098 100644 --- a/arch/arm/mach-clps711x/board-edb7211.c +++ b/arch/arm/mach-clps711x/board-edb7211.c @@ -177,7 +177,6 @@ static void __init edb7211_init_late(void) MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") /* Maintainer: Jon McClintock */ .atag_offset = VIDEORAM_SIZE + 0x100, - .nr_irqs = CLPS711X_NR_IRQS, .fixup = fixup_edb7211, .reserve = edb7211_reserve, .map_io = clps711x_map_io, @@ -186,6 +185,5 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") .init_time = clps711x_timer_init, .init_machine = edb7211_init, .init_late = edb7211_init_late, - .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, MACHINE_END diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c index dd81b06..67b7337 100644 --- a/arch/arm/mach-clps711x/board-p720t.c +++ b/arch/arm/mach-clps711x/board-p720t.c @@ -363,7 +363,6 @@ static void __init p720t_init_late(void) MACHINE_START(P720T, "ARM-Prospector720T") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .atag_offset = 0x100, - .nr_irqs = CLPS711X_NR_IRQS, .fixup = fixup_p720t, .map_io = clps711x_map_io, .init_early = clps711x_init_early, @@ -371,6 +370,5 @@ MACHINE_START(P720T, "ARM-Prospector720T") .init_time = clps711x_timer_init, .init_machine = p720t_init, .init_late = p720t_init_late, - .handle_irq = clps711x_handle_irq, .restart = clps711x_restart, MACHINE_END diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index a193591..aee81fa 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c @@ -31,14 +31,14 @@ #include <linux/clk-provider.h> #include <linux/sched_clock.h> -#include <asm/exception.h> -#include <asm/mach/irq.h> #include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/system_misc.h> #include <mach/hardware.h> +#include "common.h" + static struct clk *clk_pll, *clk_bus, *clk_uart, *clk_timerl, *clk_timerh, *clk_tint, *clk_spi; @@ -59,204 +59,9 @@ void __init clps711x_map_io(void) iotable_init(clps711x_io_desc, ARRAY_SIZE(clps711x_io_desc)); } -static void int1_mask(struct irq_data *d) -{ - u32 intmr1; - - intmr1 = clps_readl(INTMR1); - intmr1 &= ~(1 << d->irq); - clps_writel(intmr1, INTMR1); -} - -static void int1_eoi(struct irq_data *d) -{ - switch (d->irq) { - case IRQ_CSINT: clps_writel(0, COEOI); break; - case IRQ_TC1OI: clps_writel(0, TC1EOI); break; - case IRQ_TC2OI: clps_writel(0, TC2EOI); break; - case IRQ_RTCMI: clps_writel(0, RTCEOI); break; - case IRQ_TINT: clps_writel(0, TEOI); break; - case IRQ_UMSINT: clps_writel(0, UMSEOI); break; - } -} - -static void int1_unmask(struct irq_data *d) -{ - u32 intmr1; - - intmr1 = clps_readl(INTMR1); - intmr1 |= 1 << d->irq; - clps_writel(intmr1, INTMR1); -} - -static struct irq_chip int1_chip = { - .name = "Interrupt Vector 1", - .irq_eoi = int1_eoi, - .irq_mask = int1_mask, - .irq_unmask = int1_unmask, -}; - -static void int2_mask(struct irq_data *d) -{ - u32 intmr2; - - intmr2 = clps_readl(INTMR2); - intmr2 &= ~(1 << (d->irq - 16)); - clps_writel(intmr2, INTMR2); -} - -static void int2_eoi(struct irq_data *d) -{ - switch (d->irq) { - case IRQ_KBDINT: clps_writel(0, KBDEOI); break; - } -} - -static void int2_unmask(struct irq_data *d) -{ - u32 intmr2; - - intmr2 = clps_readl(INTMR2); - intmr2 |= 1 << (d->irq - 16); - clps_writel(intmr2, INTMR2); -} - -static struct irq_chip int2_chip = { - .name = "Interrupt Vector 2", - .irq_eoi = int2_eoi, - .irq_mask = int2_mask, - .irq_unmask = int2_unmask, -}; - -static void int3_mask(struct irq_data *d) -{ - u32 intmr3; - - intmr3 = clps_readl(INTMR3); - intmr3 &= ~(1 << (d->irq - 32)); - clps_writel(intmr3, INTMR3); -} - -static void int3_unmask(struct irq_data *d) -{ - u32 intmr3; - - intmr3 = clps_readl(INTMR3); - intmr3 |= 1 << (d->irq - 32); - clps_writel(intmr3, INTMR3); -} - -static struct irq_chip int3_chip = { - .name = "Interrupt Vector 3", - .irq_mask = int3_mask, - .irq_unmask = int3_unmask, -}; - -static struct { - int nr; - struct irq_chip *chip; - irq_flow_handler_t handle; -} clps711x_irqdescs[] __initdata = { - { IRQ_CSINT, &int1_chip, handle_fasteoi_irq, }, - { IRQ_EINT1, &int1_chip, handle_level_irq, }, - { IRQ_EINT2, &int1_chip, handle_level_irq, }, - { IRQ_EINT3, &int1_chip, handle_level_irq, }, - { IRQ_TC1OI, &int1_chip, handle_fasteoi_irq, }, - { IRQ_TC2OI, &int1_chip, handle_fasteoi_irq, }, - { IRQ_RTCMI, &int1_chip, handle_fasteoi_irq, }, - { IRQ_TINT, &int1_chip, handle_fasteoi_irq, }, - { IRQ_UTXINT1, &int1_chip, handle_level_irq, }, - { IRQ_URXINT1, &int1_chip, handle_level_irq, }, - { IRQ_UMSINT, &int1_chip, handle_fasteoi_irq, }, - { IRQ_SSEOTI, &int1_chip, handle_level_irq, }, - { IRQ_KBDINT, &int2_chip, handle_fasteoi_irq, }, - { IRQ_SS2RX, &int2_chip, handle_level_irq, }, - { IRQ_SS2TX, &int2_chip, handle_level_irq, }, - { IRQ_UTXINT2, &int2_chip, handle_level_irq, }, - { IRQ_URXINT2, &int2_chip, handle_level_irq, }, -}; - void __init clps711x_init_irq(void) { - unsigned int i; - - /* Disable interrupts */ - clps_writel(0, INTMR1); - clps_writel(0, INTMR2); - clps_writel(0, INTMR3); - - /* Clear down any pending interrupts */ - clps_writel(0, BLEOI); - clps_writel(0, MCEOI); - clps_writel(0, COEOI); - clps_writel(0, TC1EOI); - clps_writel(0, TC2EOI); - clps_writel(0, RTCEOI); - clps_writel(0, TEOI); - clps_writel(0, UMSEOI); - clps_writel(0, KBDEOI); - clps_writel(0, SRXEOF); - clps_writel(0xffffffff, DAISR); - - for (i = 0; i < ARRAY_SIZE(clps711x_irqdescs); i++) { - irq_set_chip_and_handler(clps711x_irqdescs[i].nr, - clps711x_irqdescs[i].chip, - clps711x_irqdescs[i].handle); - set_irq_flags(clps711x_irqdescs[i].nr, - IRQF_VALID | IRQF_PROBE); - } - - if (IS_ENABLED(CONFIG_FIQ)) { - init_FIQ(0); - irq_set_chip_and_handler(IRQ_DAIINT, &int3_chip, - handle_bad_irq); - set_irq_flags(IRQ_DAIINT, - IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN); - } -} - -static inline u32 fls16(u32 x) -{ - u32 r = 15; - - if (!(x & 0xff00)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf000)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc000)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x8000)) - r--; - - return r; -} - -asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs) -{ - do { - u32 irqstat; - void __iomem *base = CLPS711X_VIRT_BASE; - - irqstat = readw_relaxed(base + INTSR1) & - readw_relaxed(base + INTMR1); - if (irqstat) - handle_IRQ(fls16(irqstat), regs); - - irqstat = readw_relaxed(base + INTSR2) & - readw_relaxed(base + INTMR2); - if (irqstat) { - handle_IRQ(fls16(irqstat) + 16, regs); - continue; - } - - break; - } while (1); + clps711x_intc_init(CLPS711X_PHYS_BASE, SZ_16K); } static u64 notrace clps711x_sched_clock_read(void) diff --git a/arch/arm/mach-clps711x/common.h b/arch/arm/mach-clps711x/common.h index 9a6767b..7489139 100644 --- a/arch/arm/mach-clps711x/common.h +++ b/arch/arm/mach-clps711x/common.h @@ -6,13 +6,14 @@ #include <linux/reboot.h> -#define CLPS711X_NR_IRQS (33) #define CLPS711X_NR_GPIO (4 * 8 + 3) #define CLPS711X_GPIO(prt, bit) ((prt) * 8 + (bit)) extern void clps711x_map_io(void); extern void clps711x_init_irq(void); extern void clps711x_timer_init(void); -extern void clps711x_handle_irq(struct pt_regs *regs); extern void clps711x_restart(enum reboot_mode mode, const char *cmd); extern void clps711x_init_early(void); + +/* drivers/irqchip/irq-clps711x.c */ +void clps711x_intc_init(phys_addr_t, resource_size_t); diff --git a/arch/arm/mach-clps711x/include/mach/clps711x.h b/arch/arm/mach-clps711x/include/mach/clps711x.h index 0286f4b..eb052a1 100644 --- a/arch/arm/mach-clps711x/include/mach/clps711x.h +++ b/arch/arm/mach-clps711x/include/mach/clps711x.h @@ -40,8 +40,6 @@ #define MEMCFG1 (0x0180) #define MEMCFG2 (0x01c0) #define DRFPR (0x0200) -#define INTSR1 (0x0240) -#define INTMR1 (0x0280) #define LCDCON (0x02c0) #define TC1D (0x0300) #define TC2D (0x0340) @@ -55,28 +53,16 @@ #define PALLSW (0x0540) #define PALMSW (0x0580) #define STFCLR (0x05c0) -#define BLEOI (0x0600) -#define MCEOI (0x0640) -#define TEOI (0x0680) -#define TC1EOI (0x06c0) -#define TC2EOI (0x0700) -#define RTCEOI (0x0740) -#define UMSEOI (0x0780) -#define COEOI (0x07c0) #define HALT (0x0800) #define STDBY (0x0840) #define FBADDR (0x1000) #define SYSCON2 (0x1100) #define SYSFLG2 (0x1140) -#define INTSR2 (0x1240) -#define INTMR2 (0x1280) #define UARTDR2 (0x1480) #define UBRLCR2 (0x14c0) #define SS2DR (0x1500) -#define SRXEOF (0x1600) #define SS2POP (0x16c0) -#define KBDEOI (0x1700) #define DAIR (0x2000) #define DAIDR0 (0x2040) @@ -84,8 +70,6 @@ #define DAIDR2 (0x20c0) #define DAISR (0x2100) #define SYSCON3 (0x2200) -#define INTSR3 (0x2240) -#define INTMR3 (0x2280) #define LEDFLSH (0x22c0) #define SDCONF (0x2300) #define SDRFPR (0x2340) diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 9625cf3..a7f959e 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -1,50 +1,9 @@ -config ARCH_MSM - bool - -config ARCH_MSM_DT - bool "Qualcomm MSM DT Support" if ARCH_MULTI_V7 - select ARCH_MSM - select ARCH_REQUIRE_GPIOLIB - select CLKSRC_OF - select GENERIC_CLOCKEVENTS - help - Support for Qualcomm's devicetree based MSM systems. - if ARCH_MSM -menu "Qualcomm MSM SoC Selection" - depends on ARCH_MSM_DT - -config ARCH_MSM8X60 - bool "Enable support for MSM8X60" - select ARM_GIC - select CPU_V7 - select HAVE_SMP - select MSM_SCM if SMP - select MSM_TIMER - -config ARCH_MSM8960 - bool "Enable support for MSM8960" - select ARM_GIC - select CPU_V7 - select HAVE_SMP - select MSM_SCM if SMP - select MSM_TIMER - -config ARCH_MSM8974 - bool "Enable support for MSM8974" - select ARM_GIC - select CPU_V7 - select HAVE_ARM_ARCH_TIMER - select HAVE_SMP - select MSM_SCM if SMP - -endmenu - choice prompt "Qualcomm MSM SoC Type" default ARCH_MSM7X00A - depends on ARCH_MSM_NODT + depends on ARCH_MSM config ARCH_MSM7X00A bool "MSM7x00A / MSM7x01A" @@ -54,7 +13,7 @@ config ARCH_MSM7X00A select MACH_TROUT if !MACH_HALIBUT select MSM_PROC_COMM select MSM_SMD - select MSM_TIMER + select CLKSRC_QCOM select MSM_SMD_PKG3 config ARCH_MSM7X30 @@ -66,7 +25,7 @@ config ARCH_MSM7X30 select MSM_GPIOMUX select MSM_PROC_COMM select MSM_SMD - select MSM_TIMER + select CLKSRC_QCOM select MSM_VIC config ARCH_QSD8X50 @@ -78,7 +37,7 @@ config ARCH_QSD8X50 select MSM_GPIOMUX select MSM_PROC_COMM select MSM_SMD - select MSM_TIMER + select CLKSRC_QCOM select MSM_VIC endchoice @@ -99,7 +58,7 @@ config MSM_VIC bool menu "Qualcomm MSM Board Type" - depends on ARCH_MSM_NODT + depends on ARCH_MSM config MACH_HALIBUT depends on ARCH_MSM @@ -153,7 +112,4 @@ config MSM_GPIOMUX config MSM_SCM bool -config MSM_TIMER - bool - endif diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 8e307a1..27c078a 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -1,4 +1,3 @@ -obj-$(CONFIG_MSM_TIMER) += timer.o obj-$(CONFIG_MSM_PROC_COMM) += clock.o obj-$(CONFIG_MSM_VIC) += irq-vic.o @@ -14,18 +13,11 @@ obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o obj-$(CONFIG_MSM_SMD) += last_radio_log.o -obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o - -CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) - -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_SMP) += headsmp.o platsmp.o obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o -obj-$(CONFIG_ARCH_MSM_DT) += board-dt.o obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h index 33c7725..572479a 100644 --- a/arch/arm/mach-msm/common.h +++ b/arch/arm/mach-msm/common.h @@ -23,9 +23,6 @@ extern void msm_map_qsd8x50_io(void); extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size, unsigned int mtype, void *caller); -extern struct smp_operations msm_smp_ops; -extern void msm_cpu_die(unsigned int cpu); - struct msm_mmc_platform_data; extern void msm_add_devices(void); diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S deleted file mode 100644 index 6c62c3f..0000000 --- a/arch/arm/mach-msm/headsmp.S +++ /dev/null @@ -1,39 +0,0 @@ -/* - * linux/arch/arm/mach-realview/headsmp.S - * - * Copyright (c) 2003 ARM Limited - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/linkage.h> -#include <linux/init.h> - -/* - * MSM specific entry point for secondary CPUs. This provides - * a "holding pen" into which all secondary cores are held until we're - * ready for them to initialise. - */ -ENTRY(msm_secondary_startup) - mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 - adr r4, 1f - ldmia r4, {r5, r6} - sub r4, r4, r5 - add r6, r6, r4 -pen: ldr r7, [r6] - cmp r7, r0 - bne pen - - /* - * we've been released from the holding pen: secondary_stack - * should now contain the SVC stack for this core - */ - b secondary_startup -ENDPROC(msm_secondary_startup) - - .align -1: .long . - .long pen_release diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c deleted file mode 100644 index 326a872..0000000 --- a/arch/arm/mach-msm/hotplug.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/smp.h> - -#include <asm/smp_plat.h> - -#include "common.h" - -static inline void cpu_enter_lowpower(void) -{ -} - -static inline void cpu_leave_lowpower(void) -{ -} - -static inline void platform_do_lowpower(unsigned int cpu) -{ - /* Just enter wfi for now. TODO: Properly shut off the cpu. */ - for (;;) { - /* - * here's the WFI - */ - asm("wfi" - : - : - : "memory", "cc"); - - if (pen_release == cpu_logical_map(cpu)) { - /* - * OK, proper wakeup, we're done - */ - break; - } - - /* - * getting here, means that we have come out of WFI without - * having been woken up - this shouldn't happen - * - * The trouble is, letting people know about this is not really - * possible, since we are currently running incoherently, and - * therefore cannot safely call printk() or anything else - */ - pr_debug("CPU%u: spurious wakeup call\n", cpu); - } -} - -/* - * platform-specific code to shutdown a CPU - * - * Called with IRQs disabled - */ -void __ref msm_cpu_die(unsigned int cpu) -{ - /* - * we're ready for shutdown now, so do it - */ - cpu_enter_lowpower(); - platform_do_lowpower(cpu); - - /* - * bring this CPU back into the world of cache - * coherency, and then restore interrupts - */ - cpu_leave_lowpower(); -} diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c deleted file mode 100644 index f10a1f5..0000000 --- a/arch/arm/mach-msm/platsmp.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/jiffies.h> -#include <linux/smp.h> -#include <linux/io.h> - -#include <asm/cacheflush.h> -#include <asm/cputype.h> -#include <asm/mach-types.h> -#include <asm/smp_plat.h> - -#include "scm-boot.h" -#include "common.h" - -#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0 -#define SCSS_CPU1CORE_RESET 0xD80 -#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 - -extern void msm_secondary_startup(void); - -static DEFINE_SPINLOCK(boot_lock); - -static inline int get_core_count(void) -{ - /* 1 + the PART[1:0] field of MIDR */ - return ((read_cpuid_id() >> 4) & 3) + 1; -} - -static void msm_secondary_init(unsigned int cpu) -{ - /* - * let the primary processor know we're out of the - * pen, then head off into the C entry point - */ - pen_release = -1; - smp_wmb(); - - /* - * Synchronise with the boot thread. - */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); -} - -static void prepare_cold_cpu(unsigned int cpu) -{ - int ret; - ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup), - SCM_FLAG_COLDBOOT_CPU1); - if (ret == 0) { - void __iomem *sc1_base_ptr; - sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2); - if (sc1_base_ptr) { - writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL); - writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET); - writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP); - iounmap(sc1_base_ptr); - } - } else - printk(KERN_DEBUG "Failed to set secondary core boot " - "address\n"); -} - -static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - unsigned long timeout; - static int cold_boot_done; - - /* Only need to bring cpu out of reset this way once */ - if (cold_boot_done == false) { - prepare_cold_cpu(cpu); - cold_boot_done = true; - } - - /* - * set synchronisation state between this boot processor - * and the secondary one - */ - spin_lock(&boot_lock); - - /* - * The secondary processor is waiting to be released from - * the holding pen - release it, then wait for it to flag - * that it has been released by resetting pen_release. - * - * Note that "pen_release" is the hardware CPU ID, whereas - * "cpu" is Linux's internal ID. - */ - pen_release = cpu_logical_map(cpu); - sync_cache_w(&pen_release); - - /* - * Send the secondary CPU a soft interrupt, thereby causing - * the boot monitor to read the system wide flags register, - * and branch to the address found there. - */ - arch_send_wakeup_ipi_mask(cpumask_of(cpu)); - - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) { - smp_rmb(); - if (pen_release == -1) - break; - - udelay(10); - } - - /* - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ - spin_unlock(&boot_lock); - - return pen_release != -1 ? -ENOSYS : 0; -} - -/* - * Initialise the CPU possible map early - this describes the CPUs - * which may be present or become present in the system. The msm8x60 - * does not support the ARM SCU, so just set the possible cpu mask to - * NR_CPUS. - */ -static void __init msm_smp_init_cpus(void) -{ - unsigned int i, ncores = get_core_count(); - - if (ncores > nr_cpu_ids) { - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; - } - - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); -} - -static void __init msm_smp_prepare_cpus(unsigned int max_cpus) -{ -} - -struct smp_operations msm_smp_ops __initdata = { - .smp_init_cpus = msm_smp_init_cpus, - .smp_prepare_cpus = msm_smp_prepare_cpus, - .smp_secondary_init = msm_secondary_init, - .smp_boot_secondary = msm_boot_secondary, -#ifdef CONFIG_HOTPLUG_CPU - .cpu_die = msm_cpu_die, -#endif -}; diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 875a352..f961ae4 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -16,25 +16,54 @@ if ARCH_MVEBU menu "Marvell SOC with device tree" -config MACH_ARMADA_370_XP +config MACH_MVEBU_V7 bool select ARMADA_370_XP_TIMER select CACHE_L2X0 - select CPU_PJ4B config MACH_ARMADA_370 bool "Marvell Armada 370 boards" select ARMADA_370_CLK - select MACH_ARMADA_370_XP + select CPU_PJ4B + select MACH_MVEBU_V7 select PINCTRL_ARMADA_370 help Say 'Y' here if you want your kernel to support boards based on the Marvell Armada 370 SoC with device tree. +config MACH_ARMADA_375 + bool "Marvell Armada 375 boards" + select ARM_ERRATA_720789 + select ARM_ERRATA_753970 + select ARM_GIC + select ARMADA_375_CLK + select CPU_V7 + select MACH_MVEBU_V7 + select NEON + select PINCTRL_ARMADA_375 + help + Say 'Y' here if you want your kernel to support boards based + on the Marvell Armada 375 SoC with device tree. + +config MACH_ARMADA_38X + bool "Marvell Armada 380/385 boards" + select ARM_ERRATA_720789 + select ARM_ERRATA_753970 + select ARM_GIC + select ARMADA_38X_CLK + select CPU_V7 + select MACH_MVEBU_V7 + select NEON + select PINCTRL_ARMADA_38X + help + Say 'Y' here if you want your kernel to support boards based + on the Marvell Armada 380/385 SoC with device tree. + config MACH_ARMADA_XP bool "Marvell Armada XP boards" select ARMADA_XP_CLK - select MACH_ARMADA_370_XP + select CPU_PJ4B + select MACH_MVEBU_V7 select PINCTRL_ARMADA_XP help Say 'Y' here if you want your kernel to support boards based diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 878aebe..2c1db29 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -4,7 +4,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ AFLAGS_coherency_ll.o := -Wa,-march=armv7-a obj-y += system-controller.o mvebu-soc-id.o -obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o +obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/board-v7.c index f6c9d1d..746134e 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -31,12 +31,28 @@ #include "coherency.h" #include "mvebu-soc-id.h" -static void __init armada_370_xp_map_io(void) +/* + * Early versions of Armada 375 SoC have a bug where the BootROM + * leaves an external data abort pending. The kernel is hit by this + * data abort as soon as it enters userspace, because it unmasks the + * data aborts at this moment. We register a custom abort handler + * below to ignore the first data abort to work around this + * problem. + */ +static int armada_375_external_abort_wa(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) { - debug_ll_io_init(); + static int ignore_first; + + if (!ignore_first && fsr == 0x1406) { + ignore_first = 1; + return 0; + } + + return 1; } -static void __init armada_370_xp_timer_and_clk_init(void) +static void __init mvebu_timer_and_clk_init(void) { of_clk_init(NULL); clocksource_of_init(); @@ -45,6 +61,10 @@ static void __init armada_370_xp_timer_and_clk_init(void) #ifdef CONFIG_CACHE_L2X0 l2x0_of_init(0, ~0UL); #endif + + if (of_machine_is_compatible("marvell,armada375")) + hook_fault_code(16 + 6, armada_375_external_abort_wa, SIGBUS, 0, + "imprecise external abort"); } static void __init i2c_quirk(void) @@ -75,7 +95,7 @@ static void __init i2c_quirk(void) return; } -static void __init armada_370_xp_dt_init(void) +static void __init mvebu_dt_init(void) { if (of_machine_is_compatible("plathome,openblocks-ax3-4")) i2c_quirk(); @@ -87,11 +107,33 @@ static const char * const armada_370_xp_dt_compat[] = { NULL, }; -DT_MACHINE_START(ARMADA_XP_DT, "Marvell Armada 370/XP (Device Tree)") +DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)") .smp = smp_ops(armada_xp_smp_ops), - .init_machine = armada_370_xp_dt_init, - .map_io = armada_370_xp_map_io, - .init_time = armada_370_xp_timer_and_clk_init, + .init_machine = mvebu_dt_init, + .init_time = mvebu_timer_and_clk_init, .restart = mvebu_restart, .dt_compat = armada_370_xp_dt_compat, MACHINE_END + +static const char * const armada_375_dt_compat[] = { + "marvell,armada375", + NULL, +}; + +DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)") + .init_time = mvebu_timer_and_clk_init, + .restart = mvebu_restart, + .dt_compat = armada_375_dt_compat, +MACHINE_END + +static const char * const armada_38x_dt_compat[] = { + "marvell,armada380", + "marvell,armada385", + NULL, +}; + +DT_MACHINE_START(ARMADA_38X_DT, "Marvell Armada 380/385 (Device Tree)") + .init_time = mvebu_timer_and_clk_init, + .restart = mvebu_restart, + .dt_compat = armada_38x_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c index a7fb89a..614ba68 100644 --- a/arch/arm/mach-mvebu/system-controller.c +++ b/arch/arm/mach-mvebu/system-controller.c @@ -1,5 +1,5 @@ /* - * System controller support for Armada 370 and XP platforms. + * System controller support for Armada 370, 375 and XP platforms. * * Copyright (C) 2012 Marvell * @@ -11,7 +11,7 @@ * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. * - * The Armada 370 and Armada XP SoCs both have a range of + * The Armada 370, 375 and Armada XP SoCs have a range of * miscellaneous registers, that do not belong to a particular device, * but rather provide system-level features. This basic * system-controller driver provides a device tree binding for those @@ -47,6 +47,13 @@ static const struct mvebu_system_controller armada_370_xp_system_controller = { .system_soft_reset = 0x1, }; +static const struct mvebu_system_controller armada_375_system_controller = { + .rstoutn_mask_offset = 0x54, + .system_soft_reset_offset = 0x58, + .rstoutn_mask_reset_out_en = 0x1, + .system_soft_reset = 0x1, +}; + static const struct mvebu_system_controller orion_system_controller = { .rstoutn_mask_offset = 0x108, .system_soft_reset_offset = 0x10c, @@ -54,13 +61,16 @@ static const struct mvebu_system_controller orion_system_controller = { .system_soft_reset = 0x1, }; -static struct of_device_id of_system_controller_table[] = { +static const struct of_device_id of_system_controller_table[] = { { .compatible = "marvell,orion-system-controller", .data = (void *) &orion_system_controller, }, { .compatible = "marvell,armada-370-xp-system-controller", .data = (void *) &armada_370_xp_system_controller, + }, { + .compatible = "marvell,armada-375-system-controller", + .data = (void *) &armada_375_system_controller, }, { /* end of list */ }, }; @@ -90,13 +100,12 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd) static int __init mvebu_system_controller_init(void) { + const struct of_device_id *match; struct device_node *np; - np = of_find_matching_node(NULL, of_system_controller_table); + np = of_find_matching_node_and_match(NULL, of_system_controller_table, + &match); if (np) { - const struct of_device_id *match = - of_match_node(of_system_controller_table, np); - BUG_ON(!match); system_controller_base = of_iomap(np, 0); mvebu_sc = (struct mvebu_system_controller *)match->data; of_node_put(np); diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index eec053c..e55ae63 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -152,12 +152,6 @@ config SOC_TI81XX depends on ARCH_OMAP3 default y -config OMAP_PACKAGE_ZAF - bool - -config OMAP_PACKAGE_ZAC - bool - config OMAP_PACKAGE_CBC bool @@ -267,7 +261,6 @@ config MACH_NOKIA_N8X0 default y select MACH_NOKIA_N810 select MACH_NOKIA_N810_WIMAX - select OMAP_PACKAGE_ZAC config MACH_NOKIA_RX51 bool "Nokia N900 (RX-51) phone" diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index e6eec6f..8421f38 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -60,6 +60,7 @@ AFLAGS_sram34xx.o :=-Wa,-march=armv7-a obj-$(CONFIG_SOC_OMAP2420) += omap2-restart.o obj-$(CONFIG_SOC_OMAP2430) += omap2-restart.o obj-$(CONFIG_SOC_AM33XX) += am33xx-restart.o +obj-$(CONFIG_SOC_AM43XX) += omap4-restart.o obj-$(CONFIG_ARCH_OMAP3) += omap3-restart.o obj-$(CONFIG_ARCH_OMAP4) += omap4-restart.o obj-$(CONFIG_SOC_OMAP5) += omap4-restart.o diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 8e3daa1..bc6013f 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -229,8 +229,9 @@ DT_MACHINE_START(AM43_DT, "Generic AM43 (Flattened Device Tree)") .init_late = am43xx_init_late, .init_irq = omap_gic_of_init, .init_machine = omap_generic_init, - .init_time = omap3_sync32k_timer_init, + .init_time = omap3_gptimer_timer_init, .dt_compat = am43_boards_compat, + .restart = omap44xx_restart, MACHINE_END #endif diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c index 47f9562..2649ce4 100644 --- a/arch/arm/mach-omap2/clkt_dpll.c +++ b/arch/arm/mach-omap2/clkt_dpll.c @@ -306,7 +306,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, ref_rate = __clk_get_rate(dd->clk_ref); clk_name = __clk_get_name(hw->clk); - pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n", + pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", clk_name, target_rate); scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR); @@ -342,7 +342,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, if (r == DPLL_MULT_UNDERFLOW) continue; - pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n", + pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n", clk_name, m, n, new_rate); if (target_rate == new_rate) { @@ -354,7 +354,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, } if (target_rate != new_rate) { - pr_debug("clock: %s: cannot round to rate %ld\n", + pr_debug("clock: %s: cannot round to rate %lu\n", clk_name, target_rate); return ~0; } diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 731ca13..f5c4731 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -254,6 +254,11 @@ void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs) * */ +void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs) +{ + _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, part, inst, cdoffs); +} + /** * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state * @part: PRCM partition ID that the CM_CLKCTRL register exists in @@ -404,8 +409,17 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) static int omap4_clkdm_sleep(struct clockdomain *clkdm) { - omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, clkdm->clkdm_offs); + if (clkdm->flags & CLKDM_CAN_HWSUP) + omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, + clkdm->cm_inst, + clkdm->clkdm_offs); + else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP) + omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition, + clkdm->cm_inst, + clkdm->clkdm_offs); + else + return -EINVAL; + return 0; } diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 3185ced..d9bcbf7 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -525,7 +525,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, * stuff is inherited for free */ - if (!ret) + if (!ret && clk_get_parent(hw->clk) != new_parent) __clk_reparent(hw->clk, new_parent); return 0; diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 9428c5f..157412e 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -465,8 +465,18 @@ void __init omap3xxx_check_revision(void) } break; case 0xb98c: - omap_revision = AM437X_REV_ES1_0; - cpu_rev = "1.0"; + switch (rev) { + case 0: + omap_revision = AM437X_REV_ES1_0; + cpu_rev = "1.0"; + break; + case 1: + /* FALLTHROUGH */ + default: + omap_revision = AM437X_REV_ES1_1; + cpu_rev = "1.1"; + break; + } break; case 0xb8f2: switch (rev) { @@ -657,6 +667,8 @@ static const char * __init omap_get_family(void) return kasprintf(GFP_KERNEL, "OMAP4"); else if (soc_is_omap54xx()) return kasprintf(GFP_KERNEL, "OMAP5"); + else if (soc_is_am43xx()) + return kasprintf(GFP_KERNEL, "AM43xx"); else return kasprintf(GFP_KERNEL, "Unknown"); } diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index af432b1..f14f9ac 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -604,6 +604,7 @@ void __init am43xx_init_early(void) omap_prm_base_init(); omap_cm_base_init(); omap3xxx_check_revision(); + am33xx_check_features(); am43xx_powerdomains_init(); am43xx_clockdomains_init(); am43xx_hwmod_init(); diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h index a722330..d121fb6 100644 --- a/arch/arm/mach-omap2/mux.h +++ b/arch/arm/mach-omap2/mux.h @@ -63,9 +63,6 @@ #define OMAP_PACKAGE_CUS 5 /* 423-pin 0.65 */ #define OMAP_PACKAGE_CBB 4 /* 515-pin 0.40 0.50 */ #define OMAP_PACKAGE_CBC 3 /* 515-pin 0.50 0.65 */ -#define OMAP_PACKAGE_ZAC 2 /* 24xx 447-pin POP */ -#define OMAP_PACKAGE_ZAF 1 /* 2420 447-pin SIP */ - #define OMAP_MUX_NR_MODES 8 /* Available modes */ #define OMAP_MUX_NR_SIDES 2 /* Bottom & top */ diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index 9002fca..5c2cc80 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -719,6 +719,7 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { &am33xx_l4_ls__uart4, &am33xx_l4_ls__uart5, &am33xx_l4_ls__uart6, + &am33xx_l4_ls__spinlock, &am33xx_l4_ls__elm, &am33xx_l4_ls__epwmss0, &am33xx_epwmss0__ecap0, diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c index 6334b96..f5989f2 100644 --- a/arch/arm/mach-omap2/prminst44xx.c +++ b/arch/arm/mach-omap2/prminst44xx.c @@ -25,6 +25,7 @@ #include "prminst44xx.h" #include "prm-regbits-44xx.h" #include "prcm44xx.h" +#include "prcm43xx.h" #include "prcm_mpu44xx.h" #include "soc.h" @@ -176,6 +177,8 @@ void omap4_prminst_global_warm_sw_reset(void) dev_inst = OMAP54XX_PRM_DEVICE_INST; else if (soc_is_dra7xx()) dev_inst = DRA7XX_PRM_DEVICE_INST; + else if (soc_is_am43xx()) + dev_inst = AM43XX_PRM_DEVICE_INST; else return; diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h index 076bd90..30abcc8 100644 --- a/arch/arm/mach-omap2/soc.h +++ b/arch/arm/mach-omap2/soc.h @@ -438,7 +438,8 @@ IS_OMAP_TYPE(3430, 0x3430) #define AM335X_REV_ES2_1 (AM335X_CLASS | (0x2 << 8)) #define AM437X_CLASS 0x43700000 -#define AM437X_REV_ES1_0 AM437X_CLASS +#define AM437X_REV_ES1_0 (AM437X_CLASS | (0x10 << 8)) +#define AM437X_REV_ES1_1 (AM437X_CLASS | (0x11 << 8)) #define OMAP443X_CLASS 0x44300044 #define OMAP4430_REV_ES1_0 (OMAP443X_CLASS | (0x10 << 8)) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 74044aa..b62de9f 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -604,7 +604,8 @@ OMAP_SYS_32K_TIMER_INIT(3_secure, 12, "secure_32k_fck", "ti,timer-secure", 2, "timer_sys_ck", NULL); #endif /* CONFIG_ARCH_OMAP3 */ -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \ + defined(CONFIG_SOC_AM43XX) OMAP_SYS_GP_TIMER_INIT(3, 2, "timer_sys_ck", NULL, 1, "timer_sys_ck", "ti,timer-alwon"); #endif diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig new file mode 100644 index 0000000..a028be2 --- /dev/null +++ b/arch/arm/mach-qcom/Kconfig @@ -0,0 +1,33 @@ +config ARCH_QCOM + bool "Qualcomm Support" if ARCH_MULTI_V7 + select ARCH_REQUIRE_GPIOLIB + select ARM_GIC + select CLKSRC_OF + select GENERIC_CLOCKEVENTS + select HAVE_SMP + select QCOM_SCM if SMP + help + Support for Qualcomm's devicetree based systems. + +if ARCH_QCOM + +menu "Qualcomm SoC Selection" + +config ARCH_MSM8X60 + bool "Enable support for MSM8X60" + select CLKSRC_QCOM + +config ARCH_MSM8960 + bool "Enable support for MSM8960" + select CLKSRC_QCOM + +config ARCH_MSM8974 + bool "Enable support for MSM8974" + select HAVE_ARM_ARCH_TIMER + +endmenu + +config QCOM_SCM + bool + +endif diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile new file mode 100644 index 0000000..8f756ae --- /dev/null +++ b/arch/arm/mach-qcom/Makefile @@ -0,0 +1,5 @@ +obj-y := board.o +obj-$(CONFIG_SMP) += platsmp.o +obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o + +CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-qcom/board.c index 1f11d93..bae617e 100644 --- a/arch/arm/mach-msm/board-dt.c +++ b/arch/arm/mach-qcom/board.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012,2013 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -11,31 +11,16 @@ */ #include <linux/init.h> -#include <linux/of.h> -#include <linux/of_platform.h> #include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include "common.h" - -static const char * const msm_dt_match[] __initconst = { - "qcom,msm8660-fluid", +static const char * const qcom_dt_match[] __initconst = { "qcom,msm8660-surf", "qcom,msm8960-cdp", - NULL -}; - -static const char * const apq8074_dt_match[] __initconst = { "qcom,apq8074-dragonboard", NULL }; -DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)") - .smp = smp_ops(msm_smp_ops), - .dt_compat = msm_dt_match, -MACHINE_END - -DT_MACHINE_START(APQ_DT, "Qualcomm MSM (Flattened Device Tree)") - .dt_compat = apq8074_dt_match, +DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)") + .dt_compat = qcom_dt_match, MACHINE_END diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c new file mode 100644 index 0000000..d690856 --- /dev/null +++ b/arch/arm/mach-qcom/platsmp.c @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/smp.h> +#include <linux/io.h> + +#include <asm/smp_plat.h> + +#include "scm-boot.h" + +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0 +#define SCSS_CPU1CORE_RESET 0x2d80 +#define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64 + +#define APCS_CPU_PWR_CTL 0x04 +#define PLL_CLAMP BIT(8) +#define CORE_PWRD_UP BIT(7) +#define COREPOR_RST BIT(5) +#define CORE_RST BIT(4) +#define L2DT_SLP BIT(3) +#define CLAMP BIT(0) + +#define APC_PWR_GATE_CTL 0x14 +#define BHS_CNT_SHIFT 24 +#define LDO_PWR_DWN_SHIFT 16 +#define LDO_BYP_SHIFT 8 +#define BHS_SEG_SHIFT 1 +#define BHS_EN BIT(0) + +#define APCS_SAW2_VCTL 0x14 +#define APCS_SAW2_2_VCTL 0x1c + +extern void secondary_startup(void); + +static DEFINE_SPINLOCK(boot_lock); + +#ifdef CONFIG_HOTPLUG_CPU +static void __ref qcom_cpu_die(unsigned int cpu) +{ + wfi(); +} +#endif + +static void qcom_secondary_init(unsigned int cpu) +{ + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +static int scss_release_secondary(unsigned int cpu) +{ + struct device_node *node; + void __iomem *base; + + node = of_find_compatible_node(NULL, NULL, "qcom,gcc-msm8660"); + if (!node) { + pr_err("%s: can't find node\n", __func__); + return -ENXIO; + } + + base = of_iomap(node, 0); + of_node_put(node); + if (!base) + return -ENOMEM; + + writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL); + writel_relaxed(0, base + SCSS_CPU1CORE_RESET); + writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP); + mb(); + iounmap(base); + + return 0; +} + +static int kpssv1_release_secondary(unsigned int cpu) +{ + int ret = 0; + void __iomem *reg, *saw_reg; + struct device_node *cpu_node, *acc_node, *saw_node; + u32 val; + + cpu_node = of_get_cpu_node(cpu, NULL); + if (!cpu_node) + return -ENODEV; + + acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); + if (!acc_node) { + ret = -ENODEV; + goto out_acc; + } + + saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); + if (!saw_node) { + ret = -ENODEV; + goto out_saw; + } + + reg = of_iomap(acc_node, 0); + if (!reg) { + ret = -ENOMEM; + goto out_acc_map; + } + + saw_reg = of_iomap(saw_node, 0); + if (!saw_reg) { + ret = -ENOMEM; + goto out_saw_map; + } + + /* Turn on CPU rail */ + writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL); + mb(); + udelay(512); + + /* Krait bring-up sequence */ + val = PLL_CLAMP | L2DT_SLP | CLAMP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + val &= ~L2DT_SLP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + ndelay(300); + + val |= COREPOR_RST; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + val &= ~CLAMP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + val &= ~COREPOR_RST; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(100); + + val |= CORE_PWRD_UP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + + iounmap(saw_reg); +out_saw_map: + iounmap(reg); +out_acc_map: + of_node_put(saw_node); +out_saw: + of_node_put(acc_node); +out_acc: + of_node_put(cpu_node); + return ret; +} + +static int kpssv2_release_secondary(unsigned int cpu) +{ + void __iomem *reg; + struct device_node *cpu_node, *l2_node, *acc_node, *saw_node; + void __iomem *l2_saw_base; + unsigned reg_val; + int ret; + + cpu_node = of_get_cpu_node(cpu, NULL); + if (!cpu_node) + return -ENODEV; + + acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); + if (!acc_node) { + ret = -ENODEV; + goto out_acc; + } + + l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0); + if (!l2_node) { + ret = -ENODEV; + goto out_l2; + } + + saw_node = of_parse_phandle(l2_node, "qcom,saw", 0); + if (!saw_node) { + ret = -ENODEV; + goto out_saw; + } + + reg = of_iomap(acc_node, 0); + if (!reg) { + ret = -ENOMEM; + goto out_map; + } + + l2_saw_base = of_iomap(saw_node, 0); + if (!l2_saw_base) { + ret = -ENOMEM; + goto out_saw_map; + } + + /* Turn on the BHS, turn off LDO Bypass and power down LDO */ + reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN; + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); + mb(); + /* wait for the BHS to settle */ + udelay(1); + + /* Turn on BHS segments */ + reg_val |= 0x3f << BHS_SEG_SHIFT; + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); + mb(); + /* wait for the BHS to settle */ + udelay(1); + + /* Finally turn on the bypass so that BHS supplies power */ + reg_val |= 0x3f << LDO_BYP_SHIFT; + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); + + /* enable max phases */ + writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL); + mb(); + udelay(50); + + reg_val = COREPOR_RST | CLAMP; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + reg_val &= ~CLAMP; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + reg_val &= ~COREPOR_RST; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + + reg_val |= CORE_PWRD_UP; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + + ret = 0; + + iounmap(l2_saw_base); +out_saw_map: + iounmap(reg); +out_map: + of_node_put(saw_node); +out_saw: + of_node_put(l2_node); +out_l2: + of_node_put(acc_node); +out_acc: + of_node_put(cpu_node); + + return ret; +} + +static DEFINE_PER_CPU(int, cold_boot_done); + +static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) +{ + int ret = 0; + + if (!per_cpu(cold_boot_done, cpu)) { + ret = func(cpu); + if (!ret) + per_cpu(cold_boot_done, cpu) = true; + } + + /* + * set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return ret; +} + +static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + return qcom_boot_secondary(cpu, scss_release_secondary); +} + +static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + return qcom_boot_secondary(cpu, kpssv1_release_secondary); +} + +static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + return qcom_boot_secondary(cpu, kpssv2_release_secondary); +} + +static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) +{ + int cpu, map; + unsigned int flags = 0; + static const int cold_boot_flags[] = { + 0, + SCM_FLAG_COLDBOOT_CPU1, + SCM_FLAG_COLDBOOT_CPU2, + SCM_FLAG_COLDBOOT_CPU3, + }; + + for_each_present_cpu(cpu) { + map = cpu_logical_map(cpu); + if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) { + set_cpu_present(cpu, false); + continue; + } + flags |= cold_boot_flags[map]; + } + + if (scm_set_boot_addr(virt_to_phys(secondary_startup), flags)) { + for_each_present_cpu(cpu) { + if (cpu == smp_processor_id()) + continue; + set_cpu_present(cpu, false); + } + pr_warn("Failed to set CPU boot address, disabling SMP\n"); + } +} + +static struct smp_operations smp_msm8660_ops __initdata = { + .smp_prepare_cpus = qcom_smp_prepare_cpus, + .smp_secondary_init = qcom_secondary_init, + .smp_boot_secondary = msm8660_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = qcom_cpu_die, +#endif +}; +CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops); + +static struct smp_operations qcom_smp_kpssv1_ops __initdata = { + .smp_prepare_cpus = qcom_smp_prepare_cpus, + .smp_secondary_init = qcom_secondary_init, + .smp_boot_secondary = kpssv1_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = qcom_cpu_die, +#endif +}; +CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops); + +static struct smp_operations qcom_smp_kpssv2_ops __initdata = { + .smp_prepare_cpus = qcom_smp_prepare_cpus, + .smp_secondary_init = qcom_secondary_init, + .smp_boot_secondary = kpssv2_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = qcom_cpu_die, +#endif +}; +CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops); diff --git a/arch/arm/mach-msm/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c index 45cee3e..45cee3e 100644 --- a/arch/arm/mach-msm/scm-boot.c +++ b/arch/arm/mach-qcom/scm-boot.c diff --git a/arch/arm/mach-msm/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h index 7be32ff..6aabb24 100644 --- a/arch/arm/mach-msm/scm-boot.h +++ b/arch/arm/mach-qcom/scm-boot.h @@ -13,9 +13,11 @@ #define __MACH_SCM_BOOT_H #define SCM_BOOT_ADDR 0x1 -#define SCM_FLAG_COLDBOOT_CPU1 0x1 -#define SCM_FLAG_WARMBOOT_CPU1 0x2 -#define SCM_FLAG_WARMBOOT_CPU0 0x4 +#define SCM_FLAG_COLDBOOT_CPU1 0x01 +#define SCM_FLAG_COLDBOOT_CPU2 0x08 +#define SCM_FLAG_COLDBOOT_CPU3 0x20 +#define SCM_FLAG_WARMBOOT_CPU0 0x04 +#define SCM_FLAG_WARMBOOT_CPU1 0x02 int scm_set_boot_addr(phys_addr_t addr, int flags); diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-qcom/scm.c index c536fd6..c536fd6 100644 --- a/arch/arm/mach-msm/scm.c +++ b/arch/arm/mach-qcom/scm.c diff --git a/arch/arm/mach-msm/scm.h b/arch/arm/mach-qcom/scm.h index 00b31ea..00b31ea 100644 --- a/arch/arm/mach-msm/scm.h +++ b/arch/arm/mach-qcom/scm.h diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 6b2f586..1caee6d 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -5,6 +5,7 @@ config ARCH_ROCKCHIP select ARCH_REQUIRE_GPIOLIB select ARM_GIC select CACHE_L2X0 + select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select DW_APB_TIMER_OF select ARM_GLOBAL_TIMER diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 1547d4f..4377a14 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o +obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-rockchip/core.h b/arch/arm/mach-rockchip/core.h new file mode 100644 index 0000000..e2e7c9d --- /dev/null +++ b/arch/arm/mach-rockchip/core.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +extern char rockchip_secondary_trampoline; +extern char rockchip_secondary_trampoline_end; + +extern unsigned long rockchip_boot_fn; +extern void rockchip_secondary_startup(void); + +extern struct smp_operations rockchip_smp_ops; diff --git a/arch/arm/mach-rockchip/headsmp.S b/arch/arm/mach-rockchip/headsmp.S new file mode 100644 index 0000000..73206e3 --- /dev/null +++ b/arch/arm/mach-rockchip/headsmp.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/linkage.h> +#include <linux/init.h> + +ENTRY(rockchip_secondary_startup) + bl v7_invalidate_l1 + b secondary_startup +ENDPROC(rockchip_secondary_startup) + +ENTRY(rockchip_secondary_trampoline) + ldr pc, 1f +ENDPROC(rockchip_secondary_trampoline) + .globl rockchip_boot_fn +rockchip_boot_fn: +1: .space 4 + +ENTRY(rockchip_secondary_trampoline_end) diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c new file mode 100644 index 0000000..dbfa5a2 --- /dev/null +++ b/arch/arm/mach-rockchip/platsmp.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include <asm/cacheflush.h> +#include <asm/smp_scu.h> +#include <asm/smp_plat.h> +#include <asm/mach/map.h> + +#include "core.h" + +static void __iomem *scu_base_addr; +static void __iomem *sram_base_addr; +static int ncores; + +#define PMU_PWRDN_CON 0x08 +#define PMU_PWRDN_ST 0x0c + +#define PMU_PWRDN_SCU 4 + +static void __iomem *pmu_base_addr; + +static inline bool pmu_power_domain_is_on(int pd) +{ + return !(readl_relaxed(pmu_base_addr + PMU_PWRDN_ST) & BIT(pd)); +} + +static void pmu_set_power_domain(int pd, bool on) +{ + u32 val = readl_relaxed(pmu_base_addr + PMU_PWRDN_CON); + if (on) + val &= ~BIT(pd); + else + val |= BIT(pd); + writel(val, pmu_base_addr + PMU_PWRDN_CON); + + while (pmu_power_domain_is_on(pd) != on) { } +} + +/* + * Handling of CPU cores + */ + +static int __cpuinit rockchip_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + if (!sram_base_addr || !pmu_base_addr) { + pr_err("%s: sram or pmu missing for cpu boot\n", __func__); + return -ENXIO; + } + + if (cpu >= ncores) { + pr_err("%s: cpu %d outside maximum number of cpus %d\n", + __func__, cpu, ncores); + return -ENXIO; + } + + /* start the core */ + pmu_set_power_domain(0 + cpu, true); + + return 0; +} + +/** + * rockchip_smp_prepare_sram - populate necessary sram block + * Starting cores execute the code residing at the start of the on-chip sram + * after power-on. Therefore make sure, this sram region is reserved and + * big enough. After this check, copy the trampoline code that directs the + * core to the real startup code in ram into the sram-region. + * @node: mmio-sram device node + */ +static int __init rockchip_smp_prepare_sram(struct device_node *node) +{ + unsigned int trampoline_sz = &rockchip_secondary_trampoline_end - + &rockchip_secondary_trampoline; + struct resource res; + unsigned int rsize; + int ret; + + ret = of_address_to_resource(node, 0, &res); + if (ret < 0) { + pr_err("%s: could not get address for node %s\n", + __func__, node->full_name); + return ret; + } + + rsize = resource_size(&res); + if (rsize < trampoline_sz) { + pr_err("%s: reserved block with size 0x%x is to small for trampoline size 0x%x\n", + __func__, rsize, trampoline_sz); + return -EINVAL; + } + + sram_base_addr = of_iomap(node, 0); + + /* set the boot function for the sram code */ + rockchip_boot_fn = virt_to_phys(rockchip_secondary_startup); + + /* copy the trampoline to sram, that runs during startup of the core */ + memcpy(sram_base_addr, &rockchip_secondary_trampoline, trampoline_sz); + flush_cache_all(); + outer_clean_range(0, trampoline_sz); + + dsb_sev(); + + return 0; +} + +static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *node; + unsigned int i; + + node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + if (!node) { + pr_err("%s: missing scu\n", __func__); + return; + } + + scu_base_addr = of_iomap(node, 0); + if (!scu_base_addr) { + pr_err("%s: could not map scu registers\n", __func__); + return; + } + + node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-smp-sram"); + if (!node) { + pr_err("%s: could not find sram dt node\n", __func__); + return; + } + + if (rockchip_smp_prepare_sram(node)) + return; + + node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu"); + if (!node) { + pr_err("%s: could not find sram dt node\n", __func__); + return; + } + + pmu_base_addr = of_iomap(node, 0); + if (!pmu_base_addr) { + pr_err("%s: could not map pmu registers\n", __func__); + return; + } + + /* enable the SCU power domain */ + pmu_set_power_domain(PMU_PWRDN_SCU, true); + + /* + * While the number of cpus is gathered from dt, also get the number + * of cores from the scu to verify this value when booting the cores. + */ + ncores = scu_get_core_count(scu_base_addr); + + scu_enable(scu_base_addr); + + /* Make sure that all cores except the first are really off */ + for (i = 1; i < ncores; i++) + pmu_set_power_domain(0 + i, false); +} + +struct smp_operations rockchip_smp_ops __initdata = { + .smp_prepare_cpus = rockchip_smp_prepare_cpus, + .smp_boot_secondary = rockchip_boot_secondary, +}; diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index 82c0b07..d211d6f 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -22,6 +22,7 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/hardware/cache-l2x0.h> +#include "core.h" static void __init rockchip_dt_init(void) { @@ -38,6 +39,7 @@ static const char * const rockchip_board_dt_compat[] = { }; DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)") + .smp = smp_ops(rockchip_smp_ops), .init_machine = rockchip_dt_init, .dt_compat = rockchip_board_dt_compat, MACHINE_END diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index cd6950f..6510ec4 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -140,3 +140,6 @@ config VF_PIT_TIMER bool help Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. + +config CLKSRC_QCOM + bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index c7ca50a..2e0c0cc 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o +obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o diff --git a/arch/arm/mach-msm/timer.c b/drivers/clocksource/qcom-timer.c index fd16449..e807acf 100644 --- a/arch/arm/mach-msm/timer.c +++ b/drivers/clocksource/qcom-timer.c @@ -1,7 +1,7 @@ /* * * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -26,10 +26,6 @@ #include <linux/of_irq.h> #include <linux/sched_clock.h> -#include <asm/mach/time.h> - -#include "common.h" - #define TIMER_MATCH_VAL 0x0000 #define TIMER_COUNT_VAL 0x0004 #define TIMER_ENABLE 0x0008 @@ -110,15 +106,6 @@ static notrace cycle_t msm_read_timer_count(struct clocksource *cs) return readl_relaxed(source_base + TIMER_COUNT_VAL); } -static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) -{ - /* - * Shift timer count down by a constant due to unreliable lower bits - * on some targets. - */ - return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; -} - static struct clocksource msm_clocksource = { .name = "dg_timer", .rating = 300, @@ -232,7 +219,7 @@ err: sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); } -#ifdef CONFIG_OF +#ifdef CONFIG_ARCH_QCOM static void __init msm_dt_timer_init(struct device_node *np) { u32 freq; @@ -285,7 +272,7 @@ static void __init msm_dt_timer_init(struct device_node *np) } CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); -#endif +#else static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, u32 sts) @@ -305,6 +292,15 @@ static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, return 0; } +static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) +{ + /* + * Shift timer count down by a constant due to unreliable lower bits + * on some targets. + */ + return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; +} + void __init msm7x01_timer_init(void) { struct clocksource *cs = &msm_clocksource; @@ -331,3 +327,4 @@ void __init qsd8x50_timer_init(void) return; msm_timer_init(19200000 / 4, 32, 7, false); } +#endif diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 61ffdca..ec42d2d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -39,6 +39,14 @@ config IMGPDC_IRQ select GENERIC_IRQ_CHIP select IRQ_DOMAIN +config CLPS711X_IRQCHIP + bool + depends on ARCH_CLPS711X + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + select SPARSE_IRQ + default y + config ORION_IRQCHIP bool select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 5194afb..ac61b92 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o obj-$(CONFIG_METAG) += irq-metag-ext.o obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o +obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c new file mode 100644 index 0000000..33340dc --- /dev/null +++ b/drivers/irqchip/irq-clps711x.c @@ -0,0 +1,243 @@ +/* + * CLPS711X IRQ driver + * + * Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/slab.h> + +#include <asm/exception.h> +#include <asm/mach/irq.h> + +#include "irqchip.h" + +#define CLPS711X_INTSR1 (0x0240) +#define CLPS711X_INTMR1 (0x0280) +#define CLPS711X_BLEOI (0x0600) +#define CLPS711X_MCEOI (0x0640) +#define CLPS711X_TEOI (0x0680) +#define CLPS711X_TC1EOI (0x06c0) +#define CLPS711X_TC2EOI (0x0700) +#define CLPS711X_RTCEOI (0x0740) +#define CLPS711X_UMSEOI (0x0780) +#define CLPS711X_COEOI (0x07c0) +#define CLPS711X_INTSR2 (0x1240) +#define CLPS711X_INTMR2 (0x1280) +#define CLPS711X_SRXEOF (0x1600) +#define CLPS711X_KBDEOI (0x1700) +#define CLPS711X_INTSR3 (0x2240) +#define CLPS711X_INTMR3 (0x2280) + +static const struct { +#define CLPS711X_FLAG_EN (1 << 0) +#define CLPS711X_FLAG_FIQ (1 << 1) + unsigned int flags; + phys_addr_t eoi; +} clps711x_irqs[] = { + [1] = { CLPS711X_FLAG_FIQ, CLPS711X_BLEOI, }, + [3] = { CLPS711X_FLAG_FIQ, CLPS711X_MCEOI, }, + [4] = { CLPS711X_FLAG_EN, CLPS711X_COEOI, }, + [5] = { CLPS711X_FLAG_EN, }, + [6] = { CLPS711X_FLAG_EN, }, + [7] = { CLPS711X_FLAG_EN, }, + [8] = { CLPS711X_FLAG_EN, CLPS711X_TC1EOI, }, + [9] = { CLPS711X_FLAG_EN, CLPS711X_TC2EOI, }, + [10] = { CLPS711X_FLAG_EN, CLPS711X_RTCEOI, }, + [11] = { CLPS711X_FLAG_EN, CLPS711X_TEOI, }, + [12] = { CLPS711X_FLAG_EN, }, + [13] = { CLPS711X_FLAG_EN, }, + [14] = { CLPS711X_FLAG_EN, CLPS711X_UMSEOI, }, + [15] = { CLPS711X_FLAG_EN, CLPS711X_SRXEOF, }, + [16] = { CLPS711X_FLAG_EN, CLPS711X_KBDEOI, }, + [17] = { CLPS711X_FLAG_EN, }, + [18] = { CLPS711X_FLAG_EN, }, + [28] = { CLPS711X_FLAG_EN, }, + [29] = { CLPS711X_FLAG_EN, }, + [32] = { CLPS711X_FLAG_FIQ, }, +}; + +static struct { + void __iomem *base; + void __iomem *intmr[3]; + void __iomem *intsr[3]; + struct irq_domain *domain; + struct irq_domain_ops ops; +} *clps711x_intc; + +static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs) +{ + u32 irqnr, irqstat; + + do { + irqstat = readw_relaxed(clps711x_intc->intmr[0]) & + readw_relaxed(clps711x_intc->intsr[0]); + if (irqstat) { + irqnr = irq_find_mapping(clps711x_intc->domain, + fls(irqstat) - 1); + handle_IRQ(irqnr, regs); + } + + irqstat = readw_relaxed(clps711x_intc->intmr[1]) & + readw_relaxed(clps711x_intc->intsr[1]); + if (irqstat) { + irqnr = irq_find_mapping(clps711x_intc->domain, + fls(irqstat) - 1 + 16); + handle_IRQ(irqnr, regs); + } + } while (irqstat); +} + +static void clps711x_intc_eoi(struct irq_data *d) +{ + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + writel_relaxed(0, clps711x_intc->base + clps711x_irqs[hwirq].eoi); +} + +static void clps711x_intc_mask(struct irq_data *d) +{ + irq_hw_number_t hwirq = irqd_to_hwirq(d); + void __iomem *intmr = clps711x_intc->intmr[hwirq / 16]; + u32 tmp; + + tmp = readl_relaxed(intmr); + tmp &= ~(1 << (hwirq % 16)); + writel_relaxed(tmp, intmr); +} + +static void clps711x_intc_unmask(struct irq_data *d) +{ + irq_hw_number_t hwirq = irqd_to_hwirq(d); + void __iomem *intmr = clps711x_intc->intmr[hwirq / 16]; + u32 tmp; + + tmp = readl_relaxed(intmr); + tmp |= 1 << (hwirq % 16); + writel_relaxed(tmp, intmr); +} + +static struct irq_chip clps711x_intc_chip = { + .name = "clps711x-intc", + .irq_eoi = clps711x_intc_eoi, + .irq_mask = clps711x_intc_mask, + .irq_unmask = clps711x_intc_unmask, +}; + +static int __init clps711x_intc_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + irq_flow_handler_t handler = handle_level_irq; + unsigned int flags = IRQF_VALID | IRQF_PROBE; + + if (!clps711x_irqs[hw].flags) + return 0; + + if (clps711x_irqs[hw].flags & CLPS711X_FLAG_FIQ) { + handler = handle_bad_irq; + flags |= IRQF_NOAUTOEN; + } else if (clps711x_irqs[hw].eoi) { + handler = handle_fasteoi_irq; + } + + /* Clear down pending interrupt */ + if (clps711x_irqs[hw].eoi) + writel_relaxed(0, clps711x_intc->base + clps711x_irqs[hw].eoi); + + irq_set_chip_and_handler(virq, &clps711x_intc_chip, handler); + set_irq_flags(virq, flags); + + return 0; +} + +static int __init _clps711x_intc_init(struct device_node *np, + phys_addr_t base, resource_size_t size) +{ + int err; + + clps711x_intc = kzalloc(sizeof(*clps711x_intc), GFP_KERNEL); + if (!clps711x_intc) + return -ENOMEM; + + clps711x_intc->base = ioremap(base, size); + if (!clps711x_intc->base) { + err = -ENOMEM; + goto out_kfree; + } + + clps711x_intc->intsr[0] = clps711x_intc->base + CLPS711X_INTSR1; + clps711x_intc->intmr[0] = clps711x_intc->base + CLPS711X_INTMR1; + clps711x_intc->intsr[1] = clps711x_intc->base + CLPS711X_INTSR2; + clps711x_intc->intmr[1] = clps711x_intc->base + CLPS711X_INTMR2; + clps711x_intc->intsr[2] = clps711x_intc->base + CLPS711X_INTSR3; + clps711x_intc->intmr[2] = clps711x_intc->base + CLPS711X_INTMR3; + + /* Mask all interrupts */ + writel_relaxed(0, clps711x_intc->intmr[0]); + writel_relaxed(0, clps711x_intc->intmr[1]); + writel_relaxed(0, clps711x_intc->intmr[2]); + + err = irq_alloc_descs(-1, 0, ARRAY_SIZE(clps711x_irqs), numa_node_id()); + if (IS_ERR_VALUE(err)) + goto out_iounmap; + + clps711x_intc->ops.map = clps711x_intc_irq_map; + clps711x_intc->ops.xlate = irq_domain_xlate_onecell; + clps711x_intc->domain = + irq_domain_add_legacy(np, ARRAY_SIZE(clps711x_irqs), + 0, 0, &clps711x_intc->ops, NULL); + if (!clps711x_intc->domain) { + err = -ENOMEM; + goto out_irqfree; + } + + irq_set_default_host(clps711x_intc->domain); + set_handle_irq(clps711x_irqh); + +#ifdef CONFIG_FIQ + init_FIQ(0); +#endif + + return 0; + +out_irqfree: + irq_free_descs(0, ARRAY_SIZE(clps711x_irqs)); + +out_iounmap: + iounmap(clps711x_intc->base); + +out_kfree: + kfree(clps711x_intc); + + return err; +} + +void __init clps711x_intc_init(phys_addr_t base, resource_size_t size) +{ + BUG_ON(_clps711x_intc_init(NULL, base, size)); +} + +#ifdef CONFIG_IRQCHIP +static int __init clps711x_intc_init_dt(struct device_node *np, + struct device_node *parent) +{ + struct resource res; + int err; + + err = of_address_to_resource(np, 0, &res); + if (err) + return err; + + return _clps711x_intc_init(np, res.start, resource_size(&res)); +} +IRQCHIP_DECLARE(clps711x, "cirrus,clps711x-intc", clps711x_intc_init_dt); +#endif diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index bc2121f..bd02ca7 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -167,6 +167,15 @@ #define CLK_OF_TABLES() #endif +#ifdef CONFIG_SMP +#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \ + VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \ + *(__cpu_method_of_table) \ + VMLINUX_SYMBOL(__cpu_method_of_table_end) = .; +#else +#define CPU_METHOD_OF_TABLES() +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__dtb_start) = .; \ @@ -491,6 +500,7 @@ MEM_DISCARD(init.rodata) \ CLK_OF_TABLES() \ CLKSRC_OF_TABLES() \ + CPU_METHOD_OF_TABLES() \ KERNEL_DTB() \ IRQCHIP_OF_MATCH_TABLE() |