Skip to content

Instantly share code, notes, and snippets.

@cjdelisle
Created March 19, 2023 12:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cjdelisle/1bf34f4b16a476ce28dd5513e8a91dc1 to your computer and use it in GitHub Desktop.
Save cjdelisle/1bf34f4b16a476ce28dd5513e8a91dc1 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
diff --git a/.get_maintainer.ignore b/.get_maintainer.ignore
deleted file mode 100644
index cca6d870f7a5..000000000000
--- a/.get_maintainer.ignore
+++ /dev/null
@@ -1 +0,0 @@
-Christoph Hellwig <hch@lst.de>
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 89c411b5ce6b..000000000000
--- a/.gitattributes
+++ /dev/null
@@ -1,2 +0,0 @@
-*.c diff=cpp
-*.h diff=cpp
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
index 0120c7f1109c..a46929bc1ec8 100644
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
@@ -7,10 +7,19 @@ This file documents differences between the core properties in mmc.txt
and the properties used by the msdc driver.
Required properties:
-- compatible: Should be "mediatek,mt8173-mmc","mediatek,mt8135-mmc"
+- compatible: value should be either of the following.
+ "mediatek,mt8135-mmc": for mmc host ip compatible with mt8135
+ "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173
+ "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701
+ "mediatek,mt7622-mmc": for MT7622 SoC
+ "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC
+
+- reg: physical base address of the controller and length
- interrupts: Should contain MSDC interrupt number
-- clocks: MSDC source clock, HCLK
-- clock-names: "source", "hclk"
+- clocks: Should contain phandle for the clock feeding the MMC controller
+- clock-names: Should contain the following:
+ "source" - source clock (required)
+ "hclk" - HCLK which used for host (required)
- pinctrl-names: should be "default", "state_uhs"
- pinctrl-0: should contain default/high speed pin ctrl
- pinctrl-1: should contain uhs mode pin ctrl
@@ -21,6 +30,19 @@ Optional properties:
- assigned-clocks: PLL of the source clock
- assigned-clock-parents: parent of source clock, used for HS400 mode to get 400Mhz source clock
- hs400-ds-delay: HS400 DS delay setting
+- mediatek,hs200-cmd-int-delay: HS200 command internal delay setting.
+ This field has total 32 stages.
+ The value is an integer from 0 to 31.
+- mediatek,hs400-cmd-int-delay: HS400 command internal delay setting
+ This field has total 32 stages.
+ The value is an integer from 0 to 31.
+- mediatek,hs400-cmd-resp-sel-rising: HS400 command response sample selection
+ If present,HS400 command responses are sampled on rising edges.
+ If not present,HS400 command responses are sampled on falling edges.
+- mediatek,latch-ck: Some SoCs do not support enhance_rx, need set correct latch-ck to avoid data crc
+ error caused by stop clock(fifo full)
+ Valid range = [0:0x7]. if not present, default value is 0.
+ applied to compatible "mediatek,mt2701-mmc".
Examples:
mmc0: mmc@11230000 {
@@ -38,4 +60,7 @@ mmc0: mmc@11230000 {
assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>;
hs400-ds-delay = <0x14015>;
+ mediatek,hs200-cmd-int-delay = <26>;
+ mediatek,hs400-cmd-int-delay = <14>;
+ mediatek,hs400-cmd-resp-sel-rising;
};
diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
new file mode 100644
index 000000000000..3a6ce55dd310
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
@@ -0,0 +1,284 @@
+MediaTek Gen2 PCIe controller
+
+Required properties:
+- compatible: Should contain one of the following strings:
+ "mediatek,mt2701-pcie"
+ "mediatek,mt2712-pcie"
+ "mediatek,mt7622-pcie"
+ "mediatek,mt7623-pcie"
+- device_type: Must be "pci"
+- reg: Base addresses and lengths of the PCIe subsys and root ports.
+- reg-names: Names of the above areas to use during resource lookup.
+- #address-cells: Address representation for root ports (must be 3)
+- #size-cells: Size representation for root ports (must be 2)
+- clocks: Must contain an entry for each entry in clock-names.
+ See ../clocks/clock-bindings.txt for details.
+- clock-names:
+ Mandatory entries:
+ - sys_ckN :transaction layer and data link layer clock
+ Required entries for MT2701/MT7623:
+ - free_ck :for reference clock of PCIe subsys
+ Required entries for MT2712/MT7622:
+ - ahb_ckN :AHB slave interface operating clock for CSR access and RC
+ initiated MMIO access
+ Required entries for MT7622:
+ - axi_ckN :application layer MMIO channel operating clock
+ - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
+ pcie_mac_ck/pcie_pipe_ck is turned off
+ - obff_ckN :OBFF functional block operating clock
+ - pipe_ckN :LTSSM and PHY/MAC layer operating clock
+ where N starting from 0 to one less than the number of root ports.
+- phys: List of PHY specifiers (used by generic PHY framework).
+- phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
+ number of PHYs as specified in *phys* property.
+- power-domains: A phandle and power domain specifier pair to the power domain
+ which is responsible for collapsing and restoring power to the peripheral.
+- bus-range: Range of bus numbers associated with this controller.
+- ranges: Ranges for the PCI memory and I/O regions.
+
+Required properties for MT7623/MT2701:
+- #interrupt-cells: Size representation for interrupts (must be 1)
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+ Please refer to the standard PCI bus binding document for a more detailed
+ explanation.
+- resets: Must contain an entry for each entry in reset-names.
+ See ../reset/reset.txt for details.
+- reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
+ number of root ports.
+
+Required properties for MT2712/MT7622:
+-interrupts: A list of interrupt outputs of the controller, must have one
+ entry for each PCIe port
+
+In addition, the device tree node must have sub-nodes describing each
+PCIe port interface, having the following mandatory properties:
+
+Required properties:
+- device_type: Must be "pci"
+- reg: Only the first four bytes are used to refer to the correct bus number
+ and device number.
+- #address-cells: Must be 3
+- #size-cells: Must be 2
+- #interrupt-cells: Must be 1
+- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
+ Please refer to the standard PCI bus binding document for a more detailed
+ explanation.
+- ranges: Sub-ranges distributed from the PCIe controller node. An empty
+ property is sufficient.
+- num-lanes: Number of lanes to use for this port.
+
+Examples for MT7623:
+
+ hifsys: syscon@1a000000 {
+ compatible = "mediatek,mt7623-hifsys",
+ "mediatek,mt2701-hifsys",
+ "syscon";
+ reg = <0 0x1a000000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ pcie: pcie-controller@1a140000 {
+ compatible = "mediatek,mt7623-pcie";
+ device_type = "pci";
+ reg = <0 0x1a140000 0 0x1000>, /* PCIe shared registers */
+ <0 0x1a142000 0 0x1000>, /* Port0 registers */
+ <0 0x1a143000 0 0x1000>, /* Port1 registers */
+ <0 0x1a144000 0 0x1000>; /* Port2 registers */
+ reg-names = "subsys", "port0", "port1", "port2";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xf800 0 0 0>;
+ interrupt-map = <0x0000 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>,
+ <0x0800 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>,
+ <0x1000 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_ETHIF_SEL>,
+ <&hifsys CLK_HIFSYS_PCIE0>,
+ <&hifsys CLK_HIFSYS_PCIE1>,
+ <&hifsys CLK_HIFSYS_PCIE2>;
+ clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2";
+ resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>,
+ <&hifsys MT2701_HIFSYS_PCIE1_RST>,
+ <&hifsys MT2701_HIFSYS_PCIE2_RST>;
+ reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2";
+ phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>,
+ <&pcie2_phy PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
+ power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* I/O space */
+ 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* memory space */
+
+ pcie@0,0 {
+ device_type = "pci";
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>;
+ ranges;
+ num-lanes = <1>;
+ };
+
+ pcie@1,0 {
+ device_type = "pci";
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
+ ranges;
+ num-lanes = <1>;
+ };
+
+ pcie@2,0 {
+ device_type = "pci";
+ reg = <0x1000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>;
+ ranges;
+ num-lanes = <1>;
+ };
+ };
+
+Examples for MT2712:
+ pcie: pcie@11700000 {
+ compatible = "mediatek,mt2712-pcie";
+ device_type = "pci";
+ reg = <0 0x11700000 0 0x1000>,
+ <0 0x112ff000 0 0x1000>;
+ reg-names = "port0", "port1";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
+ <&topckgen CLK_TOP_PE2_MAC_P1_SEL>,
+ <&pericfg CLK_PERI_PCIE0>,
+ <&pericfg CLK_PERI_PCIE1>;
+ clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
+ phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy0", "pcie-phy1";
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
+
+ pcie0: pcie@0,0 {
+ device_type = "pci";
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+ <0 0 0 2 &pcie_intc0 1>,
+ <0 0 0 3 &pcie_intc0 2>,
+ <0 0 0 4 &pcie_intc0 3>;
+ pcie_intc0: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ pcie1: pcie@1,0 {
+ device_type = "pci";
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+ <0 0 0 2 &pcie_intc1 1>,
+ <0 0 0 3 &pcie_intc1 2>,
+ <0 0 0 4 &pcie_intc1 3>;
+ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+Examples for MT7622:
+ pcie: pcie@1a140000 {
+ compatible = "mediatek,mt7622-pcie";
+ device_type = "pci";
+ reg = <0 0x1a140000 0 0x1000>,
+ <0 0x1a143000 0 0x1000>,
+ <0 0x1a145000 0 0x1000>;
+ reg-names = "subsys", "port0", "port1";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+ <&pciesys CLK_PCIE_P1_MAC_EN>,
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+ <&pciesys CLK_PCIE_P1_AHB_EN>,
+ <&pciesys CLK_PCIE_P0_AUX_EN>,
+ <&pciesys CLK_PCIE_P1_AUX_EN>,
+ <&pciesys CLK_PCIE_P0_AXI_EN>,
+ <&pciesys CLK_PCIE_P1_AXI_EN>,
+ <&pciesys CLK_PCIE_P0_OBFF_EN>,
+ <&pciesys CLK_PCIE_P1_OBFF_EN>,
+ <&pciesys CLK_PCIE_P0_PIPE_EN>,
+ <&pciesys CLK_PCIE_P1_PIPE_EN>;
+ clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+ "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+ "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+ phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy0", "pcie-phy1";
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
+
+ pcie0: pcie@0,0 {
+ device_type = "pci";
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+ <0 0 0 2 &pcie_intc0 1>,
+ <0 0 0 3 &pcie_intc0 2>,
+ <0 0 0 4 &pcie_intc0 3>;
+ pcie_intc0: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ pcie1: pcie@1,0 {
+ device_type = "pci";
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+ <0 0 0 2 &pcie_intc1 1>,
+ <0 0 0 3 &pcie_intc1 2>,
+ <0 0 0 4 &pcie_intc1 3>;
+ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt b/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt
deleted file mode 100644
index 33a2b1ee3f3e..000000000000
--- a/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt
+++ /dev/null
@@ -1,70 +0,0 @@
-mt65xx USB3.0 PHY binding
---------------------------
-
-This binding describes a usb3.0 phy for mt65xx platforms of Medaitek SoC.
-
-Required properties (controller (parent) node):
- - compatible : should be one of
- "mediatek,mt2701-u3phy"
- "mediatek,mt8173-u3phy"
- - reg : offset and length of register for phy, exclude port's
- register.
- - clocks : a list of phandle + clock-specifier pairs, one for each
- entry in clock-names
- - clock-names : must contain
- "u3phya_ref": for reference clock of usb3.0 analog phy.
-
-Required nodes : a sub-node is required for each port the controller
- provides. Address range information including the usual
- 'reg' property is used inside these nodes to describe
- the controller's topology.
-
-Required properties (port (child) node):
-- reg : address and length of the register set for the port.
-- #phy-cells : should be 1 (See second example)
- cell after port phandle is phy type from:
- - PHY_TYPE_USB2
- - PHY_TYPE_USB3
-
-Example:
-
-u3phy: usb-phy@11290000 {
- compatible = "mediatek,mt8173-u3phy";
- reg = <0 0x11290000 0 0x800>;
- clocks = <&apmixedsys CLK_APMIXED_REF2USB_TX>;
- clock-names = "u3phya_ref";
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- status = "okay";
-
- phy_port0: port@11290800 {
- reg = <0 0x11290800 0 0x800>;
- #phy-cells = <1>;
- status = "okay";
- };
-
- phy_port1: port@11291000 {
- reg = <0 0x11291000 0 0x800>;
- #phy-cells = <1>;
- status = "okay";
- };
-};
-
-Specifying phy control of devices
----------------------------------
-
-Device nodes should specify the configuration required in their "phys"
-property, containing a phandle to the phy port node and a device type;
-phy-names for each port are optional.
-
-Example:
-
-#include <dt-bindings/phy/phy.h>
-
-usb30: usb@11270000 {
- ...
- phys = <&phy_port0 PHY_TYPE_USB3>;
- phy-names = "usb3-0";
- ...
-};
diff --git a/Documentation/devicetree/bindings/phy/phy-mtk-tphy.txt b/Documentation/devicetree/bindings/phy/phy-mtk-tphy.txt
new file mode 100644
index 000000000000..faf18084a33a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-mtk-tphy.txt
@@ -0,0 +1,144 @@
+MediaTek T-PHY binding
+--------------------------
+
+T-phy controller supports physical layer functionality for a number of
+controllers on MediaTek SoCs, such as, USB2.0, USB3.0, PCIe, and SATA.
+
+Required properties (controller (parent) node):
+ - compatible : should be one of
+ "mediatek,generic-tphy-v1"
+ "mediatek,generic-tphy-v2"
+ "mediatek,mt2701-u3phy" (deprecated)
+ "mediatek,mt2712-u3phy" (deprecated)
+ "mediatek,mt8173-u3phy";
+ make use of "mediatek,generic-tphy-v1" on mt2701 instead and
+ "mediatek,generic-tphy-v2" on mt2712 instead.
+ - clocks : (deprecated, use port's clocks instead) a list of phandle +
+ clock-specifier pairs, one for each entry in clock-names
+ - clock-names : (deprecated, use port's one instead) must contain
+ "u3phya_ref": for reference clock of usb3.0 analog phy.
+
+Required nodes : a sub-node is required for each port the controller
+ provides. Address range information including the usual
+ 'reg' property is used inside these nodes to describe
+ the controller's topology.
+
+Optional properties (controller (parent) node):
+ - reg : offset and length of register shared by multiple ports,
+ exclude port's private register. It is needed on mt2701
+ and mt8173, but not on mt2712.
+
+Required properties (port (child) node):
+- reg : address and length of the register set for the port.
+- clocks : a list of phandle + clock-specifier pairs, one for each
+ entry in clock-names
+- clock-names : must contain
+ "ref": 48M reference clock for HighSpeed analog phy; and 26M
+ reference clock for SuperSpeed analog phy, sometimes is
+ 24M, 25M or 27M, depended on platform.
+- #phy-cells : should be 1 (See second example)
+ cell after port phandle is phy type from:
+ - PHY_TYPE_USB2
+ - PHY_TYPE_USB3
+ - PHY_TYPE_PCIE
+ - PHY_TYPE_SATA
+
+Example:
+
+u3phy: usb-phy@11290000 {
+ compatible = "mediatek,mt8173-u3phy";
+ reg = <0 0x11290000 0 0x800>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "okay";
+
+ u2port0: usb-phy@11290800 {
+ reg = <0 0x11290800 0 0x100>;
+ clocks = <&apmixedsys CLK_APMIXED_REF2USB_TX>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ status = "okay";
+ };
+
+ u3port0: usb-phy@11290900 {
+ reg = <0 0x11290800 0 0x700>;
+ clocks = <&clk26m>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ status = "okay";
+ };
+
+ u2port1: usb-phy@11291000 {
+ reg = <0 0x11291000 0 0x100>;
+ clocks = <&apmixedsys CLK_APMIXED_REF2USB_TX>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ status = "okay";
+ };
+};
+
+Specifying phy control of devices
+---------------------------------
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy port node and a device type;
+phy-names for each port are optional.
+
+Example:
+
+#include <dt-bindings/phy/phy.h>
+
+usb30: usb@11270000 {
+ ...
+ phys = <&u2port0 PHY_TYPE_USB2>, <&u3port0 PHY_TYPE_USB3>;
+ phy-names = "usb2-0", "usb3-0";
+ ...
+};
+
+
+Layout differences of banks between mt8173/mt2701 and mt2712
+-------------------------------------------------------------
+mt8173 and mt2701:
+port offset bank
+shared 0x0000 SPLLC
+ 0x0100 FMREG
+u2 port0 0x0800 U2PHY_COM
+u3 port0 0x0900 U3PHYD
+ 0x0a00 U3PHYD_BANK2
+ 0x0b00 U3PHYA
+ 0x0c00 U3PHYA_DA
+u2 port1 0x1000 U2PHY_COM
+u3 port1 0x1100 U3PHYD
+ 0x1200 U3PHYD_BANK2
+ 0x1300 U3PHYA
+ 0x1400 U3PHYA_DA
+u2 port2 0x1800 U2PHY_COM
+ ...
+
+mt2712:
+port offset bank
+u2 port0 0x0000 MISC
+ 0x0100 FMREG
+ 0x0300 U2PHY_COM
+u3 port0 0x0700 SPLLC
+ 0x0800 CHIP
+ 0x0900 U3PHYD
+ 0x0a00 U3PHYD_BANK2
+ 0x0b00 U3PHYA
+ 0x0c00 U3PHYA_DA
+u2 port1 0x1000 MISC
+ 0x1100 FMREG
+ 0x1300 U2PHY_COM
+u3 port1 0x1700 SPLLC
+ 0x1800 CHIP
+ 0x1900 U3PHYD
+ 0x1a00 U3PHYD_BANK2
+ 0x1b00 U3PHYA
+ 0x1c00 U3PHYA_DA
+u2 port2 0x2000 MISC
+ ...
+
+ SPLLC shared by u3 ports and FMREG shared by u2 ports on
+mt8173/mt2701 are put back into each port; a new bank MISC for
+u2 ports and CHIP for u3 ports are added on mt2712.
diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index e8f15e34027f..16fe94d7783c 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -9,17 +9,20 @@ domain control.
The driver implements the Generic PM domain bindings described in
power/power_domain.txt. It provides the power domains defined in
-include/dt-bindings/power/mt8173-power.h.
+include/dt-bindings/power/mt8173-power.h and mt2701-power.h.
Required properties:
-- compatible: Must be "mediatek,mt8173-scpsys"
+- compatible: Should be one of:
+ - "mediatek,mt2701-scpsys"
+ - "mediatek,mt8173-scpsys"
- #power-domain-cells: Must be 1
- reg: Address range of the SCPSYS unit
- infracfg: must contain a phandle to the infracfg controller
- clock, clock-names: clocks according to the common clock binding.
- The clocks needed "mm", "mfg", "venc" and "venc_lt".
- These are the clocks which hardware needs to be enabled
- before enabling certain power domains.
+ These are clocks which hardware needs to be
+ enabled before enabling certain power domains.
+ Required clocks for MT2701: "mm", "mfg", "ethif"
+ Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
Optional properties:
- vdec-supply: Power supply for the vdec power domain
diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
index 6a00939a059a..95bf107ed80a 100644
--- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
@@ -9,9 +9,13 @@ Required properties:
- reg : Specifies base physical address and size of the registers.
+Optional properties:
+- timeout-sec: contains the watchdog timeout in seconds.
+
Example:
-wdt: watchdog@010000000 {
+wdt: watchdog@10000000 {
compatible = "mediatek,mt6589-wdt";
reg = <0x10000000 0x18>;
+ timeout-sec = <10>;
};
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 167070895498..1fa6c386ee59 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -333,6 +333,7 @@ MFD
devm_mfd_add_devices()
PCI
+ devm_pci_alloc_host_bridge() : managed PCI host bridge allocation
pcim_enable_device() : after success, all PCI ops become managed
pcim_pin_device() : keep PCI device enabled after release
diff --git a/Makefile b/Makefile
index c6fbf52eff45..563eb571670f 100644
--- a/Makefile
+++ b/Makefile
@@ -667,11 +667,6 @@ KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context)
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
KBUILD_CFLAGS += $(call cc-disable-warning, attribute-alias)
-ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
-KBUILD_CFLAGS += $(call cc-option,-ffunction-sections,)
-KBUILD_CFLAGS += $(call cc-option,-fdata-sections,)
-endif
-
ifdef CONFIG_LTO_CLANG
lto-clang-flags := -flto -fvisibility=hidden
@@ -720,7 +715,7 @@ export DISABLE_CFI
endif
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS += -Os
+KBUILD_CFLAGS += -O2 -fno-caller-saves $(call cc-option,-fno-inline-functions)
else
KBUILD_CFLAGS += -O2
endif
@@ -854,6 +849,11 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH
KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
endif
+ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
+KBUILD_CFLAGS_KERNEL += $(call cc-option,-ffunction-sections,)
+KBUILD_CFLAGS_KERNEL += $(call cc-option,-fdata-sections,)
+endif
+
# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
@@ -1103,7 +1103,8 @@ $(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
define filechk_kernel.release
- echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"
+ (echo -n "$(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL))$(EXTRAVERSION)"; \
+ echo "$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))";)
endef
# Store (new) KERNELRELEASE string in include/config/kernel.release
@@ -1341,7 +1342,6 @@ endif
PHONY += modules
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
- $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
@$(kecho) ' Building modules, stage 2.';
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
@@ -1371,7 +1371,6 @@ _modinst_:
rm -f $(MODLIB)/build ; \
ln -s $(CURDIR) $(MODLIB)/build ; \
fi
- @cp -f $(objtree)/modules.order $(MODLIB)/
@cp -f $(objtree)/modules.builtin $(MODLIB)/
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6c8aed4a296c..142825a938aa 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -82,6 +82,7 @@ config ARM
select HAVE_UID16
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select IRQ_FORCED_THREADING
+ select LD_DEAD_CODE_DATA_ELIMINATION
select MODULES_USE_ELF_REL
select NO_BOOTMEM
select OF_EARLY_FLATTREE if OF
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 561dbc0ee2ba..9e7e681f8759 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -104,6 +104,7 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
endif
+KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL))
# -fstack-protector-strong triggers protection checks in this code,
# but it is being used too early to link to meaningful stack_chk logic.
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 0d560a24408f..1aadaeb5e051 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -30,7 +30,7 @@
#define PROC_INFO \
. = ALIGN(4); \
VMLINUX_SYMBOL(__proc_info_begin) = .; \
- *(.proc.info.init) \
+ KEEP(*(.proc.info.init)) \
VMLINUX_SYMBOL(__proc_info_end) = .;
#define HYPERVISOR_TEXT \
@@ -41,11 +41,11 @@
#define IDMAP_TEXT \
ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__idmap_text_start) = .; \
- *(.idmap.text) \
+ KEEP(*(.idmap.text)) \
VMLINUX_SYMBOL(__idmap_text_end) = .; \
. = ALIGN(PAGE_SIZE); \
VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \
- *(.hyp.idmap.text) \
+ KEEP(*(.hyp.idmap.text)) \
VMLINUX_SYMBOL(__hyp_idmap_text_end) = .;
#ifdef CONFIG_HOTPLUG_CPU
@@ -118,7 +118,7 @@ SECTIONS
_stext = .; /* Text and read-only data */
IDMAP_TEXT
__exception_text_start = .;
- *(.exception.text)
+ KEEP(*(.exception.text))
__exception_text_end = .;
IRQENTRY_TEXT
SOFTIRQENTRY_TEXT
@@ -147,7 +147,7 @@ SECTIONS
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
__start___ex_table = .;
#ifdef CONFIG_MMU
- *(__ex_table)
+ KEEP(*(__ex_table))
#endif
__stop___ex_table = .;
}
@@ -159,12 +159,12 @@ SECTIONS
. = ALIGN(8);
.ARM.unwind_idx : {
__start_unwind_idx = .;
- *(.ARM.exidx*)
+ KEEP(*(.ARM.exidx*))
__stop_unwind_idx = .;
}
.ARM.unwind_tab : {
__start_unwind_tab = .;
- *(.ARM.extab*)
+ KEEP(*(.ARM.extab*))
__stop_unwind_tab = .;
}
#endif
@@ -185,13 +185,13 @@ SECTIONS
__vectors_lma = .;
OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) {
.vectors {
- *(.vectors)
+ KEEP(*(.vectors))
}
.vectors.bhb.loop8 {
- *(.vectors.bhb.loop8)
+ KEEP(*(.vectors.bhb.loop8))
}
.vectors.bhb.bpiall {
- *(.vectors.bhb.bpiall)
+ KEEP(*(.vectors.bhb.bpiall))
}
}
ARM_LMA(__vectors, .vectors);
@@ -203,7 +203,7 @@ SECTIONS
__stubs_lma = .;
.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) {
- *(.stubs)
+ KEEP(*(.stubs))
}
ARM_LMA(__stubs, .stubs);
. = __stubs_lma + SIZEOF(.stubs);
@@ -219,24 +219,24 @@ SECTIONS
}
.init.arch.info : {
__arch_info_begin = .;
- *(.arch.info.init)
+ KEEP(*(.arch.info.init))
__arch_info_end = .;
}
.init.tagtable : {
__tagtable_begin = .;
- *(.taglist.init)
+ KEEP(*(.taglist.init))
__tagtable_end = .;
}
#ifdef CONFIG_SMP_ON_UP
.init.smpalt : {
__smpalt_begin = .;
- *(.alt.smp.init)
+ KEEP(*(.alt.smp.init))
__smpalt_end = .;
}
#endif
.init.pv_table : {
__pv_table_begin = .;
- *(.pv_table)
+ KEEP(*(.pv_table))
__pv_table_end = .;
}
.init.data : {
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 26e802db9e84..e60896a64236 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -111,6 +111,7 @@ config ARM64
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
+ select LD_DEAD_CODE_DATA_ELIMINATION
help
ARM 64-bit (AArch64) Linux support.
@@ -1077,6 +1078,7 @@ config EFI_STUB
config EFI
bool "UEFI runtime support"
depends on OF && !CPU_BIG_ENDIAN
+ depends on KERNEL_MODE_NEON
select LIBFDT
select UCS2_STRING
select EFI_PARAMS_FROM_FDT
@@ -1219,3 +1221,5 @@ source "arch/arm64/crypto/Kconfig"
endif
source "lib/Kconfig"
+
+source "ndm/Kconfig"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2f9c2a95c40e..e40e39fa418d 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -92,6 +92,14 @@ config ARCH_MEDIATEK
help
Support for Mediatek MT65xx & MT81xx ARMv8 SoCs
+if ARCH_MEDIATEK
+
+config MACH_MT7622
+ bool "MediaTek MT7622 SoCs support"
+ default ARCH_MEDIATEK
+
+endif
+
config ARCH_MESON
bool "Amlogic Platforms"
select PINCTRL
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 9fbfd3238469..66753cc6513a 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -1,6 +1,14 @@
+ifeq ($(CONFIG_MACH_MT7622),y)
+#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-evb.dtb
+#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
+#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb2.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-ac2600rfb1.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-ac4300rfb1.dtb
+else
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
+endif
always := $(dtb-y)
subdir-y := $(dts-dirs)
diff --git a/arch/arm64/boot/dts/mediatek/mt6380.dtsi b/arch/arm64/boot/dts/mediatek/mt6380.dtsi
new file mode 100644
index 000000000000..a4b911738c0f
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6380.dtsi
@@ -0,0 +1,96 @@
+/*
+ * Mediatek's PMIC mt6380 device tree source
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&pwrap {
+ status = "okay";
+
+ pmic: mt6380 {
+ compatible = "mediatek,mt6380";
+ };
+
+ mt6380regulator: mt6380regulator {
+ compatible = "mediatek,mt6380-regulator";
+
+ mt6380_vcpu_reg: buck_vcore1 {
+ regulator-name = "vcpu";
+ regulator-min-microvolt = < 600000>;
+ regulator-max-microvolt = <1393750>;
+ regulator-ramp-delay = <6250>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ mt6380_vcore_reg: buck_vcore {
+ regulator-name = "vcore";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1393750>;
+ regulator-ramp-delay = <6250>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ mt6380_vrf_reg: buck_vrf {
+ regulator-name = "vrf";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1575000>;
+ regulator-ramp-delay = <0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ mt6380_vm_reg: ldo_vmldo {
+ regulator-name = "vmldo";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-ramp-delay = <0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ mt6380_va_reg: ldo_valdo {
+ regulator-name = "valdo";
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ mt6380_vphy_reg: ldo_vphyldo {
+ regulator-name = "vphyldo";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ mt6380_vddr_reg: ldo_vddrldo {
+ regulator-name = "vddr";
+ regulator-min-microvolt = <1240000>;
+ regulator-max-microvolt = <1840000>;
+ regulator-ramp-delay = <0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ mt6380_vt_reg: ldo_vtldo {
+ regulator-name = "vadc18";
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-ac2600rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-ac2600rfb1.dts
new file mode 100644
index 000000000000..b2e9ac29e624
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622-ac2600rfb1.dts
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+ model = "MediaTek MT7622 AC2600rfb1 board";
+ compatible = "mediatek,mt7622-ac2600rfb1", "mediatek,mt7622";
+
+ chosen {
+ bootargs = "console=ttyS0,115200n1 loglevel=8 swiotlb=512 rootfstype=squashfs";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset {
+ label = "reset";
+ gpios = <&pio 0 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ };
+
+ wps {
+ label = "wps";
+ gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_WPS_BUTTON>;
+ };
+ };
+
+ mmc_fixed_1v8_io: fixedregulator-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ mmc_fixed_3v3_power: fixedregulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_power";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x3F000000>;
+ };
+
+ sound: sound {
+ compatible = "mediatek,mt7622-wm8960-machine";
+ mediatek,platform = <&afe>;
+ audio-routing =
+ "Headphone", "HP_L",
+ "Headphone", "HP_R",
+ "LINPUT2", "AMIC",
+ "RINPUT2", "AMIC";
+ mediatek,audio-codec = <&wm8960>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins_default>;
+ status = "disabled";
+ };
+};
+
+&auxadc {
+ status = "okay";
+};
+
+&bch {
+ status = "disabled";
+};
+
+&cpu0 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&cpu1 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&efuse {
+ status = "okay";
+};
+
+&raeth {
+ mac-address = [00 00 00 00 00 00];
+ dma-coherent;
+ wan_at = "p4";
+ gmac1-support = "sgmii-1";
+ sgmii-mode-1 = "force-2500";
+ #gmac1-support = "rgmii-1";
+ #rgmii-mode-1 = "force-1000";
+ #gmac1-phy-address = <0x1f>;
+ gmac2-support = "rgmii-2";
+ rgmii-mode-2 = "force-1000";
+ #rgmii-mode-2 = "an";
+ #gmac2-phy-address = <0x1e>;
+ gmac1_txq_num = <1>;
+ gmac1_txq_txd_num = <2048>;
+ gmac2_txq_num = <1>;
+ gmac2_txq_txd_num = <1024>;
+ num_rx_desc = <2048>;
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "disabled";
+
+ wm8960: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ status = "okay";
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_1v8_io>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ r_smpl = <1>;
+ cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_3v3_power>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nandc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins_default>;
+ status = "disabled";
+ reg = <0>;
+ nand-ecc-mode = "hw";
+};
+
+&nor_flash {
+ status = "disabled";
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+};
+
+&pio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+ state_default:pinconf_default {
+ };
+
+ aud_pins_default: audiodefault {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_3_I2S_BCLK__FUNC_I2S_BCLK_OUT>,
+ <MT7622_PIN_4_I2S_WS__FUNC_I2S_WS_OUT>,
+ <MT7622_PIN_5_I2S_MCLK__FUNC_I2S_MCLK>,
+ <MT7622_PIN_2_I2S1_OUT__FUNC_I2S1_OUT>,
+ <MT7622_PIN_1_I2S1_IN__FUNC_I2S1_IN>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down;
+ };
+ };
+
+ i2c0_pins: i2c0-pins {
+ pins_bus {
+ pinmux = <MT7622_PIN_14_I2C_SDA__FUNC_I2C0_SDA>,
+ <MT7622_PIN_15_I2C_SCL__FUNC_I2C0_SCL>;
+ bias-disable;
+ };
+ };
+
+ mmc0_pins_default: mmc0default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ bias-pull-down;
+ };
+ };
+
+ mmc0_pins_uhs: mmc0-pins-uhs {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ mmc1_pins_default: mmc1default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins_insert {
+ pinmux = <MT7622_PIN_81_TXD3__FUNC_GPIO81>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_pins_uhs: mmc1-pins-uhs {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ nand_pins_default: nanddefault {
+ pins_dat {
+ pinmux = <MT7622_PIN_37_NCEB__FUNC_ND_CS_N>,
+ <MT7622_PIN_38_NWEB__FUNC_ND_WE_N>,
+ <MT7622_PIN_39_NREB__FUNC_ND_RE_N>,
+ <MT7622_PIN_40_NDL4__FUNC_ND_D4>,
+ <MT7622_PIN_41_NDL5__FUNC_ND_D5>,
+ <MT7622_PIN_42_NDL6__FUNC_ND_D6>,
+ <MT7622_PIN_43_NDL7__FUNC_ND_D7>,
+ <MT7622_PIN_44_NRB__FUNC_ND_RB_N>,
+ <MT7622_PIN_45_NCLE__FUNC_ND_CLE>,
+ <MT7622_PIN_46_NALE__FUNC_ND_ALE>,
+ <MT7622_PIN_47_NDL0__FUNC_ND_D0>,
+ <MT7622_PIN_48_NDL1__FUNC_ND_D1>,
+ <MT7622_PIN_49_NDL2__FUNC_ND_D2>,
+ <MT7622_PIN_50_NDL3__FUNC_ND_D3>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up;
+ };
+ };
+
+ snand_pins_default: snand-pins-default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_8_SPI_WP__FUNC_SNFI_WP>,
+ <MT7622_PIN_9_SPI_HOLD__FUNC_SNFI_HOLD>,
+ <MT7622_PIN_11_SPI_MOSI__FUNC_SNFI_MOSI>,
+ <MT7622_PIN_12_SPI_MISO__FUNC_SNFI_MISO>,
+ <MT7622_PIN_13_SPI_CS__FUNC_SNFI_CS>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ pins_clk {
+ pinmux = <MT7622_PIN_10_SPI_CLK__FUNC_SNFI_CLK>;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ wbsys_pins_default: wbsysdefault {
+ };
+
+ wbsys_pins_epa: wbsysepa {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_91_TXD4__FUNC_ANTSEL0>,
+ <MT7622_PIN_92_RXD4__FUNC_ANTSEL1>,
+ <MT7622_PIN_93_RTS4_N__FUNC_ANTSEL2>,
+ <MT7622_PIN_94_CTS4_N__FUNC_ANTSEL3>,
+ <MT7622_PIN_95_PWM1__FUNC_ANTSEL4>,
+ <MT7622_PIN_96_PWM2__FUNC_ANTSEL5>,
+ <MT7622_PIN_97_PWM3__FUNC_ANTSEL6>,
+ <MT7622_PIN_98_PWM4__FUNC_ANTSEL7>,
+ <MT7622_PIN_99_PWM5__FUNC_ANTSEL8>,
+ <MT7622_PIN_100_PWM6__FUNC_ANTSEL9>,
+ <MT7622_PIN_73_SPIC1_CLK__FUNC_ANTSEL12>,
+ <MT7622_PIN_74_SPIC1_MOSI__FUNC_ANTSEL13>,
+ <MT7622_PIN_75_SPIC1_MISO__FUNC_ANTSEL14>,
+ <MT7622_PIN_76_SPIC1_CS__FUNC_ANTSEL15>,
+ <MT7622_PIN_77_GPIO_D__FUNC_ANTSEL16>,
+ <MT7622_PIN_22_GPIO_B__FUNC_ANTSEL17>;
+ };
+ };
+};
+
+&pwm {
+ status = "okay";
+};
+
+&snand {
+ pinctrl-0 = <&snand_pins_default>;
+ status = "okay";
+};
+
+&svs {
+ vproc-supply = <&mt6380_vcpu_reg>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&sata_phy {
+ status = "okay";
+};
+
+&wbsys {
+ pinctrl-names = "default", "state_epa";
+ pinctrl-0 = <&wbsys_pins_default>;
+ pinctrl-1 = <&wbsys_pins_epa>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-ac4300rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-ac4300rfb1.dts
new file mode 100644
index 000000000000..36a9df4a9918
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622-ac4300rfb1.dts
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+ model = "MediaTek MT7622 AC4300rfb1 board";
+ compatible = "mediatek,mt7622-ac4300rfb1", "mediatek,mt7622";
+
+ chosen {
+ bootargs = "console=ttyS0,115200n1 loglevel=8 swiotlb=512 rootfstype=squashfs";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset {
+ label = "reset";
+ gpios = <&pio 0 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ };
+
+ wps {
+ label = "wps";
+ gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_WPS_BUTTON>;
+ };
+ };
+
+ mmc_fixed_1v8_io: fixedregulator-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ mmc_fixed_3v3_power: fixedregulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_power";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x3F000000>;
+ };
+};
+
+&auxadc {
+ status = "okay";
+};
+
+&bch {
+ status = "disabled";
+};
+
+&cpu0 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&cpu1 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&efuse {
+ status = "okay";
+};
+
+&raeth {
+ mac-address = [00 00 00 00 00 00];
+ dma-coherent;
+ wan_at = "p4";
+ gmac1-support = "sgmii-1";
+ sgmii-mode-1 = "force-2500";
+ #gmac1-support = "rgmii-1";
+ #rgmii-mode-1 = "force-1000";
+ #gmac1-phy-address = <0x1f>;
+ gmac2-support = "rgmii-2";
+ rgmii-mode-2 = "force-1000";
+ #rgmii-mode-2 = "an";
+ #gmac2-phy-address = <0x1e>;
+ gmac1_txq_num = <1>;
+ gmac1_txq_txd_num = <2048>;
+ gmac2_txq_num = <1>;
+ gmac2_txq_txd_num = <1024>;
+ num_rx_desc = <2048>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ status = "okay";
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_1v8_io>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ r_smpl = <1>;
+ cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_3v3_power>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nandc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins_default>;
+ status = "disabled";
+ reg = <0>;
+ nand-ecc-mode = "hw";
+};
+
+&nor_flash {
+ status = "disabled";
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+};
+
+&pio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+ state_default:pinconf_default {
+ };
+
+ mmc0_pins_default: mmc0default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ bias-pull-down;
+ };
+ };
+
+ mmc0_pins_uhs: mmc0-pins-uhs {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ mmc1_pins_default: mmc1default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins_insert {
+ pinmux = <MT7622_PIN_81_TXD3__FUNC_GPIO81>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_pins_uhs: mmc1-pins-uhs {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ nand_pins_default: nanddefault {
+ pins_dat {
+ pinmux = <MT7622_PIN_37_NCEB__FUNC_ND_CS_N>,
+ <MT7622_PIN_38_NWEB__FUNC_ND_WE_N>,
+ <MT7622_PIN_39_NREB__FUNC_ND_RE_N>,
+ <MT7622_PIN_40_NDL4__FUNC_ND_D4>,
+ <MT7622_PIN_41_NDL5__FUNC_ND_D5>,
+ <MT7622_PIN_42_NDL6__FUNC_ND_D6>,
+ <MT7622_PIN_43_NDL7__FUNC_ND_D7>,
+ <MT7622_PIN_44_NRB__FUNC_ND_RB_N>,
+ <MT7622_PIN_45_NCLE__FUNC_ND_CLE>,
+ <MT7622_PIN_46_NALE__FUNC_ND_ALE>,
+ <MT7622_PIN_47_NDL0__FUNC_ND_D0>,
+ <MT7622_PIN_48_NDL1__FUNC_ND_D1>,
+ <MT7622_PIN_49_NDL2__FUNC_ND_D2>,
+ <MT7622_PIN_50_NDL3__FUNC_ND_D3>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up;
+ };
+ };
+
+ snand_pins_default: snand-pins-default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_8_SPI_WP__FUNC_SNFI_WP>,
+ <MT7622_PIN_9_SPI_HOLD__FUNC_SNFI_HOLD>,
+ <MT7622_PIN_11_SPI_MOSI__FUNC_SNFI_MOSI>,
+ <MT7622_PIN_12_SPI_MISO__FUNC_SNFI_MISO>,
+ <MT7622_PIN_13_SPI_CS__FUNC_SNFI_CS>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ pins_clk {
+ pinmux = <MT7622_PIN_10_SPI_CLK__FUNC_SNFI_CLK>;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ wbsys_pins_default: wbsysdefault {
+ };
+
+ wbsys_pins_epa: wbsysepa {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_91_TXD4__FUNC_ANTSEL0>,
+ <MT7622_PIN_92_RXD4__FUNC_ANTSEL1>,
+ <MT7622_PIN_93_RTS4_N__FUNC_ANTSEL2>,
+ <MT7622_PIN_94_CTS4_N__FUNC_ANTSEL3>,
+ <MT7622_PIN_95_PWM1__FUNC_ANTSEL4>,
+ <MT7622_PIN_96_PWM2__FUNC_ANTSEL5>,
+ <MT7622_PIN_97_PWM3__FUNC_ANTSEL6>,
+ <MT7622_PIN_98_PWM4__FUNC_ANTSEL7>,
+ <MT7622_PIN_99_PWM5__FUNC_ANTSEL8>,
+ <MT7622_PIN_100_PWM6__FUNC_ANTSEL9>,
+ <MT7622_PIN_73_SPIC1_CLK__FUNC_ANTSEL12>,
+ <MT7622_PIN_74_SPIC1_MOSI__FUNC_ANTSEL13>,
+ <MT7622_PIN_75_SPIC1_MISO__FUNC_ANTSEL14>,
+ <MT7622_PIN_76_SPIC1_CS__FUNC_ANTSEL15>,
+ <MT7622_PIN_77_GPIO_D__FUNC_ANTSEL16>,
+ <MT7622_PIN_22_GPIO_B__FUNC_ANTSEL17>;
+ };
+ };
+};
+
+&pwm {
+ status = "okay";
+};
+
+&snand {
+ pinctrl-0 = <&snand_pins_default>;
+ status = "okay";
+};
+
+&svs {
+ vproc-supply = <&mt6380_vcpu_reg>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
+
+&wbsys {
+ pinctrl-names = "default", "state_epa";
+ pinctrl-0 = <&wbsys_pins_default>;
+ pinctrl-1 = <&wbsys_pins_epa>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-clkao.dtsi b/arch/arm64/boot/dts/mediatek/mt7622-clkao.dtsi
new file mode 100644
index 000000000000..5442ea59fdbf
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622-clkao.dtsi
@@ -0,0 +1,166 @@
+&clkao {
+ status = "disabled";
+
+ bring-up {
+ compatible = "mediatek,clk-bring-up";
+ clocks =
+ <&apmixedsys CLK_APMIXED_ARMPLL>,
+ <&apmixedsys CLK_APMIXED_MAINPLL>,
+ <&apmixedsys CLK_APMIXED_UNIV2PLL>,
+ <&apmixedsys CLK_APMIXED_ETH1PLL>,
+ <&apmixedsys CLK_APMIXED_ETH2PLL>,
+ <&apmixedsys CLK_APMIXED_AUD1PLL>,
+ <&apmixedsys CLK_APMIXED_AUD2PLL>,
+ <&apmixedsys CLK_APMIXED_TRGPLL>,
+ <&apmixedsys CLK_APMIXED_SGMIPLL>,
+ <&infracfg CLK_INFRA_DBGCLK_PD>,
+ <&infracfg CLK_INFRA_AUDIO_PD>,
+ <&infracfg CLK_INFRA_IRRX_PD>,
+ <&infracfg CLK_INFRA_APXGPT_PD>,
+ <&infracfg CLK_INFRA_PMIC_PD>,
+ <&pericfg CLK_PERI_THERM_PD>,
+ <&pericfg CLK_PERI_PWM1_PD>,
+ <&pericfg CLK_PERI_PWM2_PD>,
+ <&pericfg CLK_PERI_PWM3_PD>,
+ <&pericfg CLK_PERI_PWM4_PD>,
+ <&pericfg CLK_PERI_PWM5_PD>,
+ <&pericfg CLK_PERI_PWM6_PD>,
+ <&pericfg CLK_PERI_PWM7_PD>,
+ <&pericfg CLK_PERI_PWM_PD>,
+ <&pericfg CLK_PERI_AP_DMA_PD>,
+ <&pericfg CLK_PERI_MSDC30_0_PD>,
+ <&pericfg CLK_PERI_MSDC30_1_PD>,
+ <&pericfg CLK_PERI_UART0_PD>,
+ <&pericfg CLK_PERI_UART1_PD>,
+ <&pericfg CLK_PERI_UART2_PD>,
+ <&pericfg CLK_PERI_UART3_PD>,
+ <&pericfg CLK_PERI_UART4_PD>,
+ <&pericfg CLK_PERI_BTIF_PD>,
+ <&pericfg CLK_PERI_I2C0_PD>,
+ <&pericfg CLK_PERI_I2C1_PD>,
+ <&pericfg CLK_PERI_I2C2_PD>,
+ <&pericfg CLK_PERI_SPI1_PD>,
+ <&pericfg CLK_PERI_AUXADC_PD>,
+ <&pericfg CLK_PERI_SPI0_PD>,
+ <&pericfg CLK_PERI_SNFI_PD>,
+ <&pericfg CLK_PERI_NFI_PD>,
+ <&pericfg CLK_PERI_NFIECC_PD>,
+ <&pericfg CLK_PERI_FLASH_PD>,
+ <&pericfg CLK_PERI_IRTX_PD>,
+ <&topckgen CLK_TOP_MSDC50_0_SEL>,
+ <&topckgen CLK_TOP_MSDC30_0_SEL>,
+ <&topckgen CLK_TOP_APLL1_DIV_PD>,
+ <&topckgen CLK_TOP_APLL2_DIV_PD>,
+ <&topckgen CLK_TOP_I2S0_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S1_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S2_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S3_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_A1SYS_HP_DIV_PD>,
+ <&topckgen CLK_TOP_A2SYS_HP_DIV_PD>,
+ <&audiosys CLK_AUDIO_AFE>,
+ <&audiosys CLK_AUDIO_HDMI>,
+ <&audiosys CLK_AUDIO_SPDF>,
+ <&audiosys CLK_AUDIO_APLL>,
+ <&audiosys CLK_AUDIO_I2SIN1>,
+ <&audiosys CLK_AUDIO_I2SIN2>,
+ <&audiosys CLK_AUDIO_I2SIN3>,
+ <&audiosys CLK_AUDIO_I2SIN4>,
+ <&audiosys CLK_AUDIO_I2SO1>,
+ <&audiosys CLK_AUDIO_I2SO2>,
+ <&audiosys CLK_AUDIO_I2SO3>,
+ <&audiosys CLK_AUDIO_I2SO4>,
+ <&audiosys CLK_AUDIO_ASRCI1>,
+ <&audiosys CLK_AUDIO_ASRCI2>,
+ <&audiosys CLK_AUDIO_ASRCO1>,
+ <&audiosys CLK_AUDIO_ASRCO2>,
+ <&audiosys CLK_AUDIO_INTDIR>,
+ <&audiosys CLK_AUDIO_A1SYS>,
+ <&audiosys CLK_AUDIO_A2SYS>,
+ <&audiosys CLK_AUDIO_UL1>,
+ <&audiosys CLK_AUDIO_UL2>,
+ <&audiosys CLK_AUDIO_UL3>,
+ <&audiosys CLK_AUDIO_UL4>,
+ <&audiosys CLK_AUDIO_UL5>,
+ <&audiosys CLK_AUDIO_UL6>,
+ <&audiosys CLK_AUDIO_DL1>,
+ <&audiosys CLK_AUDIO_DL2>,
+ <&audiosys CLK_AUDIO_DL3>,
+ <&audiosys CLK_AUDIO_DL4>,
+ <&audiosys CLK_AUDIO_DL5>,
+ <&audiosys CLK_AUDIO_DL6>,
+ <&audiosys CLK_AUDIO_DLMCH>,
+ <&audiosys CLK_AUDIO_ARB1>,
+ <&audiosys CLK_AUDIO_AWB>,
+ <&audiosys CLK_AUDIO_AWB2>,
+ <&audiosys CLK_AUDIO_DAI>,
+ <&audiosys CLK_AUDIO_MOD>,
+ <&audiosys CLK_AUDIO_ASRCI3>,
+ <&audiosys CLK_AUDIO_ASRCI4>,
+ <&audiosys CLK_AUDIO_ASRCO3>,
+ <&audiosys CLK_AUDIO_ASRCO4>,
+ <&audiosys CLK_AUDIO_MEM_ASRC1>,
+ <&audiosys CLK_AUDIO_MEM_ASRC2>,
+ <&audiosys CLK_AUDIO_MEM_ASRC3>,
+ <&audiosys CLK_AUDIO_MEM_ASRC4>,
+ <&audiosys CLK_AUDIO_MEM_ASRC5>,
+ <&ssusbsys CLK_SSUSB_U2_PHY_1P_EN>,
+ <&ssusbsys CLK_SSUSB_U2_PHY_EN>,
+ <&ssusbsys CLK_SSUSB_REF_EN>,
+ <&ssusbsys CLK_SSUSB_SYS_EN>,
+ <&ssusbsys CLK_SSUSB_MCU_EN>,
+ <&ssusbsys CLK_SSUSB_DMA_EN>,
+ <&pciesys CLK_PCIE_P1_AUX_EN>,
+ <&pciesys CLK_PCIE_P1_OBFF_EN>,
+ <&pciesys CLK_PCIE_P1_AHB_EN>,
+ <&pciesys CLK_PCIE_P1_AXI_EN>,
+ <&pciesys CLK_PCIE_P1_MAC_EN>,
+ <&pciesys CLK_PCIE_P1_PIPE_EN>,
+ <&pciesys CLK_PCIE_P0_AUX_EN>,
+ <&pciesys CLK_PCIE_P0_OBFF_EN>,
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+ <&pciesys CLK_PCIE_P0_AXI_EN>,
+ <&pciesys CLK_PCIE_P0_MAC_EN>,
+ <&pciesys CLK_PCIE_P0_PIPE_EN>,
+ <&pciesys CLK_SATA_AHB_EN>,
+ <&pciesys CLK_SATA_AXI_EN>,
+ <&pciesys CLK_SATA_ASIC_EN>,
+ <&pciesys CLK_SATA_RBC_EN>,
+ <&pciesys CLK_SATA_PM_EN>,
+ <&ethsys CLK_ETH_HSDMA_EN>,
+ <&ethsys CLK_ETH_ESW_EN>,
+ <&ethsys CLK_ETH_GP2_EN>,
+ <&ethsys CLK_ETH_GP1_EN>,
+ <&ethsys CLK_ETH_GP0_EN>,
+ <&sgmiisys CLK_SGMII_TX250M_EN>,
+ <&sgmiisys CLK_SGMII_RX250M_EN>,
+ <&sgmiisys CLK_SGMII_CDR_REF>,
+ <&sgmiisys CLK_SGMII_CDR_FB>;
+
+ clock-names = "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
+ "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35",
+ "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47",
+ "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
+ "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71",
+ "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83",
+ "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95",
+ "96", "97", "98", "99", "100", "101", "102", "103", "104", "105", "106",
+ "107", "108", "109", "110", "111", "112", "113", "114", "115", "116", "117",
+ "118", "119", "120", "121", "122", "123", "124", "125";
+ };
+
+ bring-up-pd-ethsys {
+ compatible = "mediatek,scpsys-bring-up";
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+ };
+
+ bring-up-pd-hif0 {
+ compatible = "mediatek,scpsys-bring-up";
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ };
+
+ bring-up-pd-hif1 {
+ compatible = "mediatek,scpsys-bring-up";
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-evb.dts b/arch/arm64/boot/dts/mediatek/mt7622-evb.dts
new file mode 100644
index 000000000000..4690d32a5eba
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622-evb.dts
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+ model = "MediaTek MT7622 EVB board";
+ compatible = "mediatek,mt7622-evb", "mediatek,mt7622";
+
+ chosen {
+ bootargs = "console=ttyS0,115200n1 root=/dev/ram \
+ initrd=0x44000000,0x615E36 loglevel=8 androidboot.hardware=mt7622 swiotlb=512";
+ };
+
+ dummy_codec:dummy_codec {
+ compatible = "mediatek,dummy-codec";
+ };
+
+ mmc_fixed_1v8_io: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ mmc_fixed_3v3_power: fixedregulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_power";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ memory {
+ reg = <0 0x40000000 0 0x3F000000>;
+ };
+
+ sound: sound {
+ compatible = "mediatek,mt7622-soc-machine";
+ mediatek,platform = <&afe>;
+ mediatek,audio-codec = <&dummy_codec>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins_default>;
+ status = "okay";
+ };
+};
+
+&bch {
+ status = "disabled";
+};
+
+&cpu0 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&cpu1 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&auxadc {
+ status = "okay";
+};
+
+&efuse {
+ status = "okay";
+};
+
+&eth {
+ mac-address = [00 00 00 00 00 00];
+ dma-coherent;
+ gmac1-support = "esw";
+ gmac2-support = "rgmii-2";
+ rgmii-mode-2 = "an";
+ gmac2-phy-address = <0x05>;
+ gmac1_txq_num = <1>;
+ gmac1_txq_txd_num = <2048>;
+ gmac2_txq_num = <1>;
+ gmac2_txq_txd_num = <1024>;
+ num_rx_desc = <2048>;
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ephy_default>;
+};
+
+&gsw {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&irrx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&irrx_pins_ir_input>;
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ status = "okay";
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_1v8_io>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ r_smpl = <1>;
+ cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_3v3_power>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nandc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins_default>;
+ status = "disabled";
+ flash@0 {
+ reg = <0>;
+ nand-ecc-mode = "hw";
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "Preloader";
+ reg = <0x00000 0x0080000>;
+ read-only;
+ };
+
+ partition@80000 {
+ label = "ATF";
+ reg = <0x80000 0x0040000>;
+ };
+
+ partition@c0000 {
+ label = "Bootloader";
+ reg = <0xc0000 0x0080000>;
+ };
+
+ partition@140000 {
+ label = "Config";
+ reg = <0x140000 0x0080000>;
+ };
+
+ partition@1c0000 {
+ label = "Factory";
+ reg = <0x1c0000 0x0040000>;
+ };
+
+ partition@200000 {
+ label = "Kernel";
+ reg = <0x200000 0x2000000>;
+ };
+
+ partition@2200000 {
+ label = "User_data";
+ reg = <0x2200000 0x4000000>;
+ };
+ };
+ };
+};
+
+&nor_flash {
+ status = "okay";
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ };
+};
+
+&pio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+ state_default:pinconf_default {
+ };
+
+ irrx_pins_ir_input: irrx_pin_ir {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_100_PWM6__FUNC_IR_R>;
+ bias-disable;
+ };
+ };
+
+ aud_pins_default: audiodefault {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_3_I2S_BCLK__FUNC_I2S_BCLK_OUT>,
+ <MT7622_PIN_4_I2S_WS__FUNC_I2S_WS_OUT>,
+ <MT7622_PIN_5_I2S_MCLK__FUNC_I2S_MCLK>,
+ <MT7622_PIN_2_I2S1_OUT__FUNC_I2S1_OUT>,
+ <MT7622_PIN_1_I2S1_IN__FUNC_I2S1_IN>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down;
+ };
+ };
+
+ i2c0_pins: i2c0@0 {
+ pins_bus {
+ pinmux = <MT7622_PIN_14_I2C_SDA__FUNC_I2C0_SDA>,
+ <MT7622_PIN_15_I2C_SCL__FUNC_I2C0_SCL>;
+ bias-disable;
+ };
+ };
+
+ mmc0_pins_default: mmc0default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ bias-pull-down;
+ };
+ };
+
+ mmc0_pins_uhs: mmc0@0{
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ mmc1_pins_default: mmc1default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins_insert {
+ pinmux = <MT7622_PIN_81_TXD3__FUNC_GPIO81>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_pins_uhs: mmc1@0 {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ nand_pins_default: nanddefault {
+ pins_dat {
+ pinmux = <MT7622_PIN_37_NCEB__FUNC_ND_CS_N>,
+ <MT7622_PIN_38_NWEB__FUNC_ND_WE_N>,
+ <MT7622_PIN_39_NREB__FUNC_ND_RE_N>,
+ <MT7622_PIN_40_NDL4__FUNC_ND_D4>,
+ <MT7622_PIN_41_NDL5__FUNC_ND_D5>,
+ <MT7622_PIN_42_NDL6__FUNC_ND_D6>,
+ <MT7622_PIN_43_NDL7__FUNC_ND_D7>,
+ <MT7622_PIN_44_NRB__FUNC_ND_RB_N>,
+ <MT7622_PIN_45_NCLE__FUNC_ND_CLE>,
+ <MT7622_PIN_46_NALE__FUNC_ND_ALE>,
+ <MT7622_PIN_47_NDL0__FUNC_ND_D0>,
+ <MT7622_PIN_48_NDL1__FUNC_ND_D1>,
+ <MT7622_PIN_49_NDL2__FUNC_ND_D2>,
+ <MT7622_PIN_50_NDL3__FUNC_ND_D3>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up;
+ };
+ };
+
+ snand_pins_default: snand@0 {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_8_SPI_WP__FUNC_SNFI_WP>,
+ <MT7622_PIN_9_SPI_HOLD__FUNC_SNFI_HOLD>,
+ <MT7622_PIN_11_SPI_MOSI__FUNC_SNFI_MOSI>,
+ <MT7622_PIN_12_SPI_MISO__FUNC_SNFI_MISO>,
+ <MT7622_PIN_13_SPI_CS__FUNC_SNFI_CS>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ pins_clk {
+ pinmux = <MT7622_PIN_10_SPI_CLK__FUNC_SNFI_CLK>;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+};
+
+&pwm {
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&sata_phy {
+ status = "okay";
+};
+
+&snand {
+ pinctrl-0 = <&snand_pins_default>;
+ status = "okay";
+ flash@0 {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "Preloader";
+ reg = <0x00000 0x0080000>;
+ read-only;
+ };
+
+ partition@80000 {
+ label = "ATF";
+ reg = <0x80000 0x0040000>;
+ };
+
+ partition@c0000 {
+ label = "Bootloader";
+ reg = <0xc0000 0x0080000>;
+ };
+
+ partition@140000 {
+ label = "Config";
+ reg = <0x140000 0x0080000>;
+ };
+
+ partition@1c0000 {
+ label = "Factory";
+ reg = <0x1c0000 0x0040000>;
+ };
+
+ partition@200000 {
+ label = "Kernel";
+ reg = <0x200000 0x2000000>;
+ };
+
+ partition@2200000 {
+ label = "User_data";
+ reg = <0x2200000 0x4000000>;
+ };
+ };
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pinctl0>;
+};
+
+&pcie1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pinctl1>;
+};
+
+&pio {
+ ephy_default: ephy_default {
+ pins_eth {
+ pinmux = <MT7622_PIN_23_MDC__FUNC_MDC>,
+ <MT7622_PIN_24_MDIO__FUNC_MDIO>,
+ <MT7622_PIN_25_G2_TXD0__FUNC_G2_TXD0>,
+ <MT7622_PIN_26_G2_TXD1__FUNC_G2_TXD1>,
+ <MT7622_PIN_27_G2_TXD2__FUNC_G2_TXD2>,
+ <MT7622_PIN_28_G2_TXD3__FUNC_G2_TXD3>,
+ <MT7622_PIN_29_G2_TXEN__FUNC_G2_TXEN>,
+ <MT7622_PIN_30_G2_TXC__FUNC_G2_TXC>,
+ <MT7622_PIN_31_G2_RXD0__FUNC_G2_RXD0>,
+ <MT7622_PIN_32_G2_RXD1__FUNC_G2_RXD1>,
+ <MT7622_PIN_33_G2_RXD2__FUNC_G2_RXD2>,
+ <MT7622_PIN_34_G2_RXD3__FUNC_G2_RXD3>,
+ <MT7622_PIN_35_G2_RXDV__FUNC_G2_RXDV>,
+ <MT7622_PIN_36_G2_RXC__FUNC_G2_RXC>;
+ };
+ };
+
+ pcie_pinctl0: pcie0 {
+ pcie0 {
+ pinmux = <MT7622_PIN_80_CTS3_N__FUNC_PCIE0_PAD_CLKREQ_N>,
+ <MT7622_PIN_79_RTS3_N__FUNC_PCIE0_PAD_WAKE_N>;
+ };
+ };
+
+ pcie_pinctl1: pcie1 {
+ pcie1 {
+ pinmux = <MT7622_PIN_15_I2C_SCL__FUNC_PCIE0_PAD_CLKREQ_N>,
+ <MT7622_PIN_14_I2C_SDA__FUNC_PCIE0_PAD_WAKE_N>;
+ };
+ };
+};
+
+&svs {
+ vproc-supply = <&mt6380_vcpu_reg>;
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-pinfunc.h b/arch/arm64/boot/dts/mediatek/mt7622-pinfunc.h
new file mode 100644
index 000000000000..c34d3ae5e5d5
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622-pinfunc.h
@@ -0,0 +1,582 @@
+/*
+ * Copyright (C) 2016 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DTS_MT7622_PINFUNC_H
+#define __DTS_MT7622_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define MT7622_PIN_0_GPIO_A__FUNC_GPIO0 (MTK_PIN_NO(0) | 1)
+
+#define MT7622_PIN_1_I2S1_IN__FUNC_I2S1_IN (MTK_PIN_NO(1) | 0)
+#define MT7622_PIN_1_I2S1_IN__FUNC_GPIO1 (MTK_PIN_NO(1) | 1)
+#define MT7622_PIN_1_I2S1_IN__FUNC_RTS2_N (MTK_PIN_NO(1) | 2)
+
+#define MT7622_PIN_2_I2S1_OUT__FUNC_I2S1_OUT (MTK_PIN_NO(2) | 0)
+#define MT7622_PIN_2_I2S1_OUT__FUNC_GPIO2 (MTK_PIN_NO(2) | 1)
+#define MT7622_PIN_2_I2S1_OUT__FUNC_CTS2_N (MTK_PIN_NO(2) | 2)
+
+#define MT7622_PIN_3_I2S_BCLK__FUNC_I2S_BCLK_OUT (MTK_PIN_NO(3) | 0)
+#define MT7622_PIN_3_I2S_BCLK__FUNC_GPIO3 (MTK_PIN_NO(3) | 1)
+#define MT7622_PIN_3_I2S_BCLK__FUNC_TXD2 (MTK_PIN_NO(3) | 2)
+#define MT7622_PIN_3_I2S_BCLK__FUNC_I2S_BCLK_IN (MTK_PIN_NO(3) | 3)
+
+#define MT7622_PIN_4_I2S_WS__FUNC_I2S_WS_OUT (MTK_PIN_NO(4) | 0)
+#define MT7622_PIN_4_I2S_WS__FUNC_GPIO4 (MTK_PIN_NO(4) | 1)
+#define MT7622_PIN_4_I2S_WS__FUNC_RXD2 (MTK_PIN_NO(4) | 2)
+#define MT7622_PIN_4_I2S_WS__FUNC_I2S_WS_IN (MTK_PIN_NO(4) | 3)
+
+#define MT7622_PIN_5_I2S_MCLK__FUNC_I2S_MCLK (MTK_PIN_NO(5) | 0)
+#define MT7622_PIN_5_I2S_MCLK__FUNC_GPIO5 (MTK_PIN_NO(5) | 1)
+#define MT7622_PIN_5_I2S_MCLK__FUNC_DBG_UTIF17 (MTK_PIN_NO(5) | 7)
+
+#define MT7622_PIN_6_TXD0__FUNC_TXD0 (MTK_PIN_NO(6) | 0)
+#define MT7622_PIN_6_TXD0__FUNC_GPIO6 (MTK_PIN_NO(6) | 1)
+#define MT7622_PIN_6_TXD0__FUNC_TM_SUTIF_TXD (MTK_PIN_NO(6) | 7)
+
+#define MT7622_PIN_7_RXD0__FUNC_RXD0 (MTK_PIN_NO(7) | 0)
+#define MT7622_PIN_7_RXD0__FUNC_GPIO7 (MTK_PIN_NO(7) | 1)
+#define MT7622_PIN_7_RXD0__FUNC_TM_SUTIF_RXD (MTK_PIN_NO(7) | 7)
+
+#define MT7622_PIN_8_SPI_WP__FUNC_SPI_WP (MTK_PIN_NO(8) | 0)
+#define MT7622_PIN_8_SPI_WP__FUNC_GPIO8 (MTK_PIN_NO(8) | 1)
+#define MT7622_PIN_8_SPI_WP__FUNC_SNFI_WP (MTK_PIN_NO(8) | 2)
+#define MT7622_PIN_8_SPI_WP__FUNC_TDM_OUT_MCLK (MTK_PIN_NO(8) | 3)
+#define MT7622_PIN_8_SPI_WP__FUNC_FPC_DAT_STS (MTK_PIN_NO(8) | 6)
+
+#define MT7622_PIN_9_SPI_HOLD__FUNC_SPI_HOLD (MTK_PIN_NO(9) | 0)
+#define MT7622_PIN_9_SPI_HOLD__FUNC_GPIO9 (MTK_PIN_NO(9) | 1)
+#define MT7622_PIN_9_SPI_HOLD__FUNC_SNFI_HOLD (MTK_PIN_NO(9) | 2)
+#define MT7622_PIN_9_SPI_HOLD__FUNC_TDM_OUT_BCLK (MTK_PIN_NO(9) | 3)
+#define MT7622_PIN_9_SPI_HOLD__FUNC_FPC_DL_STS (MTK_PIN_NO(9) | 6)
+
+#define MT7622_PIN_10_SPI_CLK__FUNC_SPI_CLK (MTK_PIN_NO(10) | 0)
+#define MT7622_PIN_10_SPI_CLK__FUNC_GPIO10 (MTK_PIN_NO(10) | 1)
+#define MT7622_PIN_10_SPI_CLK__FUNC_SNFI_CLK (MTK_PIN_NO(10) | 2)
+#define MT7622_PIN_10_SPI_CLK__FUNC_TDM_OUT_WS (MTK_PIN_NO(10) | 3)
+
+#define MT7622_PIN_11_SPI_MOSI__FUNC_SPI_MOSI (MTK_PIN_NO(11) | 0)
+#define MT7622_PIN_11_SPI_MOSI__FUNC_GPIO11 (MTK_PIN_NO(11) | 1)
+#define MT7622_PIN_11_SPI_MOSI__FUNC_SNFI_MOSI (MTK_PIN_NO(11) | 2)
+#define MT7622_PIN_11_SPI_MOSI__FUNC_TDM_IN_MCLK (MTK_PIN_NO(11) | 3)
+
+#define MT7622_PIN_12_SPI_MISO__FUNC_SPI_MISO (MTK_PIN_NO(12) | 0)
+#define MT7622_PIN_12_SPI_MISO__FUNC_GPIO12 (MTK_PIN_NO(12) | 1)
+#define MT7622_PIN_12_SPI_MISO__FUNC_SNFI_MISO (MTK_PIN_NO(12) | 2)
+#define MT7622_PIN_12_SPI_MISO__FUNC_TDM_IN_BCLK (MTK_PIN_NO(12) | 3)
+
+#define MT7622_PIN_13_SPI_CS__FUNC_SPI_CS (MTK_PIN_NO(13) | 0)
+#define MT7622_PIN_13_SPI_CS__FUNC_GPIO13 (MTK_PIN_NO(13) | 1)
+#define MT7622_PIN_13_SPI_CS__FUNC_SNFI_CS (MTK_PIN_NO(13) | 2)
+#define MT7622_PIN_13_SPI_CS__FUNC_TDM_IN_WS (MTK_PIN_NO(13) | 3)
+
+#define MT7622_PIN_14_I2C_SDA__FUNC_I2C0_SDA (MTK_PIN_NO(14) | 0)
+#define MT7622_PIN_14_I2C_SDA__FUNC_GPIO14 (MTK_PIN_NO(14) | 1)
+#define MT7622_PIN_14_I2C_SDA__FUNC_PCIE0_PAD_WAKE_N (MTK_PIN_NO(14) | 2)
+#define MT7622_PIN_14_I2C_SDA__FUNC_PCIE1_PAD_WAKE_N (MTK_PIN_NO(14) | 3)
+#define MT7622_PIN_14_I2C_SDA__FUNC_ANTSEL22 (MTK_PIN_NO(14) | 5)
+#define MT7622_PIN_14_I2C_SDA__FUNC_TM_EXT_BGCK (MTK_PIN_NO(14) | 7)
+
+#define MT7622_PIN_15_I2C_SCL__FUNC_I2C0_SCL (MTK_PIN_NO(15) | 0)
+#define MT7622_PIN_15_I2C_SCL__FUNC_GPIO15 (MTK_PIN_NO(15) | 1)
+#define MT7622_PIN_15_I2C_SCL__FUNC_PCIE0_PAD_CLKREQ_N (MTK_PIN_NO(15) | 2)
+#define MT7622_PIN_15_I2C_SCL__FUNC_PCIE1_PAD_CLKREQ_N (MTK_PIN_NO(15) | 3)
+#define MT7622_PIN_15_I2C_SCL__FUNC_ANTSEL23 (MTK_PIN_NO(15) | 5)
+
+#define MT7622_PIN_16_I2S2_IN__FUNC_I2S2_IN (MTK_PIN_NO(16) | 0)
+#define MT7622_PIN_16_I2S2_IN__FUNC_GPIO16 (MTK_PIN_NO(16) | 1)
+#define MT7622_PIN_16_I2S2_IN__FUNC_SD_D3 (MTK_PIN_NO(16) | 2)
+#define MT7622_PIN_16_I2S2_IN__FUNC_IR_T (MTK_PIN_NO(16) | 4)
+#define MT7622_PIN_16_I2S2_IN__FUNC_ANTSEL24 (MTK_PIN_NO(16) | 5)
+#define MT7622_PIN_16_I2S2_IN__FUNC_BT_EPA_EN (MTK_PIN_NO(16) | 6)
+#define MT7622_PIN_16_I2S2_IN__FUNC_DBG_UTIF10 (MTK_PIN_NO(16) | 7)
+
+#define MT7622_PIN_17_I2S3_IN__FUNC_I2S3_IN (MTK_PIN_NO(17) | 0)
+#define MT7622_PIN_17_I2S3_IN__FUNC_GPIO17 (MTK_PIN_NO(17) | 1)
+#define MT7622_PIN_17_I2S3_IN__FUNC_SD_D2 (MTK_PIN_NO(17) | 2)
+#define MT7622_PIN_17_I2S3_IN__FUNC_IR_R (MTK_PIN_NO(17) | 4)
+#define MT7622_PIN_17_I2S3_IN__FUNC_ANTSEL25 (MTK_PIN_NO(17) | 5)
+#define MT7622_PIN_17_I2S3_IN__FUNC_BT_ELNA_EN (MTK_PIN_NO(17) | 6)
+#define MT7622_PIN_17_I2S3_IN__FUNC_DBG_UTIF11 (MTK_PIN_NO(17) | 7)
+
+#define MT7622_PIN_18_I2S4_IN__FUNC_I2S4_IN (MTK_PIN_NO(18) | 0)
+#define MT7622_PIN_18_I2S4_IN__FUNC_GPIO18 (MTK_PIN_NO(18) | 1)
+#define MT7622_PIN_18_I2S4_IN__FUNC_SD_D1 (MTK_PIN_NO(18) | 2)
+#define MT7622_PIN_18_I2S4_IN__FUNC_ANTSEL26 (MTK_PIN_NO(18) | 5)
+#define MT7622_PIN_18_I2S4_IN__FUNC_BT_ERX_EN (MTK_PIN_NO(18) | 6)
+#define MT7622_PIN_18_I2S4_IN__FUNC_DBG_UTIF12 (MTK_PIN_NO(18) | 7)
+
+#define MT7622_PIN_19_I2S2_OUT__FUNC_I2S2_OUT (MTK_PIN_NO(19) | 0)
+#define MT7622_PIN_19_I2S2_OUT__FUNC_GPIO19 (MTK_PIN_NO(19) | 1)
+#define MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0 (MTK_PIN_NO(19) | 2)
+#define MT7622_PIN_19_I2S2_OUT__FUNC_ANTSEL27 (MTK_PIN_NO(19) | 5)
+#define MT7622_PIN_19_I2S2_OUT__FUNC_BT_IPATH_EN (MTK_PIN_NO(19) | 6)
+#define MT7622_PIN_19_I2S2_OUT__FUNC_DBG_UTIF13 (MTK_PIN_NO(19) | 7)
+
+#define MT7622_PIN_20_I2S3_OUT__FUNC_I2S3_OUT (MTK_PIN_NO(20) | 0)
+#define MT7622_PIN_20_I2S3_OUT__FUNC_GPIO20 (MTK_PIN_NO(20) | 1)
+#define MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK (MTK_PIN_NO(20) | 2)
+#define MT7622_PIN_20_I2S3_OUT__FUNC_TDM_OUT_DATA (MTK_PIN_NO(20) | 3)
+#define MT7622_PIN_20_I2S3_OUT__FUNC_ANTSEL28 (MTK_PIN_NO(20) | 5)
+#define MT7622_PIN_20_I2S3_OUT__FUNC_BT_SPXT_C1 (MTK_PIN_NO(20) | 6)
+#define MT7622_PIN_20_I2S3_OUT__FUNC_DBG_UTIF14 (MTK_PIN_NO(20) | 7)
+
+#define MT7622_PIN_21_I2S4_OUT__FUNC_I2S4_OUT (MTK_PIN_NO(21) | 0)
+#define MT7622_PIN_21_I2S4_OUT__FUNC_GPIO21 (MTK_PIN_NO(21) | 1)
+#define MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD (MTK_PIN_NO(21) | 2)
+#define MT7622_PIN_21_I2S4_OUT__FUNC_TDM_IN_DATA (MTK_PIN_NO(21) | 3)
+#define MT7622_PIN_21_I2S4_OUT__FUNC_ANTSEL29 (MTK_PIN_NO(21) | 5)
+#define MT7622_PIN_21_I2S4_OUT__FUNC_BT_SPXT_C0 (MTK_PIN_NO(21) | 6)
+#define MT7622_PIN_21_I2S4_OUT__FUNC_DBG_UTIF15 (MTK_PIN_NO(21) | 7)
+
+#define MT7622_PIN_22_GPIO_B__FUNC_GPIO22 (MTK_PIN_NO(22) | 1)
+#define MT7622_PIN_22_GPIO_B__FUNC_TSF_INTR (MTK_PIN_NO(22) | 3)
+#define MT7622_PIN_22_GPIO_B__FUNC_ANTSEL17 (MTK_PIN_NO(22) | 5)
+#define MT7622_PIN_22_GPIO_B__FUNC_DBG_UTIF16 (MTK_PIN_NO(22) | 7)
+
+#define MT7622_PIN_23_MDC__FUNC_MDC (MTK_PIN_NO(23) | 0)
+#define MT7622_PIN_23_MDC__FUNC_GPIO23 (MTK_PIN_NO(23) | 1)
+
+#define MT7622_PIN_24_MDIO__FUNC_MDIO (MTK_PIN_NO(24) | 0)
+#define MT7622_PIN_24_MDIO__FUNC_GPIO24 (MTK_PIN_NO(24) | 1)
+
+#define MT7622_PIN_25_G2_TXD0__FUNC_G2_TXD0 (MTK_PIN_NO(25) | 0)
+#define MT7622_PIN_25_G2_TXD0__FUNC_GPIO25 (MTK_PIN_NO(25) | 1)
+#define MT7622_PIN_25_G2_TXD0__FUNC_SD_D3 (MTK_PIN_NO(25) | 2)
+
+#define MT7622_PIN_26_G2_TXD1__FUNC_G2_TXD1 (MTK_PIN_NO(26) | 0)
+#define MT7622_PIN_26_G2_TXD1__FUNC_GPIO26 (MTK_PIN_NO(26) | 1)
+#define MT7622_PIN_26_G2_TXD1__FUNC_SD_D2 (MTK_PIN_NO(26) | 2)
+
+#define MT7622_PIN_27_G2_TXD2__FUNC_G2_TXD2 (MTK_PIN_NO(27) | 0)
+#define MT7622_PIN_27_G2_TXD2__FUNC_GPIO27 (MTK_PIN_NO(27) | 1)
+#define MT7622_PIN_27_G2_TXD2__FUNC_SD_D1 (MTK_PIN_NO(27) | 2)
+
+#define MT7622_PIN_28_G2_TXD3__FUNC_G2_TXD3 (MTK_PIN_NO(28) | 0)
+#define MT7622_PIN_28_G2_TXD3__FUNC_GPIO28 (MTK_PIN_NO(28) | 1)
+#define MT7622_PIN_28_G2_TXD3__FUNC_SD_D0 (MTK_PIN_NO(28) | 2)
+
+#define MT7622_PIN_29_G2_TXEN__FUNC_G2_TXEN (MTK_PIN_NO(29) | 0)
+#define MT7622_PIN_29_G2_TXEN__FUNC_GPIO29 (MTK_PIN_NO(29) | 1)
+#define MT7622_PIN_29_G2_TXEN__FUNC_SD_CLK (MTK_PIN_NO(29) | 2)
+
+#define MT7622_PIN_30_G2_TXC__FUNC_G2_TXC (MTK_PIN_NO(30) | 0)
+#define MT7622_PIN_30_G2_TXC__FUNC_GPIO30 (MTK_PIN_NO(30) | 1)
+#define MT7622_PIN_30_G2_TXC__FUNC_SD_CMD (MTK_PIN_NO(30) | 2)
+
+#define MT7622_PIN_31_G2_RXD0__FUNC_G2_RXD0 (MTK_PIN_NO(31) | 0)
+#define MT7622_PIN_31_G2_RXD0__FUNC_GPIO31 (MTK_PIN_NO(31) | 1)
+#define MT7622_PIN_31_G2_RXD0__FUNC_G2_GPIO31 (MTK_PIN_NO(31) | 2)
+
+#define MT7622_PIN_32_G2_RXD1__FUNC_G2_RXD1 (MTK_PIN_NO(32) | 0)
+#define MT7622_PIN_32_G2_RXD1__FUNC_GPIO32 (MTK_PIN_NO(32) | 1)
+#define MT7622_PIN_32_G2_RXD1__FUNC_G2_GPIO32 (MTK_PIN_NO(32) | 2)
+
+#define MT7622_PIN_33_G2_RXD2__FUNC_G2_RXD2 (MTK_PIN_NO(33) | 0)
+#define MT7622_PIN_33_G2_RXD2__FUNC_GPIO33 (MTK_PIN_NO(33) | 1)
+#define MT7622_PIN_33_G2_RXD2__FUNC_G2_GPIO33 (MTK_PIN_NO(33) | 2)
+
+#define MT7622_PIN_34_G2_RXD3__FUNC_G2_RXD3 (MTK_PIN_NO(34) | 0)
+#define MT7622_PIN_34_G2_RXD3__FUNC_GPIO34 (MTK_PIN_NO(34) | 1)
+#define MT7622_PIN_34_G2_RXD3__FUNC_G2_GPIO34 (MTK_PIN_NO(34) | 2)
+
+#define MT7622_PIN_35_G2_RXDV__FUNC_G2_RXDV (MTK_PIN_NO(35) | 0)
+#define MT7622_PIN_35_G2_RXDV__FUNC_GPIO35 (MTK_PIN_NO(35) | 1)
+#define MT7622_PIN_35_G2_RXDV__FUNC_G2_GPIO35 (MTK_PIN_NO(35) | 2)
+
+#define MT7622_PIN_36_G2_RXC__FUNC_G2_RXC (MTK_PIN_NO(36) | 0)
+#define MT7622_PIN_36_G2_RXC__FUNC_GPIO36 (MTK_PIN_NO(36) | 1)
+#define MT7622_PIN_36_G2_RXC__FUNC_G2_GPIO36 (MTK_PIN_NO(36) | 2)
+
+#define MT7622_PIN_37_NCEB__FUNC_ND_CS_N (MTK_PIN_NO(37) | 0)
+#define MT7622_PIN_37_NCEB__FUNC_GPIO37 (MTK_PIN_NO(37) | 1)
+#define MT7622_PIN_37_NCEB__FUNC_G2_GPIO37 (MTK_PIN_NO(37) | 2)
+#define MT7622_PIN_37_NCEB__FUNC_DBG_UTIF18 (MTK_PIN_NO(37) | 7)
+
+#define MT7622_PIN_38_NWEB__FUNC_ND_WE_N (MTK_PIN_NO(38) | 0)
+#define MT7622_PIN_38_NWEB__FUNC_GPIO38 (MTK_PIN_NO(38) | 1)
+#define MT7622_PIN_38_NWEB__FUNC_G2_GPIO38 (MTK_PIN_NO(38) | 2)
+#define MT7622_PIN_38_NWEB__FUNC_DBG_UTIF19 (MTK_PIN_NO(38) | 7)
+
+#define MT7622_PIN_39_NREB__FUNC_ND_RE_N (MTK_PIN_NO(39) | 0)
+#define MT7622_PIN_39_NREB__FUNC_GPIO39 (MTK_PIN_NO(39) | 1)
+#define MT7622_PIN_39_NREB__FUNC_G2_GPIO39 (MTK_PIN_NO(39) | 2)
+#define MT7622_PIN_39_NREB__FUNC_DBG_UTIF20 (MTK_PIN_NO(39) | 7)
+
+#define MT7622_PIN_40_NDL4__FUNC_ND_D4 (MTK_PIN_NO(40) | 0)
+#define MT7622_PIN_40_NDL4__FUNC_GPIO40 (MTK_PIN_NO(40) | 1)
+#define MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4 (MTK_PIN_NO(40) | 2)
+#define MT7622_PIN_40_NDL4__FUNC_DBG_UTIF21 (MTK_PIN_NO(40) | 7)
+
+#define MT7622_PIN_41_NDL5__FUNC_ND_D5 (MTK_PIN_NO(41) | 0)
+#define MT7622_PIN_41_NDL5__FUNC_GPIO41 (MTK_PIN_NO(41) | 1)
+#define MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5 (MTK_PIN_NO(41) | 2)
+#define MT7622_PIN_41_NDL5__FUNC_DBG_UTIF22 (MTK_PIN_NO(41) | 7)
+
+#define MT7622_PIN_42_NDL6__FUNC_ND_D6 (MTK_PIN_NO(42) | 0)
+#define MT7622_PIN_42_NDL6__FUNC_GPIO42 (MTK_PIN_NO(42) | 1)
+#define MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6 (MTK_PIN_NO(42) | 2)
+#define MT7622_PIN_42_NDL6__FUNC_DBG_UTIF23 (MTK_PIN_NO(42) | 7)
+
+#define MT7622_PIN_43_NDL7__FUNC_ND_D7 (MTK_PIN_NO(43) | 0)
+#define MT7622_PIN_43_NDL7__FUNC_GPIO43 (MTK_PIN_NO(43) | 1)
+#define MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7 (MTK_PIN_NO(43) | 2)
+#define MT7622_PIN_43_NDL7__FUNC_DBG_UTIF24 (MTK_PIN_NO(43) | 7)
+
+#define MT7622_PIN_44_NRB__FUNC_ND_RB_N (MTK_PIN_NO(44) | 0)
+#define MT7622_PIN_44_NRB__FUNC_GPIO44 (MTK_PIN_NO(44) | 1)
+#define MT7622_PIN_44_NRB__FUNC_EMMC_CMD (MTK_PIN_NO(44) | 2)
+#define MT7622_PIN_44_NRB__FUNC_DBG_UTIF25 (MTK_PIN_NO(44) | 7)
+
+#define MT7622_PIN_45_NCLE__FUNC_ND_CLE (MTK_PIN_NO(45) | 0)
+#define MT7622_PIN_45_NCLE__FUNC_GPIO45 (MTK_PIN_NO(45) | 1)
+#define MT7622_PIN_45_NCLE__FUNC_EMMC_CK (MTK_PIN_NO(45) | 2)
+#define MT7622_PIN_45_NCLE__FUNC_DBG_UTIF26 (MTK_PIN_NO(45) | 7)
+
+#define MT7622_PIN_46_NALE__FUNC_ND_ALE (MTK_PIN_NO(46) | 0)
+#define MT7622_PIN_46_NALE__FUNC_GPIO46 (MTK_PIN_NO(46) | 1)
+#define MT7622_PIN_46_NALE__FUNC_G2_GPIO46 (MTK_PIN_NO(46) | 2)
+#define MT7622_PIN_46_NALE__FUNC_DBG_UTIF27 (MTK_PIN_NO(46) | 7)
+
+#define MT7622_PIN_47_NDL0__FUNC_ND_D0 (MTK_PIN_NO(47) | 0)
+#define MT7622_PIN_47_NDL0__FUNC_GPIO47 (MTK_PIN_NO(47) | 1)
+#define MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0 (MTK_PIN_NO(47) | 2)
+#define MT7622_PIN_47_NDL0__FUNC_DBG_UTIF28 (MTK_PIN_NO(47) | 7)
+
+#define MT7622_PIN_48_NDL1__FUNC_ND_D1 (MTK_PIN_NO(48) | 0)
+#define MT7622_PIN_48_NDL1__FUNC_GPIO48 (MTK_PIN_NO(48) | 1)
+#define MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1 (MTK_PIN_NO(48) | 2)
+#define MT7622_PIN_48_NDL1__FUNC_DBG_UTIF29 (MTK_PIN_NO(48) | 7)
+
+#define MT7622_PIN_49_NDL2__FUNC_ND_D2 (MTK_PIN_NO(49) | 0)
+#define MT7622_PIN_49_NDL2__FUNC_GPIO49 (MTK_PIN_NO(49) | 1)
+#define MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2 (MTK_PIN_NO(49) | 2)
+#define MT7622_PIN_49_NDL2__FUNC_DBG_UTIF30 (MTK_PIN_NO(49) | 7)
+
+#define MT7622_PIN_50_NDL3__FUNC_ND_D3 (MTK_PIN_NO(50) | 0)
+#define MT7622_PIN_50_NDL3__FUNC_GPIO50 (MTK_PIN_NO(50) | 1)
+#define MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3 (MTK_PIN_NO(50) | 2)
+#define MT7622_PIN_50_NDL3__FUNC_DBG_UTIF31 (MTK_PIN_NO(50) | 7)
+
+#define MT7622_PIN_51_MDI_TP_P0__FUNC_TXD2 (MTK_PIN_NO(51) | 0)
+#define MT7622_PIN_51_MDI_TP_P0__FUNC_GPIO51 (MTK_PIN_NO(51) | 1)
+#define MT7622_PIN_51_MDI_TP_P0__FUNC_PWM_CH1 (MTK_PIN_NO(51) | 3)
+
+#define MT7622_PIN_52_MDI_TN_P0__FUNC_RXD2 (MTK_PIN_NO(52) | 0)
+#define MT7622_PIN_52_MDI_TN_P0__FUNC_GPIO52 (MTK_PIN_NO(52) | 1)
+#define MT7622_PIN_52_MDI_TN_P0__FUNC_PWM_CH2 (MTK_PIN_NO(52) | 3)
+
+#define MT7622_PIN_53_MDI_RP_P0__FUNC_RTS2_N (MTK_PIN_NO(53) | 0)
+#define MT7622_PIN_53_MDI_RP_P0__FUNC_GPIO53 (MTK_PIN_NO(53) | 1)
+#define MT7622_PIN_53_MDI_RP_P0__FUNC_PWM_CH3 (MTK_PIN_NO(53) | 3)
+
+#define MT7622_PIN_54_MDI_RN_P0__FUNC_CTS2_N (MTK_PIN_NO(54) | 0)
+#define MT7622_PIN_54_MDI_RN_P0__FUNC_GPIO54 (MTK_PIN_NO(54) | 1)
+#define MT7622_PIN_54_MDI_RN_P0__FUNC_PWM_CH4 (MTK_PIN_NO(54) | 3)
+
+#define MT7622_PIN_55_MDI_TP_P1__FUNC_I2C1_SCL (MTK_PIN_NO(55) | 0)
+#define MT7622_PIN_55_MDI_TP_P1__FUNC_GPIO55 (MTK_PIN_NO(55) | 1)
+#define MT7622_PIN_55_MDI_TP_P1__FUNC_TXD1 (MTK_PIN_NO(55) | 2)
+#define MT7622_PIN_55_MDI_TP_P1__FUNC_TDM_OUT_DATA (MTK_PIN_NO(55) | 3)
+
+#define MT7622_PIN_56_MDI_TN_P1__FUNC_I2C1_SDA (MTK_PIN_NO(56) | 0)
+#define MT7622_PIN_56_MDI_TN_P1__FUNC_GPIO56 (MTK_PIN_NO(56) | 1)
+#define MT7622_PIN_56_MDI_TN_P1__FUNC_RXD1 (MTK_PIN_NO(56) | 2)
+#define MT7622_PIN_56_MDI_TN_P1__FUNC_TDM_IN_DATA (MTK_PIN_NO(56) | 3)
+
+#define MT7622_PIN_57_MDI_RP_P1__FUNC_I2C2_SCL (MTK_PIN_NO(57) | 0)
+#define MT7622_PIN_57_MDI_RP_P1__FUNC_GPIO57 (MTK_PIN_NO(57) | 1)
+#define MT7622_PIN_57_MDI_RP_P1__FUNC_RTS1_N (MTK_PIN_NO(57) | 2)
+#define MT7622_PIN_57_MDI_RP_P1__FUNC_TDM_OUT_MCLK (MTK_PIN_NO(57) | 3)
+#define MT7622_PIN_57_MDI_RP_P1__FUNC_TXD3 (MTK_PIN_NO(57) | 5)
+
+#define MT7622_PIN_58_MDI_RN_P1__FUNC_I2C2_SDA (MTK_PIN_NO(58) | 0)
+#define MT7622_PIN_58_MDI_RN_P1__FUNC_GPIO58 (MTK_PIN_NO(58) | 1)
+#define MT7622_PIN_58_MDI_RN_P1__FUNC_CTS1_N (MTK_PIN_NO(58) | 2)
+#define MT7622_PIN_58_MDI_RN_P1__FUNC_TDM_OUT_BCLK (MTK_PIN_NO(58) | 3)
+#define MT7622_PIN_58_MDI_RN_P1__FUNC_RXD3 (MTK_PIN_NO(58) | 5)
+
+#define MT7622_PIN_59_MDI_RP_P2__FUNC_ESW_TXD0 (MTK_PIN_NO(59) | 0)
+#define MT7622_PIN_59_MDI_RP_P2__FUNC_GPIO59 (MTK_PIN_NO(59) | 1)
+#define MT7622_PIN_59_MDI_RP_P2__FUNC_G1_TXD0 (MTK_PIN_NO(59) | 2)
+#define MT7622_PIN_59_MDI_RP_P2__FUNC_TDM_OUT_WS (MTK_PIN_NO(59) | 3)
+#define MT7622_PIN_59_MDI_RP_P2__FUNC_TXD2 (MTK_PIN_NO(59) | 4)
+#define MT7622_PIN_59_MDI_RP_P2__FUNC_IR_T (MTK_PIN_NO(59) | 5)
+
+#define MT7622_PIN_60_MDI_RN_P2__FUNC_ESW_TXD1 (MTK_PIN_NO(60) | 0)
+#define MT7622_PIN_60_MDI_RN_P2__FUNC_GPIO60 (MTK_PIN_NO(60) | 1)
+#define MT7622_PIN_60_MDI_RN_P2__FUNC_G1_TXD1 (MTK_PIN_NO(60) | 2)
+#define MT7622_PIN_60_MDI_RN_P2__FUNC_TDM_IN_MCLK (MTK_PIN_NO(60) | 3)
+#define MT7622_PIN_60_MDI_RN_P2__FUNC_RXD2 (MTK_PIN_NO(60) | 4)
+#define MT7622_PIN_60_MDI_RN_P2__FUNC_IR_R (MTK_PIN_NO(60) | 5)
+
+#define MT7622_PIN_61_MDI_TP_P2__FUNC_ESW_TXD2 (MTK_PIN_NO(61) | 0)
+#define MT7622_PIN_61_MDI_TP_P2__FUNC_GPIO61 (MTK_PIN_NO(61) | 1)
+#define MT7622_PIN_61_MDI_TP_P2__FUNC_G1_TXD2 (MTK_PIN_NO(61) | 2)
+#define MT7622_PIN_61_MDI_TP_P2__FUNC_TDM_IN_BCLK (MTK_PIN_NO(61) | 3)
+#define MT7622_PIN_61_MDI_TP_P2__FUNC_RTS2_N (MTK_PIN_NO(61) | 4)
+#define MT7622_PIN_61_MDI_TP_P2__FUNC_TXD4 (MTK_PIN_NO(61) | 5)
+
+#define MT7622_PIN_62_MDI_TN_P2__FUNC_ESW_TXD3 (MTK_PIN_NO(62) | 0)
+#define MT7622_PIN_62_MDI_TN_P2__FUNC_GPIO62 (MTK_PIN_NO(62) | 1)
+#define MT7622_PIN_62_MDI_TN_P2__FUNC_G1_TXD3 (MTK_PIN_NO(62) | 2)
+#define MT7622_PIN_62_MDI_TN_P2__FUNC_TDM_IN_WS (MTK_PIN_NO(62) | 3)
+#define MT7622_PIN_62_MDI_TN_P2__FUNC_CTS2_N (MTK_PIN_NO(62) | 4)
+#define MT7622_PIN_62_MDI_TN_P2__FUNC_RXD4 (MTK_PIN_NO(62) | 5)
+
+#define MT7622_PIN_63_MDI_TP_P3__FUNC_ESW_TXEN (MTK_PIN_NO(63) | 0)
+#define MT7622_PIN_63_MDI_TP_P3__FUNC_GPIO63 (MTK_PIN_NO(63) | 1)
+#define MT7622_PIN_63_MDI_TP_P3__FUNC_G1_TXEN (MTK_PIN_NO(63) | 2)
+#define MT7622_PIN_63_MDI_TP_P3__FUNC_SPIC0_CLK (MTK_PIN_NO(63) | 4)
+
+#define MT7622_PIN_64_MDI_TN_P3__FUNC_ESW_TXC (MTK_PIN_NO(64) | 0)
+#define MT7622_PIN_64_MDI_TN_P3__FUNC_GPIO64 (MTK_PIN_NO(64) | 1)
+#define MT7622_PIN_64_MDI_TN_P3__FUNC_G1_TXC (MTK_PIN_NO(64) | 2)
+#define MT7622_PIN_64_MDI_TN_P3__FUNC_SPIC0_MOSI (MTK_PIN_NO(64) | 4)
+
+#define MT7622_PIN_65_MDI_RP_P3__FUNC_ESW_RXD0 (MTK_PIN_NO(65) | 0)
+#define MT7622_PIN_65_MDI_RP_P3__FUNC_GPIO65 (MTK_PIN_NO(65) | 1)
+#define MT7622_PIN_65_MDI_RP_P3__FUNC_G1_RXD0 (MTK_PIN_NO(65) | 2)
+#define MT7622_PIN_65_MDI_RP_P3__FUNC_SPIC0_MISO (MTK_PIN_NO(65) | 4)
+
+#define MT7622_PIN_66_MDI_RN_P3__FUNC_ESW_RXD1 (MTK_PIN_NO(66) | 0)
+#define MT7622_PIN_66_MDI_RN_P3__FUNC_GPIO66 (MTK_PIN_NO(66) | 1)
+#define MT7622_PIN_66_MDI_RN_P3__FUNC_G1_RXD1 (MTK_PIN_NO(66) | 2)
+#define MT7622_PIN_66_MDI_RN_P3__FUNC_SPIC0_CS (MTK_PIN_NO(66) | 4)
+
+#define MT7622_PIN_67_MDI_RP_P4__FUNC_ESW_RXD2 (MTK_PIN_NO(67) | 0)
+#define MT7622_PIN_67_MDI_RP_P4__FUNC_GPIO67 (MTK_PIN_NO(67) | 1)
+#define MT7622_PIN_67_MDI_RP_P4__FUNC_G1_RXD2 (MTK_PIN_NO(67) | 2)
+#define MT7622_PIN_67_MDI_RP_P4__FUNC_PWM_CH4 (MTK_PIN_NO(67) | 3)
+#define MT7622_PIN_67_MDI_RP_P4__FUNC_SPIC1_CLK (MTK_PIN_NO(67) | 4)
+
+#define MT7622_PIN_68_MDI_RN_P4__FUNC_ESW_RXD3 (MTK_PIN_NO(68) | 0)
+#define MT7622_PIN_68_MDI_RN_P4__FUNC_GPIO68 (MTK_PIN_NO(68) | 1)
+#define MT7622_PIN_68_MDI_RN_P4__FUNC_G1_RXD3 (MTK_PIN_NO(68) | 2)
+#define MT7622_PIN_68_MDI_RN_P4__FUNC_PWM_CH5 (MTK_PIN_NO(68) | 3)
+#define MT7622_PIN_68_MDI_RN_P4__FUNC_SPIC1_MOSI (MTK_PIN_NO(68) | 4)
+
+#define MT7622_PIN_69_MDI_TP_P4__FUNC_ESW_RXDV (MTK_PIN_NO(69) | 0)
+#define MT7622_PIN_69_MDI_TP_P4__FUNC_GPIO69 (MTK_PIN_NO(69) | 1)
+#define MT7622_PIN_69_MDI_TP_P4__FUNC_G1_RXDV (MTK_PIN_NO(69) | 2)
+#define MT7622_PIN_69_MDI_TP_P4__FUNC_PWM_CH6 (MTK_PIN_NO(69) | 3)
+#define MT7622_PIN_69_MDI_TP_P4__FUNC_SPIC1_MISO (MTK_PIN_NO(69) | 4)
+
+#define MT7622_PIN_70_MDI_TN_P4__FUNC_ESW_RXC (MTK_PIN_NO(70) | 0)
+#define MT7622_PIN_70_MDI_TN_P4__FUNC_GPIO70 (MTK_PIN_NO(70) | 1)
+#define MT7622_PIN_70_MDI_TN_P4__FUNC_G1_RXC (MTK_PIN_NO(70) | 2)
+#define MT7622_PIN_70_MDI_TN_P4__FUNC_PWM_CH7 (MTK_PIN_NO(70) | 3)
+#define MT7622_PIN_70_MDI_TN_P4__FUNC_SPIC1_CS (MTK_PIN_NO(70) | 4)
+
+#define MT7622_PIN_71_SPI2_CK__FUNC_SPI2_CK (MTK_PIN_NO(71) | 0)
+#define MT7622_PIN_71_SPI2_CK__FUNC_GPIO71 (MTK_PIN_NO(71) | 1)
+
+#define MT7622_PIN_72_SPI2_DATA__FUNC_SPI2_DATA (MTK_PIN_NO(72) | 0)
+#define MT7622_PIN_72_SPI2_DATA__FUNC_GPIO72 (MTK_PIN_NO(72) | 1)
+
+#define MT7622_PIN_73_SPIC1_CLK__FUNC_SPIC1_CLK (MTK_PIN_NO(73) | 0)
+#define MT7622_PIN_73_SPIC1_CLK__FUNC_GPIO73 (MTK_PIN_NO(73) | 1)
+#define MT7622_PIN_73_SPIC1_CLK__FUNC_TXD1 (MTK_PIN_NO(73) | 2)
+#define MT7622_PIN_73_SPIC1_CLK__FUNC_I2C1_SCL (MTK_PIN_NO(73) | 3)
+#define MT7622_PIN_73_SPIC1_CLK__FUNC_PWM_CH1 (MTK_PIN_NO(73) | 4)
+#define MT7622_PIN_73_SPIC1_CLK__FUNC_ANTSEL12 (MTK_PIN_NO(73) | 5)
+#define MT7622_PIN_73_SPIC1_CLK__FUNC_DBG_UTIF0 (MTK_PIN_NO(73) | 7)
+
+#define MT7622_PIN_74_SPIC1_MOSI__FUNC_SPIC1_MOSI (MTK_PIN_NO(74) | 0)
+#define MT7622_PIN_74_SPIC1_MOSI__FUNC_GPIO74 (MTK_PIN_NO(74) | 1)
+#define MT7622_PIN_74_SPIC1_MOSI__FUNC_RXD1 (MTK_PIN_NO(74) | 2)
+#define MT7622_PIN_74_SPIC1_MOSI__FUNC_I2C1_SDA (MTK_PIN_NO(74) | 3)
+#define MT7622_PIN_74_SPIC1_MOSI__FUNC_PWM_CH2 (MTK_PIN_NO(74) | 4)
+#define MT7622_PIN_74_SPIC1_MOSI__FUNC_ANTSEL13 (MTK_PIN_NO(74) | 5)
+#define MT7622_PIN_74_SPIC1_MOSI__FUNC_DBG_UTIF1 (MTK_PIN_NO(74) | 7)
+
+#define MT7622_PIN_75_SPIC1_MISO__FUNC_SPIC1_MISO (MTK_PIN_NO(75) | 0)
+#define MT7622_PIN_75_SPIC1_MISO__FUNC_GPIO75 (MTK_PIN_NO(75) | 1)
+#define MT7622_PIN_75_SPIC1_MISO__FUNC_RTS1_N (MTK_PIN_NO(75) | 2)
+#define MT7622_PIN_75_SPIC1_MISO__FUNC_I2C2_SCL (MTK_PIN_NO(75) | 3)
+#define MT7622_PIN_75_SPIC1_MISO__FUNC_PWM_CH3 (MTK_PIN_NO(75) | 4)
+#define MT7622_PIN_75_SPIC1_MISO__FUNC_ANTSEL14 (MTK_PIN_NO(75) | 5)
+#define MT7622_PIN_75_SPIC1_MISO__FUNC_DBG_UTIF2 (MTK_PIN_NO(75) | 7)
+
+#define MT7622_PIN_76_SPIC1_CS__FUNC_SPIC1_CS (MTK_PIN_NO(76) | 0)
+#define MT7622_PIN_76_SPIC1_CS__FUNC_GPIO76 (MTK_PIN_NO(76) | 1)
+#define MT7622_PIN_76_SPIC1_CS__FUNC_CTS1_N (MTK_PIN_NO(76) | 2)
+#define MT7622_PIN_76_SPIC1_CS__FUNC_I2C2_SDA (MTK_PIN_NO(76) | 3)
+#define MT7622_PIN_76_SPIC1_CS__FUNC_PWM_CH4 (MTK_PIN_NO(76) | 4)
+#define MT7622_PIN_76_SPIC1_CS__FUNC_ANTSEL15 (MTK_PIN_NO(76) | 5)
+#define MT7622_PIN_76_SPIC1_CS__FUNC_DBG_UTIF3 (MTK_PIN_NO(76) | 7)
+
+#define MT7622_PIN_77_GPIO_D__FUNC_GPIO77 (MTK_PIN_NO(77) | 1)
+#define MT7622_PIN_77_GPIO_D__FUNC_PWM_CH5 (MTK_PIN_NO(77) | 4)
+#define MT7622_PIN_77_GPIO_D__FUNC_ANTSEL16 (MTK_PIN_NO(77) | 5)
+#define MT7622_PIN_77_GPIO_D__FUNC_DBG_UTIF4 (MTK_PIN_NO(77) | 7)
+
+#define MT7622_PIN_78_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(78) | 0)
+#define MT7622_PIN_78_WATCHDOG__FUNC_GPIO78 (MTK_PIN_NO(78) | 1)
+#define MT7622_PIN_78_WATCHDOG__FUNC_PWM_CH6 (MTK_PIN_NO(78) | 4)
+#define MT7622_PIN_78_WATCHDOG__FUNC_ANTSEL17 (MTK_PIN_NO(78) | 5)
+#define MT7622_PIN_78_WATCHDOG__FUNC_DBG_UTIF5 (MTK_PIN_NO(78) | 7)
+
+#define MT7622_PIN_79_RTS3_N__FUNC_RTS3_N (MTK_PIN_NO(79) | 0)
+#define MT7622_PIN_79_RTS3_N__FUNC_GPIO79 (MTK_PIN_NO(79) | 1)
+#define MT7622_PIN_79_RTS3_N__FUNC_SPIC0_MISO (MTK_PIN_NO(79) | 3)
+#define MT7622_PIN_79_RTS3_N__FUNC_PCIE0_PAD_WAKE_N (MTK_PIN_NO(79) | 4)
+#define MT7622_PIN_79_RTS3_N__FUNC_ANTSEL18 (MTK_PIN_NO(79) | 5)
+#define MT7622_PIN_79_RTS3_N__FUNC_DBG_UTIF6 (MTK_PIN_NO(79) | 7)
+
+#define MT7622_PIN_80_CTS3_N__FUNC_CTS3_N (MTK_PIN_NO(80) | 0)
+#define MT7622_PIN_80_CTS3_N__FUNC_GPIO80 (MTK_PIN_NO(80) | 1)
+#define MT7622_PIN_80_CTS3_N__FUNC_SPIC0_CS (MTK_PIN_NO(80) | 3)
+#define MT7622_PIN_80_CTS3_N__FUNC_PCIE0_PAD_CLKREQ_N (MTK_PIN_NO(80) | 4)
+#define MT7622_PIN_80_CTS3_N__FUNC_ANTSEL19 (MTK_PIN_NO(80) | 5)
+#define MT7622_PIN_80_CTS3_N__FUNC_DBG_UTIF7 (MTK_PIN_NO(80) | 7)
+
+#define MT7622_PIN_81_TXD3__FUNC_TXD3 (MTK_PIN_NO(81) | 0)
+#define MT7622_PIN_81_TXD3__FUNC_GPIO81 (MTK_PIN_NO(81) | 1)
+#define MT7622_PIN_81_TXD3__FUNC_SPDIF_T (MTK_PIN_NO(81) | 2)
+#define MT7622_PIN_81_TXD3__FUNC_SPIC0_CLK (MTK_PIN_NO(81) | 3)
+#define MT7622_PIN_81_TXD3__FUNC_PWM_CH6 (MTK_PIN_NO(81) | 4)
+#define MT7622_PIN_81_TXD3__FUNC_ANTSEL20 (MTK_PIN_NO(81) | 5)
+#define MT7622_PIN_81_TXD3__FUNC_DBG_UTIF8 (MTK_PIN_NO(81) | 7)
+
+#define MT7622_PIN_82_RXD3__FUNC_RXD3 (MTK_PIN_NO(82) | 0)
+#define MT7622_PIN_82_RXD3__FUNC_GPIO82 (MTK_PIN_NO(82) | 1)
+#define MT7622_PIN_82_RXD3__FUNC_SPDIF_R (MTK_PIN_NO(82) | 2)
+#define MT7622_PIN_82_RXD3__FUNC_SPIC0_MOSI (MTK_PIN_NO(82) | 3)
+#define MT7622_PIN_82_RXD3__FUNC_PWM_CH7 (MTK_PIN_NO(82) | 4)
+#define MT7622_PIN_82_RXD3__FUNC_ANTSEL21 (MTK_PIN_NO(82) | 5)
+#define MT7622_PIN_82_RXD3__FUNC_DBG_UTIF9 (MTK_PIN_NO(82) | 7)
+
+#define MT7622_PIN_83_PERST0_N__FUNC_PCIE0_PAD_PERST_N (MTK_PIN_NO(83) | 0)
+#define MT7622_PIN_83_PERST0_N__FUNC_GPIO83 (MTK_PIN_NO(83) | 1)
+
+#define MT7622_PIN_84_PERST1_N__FUNC_PCIE1_PAD_PERST_N (MTK_PIN_NO(84) | 0)
+#define MT7622_PIN_84_PERST1_N__FUNC_GPIO84 (MTK_PIN_NO(84) | 1)
+
+#define MT7622_PIN_85_WLED_N__FUNC_WLED_N (MTK_PIN_NO(85) | 0)
+#define MT7622_PIN_85_WLED_N__FUNC_GPIO85 (MTK_PIN_NO(85) | 1)
+
+#define MT7622_PIN_86_EPHY_LED0_N__FUNC_EPHY_LED0_N (MTK_PIN_NO(86) | 0)
+#define MT7622_PIN_86_EPHY_LED0_N__FUNC_GPIO86 (MTK_PIN_NO(86) | 1)
+#define MT7622_PIN_86_EPHY_LED0_N__FUNC_CPUM_HW_SEL (MTK_PIN_NO(86) | 4)
+#define MT7622_PIN_86_EPHY_LED0_N__FUNC_FPC_CTL0 (MTK_PIN_NO(86) | 6)
+#define MT7622_PIN_86_EPHY_LED0_N__FUNC_JTRST_N (MTK_PIN_NO(86) | 7)
+
+#define MT7622_PIN_87_AUXIN0__FUNC_I2C1_SCL (MTK_PIN_NO(87) | 0)
+#define MT7622_PIN_87_AUXIN0__FUNC_GPIO87 (MTK_PIN_NO(87) | 1)
+
+#define MT7622_PIN_88_AUXIN1__FUNC_I2C1_SDA (MTK_PIN_NO(88) | 0)
+#define MT7622_PIN_88_AUXIN1__FUNC_GPIO88 (MTK_PIN_NO(88) | 1)
+
+#define MT7622_PIN_89_AUXIN2__FUNC_I2C2_SCL (MTK_PIN_NO(89) | 0)
+#define MT7622_PIN_89_AUXIN2__FUNC_GPIO89 (MTK_PIN_NO(89) | 1)
+
+#define MT7622_PIN_90_AUXIN3__FUNC_I2C2_SDA (MTK_PIN_NO(90) | 0)
+#define MT7622_PIN_90_AUXIN3__FUNC_GPIO90 (MTK_PIN_NO(90) | 1)
+
+#define MT7622_PIN_91_TXD4__FUNC_TXD4 (MTK_PIN_NO(91) | 0)
+#define MT7622_PIN_91_TXD4__FUNC_GPIO91 (MTK_PIN_NO(91) | 1)
+#define MT7622_PIN_91_TXD4__FUNC_EPHY_LED1_N (MTK_PIN_NO(91) | 2)
+#define MT7622_PIN_91_TXD4__FUNC_DFD_TDI (MTK_PIN_NO(91) | 3)
+#define MT7622_PIN_91_TXD4__FUNC_CPUM_2B_SEL (MTK_PIN_NO(91) | 4)
+#define MT7622_PIN_91_TXD4__FUNC_ANTSEL0 (MTK_PIN_NO(91) | 5)
+#define MT7622_PIN_91_TXD4__FUNC_FPC_CK_XI (MTK_PIN_NO(91) | 6)
+#define MT7622_PIN_91_TXD4__FUNC_JTDI (MTK_PIN_NO(91) | 7)
+
+#define MT7622_PIN_92_RXD4__FUNC_RXD4 (MTK_PIN_NO(92) | 0)
+#define MT7622_PIN_92_RXD4__FUNC_GPIO92 (MTK_PIN_NO(92) | 1)
+#define MT7622_PIN_92_RXD4__FUNC_EPHY_LED2_N (MTK_PIN_NO(92) | 2)
+#define MT7622_PIN_92_RXD4__FUNC_DFD_TDO (MTK_PIN_NO(92) | 3)
+#define MT7622_PIN_92_RXD4__FUNC_CPUM0 (MTK_PIN_NO(92) | 4)
+#define MT7622_PIN_92_RXD4__FUNC_ANTSEL1 (MTK_PIN_NO(92) | 5)
+#define MT7622_PIN_92_RXD4__FUNC_FPC_CTL1 (MTK_PIN_NO(92) | 6)
+#define MT7622_PIN_92_RXD4__FUNC_JTDO (MTK_PIN_NO(92) | 7)
+
+#define MT7622_PIN_93_RTS4_N__FUNC_RTS4_N (MTK_PIN_NO(93) | 0)
+#define MT7622_PIN_93_RTS4_N__FUNC_GPIO93 (MTK_PIN_NO(93) | 1)
+#define MT7622_PIN_93_RTS4_N__FUNC_EPHY_LED3_N (MTK_PIN_NO(93) | 2)
+#define MT7622_PIN_93_RTS4_N__FUNC_DFD_TCK (MTK_PIN_NO(93) | 3)
+#define MT7622_PIN_93_RTS4_N__FUNC_CPUM1 (MTK_PIN_NO(93) | 4)
+#define MT7622_PIN_93_RTS4_N__FUNC_ANTSEL2 (MTK_PIN_NO(93) | 5)
+#define MT7622_PIN_93_RTS4_N__FUNC_FPC_CTL2 (MTK_PIN_NO(93) | 6)
+#define MT7622_PIN_93_RTS4_N__FUNC_JTCLK (MTK_PIN_NO(93) | 7)
+
+#define MT7622_PIN_94_CTS4_N__FUNC_CTS4_N (MTK_PIN_NO(94) | 0)
+#define MT7622_PIN_94_CTS4_N__FUNC_GPIO94 (MTK_PIN_NO(94) | 1)
+#define MT7622_PIN_94_CTS4_N__FUNC_EPHY_LED4_N (MTK_PIN_NO(94) | 2)
+#define MT7622_PIN_94_CTS4_N__FUNC_DFD_TMS (MTK_PIN_NO(94) | 3)
+#define MT7622_PIN_94_CTS4_N__FUNC_CPUM2 (MTK_PIN_NO(94) | 4)
+#define MT7622_PIN_94_CTS4_N__FUNC_ANTSEL3 (MTK_PIN_NO(94) | 5)
+#define MT7622_PIN_94_CTS4_N__FUNC_FPC_CTL3 (MTK_PIN_NO(94) | 6)
+#define MT7622_PIN_94_CTS4_N__FUNC_JTMS (MTK_PIN_NO(94) | 7)
+
+#define MT7622_PIN_95_PWM1__FUNC_PWM_CH1 (MTK_PIN_NO(95) | 0)
+#define MT7622_PIN_95_PWM1__FUNC_GPIO95 (MTK_PIN_NO(95) | 1)
+#define MT7622_PIN_95_PWM1__FUNC_RTS4_N (MTK_PIN_NO(95) | 2)
+#define MT7622_PIN_95_PWM1__FUNC_TXD2 (MTK_PIN_NO(95) | 3)
+#define MT7622_PIN_95_PWM1__FUNC_CPUM3 (MTK_PIN_NO(95) | 4)
+#define MT7622_PIN_95_PWM1__FUNC_ANTSEL4 (MTK_PIN_NO(95) | 5)
+#define MT7622_PIN_95_PWM1__FUNC_FPC_DATA0 (MTK_PIN_NO(95) | 6)
+#define MT7622_PIN_95_PWM1__FUNC_W_DBGIN (MTK_PIN_NO(95) | 7)
+
+#define MT7622_PIN_96_PWM2__FUNC_PWM_CH2 (MTK_PIN_NO(96) | 0)
+#define MT7622_PIN_96_PWM2__FUNC_GPIO96 (MTK_PIN_NO(96) | 1)
+#define MT7622_PIN_96_PWM2__FUNC_CTS4_N (MTK_PIN_NO(96) | 2)
+#define MT7622_PIN_96_PWM2__FUNC_RXD2 (MTK_PIN_NO(96) | 3)
+#define MT7622_PIN_96_PWM2__FUNC_CPUM_CK_XI (MTK_PIN_NO(96) | 4)
+#define MT7622_PIN_96_PWM2__FUNC_ANTSEL5 (MTK_PIN_NO(96) | 5)
+#define MT7622_PIN_96_PWM2__FUNC_FPC_DATA1 (MTK_PIN_NO(96) | 6)
+#define MT7622_PIN_96_PWM2__FUNC_W_DBGACK (MTK_PIN_NO(96) | 7)
+
+#define MT7622_PIN_97_PWM3__FUNC_PWM_CH3 (MTK_PIN_NO(97) | 0)
+#define MT7622_PIN_97_PWM3__FUNC_GPIO97 (MTK_PIN_NO(97) | 1)
+#define MT7622_PIN_97_PWM3__FUNC_TXD4 (MTK_PIN_NO(97) | 2)
+#define MT7622_PIN_97_PWM3__FUNC_AICE_TCKC (MTK_PIN_NO(97) | 4)
+#define MT7622_PIN_97_PWM3__FUNC_ANTSEL6 (MTK_PIN_NO(97) | 5)
+#define MT7622_PIN_97_PWM3__FUNC_FPC_DATA2 (MTK_PIN_NO(97) | 6)
+#define MT7622_PIN_97_PWM3__FUNC_W_JTCLK (MTK_PIN_NO(97) | 7)
+
+#define MT7622_PIN_98_PWM4__FUNC_PWM_CH4 (MTK_PIN_NO(98) | 0)
+#define MT7622_PIN_98_PWM4__FUNC_GPIO98 (MTK_PIN_NO(98) | 1)
+#define MT7622_PIN_98_PWM4__FUNC_RXD4 (MTK_PIN_NO(98) | 2)
+#define MT7622_PIN_98_PWM4__FUNC_ANTSEL7 (MTK_PIN_NO(98) | 5)
+#define MT7622_PIN_98_PWM4__FUNC_FPC_DATA3 (MTK_PIN_NO(98) | 6)
+#define MT7622_PIN_98_PWM4__FUNC_W_JTDI (MTK_PIN_NO(98) | 7)
+
+#define MT7622_PIN_99_PWM5__FUNC_PWM_CH5 (MTK_PIN_NO(99) | 0)
+#define MT7622_PIN_99_PWM5__FUNC_GPIO99 (MTK_PIN_NO(99) | 1)
+#define MT7622_PIN_99_PWM5__FUNC_IR_T (MTK_PIN_NO(99) | 3)
+#define MT7622_PIN_99_PWM5__FUNC_AICE_TMSC (MTK_PIN_NO(99) | 4)
+#define MT7622_PIN_99_PWM5__FUNC_ANTSEL8 (MTK_PIN_NO(99) | 5)
+#define MT7622_PIN_99_PWM5__FUNC_FPC_DATA4 (MTK_PIN_NO(99) | 6)
+#define MT7622_PIN_99_PWM5__FUNC_W_JTMS (MTK_PIN_NO(99) | 7)
+
+#define MT7622_PIN_100_PWM6__FUNC_PWM_CH6 (MTK_PIN_NO(100) | 0)
+#define MT7622_PIN_100_PWM6__FUNC_GPIO100 (MTK_PIN_NO(100) | 1)
+#define MT7622_PIN_100_PWM6__FUNC_IR_R (MTK_PIN_NO(100) | 3)
+#define MT7622_PIN_100_PWM6__FUNC_ANTSEL9 (MTK_PIN_NO(100) | 5)
+#define MT7622_PIN_100_PWM6__FUNC_FPC_DATA5 (MTK_PIN_NO(100) | 6)
+#define MT7622_PIN_100_PWM6__FUNC_W_JTRST_N (MTK_PIN_NO(100) | 7)
+
+#define MT7622_PIN_101_PWM7__FUNC_PWM_CH7 (MTK_PIN_NO(101) | 0)
+#define MT7622_PIN_101_PWM7__FUNC_GPIO101 (MTK_PIN_NO(101) | 1)
+#define MT7622_PIN_101_PWM7__FUNC_ANTSEL10 (MTK_PIN_NO(101) | 5)
+#define MT7622_PIN_101_PWM7__FUNC_FPC_DATA6 (MTK_PIN_NO(101) | 6)
+#define MT7622_PIN_101_PWM7__FUNC_DBG_UART_TXD (MTK_PIN_NO(101) | 7)
+
+#define MT7622_PIN_102_GPIO_E__FUNC_GPIO102 (MTK_PIN_NO(102) | 1)
+#define MT7622_PIN_102_GPIO_E__FUNC_ANTSEL11 (MTK_PIN_NO(102) | 5)
+#define MT7622_PIN_102_GPIO_E__FUNC_FPC_DATA7 (MTK_PIN_NO(102) | 6)
+#define MT7622_PIN_102_GPIO_E__FUNC_W_JTDO (MTK_PIN_NO(102) | 7)
+
+#endif /* __DTS_MT7622_PINFUNC_H */
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
new file mode 100644
index 000000000000..b7a677502a0b
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+ model = "MediaTek MT7622 RFB1 board";
+ compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";
+
+ chosen {
+ bootargs = "console=ttyS0,115200n1 root=/dev/ram \
+ initrd=0x44000000,0x615E36 loglevel=8 androidboot.hardware=mt7622 swiotlb=512";
+ };
+
+ mmc_fixed_1v8_io: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ mmc_fixed_3v3_power: fixedregulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_power";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ memory {
+ reg = <0 0x40000000 0 0x3F000000>;
+ };
+};
+
+&auxadc {
+ status = "okay";
+};
+
+&cpu0 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&cpu1 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&efuse {
+ status = "okay";
+};
+
+&eth {
+ mac-address = [00 00 00 00 00 00];
+ dma-coherent;
+ wan_at = "p4";
+ gmac1-support = "sgmii-1";
+ sgmii-mode-1 = "force-2500";
+ #gmac1-support = "rgmii-1";
+ #rgmii-mode-1 = "force-1000";
+ #gmac1-phy-address = <0x1f>;
+ gmac2-support = "rgmii-2";
+ rgmii-mode-2 = "force-1000";
+ #rgmii-mode-2 = "an";
+ #gmac2-phy-address = <0x1e>;
+ gmac1_txq_num = <1>;
+ gmac1_txq_txd_num = <2048>;
+ gmac2_txq_num = <1>;
+ gmac2_txq_txd_num = <1024>;
+ num_rx_desc = <2048>;
+ status = "okay";
+};
+
+&gsw {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ status = "okay";
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_1v8_io>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ r_smpl = <1>;
+ cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_3v3_power>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nor_flash {
+ status = "okay";
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@00000 {
+ label = "Preloader";
+ reg = <0x00000 0x0040000>;
+ };
+ partition@40000 {
+ label = "ATF";
+ reg = <0x40000 0x0020000>;
+ };
+ partition@60000 {
+ label = "Bootloader";
+ reg = <0x60000 0x0040000>;
+ };
+ partition@A0000 {
+ label = "Config";
+ reg = <0xA0000 0x0020000>;
+ };
+ partition@C0000 {
+ label = "Factory";
+ reg = <0xC0000 0x0020000>;
+ };
+ partition@E0000 {
+ label = "Kernel";
+ reg = <0xE0000 0xF20000>;
+ };
+ };
+};
+
+&pio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+ state_default:pinconf_default {
+ };
+
+ mmc0_pins_default: mmc0default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ bias-pull-down;
+ };
+ };
+
+ mmc0_pins_uhs: mmc0@0{
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ mmc1_pins_default: mmc1default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins_insert {
+ pinmux = <MT7622_PIN_81_TXD3__FUNC_GPIO81>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_pins_uhs: mmc1@0 {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_19_I2S2_OUT__FUNC_SD_D0>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_SD_D1>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_SD_D2>,
+ <MT7622_PIN_16_I2S2_IN__FUNC_SD_D3>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_SD_CMD>;
+ input-enable;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_20_I2S3_OUT__FUNC_SD_CLK>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ snand_pins_default: snand@0 {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_8_SPI_WP__FUNC_SNFI_WP>,
+ <MT7622_PIN_9_SPI_HOLD__FUNC_SNFI_HOLD>,
+ <MT7622_PIN_11_SPI_MOSI__FUNC_SNFI_MOSI>,
+ <MT7622_PIN_12_SPI_MISO__FUNC_SNFI_MISO>,
+ <MT7622_PIN_13_SPI_CS__FUNC_SNFI_CS>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+ pins_clk {
+ pinmux = <MT7622_PIN_10_SPI_CLK__FUNC_SNFI_CLK>;
+ drive-strength = <MTK_DRIVE_16mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+};
+
+&pwm {
+ status = "okay";
+};
+
+&snand {
+ pinctrl-0 = <&snand_pins_default>;
+ status = "okay";
+ flash@0 {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "Preloader";
+ reg = <0x00000 0x0080000>;
+ read-only;
+ };
+
+ partition@80000 {
+ label = "ATF";
+ reg = <0x80000 0x0040000>;
+ };
+
+ partition@c0000 {
+ label = "Bootloader";
+ reg = <0xc0000 0x0080000>;
+ };
+
+ partition@140000 {
+ label = "Config";
+ reg = <0x140000 0x0080000>;
+ };
+
+ partition@1c0000 {
+ label = "Factory";
+ reg = <0x1c0000 0x0040000>;
+ };
+
+ partition@200000 {
+ label = "Kernel";
+ reg = <0x200000 0x2000000>;
+ };
+
+ partition@2200000 {
+ label = "User_data";
+ reg = <0x2200000 0x4000000>;
+ };
+ };
+ };
+};
+
+&svs {
+ vproc-supply = <&mt6380_vcpu_reg>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb2.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb2.dts
new file mode 100644
index 000000000000..bdabfa645c85
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb2.dts
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Huang <ming.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+ model = "MediaTek MT7622 RFB2 board";
+ compatible = "mediatek,mt7622-rfb2", "mediatek,mt7622";
+
+ chosen {
+ bootargs = "console=ttyS0,115200n1 root=/dev/ram \
+ initrd=0x44000000,0x615E36 loglevel=8 androidboot.hardware=mt7622 swiotlb=512";
+ };
+
+ dummy_codec:dummy_codec {
+ compatible = "mediatek,dummy-codec";
+ };
+
+ mmc_fixed_1v8_io: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ mmc_fixed_3v3_power: fixedregulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "mmc_power";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ memory {
+ reg = <0 0x40000000 0 0x3F000000>;
+ };
+
+ sound: sound {
+ compatible = "mediatek,mt7622-soc-machine";
+ mediatek,platform = <&afe>;
+ mediatek,audio-codec = <&dummy_codec>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&aud_pins_default>;
+ status = "okay";
+ };
+};
+
+&auxadc {
+ status = "okay";
+};
+
+&btif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&btif_default>;
+};
+
+&cpu0 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&cpu1 {
+ proc-supply = <&mt6380_vcpu_reg>;
+ sram-supply = <&mt6380_vm_reg>;
+};
+
+&efuse {
+ status = "okay";
+};
+
+&eth {
+ mac-address = [00 00 00 00 00 00];
+ dma-coherent;
+ wan_at = "p0";
+ gmac1-support = "esw";
+ gmac1_txq_num = <1>;
+ gmac1_txq_txd_num = <2048>;
+ gmac2_txq_num = <1>;
+ gmac2_txq_txd_num = <1024>;
+ num_rx_desc = <2048>;
+ status = "okay";
+};
+
+&gsw {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ status = "okay";
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_1v8_io>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ r_smpl = <1>;
+ cd-gpios = <&pio 32 0>;
+ vmmc-supply = <&mmc_fixed_3v3_power>;
+ vqmmc-supply = <&mmc_fixed_3v3_power>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>;
+};
+
+&nor_flash {
+ status = "okay";
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@00000 {
+ label = "Preloader";
+ reg = <0x00000 0x0040000>;
+ };
+ partition@40000 {
+ label = "ATF";
+ reg = <0x40000 0x0020000>;
+ };
+ partition@60000 {
+ label = "Bootloader";
+ reg = <0x60000 0x0040000>;
+ };
+ partition@A0000 {
+ label = "Config";
+ reg = <0xA0000 0x0020000>;
+ };
+ partition@C0000 {
+ label = "Factory";
+ reg = <0xC0000 0x0020000>;
+ };
+ partition@E0000 {
+ label = "Kernel";
+ reg = <0xE0000 0xF20000>;
+ };
+ };
+};
+
+&pio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+ state_default:pinconf_default {
+ };
+
+ aud_pins_default: audiodefault {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_3_I2S_BCLK__FUNC_I2S_BCLK_OUT>,
+ <MT7622_PIN_4_I2S_WS__FUNC_I2S_WS_OUT>,
+ <MT7622_PIN_5_I2S_MCLK__FUNC_I2S_MCLK>,
+ <MT7622_PIN_2_I2S1_OUT__FUNC_I2S1_OUT>,
+ <MT7622_PIN_1_I2S1_IN__FUNC_I2S1_IN>,
+ <MT7622_PIN_8_SPI_WP__FUNC_TDM_OUT_MCLK>,
+ <MT7622_PIN_9_SPI_HOLD__FUNC_TDM_OUT_BCLK>,
+ <MT7622_PIN_10_SPI_CLK__FUNC_TDM_OUT_WS>,
+ <MT7622_PIN_11_SPI_MOSI__FUNC_TDM_IN_MCLK>,
+ <MT7622_PIN_12_SPI_MISO__FUNC_TDM_IN_BCLK>,
+ <MT7622_PIN_13_SPI_CS__FUNC_TDM_IN_WS>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down;
+ };
+ };
+
+ btif_default:btif_default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_16_I2S2_IN__FUNC_BT_EPA_EN>,
+ <MT7622_PIN_17_I2S3_IN__FUNC_BT_ELNA_EN>,
+ <MT7622_PIN_18_I2S4_IN__FUNC_BT_ERX_EN>,
+ <MT7622_PIN_19_I2S2_OUT__FUNC_BT_IPATH_EN>,
+ <MT7622_PIN_20_I2S3_OUT__FUNC_BT_SPXT_C1>,
+ <MT7622_PIN_21_I2S4_OUT__FUNC_BT_SPXT_C0>;
+ };
+ };
+
+ mmc0_pins_default: mmc0default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ bias-pull-down;
+ };
+ };
+
+ mmc0_pins_uhs: mmc0@0{
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_47_NDL0__FUNC_EMMC_DATA0>,
+ <MT7622_PIN_48_NDL1__FUNC_EMMC_DATA1>,
+ <MT7622_PIN_49_NDL2__FUNC_EMMC_DATA2>,
+ <MT7622_PIN_50_NDL3__FUNC_EMMC_DATA3>,
+ <MT7622_PIN_40_NDL4__FUNC_EMMC_DATA4>,
+ <MT7622_PIN_41_NDL5__FUNC_EMMC_DATA5>,
+ <MT7622_PIN_42_NDL6__FUNC_EMMC_DATA6>,
+ <MT7622_PIN_43_NDL7__FUNC_EMMC_DATA7>,
+ <MT7622_PIN_44_NRB__FUNC_EMMC_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_45_NCLE__FUNC_EMMC_CK>;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ mmc1_pins_default: mmc1default {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_28_G2_TXD3__FUNC_SD_D0>,
+ <MT7622_PIN_27_G2_TXD2__FUNC_SD_D1>,
+ <MT7622_PIN_26_G2_TXD1__FUNC_SD_D2>,
+ <MT7622_PIN_25_G2_TXD0__FUNC_SD_D3>,
+ <MT7622_PIN_30_G2_TXC__FUNC_SD_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_29_G2_TXEN__FUNC_SD_CLK>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins_insert {
+ pinmux = <MT7622_PIN_32_G2_RXD1__FUNC_G2_GPIO32>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_pins_uhs: mmc1@0 {
+ pins_cmd_dat {
+ pinmux = <MT7622_PIN_28_G2_TXD3__FUNC_SD_D0>,
+ <MT7622_PIN_27_G2_TXD2__FUNC_SD_D1>,
+ <MT7622_PIN_26_G2_TXD1__FUNC_SD_D2>,
+ <MT7622_PIN_25_G2_TXD0__FUNC_SD_D3>,
+ <MT7622_PIN_30_G2_TXC__FUNC_SD_CMD>;
+ input-enable;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins_clk {
+ pinmux = <MT7622_PIN_29_G2_TXEN__FUNC_SD_CLK>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+};
+
+&pwm {
+ status = "okay";
+};
+
+&svs {
+ vproc-supply = <&mt6380_vcpu_reg>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
new file mode 100644
index 000000000000..baf78212ebbe
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -0,0 +1,1109 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming.Huang <ming.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 <dt-bindings/clock/mt7622-clk.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/mt7622-power.h>
+#include <dt-bindings/reset/mt7622-resets.h>
+#include <dt-bindings/phy/phy.h>
+#include "mt7622-pinfunc.h"
+
+/ {
+ compatible = "mediatek,mt7622";
+ interrupt-parent = <&sysirq>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ mtcpufreq {
+ compatible = "mediatek,mt7622-cpufreq";
+ };
+
+ cluster0_opp: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+ opp00 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <950000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <437500000>;
+ opp-microvolt = <1000000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <1050000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <812500000>;
+ opp-microvolt = <1100000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1025000000>;
+ opp-microvolt = <1150000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1137500000>;
+ opp-microvolt = <1200000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1262500000>;
+ opp-microvolt = <1250000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1350000000>;
+ opp-microvolt = <1310000>;
+ };
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&L2_CA53>;
+ cpu-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_0>,
+ <&CPU_SLEEP_0_0 &CPU_SLEEP_0_0 &CPU_SLEEP_0_0>;
+ clocks = <&infracfg CLK_INFRA_MUX1_SEL>,
+ <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>,
+ <&apmixedsys CLK_APMIXED_ARMPLL>;
+ clock-names = "cpu", "intermediate", "armpll";
+ operating-points-v2 = <&cluster0_opp>;
+ cpu-release-addr = <0x0 0x40000200>;
+ clock-frequency = <1300000000>;
+ cci-control-port = <&cci_control2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0 0x1>;
+ enable-method = "psci";
+ next-level-cache = <&L2_CA53>;
+ cpu-idle-states = <&CLUSTER_SLEEP_0 &CLUSTER_SLEEP_0>,
+ <&CPU_SLEEP_0_0 &CPU_SLEEP_0_0 &CPU_SLEEP_0_0>;
+ clocks = <&infracfg CLK_INFRA_MUX1_SEL>,
+ <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>,
+ <&apmixedsys CLK_APMIXED_ARMPLL>;
+ clock-names = "cpu", "intermediate", "armpll";
+ operating-points-v2 = <&cluster0_opp>;
+ cpu-release-addr = <0x0 0x40000200>;
+ clock-frequency = <1300000000>;
+ cci-control-port = <&cci_control2>;
+ };
+
+ L2_CA53: l2-cache0 {
+ compatible = "cache";
+ cache-level = <2>;
+ };
+
+ idle-states {
+ entry-method = "arm,psci";
+
+ CPU_SLEEP_0_0: cpu-sleep-0-0 {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x0010000>;
+ entry-latency-us = <600>;
+ exit-latency-us = <600>;
+ min-residency-us = <1200>;
+ };
+
+ CLUSTER_SLEEP_0: cluster-sleep-0 {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x1010000>;
+ entry-latency-us = <800>;
+ exit-latency-us = <1000>;
+ min-residency-us = <2000>;
+ };
+
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ atf-reserved-memory@43000000 {
+ compatible = "mediatek,mt7622-atf-reserved-memory";
+ no-map;
+ reg = <0 0x43000000 0 0x30000>;
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
+ clk25m: oscillator-clk25m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ clock-output-names = "clkxtal";
+ };
+
+ clksrc_pll: oscillator-clksrc_pll {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ clock-output-names = "clksrc_pll";
+ };
+
+ flash_peri_clk: dummy133m {
+ compatible = "fixed-clocks";
+ clock-frequency = <133000000>;
+ #clock-cells = <0>;
+ };
+
+ nfiecc_top_clk: dummy98m {
+ compatible = "fixed-clocks";
+ clock-frequency = <48000000>;
+ #clock-cells = <0>;
+ };
+
+ flash_top_clk: dummy48m {
+ compatible = "fixed-clocks";
+ clock-frequency = <48000000>;
+ #clock-cells = <0>;
+ };
+
+ system_clk: dummy13m {
+ compatible = "fixed-clock";
+ clock-frequency = <12500000>;
+ #clock-cells = <0>;
+ };
+
+ rtc_clk: dummy32k {
+ compatible = "fixed-clock";
+ clock-frequency = <32000>;
+ #clock-cells = <0>;
+ };
+
+ pwrap_clk: dummy40m {
+ compatible = "fixed-clock";
+ clock-frequency = <40000000>;
+ #clock-cells = <0>;
+ };
+
+ chipid: chipid@08000000 {
+ compatible = "mediatek,chipid";
+ reg = <0 0x08000000 0 0x0004>,
+ <0 0x08000004 0 0x0004>,
+ <0 0x08000008 0 0x0004>,
+ <0 0x0800000c 0 0x0004>;
+ };
+
+ infracfg: infracfg@10000000 {
+ compatible = "mediatek,mt7622-infracfg", "syscon";
+ reg = <0 0x10000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ pwrap: pwrap@10001000 {
+ compatible = "mediatek,mt7622-pwrap";
+ reg = <0 0x10001000 0 0x250>;
+ reg-names = "pwrap";
+ clocks = <&infracfg CLK_INFRA_PMIC_PD>,<&pwrap_clk>;
+ clock-names = "spi","wrap";
+ status = "disabled";
+ };
+
+ pericfg: pericfg@10002000 {
+ compatible = "mediatek,mt7622-pericfg", "syscon";
+ reg = <0 0x10002000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ ice: ice_debug {
+ compatible ="mediatek,mt7622-ice_debug",
+ "mediatek,mt2701-ice_debug";
+ clocks = <&infracfg CLK_INFRA_DBGCLK_PD>;
+ clock-names = "ice_dbg";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ pcie_mirror: pcie_mirror@10000400 {
+ compatible = "mediatek,pcie-mirror";
+ reg = <0 0x10000400 0 0x10>;
+ };
+
+ timer: timer@10004000 {
+ compatible = "mediatek,mt7622-timer",
+ "mediatek,mt6577-timer";
+ reg = <0 0x10004000 0 0x80>;
+ interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_APXGPT_PD>, <&topckgen CLK_TOP_RTC>;
+ clock-names = "system-clk", "rtc-clk";
+ };
+
+ scpsys: scpsys@10006000 {
+ compatible = "mediatek,mt7622-scpsys", "syscon";
+ #power-domain-cells = <1>;
+ reg = <0 0x10006000 0 0x1000>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 166 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 167 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_LOW>;
+ infracfg = <&infracfg>;
+ clocks = <&topckgen CLK_TOP_RTC>, <&topckgen CLK_TOP_HIF_SEL>;
+ clock-names = "spm_rtc", "hif_sel";
+ };
+
+ irrx: irrx@10009000 {
+ compatible = "mediatek,mt7622-irrx";
+ reg = <0 0x10009000 0 0x1000>;
+ interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_IRRX_PD>;
+ clock-names = "irrx_clock";
+ status = "disabled";
+ };
+
+ sysirq: interrupt-controller@10200620 {
+ compatible = "mediatek,mt7622-sysirq",
+ "mediatek,mt6577-sysirq";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ reg = <0 0x10200620 0 0x20>;
+ };
+
+ emi: emi@10203000 {
+ compatible = "mediatek,mt7622-emi",
+ "mediatek,mt8127-emi";
+ reg = <0 0x10203000 0 0x1000>;
+ };
+
+ sys_cirq: sys_cirq@10204000 {
+ compatible = "mediatek,mt7622-sys_cirq",
+ "mediatek,sys_cirq";
+ reg = <0 0x10204000 0 0x1000>;
+ interrupts = <GIC_SPI 231 IRQ_TYPE_LEVEL_LOW>;
+ mediatek,cirq_num = <169>;
+ mediatek,spi_start_offset = <72>;
+ };
+
+ efuse: efuse@10206000 {
+ compatible = "mediatek,mt7622-efuse",
+ "mediatek,efuse";
+ reg = <0 0x10206000 0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+ svs_calibration: calib@180 {
+ reg = <0x180 0x8>;
+ };
+ thermal_calibration: calib@198 {
+ reg = <0x198 0x8>;
+ };
+ };
+
+ apmixedsys: apmixedsys@10209000 {
+ compatible = "mediatek,mt7622-apmixedsys", "syscon";
+ reg = <0 0x10209000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ wed: wed@1020b000 {
+ compatible = "mediatek,wed";
+ wed_num = <2>;
+ /* add this property for wed get the pci slot number. */
+ pci_slot_map = <0>, <1>;
+ reg = <0 0x1020a000 0 0x1000>,
+ <0 0x1020b000 0 0x1000>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ wed2: wed2@1020b000 {
+ compatible = "mediatek,wed2";
+ wed_num = <2>;
+ reg = <0 0x1020a000 0 0x1000>,
+ <0 0x1020b000 0 0x1000>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ rng: rng@1020f000 {
+ compatible = "mediatek,mt7622-rng",
+ "mediatek,mt7623-rng";
+ reg = <0 0x1020f000 0 0x100>;
+ clocks = <&infracfg CLK_INFRA_TRNG_PD>;
+ clock-names = "rng";
+
+ };
+
+ dramc_nao: dramc_nao@0x1020e000 {
+ compatible = "mediatek,mt7622-dramc_nao";
+ reg = <0 0x1020E000 0 0x1000>;
+ };
+
+ topckgen: topckgen@10210000 {
+ compatible = "mediatek,mt7622-topckgen", "syscon";
+ reg = <0 0x10210000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ syscfg_pctl_a: syscfg_pctl_a@10211000 {
+ compatible = "mediatek,mt7622-pctl-a-syscfg", "syscon";
+ reg = <0 0x10211000 0 0x1000>;
+ };
+
+ pio: pinctrl@10211000 {
+ compatible = "mediatek,mt7622-pinctrl";
+ reg = <0 0x10005000 0 0x1000>;
+ mediatek,pctl-regmap = <&syscfg_pctl_a>;
+ pins-are-numbered;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ watchdog: watchdog@10212000 {
+ compatible = "mediatek,mt7622-wdt",
+ "mediatek,mt6589-wdt";
+ reg = <0 0x10212000 0 0x1000>;
+ timeout-sec = <30>;
+ mediatek,timer = <&timer>;
+ #reset-cells = <1>;
+ };
+
+ dramc: dramc@10214000 {
+ compatible = "mediatek,mt7622-dramc";
+ reg = <0 0x10214000 0 0x1000>;
+ };
+
+ gic: interrupt-controller@10300000 {
+ compatible = "arm,gic-400";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ reg = <0 0x10310000 0 0x1000>,
+ <0 0x10320000 0 0x1000>,
+ <0 0x10340000 0 0x2000>,
+ <0 0x10360000 0 0x2000>;
+ };
+
+ cci: cci@10390000 {
+ compatible = "arm,cci-400";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0 0x10390000 0 0x1000>;
+ ranges = <0 0 0x10390000 0x10000>;
+
+ cci_control0: slave-if@1000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace-lite";
+ reg = <0x1000 0x1000>;
+ };
+
+ cci_control1: slave-if@4000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x4000 0x1000>;
+ };
+
+ cci_control2: slave-if@5000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x5000 0x1000>;
+ };
+
+ pmu@9000 {
+ compatible = "arm,cci-400-pmu,r1";
+ reg = <0x9000 0x5000>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ btif_tx: btif_tx@11000780 {
+ compatible = "mediatek,btif_tx";
+ reg = <0 0x11000780 0 0x80>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ btif_rx: btif_rx@11000800 {
+ compatible = "mediatek,btif_rx";
+ reg = <0 0x11000800 0 0x80>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ auxadc: adc@11001000 {
+ compatible = "mediatek,mt7622-auxadc";
+ reg = <0 0x11001000 0 0x1000>;
+ clocks = <&pericfg CLK_PERI_AUXADC_PD>;
+ clock-names = "main";
+ #io-channel-cells = <1>;
+ status = "disabled";
+ };
+
+ uart0: serial@11002000 {
+ compatible = "mediatek,mt7622-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11002000 0 0x400>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>, <&pericfg CLK_PERI_UART0_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ uart1: serial@11003000 {
+ compatible = "mediatek,mt7622-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11003000 0 0x400>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>, <&pericfg CLK_PERI_UART1_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ uart2: serial@11004000 {
+ compatible = "mediatek,mt7622-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11004000 0 0x400>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>, <&pericfg CLK_PERI_UART2_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ uart3: serial@11005000 {
+ compatible = "mediatek,mt7622-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11005000 0 0x400>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>, <&pericfg CLK_PERI_UART3_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ pwm: pwm@11006000 {
+ compatible = "mediatek,mt7622-pwm";
+ reg = <0 0x11006000 0 0x1000>;
+ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_PWM_SEL>,
+ <&pericfg CLK_PERI_PWM_PD>,
+ <&pericfg CLK_PERI_PWM1_PD>,
+ <&pericfg CLK_PERI_PWM2_PD>,
+ <&pericfg CLK_PERI_PWM3_PD>,
+ <&pericfg CLK_PERI_PWM4_PD>,
+ <&pericfg CLK_PERI_PWM5_PD>,
+ <&pericfg CLK_PERI_PWM6_PD>;
+ clock-names = "top",
+ "main",
+ "pwm1",
+ "pwm2",
+ "pwm3",
+ "pwm4",
+ "pwm5",
+ "pwm6";
+ status = "disabled";
+ };
+
+ i2c0: i2c@11007000 {
+ compatible = "mediatek,mt7622-i2c";
+ reg = <0 0x11007000 0 0x90>,
+ <0 0x11000100 0 0x80>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>;
+ clock-div = <16>;
+ clocks = <&pericfg CLK_PERI_I2C0_PD>,
+ <&pericfg CLK_PERI_AP_DMA_PD>;
+ clock-names = "main", "dma";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@11008000 {
+ compatible = "mediatek,mt7622-i2c";
+ reg = <0 0x11008000 0 0x90>,
+ <0 0x11000180 0 0x80>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_LOW>;
+ clock-div = <16>;
+ clocks = <&pericfg CLK_PERI_I2C1_PD>,
+ <&pericfg CLK_PERI_AP_DMA_PD>;
+ clock-names = "main", "dma";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@11009000 {
+ compatible = "mediatek,mt7622-i2c";
+ reg = <0 0x11009000 0 0x90>,
+ <0 0x11000200 0 0x80>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_LOW>;
+ clock-div = <16>;
+ clocks = <&pericfg CLK_PERI_I2C2_PD>,
+ <&pericfg CLK_PERI_AP_DMA_PD>;
+ clock-names = "main", "dma";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi0: spi@1100a000 {
+ compatible = "mediatek,mt7622-spi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0 0x1100a000 0 0x100>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+ <&topckgen CLK_TOP_SPI0_SEL>,
+ <&pericfg CLK_PERI_SPI0_PD>;
+ clock-names = "parent-clk", "sel-clk", "spi-clk";
+ status = "disabled";
+ };
+
+ thermal: thermal@1100b000 {
+ compatible = "mediatek,mt7622-thermal";
+ reg = <0 0x1100b000 0 0x1000>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_THERM_PD>, <&pericfg CLK_PERI_AUXADC_PD>;
+ clock-names = "therm", "auxadc";
+ auxadc = <&auxadc>;
+ apmixedsys = <&apmixedsys>;
+ pericfg = <&pericfg>;
+ nvmem-cells = <&thermal_calibration>;
+ nvmem-cell-names = "calibration-data";
+ };
+
+ svs: svs@1100b000 {
+ compatible = "mediatek,mt7622-svs";
+ reg = <0 0x1100b000 0 0x1000>;
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_LOW>;
+ nvmem-cells = <&svs_calibration>;
+ nvmem-cell-names = "svs_calibration";
+ };
+
+ btif: btif@1100c000 {
+ compatible = "mediatek,btif";
+ reg = <0 0x1100c000 0 0x1000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_LOW>, <GIC_SPI 126 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_BTIF_PD>, <&pericfg CLK_PERI_AP_DMA_PD>;
+ clock-names = "btifc", "apdmac";
+ };
+
+ nandc: nfi@1100d000 {
+ compatible = "mediatek,mt7622-nfc";
+ reg = <0 0x1100D000 0 0x1000>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_NFI_PD>, <&pericfg CLK_PERI_SNFI_PD>;
+ clock-names = "nfi_clk", "pad_clk";
+ ecc-engine = <&bch>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ snand: snfi@1100d000 {
+ compatible = "mediatek,mt7622-snand";
+ reg = <0 0x1100d000 0 0x2000>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_NFI_PD>,
+ <&pericfg CLK_PERI_SNFI_PD>,
+ <&pericfg CLK_PERI_NFIECC_PD>;
+ clock-names = "nfi_clk", "pad_clk", "nfiecc_clk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ bch: ecc@1100e000 {
+ compatible = "mediatek,mt7622-ecc";
+ reg = <0 0x1100e000 0 0x1000>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_NFIECC_PD>;
+ clock-names = "nfiecc_clk";
+ status = "disabled";
+ };
+
+ nor_flash: spi@11014000 {
+ compatible = "mediatek,mt7622-nor",
+ "mediatek,mt8173-nor";
+ reg = <0 0x11014000 0 0xe0>;
+ clocks = <&pericfg CLK_PERI_FLASH_PD>,
+ <&topckgen CLK_TOP_FLASH_SEL>;
+ clock-names = "spi", "sf";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+ };
+
+ spi1: spi@11016000 {
+ compatible = "mediatek,mt7622-spi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0 0x11016000 0 0x100>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+ <&topckgen CLK_TOP_SPI1_SEL>,
+ <&pericfg CLK_PERI_SPI1_PD>;
+ clock-names = "parent-clk", "sel-clk", "spi-clk";
+ status = "disabled";
+ };
+
+ uart4: serial@11019000 {
+ compatible = "mediatek,mt7622-uart",
+ "mediatek,mt6577-uart";
+ reg = <0 0x11019000 0 0x400>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_UART_SEL>, <&pericfg CLK_PERI_UART4_PD>;
+ clock-names = "baud", "bus";
+ status = "disabled";
+ };
+
+ audiosys: audiosys@11220000 {
+ compatible = "mediatek,mt7622-audiosys", "syscon";
+ reg = <0 0x11220000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ afe: audio-controller@11220000 {
+ compatible = "mediatek,mt7622-audio";
+ reg = <0 0x11220000 0 0x2000>,
+ <0 0x112a0000 0 0x10000>;
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&infracfg CLK_INFRA_AUDIO_PD>,
+ <&topckgen CLK_TOP_A1SYS_HP_SEL>,
+ <&topckgen CLK_TOP_A2SYS_HP_SEL>,
+ <&topckgen CLK_TOP_A1SYS_HP_DIV>,
+ <&topckgen CLK_TOP_A2SYS_HP_DIV>,
+ <&topckgen CLK_TOP_AUD1PLL>,
+ <&topckgen CLK_TOP_AUD2PLL>,
+ <&topckgen CLK_TOP_A1SYS_HP_DIV_PD>,
+ <&topckgen CLK_TOP_A2SYS_HP_DIV_PD>,
+ <&topckgen CLK_TOP_AUD_INTBUS_SEL>,
+ <&topckgen CLK_TOP_SYSPLL1_D4>,
+ <&topckgen CLK_TOP_INTDIR_SEL>,
+ <&topckgen CLK_TOP_UNIVPLL_D2>,
+ <&topckgen CLK_TOP_APLL1_SEL>,
+ <&topckgen CLK_TOP_APLL2_SEL>,
+ <&topckgen CLK_TOP_I2S0_MCK_SEL>,
+ <&topckgen CLK_TOP_I2S1_MCK_SEL>,
+ <&topckgen CLK_TOP_I2S2_MCK_SEL>,
+ <&topckgen CLK_TOP_I2S3_MCK_SEL>,
+ <&topckgen CLK_TOP_APLL1_DIV>,
+ <&topckgen CLK_TOP_APLL2_DIV>,
+ <&topckgen CLK_TOP_I2S0_MCK_DIV>,
+ <&topckgen CLK_TOP_I2S1_MCK_DIV>,
+ <&topckgen CLK_TOP_I2S2_MCK_DIV>,
+ <&topckgen CLK_TOP_I2S3_MCK_DIV>,
+ <&topckgen CLK_TOP_APLL1_DIV_PD>,
+ <&topckgen CLK_TOP_APLL2_DIV_PD>,
+ <&topckgen CLK_TOP_I2S0_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S1_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S2_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S3_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_AUD1_SEL>,
+ <&topckgen CLK_TOP_AUD2_SEL>,
+ <&topckgen CLK_TOP_ASM_H_SEL>,
+ <&topckgen CLK_TOP_ASM_M_SEL>,
+ <&topckgen CLK_TOP_SYSPLL_D5>,
+ <&topckgen CLK_TOP_UNIVPLL2_D2>,
+ <&audiosys CLK_AUDIO_AFE>,
+ <&audiosys CLK_AUDIO_APLL>,
+ <&audiosys CLK_AUDIO_A1SYS>,
+ <&audiosys CLK_AUDIO_A2SYS>;
+
+ clock-names = "infra_audio_pd",
+ "top_a1sys_hp_sel",
+ "top_a2sys_hp_sel",
+ "top_a1sys_div",
+ "top_a2sys_div",
+ "top_aud1pll_ck",
+ "top_aud2pll_ck",
+ "top_a1sys_div_pd",
+ "top_a2sys_div_pd",
+ "top_aud_intbus_sel",
+ "top_syspll1_d4",
+ "top_intdir_sel",
+ "top_univpll_d2",
+ "top_apll1_ck_sel",
+ "top_apll2_ck_sel",
+ "top_i2s0_mck_sel",
+ "top_i2s1_mck_sel",
+ "top_i2s2_mck_sel",
+ "top_i2s3_mck_sel",
+ "top_apll1_ck_div",
+ "top_apll2_ck_div",
+ "top_i2s0_mck_div",
+ "top_i2s1_mck_div",
+ "top_i2s2_mck_div",
+ "top_i2s3_mck_div",
+ "top_apll1_ck_div_pd",
+ "top_apll2_ck_div_pd",
+ "top_i2s0_mck_div_pd",
+ "top_i2s1_mck_div_pd",
+ "top_i2s2_mck_div_pd",
+ "top_i2s3_mck_div_pd",
+ "top_aud1_sel",
+ "top_aud2_sel",
+ "top_asm_h_sel",
+ "top_asm_m_sel",
+ "top_syspll_d5",
+ "top_univpll2_d2",
+ "top_audio_afe",
+ "top_audio_apll",
+ "top_audio_a1sys",
+ "top_audio_a2sys";
+ };
+
+ mmc0: mmc@11230000 {
+ compatible = "mediatek,mt7622-mmc";
+ reg = <0 0x11230000 0 0x1000>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_MSDC30_0_PD>,
+ <&topckgen CLK_TOP_MSDC50_0_SEL>;
+ clock-names = "source", "hclk";
+ status = "disabled";
+ };
+
+ mmc1: mmc@11240000 {
+ compatible = "mediatek,mt7622-mmc";
+ reg = <0 0x11240000 0 0x1000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_MSDC30_1_PD>,
+ <&topckgen CLK_TOP_AXI_SEL>;
+ clock-names = "source", "hclk";
+ status = "disabled";
+ };
+
+ wbsys: wbsys@18000000 {
+ compatible = "mediatek,wbsys";
+ reg = <0 0x18000000 0 0x100000>;
+ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_LOW>;
+ #interrupt-cells = <1>;
+ dma-coherent;
+ };
+
+ ssusbsys: ssusbsys@1a000000 {
+ compatible = "mediatek,mt7622-ssusbsys", "syscon";
+ reg = <0 0x1a000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ usb1: usb@1a0c0000 {
+ compatible = "mediatek,mt7622-xhci", "mediatek,mtk-xhci";
+ reg = <0 0x1a0c0000 0 0x01000>,
+ <0 0x1a0c4700 0 0x0100>;
+ reg-names = "mac", "ippc";
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_LOW>;
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF1>;
+ clocks = <&ssusbsys CLK_SSUSB_SYS_EN>,
+ <&ssusbsys CLK_SSUSB_REF_EN>,
+ <&ssusbsys CLK_SSUSB_MCU_EN>,
+ <&ssusbsys CLK_SSUSB_DMA_EN>;
+ clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck";
+ phys = <&u2port0 PHY_TYPE_USB2>,
+ <&u3port0 PHY_TYPE_USB3>,
+ <&u2port1 PHY_TYPE_USB2>;
+ status = "disabled";
+ };
+
+ u3phy1: usb-phy@1a0c4000 {
+ compatible = "mediatek,mt7622-u3phy", "mediatek,generic-tphy-v1";
+ reg = <0 0x1a0c4000 0 0x700>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ u2port0: usb-phy@1a0c4800 {
+ reg = <0 0x1a0c4800 0 0x0100>;
+ #phy-cells = <1>;
+ clocks = <&ssusbsys CLK_SSUSB_U2_PHY_EN>;
+ clock-names = "ref";
+ };
+
+ u3port0: usb-phy@1a0c4900 {
+ reg = <0 0x1a0c4900 0 0x0700>;
+ #phy-cells = <1>;
+ clocks = <&clk25m>;
+ clock-names = "ref";
+ };
+
+ u2port1: usb-phy@1a0c5000 {
+ reg = <0 0x1a0c5000 0 0x0100>;
+ #phy-cells = <1>;
+ clocks = <&ssusbsys CLK_SSUSB_U2_PHY_1P_EN>;
+ clock-names = "ref";
+ };
+ };
+
+ pciesys: pciesys@1a100800 {
+ compatible = "mediatek,mt7622-pciesys", "syscon";
+ reg = <0 0x1a100800 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ pcie: pcie@1a140000 {
+ compatible = "mediatek,mt7622-pcie";
+ device_type = "pci";
+ reg = <0 0x1a140000 0 0x1000>,
+ <0 0x1a143000 0 0x1000>,
+ <0 0x1a145000 0 0x1000>;
+ reg-names = "subsys", "port0", "port1";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+ <&pciesys CLK_PCIE_P1_MAC_EN>,
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+ /* designer has connect rc1 with p0_ahb clock */
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+ <&pciesys CLK_PCIE_P0_AUX_EN>,
+ <&pciesys CLK_PCIE_P1_AUX_EN>,
+ <&pciesys CLK_PCIE_P0_AXI_EN>,
+ <&pciesys CLK_PCIE_P1_AXI_EN>,
+ <&pciesys CLK_PCIE_P0_OBFF_EN>,
+ <&pciesys CLK_PCIE_P1_OBFF_EN>,
+ <&pciesys CLK_PCIE_P0_PIPE_EN>,
+ <&pciesys CLK_PCIE_P1_PIPE_EN>;
+ clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+ "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+ "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+
+ phys = <&pcieport0 PHY_TYPE_PCIE>,
+ <&pcieport1 PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy0", "pcie-phy1";
+
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
+ pcie0: pcie@0,0 {
+ device_type = "pci";
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+ <0 0 0 2 &pcie_intc0 1>,
+ <0 0 0 3 &pcie_intc0 2>,
+ <0 0 0 4 &pcie_intc0 3>;
+ pcie_intc0: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ pcie1: pcie@1,0 {
+ device_type = "pci";
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+ <0 0 0 2 &pcie_intc1 1>,
+ <0 0 0 3 &pcie_intc1 2>,
+ <0 0 0 4 &pcie_intc1 3>;
+ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ pciephy: pcie-phy@1a148000 {
+ compatible = "mediatek,generic-tphy-v2";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ pcieport0: port0phy {
+ reg = <0 0x1a148000 0 0x1000>;
+ clocks = <&clk25m>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ };
+
+ pcieport1: port1phy {
+ reg = <0 0x1a14a000 0 0x1000>;
+ clocks = <&clk25m>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ };
+ };
+
+ sata: sata@1a200000 {
+ compatible = "mediatek,mt7622-ahci",
+ "mediatek,mtk-ahci";
+ reg = <0 0x1a200000 0 0x1100>;
+ interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hostc";
+ clocks = <&apmixedsys CLK_APMIXED_ETH1PLL>,
+ <&pciesys CLK_SATA_AHB_EN>,
+ <&pciesys CLK_SATA_AXI_EN>,
+ <&pciesys CLK_SATA_ASIC_EN>,
+ <&pciesys CLK_SATA_RBC_EN>,
+ <&pciesys CLK_SATA_PM_EN>;
+ clock-names = "pll", "ahb", "axi", "asic", "rbc", "pm";
+ phys = <&sata_port PHY_TYPE_SATA>;
+ phy-names = "sata-phy";
+ ports-implemented = <0x1>;
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ resets = <&pciesys MT7622_SATA_AXI_BUS_RST>,
+ <&pciesys MT7622_SATA_PHY_SW_RST>,
+ <&pciesys MT7622_SATA_PHY_REG_RST>;
+ reset-names = "axi", "sw", "reg";
+ mediatek,phy-mode = <&pciesys>;
+ };
+
+ sata_phy: sata-phy@1a242000 {
+ compatible = "mediatek,generic-tphy-v1";
+ reg = <0 0x1a242000 0 0x0100>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ sata_port: sata-phy@1a243000 {
+ reg = <0 0x1a243000 0 0x0100>;
+ clocks = <&pciesys CLK_SATA_AHB_EN>;
+ clock-names = "ref";
+ #phy-cells = <1>;
+ };
+ };
+
+ hifsys: syscon@1af00000 {
+ compatible = "mediatek,mt7622-hifsys", "syscon";
+ reg = <0 0x1af00000 0 0x70>;
+ };
+
+ ethsys: syscon@1b000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mediatek,mt7622-ethsys",
+ "syscon";
+ reg = <0 0x1b000000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ gsw: gsw@1b100000 {
+ compatible = "mediatek,rtk-gsw",
+ "mediatek,mt753x";
+ mediatek,ethsys = <&ethsys>;
+ status = "disabled";
+ };
+
+ raeth: raeth@1b100000 {
+ compatible = "mediatek,mt7622-raeth";
+ reg = <0 0x1b100000 0 0x20000>;
+ interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 225 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 240 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&topckgen CLK_TOP_ETH_SEL>,
+ <&apmixedsys CLK_APMIXED_ETH1PLL>,
+ <&apmixedsys CLK_APMIXED_ETH2PLL>,
+ <&apmixedsys CLK_APMIXED_SGMIPLL>,
+ <&clk25m>,
+ <&ethsys CLK_ETH_ESW_EN>,
+ <&ethsys CLK_ETH_GP2_EN>,
+ <&ethsys CLK_ETH_GP1_EN>,
+ <&ethsys CLK_ETH_GP0_EN>,
+ <&sgmiisys CLK_SGMII_TX250M_EN>,
+ <&sgmiisys CLK_SGMII_RX250M_EN>,
+ <&sgmiisys CLK_SGMII_CDR_REF>,
+ <&sgmiisys CLK_SGMII_CDR_FB>;
+ clock-names = "ethif", "eth1pll", "eth2pll",
+ "sgmipll", "trgpll", "esw", "gp2",
+ "gp1", "gp0", "sgmii_tx250m",
+ "sgmii_rx250m", "sgmii_cdr_ref",
+ "sgmii_cdr_fb";
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+ mediatek,ethsys = <&ethsys>;
+ mediatek,gsw = <&gsw>;
+ #reset-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ wdma: wdma@1b102800 {
+ compatible = "mediatek,wed-wdma";
+ reg = <0 0x1b102800 0 0x400>,
+ <0 0x1b102c00 0 0x400>;
+ interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 217 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 218 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 219 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 220 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 221 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ sgmiisys: sgmiisys@1b128000 {
+ compatible = "mediatek,mt7622-sgmiisys", "syscon";
+ reg = <0 0x1b128000 0 0x3000>;
+ mediatek,physpeed = "2500";
+ #clock-cells = <1>;
+ };
+
+ clkao: clkao {
+ compatible = "simple-bus";
+ };
+
+ ioc: ioc {
+ compatible = "mediatek,mt7622-subsys-ioc";
+ arm,cci-400-s4 = <&cci_control2>;
+ mediatek,wbsys = <&infracfg>;
+ mediatek,hifsys = <&hifsys>;
+ mediatek,ethsys = <&ethsys>;
+ mediatek,eth = <&raeth>;
+ mediatek,wifi = <&wbsys>;
+
+ mediatek,en_usb;
+ mediatek,en_pcie_sata;
+ };
+};
+
+#include "mt7622-clkao.dtsi"
diff --git a/arch/arm64/configs/mt7622_defconfig b/arch/arm64/configs/mt7622_defconfig
new file mode 100644
index 000000000000..6252edb21ac3
--- /dev/null
+++ b/arch/arm64/configs/mt7622_defconfig
@@ -0,0 +1,222 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_CGROUP_HUGETLB=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_MACH_MT7622=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCI_XGENE=y
+CONFIG_PCIE_MEDIATEK=y
+CONFIG_SCHED_MC=y
+CONFIG_PREEMPT=y
+CONFIG_KSM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CMA=y
+CONFIG_CMDLINE="console=ttyAMA0"
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_BPF_JIT=y
+# CONFIG_WIRELESS is not set
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+# CONFIG_TEGRA_AHB is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
+CONFIG_MTK_SUBSYS_IOC=y
+CONFIG_MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_MTK=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_MTK_ICE_DEBUG=y
+CONFIG_MTK_EMI_BWL=y
+CONFIG_MTK_EMI_7622=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_CEVA=y
+CONFIG_AHCI_MTK=y
+CONFIG_AHCI_XGENE=y
+CONFIG_PATA_PLATFORM=y
+CONFIG_PATA_OF_PLATFORM=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
+CONFIG_NET_XGENE=y
+CONFIG_SKY2=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_MT6577=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_MT65XX=y
+CONFIG_I2C_QUP=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_QUP=y
+CONFIG_PINCTRL_MSM8916=y
+# CONFIG_PINCTRL_MT2712 is not set
+# CONFIG_PINCTRL_MT8173 is not set
+CONFIG_GPIO_PL061=y
+CONFIG_GPIO_XGENE=y
+CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_SYSCON=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_MEDIATEK_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_QCOM_SMD_RPM=y
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ULPI=y
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_EXYNOS=y
+CONFIG_MMC_MTK=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_SYSCON=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_EFI=y
+CONFIG_RTC_DRV_XGENE=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_BAM_DMA=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_HWSPINLOCK_QCOM=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_QCOM_SMEM=y
+CONFIG_QCOM_SMD=y
+CONFIG_QCOM_SMD_RPM=y
+CONFIG_IIO=y
+CONFIG_MEDIATEK_MT6577_AUXADC=y
+CONFIG_PWM=y
+CONFIG_PWM_MEDIATEK=y
+CONFIG_PHY_XGENE=y
+CONFIG_NVMEM=y
+CONFIG_MTK_EFUSE=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
+CONFIG_QUOTA=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_EFIVAR_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_9P_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
+CONFIG_MEMTEST=y
+CONFIG_SECURITY=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
diff --git a/arch/arm64/configs/mt7622_rfb1_defconfig b/arch/arm64/configs/mt7622_rfb1_defconfig
new file mode 100644
index 000000000000..3235de32cb98
--- /dev/null
+++ b/arch/arm64/configs/mt7622_rfb1_defconfig
@@ -0,0 +1,75 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="(mt7622)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+# CONFIG_USELIB is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_UTS_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../prebuilt/bootable/7622_loader/rootfs.cpio.gz"
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_MACH_MT7622=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=2
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+# CONFIG_BOUNCE is not set
+CONFIG_CMDLINE="console=ttyS0"
+# CONFIG_EFI is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+# CONFIG_SUSPEND is not set
+# CONFIG_WAKELOCK is not set
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_GOV_LADDER is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_BLK_DEV is not set
+# CONFIG_GPS is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_MT6577=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_POWER_RESET_SYSCON=y
+# CONFIG_HWMON is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_COMMON_CLK_MT2701 is not set
+# CONFIG_COMMON_CLK_MT8135 is not set
+# CONFIG_COMMON_CLK_MT8173 is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_CRC16=y
diff --git a/arch/arm64/crypto/.gitignore b/arch/arm64/crypto/.gitignore
new file mode 100644
index 000000000000..879df8781ed5
--- /dev/null
+++ b/arch/arm64/crypto/.gitignore
@@ -0,0 +1,2 @@
+sha256-core.S
+sha512-core.S
diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
index 2cf32e9887e1..d92ae2e3a779 100644
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -8,31 +8,48 @@ menuconfig ARM64_CRYPTO
if ARM64_CRYPTO
+config CRYPTO_SHA256_ARM64
+ tristate "SHA-224/SHA-256 digest algorithm for arm64"
+ select CRYPTO_HASH
+
+config CRYPTO_SHA512_ARM64
+ tristate "SHA-384/SHA-512 digest algorithm for arm64"
+ select CRYPTO_HASH
+
config CRYPTO_SHA1_ARM64_CE
tristate "SHA-1 digest algorithm (ARMv8 Crypto Extensions)"
- depends on ARM64 && KERNEL_MODE_NEON
+ depends on KERNEL_MODE_NEON
select CRYPTO_HASH
+ select CRYPTO_SHA1
config CRYPTO_SHA2_ARM64_CE
tristate "SHA-224/SHA-256 digest algorithm (ARMv8 Crypto Extensions)"
- depends on ARM64 && KERNEL_MODE_NEON
+ depends on KERNEL_MODE_NEON
select CRYPTO_HASH
+ select CRYPTO_SHA256_ARM64
config CRYPTO_GHASH_ARM64_CE
tristate "GHASH (for GCM chaining mode) using ARMv8 Crypto Extensions"
- depends on ARM64 && KERNEL_MODE_NEON
+ depends on KERNEL_MODE_NEON
select CRYPTO_HASH
+ select CRYPTO_GF128MUL
+
+config CRYPTO_AES_ARM64
+ tristate "AES core cipher using scalar instructions"
+ select CRYPTO_AES
config CRYPTO_AES_ARM64_CE
tristate "AES core cipher using ARMv8 Crypto Extensions"
depends on ARM64 && KERNEL_MODE_NEON
select CRYPTO_ALGAPI
+ select CRYPTO_AES_ARM64
config CRYPTO_AES_ARM64_CE_CCM
tristate "AES in CCM mode using ARMv8 Crypto Extensions"
depends on ARM64 && KERNEL_MODE_NEON
select CRYPTO_ALGAPI
select CRYPTO_AES_ARM64_CE
+ select CRYPTO_AES_ARM64
select CRYPTO_AEAD
config CRYPTO_AES_ARM64_CE_BLK
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index 550e02a5aa32..94a75cac554f 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -30,6 +30,15 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o
obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o
aes-neon-blk-y := aes-glue-neon.o aes-neon.o
+obj-$(CONFIG_CRYPTO_SHA256_ARM64) += sha256-arm64.o
+sha256-arm64-y := sha256-glue.o sha256-core.o
+
+obj-$(CONFIG_CRYPTO_SHA512_ARM64) += sha512-arm64.o
+sha512-arm64-y := sha512-glue.o sha512-core.o
+
+obj-$(CONFIG_CRYPTO_AES_ARM64) += aes-arm64.o
+aes-arm64-y := aes-cipher-core.o aes-cipher-glue.o
+
AFLAGS_aes-ce.o := -DINTERLEAVE=4
AFLAGS_aes-neon.o := -DINTERLEAVE=4
@@ -41,3 +50,14 @@ CFLAGS_crc32-arm64.o := -mcpu=generic+crc
$(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
$(call if_changed_rule,cc_o_c)
+
+quiet_cmd_perlasm = PERLASM $@
+ cmd_perlasm = $(PERL) $(<) void $(@)
+
+$(obj)/sha256-core.S: $(src)/sha512-armv8.pl
+ $(call cmd,perlasm)
+
+$(obj)/sha512-core.S: $(src)/sha512-armv8.pl
+ $(call cmd,perlasm)
+
+.PRECIOUS: $(obj)/sha256-core.S $(obj)/sha512-core.S
diff --git a/arch/arm64/crypto/aes-ce-ccm-core.S b/arch/arm64/crypto/aes-ce-ccm-core.S
index 7bc459d9235c..1b151442dac1 100644
--- a/arch/arm64/crypto/aes-ce-ccm-core.S
+++ b/arch/arm64/crypto/aes-ce-ccm-core.S
@@ -1,7 +1,7 @@
/*
* aesce-ccm-core.S - AES-CCM transform for ARMv8 with Crypto Extensions
*
- * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*
* 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
@@ -32,7 +32,7 @@ ENTRY(ce_aes_ccm_auth_data)
beq 8f /* out of input? */
cbnz w8, 0b
eor v0.16b, v0.16b, v1.16b
-1: ld1 {v3.16b}, [x4] /* load first round key */
+1: ld1 {v3.4s}, [x4] /* load first round key */
prfm pldl1strm, [x1]
cmp w5, #12 /* which key size? */
add x6, x4, #16
@@ -42,17 +42,17 @@ ENTRY(ce_aes_ccm_auth_data)
mov v5.16b, v3.16b
b 4f
2: mov v4.16b, v3.16b
- ld1 {v5.16b}, [x6], #16 /* load 2nd round key */
+ ld1 {v5.4s}, [x6], #16 /* load 2nd round key */
3: aese v0.16b, v4.16b
aesmc v0.16b, v0.16b
-4: ld1 {v3.16b}, [x6], #16 /* load next round key */
+4: ld1 {v3.4s}, [x6], #16 /* load next round key */
aese v0.16b, v5.16b
aesmc v0.16b, v0.16b
-5: ld1 {v4.16b}, [x6], #16 /* load next round key */
+5: ld1 {v4.4s}, [x6], #16 /* load next round key */
subs w7, w7, #3
aese v0.16b, v3.16b
aesmc v0.16b, v0.16b
- ld1 {v5.16b}, [x6], #16 /* load next round key */
+ ld1 {v5.4s}, [x6], #16 /* load next round key */
bpl 3b
aese v0.16b, v4.16b
subs w2, w2, #16 /* last data? */
@@ -91,7 +91,7 @@ ENDPROC(ce_aes_ccm_auth_data)
* u32 rounds);
*/
ENTRY(ce_aes_ccm_final)
- ld1 {v3.16b}, [x2], #16 /* load first round key */
+ ld1 {v3.4s}, [x2], #16 /* load first round key */
ld1 {v0.16b}, [x0] /* load mac */
cmp w3, #12 /* which key size? */
sub w3, w3, #2 /* modified # of rounds */
@@ -101,17 +101,17 @@ ENTRY(ce_aes_ccm_final)
mov v5.16b, v3.16b
b 2f
0: mov v4.16b, v3.16b
-1: ld1 {v5.16b}, [x2], #16 /* load next round key */
+1: ld1 {v5.4s}, [x2], #16 /* load next round key */
aese v0.16b, v4.16b
aesmc v0.16b, v0.16b
aese v1.16b, v4.16b
aesmc v1.16b, v1.16b
-2: ld1 {v3.16b}, [x2], #16 /* load next round key */
+2: ld1 {v3.4s}, [x2], #16 /* load next round key */
aese v0.16b, v5.16b
aesmc v0.16b, v0.16b
aese v1.16b, v5.16b
aesmc v1.16b, v1.16b
-3: ld1 {v4.16b}, [x2], #16 /* load next round key */
+3: ld1 {v4.4s}, [x2], #16 /* load next round key */
subs w3, w3, #3
aese v0.16b, v3.16b
aesmc v0.16b, v0.16b
@@ -138,31 +138,31 @@ CPU_LE( rev x8, x8 ) /* keep swabbed ctr in reg */
cmp w4, #12 /* which key size? */
sub w7, w4, #2 /* get modified # of rounds */
ins v1.d[1], x9 /* no carry in lower ctr */
- ld1 {v3.16b}, [x3] /* load first round key */
+ ld1 {v3.4s}, [x3] /* load first round key */
add x10, x3, #16
bmi 1f
bne 4f
mov v5.16b, v3.16b
b 3f
1: mov v4.16b, v3.16b
- ld1 {v5.16b}, [x10], #16 /* load 2nd round key */
+ ld1 {v5.4s}, [x10], #16 /* load 2nd round key */
2: /* inner loop: 3 rounds, 2x interleaved */
aese v0.16b, v4.16b
aesmc v0.16b, v0.16b
aese v1.16b, v4.16b
aesmc v1.16b, v1.16b
-3: ld1 {v3.16b}, [x10], #16 /* load next round key */
+3: ld1 {v3.4s}, [x10], #16 /* load next round key */
aese v0.16b, v5.16b
aesmc v0.16b, v0.16b
aese v1.16b, v5.16b
aesmc v1.16b, v1.16b
-4: ld1 {v4.16b}, [x10], #16 /* load next round key */
+4: ld1 {v4.4s}, [x10], #16 /* load next round key */
subs w7, w7, #3
aese v0.16b, v3.16b
aesmc v0.16b, v0.16b
aese v1.16b, v3.16b
aesmc v1.16b, v1.16b
- ld1 {v5.16b}, [x10], #16 /* load next round key */
+ ld1 {v5.4s}, [x10], #16 /* load next round key */
bpl 2b
aese v0.16b, v4.16b
aese v1.16b, v4.16b
diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c
index f4bf2f2a014c..915c661e6d34 100644
--- a/arch/arm64/crypto/aes-ce-ccm-glue.c
+++ b/arch/arm64/crypto/aes-ce-ccm-glue.c
@@ -1,7 +1,7 @@
/*
* aes-ccm-glue.c - AES-CCM transform for ARMv8 with Crypto Extensions
*
- * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*
* 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
@@ -9,6 +9,7 @@
*/
#include <asm/neon.h>
+#include <asm/simd.h>
#include <asm/unaligned.h>
#include <crypto/aes.h>
#include <crypto/algapi.h>
@@ -44,6 +45,8 @@ asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
asmlinkage void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u32 const rk[],
u32 rounds);
+asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds);
+
static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key,
unsigned int key_len)
{
@@ -103,7 +106,43 @@ static int ccm_init_mac(struct aead_request *req, u8 maciv[], u32 msglen)
return 0;
}
-static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
+static void ccm_update_mac(struct crypto_aes_ctx *key, u8 mac[], u8 const in[],
+ u32 abytes, u32 *macp, bool use_neon)
+{
+ if (likely(use_neon)) {
+ ce_aes_ccm_auth_data(mac, in, abytes, macp, key->key_enc,
+ num_rounds(key));
+ } else {
+ if (*macp > 0 && *macp < AES_BLOCK_SIZE) {
+ int added = min(abytes, AES_BLOCK_SIZE - *macp);
+
+ crypto_xor(&mac[*macp], in, added);
+
+ *macp += added;
+ in += added;
+ abytes -= added;
+ }
+
+ while (abytes >= AES_BLOCK_SIZE) {
+ __aes_arm64_encrypt(key->key_enc, mac, mac,
+ num_rounds(key));
+ crypto_xor(mac, in, AES_BLOCK_SIZE);
+
+ in += AES_BLOCK_SIZE;
+ abytes -= AES_BLOCK_SIZE;
+ }
+
+ if (abytes > 0) {
+ __aes_arm64_encrypt(key->key_enc, mac, mac,
+ num_rounds(key));
+ crypto_xor(mac, in, abytes);
+ *macp = abytes;
+ }
+ }
+}
+
+static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[],
+ bool use_neon)
{
struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead);
@@ -122,8 +161,7 @@ static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
ltag.len = 6;
}
- ce_aes_ccm_auth_data(mac, (u8 *)&ltag, ltag.len, &macp, ctx->key_enc,
- num_rounds(ctx));
+ ccm_update_mac(ctx, mac, (u8 *)&ltag, ltag.len, &macp, use_neon);
scatterwalk_start(&walk, req->src);
do {
@@ -135,8 +173,7 @@ static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
n = scatterwalk_clamp(&walk, len);
}
p = scatterwalk_map(&walk);
- ce_aes_ccm_auth_data(mac, p, n, &macp, ctx->key_enc,
- num_rounds(ctx));
+ ccm_update_mac(ctx, mac, p, n, &macp, use_neon);
len -= n;
scatterwalk_unmap(p);
@@ -145,6 +182,61 @@ static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
} while (len);
}
+static int ccm_crypt_fallback(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk, u8 mac[], u8 iv0[],
+ struct crypto_aes_ctx *ctx, bool enc)
+{
+ u8 buf[AES_BLOCK_SIZE];
+ int err = 0;
+
+ while (walk->nbytes) {
+ int blocks = walk->nbytes / AES_BLOCK_SIZE;
+ u32 tail = walk->nbytes % AES_BLOCK_SIZE;
+ u8 *dst = walk->dst.virt.addr;
+ u8 *src = walk->src.virt.addr;
+ u32 nbytes = walk->nbytes;
+
+ if (nbytes == walk->total && tail > 0) {
+ blocks++;
+ tail = 0;
+ }
+
+ do {
+ u32 bsize = AES_BLOCK_SIZE;
+
+ if (nbytes < AES_BLOCK_SIZE)
+ bsize = nbytes;
+
+ crypto_inc(walk->iv, AES_BLOCK_SIZE);
+ __aes_arm64_encrypt(ctx->key_enc, buf, walk->iv,
+ num_rounds(ctx));
+ __aes_arm64_encrypt(ctx->key_enc, mac, mac,
+ num_rounds(ctx));
+ if (enc)
+ crypto_xor(mac, src, bsize);
+
+ if (dst != src)
+ memcpy(dst, src, bsize);
+ crypto_xor(dst, buf, bsize);
+
+ if (!enc)
+ crypto_xor(mac, dst, bsize);
+ dst += bsize;
+ src += bsize;
+ nbytes -= bsize;
+ } while (--blocks);
+
+ err = blkcipher_walk_done(desc, walk, tail);
+ }
+
+ if (!err) {
+ __aes_arm64_encrypt(ctx->key_enc, buf, iv0, num_rounds(ctx));
+ __aes_arm64_encrypt(ctx->key_enc, mac, mac, num_rounds(ctx));
+ crypto_xor(mac, buf, AES_BLOCK_SIZE);
+ }
+ return err;
+}
+
static int ccm_encrypt(struct aead_request *req)
{
struct crypto_aead *aead = crypto_aead_reqtfm(req);
@@ -158,16 +250,18 @@ static int ccm_encrypt(struct aead_request *req)
u8 __aligned(8) mac[AES_BLOCK_SIZE];
u8 buf[AES_BLOCK_SIZE];
u32 len = req->cryptlen;
+ bool use_neon = may_use_simd();
int err;
err = ccm_init_mac(req, mac, len);
if (err)
return err;
- kernel_neon_begin_partial(6);
+ if (likely(use_neon))
+ kernel_neon_begin();
if (req->assoclen)
- ccm_calculate_auth_mac(req, mac);
+ ccm_calculate_auth_mac(req, mac, use_neon);
/* preserve the original iv for the final round */
memcpy(buf, req->iv, AES_BLOCK_SIZE);
@@ -181,23 +275,29 @@ static int ccm_encrypt(struct aead_request *req)
err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
AES_BLOCK_SIZE);
- while (walk.nbytes) {
- u32 tail = walk.nbytes % AES_BLOCK_SIZE;
+ if (likely(use_neon)) {
+ while (walk.nbytes) {
+ u32 tail = walk.nbytes % AES_BLOCK_SIZE;
- if (walk.nbytes == len)
- tail = 0;
+ if (walk.nbytes == len)
+ tail = 0;
- ce_aes_ccm_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
- walk.nbytes - tail, ctx->key_enc,
- num_rounds(ctx), mac, walk.iv);
+ ce_aes_ccm_encrypt(walk.dst.virt.addr,
+ walk.src.virt.addr,
+ walk.nbytes - tail, ctx->key_enc,
+ num_rounds(ctx), mac, walk.iv);
- len -= walk.nbytes - tail;
- err = blkcipher_walk_done(&desc, &walk, tail);
- }
- if (!err)
- ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx));
+ len -= walk.nbytes - tail;
+ err = blkcipher_walk_done(&desc, &walk, tail);
+ }
+ if (!err)
+ ce_aes_ccm_final(mac, buf, ctx->key_enc,
+ num_rounds(ctx));
- kernel_neon_end();
+ kernel_neon_end();
+ } else {
+ err = ccm_crypt_fallback(&desc, &walk, mac, buf, ctx, true);
+ }
if (err)
return err;
@@ -223,16 +323,18 @@ static int ccm_decrypt(struct aead_request *req)
u8 __aligned(8) mac[AES_BLOCK_SIZE];
u8 buf[AES_BLOCK_SIZE];
u32 len = req->cryptlen - authsize;
+ bool use_neon = may_use_simd();
int err;
err = ccm_init_mac(req, mac, len);
if (err)
return err;
- kernel_neon_begin_partial(6);
+ if (likely(use_neon))
+ kernel_neon_begin();
if (req->assoclen)
- ccm_calculate_auth_mac(req, mac);
+ ccm_calculate_auth_mac(req, mac, use_neon);
/* preserve the original iv for the final round */
memcpy(buf, req->iv, AES_BLOCK_SIZE);
@@ -246,23 +348,29 @@ static int ccm_decrypt(struct aead_request *req)
err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
AES_BLOCK_SIZE);
- while (walk.nbytes) {
- u32 tail = walk.nbytes % AES_BLOCK_SIZE;
+ if (likely(use_neon)) {
+ while (walk.nbytes) {
+ u32 tail = walk.nbytes % AES_BLOCK_SIZE;
- if (walk.nbytes == len)
- tail = 0;
+ if (walk.nbytes == len)
+ tail = 0;
- ce_aes_ccm_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
- walk.nbytes - tail, ctx->key_enc,
- num_rounds(ctx), mac, walk.iv);
+ ce_aes_ccm_decrypt(walk.dst.virt.addr,
+ walk.src.virt.addr,
+ walk.nbytes - tail, ctx->key_enc,
+ num_rounds(ctx), mac, walk.iv);
- len -= walk.nbytes - tail;
- err = blkcipher_walk_done(&desc, &walk, tail);
- }
- if (!err)
- ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx));
+ len -= walk.nbytes - tail;
+ err = blkcipher_walk_done(&desc, &walk, tail);
+ }
+ if (!err)
+ ce_aes_ccm_final(mac, buf, ctx->key_enc,
+ num_rounds(ctx));
- kernel_neon_end();
+ kernel_neon_end();
+ } else {
+ err = ccm_crypt_fallback(&desc, &walk, mac, buf, ctx, false);
+ }
if (err)
return err;
diff --git a/arch/arm64/crypto/aes-ce-cipher-core.c b/arch/arm64/crypto/aes-ce-cipher-core.c
index 9f4191774b35..d857b0f01fc9 100644
--- a/arch/arm64/crypto/aes-ce-cipher-core.c
+++ b/arch/arm64/crypto/aes-ce-cipher-core.c
@@ -1,7 +1,7 @@
/*
* aes-ce-cipher-core.c - core AES cipher using ARMv8 Crypto Extensions
*
- * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*
* 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
@@ -9,11 +9,16 @@
*/
#include <asm/neon.h>
+#include <asm/simd.h>
+#include <asm/unaligned.h>
#include <crypto/aes.h>
#include <linux/crypto.h>
#include "aes-ce-setkey.h"
+asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds);
+asmlinkage void __aes_arm64_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds);
+
struct aes_block {
u8 b[AES_BLOCK_SIZE];
};
@@ -38,27 +43,32 @@ void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
void *dummy0;
int dummy1;
- kernel_neon_begin_partial(4);
+ if (!may_use_simd()) {
+ __aes_arm64_encrypt(ctx->key_enc, dst, src, num_rounds(ctx));
+ return;
+ }
+
+ kernel_neon_begin();
__asm__(" ld1 {v0.16b}, %[in] ;"
- " ld1 {v1.16b}, [%[key]], #16 ;"
+ " ld1 {v1.4s}, [%[key]], #16 ;"
" cmp %w[rounds], #10 ;"
" bmi 0f ;"
" bne 3f ;"
" mov v3.16b, v1.16b ;"
" b 2f ;"
"0: mov v2.16b, v1.16b ;"
- " ld1 {v3.16b}, [%[key]], #16 ;"
+ " ld1 {v3.4s}, [%[key]], #16 ;"
"1: aese v0.16b, v2.16b ;"
" aesmc v0.16b, v0.16b ;"
- "2: ld1 {v1.16b}, [%[key]], #16 ;"
+ "2: ld1 {v1.4s}, [%[key]], #16 ;"
" aese v0.16b, v3.16b ;"
" aesmc v0.16b, v0.16b ;"
- "3: ld1 {v2.16b}, [%[key]], #16 ;"
+ "3: ld1 {v2.4s}, [%[key]], #16 ;"
" subs %w[rounds], %w[rounds], #3 ;"
" aese v0.16b, v1.16b ;"
" aesmc v0.16b, v0.16b ;"
- " ld1 {v3.16b}, [%[key]], #16 ;"
+ " ld1 {v3.4s}, [%[key]], #16 ;"
" bpl 1b ;"
" aese v0.16b, v2.16b ;"
" eor v0.16b, v0.16b, v3.16b ;"
@@ -83,27 +93,32 @@ void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
void *dummy0;
int dummy1;
- kernel_neon_begin_partial(4);
+ if (!may_use_simd()) {
+ __aes_arm64_decrypt(ctx->key_dec, dst, src, num_rounds(ctx));
+ return;
+ }
+
+ kernel_neon_begin();
__asm__(" ld1 {v0.16b}, %[in] ;"
- " ld1 {v1.16b}, [%[key]], #16 ;"
+ " ld1 {v1.4s}, [%[key]], #16 ;"
" cmp %w[rounds], #10 ;"
" bmi 0f ;"
" bne 3f ;"
" mov v3.16b, v1.16b ;"
" b 2f ;"
"0: mov v2.16b, v1.16b ;"
- " ld1 {v3.16b}, [%[key]], #16 ;"
+ " ld1 {v3.4s}, [%[key]], #16 ;"
"1: aesd v0.16b, v2.16b ;"
" aesimc v0.16b, v0.16b ;"
- "2: ld1 {v1.16b}, [%[key]], #16 ;"
+ "2: ld1 {v1.4s}, [%[key]], #16 ;"
" aesd v0.16b, v3.16b ;"
" aesimc v0.16b, v0.16b ;"
- "3: ld1 {v2.16b}, [%[key]], #16 ;"
+ "3: ld1 {v2.4s}, [%[key]], #16 ;"
" subs %w[rounds], %w[rounds], #3 ;"
" aesd v0.16b, v1.16b ;"
" aesimc v0.16b, v0.16b ;"
- " ld1 {v3.16b}, [%[key]], #16 ;"
+ " ld1 {v3.4s}, [%[key]], #16 ;"
" bpl 1b ;"
" aesd v0.16b, v2.16b ;"
" eor v0.16b, v0.16b, v3.16b ;"
@@ -159,20 +174,16 @@ int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
key_len != AES_KEYSIZE_256)
return -EINVAL;
- memcpy(ctx->key_enc, in_key, key_len);
ctx->key_length = key_len;
+ for (i = 0; i < kwords; i++)
+ ctx->key_enc[i] = get_unaligned_le32(in_key + i * sizeof(u32));
- kernel_neon_begin_partial(2);
+ kernel_neon_begin();
for (i = 0; i < sizeof(rcon); i++) {
u32 *rki = ctx->key_enc + (i * kwords);
u32 *rko = rki + kwords;
-#ifndef CONFIG_CPU_BIG_ENDIAN
rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0];
-#else
- rko[0] = rol32(aes_sub(rki[kwords - 1]), 8) ^ (rcon[i] << 24) ^
- rki[0];
-#endif
rko[1] = rko[0] ^ rki[1];
rko[2] = rko[1] ^ rki[2];
rko[3] = rko[2] ^ rki[3];
@@ -204,9 +215,9 @@ int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
key_dec[0] = key_enc[j];
for (i = 1, j--; j > 0; i++, j--)
- __asm__("ld1 {v0.16b}, %[in] ;"
+ __asm__("ld1 {v0.4s}, %[in] ;"
"aesimc v1.16b, v0.16b ;"
- "st1 {v1.16b}, %[out] ;"
+ "st1 {v1.4s}, %[out] ;"
: [out] "=Q"(key_dec[i])
: [in] "Q"(key_enc[j])
diff --git a/arch/arm64/crypto/aes-ce.S b/arch/arm64/crypto/aes-ce.S
index b46093d567e5..50330f5c3adc 100644
--- a/arch/arm64/crypto/aes-ce.S
+++ b/arch/arm64/crypto/aes-ce.S
@@ -2,7 +2,7 @@
* linux/arch/arm64/crypto/aes-ce.S - AES cipher for ARMv8 with
* Crypto Extensions
*
- * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*
* 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
@@ -22,11 +22,11 @@
cmp \rounds, #12
blo 2222f /* 128 bits */
beq 1111f /* 192 bits */
- ld1 {v17.16b-v18.16b}, [\rk], #32
-1111: ld1 {v19.16b-v20.16b}, [\rk], #32
-2222: ld1 {v21.16b-v24.16b}, [\rk], #64
- ld1 {v25.16b-v28.16b}, [\rk], #64
- ld1 {v29.16b-v31.16b}, [\rk]
+ ld1 {v17.4s-v18.4s}, [\rk], #32
+1111: ld1 {v19.4s-v20.4s}, [\rk], #32
+2222: ld1 {v21.4s-v24.4s}, [\rk], #64
+ ld1 {v25.4s-v28.4s}, [\rk], #64
+ ld1 {v29.4s-v31.4s}, [\rk]
.endm
/* prepare for encryption with key in rk[] */
diff --git a/arch/arm64/crypto/aes-cipher-core.S b/arch/arm64/crypto/aes-cipher-core.S
new file mode 100644
index 000000000000..3a44eada2347
--- /dev/null
+++ b/arch/arm64/crypto/aes-cipher-core.S
@@ -0,0 +1,173 @@
+/*
+ * Scalar AES core transform
+ *
+ * Copyright (C) 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * 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 <asm/assembler.h>
+#include <asm/cache.h>
+
+ .text
+
+ rk .req x0
+ out .req x1
+ in .req x2
+ rounds .req x3
+ tt .req x2
+
+ .macro __pair1, sz, op, reg0, reg1, in0, in1e, in1d, shift
+ .ifc \op\shift, b0
+ ubfiz \reg0, \in0, #2, #8
+ ubfiz \reg1, \in1e, #2, #8
+ .else
+ ubfx \reg0, \in0, #\shift, #8
+ ubfx \reg1, \in1e, #\shift, #8
+ .endif
+
+ /*
+ * AArch64 cannot do byte size indexed loads from a table containing
+ * 32-bit quantities, i.e., 'ldrb w12, [tt, w12, uxtw #2]' is not a
+ * valid instruction. So perform the shift explicitly first for the
+ * high bytes (the low byte is shifted implicitly by using ubfiz rather
+ * than ubfx above)
+ */
+ .ifnc \op, b
+ ldr \reg0, [tt, \reg0, uxtw #2]
+ ldr \reg1, [tt, \reg1, uxtw #2]
+ .else
+ .if \shift > 0
+ lsl \reg0, \reg0, #2
+ lsl \reg1, \reg1, #2
+ .endif
+ ldrb \reg0, [tt, \reg0, uxtw]
+ ldrb \reg1, [tt, \reg1, uxtw]
+ .endif
+ .endm
+
+ .macro __pair0, sz, op, reg0, reg1, in0, in1e, in1d, shift
+ ubfx \reg0, \in0, #\shift, #8
+ ubfx \reg1, \in1d, #\shift, #8
+ ldr\op \reg0, [tt, \reg0, uxtw #\sz]
+ ldr\op \reg1, [tt, \reg1, uxtw #\sz]
+ .endm
+
+ .macro __hround, out0, out1, in0, in1, in2, in3, t0, t1, enc, sz, op
+ ldp \out0, \out1, [rk], #8
+
+ __pair\enc \sz, \op, w12, w13, \in0, \in1, \in3, 0
+ __pair\enc \sz, \op, w14, w15, \in1, \in2, \in0, 8
+ __pair\enc \sz, \op, w16, w17, \in2, \in3, \in1, 16
+ __pair\enc \sz, \op, \t0, \t1, \in3, \in0, \in2, 24
+
+ eor \out0, \out0, w12
+ eor \out1, \out1, w13
+ eor \out0, \out0, w14, ror #24
+ eor \out1, \out1, w15, ror #24
+ eor \out0, \out0, w16, ror #16
+ eor \out1, \out1, w17, ror #16
+ eor \out0, \out0, \t0, ror #8
+ eor \out1, \out1, \t1, ror #8
+ .endm
+
+ .macro fround, out0, out1, out2, out3, in0, in1, in2, in3, sz=2, op
+ __hround \out0, \out1, \in0, \in1, \in2, \in3, \out2, \out3, 1, \sz, \op
+ __hround \out2, \out3, \in2, \in3, \in0, \in1, \in1, \in2, 1, \sz, \op
+ .endm
+
+ .macro iround, out0, out1, out2, out3, in0, in1, in2, in3, sz=2, op
+ __hround \out0, \out1, \in0, \in3, \in2, \in1, \out2, \out3, 0, \sz, \op
+ __hround \out2, \out3, \in2, \in1, \in0, \in3, \in1, \in0, 0, \sz, \op
+ .endm
+
+ .macro do_crypt, round, ttab, ltab, bsz
+ ldp w4, w5, [in]
+ ldp w6, w7, [in, #8]
+ ldp w8, w9, [rk], #16
+ ldp w10, w11, [rk, #-8]
+
+CPU_BE( rev w4, w4 )
+CPU_BE( rev w5, w5 )
+CPU_BE( rev w6, w6 )
+CPU_BE( rev w7, w7 )
+
+ eor w4, w4, w8
+ eor w5, w5, w9
+ eor w6, w6, w10
+ eor w7, w7, w11
+
+ adr_l tt, \ttab
+
+ tbnz rounds, #1, 1f
+
+0: \round w8, w9, w10, w11, w4, w5, w6, w7
+ \round w4, w5, w6, w7, w8, w9, w10, w11
+
+1: subs rounds, rounds, #4
+ \round w8, w9, w10, w11, w4, w5, w6, w7
+ b.ls 3f
+2: \round w4, w5, w6, w7, w8, w9, w10, w11
+ b 0b
+3: adr_l tt, \ltab
+ \round w4, w5, w6, w7, w8, w9, w10, w11, \bsz, b
+
+CPU_BE( rev w4, w4 )
+CPU_BE( rev w5, w5 )
+CPU_BE( rev w6, w6 )
+CPU_BE( rev w7, w7 )
+
+ stp w4, w5, [out]
+ stp w6, w7, [out, #8]
+ ret
+ .endm
+
+ENTRY(__aes_arm64_encrypt)
+ do_crypt fround, crypto_ft_tab, crypto_ft_tab + 1, 2
+ENDPROC(__aes_arm64_encrypt)
+
+ .align 5
+ENTRY(__aes_arm64_decrypt)
+ do_crypt iround, crypto_it_tab, __aes_arm64_inverse_sbox, 0
+ENDPROC(__aes_arm64_decrypt)
+
+ .section ".rodata", "a"
+ .align L1_CACHE_SHIFT
+ .type __aes_arm64_inverse_sbox, %object
+__aes_arm64_inverse_sbox:
+ .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38
+ .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+ .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
+ .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+ .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
+ .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+ .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
+ .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+ .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
+ .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+ .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
+ .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+ .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
+ .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+ .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
+ .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+ .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
+ .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+ .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
+ .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+ .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
+ .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+ .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
+ .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+ .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
+ .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+ .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
+ .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+ .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
+ .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+ .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
+ .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+ .size __aes_arm64_inverse_sbox, . - __aes_arm64_inverse_sbox
diff --git a/arch/arm64/crypto/aes-cipher-glue.c b/arch/arm64/crypto/aes-cipher-glue.c
new file mode 100644
index 000000000000..0e90b06ebcec
--- /dev/null
+++ b/arch/arm64/crypto/aes-cipher-glue.c
@@ -0,0 +1,69 @@
+/*
+ * Scalar AES core transform
+ *
+ * Copyright (C) 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * 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 <crypto/aes.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+
+asmlinkage void __aes_arm64_encrypt(u32 *rk, u8 *out, const u8 *in, int rounds);
+EXPORT_SYMBOL(__aes_arm64_encrypt);
+
+asmlinkage void __aes_arm64_decrypt(u32 *rk, u8 *out, const u8 *in, int rounds);
+EXPORT_SYMBOL(__aes_arm64_decrypt);
+
+static void aes_arm64_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ int rounds = 6 + ctx->key_length / 4;
+
+ __aes_arm64_encrypt(ctx->key_enc, out, in, rounds);
+}
+
+static void aes_arm64_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ int rounds = 6 + ctx->key_length / 4;
+
+ __aes_arm64_decrypt(ctx->key_dec, out, in, rounds);
+}
+
+static struct crypto_alg aes_alg = {
+ .cra_name = "aes",
+ .cra_driver_name = "aes-arm64",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx),
+ .cra_module = THIS_MODULE,
+
+ .cra_cipher.cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cra_cipher.cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cra_cipher.cia_setkey = crypto_aes_set_key,
+ .cra_cipher.cia_encrypt = aes_arm64_encrypt,
+ .cra_cipher.cia_decrypt = aes_arm64_decrypt
+};
+
+static int __init aes_init(void)
+{
+ return crypto_register_alg(&aes_alg);
+}
+
+static void __exit aes_fini(void)
+{
+ crypto_unregister_alg(&aes_alg);
+}
+
+module_init(aes_init);
+module_exit(aes_fini);
+
+MODULE_DESCRIPTION("Scalar AES cipher for arm64");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("aes");
diff --git a/arch/arm64/crypto/ghash-ce-glue.c b/arch/arm64/crypto/ghash-ce-glue.c
index 833ec1e3f3e9..30221ef56e70 100644
--- a/arch/arm64/crypto/ghash-ce-glue.c
+++ b/arch/arm64/crypto/ghash-ce-glue.c
@@ -1,7 +1,7 @@
/*
* Accelerated GHASH implementation with ARMv8 PMULL instructions.
*
- * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2014 - 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
*
* 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
@@ -9,7 +9,9 @@
*/
#include <asm/neon.h>
+#include <asm/simd.h>
#include <asm/unaligned.h>
+#include <crypto/gf128mul.h>
#include <crypto/internal/hash.h>
#include <linux/cpufeature.h>
#include <linux/crypto.h>
@@ -25,6 +27,7 @@ MODULE_LICENSE("GPL v2");
struct ghash_key {
u64 a;
u64 b;
+ be128 k;
};
struct ghash_desc_ctx {
@@ -44,6 +47,36 @@ static int ghash_init(struct shash_desc *desc)
return 0;
}
+static void ghash_do_update(int blocks, u64 dg[], const char *src,
+ struct ghash_key *key, const char *head)
+{
+ if (likely(may_use_simd())) {
+ kernel_neon_begin();
+ pmull_ghash_update(blocks, dg, src, key, head);
+ kernel_neon_end();
+ } else {
+ be128 dst = { cpu_to_be64(dg[1]), cpu_to_be64(dg[0]) };
+
+ do {
+ const u8 *in = src;
+
+ if (head) {
+ in = head;
+ blocks++;
+ head = NULL;
+ } else {
+ src += GHASH_BLOCK_SIZE;
+ }
+
+ crypto_xor((u8 *)&dst, in, GHASH_BLOCK_SIZE);
+ gf128mul_lle(&dst, &key->k);
+ } while (--blocks);
+
+ dg[0] = be64_to_cpu(dst.b);
+ dg[1] = be64_to_cpu(dst.a);
+ }
+}
+
static int ghash_update(struct shash_desc *desc, const u8 *src,
unsigned int len)
{
@@ -67,10 +100,9 @@ static int ghash_update(struct shash_desc *desc, const u8 *src,
blocks = len / GHASH_BLOCK_SIZE;
len %= GHASH_BLOCK_SIZE;
- kernel_neon_begin_partial(8);
- pmull_ghash_update(blocks, ctx->digest, src, key,
- partial ? ctx->buf : NULL);
- kernel_neon_end();
+ ghash_do_update(blocks, ctx->digest, src, key,
+ partial ? ctx->buf : NULL);
+
src += blocks * GHASH_BLOCK_SIZE;
partial = 0;
}
@@ -89,9 +121,7 @@ static int ghash_final(struct shash_desc *desc, u8 *dst)
memset(ctx->buf + partial, 0, GHASH_BLOCK_SIZE - partial);
- kernel_neon_begin_partial(8);
- pmull_ghash_update(1, ctx->digest, ctx->buf, key, NULL);
- kernel_neon_end();
+ ghash_do_update(1, ctx->digest, ctx->buf, key, NULL);
}
put_unaligned_be64(ctx->digest[1], dst);
put_unaligned_be64(ctx->digest[0], dst + 8);
@@ -111,6 +141,9 @@ static int ghash_setkey(struct crypto_shash *tfm,
return -EINVAL;
}
+ /* needed for the fallback */
+ memcpy(&key->k, inkey, GHASH_BLOCK_SIZE);
+
/* perform multiplication by 'x' in GF(2^128) */
b = get_unaligned_be64(inkey);
a = get_unaligned_be64(inkey + 8);
diff --git a/arch/arm64/crypto/sha1-ce-glue.c b/arch/arm64/crypto/sha1-ce-glue.c
index 3431bb514fd4..fb7a9caf51c8 100644
--- a/arch/arm64/crypto/sha1-ce-glue.c
+++ b/arch/arm64/crypto/sha1-ce-glue.c
@@ -1,7 +1,7 @@
/*
* sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions
*
- * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2014 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*
* 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
@@ -9,6 +9,7 @@
*/
#include <asm/neon.h>
+#include <asm/simd.h>
#include <asm/unaligned.h>
#include <crypto/internal/hash.h>
#include <crypto/sha.h>
@@ -45,8 +46,11 @@ static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
{
struct sha1_ce_state *sctx = shash_desc_ctx(desc);
+ if (!may_use_simd())
+ return crypto_sha1_update(desc, data, len);
+
sctx->finalize = 0;
- kernel_neon_begin_partial(16);
+ kernel_neon_begin();
sha1_base_do_update(desc, data, len,
(sha1_block_fn *)sha1_ce_transform);
kernel_neon_end();
@@ -60,13 +64,16 @@ static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
struct sha1_ce_state *sctx = shash_desc_ctx(desc);
bool finalize = !sctx->sst.count && !(len % SHA1_BLOCK_SIZE) && len;
+ if (!may_use_simd())
+ return crypto_sha1_finup(desc, data, len, out);
+
/*
* Allow the asm code to perform the finalization if there is no
* partial data and the input is a round multiple of the block size.
*/
sctx->finalize = finalize;
- kernel_neon_begin_partial(16);
+ kernel_neon_begin();
sha1_base_do_update(desc, data, len,
(sha1_block_fn *)sha1_ce_transform);
if (!finalize)
@@ -79,8 +86,11 @@ static int sha1_ce_final(struct shash_desc *desc, u8 *out)
{
struct sha1_ce_state *sctx = shash_desc_ctx(desc);
+ if (!may_use_simd())
+ return crypto_sha1_finup(desc, NULL, 0, out);
+
sctx->finalize = 0;
- kernel_neon_begin_partial(16);
+ kernel_neon_begin();
sha1_base_do_finalize(desc, (sha1_block_fn *)sha1_ce_transform);
kernel_neon_end();
return sha1_base_finish(desc, out);
diff --git a/arch/arm64/crypto/sha2-ce-glue.c b/arch/arm64/crypto/sha2-ce-glue.c
index 42d96ddd35c3..9141184d89e4 100644
--- a/arch/arm64/crypto/sha2-ce-glue.c
+++ b/arch/arm64/crypto/sha2-ce-glue.c
@@ -1,7 +1,7 @@
/*
* sha2-ce-glue.c - SHA-224/SHA-256 using ARMv8 Crypto Extensions
*
- * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (C) 2014 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
*
* 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
@@ -9,6 +9,7 @@
*/
#include <asm/neon.h>
+#include <asm/simd.h>
#include <asm/unaligned.h>
#include <crypto/internal/hash.h>
#include <crypto/sha.h>
@@ -42,13 +43,19 @@ const u32 sha256_ce_offsetof_count = offsetof(struct sha256_ce_state,
const u32 sha256_ce_offsetof_finalize = offsetof(struct sha256_ce_state,
finalize);
+asmlinkage void sha256_block_data_order(u32 *digest, u8 const *src, int blocks);
+
static int sha256_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
+ if (!may_use_simd())
+ return sha256_base_do_update(desc, data, len,
+ (sha256_block_fn *)sha256_block_data_order);
+
sctx->finalize = 0;
- kernel_neon_begin_partial(28);
+ kernel_neon_begin();
sha256_base_do_update(desc, data, len,
(sha256_block_fn *)sha2_ce_transform);
kernel_neon_end();
@@ -62,13 +69,22 @@ static int sha256_ce_finup(struct shash_desc *desc, const u8 *data,
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
bool finalize = !sctx->sst.count && !(len % SHA256_BLOCK_SIZE) && len;
+ if (!may_use_simd()) {
+ if (len)
+ sha256_base_do_update(desc, data, len,
+ (sha256_block_fn *)sha256_block_data_order);
+ sha256_base_do_finalize(desc,
+ (sha256_block_fn *)sha256_block_data_order);
+ return sha256_base_finish(desc, out);
+ }
+
/*
* Allow the asm code to perform the finalization if there is no
* partial data and the input is a round multiple of the block size.
*/
sctx->finalize = finalize;
- kernel_neon_begin_partial(28);
+ kernel_neon_begin();
sha256_base_do_update(desc, data, len,
(sha256_block_fn *)sha2_ce_transform);
if (!finalize)
@@ -82,8 +98,14 @@ static int sha256_ce_final(struct shash_desc *desc, u8 *out)
{
struct sha256_ce_state *sctx = shash_desc_ctx(desc);
+ if (!may_use_simd()) {
+ sha256_base_do_finalize(desc,
+ (sha256_block_fn *)sha256_block_data_order);
+ return sha256_base_finish(desc, out);
+ }
+
sctx->finalize = 0;
- kernel_neon_begin_partial(28);
+ kernel_neon_begin();
sha256_base_do_finalize(desc, (sha256_block_fn *)sha2_ce_transform);
kernel_neon_end();
return sha256_base_finish(desc, out);
diff --git a/arch/arm64/crypto/sha256-glue.c b/arch/arm64/crypto/sha256-glue.c
new file mode 100644
index 000000000000..2e6a323d1b93
--- /dev/null
+++ b/arch/arm64/crypto/sha256-glue.c
@@ -0,0 +1,196 @@
+/*
+ * Linux/arm64 port of the OpenSSL SHA256 implementation for AArch64
+ *
+ * Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+#include <crypto/sha256_base.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64");
+MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha224");
+MODULE_ALIAS_CRYPTO("sha256");
+
+asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
+ unsigned int num_blks);
+EXPORT_SYMBOL(sha256_block_data_order);
+
+asmlinkage void sha256_block_neon(u32 *digest, const void *data,
+ unsigned int num_blks);
+
+static int crypto_sha256_arm64_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ return sha256_base_do_update(desc, data, len,
+ (sha256_block_fn *)sha256_block_data_order);
+}
+
+static int crypto_sha256_arm64_finup(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ if (len)
+ sha256_base_do_update(desc, data, len,
+ (sha256_block_fn *)sha256_block_data_order);
+ sha256_base_do_finalize(desc,
+ (sha256_block_fn *)sha256_block_data_order);
+
+ return sha256_base_finish(desc, out);
+}
+
+static int crypto_sha256_arm64_final(struct shash_desc *desc, u8 *out)
+{
+ return crypto_sha256_arm64_finup(desc, NULL, 0, out);
+}
+
+static struct shash_alg algs[] = { {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .init = sha256_base_init,
+ .update = crypto_sha256_arm64_update,
+ .final = crypto_sha256_arm64_final,
+ .finup = crypto_sha256_arm64_finup,
+ .descsize = sizeof(struct sha256_state),
+ .base.cra_name = "sha256",
+ .base.cra_driver_name = "sha256-arm64",
+ .base.cra_priority = 125,
+ .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .base.cra_blocksize = SHA256_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+}, {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .init = sha224_base_init,
+ .update = crypto_sha256_arm64_update,
+ .final = crypto_sha256_arm64_final,
+ .finup = crypto_sha256_arm64_finup,
+ .descsize = sizeof(struct sha256_state),
+ .base.cra_name = "sha224",
+ .base.cra_driver_name = "sha224-arm64",
+ .base.cra_priority = 125,
+ .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .base.cra_blocksize = SHA224_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+} };
+
+static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha256_state *sctx = shash_desc_ctx(desc);
+
+ if (!may_use_simd())
+ return sha256_base_do_update(desc, data, len,
+ (sha256_block_fn *)sha256_block_data_order);
+
+ while (len > 0) {
+ unsigned int chunk = len;
+
+ /*
+ * Don't hog the CPU for the entire time it takes to process all
+ * input when running on a preemptible kernel, but process the
+ * data block by block instead.
+ */
+ if (IS_ENABLED(CONFIG_PREEMPT) &&
+ chunk + sctx->count % SHA256_BLOCK_SIZE > SHA256_BLOCK_SIZE)
+ chunk = SHA256_BLOCK_SIZE -
+ sctx->count % SHA256_BLOCK_SIZE;
+
+ kernel_neon_begin();
+ sha256_base_do_update(desc, data, chunk,
+ (sha256_block_fn *)sha256_block_neon);
+ kernel_neon_end();
+ data += chunk;
+ len -= chunk;
+ }
+ return 0;
+}
+
+static int sha256_finup_neon(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ if (!may_use_simd()) {
+ if (len)
+ sha256_base_do_update(desc, data, len,
+ (sha256_block_fn *)sha256_block_data_order);
+ sha256_base_do_finalize(desc,
+ (sha256_block_fn *)sha256_block_data_order);
+ } else {
+ if (len)
+ sha256_update_neon(desc, data, len);
+ kernel_neon_begin();
+ sha256_base_do_finalize(desc,
+ (sha256_block_fn *)sha256_block_neon);
+ kernel_neon_end();
+ }
+ return sha256_base_finish(desc, out);
+}
+
+static int sha256_final_neon(struct shash_desc *desc, u8 *out)
+{
+ return sha256_finup_neon(desc, NULL, 0, out);
+}
+
+static struct shash_alg neon_algs[] = { {
+ .digestsize = SHA256_DIGEST_SIZE,
+ .init = sha256_base_init,
+ .update = sha256_update_neon,
+ .final = sha256_final_neon,
+ .finup = sha256_finup_neon,
+ .descsize = sizeof(struct sha256_state),
+ .base.cra_name = "sha256",
+ .base.cra_driver_name = "sha256-arm64-neon",
+ .base.cra_priority = 150,
+ .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .base.cra_blocksize = SHA256_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+}, {
+ .digestsize = SHA224_DIGEST_SIZE,
+ .init = sha224_base_init,
+ .update = sha256_update_neon,
+ .final = sha256_final_neon,
+ .finup = sha256_finup_neon,
+ .descsize = sizeof(struct sha256_state),
+ .base.cra_name = "sha224",
+ .base.cra_driver_name = "sha224-arm64-neon",
+ .base.cra_priority = 150,
+ .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .base.cra_blocksize = SHA224_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+} };
+
+static int __init sha256_mod_init(void)
+{
+ int ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
+ if (ret)
+ return ret;
+
+ if (elf_hwcap & HWCAP_ASIMD) {
+ ret = crypto_register_shashes(neon_algs, ARRAY_SIZE(neon_algs));
+ if (ret)
+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+ }
+ return ret;
+}
+
+static void __exit sha256_mod_fini(void)
+{
+ if (elf_hwcap & HWCAP_ASIMD)
+ crypto_unregister_shashes(neon_algs, ARRAY_SIZE(neon_algs));
+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+
+module_init(sha256_mod_init);
+module_exit(sha256_mod_fini);
diff --git a/arch/arm64/crypto/sha512-armv8.pl b/arch/arm64/crypto/sha512-armv8.pl
new file mode 100644
index 000000000000..2d8655d5b1af
--- /dev/null
+++ b/arch/arm64/crypto/sha512-armv8.pl
@@ -0,0 +1,786 @@
+#! /usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0
+
+# This code is taken from the OpenSSL project but the author (Andy Polyakov)
+# has relicensed it under the GPLv2. Therefore 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.
+#
+# The original headers, including the original license headers, are
+# included below for completeness.
+
+# Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# SHA256/512 for ARMv8.
+#
+# Performance in cycles per processed byte and improvement coefficient
+# over code generated with "default" compiler:
+#
+# SHA256-hw SHA256(*) SHA512
+# Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**))
+# Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***))
+# Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***))
+# Denver 2.01 10.5 (+26%) 6.70 (+8%)
+# X-Gene 20.0 (+100%) 12.8 (+300%(***))
+# Mongoose 2.36 13.0 (+50%) 8.36 (+33%)
+#
+# (*) Software SHA256 results are of lesser relevance, presented
+# mostly for informational purposes.
+# (**) The result is a trade-off: it's possible to improve it by
+# 10% (or by 1 cycle per round), but at the cost of 20% loss
+# on Cortex-A53 (or by 4 cycles per round).
+# (***) Super-impressive coefficients over gcc-generated code are
+# indication of some compiler "pathology", most notably code
+# generated with -mgeneral-regs-only is significanty faster
+# and the gap is only 40-90%.
+#
+# October 2016.
+#
+# Originally it was reckoned that it makes no sense to implement NEON
+# version of SHA256 for 64-bit processors. This is because performance
+# improvement on most wide-spread Cortex-A5x processors was observed
+# to be marginal, same on Cortex-A53 and ~10% on A57. But then it was
+# observed that 32-bit NEON SHA256 performs significantly better than
+# 64-bit scalar version on *some* of the more recent processors. As
+# result 64-bit NEON version of SHA256 was added to provide best
+# all-round performance. For example it executes ~30% faster on X-Gene
+# and Mongoose. [For reference, NEON version of SHA512 is bound to
+# deliver much less improvement, likely *negative* on Cortex-A5x.
+# Which is why NEON support is limited to SHA256.]
+
+$output=pop;
+$flavour=pop;
+
+if ($flavour && $flavour ne "void") {
+ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+ ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+ ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+ die "can't locate arm-xlate.pl";
+
+ open OUT,"| \"$^X\" $xlate $flavour $output";
+ *STDOUT=*OUT;
+} else {
+ open STDOUT,">$output";
+}
+
+if ($output =~ /512/) {
+ $BITS=512;
+ $SZ=8;
+ @Sigma0=(28,34,39);
+ @Sigma1=(14,18,41);
+ @sigma0=(1, 8, 7);
+ @sigma1=(19,61, 6);
+ $rounds=80;
+ $reg_t="x";
+} else {
+ $BITS=256;
+ $SZ=4;
+ @Sigma0=( 2,13,22);
+ @Sigma1=( 6,11,25);
+ @sigma0=( 7,18, 3);
+ @sigma1=(17,19,10);
+ $rounds=64;
+ $reg_t="w";
+}
+
+$func="sha${BITS}_block_data_order";
+
+($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30));
+
+@X=map("$reg_t$_",(3..15,0..2));
+@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("$reg_t$_",(20..27));
+($t0,$t1,$t2,$t3)=map("$reg_t$_",(16,17,19,28));
+
+sub BODY_00_xx {
+my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
+my $j=($i+1)&15;
+my ($T0,$T1,$T2)=(@X[($i-8)&15],@X[($i-9)&15],@X[($i-10)&15]);
+ $T0=@X[$i+3] if ($i<11);
+
+$code.=<<___ if ($i<16);
+#ifndef __AARCH64EB__
+ rev @X[$i],@X[$i] // $i
+#endif
+___
+$code.=<<___ if ($i<13 && ($i&1));
+ ldp @X[$i+1],@X[$i+2],[$inp],#2*$SZ
+___
+$code.=<<___ if ($i==13);
+ ldp @X[14],@X[15],[$inp]
+___
+$code.=<<___ if ($i>=14);
+ ldr @X[($i-11)&15],[sp,#`$SZ*(($i-11)%4)`]
+___
+$code.=<<___ if ($i>0 && $i<16);
+ add $a,$a,$t1 // h+=Sigma0(a)
+___
+$code.=<<___ if ($i>=11);
+ str @X[($i-8)&15],[sp,#`$SZ*(($i-8)%4)`]
+___
+# While ARMv8 specifies merged rotate-n-logical operation such as
+# 'eor x,y,z,ror#n', it was found to negatively affect performance
+# on Apple A7. The reason seems to be that it requires even 'y' to
+# be available earlier. This means that such merged instruction is
+# not necessarily best choice on critical path... On the other hand
+# Cortex-A5x handles merged instructions much better than disjoint
+# rotate and logical... See (**) footnote above.
+$code.=<<___ if ($i<15);
+ ror $t0,$e,#$Sigma1[0]
+ add $h,$h,$t2 // h+=K[i]
+ eor $T0,$e,$e,ror#`$Sigma1[2]-$Sigma1[1]`
+ and $t1,$f,$e
+ bic $t2,$g,$e
+ add $h,$h,@X[$i&15] // h+=X[i]
+ orr $t1,$t1,$t2 // Ch(e,f,g)
+ eor $t2,$a,$b // a^b, b^c in next round
+ eor $t0,$t0,$T0,ror#$Sigma1[1] // Sigma1(e)
+ ror $T0,$a,#$Sigma0[0]
+ add $h,$h,$t1 // h+=Ch(e,f,g)
+ eor $t1,$a,$a,ror#`$Sigma0[2]-$Sigma0[1]`
+ add $h,$h,$t0 // h+=Sigma1(e)
+ and $t3,$t3,$t2 // (b^c)&=(a^b)
+ add $d,$d,$h // d+=h
+ eor $t3,$t3,$b // Maj(a,b,c)
+ eor $t1,$T0,$t1,ror#$Sigma0[1] // Sigma0(a)
+ add $h,$h,$t3 // h+=Maj(a,b,c)
+ ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round
+ //add $h,$h,$t1 // h+=Sigma0(a)
+___
+$code.=<<___ if ($i>=15);
+ ror $t0,$e,#$Sigma1[0]
+ add $h,$h,$t2 // h+=K[i]
+ ror $T1,@X[($j+1)&15],#$sigma0[0]
+ and $t1,$f,$e
+ ror $T2,@X[($j+14)&15],#$sigma1[0]
+ bic $t2,$g,$e
+ ror $T0,$a,#$Sigma0[0]
+ add $h,$h,@X[$i&15] // h+=X[i]
+ eor $t0,$t0,$e,ror#$Sigma1[1]
+ eor $T1,$T1,@X[($j+1)&15],ror#$sigma0[1]
+ orr $t1,$t1,$t2 // Ch(e,f,g)
+ eor $t2,$a,$b // a^b, b^c in next round
+ eor $t0,$t0,$e,ror#$Sigma1[2] // Sigma1(e)
+ eor $T0,$T0,$a,ror#$Sigma0[1]
+ add $h,$h,$t1 // h+=Ch(e,f,g)
+ and $t3,$t3,$t2 // (b^c)&=(a^b)
+ eor $T2,$T2,@X[($j+14)&15],ror#$sigma1[1]
+ eor $T1,$T1,@X[($j+1)&15],lsr#$sigma0[2] // sigma0(X[i+1])
+ add $h,$h,$t0 // h+=Sigma1(e)
+ eor $t3,$t3,$b // Maj(a,b,c)
+ eor $t1,$T0,$a,ror#$Sigma0[2] // Sigma0(a)
+ eor $T2,$T2,@X[($j+14)&15],lsr#$sigma1[2] // sigma1(X[i+14])
+ add @X[$j],@X[$j],@X[($j+9)&15]
+ add $d,$d,$h // d+=h
+ add $h,$h,$t3 // h+=Maj(a,b,c)
+ ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round
+ add @X[$j],@X[$j],$T1
+ add $h,$h,$t1 // h+=Sigma0(a)
+ add @X[$j],@X[$j],$T2
+___
+ ($t2,$t3)=($t3,$t2);
+}
+
+$code.=<<___;
+#ifndef __KERNEL__
+# include "arm_arch.h"
+#endif
+
+.text
+
+.extern OPENSSL_armcap_P
+.globl $func
+.type $func,%function
+.align 6
+$func:
+___
+$code.=<<___ if ($SZ==4);
+#ifndef __KERNEL__
+# ifdef __ILP32__
+ ldrsw x16,.LOPENSSL_armcap_P
+# else
+ ldr x16,.LOPENSSL_armcap_P
+# endif
+ adr x17,.LOPENSSL_armcap_P
+ add x16,x16,x17
+ ldr w16,[x16]
+ tst w16,#ARMV8_SHA256
+ b.ne .Lv8_entry
+ tst w16,#ARMV7_NEON
+ b.ne .Lneon_entry
+#endif
+___
+$code.=<<___;
+ stp x29,x30,[sp,#-128]!
+ add x29,sp,#0
+
+ stp x19,x20,[sp,#16]
+ stp x21,x22,[sp,#32]
+ stp x23,x24,[sp,#48]
+ stp x25,x26,[sp,#64]
+ stp x27,x28,[sp,#80]
+ sub sp,sp,#4*$SZ
+
+ ldp $A,$B,[$ctx] // load context
+ ldp $C,$D,[$ctx,#2*$SZ]
+ ldp $E,$F,[$ctx,#4*$SZ]
+ add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input
+ ldp $G,$H,[$ctx,#6*$SZ]
+ adr $Ktbl,.LK$BITS
+ stp $ctx,$num,[x29,#96]
+
+.Loop:
+ ldp @X[0],@X[1],[$inp],#2*$SZ
+ ldr $t2,[$Ktbl],#$SZ // *K++
+ eor $t3,$B,$C // magic seed
+ str $inp,[x29,#112]
+___
+for ($i=0;$i<16;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); }
+$code.=".Loop_16_xx:\n";
+for (;$i<32;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+ cbnz $t2,.Loop_16_xx
+
+ ldp $ctx,$num,[x29,#96]
+ ldr $inp,[x29,#112]
+ sub $Ktbl,$Ktbl,#`$SZ*($rounds+1)` // rewind
+
+ ldp @X[0],@X[1],[$ctx]
+ ldp @X[2],@X[3],[$ctx,#2*$SZ]
+ add $inp,$inp,#14*$SZ // advance input pointer
+ ldp @X[4],@X[5],[$ctx,#4*$SZ]
+ add $A,$A,@X[0]
+ ldp @X[6],@X[7],[$ctx,#6*$SZ]
+ add $B,$B,@X[1]
+ add $C,$C,@X[2]
+ add $D,$D,@X[3]
+ stp $A,$B,[$ctx]
+ add $E,$E,@X[4]
+ add $F,$F,@X[5]
+ stp $C,$D,[$ctx,#2*$SZ]
+ add $G,$G,@X[6]
+ add $H,$H,@X[7]
+ cmp $inp,$num
+ stp $E,$F,[$ctx,#4*$SZ]
+ stp $G,$H,[$ctx,#6*$SZ]
+ b.ne .Loop
+
+ ldp x19,x20,[x29,#16]
+ add sp,sp,#4*$SZ
+ ldp x21,x22,[x29,#32]
+ ldp x23,x24,[x29,#48]
+ ldp x25,x26,[x29,#64]
+ ldp x27,x28,[x29,#80]
+ ldp x29,x30,[sp],#128
+ ret
+.size $func,.-$func
+
+.align 6
+.type .LK$BITS,%object
+.LK$BITS:
+___
+$code.=<<___ if ($SZ==8);
+ .quad 0x428a2f98d728ae22,0x7137449123ef65cd
+ .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+ .quad 0x3956c25bf348b538,0x59f111f1b605d019
+ .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118
+ .quad 0xd807aa98a3030242,0x12835b0145706fbe
+ .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+ .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1
+ .quad 0x9bdc06a725c71235,0xc19bf174cf692694
+ .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3
+ .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+ .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483
+ .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+ .quad 0x983e5152ee66dfab,0xa831c66d2db43210
+ .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4
+ .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725
+ .quad 0x06ca6351e003826f,0x142929670a0e6e70
+ .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926
+ .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+ .quad 0x650a73548baf63de,0x766a0abb3c77b2a8
+ .quad 0x81c2c92e47edaee6,0x92722c851482353b
+ .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001
+ .quad 0xc24b8b70d0f89791,0xc76c51a30654be30
+ .quad 0xd192e819d6ef5218,0xd69906245565a910
+ .quad 0xf40e35855771202a,0x106aa07032bbd1b8
+ .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53
+ .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+ .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+ .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+ .quad 0x748f82ee5defb2fc,0x78a5636f43172f60
+ .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec
+ .quad 0x90befffa23631e28,0xa4506cebde82bde9
+ .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b
+ .quad 0xca273eceea26619c,0xd186b8c721c0c207
+ .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+ .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6
+ .quad 0x113f9804bef90dae,0x1b710b35131c471b
+ .quad 0x28db77f523047d84,0x32caab7b40c72493
+ .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+ .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+ .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817
+ .quad 0 // terminator
+___
+$code.=<<___ if ($SZ==4);
+ .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+ .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+ .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+ .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+ .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+ .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+ .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+ .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+ .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+ .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+ .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+ .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+ .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+ .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+ .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+ .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+ .long 0 //terminator
+___
+$code.=<<___;
+.size .LK$BITS,.-.LK$BITS
+#ifndef __KERNEL__
+.align 3
+.LOPENSSL_armcap_P:
+# ifdef __ILP32__
+ .long OPENSSL_armcap_P-.
+# else
+ .quad OPENSSL_armcap_P-.
+# endif
+#endif
+.asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align 2
+___
+
+if ($SZ==4) {
+my $Ktbl="x3";
+
+my ($ABCD,$EFGH,$abcd)=map("v$_.16b",(0..2));
+my @MSG=map("v$_.16b",(4..7));
+my ($W0,$W1)=("v16.4s","v17.4s");
+my ($ABCD_SAVE,$EFGH_SAVE)=("v18.16b","v19.16b");
+
+$code.=<<___;
+#ifndef __KERNEL__
+.type sha256_block_armv8,%function
+.align 6
+sha256_block_armv8:
+.Lv8_entry:
+ stp x29,x30,[sp,#-16]!
+ add x29,sp,#0
+
+ ld1.32 {$ABCD,$EFGH},[$ctx]
+ adr $Ktbl,.LK256
+
+.Loop_hw:
+ ld1 {@MSG[0]-@MSG[3]},[$inp],#64
+ sub $num,$num,#1
+ ld1.32 {$W0},[$Ktbl],#16
+ rev32 @MSG[0],@MSG[0]
+ rev32 @MSG[1],@MSG[1]
+ rev32 @MSG[2],@MSG[2]
+ rev32 @MSG[3],@MSG[3]
+ orr $ABCD_SAVE,$ABCD,$ABCD // offload
+ orr $EFGH_SAVE,$EFGH,$EFGH
+___
+for($i=0;$i<12;$i++) {
+$code.=<<___;
+ ld1.32 {$W1},[$Ktbl],#16
+ add.i32 $W0,$W0,@MSG[0]
+ sha256su0 @MSG[0],@MSG[1]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+ sha256su1 @MSG[0],@MSG[2],@MSG[3]
+___
+ ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG));
+}
+$code.=<<___;
+ ld1.32 {$W1},[$Ktbl],#16
+ add.i32 $W0,$W0,@MSG[0]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+
+ ld1.32 {$W0},[$Ktbl],#16
+ add.i32 $W1,$W1,@MSG[1]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W1
+ sha256h2 $EFGH,$abcd,$W1
+
+ ld1.32 {$W1},[$Ktbl]
+ add.i32 $W0,$W0,@MSG[2]
+ sub $Ktbl,$Ktbl,#$rounds*$SZ-16 // rewind
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W0
+ sha256h2 $EFGH,$abcd,$W0
+
+ add.i32 $W1,$W1,@MSG[3]
+ orr $abcd,$ABCD,$ABCD
+ sha256h $ABCD,$EFGH,$W1
+ sha256h2 $EFGH,$abcd,$W1
+
+ add.i32 $ABCD,$ABCD,$ABCD_SAVE
+ add.i32 $EFGH,$EFGH,$EFGH_SAVE
+
+ cbnz $num,.Loop_hw
+
+ st1.32 {$ABCD,$EFGH},[$ctx]
+
+ ldr x29,[sp],#16
+ ret
+.size sha256_block_armv8,.-sha256_block_armv8
+#endif
+___
+}
+
+if ($SZ==4) { ######################################### NEON stuff #
+# You'll surely note a lot of similarities with sha256-armv4 module,
+# and of course it's not a coincidence. sha256-armv4 was used as
+# initial template, but was adapted for ARMv8 instruction set and
+# extensively re-tuned for all-round performance.
+
+my @V = ($A,$B,$C,$D,$E,$F,$G,$H) = map("w$_",(3..10));
+my ($t0,$t1,$t2,$t3,$t4) = map("w$_",(11..15));
+my $Ktbl="x16";
+my $Xfer="x17";
+my @X = map("q$_",(0..3));
+my ($T0,$T1,$T2,$T3,$T4,$T5,$T6,$T7) = map("q$_",(4..7,16..19));
+my $j=0;
+
+sub AUTOLOAD() # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+ my $arg = pop;
+ $arg = "#$arg" if ($arg*1 eq $arg);
+ $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+sub Dscalar { shift =~ m|[qv]([0-9]+)|?"d$1":""; }
+sub Dlo { shift =~ m|[qv]([0-9]+)|?"v$1.d[0]":""; }
+sub Dhi { shift =~ m|[qv]([0-9]+)|?"v$1.d[1]":""; }
+
+sub Xupdate()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e,$f,$g,$h);
+
+ &ext_8 ($T0,@X[0],@X[1],4); # X[1..4]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ext_8 ($T3,@X[2],@X[3],4); # X[9..12]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &mov (&Dscalar($T7),&Dhi(@X[3])); # X[14..15]
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ushr_32 ($T2,$T0,$sigma0[0]);
+ eval(shift(@insns));
+ &ushr_32 ($T1,$T0,$sigma0[2]);
+ eval(shift(@insns));
+ &add_32 (@X[0],@X[0],$T3); # X[0..3] += X[9..12]
+ eval(shift(@insns));
+ &sli_32 ($T2,$T0,32-$sigma0[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ushr_32 ($T3,$T0,$sigma0[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &eor_8 ($T1,$T1,$T2);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &sli_32 ($T3,$T0,32-$sigma0[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ushr_32 ($T4,$T7,$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &eor_8 ($T1,$T1,$T3); # sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &sli_32 ($T4,$T7,32-$sigma1[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ushr_32 ($T5,$T7,$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ushr_32 ($T3,$T7,$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &add_32 (@X[0],@X[0],$T1); # X[0..3] += sigma0(X[1..4])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &sli_u32 ($T3,$T7,32-$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &eor_8 ($T5,$T5,$T4);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &eor_8 ($T5,$T5,$T3); # sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &add_32 (@X[0],@X[0],$T5); # X[0..1] += sigma1(X[14..15])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ushr_32 ($T6,@X[0],$sigma1[0]);
+ eval(shift(@insns));
+ &ushr_32 ($T7,@X[0],$sigma1[2]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &sli_32 ($T6,@X[0],32-$sigma1[0]);
+ eval(shift(@insns));
+ &ushr_32 ($T5,@X[0],$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &eor_8 ($T7,$T7,$T6);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &sli_32 ($T5,@X[0],32-$sigma1[1]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ld1_32 ("{$T0}","[$Ktbl], #16");
+ eval(shift(@insns));
+ &eor_8 ($T7,$T7,$T5); # sigma1(X[16..17])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &eor_8 ($T5,$T5,$T5);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &mov (&Dhi($T5), &Dlo($T7));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &add_32 (@X[0],@X[0],$T5); # X[2..3] += sigma1(X[16..17])
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &add_32 ($T0,$T0,@X[0]);
+ while($#insns>=1) { eval(shift(@insns)); }
+ &st1_32 ("{$T0}","[$Xfer], #16");
+ eval(shift(@insns));
+
+ push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub Xpreload()
+{ use integer;
+ my $body = shift;
+ my @insns = (&$body,&$body,&$body,&$body);
+ my ($a,$b,$c,$d,$e,$f,$g,$h);
+
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ld1_8 ("{@X[0]}","[$inp],#16");
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &ld1_32 ("{$T0}","[$Ktbl],#16");
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &rev32 (@X[0],@X[0]);
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ eval(shift(@insns));
+ &add_32 ($T0,$T0,@X[0]);
+ foreach (@insns) { eval; } # remaining instructions
+ &st1_32 ("{$T0}","[$Xfer], #16");
+
+ push(@X,shift(@X)); # "rotate" X[]
+}
+
+sub body_00_15 () {
+ (
+ '($a,$b,$c,$d,$e,$f,$g,$h)=@V;'.
+ '&add ($h,$h,$t1)', # h+=X[i]+K[i]
+ '&add ($a,$a,$t4);'. # h+=Sigma0(a) from the past
+ '&and ($t1,$f,$e)',
+ '&bic ($t4,$g,$e)',
+ '&eor ($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))',
+ '&add ($a,$a,$t2)', # h+=Maj(a,b,c) from the past
+ '&orr ($t1,$t1,$t4)', # Ch(e,f,g)
+ '&eor ($t0,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))', # Sigma1(e)
+ '&eor ($t4,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))',
+ '&add ($h,$h,$t1)', # h+=Ch(e,f,g)
+ '&ror ($t0,$t0,"#$Sigma1[0]")',
+ '&eor ($t2,$a,$b)', # a^b, b^c in next round
+ '&eor ($t4,$t4,$a,"ror#".($Sigma0[2]-$Sigma0[0]))', # Sigma0(a)
+ '&add ($h,$h,$t0)', # h+=Sigma1(e)
+ '&ldr ($t1,sprintf "[sp,#%d]",4*(($j+1)&15)) if (($j&15)!=15);'.
+ '&ldr ($t1,"[$Ktbl]") if ($j==15);'.
+ '&and ($t3,$t3,$t2)', # (b^c)&=(a^b)
+ '&ror ($t4,$t4,"#$Sigma0[0]")',
+ '&add ($d,$d,$h)', # d+=h
+ '&eor ($t3,$t3,$b)', # Maj(a,b,c)
+ '$j++; unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);'
+ )
+}
+
+$code.=<<___;
+#ifdef __KERNEL__
+.globl sha256_block_neon
+#endif
+.type sha256_block_neon,%function
+.align 4
+sha256_block_neon:
+.Lneon_entry:
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ sub sp,sp,#16*4
+
+ adr $Ktbl,.LK256
+ add $num,$inp,$num,lsl#6 // len to point at the end of inp
+
+ ld1.8 {@X[0]},[$inp], #16
+ ld1.8 {@X[1]},[$inp], #16
+ ld1.8 {@X[2]},[$inp], #16
+ ld1.8 {@X[3]},[$inp], #16
+ ld1.32 {$T0},[$Ktbl], #16
+ ld1.32 {$T1},[$Ktbl], #16
+ ld1.32 {$T2},[$Ktbl], #16
+ ld1.32 {$T3},[$Ktbl], #16
+ rev32 @X[0],@X[0] // yes, even on
+ rev32 @X[1],@X[1] // big-endian
+ rev32 @X[2],@X[2]
+ rev32 @X[3],@X[3]
+ mov $Xfer,sp
+ add.32 $T0,$T0,@X[0]
+ add.32 $T1,$T1,@X[1]
+ add.32 $T2,$T2,@X[2]
+ st1.32 {$T0-$T1},[$Xfer], #32
+ add.32 $T3,$T3,@X[3]
+ st1.32 {$T2-$T3},[$Xfer]
+ sub $Xfer,$Xfer,#32
+
+ ldp $A,$B,[$ctx]
+ ldp $C,$D,[$ctx,#8]
+ ldp $E,$F,[$ctx,#16]
+ ldp $G,$H,[$ctx,#24]
+ ldr $t1,[sp,#0]
+ mov $t2,wzr
+ eor $t3,$B,$C
+ mov $t4,wzr
+ b .L_00_48
+
+.align 4
+.L_00_48:
+___
+ &Xupdate(\&body_00_15);
+ &Xupdate(\&body_00_15);
+ &Xupdate(\&body_00_15);
+ &Xupdate(\&body_00_15);
+$code.=<<___;
+ cmp $t1,#0 // check for K256 terminator
+ ldr $t1,[sp,#0]
+ sub $Xfer,$Xfer,#64
+ bne .L_00_48
+
+ sub $Ktbl,$Ktbl,#256 // rewind $Ktbl
+ cmp $inp,$num
+ mov $Xfer, #64
+ csel $Xfer, $Xfer, xzr, eq
+ sub $inp,$inp,$Xfer // avoid SEGV
+ mov $Xfer,sp
+___
+ &Xpreload(\&body_00_15);
+ &Xpreload(\&body_00_15);
+ &Xpreload(\&body_00_15);
+ &Xpreload(\&body_00_15);
+$code.=<<___;
+ add $A,$A,$t4 // h+=Sigma0(a) from the past
+ ldp $t0,$t1,[$ctx,#0]
+ add $A,$A,$t2 // h+=Maj(a,b,c) from the past
+ ldp $t2,$t3,[$ctx,#8]
+ add $A,$A,$t0 // accumulate
+ add $B,$B,$t1
+ ldp $t0,$t1,[$ctx,#16]
+ add $C,$C,$t2
+ add $D,$D,$t3
+ ldp $t2,$t3,[$ctx,#24]
+ add $E,$E,$t0
+ add $F,$F,$t1
+ ldr $t1,[sp,#0]
+ stp $A,$B,[$ctx,#0]
+ add $G,$G,$t2
+ mov $t2,wzr
+ stp $C,$D,[$ctx,#8]
+ add $H,$H,$t3
+ stp $E,$F,[$ctx,#16]
+ eor $t3,$B,$C
+ stp $G,$H,[$ctx,#24]
+ mov $t4,wzr
+ mov $Xfer,sp
+ b.ne .L_00_48
+
+ ldr x29,[x29]
+ add sp,sp,#16*4+16
+ ret
+.size sha256_block_neon,.-sha256_block_neon
+___
+}
+
+$code.=<<___;
+#ifndef __KERNEL__
+.comm OPENSSL_armcap_P,4,4
+#endif
+___
+
+{ my %opcode = (
+ "sha256h" => 0x5e004000, "sha256h2" => 0x5e005000,
+ "sha256su0" => 0x5e282800, "sha256su1" => 0x5e006000 );
+
+ sub unsha256 {
+ my ($mnemonic,$arg)=@_;
+
+ $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o
+ &&
+ sprintf ".inst\t0x%08x\t//%s %s",
+ $opcode{$mnemonic}|$1|($2<<5)|($3<<16),
+ $mnemonic,$arg;
+ }
+}
+
+open SELF,$0;
+while(<SELF>) {
+ next if (/^#!/);
+ last if (!s/^#/\/\// and !/^$/);
+ print;
+}
+close SELF;
+
+foreach(split("\n",$code)) {
+
+ s/\`([^\`]*)\`/eval($1)/ge;
+
+ s/\b(sha256\w+)\s+([qv].*)/unsha256($1,$2)/ge;
+
+ s/\bq([0-9]+)\b/v$1.16b/g; # old->new registers
+
+ s/\.[ui]?8(\s)/$1/;
+ s/\.\w?32\b// and s/\.16b/\.4s/g;
+ m/(ld|st)1[^\[]+\[0\]/ and s/\.4s/\.s/g;
+
+ print $_,"\n";
+}
+
+close STDOUT;
diff --git a/arch/arm64/crypto/sha512-glue.c b/arch/arm64/crypto/sha512-glue.c
new file mode 100644
index 000000000000..aff35c9992a4
--- /dev/null
+++ b/arch/arm64/crypto/sha512-glue.c
@@ -0,0 +1,94 @@
+/*
+ * Linux/arm64 port of the OpenSSL SHA512 implementation for AArch64
+ *
+ * Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * 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 <crypto/internal/hash.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <crypto/sha.h>
+#include <crypto/sha512_base.h>
+#include <asm/neon.h>
+
+MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash for arm64");
+MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha384");
+MODULE_ALIAS_CRYPTO("sha512");
+
+asmlinkage void sha512_block_data_order(u32 *digest, const void *data,
+ unsigned int num_blks);
+
+static int sha512_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ return sha512_base_do_update(desc, data, len,
+ (sha512_block_fn *)sha512_block_data_order);
+}
+
+static int sha512_finup(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ if (len)
+ sha512_base_do_update(desc, data, len,
+ (sha512_block_fn *)sha512_block_data_order);
+ sha512_base_do_finalize(desc,
+ (sha512_block_fn *)sha512_block_data_order);
+
+ return sha512_base_finish(desc, out);
+}
+
+static int sha512_final(struct shash_desc *desc, u8 *out)
+{
+ return sha512_finup(desc, NULL, 0, out);
+}
+
+static struct shash_alg algs[] = { {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .init = sha512_base_init,
+ .update = sha512_update,
+ .final = sha512_final,
+ .finup = sha512_finup,
+ .descsize = sizeof(struct sha512_state),
+ .base.cra_name = "sha512",
+ .base.cra_driver_name = "sha512-arm64",
+ .base.cra_priority = 150,
+ .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .base.cra_blocksize = SHA512_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+}, {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .init = sha384_base_init,
+ .update = sha512_update,
+ .final = sha512_final,
+ .finup = sha512_finup,
+ .descsize = sizeof(struct sha512_state),
+ .base.cra_name = "sha384",
+ .base.cra_driver_name = "sha384-arm64",
+ .base.cra_priority = 150,
+ .base.cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .base.cra_blocksize = SHA384_BLOCK_SIZE,
+ .base.cra_module = THIS_MODULE,
+} };
+
+static int __init sha512_mod_init(void)
+{
+ return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+}
+
+static void __exit sha512_mod_fini(void)
+{
+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+
+module_init(sha512_mod_init);
+module_exit(sha512_mod_fini);
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 28196b18e394..23b56135bca6 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -32,7 +32,6 @@ generic-y += segment.h
generic-y += sembuf.h
generic-y += serial.h
generic-y += shmbuf.h
-generic-y += simd.h
generic-y += sizes.h
generic-y += socket.h
generic-y += sockios.h
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index f632bad491d6..74705faa29fb 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -438,6 +438,12 @@ void arm64_set_ssbd_mitigation(bool state);
static inline void arm64_set_ssbd_mitigation(bool state) {}
#endif
+static inline bool system_supports_fpsimd(void)
+{
+ /* fast stub for kernel-4.9 */
+ return true;
+}
+
/* Watch out, ordering is important here. */
enum mitigation_state {
SPECTRE_UNAFFECTED,
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index e589811c5e23..49682a9b9f41 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -2,6 +2,7 @@
#define _ASM_EFI_H
#include <asm/cpufeature.h>
+#include <asm/fpsimd.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/neon.h>
@@ -19,8 +20,8 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define arch_efi_call_virt_setup() \
({ \
- kernel_neon_begin(); \
efi_virtmap_load(); \
+ __efi_fpsimd_begin(); \
})
#define arch_efi_call_virt(p, f, args...) \
@@ -32,8 +33,8 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define arch_efi_call_virt_teardown() \
({ \
+ __efi_fpsimd_end(); \
efi_virtmap_unload(); \
- kernel_neon_end(); \
})
#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 50f559f574fe..410c48163c6a 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -41,16 +41,6 @@ struct fpsimd_state {
unsigned int cpu;
};
-/*
- * Struct for stacking the bottom 'n' FP/SIMD registers.
- */
-struct fpsimd_partial_state {
- u32 fpsr;
- u32 fpcr;
- u32 num_regs;
- __uint128_t vregs[32];
-};
-
#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
/* Masks for extracting the FPSR and FPCR from the FPSCR */
@@ -77,9 +67,9 @@ extern void fpsimd_update_current_state(struct fpsimd_state *state);
extern void fpsimd_flush_task_state(struct task_struct *target);
-extern void fpsimd_save_partial_state(struct fpsimd_partial_state *state,
- u32 num_regs);
-extern void fpsimd_load_partial_state(struct fpsimd_partial_state *state);
+/* For use by EFI runtime services calls only */
+extern void __efi_fpsimd_begin(void);
+extern void __efi_fpsimd_end(void);
#endif
diff --git a/arch/arm64/include/asm/fpsimdmacros.h b/arch/arm64/include/asm/fpsimdmacros.h
index a2daf1293028..0f5fdd388b0d 100644
--- a/arch/arm64/include/asm/fpsimdmacros.h
+++ b/arch/arm64/include/asm/fpsimdmacros.h
@@ -75,59 +75,3 @@
ldr w\tmpnr, [\state, #16 * 2 + 4]
fpsimd_restore_fpcr x\tmpnr, \state
.endm
-
-.macro fpsimd_save_partial state, numnr, tmpnr1, tmpnr2
- mrs x\tmpnr1, fpsr
- str w\numnr, [\state, #8]
- mrs x\tmpnr2, fpcr
- stp w\tmpnr1, w\tmpnr2, [\state]
- adr x\tmpnr1, 0f
- add \state, \state, x\numnr, lsl #4
- sub x\tmpnr1, x\tmpnr1, x\numnr, lsl #1
- br x\tmpnr1
- stp q30, q31, [\state, #-16 * 30 - 16]
- stp q28, q29, [\state, #-16 * 28 - 16]
- stp q26, q27, [\state, #-16 * 26 - 16]
- stp q24, q25, [\state, #-16 * 24 - 16]
- stp q22, q23, [\state, #-16 * 22 - 16]
- stp q20, q21, [\state, #-16 * 20 - 16]
- stp q18, q19, [\state, #-16 * 18 - 16]
- stp q16, q17, [\state, #-16 * 16 - 16]
- stp q14, q15, [\state, #-16 * 14 - 16]
- stp q12, q13, [\state, #-16 * 12 - 16]
- stp q10, q11, [\state, #-16 * 10 - 16]
- stp q8, q9, [\state, #-16 * 8 - 16]
- stp q6, q7, [\state, #-16 * 6 - 16]
- stp q4, q5, [\state, #-16 * 4 - 16]
- stp q2, q3, [\state, #-16 * 2 - 16]
- stp q0, q1, [\state, #-16 * 0 - 16]
-0:
-.endm
-
-.macro fpsimd_restore_partial state, tmpnr1, tmpnr2
- ldp w\tmpnr1, w\tmpnr2, [\state]
- msr fpsr, x\tmpnr1
- fpsimd_restore_fpcr x\tmpnr2, x\tmpnr1
- adr x\tmpnr1, 0f
- ldr w\tmpnr2, [\state, #8]
- add \state, \state, x\tmpnr2, lsl #4
- sub x\tmpnr1, x\tmpnr1, x\tmpnr2, lsl #1
- br x\tmpnr1
- ldp q30, q31, [\state, #-16 * 30 - 16]
- ldp q28, q29, [\state, #-16 * 28 - 16]
- ldp q26, q27, [\state, #-16 * 26 - 16]
- ldp q24, q25, [\state, #-16 * 24 - 16]
- ldp q22, q23, [\state, #-16 * 22 - 16]
- ldp q20, q21, [\state, #-16 * 20 - 16]
- ldp q18, q19, [\state, #-16 * 18 - 16]
- ldp q16, q17, [\state, #-16 * 16 - 16]
- ldp q14, q15, [\state, #-16 * 14 - 16]
- ldp q12, q13, [\state, #-16 * 12 - 16]
- ldp q10, q11, [\state, #-16 * 10 - 16]
- ldp q8, q9, [\state, #-16 * 8 - 16]
- ldp q6, q7, [\state, #-16 * 6 - 16]
- ldp q4, q5, [\state, #-16 * 4 - 16]
- ldp q2, q3, [\state, #-16 * 2 - 16]
- ldp q0, q1, [\state, #-16 * 0 - 16]
-0:
-.endm
diff --git a/arch/arm64/include/asm/neon.h b/arch/arm64/include/asm/neon.h
index 13ce4cc18e26..fb9d137256a6 100644
--- a/arch/arm64/include/asm/neon.h
+++ b/arch/arm64/include/asm/neon.h
@@ -8,11 +8,15 @@
* published by the Free Software Foundation.
*/
-#include <linux/types.h>
+#ifndef __ASM_NEON_H
+#define __ASM_NEON_H
-#define cpu_has_neon() (1)
+#include <linux/types.h>
+#include <asm/fpsimd.h>
-#define kernel_neon_begin() kernel_neon_begin_partial(32)
+#define cpu_has_neon() system_supports_fpsimd()
-void kernel_neon_begin_partial(u32 num_regs);
+void kernel_neon_begin(void);
void kernel_neon_end(void);
+
+#endif /* ! __ASM_NEON_H */
diff --git a/arch/arm64/include/asm/simd.h b/arch/arm64/include/asm/simd.h
new file mode 100644
index 000000000000..6495cc51246f
--- /dev/null
+++ b/arch/arm64/include/asm/simd.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef __ASM_SIMD_H
+#define __ASM_SIMD_H
+
+#include <linux/compiler.h>
+#include <linux/irqflags.h>
+#include <linux/percpu.h>
+#include <linux/preempt.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_KERNEL_MODE_NEON
+
+DECLARE_PER_CPU(bool, kernel_neon_busy);
+
+/*
+ * may_use_simd - whether it is allowable at this time to issue SIMD
+ * instructions or access the SIMD register file
+ *
+ * Callers must not assume that the result remains true beyond the next
+ * preempt_enable() or return from softirq context.
+ */
+static __must_check inline bool may_use_simd(void)
+{
+ /*
+ * kernel_neon_busy is only set while preemption is disabled,
+ * and is clear whenever preemption is enabled. Since
+ * this_cpu_read() is atomic w.r.t. preemption, kernel_neon_busy
+ * cannot change under our feet -- if it's set we cannot be
+ * migrated, and if it's clear we cannot be migrated to a CPU
+ * where it is set.
+ */
+ return !in_irq() && !irqs_disabled() && !in_nmi() &&
+ !this_cpu_read(kernel_neon_busy);
+}
+
+#else /* ! CONFIG_KERNEL_MODE_NEON */
+
+static __must_check inline bool may_use_simd(void) {
+ return false;
+}
+
+#endif /* ! CONFIG_KERNEL_MODE_NEON */
+
+#endif
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
index c44a82f146b1..6a27cd6dbfa6 100644
--- a/arch/arm64/kernel/entry-fpsimd.S
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -41,27 +41,3 @@ ENTRY(fpsimd_load_state)
fpsimd_restore x0, 8
ret
ENDPROC(fpsimd_load_state)
-
-#ifdef CONFIG_KERNEL_MODE_NEON
-
-/*
- * Save the bottom n FP registers.
- *
- * x0 - pointer to struct fpsimd_partial_state
- */
-ENTRY(fpsimd_save_partial_state)
- fpsimd_save_partial x0, 1, 8, 9
- ret
-ENDPROC(fpsimd_save_partial_state)
-
-/*
- * Load the bottom n FP registers.
- *
- * x0 - pointer to struct fpsimd_partial_state
- */
-ENTRY(fpsimd_load_partial_state)
- fpsimd_restore_partial x0, 8, 9
- ret
-ENDPROC(fpsimd_load_partial_state)
-
-#endif
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index ee34be8bed03..59fc9db2fc09 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -17,17 +17,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/bottom_half.h>
#include <linux/cpu.h>
#include <linux/cpu_pm.h>
#include <linux/kernel.h>
+#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/preempt.h>
#include <linux/sched.h>
#include <linux/signal.h>
-#include <linux/hardirq.h>
#include <asm/fpsimd.h>
#include <asm/cpufeature.h>
#include <asm/cputype.h>
+#include <asm/simd.h>
#define FPEXC_IOF (1 << 0)
#define FPEXC_DZF (1 << 1)
@@ -63,6 +67,13 @@
* CPU currently contain the most recent userland FPSIMD state of the current
* task.
*
+ * In order to allow softirq handlers to use FPSIMD, kernel_neon_begin() may
+ * save the task's FPSIMD context back to task_struct from softirq context.
+ * To prevent this from racing with the manipulation of the task's FPSIMD state
+ * from task context and thereby corrupting the state, it is necessary to
+ * protect any manipulation of a task's fpsimd_state or TIF_FOREIGN_FPSTATE
+ * flag with local_bh_disable() unless softirqs are already masked.
+ *
* For a certain task, the sequence may look something like this:
* - the task gets scheduled in; if both the task's fpsimd_state.cpu field
* contains the id of the current CPU, and the CPU's fpsimd_last_state per-cpu
@@ -93,7 +104,7 @@ static DEFINE_PER_CPU(struct fpsimd_state *, fpsimd_last_state);
/*
* Trapped FP/ASIMD access.
*/
-void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
+asmlinkage void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
{
/* TODO: implement lazy context saving/restoring */
WARN_ON(1);
@@ -102,7 +113,7 @@ void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
/*
* Raise a SIGFPE for the current process.
*/
-void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
+asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
{
siginfo_t info;
unsigned int si_code = 0;
@@ -128,6 +139,8 @@ void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
void fpsimd_thread_switch(struct task_struct *next)
{
+ if (!system_supports_fpsimd())
+ return;
/*
* Save the current FPSIMD state to memory, but only if whatever is in
* the registers is in fact the most recent userland FPSIMD state of
@@ -148,21 +161,24 @@ void fpsimd_thread_switch(struct task_struct *next)
if (__this_cpu_read(fpsimd_last_state) == st
&& st->cpu == smp_processor_id())
- clear_ti_thread_flag(task_thread_info(next),
- TIF_FOREIGN_FPSTATE);
+ clear_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
else
- set_ti_thread_flag(task_thread_info(next),
- TIF_FOREIGN_FPSTATE);
+ set_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
}
}
void fpsimd_flush_thread(void)
{
- preempt_disable();
+ if (!system_supports_fpsimd())
+ return;
+
+ local_bh_disable();
+
memset(&current->thread.fpsimd_state, 0, sizeof(struct fpsimd_state));
fpsimd_flush_task_state(current);
set_thread_flag(TIF_FOREIGN_FPSTATE);
- preempt_enable();
+
+ local_bh_enable();
}
/*
@@ -171,10 +187,15 @@ void fpsimd_flush_thread(void)
*/
void fpsimd_preserve_current_state(void)
{
- preempt_disable();
+ if (!system_supports_fpsimd())
+ return;
+
+ local_bh_disable();
+
if (!test_thread_flag(TIF_FOREIGN_FPSTATE))
fpsimd_save_state(&current->thread.fpsimd_state);
- preempt_enable();
+
+ local_bh_enable();
}
/*
@@ -184,15 +205,20 @@ void fpsimd_preserve_current_state(void)
*/
void fpsimd_restore_current_state(void)
{
- preempt_disable();
+ if (!system_supports_fpsimd())
+ return;
+
+ local_bh_disable();
+
if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) {
struct fpsimd_state *st = &current->thread.fpsimd_state;
fpsimd_load_state(st);
- this_cpu_write(fpsimd_last_state, st);
+ __this_cpu_write(fpsimd_last_state, st);
st->cpu = smp_processor_id();
}
- preempt_enable();
+
+ local_bh_enable();
}
/*
@@ -202,15 +228,20 @@ void fpsimd_restore_current_state(void)
*/
void fpsimd_update_current_state(struct fpsimd_state *state)
{
- preempt_disable();
+ if (!system_supports_fpsimd())
+ return;
+
+ local_bh_disable();
+
fpsimd_load_state(state);
if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) {
struct fpsimd_state *st = &current->thread.fpsimd_state;
- this_cpu_write(fpsimd_last_state, st);
+ __this_cpu_write(fpsimd_last_state, st);
st->cpu = smp_processor_id();
}
- preempt_enable();
+
+ local_bh_enable();
}
/*
@@ -223,48 +254,126 @@ void fpsimd_flush_task_state(struct task_struct *t)
#ifdef CONFIG_KERNEL_MODE_NEON
-static DEFINE_PER_CPU(struct fpsimd_partial_state, hardirq_fpsimdstate);
-static DEFINE_PER_CPU(struct fpsimd_partial_state, softirq_fpsimdstate);
+DEFINE_PER_CPU(bool, kernel_neon_busy);
+EXPORT_PER_CPU_SYMBOL(kernel_neon_busy);
/*
* Kernel-side NEON support functions
*/
-void kernel_neon_begin_partial(u32 num_regs)
+
+/*
+ * kernel_neon_begin(): obtain the CPU FPSIMD registers for use by the calling
+ * context
+ *
+ * Must not be called unless may_use_simd() returns true.
+ * Task context in the FPSIMD registers is saved back to memory as necessary.
+ *
+ * A matching call to kernel_neon_end() must be made before returning from the
+ * calling context.
+ *
+ * The caller may freely use the FPSIMD registers until kernel_neon_end() is
+ * called.
+ */
+void kernel_neon_begin(void)
{
- if (in_interrupt()) {
- struct fpsimd_partial_state *s = this_cpu_ptr(
- in_irq() ? &hardirq_fpsimdstate : &softirq_fpsimdstate);
+ if (WARN_ON(!system_supports_fpsimd()))
+ return;
- BUG_ON(num_regs > 32);
- fpsimd_save_partial_state(s, roundup(num_regs, 2));
- } else {
- /*
- * Save the userland FPSIMD state if we have one and if we
- * haven't done so already. Clear fpsimd_last_state to indicate
- * that there is no longer userland FPSIMD state in the
- * registers.
- */
- preempt_disable();
- if (current->mm &&
- !test_and_set_thread_flag(TIF_FOREIGN_FPSTATE))
- fpsimd_save_state(&current->thread.fpsimd_state);
- this_cpu_write(fpsimd_last_state, NULL);
- }
+ BUG_ON(!may_use_simd());
+
+ local_bh_disable();
+
+ __this_cpu_write(kernel_neon_busy, true);
+
+ /* Save unsaved task fpsimd state, if any: */
+ if (current->mm && !test_and_set_thread_flag(TIF_FOREIGN_FPSTATE))
+ fpsimd_save_state(&current->thread.fpsimd_state);
+
+ /* Invalidate any task state remaining in the fpsimd regs: */
+ __this_cpu_write(fpsimd_last_state, NULL);
+
+ preempt_disable();
+
+ local_bh_enable();
}
-EXPORT_SYMBOL(kernel_neon_begin_partial);
+EXPORT_SYMBOL(kernel_neon_begin);
+/*
+ * kernel_neon_end(): give the CPU FPSIMD registers back to the current task
+ *
+ * Must be called from a context in which kernel_neon_begin() was previously
+ * called, with no call to kernel_neon_end() in the meantime.
+ *
+ * The caller must not use the FPSIMD registers after this function is called,
+ * unless kernel_neon_begin() is called again in the meantime.
+ */
void kernel_neon_end(void)
{
- if (in_interrupt()) {
- struct fpsimd_partial_state *s = this_cpu_ptr(
- in_irq() ? &hardirq_fpsimdstate : &softirq_fpsimdstate);
- fpsimd_load_partial_state(s);
- } else {
- preempt_enable();
- }
+ bool busy;
+
+ if (!system_supports_fpsimd())
+ return;
+
+ busy = __this_cpu_xchg(kernel_neon_busy, false);
+ WARN_ON(!busy); /* No matching kernel_neon_begin()? */
+
+ preempt_enable();
}
EXPORT_SYMBOL(kernel_neon_end);
+#ifdef CONFIG_EFI
+
+static DEFINE_PER_CPU(struct fpsimd_state, efi_fpsimd_state);
+static DEFINE_PER_CPU(bool, efi_fpsimd_state_used);
+
+/*
+ * EFI runtime services support functions
+ *
+ * The ABI for EFI runtime services allows EFI to use FPSIMD during the call.
+ * This means that for EFI (and only for EFI), we have to assume that FPSIMD
+ * is always used rather than being an optional accelerator.
+ *
+ * These functions provide the necessary support for ensuring FPSIMD
+ * save/restore in the contexts from which EFI is used.
+ *
+ * Do not use them for any other purpose -- if tempted to do so, you are
+ * either doing something wrong or you need to propose some refactoring.
+ */
+
+/*
+ * __efi_fpsimd_begin(): prepare FPSIMD for making an EFI runtime services call
+ */
+void __efi_fpsimd_begin(void)
+{
+ if (!system_supports_fpsimd())
+ return;
+
+ WARN_ON(preemptible());
+
+ if (may_use_simd())
+ kernel_neon_begin();
+ else {
+ fpsimd_save_state(this_cpu_ptr(&efi_fpsimd_state));
+ __this_cpu_write(efi_fpsimd_state_used, true);
+ }
+}
+
+/*
+ * __efi_fpsimd_end(): clean up FPSIMD after an EFI runtime services call
+ */
+void __efi_fpsimd_end(void)
+{
+ if (!system_supports_fpsimd())
+ return;
+
+ if (__this_cpu_xchg(efi_fpsimd_state_used, false))
+ fpsimd_load_state(this_cpu_ptr(&efi_fpsimd_state));
+ else
+ kernel_neon_end();
+}
+
+#endif /* CONFIG_EFI */
+
#endif /* CONFIG_KERNEL_MODE_NEON */
#ifdef CONFIG_CPU_PM
@@ -335,4 +444,4 @@ static int __init fpsimd_init(void)
return 0;
}
-late_initcall(fpsimd_init);
+core_initcall(fpsimd_init);
diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index 1b3eb67edefb..3566556eea20 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -39,20 +39,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return res->start;
}
+#ifdef CONFIG_ACPI
/*
* Try to assign the IRQ number when probing a new device
*/
int pcibios_alloc_irq(struct pci_dev *dev)
{
- if (acpi_disabled)
- dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
-#ifdef CONFIG_ACPI
- else
- return acpi_pci_irq_enable(dev);
-#endif
+ if (!acpi_disabled)
+ acpi_pci_irq_enable(dev);
return 0;
}
+#endif
/*
* raw_pci_read/write - Platform-specific PCI config space access.
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 7990377dbbbc..16711313854c 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -622,6 +622,10 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
{
struct user_fpsimd_state *uregs;
uregs = &target->thread.fpsimd_state.user_fpsimd;
+
+ if (target == current)
+ fpsimd_preserve_current_state();
+
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
}
@@ -897,6 +901,9 @@ static int compat_vfp_get(struct task_struct *target,
uregs = &target->thread.fpsimd_state.user_fpsimd;
+ if (target == current)
+ fpsimd_preserve_current_state();
+
/*
* The VFP registers are packed into the fpsimd_state, so they all sit
* nicely together for us. We just need to create the fpscr separately.
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index b5222094ab52..4faec67e2f63 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -180,6 +180,7 @@ static void __init smp_build_mpidr_hash(void)
static void __init setup_machine_fdt(phys_addr_t dt_phys)
{
void *dt_virt = fixmap_remap_fdt(dt_phys);
+ const char *name;
if (!dt_virt || !early_init_dt_scan(dt_virt)) {
pr_crit("\n"
@@ -192,7 +193,12 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
cpu_relax();
}
- dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name());
+ name = of_flat_dt_get_machine_name();
+ if (!name)
+ return;
+
+ pr_info("Machine model: %s\n", name);
+ dump_stack_set_arch_desc("%s (DT)", name);
}
static void __init request_standard_resources(void)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index ed734264a516..312c2ff8d1be 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -19,7 +19,6 @@
#include <linux/nodemask.h>
#include <linux/of.h>
#include <linux/sched.h>
-#include <linux/sched.h>
#include <linux/sched_energy.h>
#include <asm/cputype.h>
@@ -227,7 +226,9 @@ const struct sched_group_energy * const cpu_cluster_energy(int cpu)
struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL1];
if (!sge) {
+#ifndef CONFIG_MACH_MT7622
pr_warn("Invalid sched_group_energy for Cluster%d\n", cpu);
+#endif
return NULL;
}
@@ -240,7 +241,9 @@ const struct sched_group_energy * const cpu_core_energy(int cpu)
struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL0];
if (!sge) {
+#ifndef CONFIG_MACH_MT7622
pr_warn("Invalid sched_group_energy for CPU%d\n", cpu);
+#endif
return NULL;
}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index c5c710d0b141..00e6295ec15e 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -427,37 +427,37 @@ void __init mem_init(void)
#define MLG(b, t) b, t, ((t) - (b)) >> 30
#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
- pr_notice("Virtual kernel memory layout:\n");
+ pr_info("Virtual kernel memory layout:\n");
#ifdef CONFIG_KASAN
- pr_notice(" kasan : 0x%16lx - 0x%16lx (%6ld GB)\n",
+ pr_info(" kasan : 0x%16lx - 0x%16lx (%6ld GB)\n",
MLG(KASAN_SHADOW_START, KASAN_SHADOW_END));
#endif
- pr_notice(" modules : 0x%16lx - 0x%16lx (%6ld MB)\n",
+ pr_info(" modules : 0x%16lx - 0x%16lx (%6ld MB)\n",
MLM(MODULES_VADDR, MODULES_END));
- pr_notice(" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n",
+ pr_info(" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n",
MLG(VMALLOC_START, VMALLOC_END));
- pr_notice(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n",
+ pr_info(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n",
MLK_ROUNDUP(_text, _etext));
- pr_notice(" .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n",
+ pr_info(" .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n",
MLK_ROUNDUP(__start_rodata, __init_begin));
- pr_notice(" .init : 0x%p" " - 0x%p" " (%6ld KB)\n",
+ pr_info(" .init : 0x%p" " - 0x%p" " (%6ld KB)\n",
MLK_ROUNDUP(__init_begin, __init_end));
- pr_notice(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n",
+ pr_info(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n",
MLK_ROUNDUP(_sdata, _edata));
- pr_notice(" .bss : 0x%p" " - 0x%p" " (%6ld KB)\n",
+ pr_info(" .bss : 0x%p" " - 0x%p" " (%6ld KB)\n",
MLK_ROUNDUP(__bss_start, __bss_stop));
- pr_notice(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n",
+ pr_info(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n",
MLK(FIXADDR_START, FIXADDR_TOP));
- pr_notice(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n",
+ pr_info(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n",
MLM(PCI_IO_START, PCI_IO_END));
#ifdef CONFIG_SPARSEMEM_VMEMMAP
- pr_notice(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n",
+ pr_info(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n",
MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE));
- pr_notice(" 0x%16lx - 0x%16lx (%6ld MB actual)\n",
+ pr_info(" 0x%16lx - 0x%16lx (%6ld MB actual)\n",
MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
(unsigned long)virt_to_page(high_memory)));
#endif
- pr_notice(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n",
+ pr_info(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n",
MLM(__phys_to_virt(memblock_start_of_DRAM()),
(unsigned long)high_memory));
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index f5f1bdb292de..b63da6b0a75c 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -26,12 +26,14 @@ platforms += pistachio
platforms += pmcs-msp71xx
platforms += pnx833x
platforms += ralink
+platforms += rt2880
platforms += rb532
platforms += sgi-ip22
platforms += sgi-ip27
platforms += sgi-ip32
platforms += sibyte
platforms += sni
+platforms += tc3262
platforms += txx9
platforms += vr41xx
platforms += xilfpga
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9708c319a744..e51fda9949af 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2,13 +2,13 @@ config MIPS
bool
default y
select ARCH_SUPPORTS_UPROBES
- select ARCH_MIGHT_HAVE_PC_PARPORT
+# select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
select ARCH_USE_BUILTIN_BSWAP
select HAVE_CONTEXT_TRACKING
- select HAVE_GENERIC_DMA_COHERENT
- select HAVE_IDE
+# select HAVE_GENERIC_DMA_COHERENT
+# select HAVE_IDE
select HAVE_IRQ_EXIT_ON_IRQ_STACK
select HAVE_OPROFILE
select HAVE_PERF_EVENTS
@@ -39,7 +39,7 @@ config MIPS
select GENERIC_PCI_IOMAP
select HAVE_ARCH_JUMP_LABEL
select ARCH_WANT_IPC_PARSE_VERSION
- select IRQ_FORCED_THREADING
+# select IRQ_FORCED_THREADING
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP
select ARCH_DISCARD_MEMBLOCK
@@ -56,6 +56,7 @@ config MIPS
select CLONE_BACKWARDS
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_CC_STACKPROTECTOR
+ select LD_DEAD_CODE_DATA_ELIMINATION
select CPU_PM if CPU_IDLE
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_BINFMT_ELF_STATE
@@ -68,12 +69,50 @@ config MIPS
select HAVE_EXIT_THREAD
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_ARCH_HARDENED_USERCOPY
+ select ARCH_HAS_UBSAN_SANITIZE_ALL
menu "Machine selection"
+config ECONET_EN75XX_MP
+ bool
+
+config MIPS_TC3262_34K
+ select SYS_SUPPORTS_MULTITHREADING
+ select SYS_SUPPORTS_SMP
+ bool
+
+config MIPS_TC3262_1004K
+ select SYS_SUPPORTS_MULTITHREADING
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_MIPS_CMP
+ select SYS_SUPPORTS_MIPS_CPS
+ select SYS_SUPPORTS_HIGHMEM
+ select MIPS_CPU_SCACHE
+ select IRQ_GIC
+ select IRQ_GIC_EIC
+ select WEAK_REORDERING_BEYOND_LLSC
+ select TC3262_CPU_TIMER
+ bool
+
+config MIPS_TC3262
+ bool
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select BOOT_RAW
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_MIPS16
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select CSRC_R4K
+ select CEVT_R4K
+ select CPU_MIPSR2_IRQ_VI
+ select CPU_MIPSR2_IRQ_EI
+ select NO_EXCEPT_FILL
+
choice
prompt "System type"
- default SGI_IP22
+ default RALINK_MT7621
config MIPS_GENERIC
bool "Generic board-agnostic MIPS kernel"
@@ -127,6 +166,89 @@ config MIPS_GENERIC
using the boot protocol defined in the UHI (Unified Hosting
Interface) specification.
+config RALINK_MT7621
+ bool "Ralink MT7621 board"
+ select DMA_NONCOHERENT
+ select IRQ_MIPS_CPU
+ select HW_HAS_PCI
+ select SWAP_IO_SPACE
+ select BOOT_ELF32
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_MIPS16
+ select SYS_SUPPORTS_HIGHMEM
+ select CSRC_R4K
+ select CEVT_R4K
+ select MIPS_CPU_SCACHE
+ select SYS_SUPPORTS_MULTITHREADING
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_MIPS_CMP
+ select SYS_SUPPORTS_MIPS_CPS
+ select IRQ_GIC
+# select MIPS_GIC
+ select WEAK_REORDERING_BEYOND_LLSC
+ select MIPS_L2_CACHE_ER35
+ help
+ Ralink evaluation board based on MT7621
+
+config RALINK_MT7628
+ bool "Ralink MT7628 board"
+ select DMA_NONCOHERENT
+ select IRQ_MIPS_CPU
+ select HW_HAS_PCI
+ select SWAP_IO_SPACE
+ select BOOT_ELF32
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_HAS_EARLY_PRINTK
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_MIPS16
+ select CSRC_R4K
+ select CEVT_R4K
+ select CPU_MIPSR2_IRQ_VI
+ help
+ Ralink evaluation board based on MT7628
+
+config ECONET_EN7512
+ bool "EcoNET EN7512/3 board"
+ select MIPS_TC3262
+ select MIPS_TC3262_34K
+ select ECONET_EN75XX_MP
+ select SYS_SUPPORTS_BIG_ENDIAN
+ help
+ EcoNET evaluation board based on EN7512/3
+
+config ECONET_EN7516
+ bool "EcoNET EN7516 board"
+ select MIPS_TC3262
+ select MIPS_TC3262_1004K
+ select ECONET_EN75XX_MP
+ select SYS_SUPPORTS_BIG_ENDIAN
+ help
+ EcoNET evaluation board based on EN7516
+
+config ECONET_EN7527
+ bool "EcoNET EN7527/EN7561G board"
+ select MIPS_TC3262
+ select MIPS_TC3262_1004K
+ select ECONET_EN75XX_MP
+ select SYS_SUPPORTS_BIG_ENDIAN
+ help
+ EcoNET evaluation board based on EN7527/EN7561G
+
+config ECONET_EN7528
+ bool "EcoNET EN7528DU/EN7561DU board"
+ select MIPS_TC3262
+ select MIPS_TC3262_1004K
+ select ECONET_EN75XX_MP
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ help
+ EcoNET evaluation board based on EN7528DU/EN7561DU
+
config MIPS_ALCHEMY
bool "Alchemy processor based machines"
select ARCH_PHYS_ADDR_T_64BIT
@@ -215,6 +337,7 @@ config BMIPS_GENERIC
select BRCMSTB_L2_IRQ
select IRQ_MIPS_CPU
select DMA_NONCOHERENT
+ select DMA_UNMAP_POST_FLUSH
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
@@ -343,6 +466,7 @@ config MACH_JAZZ
select CSRC_R4K
select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN
select GENERIC_ISA_DMA
+ select DMA_UNMAP_POST_FLUSH
select HAVE_PCSPKR_PLATFORM
select IRQ_MIPS_CPU
select I8253
@@ -1022,8 +1146,10 @@ source "arch/mips/pic32/Kconfig"
source "arch/mips/pistachio/Kconfig"
source "arch/mips/pmcs-msp71xx/Kconfig"
source "arch/mips/ralink/Kconfig"
+source "arch/mips/rt2880/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
+source "arch/mips/tc3262/Kconfig"
source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig"
@@ -1135,6 +1261,9 @@ config DMA_NONCOHERENT
bool
select NEED_DMA_MAP_STATE
+config DMA_UNMAP_POST_FLUSH
+ bool
+
config NEED_DMA_MAP_STATE
bool
@@ -1246,6 +1375,13 @@ config IRQ_TXX9
config IRQ_GT641XX
bool
+config IRQ_GIC
+ bool
+ select MIPS_CM
+
+config IRQ_GIC_EIC
+ bool
+
config PCI_GT64XXX_PCI0
bool
@@ -1337,6 +1473,10 @@ config MIPS_L1_CACHE_SHIFT
default "4" if MIPS_L1_CACHE_SHIFT_4
default "5"
+config MIPS_L2_CACHE_ER35
+ bool
+ select ZONE_DMA
+
config HAVE_STD_PC_SERIAL_PORT
bool
@@ -1660,6 +1800,7 @@ config CPU_R10000
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES
+ select DMA_UNMAP_POST_FLUSH
help
MIPS Technologies R10000-series processors.
@@ -1905,9 +2046,11 @@ config SYS_HAS_CPU_MIPS32_R3_5
bool
config SYS_HAS_CPU_MIPS32_R5
+ select DMA_UNMAP_POST_FLUSH
bool
config SYS_HAS_CPU_MIPS32_R6
+ select DMA_UNMAP_POST_FLUSH
bool
config SYS_HAS_CPU_MIPS64_R1
@@ -1917,6 +2060,7 @@ config SYS_HAS_CPU_MIPS64_R2
bool
config SYS_HAS_CPU_MIPS64_R6
+ select DMA_UNMAP_POST_FLUSH
bool
config SYS_HAS_CPU_R3000
@@ -2207,6 +2351,22 @@ config FORCE_MAX_ZONEORDER
The page size is not necessarily 4KB. Keep this in mind
when choosing a value for this option.
+config THREAD_STACK_SIZE_ADJUSTMENT
+ bool "Enable adjustment of a kernel thread stack size"
+
+config THREAD_SIZE_ORDER
+ int "An order of 2 for a multiplier of a thread info structure size"
+ default "2"
+ range 0 3
+ depends on THREAD_STACK_SIZE_ADJUSTMENT
+ help
+ Set a size of a kernel thread stack to
+
+ 2^(PAGE_SHIFT + THREAD_SIZE_ORDER) - sizeof(struct thread_info)
+
+ It should be larger for preemptive kernels and systems with
+ drivers that require deeper stacks.
+
config BOARD_SCACHE
bool
@@ -2509,6 +2669,11 @@ config MIPS_ASID_BITS
config MIPS_ASID_BITS_VARIABLE
bool
+config LONG_CALLS
+ bool "gcc must use -mlong-calls (RAM > 256MB)"
+ depends on 32BIT
+ default y if DYNAMIC_FTRACE
+
#
# - Highmem only makes sense for the 32-bit kernel.
# - The current highmem code will only work properly on physically indexed
@@ -2525,6 +2690,7 @@ config MIPS_ASID_BITS_VARIABLE
config HIGHMEM
bool "High Memory Support"
depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA
+ select LONG_CALLS
config CPU_SUPPORTS_HIGHMEM
bool
@@ -2898,6 +3064,20 @@ config MIPS_O32_FP64_SUPPORT
If unsure, say N.
+config MIPS_FPU_EMULATOR
+ bool "MIPS FPU Emulator"
+ default y
+ help
+ This option lets you disable the built-in MIPS FPU (Coprocessor 1)
+ emulator, which handles floating-point instructions on processors
+ without a hardware FPU. It is generally a good idea to keep the
+ emulator built-in, unless you are perfectly sure you have a
+ complete soft-float environment. With the emulator disabled, all
+ users of float operations will be killed with an illegal instr-
+ uction exception.
+
+ Say Y, please.
+
config USE_OF
bool
select OF
@@ -3095,6 +3275,10 @@ config ZONE_DMA
config ZONE_DMA32
bool
+config ZONE_DMA_SIZE
+ hex
+ default 0x1000000 if MIPS_L2_CACHE_ER35
+
source "drivers/pcmcia/Kconfig"
config RAPIDIO
@@ -3164,11 +3348,11 @@ endmenu
menu "Power management options"
config ARCH_HIBERNATION_POSSIBLE
- def_bool y
+ def_bool n
depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
config ARCH_SUSPEND_POSSIBLE
- def_bool y
+ def_bool n
depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
source "kernel/power/Kconfig"
@@ -3205,3 +3389,5 @@ source "crypto/Kconfig"
source "lib/Kconfig"
source "arch/mips/kvm/Kconfig"
+
+source "ndm/Kconfig"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index af4eff7d22ec..57c873d8ce3a 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -90,11 +90,21 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlinuz
# machines may also. Since BFD is incredibly buggy with respect to
# crossformat linking we rely on the elf2ecoff tool for format conversion.
#
-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
+cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
cflags-y += -msoft-float
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
+ifdef CONFIG_64BIT
+KBUILD_AFLAGS_MODULE += -mlong-calls
+KBUILD_CFLAGS_MODULE += -mlong-calls
+else
+ifdef CONFIG_LONG_CALLS
KBUILD_AFLAGS_MODULE += -mlong-calls
KBUILD_CFLAGS_MODULE += -mlong-calls
+else
+KBUILD_AFLAGS_MODULE += -mno-long-calls
+KBUILD_CFLAGS_MODULE += -mno-long-calls
+endif
+endif
ifeq ($(CONFIG_RELOCATABLE),y)
LDFLAGS_vmlinux += --emit-relocs
@@ -131,6 +141,21 @@ cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.
cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \
-fno-omit-frame-pointer
+
+# Some distribution-specific toolchains might pass the -fstack-check
+# option during the build, which adds a simple stack-probe at the beginning
+# of every function. This stack probe is to ensure that there is enough
+# stack space, else a SEGV is generated. This is not desirable for MIPS
+# as kernel stacks are small, placed in unmapped virtual memory, and do not
+# grow when overflowed. Especially on SGI IP27 platforms, this check will
+# lead to a NULL pointer dereference in _raw_spin_lock_irq.
+#
+# In disassembly, this stack probe appears at the top of a function as:
+# sd zero,<offset>(sp)
+# Where <offset> is a negative value.
+#
+cflags-y += -fno-stack-check
+
#
# CPU-dependent compiler/assembler options for optimization.
#
@@ -298,7 +323,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo
head-y := arch/mips/kernel/head.o
libs-y += arch/mips/lib/
-libs-y += arch/mips/math-emu/
+libs-$(CONFIG_MIPS_FPU_EMULATOR) += arch/mips/math-emu/
# See arch/mips/Kbuild for content of core part of the kernel
core-y += arch/mips/
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
index 730c0b03060d..b816cb4a25ff 100644
--- a/arch/mips/ath79/pci.c
+++ b/arch/mips/ath79/pci.c
@@ -22,10 +22,10 @@
#include "pci.h"
static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
-static const struct ath79_pci_irq *ath79_pci_irq_map __initdata;
-static unsigned ath79_pci_nr_irqs __initdata;
+static const struct ath79_pci_irq *ath79_pci_irq_map;
+static unsigned ath79_pci_nr_irqs;
-static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
+static const struct ath79_pci_irq ar71xx_pci_irq_map[] = {
{
.slot = 17,
.pin = 1,
@@ -41,7 +41,7 @@ static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
}
};
-static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
+static const struct ath79_pci_irq ar724x_pci_irq_map[] = {
{
.slot = 0,
.pin = 1,
@@ -49,7 +49,7 @@ static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
}
};
-static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = {
+static const struct ath79_pci_irq qca955x_pci_irq_map[] = {
{
.bus = 0,
.slot = 0,
@@ -64,7 +64,7 @@ static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = {
},
};
-int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
+int pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
{
int irq = -1;
int i;
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 3e93eea5a5f5..5a25767c048d 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -23,7 +23,8 @@ KBUILD_CFLAGS := $(shell echo $(KBUILD_CFLAGS) | sed -e "s/-pg//")
KBUILD_CFLAGS := $(filter-out -fstack-protector, $(KBUILD_CFLAGS))
KBUILD_CFLAGS := $(LINUXINCLUDE) $(KBUILD_CFLAGS) -D__KERNEL__ \
- -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull"
+ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" \
+ -D__ZBOOT__
KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 256fe6f65cf2..80c0706e74bb 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -184,7 +184,7 @@ static void __init octeon_smp_setup(void)
* Firmware CPU startup hook
*
*/
-static void octeon_boot_secondary(int cpu, struct task_struct *idle)
+static int octeon_boot_secondary(int cpu, struct task_struct *idle)
{
int count;
@@ -202,8 +202,12 @@ static void octeon_boot_secondary(int cpu, struct task_struct *idle)
udelay(1);
count--;
}
- if (count == 0)
+ if (count == 0) {
pr_err("Secondary boot timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
}
/**
@@ -272,7 +276,6 @@ static int octeon_cpu_disable(void)
set_cpu_online(cpu, false);
calculate_cpu_foreign_map();
- cpumask_clear_cpu(cpu, &cpu_callin_map);
octeon_fixup_irqs();
__flush_cache_all();
@@ -390,7 +393,7 @@ late_initcall(register_cavium_notifier);
#endif /* CONFIG_HOTPLUG_CPU */
-struct plat_smp_ops octeon_smp_ops = {
+const struct plat_smp_ops octeon_smp_ops = {
.send_ipi_single = octeon_send_ipi_single,
.send_ipi_mask = octeon_send_ipi_mask,
.init_secondary = octeon_init_secondary,
@@ -467,7 +470,7 @@ static void octeon_78xx_send_ipi_mask(const struct cpumask *mask,
octeon_78xx_send_ipi_single(cpu, action);
}
-static struct plat_smp_ops octeon_78xx_smp_ops = {
+static const struct plat_smp_ops octeon_78xx_smp_ops = {
.send_ipi_single = octeon_78xx_send_ipi_single,
.send_ipi_mask = octeon_78xx_send_ipi_mask,
.init_secondary = octeon_init_secondary,
@@ -483,7 +486,7 @@ static struct plat_smp_ops octeon_78xx_smp_ops = {
void __init octeon_setup_smp(void)
{
- struct plat_smp_ops *ops;
+ const struct plat_smp_ops *ops;
if (octeon_has_feature(OCTEON_FEATURE_CIU3))
ops = &octeon_78xx_smp_ops;
diff --git a/arch/mips/fw/arc/init.c b/arch/mips/fw/arc/init.c
index 629b24db0d3a..008555969534 100644
--- a/arch/mips/fw/arc/init.c
+++ b/arch/mips/fw/arc/init.c
@@ -51,7 +51,7 @@ void __init prom_init(void)
#endif
#ifdef CONFIG_SGI_IP27
{
- extern struct plat_smp_ops ip27_smp_ops;
+ extern const struct plat_smp_ops ip27_smp_ops;
register_smp_ops(&ip27_smp_ops);
}
diff --git a/arch/mips/generic/irq.c b/arch/mips/generic/irq.c
index 14064bdd91dd..b361ff91a77d 100644
--- a/arch/mips/generic/irq.c
+++ b/arch/mips/generic/irq.c
@@ -16,15 +16,16 @@
#include <linux/types.h>
#include <asm/irq.h>
+#include <asm/time.h>
int get_c0_fdc_int(void)
{
int mips_cpu_fdc_irq;
- if (cpu_has_veic)
- panic("Unimplemented!");
- else if (gic_present)
+ if (gic_present)
mips_cpu_fdc_irq = gic_get_c0_fdc_int();
+ else if (cpu_has_veic)
+ panic("Unimplemented!");
else if (cp0_fdc_irq >= 0)
mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
else
@@ -37,10 +38,10 @@ int get_c0_perfcount_int(void)
{
int mips_cpu_perf_irq;
- if (cpu_has_veic)
- panic("Unimplemented!");
- else if (gic_present)
+ if (gic_present)
mips_cpu_perf_irq = gic_get_c0_perfcount_int();
+ else if (cpu_has_veic)
+ panic("Unimplemented!");
else if (cp0_perfcount_irq >= 0)
mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
else
@@ -53,10 +54,10 @@ unsigned int get_c0_compare_int(void)
{
int mips_cpu_timer_irq;
- if (cpu_has_veic)
- panic("Unimplemented!");
- else if (gic_present)
+ if (gic_present)
mips_cpu_timer_irq = gic_get_c0_compare_int();
+ else if (cpu_has_veic)
+ panic("Unimplemented!");
else
mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index fa57cef12a46..da1b8718861e 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -456,6 +456,7 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *
{
smp_mb__before_llsc();
__clear_bit(nr, addr);
+ nudge_writes();
}
/*
diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h
index 23f55af7d6ba..a564915fddc4 100644
--- a/arch/mips/include/asm/bmips.h
+++ b/arch/mips/include/asm/bmips.h
@@ -48,8 +48,8 @@
#include <asm/r4kcache.h>
#include <asm/smp-ops.h>
-extern struct plat_smp_ops bmips43xx_smp_ops;
-extern struct plat_smp_ops bmips5000_smp_ops;
+extern const struct plat_smp_ops bmips43xx_smp_ops;
+extern const struct plat_smp_ops bmips5000_smp_ops;
static inline int register_bmips_smp_ops(void)
{
diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index 4812d1fed0c2..d687b40b9fbb 100644
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -25,7 +25,6 @@
*
* MIPS specific flush operations:
*
- * - flush_cache_sigtramp() flush signal trampoline
* - flush_icache_all() flush the entire instruction cache
* - flush_data_cache_page() flushes a page from the data cache
* - __flush_icache_user_range(start, end) flushes range of user instructions
@@ -110,7 +109,6 @@ extern void copy_from_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len);
-extern void (*flush_cache_sigtramp)(unsigned long addr);
extern void (*flush_icache_all)(void);
extern void (*local_flush_data_cache_page)(void * addr);
extern void (*flush_data_cache_page)(unsigned long addr);
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index e961c8a7ea66..c9d245dcddc7 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -181,9 +181,6 @@
#ifndef cpu_has_pindexed_dcache
#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
#endif
-#ifndef cpu_has_local_ebase
-#define cpu_has_local_ebase 1
-#endif
/*
* I-Cache snoops remote store. This only matters on SMP. Some multiprocessors
diff --git a/arch/mips/include/asm/dma.h b/arch/mips/include/asm/dma.h
index 5b9ed1bffdbc..52f11bc3edb9 100644
--- a/arch/mips/include/asm/dma.h
+++ b/arch/mips/include/asm/dma.h
@@ -86,6 +86,9 @@
#if defined(CONFIG_SGI_IP22) || defined(CONFIG_SGI_IP28)
/* don't care; ISA bus master won't work, ISA slave DMA supports 32bit addr */
#define MAX_DMA_ADDRESS PAGE_OFFSET
+#elif defined(CONFIG_MIPS_L2_CACHE_ER35)
+/* Allocate low memory to DMA */
+#define MAX_DMA_ADDRESS (PAGE_OFFSET + CONFIG_ZONE_DMA_SIZE)
#else
#define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000)
#endif
diff --git a/arch/mips/include/asm/dsemul.h b/arch/mips/include/asm/dsemul.h
index a6e067801f23..d388fbe3bfbd 100644
--- a/arch/mips/include/asm/dsemul.h
+++ b/arch/mips/include/asm/dsemul.h
@@ -41,6 +41,7 @@ struct task_struct;
extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
unsigned long branch_pc, unsigned long cont_pc);
+#ifdef CONFIG_MIPS_FPU_EMULATOR
/**
* do_dsemulret() - Return from a delay slot 'emulation' frame
* @xcp: User thread register context.
@@ -88,5 +89,27 @@ extern bool dsemul_thread_rollback(struct pt_regs *regs);
* before @mm is freed in order to avoid memory leaks.
*/
extern void dsemul_mm_cleanup(struct mm_struct *mm);
+#else
+static inline bool do_dsemulret(struct pt_regs *xcp)
+{
+ return false;
+}
+
+static inline bool dsemul_thread_cleanup(struct task_struct *tsk)
+{
+ return false;
+}
+
+static inline bool dsemul_thread_rollback(struct pt_regs *regs)
+{
+ return false;
+}
+
+static inline void dsemul_mm_cleanup(struct mm_struct *mm)
+{
+
+}
+
+#endif
#endif /* __MIPS_ASM_DSEMUL_H__ */
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index f06f97bd62df..f41f2387b9c5 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -227,8 +227,10 @@ static inline int init_fpu(void)
/* Restore FRE */
write_c0_config5(config5);
enable_fpu_hazard();
- } else
+ } else if (IS_ENABLED(CONFIG_MIPS_FPU_EMULATOR))
fpu_emulator_init_fpu();
+ else
+ ret = SIGILL;
return ret;
}
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index c05369e0b8d6..966891f71be2 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -30,6 +30,7 @@
#include <asm/local.h>
#include <asm/processor.h>
+#ifdef CONFIG_MIPS_FPU_EMULATOR
#ifdef CONFIG_DEBUG_FS
struct mips_fpu_emulator_stats {
@@ -63,6 +64,16 @@ do { \
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu,
void *__user *fault_addr);
+#else /* no CONFIG_MIPS_FPU_EMULATOR */
+static inline int fpu_emulator_cop1Handler(struct pt_regs *xcp,
+ struct mips_fpu_struct *ctx, int has_fpu,
+ void *__user *fault_addr)
+{
+ *fault_addr = NULL;
+ return SIGILL; /* we don't speak MIPS FPU */
+}
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
+
void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
struct task_struct *tsk);
int process_fpemu_return(int sig, void __user *fault_addr,
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
new file mode 100644
index 000000000000..0aac7d6f2a16
--- /dev/null
+++ b/arch/mips/include/asm/gic.h
@@ -0,0 +1,383 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000, 07 MIPS Technologies, Inc.
+ *
+ * GIC Register Definitions
+ *
+ */
+#ifndef _ASM_GICREGS_H
+#define _ASM_GICREGS_H
+
+#include <linux/bitmap.h>
+#include <linux/threads.h>
+
+#include <irq.h>
+
+#undef GICISBYTELITTLEENDIAN
+
+/* Constants */
+#define GIC_POL_POS 1
+#define GIC_POL_NEG 0
+#define GIC_TRIG_EDGE 1
+#define GIC_TRIG_LEVEL 0
+
+#define MSK(n) ((1 << (n)) - 1)
+#define REG32(addr) (*(volatile unsigned int *) (addr))
+#define REG(base, offs) REG32((unsigned long)(base) + offs##_##OFS)
+#define REGP(base, phys) REG32((unsigned long)(base) + (phys))
+
+/* Accessors */
+#define GIC_REG(segment, offset) \
+ REG32(_gic_base + segment##_##SECTION_OFS + offset##_##OFS)
+#define GIC_REG_ADDR(segment, offset) \
+ REG32(_gic_base + segment##_##SECTION_OFS + offset)
+
+#define GIC_ABS_REG(segment, offset) \
+ (_gic_base + segment##_##SECTION_OFS + offset##_##OFS)
+#define GIC_REG_ABS_ADDR(segment, offset) \
+ (_gic_base + segment##_##SECTION_OFS + offset)
+
+#ifdef GICISBYTELITTLEENDIAN
+#define GICREAD(reg, data) ((data) = (reg), (data) = le32_to_cpu(data))
+#define GICWRITE(reg, data) ((reg) = cpu_to_le32(data))
+#else
+#define GICREAD(reg, data) ((data) = (reg))
+#define GICWRITE(reg, data) ((reg) = (data))
+#endif
+#define GICBIS(reg, mask, bits) \
+ do { u32 data; \
+ GICREAD(reg, data); \
+ data &= ~(mask); \
+ data |= ((bits) & (mask)); \
+ GICWRITE((reg), data); \
+ } while (0)
+
+
+/* GIC Address Space */
+#define SHARED_SECTION_OFS 0x0000
+#define SHARED_SECTION_SIZE 0x8000
+#define VPE_LOCAL_SECTION_OFS 0x8000
+#define VPE_LOCAL_SECTION_SIZE 0x4000
+#define VPE_OTHER_SECTION_OFS 0xc000
+#define VPE_OTHER_SECTION_SIZE 0x4000
+#define USM_VISIBLE_SECTION_OFS 0x10000
+#define USM_VISIBLE_SECTION_SIZE 0x10000
+
+/* Register Map for Shared Section */
+
+#define GIC_SH_CONFIG_OFS 0x0000
+
+/* Shared Global Counter */
+#define GIC_SH_COUNTER_31_00_OFS 0x0010
+#define GIC_SH_COUNTER_63_32_OFS 0x0014
+#define GIC_SH_REVISIONID_OFS 0x0020
+
+/* Interrupt Polarity */
+#define GIC_SH_POL_31_0_OFS 0x0100
+#define GIC_SH_POL_63_32_OFS 0x0104
+#define GIC_SH_POL_95_64_OFS 0x0108
+#define GIC_SH_POL_127_96_OFS 0x010c
+#define GIC_SH_POL_159_128_OFS 0x0110
+#define GIC_SH_POL_191_160_OFS 0x0114
+#define GIC_SH_POL_223_192_OFS 0x0118
+#define GIC_SH_POL_255_224_OFS 0x011c
+
+/* Edge/Level Triggering */
+#define GIC_SH_TRIG_31_0_OFS 0x0180
+#define GIC_SH_TRIG_63_32_OFS 0x0184
+#define GIC_SH_TRIG_95_64_OFS 0x0188
+#define GIC_SH_TRIG_127_96_OFS 0x018c
+#define GIC_SH_TRIG_159_128_OFS 0x0190
+#define GIC_SH_TRIG_191_160_OFS 0x0194
+#define GIC_SH_TRIG_223_192_OFS 0x0198
+#define GIC_SH_TRIG_255_224_OFS 0x019c
+
+/* Dual Edge Triggering */
+#define GIC_SH_DUAL_31_0_OFS 0x0200
+#define GIC_SH_DUAL_63_32_OFS 0x0204
+#define GIC_SH_DUAL_95_64_OFS 0x0208
+#define GIC_SH_DUAL_127_96_OFS 0x020c
+#define GIC_SH_DUAL_159_128_OFS 0x0210
+#define GIC_SH_DUAL_191_160_OFS 0x0214
+#define GIC_SH_DUAL_223_192_OFS 0x0218
+#define GIC_SH_DUAL_255_224_OFS 0x021c
+
+/* Set/Clear corresponding bit in Edge Detect Register */
+#define GIC_SH_WEDGE_OFS 0x0280
+
+/* Reset Mask - Disables Interrupt */
+#define GIC_SH_RMASK_31_0_OFS 0x0300
+#define GIC_SH_RMASK_63_32_OFS 0x0304
+#define GIC_SH_RMASK_95_64_OFS 0x0308
+#define GIC_SH_RMASK_127_96_OFS 0x030c
+#define GIC_SH_RMASK_159_128_OFS 0x0310
+#define GIC_SH_RMASK_191_160_OFS 0x0314
+#define GIC_SH_RMASK_223_192_OFS 0x0318
+#define GIC_SH_RMASK_255_224_OFS 0x031c
+
+/* Set Mask (WO) - Enables Interrupt */
+#define GIC_SH_SMASK_31_0_OFS 0x0380
+#define GIC_SH_SMASK_63_32_OFS 0x0384
+#define GIC_SH_SMASK_95_64_OFS 0x0388
+#define GIC_SH_SMASK_127_96_OFS 0x038c
+#define GIC_SH_SMASK_159_128_OFS 0x0390
+#define GIC_SH_SMASK_191_160_OFS 0x0394
+#define GIC_SH_SMASK_223_192_OFS 0x0398
+#define GIC_SH_SMASK_255_224_OFS 0x039c
+
+/* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */
+#define GIC_SH_MASK_31_0_OFS 0x0400
+#define GIC_SH_MASK_63_32_OFS 0x0404
+#define GIC_SH_MASK_95_64_OFS 0x0408
+#define GIC_SH_MASK_127_96_OFS 0x040c
+#define GIC_SH_MASK_159_128_OFS 0x0410
+#define GIC_SH_MASK_191_160_OFS 0x0414
+#define GIC_SH_MASK_223_192_OFS 0x0418
+#define GIC_SH_MASK_255_224_OFS 0x041c
+
+/* Pending Global Interrupts (RO) */
+#define GIC_SH_PEND_31_0_OFS 0x0480
+#define GIC_SH_PEND_63_32_OFS 0x0484
+#define GIC_SH_PEND_95_64_OFS 0x0488
+#define GIC_SH_PEND_127_96_OFS 0x048c
+#define GIC_SH_PEND_159_128_OFS 0x0490
+#define GIC_SH_PEND_191_160_OFS 0x0494
+#define GIC_SH_PEND_223_192_OFS 0x0498
+#define GIC_SH_PEND_255_224_OFS 0x049c
+
+#define GIC_SH_INTR_MAP_TO_PIN_BASE_OFS 0x0500
+
+/* Maps Interrupt X to a Pin */
+#define GIC_SH_MAP_TO_PIN(intr) \
+ (GIC_SH_INTR_MAP_TO_PIN_BASE_OFS + (4 * intr))
+
+#define GIC_SH_INTR_MAP_TO_VPE_BASE_OFS 0x2000
+
+/* Maps Interrupt X to a VPE */
+#define GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe) \
+ (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + (((vpe) / 32) * 4))
+#define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
+
+/* Convert an interrupt number to a byte offset/bit for multi-word registers */
+#define GIC_INTR_OFS(intr) (((intr) / 32)*4)
+#define GIC_INTR_BIT(intr) ((intr) % 32)
+
+/* Polarity : Reset Value is always 0 */
+#define GIC_SH_SET_POLARITY_OFS 0x0100
+#define GIC_SET_POLARITY(intr, pol) \
+ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
+ GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+ (pol) << GIC_INTR_BIT(intr))
+
+/* Triggering : Reset Value is always 0 */
+#define GIC_SH_SET_TRIGGER_OFS 0x0180
+#define GIC_SET_TRIGGER(intr, trig) \
+ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
+ GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+ (trig) << GIC_INTR_BIT(intr))
+
+/* Mask manipulation */
+#define GIC_SH_SMASK_OFS 0x0380
+#define GIC_SET_INTR_MASK(intr) \
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + \
+ GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
+#define GIC_SH_RMASK_OFS 0x0300
+#define GIC_CLR_INTR_MASK(intr) \
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + \
+ GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
+
+/* Register Map for Local Section */
+#define GIC_VPE_CTL_OFS 0x0000
+#define GIC_VPE_PEND_OFS 0x0004
+#define GIC_VPE_MASK_OFS 0x0008
+#define GIC_VPE_RMASK_OFS 0x000c
+#define GIC_VPE_SMASK_OFS 0x0010
+#define GIC_VPE_WD_MAP_OFS 0x0040
+#define GIC_VPE_COMPARE_MAP_OFS 0x0044
+#define GIC_VPE_TIMER_MAP_OFS 0x0048
+#define GIC_VPE_PERFCTR_MAP_OFS 0x0050
+#define GIC_VPE_SWINT0_MAP_OFS 0x0054
+#define GIC_VPE_SWINT1_MAP_OFS 0x0058
+#define GIC_VPE_OTHER_ADDR_OFS 0x0080
+#define GIC_VP_IDENT_OFS 0x0088
+#define GIC_VPE_WD_CONFIG0_OFS 0x0090
+#define GIC_VPE_WD_COUNT0_OFS 0x0094
+#define GIC_VPE_WD_INITIAL0_OFS 0x0098
+#define GIC_VPE_COMPARE_LO_OFS 0x00a0
+#define GIC_VPE_COMPARE_HI_OFS 0x00a4
+
+#define GIC_VPE_EIC_SHADOW_SET_BASE 0x0100
+#define GIC_VPE_EIC_SS(intr) \
+ (GIC_VPE_EIC_SHADOW_SET_BASE + (4 * intr))
+
+#define GIC_VPE_EIC_VEC_BASE 0x0800
+#define GIC_VPE_EIC_VEC(intr) \
+ (GIC_VPE_EIC_VEC_BASE + (4 * intr))
+
+#define GIC_VPE_TENABLE_NMI_OFS 0x1000
+#define GIC_VPE_TENABLE_YQ_OFS 0x1004
+#define GIC_VPE_TENABLE_INT_31_0_OFS 0x1080
+#define GIC_VPE_TENABLE_INT_63_32_OFS 0x1084
+
+/* User Mode Visible Section Register Map */
+#define GIC_UMV_SH_COUNTER_31_00_OFS 0x0000
+#define GIC_UMV_SH_COUNTER_63_32_OFS 0x0004
+
+/* Masks */
+#define GIC_SH_CONFIG_COUNTSTOP_SHF 28
+#define GIC_SH_CONFIG_COUNTSTOP_MSK (MSK(1) << GIC_SH_CONFIG_COUNTSTOP_SHF)
+
+#define GIC_SH_CONFIG_COUNTBITS_SHF 24
+#define GIC_SH_CONFIG_COUNTBITS_MSK (MSK(4) << GIC_SH_CONFIG_COUNTBITS_SHF)
+
+#define GIC_SH_CONFIG_NUMINTRS_SHF 16
+#define GIC_SH_CONFIG_NUMINTRS_MSK (MSK(8) << GIC_SH_CONFIG_NUMINTRS_SHF)
+
+#define GIC_SH_CONFIG_NUMVPES_SHF 0
+#define GIC_SH_CONFIG_NUMVPES_MSK (MSK(8) << GIC_SH_CONFIG_NUMVPES_SHF)
+
+#define GIC_SH_WEDGE_SET(intr) (intr | (0x1 << 31))
+#define GIC_SH_WEDGE_CLR(intr) (intr & ~(0x1 << 31))
+
+#define GIC_MAP_TO_PIN_SHF 31
+#define GIC_MAP_TO_PIN_MSK (MSK(1) << GIC_MAP_TO_PIN_SHF)
+#define GIC_MAP_TO_NMI_SHF 30
+#define GIC_MAP_TO_NMI_MSK (MSK(1) << GIC_MAP_TO_NMI_SHF)
+#define GIC_MAP_TO_YQ_SHF 29
+#define GIC_MAP_TO_YQ_MSK (MSK(1) << GIC_MAP_TO_YQ_SHF)
+#define GIC_MAP_SHF 0
+#define GIC_MAP_MSK (MSK(6) << GIC_MAP_SHF)
+
+/* GIC_VPE_CTL Masks */
+#define GIC_VPE_CTL_PERFCNT_RTBL_SHF 2
+#define GIC_VPE_CTL_PERFCNT_RTBL_MSK (MSK(1) << GIC_VPE_CTL_PERFCNT_RTBL_SHF)
+#define GIC_VPE_CTL_TIMER_RTBL_SHF 1
+#define GIC_VPE_CTL_TIMER_RTBL_MSK (MSK(1) << GIC_VPE_CTL_TIMER_RTBL_SHF)
+#define GIC_VPE_CTL_EIC_MODE_SHF 0
+#define GIC_VPE_CTL_EIC_MODE_MSK (MSK(1) << GIC_VPE_CTL_EIC_MODE_SHF)
+
+/* GIC_VPE_PEND Masks */
+#define GIC_VPE_PEND_WD_SHF 0
+#define GIC_VPE_PEND_WD_MSK (MSK(1) << GIC_VPE_PEND_WD_SHF)
+#define GIC_VPE_PEND_CMP_SHF 1
+#define GIC_VPE_PEND_CMP_MSK (MSK(1) << GIC_VPE_PEND_CMP_SHF)
+#define GIC_VPE_PEND_TIMER_SHF 2
+#define GIC_VPE_PEND_TIMER_MSK (MSK(1) << GIC_VPE_PEND_TIMER_SHF)
+#define GIC_VPE_PEND_PERFCOUNT_SHF 3
+#define GIC_VPE_PEND_PERFCOUNT_MSK (MSK(1) << GIC_VPE_PEND_PERFCOUNT_SHF)
+#define GIC_VPE_PEND_SWINT0_SHF 4
+#define GIC_VPE_PEND_SWINT0_MSK (MSK(1) << GIC_VPE_PEND_SWINT0_SHF)
+#define GIC_VPE_PEND_SWINT1_SHF 5
+#define GIC_VPE_PEND_SWINT1_MSK (MSK(1) << GIC_VPE_PEND_SWINT1_SHF)
+
+/* GIC_VPE_RMASK Masks */
+#define GIC_VPE_RMASK_WD_SHF 0
+#define GIC_VPE_RMASK_WD_MSK (MSK(1) << GIC_VPE_RMASK_WD_SHF)
+#define GIC_VPE_RMASK_CMP_SHF 1
+#define GIC_VPE_RMASK_CMP_MSK (MSK(1) << GIC_VPE_RMASK_CMP_SHF)
+#define GIC_VPE_RMASK_TIMER_SHF 2
+#define GIC_VPE_RMASK_TIMER_MSK (MSK(1) << GIC_VPE_RMASK_TIMER_SHF)
+#define GIC_VPE_RMASK_PERFCNT_SHF 3
+#define GIC_VPE_RMASK_PERFCNT_MSK (MSK(1) << GIC_VPE_RMASK_PERFCNT_SHF)
+#define GIC_VPE_RMASK_SWINT0_SHF 4
+#define GIC_VPE_RMASK_SWINT0_MSK (MSK(1) << GIC_VPE_RMASK_SWINT0_SHF)
+#define GIC_VPE_RMASK_SWINT1_SHF 5
+#define GIC_VPE_RMASK_SWINT1_MSK (MSK(1) << GIC_VPE_RMASK_SWINT1_SHF)
+
+/* GIC_VPE_SMASK Masks */
+#define GIC_VPE_SMASK_WD_SHF 0
+#define GIC_VPE_SMASK_WD_MSK (MSK(1) << GIC_VPE_SMASK_WD_SHF)
+#define GIC_VPE_SMASK_CMP_SHF 1
+#define GIC_VPE_SMASK_CMP_MSK (MSK(1) << GIC_VPE_SMASK_CMP_SHF)
+#define GIC_VPE_SMASK_TIMER_SHF 2
+#define GIC_VPE_SMASK_TIMER_MSK (MSK(1) << GIC_VPE_SMASK_TIMER_SHF)
+#define GIC_VPE_SMASK_PERFCNT_SHF 3
+#define GIC_VPE_SMASK_PERFCNT_MSK (MSK(1) << GIC_VPE_SMASK_PERFCNT_SHF)
+#define GIC_VPE_SMASK_SWINT0_SHF 4
+#define GIC_VPE_SMASK_SWINT0_MSK (MSK(1) << GIC_VPE_SMASK_SWINT0_SHF)
+#define GIC_VPE_SMASK_SWINT1_SHF 5
+#define GIC_VPE_SMASK_SWINT1_MSK (MSK(1) << GIC_VPE_SMASK_SWINT1_SHF)
+
+/* GIC_VP_IDENT fields */
+#define GIC_VP_IDENT_VCNUM_SHF 0
+#define GIC_VP_IDENT_VCNUM_MSK (MSK(6) << GIC_VP_IDENT_VCNUM_SHF)
+
+/*
+ * Set the Mapping of Interrupt X to a VPE.
+ */
+#define GIC_SH_MAP_TO_VPE_SMASK(intr, vpe) \
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \
+ GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
+
+/*
+ * Interrupt Meta-data specification. The ipiflag helps
+ * in building ipi_map.
+ */
+struct gic_intr_map {
+ unsigned int cpunum; /* Directed to this CPU */
+#define GIC_UNUSED 0xdead /* Dummy data */
+ unsigned int pin; /* Directed to this Pin */
+ unsigned int polarity; /* Polarity : +/- */
+ unsigned int trigtype; /* Trigger : Edge/Levl */
+ unsigned int flags; /* Misc flags */
+#define GIC_FLAG_TRANSPARENT 0x01
+#define GIC_FLAG_PERCPU 0x04
+};
+
+/*
+ * This is only used in EIC mode. This helps to figure out which
+ * shared interrupts we need to process when we get a vector interrupt.
+ */
+struct gic_shared_intr_map {
+ unsigned int shared_intr_flags;
+ unsigned int shared_intr_list[NR_CPUS];
+ unsigned int local_intr_mask;
+};
+
+/* GIC nomenclature for Core Interrupt Pins. */
+#define GIC_CPU_INT0 0 /* Core Interrupt 2 */
+#define GIC_CPU_INT1 1 /* . */
+#define GIC_CPU_INT2 2 /* . */
+#define GIC_CPU_INT3 3 /* . */
+#define GIC_CPU_INT4 4 /* . */
+#define GIC_CPU_INT5 5 /* Core Interrupt 7 */
+
+/* Local GIC interrupts. */
+#define GIC_INT_TMR (GIC_CPU_INT5)
+#define GIC_INT_PERFCTR (GIC_CPU_INT5)
+
+/* Add 2 to convert GIC CPU pin to core interrupt */
+#define GIC_CPU_PIN_OFFSET 2
+
+#ifdef CONFIG_MIPS_TC3262_1004K
+/* EN7516/7527/7528 GIC pins shifted by 1, pin_offset must be 0 */
+#define GIC_CPU_TO_VEC_OFFSET (1)
+#else
+/* Add 2 to convert non-EIC hardware interrupt to EIC vector number. */
+#define GIC_CPU_TO_VEC_OFFSET (2)
+#endif
+
+/* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */
+#define GIC_PIN_TO_VEC_OFFSET (1)
+
+#include <linux/irq.h>
+
+extern unsigned int gic_present;
+extern unsigned int gic_irq_base;
+extern unsigned long _gic_base;
+
+void gic_init(unsigned long gic_base_addr,
+ unsigned long gic_addrspace_size,
+ const struct gic_intr_map *intrmap,
+ unsigned int intrmap_size,
+ unsigned int irqbase);
+
+int gic_get_usm_range(struct resource *gic_usm_res);
+unsigned gic_read_local_vp_id(void);
+void gic_irq_dispatch(void);
+void gic_platform_init(int irqs, struct irq_chip *irq_controller);
+
+#endif /* _ASM_GICREGS_H */
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
index 64f2500d891b..279b6d14ffeb 100644
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -25,9 +25,6 @@
#include <asm/cpu-features.h>
#include <asm/kmap_types.h>
-/* undef for production */
-#define HIGHMEM_DEBUG 1
-
/* declarations for highmem.c */
extern unsigned long highstart_pfn, highend_pfn;
@@ -38,7 +35,12 @@ extern pte_t *pkmap_page_table;
* easily, subsequent pte tables have to be allocated in one physical
* chunk of RAM.
*/
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#define LAST_PKMAP 512
+#else
#define LAST_PKMAP 1024
+#endif
+
#define LAST_PKMAP_MASK (LAST_PKMAP-1)
#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 5dfae80264b9..408d8722ae1c 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -297,7 +297,7 @@ static inline void iounmap(const volatile void __iomem *addr)
#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT)
#define war_io_reorder_wmb() wmb()
#else
-#define war_io_reorder_wmb() do { } while (0)
+#define war_io_reorder_wmb() barrier()
#endif
#define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \
@@ -367,6 +367,8 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \
BUG(); \
} \
\
+ /* prevent prefetching of coherent DMA data prematurely */ \
+ rmb(); \
return pfx##ioswab##bwlq(__mem, __val); \
}
diff --git a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
index 21eae03d752a..c3395fa97c3f 100644
--- a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
@@ -35,7 +35,6 @@
#define cpu_has_vtag_icache 0
#define cpu_has_ic_fills_f_dc 0
#define cpu_has_pindexed_dcache 0
-#define cpu_has_local_ebase 0
#define cpu_icache_snoops_remote_store 1
#define cpu_has_mips_4 0
#define cpu_has_mips_5 0
diff --git a/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
index 89328a3d44d8..f5cb3301e0ce 100644
--- a/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
@@ -42,7 +42,6 @@
#define cpu_has_vint 0
#define cpu_has_vtag_icache 0
#define cpu_has_watch 1
-#define cpu_has_local_ebase 0
#ifdef CONFIG_CPU_LOONGSON3
#define cpu_has_wsbh 1
diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
index c68c0cc879c6..d0ae5d55413b 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson.h
@@ -26,7 +26,7 @@ extern void mach_prepare_shutdown(void);
/* environment arguments from bootloader */
extern u32 cpu_clock_freq;
extern u32 memsize, highmemsize;
-extern struct plat_smp_ops loongson3_smp_ops;
+extern const struct plat_smp_ops loongson3_smp_ops;
/* loongson-specific command line, env and memory initialization */
extern void __init prom_init_memory(void);
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index df78b2ca70eb..3ff9bbe0de07 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1612,6 +1612,9 @@ do { \
#define read_c0_taglo() __read_32bit_c0_register($28, 0)
#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val)
+#define read_c0_idatalo() __read_32bit_c0_register($28, 1)
+#define write_c0_idatalo(val) __write_32bit_c0_register($28, 1, val)
+
#define read_c0_dtaglo() __read_32bit_c0_register($28, 2)
#define write_c0_dtaglo(val) __write_32bit_c0_register($28, 2, val)
@@ -1624,6 +1627,9 @@ do { \
#define read_c0_taghi() __read_32bit_c0_register($29, 0)
#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val)
+#define read_c0_idatahi() __read_32bit_c0_register($29, 1)
+#define write_c0_idatahi(val) __write_32bit_c0_register($29, 1, val)
+
#define read_c0_errorepc() __read_ulong_c0_register($30, 0)
#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val)
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 702c273e67a9..1d4f3b37cefe 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -11,6 +11,11 @@ struct mod_arch_specific {
const struct exception_table_entry *dbe_start;
const struct exception_table_entry *dbe_end;
struct mips_hi16 *r_mips_hi16_list;
+
+ void *phys_plt_tbl;
+ void *virt_plt_tbl;
+ unsigned int phys_plt_offset;
+ unsigned int virt_plt_offset;
};
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h
index be52c2125d71..f1a301765066 100644
--- a/arch/mips/include/asm/netlogic/common.h
+++ b/arch/mips/include/asm/netlogic/common.h
@@ -84,7 +84,7 @@ nlm_set_nmi_handler(void *handler)
*/
void nlm_init_boot_cpu(void);
unsigned int nlm_get_cpu_frequency(void);
-extern struct plat_smp_ops nlm_smp_ops;
+extern const struct plat_smp_ops nlm_smp_ops;
extern char nlm_reset_entry[], nlm_reset_entry_end[];
/* SWIOTLB */
diff --git a/arch/mips/include/asm/pbus-timer.h b/arch/mips/include/asm/pbus-timer.h
new file mode 100644
index 000000000000..0fe0f7f7e6e6
--- /dev/null
+++ b/arch/mips/include/asm/pbus-timer.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_PBUS_TIMER_H
+#define _ASM_PBUS_TIMER_H
+
+enum pbus_timer_mode {
+ PBUS_TIMER_MODE_INTERVAL,
+ PBUS_TIMER_MODE_PERIODIC,
+ PBUS_TIMER_MODE_WATCHDOG
+};
+
+static bool pbus_timer_enable(const unsigned int n,
+ const unsigned int interval_ms,
+ const enum pbus_timer_mode mode);
+
+static void pbus_timer_disable(const unsigned int n);
+
+static void pbus_timer_restart(const unsigned int n);
+
+static void pbus_timer_int_ack(const unsigned int n);
+
+static unsigned int pbus_timer_get(const unsigned int n);
+
+#include <pbus-timer.h>
+
+#endif /* _ASM_PBUS_TIMER_H */
+
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 30d1129d8624..01e2a984922e 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -39,7 +39,6 @@ struct pci_controller {
unsigned long io_offset;
unsigned long io_map_base;
struct resource *busn_resource;
- unsigned long busn_offset;
#ifndef CONFIG_PCI_DOMAINS_GENERIC
unsigned int index;
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 667ca3c467b7..7f48c2b311c4 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -48,58 +48,14 @@ extern void (*r4k_blast_icache)(void);
: \
: "i" (op), "R" (*(unsigned char *)(addr)))
-#ifdef CONFIG_MIPS_MT
-
-#define __iflush_prologue \
- unsigned long redundance; \
- extern int mt_n_iflushes; \
- for (redundance = 0; redundance < mt_n_iflushes; redundance++) {
-
-#define __iflush_epilogue \
- }
-
-#define __dflush_prologue \
- unsigned long redundance; \
- extern int mt_n_dflushes; \
- for (redundance = 0; redundance < mt_n_dflushes; redundance++) {
-
-#define __dflush_epilogue \
- }
-
-#define __inv_dflush_prologue __dflush_prologue
-#define __inv_dflush_epilogue __dflush_epilogue
-#define __sflush_prologue {
-#define __sflush_epilogue }
-#define __inv_sflush_prologue __sflush_prologue
-#define __inv_sflush_epilogue __sflush_epilogue
-
-#else /* CONFIG_MIPS_MT */
-
-#define __iflush_prologue {
-#define __iflush_epilogue }
-#define __dflush_prologue {
-#define __dflush_epilogue }
-#define __inv_dflush_prologue {
-#define __inv_dflush_epilogue }
-#define __sflush_prologue {
-#define __sflush_epilogue }
-#define __inv_sflush_prologue {
-#define __inv_sflush_epilogue }
-
-#endif /* CONFIG_MIPS_MT */
-
static inline void flush_icache_line_indexed(unsigned long addr)
{
- __iflush_prologue
cache_op(Index_Invalidate_I, addr);
- __iflush_epilogue
}
static inline void flush_dcache_line_indexed(unsigned long addr)
{
- __dflush_prologue
cache_op(Index_Writeback_Inv_D, addr);
- __dflush_epilogue
}
static inline void flush_scache_line_indexed(unsigned long addr)
@@ -109,31 +65,27 @@ static inline void flush_scache_line_indexed(unsigned long addr)
static inline void flush_icache_line(unsigned long addr)
{
- __iflush_prologue
switch (boot_cpu_type()) {
+#if defined(CONFIG_CPU_LOONGSON2)
case CPU_LOONGSON2:
cache_op(Hit_Invalidate_I_Loongson2, addr);
break;
+#endif
default:
cache_op(Hit_Invalidate_I, addr);
break;
}
- __iflush_epilogue
}
static inline void flush_dcache_line(unsigned long addr)
{
- __dflush_prologue
cache_op(Hit_Writeback_Inv_D, addr);
- __dflush_epilogue
}
static inline void invalidate_dcache_line(unsigned long addr)
{
- __dflush_prologue
cache_op(Hit_Invalidate_D, addr);
- __dflush_epilogue
}
static inline void invalidate_scache_line(unsigned long addr)
@@ -179,9 +131,11 @@ static inline void flush_scache_line(unsigned long addr)
static inline void protected_flush_icache_line(unsigned long addr)
{
switch (boot_cpu_type()) {
+#if defined(CONFIG_CPU_LOONGSON2)
case CPU_LOONGSON2:
protected_cache_op(Hit_Invalidate_I_Loongson2, addr);
break;
+#endif
default:
#ifdef CONFIG_EVA
@@ -569,13 +523,9 @@ static inline void extra##blast_##pfx##cache##lsize(void) \
current_cpu_data.desc.waybit; \
unsigned long ws, addr; \
\
- __##pfx##flush_prologue \
- \
for (ws = 0; ws < ws_end; ws += ws_inc) \
for (addr = start; addr < end; addr += lsize * 32) \
cache##lsize##_unroll32(addr|ws, indexop); \
- \
- __##pfx##flush_epilogue \
} \
\
static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
@@ -583,14 +533,10 @@ static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
unsigned long start = page; \
unsigned long end = page + PAGE_SIZE; \
\
- __##pfx##flush_prologue \
- \
do { \
cache##lsize##_unroll32(start, hitop); \
start += lsize * 32; \
} while (start < end); \
- \
- __##pfx##flush_epilogue \
} \
\
static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
@@ -603,13 +549,9 @@ static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long
current_cpu_data.desc.waybit; \
unsigned long ws, addr; \
\
- __##pfx##flush_prologue \
- \
for (ws = 0; ws < ws_end; ws += ws_inc) \
for (addr = start; addr < end; addr += lsize * 32) \
cache##lsize##_unroll32(addr|ws, indexop); \
- \
- __##pfx##flush_epilogue \
}
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
@@ -639,14 +581,10 @@ static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \
unsigned long start = page; \
unsigned long end = page + PAGE_SIZE; \
\
- __##pfx##flush_prologue \
- \
do { \
cache##lsize##_unroll32_user(start, hitop); \
start += lsize * 32; \
} while (start < end); \
- \
- __##pfx##flush_epilogue \
}
__BUILD_BLAST_USER_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D,
@@ -665,19 +603,47 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start,
unsigned long end) \
{ \
unsigned long lsize = cpu_##desc##_line_size(); \
+ unsigned long lsize_2 = lsize * 2; \
+ unsigned long lsize_3 = lsize * 3; \
+ unsigned long lsize_4 = lsize * 4; \
+ unsigned long lsize_5 = lsize * 5; \
+ unsigned long lsize_6 = lsize * 6; \
+ unsigned long lsize_7 = lsize * 7; \
+ unsigned long lsize_8 = lsize * 8; \
unsigned long addr = start & ~(lsize - 1); \
- unsigned long aend = (end - 1) & ~(lsize - 1); \
+ unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \
+ int lines = (aend - addr) / lsize; \
\
- __##pfx##flush_prologue \
+ while (lines >= 8) { \
+ prot##cache_op(hitop, addr); \
+ prot##cache_op(hitop, addr + lsize); \
+ prot##cache_op(hitop, addr + lsize_2); \
+ prot##cache_op(hitop, addr + lsize_3); \
+ prot##cache_op(hitop, addr + lsize_4); \
+ prot##cache_op(hitop, addr + lsize_5); \
+ prot##cache_op(hitop, addr + lsize_6); \
+ prot##cache_op(hitop, addr + lsize_7); \
+ addr += lsize_8; \
+ lines -= 8; \
+ } \
+ \
+ if (lines & 0x4) { \
+ prot##cache_op(hitop, addr); \
+ prot##cache_op(hitop, addr + lsize); \
+ prot##cache_op(hitop, addr + lsize_2); \
+ prot##cache_op(hitop, addr + lsize_3); \
+ addr += lsize_4; \
+ } \
\
- while (1) { \
+ if (lines & 0x2) { \
prot##cache_op(hitop, addr); \
- if (addr == aend) \
- break; \
- addr += lsize; \
+ prot##cache_op(hitop, addr + lsize); \
+ addr += lsize_2; \
} \
\
- __##pfx##flush_epilogue \
+ if (lines & 0x1) { \
+ prot##cache_op(hitop, addr); \
+ } \
}
#ifndef CONFIG_EVA
@@ -695,8 +661,6 @@ static inline void protected_blast_##pfx##cache##_range(unsigned long start,\
unsigned long addr = start & ~(lsize - 1); \
unsigned long aend = (end - 1) & ~(lsize - 1); \
\
- __##pfx##flush_prologue \
- \
if (segment_eq(get_fs(), USER_DS)) { \
while (1) { \
protected_cachee_op(hitop, addr); \
@@ -713,7 +677,6 @@ static inline void protected_blast_##pfx##cache##_range(unsigned long start,\
} \
\
} \
- __##pfx##flush_epilogue \
}
__BUILD_PROT_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D)
diff --git a/arch/mips/include/asm/rt2880/cpu-feature-overrides.h b/arch/mips/include/asm/rt2880/cpu-feature-overrides.h
new file mode 100644
index 000000000000..6db2ecfaff15
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/cpu-feature-overrides.h
@@ -0,0 +1,83 @@
+/*
+ * Ralink specific CPU feature overrides
+ *
+ * This file was derived from: include/asm-mips/cpu-features.h
+ * Copyright (C) 2003, 2004 Ralf Baechle
+ * Copyright (C) 2004 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MACH_MIPS_RT2880_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_MIPS_RT2880_CPU_FEATURE_OVERRIDES_H
+
+/* CPU options */
+#define cpu_has_tlb 1
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 1
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 0
+#define cpu_has_32fpr 0
+#define cpu_has_counter 1
+
+#define cpu_has_watch 1
+#define cpu_has_divec 1
+#define cpu_has_vce 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_cache_cdex_s 0
+#define cpu_has_mcheck 1
+#define cpu_has_ejtag 1
+#define cpu_has_nofpuex 0
+
+#define cpu_has_llsc 1
+#define cpu_has_inclusive_pcaches 0
+#define cpu_has_prefetch 1
+//#define cpu_has_vint 1 // do not override, depend from CONFIG_CPU_MIPSR2_IRQ_VI
+#define cpu_has_veic 0
+#define cpu_has_userlocal 1
+#define cpu_has_perf_cntr_intr_bit 1
+#define cpu_has_rixi 0
+
+/* CPU ases */
+#define cpu_has_mips16 1
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+#define cpu_has_dsp 1
+#if defined(CONFIG_RALINK_MT7621)
+#define cpu_has_mipsmt 1
+#else
+#define cpu_has_mipsmt 0
+#endif
+#define cpu_has_dsp2 0
+#define cpu_has_vz 0
+
+/* CPU ISA level */
+#define cpu_has_mips_2 1
+#define cpu_has_mips_3 0
+#define cpu_has_mips_4 0
+#define cpu_has_mips_5 0
+#define cpu_has_mips32r1 1
+#define cpu_has_mips32r2 1
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
+#define cpu_has_mips32r6 0
+#define cpu_has_mips64r6 0
+
+#define cpu_has_64bits 0
+#define cpu_has_64bit_zero_reg 0
+#define cpu_has_64bit_gp_regs 0
+#define cpu_has_64bit_addresses 0
+
+/* CPU cache info */
+#define cpu_has_vtag_icache 0
+#define cpu_has_ic_fills_f_dc 0
+#define cpu_has_dc_aliases 0
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 32
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/eureka_ep430.h b/arch/mips/include/asm/rt2880/eureka_ep430.h
new file mode 100644
index 000000000000..aab29c961509
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/eureka_ep430.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ */
+
+#ifndef __ASM_MACH_MIPS_RT2880_EUREKA_EP430_H
+#define __ASM_MACH_MIPS_RT2880_EUREKA_EP430_H
+
+#include <asm/addrspace.h> /* for KSEG1ADDR() */
+#include <asm/rt2880/rt_mmap.h>
+
+#define RALINK_PCI_PCICFG_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0000)
+#define RALINK_PCI_PCIRAW_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0004)
+#define RALINK_PCI_PCIINT_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0008)
+#define RALINK_PCI_PCIMSK_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x000C)
+#define RALINK_PCI_IMBASEBAR1_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x001C)
+#define RALINK_PCI_PCR_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0020)
+#define RALINK_PCI_PCR_DATA *(volatile u32 *)(RALINK_PCI_BASE + 0x0024)
+#define RALINK_PCI_MEMBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x0028)
+#define RALINK_PCI_IOBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x002C)
+#define RALINK_PCI_ARBCTL *(volatile u32 *)(RALINK_PCI_BASE + 0x0080)
+
+#if defined(CONFIG_RALINK_MT7628)
+
+#define RT6855_PCIE0_OFFSET 0x2000
+
+#define RALINK_PCI0_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010)
+#define RALINK_PCI0_BAR1SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0014)
+#define RALINK_PCI0_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018)
+#define RALINK_PCI0_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030)
+#define RALINK_PCI0_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034)
+#define RALINK_PCI0_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038)
+#define RALINK_PCI0_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050)
+#define RALINK_PCI0_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060)
+#define RALINK_PCI0_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064)
+
+#define RALINK_PCIEPHY_P0_CTL_OFFSET (RALINK_PCI_BASE + 0x9000)
+
+#elif defined(CONFIG_RALINK_MT7621)
+
+#define RT6855_PCIE0_OFFSET 0x2000
+#define RT6855_PCIE1_OFFSET 0x3000
+#define RT6855_PCIE2_OFFSET 0x4000
+
+#define RALINK_PCI0_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010)
+#define RALINK_PCI0_BAR1SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0014)
+#define RALINK_PCI0_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018)
+#define RALINK_PCI0_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030)
+#define RALINK_PCI0_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034)
+#define RALINK_PCI0_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038)
+#define RALINK_PCI0_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050)
+#define RALINK_PCI0_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060)
+#define RALINK_PCI0_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064)
+
+#define RALINK_PCI1_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0010)
+#define RALINK_PCI1_BAR1SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0014)
+#define RALINK_PCI1_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0018)
+#define RALINK_PCI1_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0030)
+#define RALINK_PCI1_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0034)
+#define RALINK_PCI1_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0038)
+#define RALINK_PCI1_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0050)
+#define RALINK_PCI1_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0060)
+#define RALINK_PCI1_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0064)
+
+#define RALINK_PCI2_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0010)
+#define RALINK_PCI2_BAR1SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0014)
+#define RALINK_PCI2_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0018)
+#define RALINK_PCI2_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0030)
+#define RALINK_PCI2_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0034)
+#define RALINK_PCI2_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0038)
+#define RALINK_PCI2_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0050)
+#define RALINK_PCI2_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0060)
+#define RALINK_PCI2_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0064)
+
+#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000)
+#define RALINK_PCIEPHY_P2_CTL_OFFSET (RALINK_PCI_BASE + 0xA000)
+
+#elif defined(CONFIG_ECONET_EN75XX_MP)
+
+/* pci_en75xx.c */
+
+#else
+#error "Ralink chip undefined for PCI MEM map"
+#endif
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/generic.h b/arch/mips/include/asm/rt2880/generic.h
new file mode 100644
index 000000000000..12cd082cc335
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/generic.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2001 Palmchip Corporation. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Defines of the Palmchip boards specific address-MAP, registers, etc.
+ */
+#ifndef __ASM_MACH_MIPS_RT2880_GENERIC_H
+#define __ASM_MACH_MIPS_RT2880_GENERIC_H
+
+#include <asm/addrspace.h>
+#include <asm/byteorder.h>
+#include <asm/rt2880/rt_mmap.h>
+
+/*
+ * Reset register.
+ */
+#define SOFTRES_REG (KSEG1ADDR(RALINK_SYSCTL_BASE+0x34))
+#define GORESET (0x1)
+
+/*
+ * Power-off register
+ */
+#define POWER_DIR_REG (KSEG1ADDR(RALINK_PIO_BASE+0x24))
+#define POWER_DIR_OUTPUT (0x80) /* GPIO 7 */
+#define POWER_POL_REG (KSEG1ADDR(RALINK_PIO_BASE+0x28))
+#define POWEROFF_REG (KSEG1ADDR(RALINK_PIO_BASE+0x20))
+#define POWEROFF (0x0) /* drive low */
+
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/irq.h b/arch/mips/include/asm/rt2880/irq.h
new file mode 100644
index 000000000000..036ec821ce0e
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/irq.h
@@ -0,0 +1,19 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_MIPS_RT2880_IRQ_H
+#define __ASM_MACH_MIPS_RT2880_IRQ_H
+
+#define MIPS_CPU_IRQ_BASE 0
+
+#include <asm/rt2880/surfboardint.h>
+
+#define NR_IRQS (SURFBOARDINT_END + 1)
+
+#include_next <irq.h>
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/pbus-timer.h b/arch/mips/include/asm/rt2880/pbus-timer.h
new file mode 100644
index 000000000000..d3eda497c31f
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/pbus-timer.h
@@ -0,0 +1,189 @@
+#ifndef __ASM_MACH_RALINK_PBUS_TIMER_H
+#define __ASM_MACH_RALINK_PBUS_TIMER_H
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <asm/rt2880/rt_mmap.h>
+
+#define RSTSTAT (RALINK_SYSCTL_BASE + 0x38)
+
+#define RSTSTAT_WDT2SYSRST_EN (1U << 31)
+#define RSTSTAT_WDT2RSTO_EN (1U << 30)
+#define RSTSTAT_SWSYSRST (1U << 2)
+#define RSTSTAT_WDRST (1U << 1)
+
+#define RSTSTAT_WDT_EN \
+ (RSTSTAT_WDT2SYSRST_EN | \
+ RSTSTAT_WDT2RSTO_EN)
+
+#define RSTSTAT_RST_STATE_MASK \
+ (RSTSTAT_SWSYSRST | \
+ RSTSTAT_WDRST)
+
+#define PBUS_TIMER_0 (0)
+#define PBUS_TIMER_1 (1)
+#define PBUS_TIMER_2 (2)
+
+#define PBUS_TIMER_WATCHDOG (PBUS_TIMER_1)
+
+#define PBUS_TIMER_0_IRQ (SURFBOARDINT_TIMER0)
+#define PBUS_TIMER_1_IRQ (SURFBOARDINT_WDG)
+#define PBUS_TIMER_2_IRQ (SURFBOARDINT_TIMER1)
+
+#define PBUS_TIMER_GLB (RALINK_TIMER_BASE + 0x00)
+#define PBUS_TIMER_GLB_RST_SHIFT (8)
+#define PBUS_TIMER_GLB_INT_SHIFT (0)
+
+#define PBUS_TIMER_GLB_RST(n) \
+ (1U << ((n) + PBUS_TIMER_GLB_RST_SHIFT))
+#define PBUS_TIMER_GLB_INT_ACK(n) \
+ (1U << ((n) + PBUS_TIMER_GLB_INT_SHIFT))
+
+#define PBUS_TIMER_GLB_RST_MASK \
+ (PBUS_TIMER_GLB_RST(PBUS_TIMER_0) | \
+ PBUS_TIMER_GLB_RST(PBUS_TIMER_1) | \
+ PBUS_TIMER_GLB_RST(PBUS_TIMER_2))
+
+#define PBUS_TIMER_GLB_INT_ACK_MASK \
+ (PBUS_TIMER_GLB_INT_ACK(PBUS_TIMER_0) | \
+ PBUS_TIMER_GLB_INT_ACK(PBUS_TIMER_1) | \
+ PBUS_TIMER_GLB_INT_ACK(PBUS_TIMER_2))
+
+#define PBUS_TIMER_CTL(n) \
+ ((RALINK_TIMER_BASE) + 0x10 * (n) + 0x10)
+
+#define PBUS_TIMER_LMT(n) \
+ ((RALINK_TIMER_BASE) + 0x10 * (n) + 0x14)
+
+#define PBUS_TIMER_VAL(n) \
+ ((RALINK_TIMER_BASE) + 0x10 * (n) + 0x18)
+
+#define PBUS_TIMER_SCALE_MS (1000)
+
+#define PBUS_TIMER_CTL_PRES_MASK (0xffff0000)
+#define PBUS_TIMER_CTL_PRES(scale) \
+ (((scale) << 16) & PBUS_TIMER_CTL_PRES_MASK)
+#define PBUS_TIMER_CTL_PRES_GET(ctl) \
+ (((ctl) & PBUS_TIMER_CTL_PRES_MASK) >> 16)
+
+#define PBUS_TIMER_CTL_EN (1U << 7)
+#define PBUS_TIMER_CTL_AL (1U << 4)
+
+static inline void
+pbus_timer_w32(const u32 reg, const u32 val)
+{
+ __raw_writel(val, (void __iomem *)(unsigned long)reg);
+}
+
+static inline u32
+pbus_timer_r32(const u32 reg)
+{
+ return __raw_readl((void __iomem *)(unsigned long)reg);
+}
+
+static inline bool
+pbus_timer_enable(const unsigned int n,
+ const unsigned int interval_ms,
+ const enum pbus_timer_mode mode)
+{
+ const u32 ctl_reg = PBUS_TIMER_CTL(n);
+ u32 limit = interval_ms;
+ u32 scale = 1;
+ u32 ctl;
+
+ if (mode == PBUS_TIMER_MODE_WATCHDOG) {
+ u32 val;
+
+ /* enable a watchdog function for a timer
+ * that does not support it
+ */
+ if (n != PBUS_TIMER_WATCHDOG)
+ return false;
+
+ val = pbus_timer_r32(RSTSTAT);
+
+ val &= ~RSTSTAT_RST_STATE_MASK;
+ val |= RSTSTAT_WDT_EN;
+ pbus_timer_w32(RSTSTAT, val);
+ } else {
+ /* use a watchdog timer as an interval or periodic timer
+ */
+ if (n == PBUS_TIMER_WATCHDOG) {
+ u32 val = pbus_timer_r32(RSTSTAT);
+
+ val &= ~RSTSTAT_RST_STATE_MASK;
+ val &= ~RSTSTAT_WDT_EN;
+ pbus_timer_w32(RSTSTAT, val);
+ }
+ }
+
+ while (limit > U16_MAX) {
+ scale <<= 1;
+ limit >>= 1;
+
+ /* an interval is too large */
+ if (PBUS_TIMER_SCALE_MS * scale > U16_MAX)
+ return false;
+ }
+
+ pbus_timer_w32(PBUS_TIMER_LMT(n), limit);
+
+ ctl = pbus_timer_r32(ctl_reg);
+
+ ctl &= PBUS_TIMER_CTL_PRES_MASK;
+ ctl |= PBUS_TIMER_CTL_PRES(PBUS_TIMER_SCALE_MS * scale);
+ ctl |= PBUS_TIMER_CTL_EN;
+
+ if (mode == PBUS_TIMER_MODE_PERIODIC)
+ ctl |= PBUS_TIMER_CTL_AL;
+ else
+ ctl &= ~PBUS_TIMER_CTL_AL;
+
+ pbus_timer_w32(ctl_reg, ctl);
+
+ return true;
+}
+
+static inline void
+pbus_timer_disable(const unsigned int n)
+{
+ const u32 ctl_reg = PBUS_TIMER_CTL(n);
+ const u32 ctl = pbus_timer_r32(ctl_reg);
+
+ pbus_timer_w32(ctl_reg, ctl & ~PBUS_TIMER_CTL_EN);
+}
+
+static inline void
+pbus_timer_restart(const unsigned int n)
+{
+ u32 glb = pbus_timer_r32(PBUS_TIMER_GLB);
+
+ glb &= ~PBUS_TIMER_GLB_RST_MASK;
+ glb &= ~PBUS_TIMER_GLB_INT_ACK_MASK;
+ glb |= PBUS_TIMER_GLB_RST(n);
+ pbus_timer_w32(PBUS_TIMER_GLB, glb);
+}
+
+static inline void
+pbus_timer_int_ack(const unsigned int n)
+{
+ u32 glb = pbus_timer_r32(PBUS_TIMER_GLB);
+
+ glb &= ~PBUS_TIMER_GLB_RST_MASK;
+ glb &= ~PBUS_TIMER_GLB_INT_ACK_MASK;
+ glb |= PBUS_TIMER_GLB_INT_ACK(n);
+ pbus_timer_w32(PBUS_TIMER_GLB, glb);
+}
+
+static inline unsigned int
+pbus_timer_get(const unsigned int n)
+{
+ const u32 val = pbus_timer_r32(PBUS_TIMER_VAL(n));
+ const u32 ctl = pbus_timer_r32(PBUS_TIMER_CTL(n));
+ const u32 pres = PBUS_TIMER_CTL_PRES_GET(ctl);
+
+ return val * (pres / PBUS_TIMER_SCALE_MS);
+}
+
+#endif /* __ASM_MACH_RALINK_PBUS_TIMER_H */
+
diff --git a/arch/mips/include/asm/rt2880/prom.h b/arch/mips/include/asm/rt2880/prom.h
new file mode 100644
index 000000000000..ca6e214b2c3f
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/prom.h
@@ -0,0 +1,37 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * MIPS boards bootprom interface for the Linux kernel.
+ *
+ */
+
+#ifndef _MIPS_PROM_H
+#define _MIPS_PROM_H
+
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *name);
+extern void prom_printf(char *fmt, ...);
+extern void prom_init_printf(int tty_no);
+extern void prom_init_cmdline(void);
+extern void prom_meminit(void);
+extern void prom_free_prom_memory(void);
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/rt_mmap.h b/arch/mips/include/asm/rt2880/rt_mmap.h
new file mode 100644
index 000000000000..cc12625858a7
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/rt_mmap.h
@@ -0,0 +1,382 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * register definition for Ralink RT-series SoC
+ *
+ * Copyright 2007 Ralink Inc.
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ */
+
+#ifndef __ASM_MACH_MIPS_RT2880_RT_MMAP_H
+#define __ASM_MACH_MIPS_RT2880_RT_MMAP_H
+
+#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
+#define sysRegRead(phys) (*(volatile unsigned int *)PHYS_TO_K1(phys))
+#define sysRegWrite(phys, val) ((*(volatile unsigned int *)PHYS_TO_K1(phys)) = (val))
+
+#if defined(CONFIG_RALINK_MT7621)
+
+#define RALINK_SYSCTL_BASE 0xBE000000
+#define RALINK_TIMER_BASE 0xBE000100
+#define RALINK_INTCL_BASE 0xBE000200
+#define RALINK_RBUS_MATRIXCTL_BASE 0xBE000400
+#define RALINK_MIPS_CNT_BASE 0x1E000500
+#define RALINK_PIO_BASE 0xBE000600
+#define RALINK_SPDIF_BASE 0xBE000700
+#define RALINK_I2C_BASE 0xBE000900
+#define RALINK_I2S_BASE 0xBE000A00
+#define RALINK_SPI_BASE 0xBE000B00
+#define RALINK_UART_LITE1_BASE 0x1E000C00
+#define RALINK_UART_LITE_BASE RALINK_UART_LITE1_BASE
+#define RALINK_UART_LITE2_BASE 0x1E000D00
+#define RALINK_UART_BASE RALINK_UART_LITE2_BASE
+#define RALINK_UART_LITE3_BASE 0x1E000E00
+#define RALINK_ANA_CTRL_BASE 0xBE000F00
+#define RALINK_PCM_BASE 0xBE002000
+#define RALINK_GDMA_BASE 0xBE002800
+#define RALINK_NAND_CTRL_BASE 0xBE003000
+#define RALINK_NANDECC_CTRL_BASE 0xBE003800
+#define RALINK_CRYPTO_ENGINE_BASE 0xBE004000
+#define RALINK_MEMCTRL_BASE 0xBE005000
+#define RALINK_EXT_MC_ARB_BASE 0xBE006000
+#define RALINK_HS_DMA_BASE 0xBE007000
+#define RALINK_FRAME_ENGINE_BASE 0xBE100000
+#define RALINK_PPE_BASE 0xBE100C00
+#define RALINK_ETH_SW_BASE 0xBE110000
+#define RALINK_ROM_BASE 0xBE118000
+#define RALINK_MSDC_BASE 0xBE130000
+#define RALINK_PCI_BASE 0xBE140000
+#define RALINK_USB_HOST_BASE 0x1E1C0000
+#define RALINK_USB_HOST_SIZE 0x00004000
+#define RALINK_USB_IPPC_BASE 0x1E1D0700
+#define RALINK_XHCI_HOST_BASE 0xBE1C0000
+#define RALINK_XHCI_UPHY_BASE 0xBE1D0000
+#define RALINK_11N_MAC_BASE 0xBE180000 // Unused
+
+#define RALINK_MCNT_CFG 0xBE000500
+#define RALINK_COMPARE 0xBE000504
+#define RALINK_COUNT 0xBE000508
+
+// GIC
+#define RALINK_GIC_BASE 0x1FBC0000
+#define RALINK_GIC_ADDRSPACE_SZ 0x20000
+
+// CPC
+#define RALINK_CPC_BASE 0x1FBF0000
+#define RALINK_CPC_ADDRSPACE_SZ 0x8000
+
+// GCMP
+#define RALINK_GCMP_BASE 0x1FBF8000
+#define RALINK_GCMP_ADDRSPACE_SZ 0x8000
+
+// CM
+#define CM_GCR_REG0_BASE_VALUE 0x1C000000 /* CM region 0 base address (Palmbus) */
+#define CM_GCR_REG0_MASK_VALUE 0x0000FC00 /* CM region 0 mask (64M) */
+
+#define CM_GCR_REG1_BASE_VALUE 0x60000000 /* CM region 1 base address (PCIe) */
+#define CM_GCR_REG1_MASK_VALUE 0x0000F000 /* CM region 1 mask (256M) */
+
+// Interrupt Controller
+#define RALINK_INTCTL_FE (1<<3)
+#define RALINK_INTCTL_PCIE0 (1<<4)
+#define RALINK_INTCTL_SYSCTL (1<<6)
+#define RALINK_INTCTL_I2C (1<<8)
+#define RALINK_INTCTL_DRAMC (1<<9)
+#define RALINK_INTCTL_PCM (1<<10)
+#define RALINK_INTCTL_HSDMA (1<<11)
+#define RALINK_INTCTL_PIO (1<<12)
+#define RALINK_INTCTL_DMA (1<<13)
+#define RALINK_INTCTL_NFI (1<<14)
+#define RALINK_INTCTL_NFIECC (1<<15)
+#define RALINK_INTCTL_I2S (1<<16)
+#define RALINK_INTCTL_SPI (1<<17)
+#define RALINK_INTCTL_SPDIF (1<<18)
+#define RALINK_INTCTL_CRYPTO (1<<19)
+#define RALINK_INTCTL_SDXC (1<<20)
+#define RALINK_INTCTL_PCTRL (1<<21)
+#define RALINK_INTCTL_USB (1<<22)
+#define RALINK_INTCTL_ESW (1<<23)
+#define RALINK_INTCTL_PCIE1 (1<<24)
+#define RALINK_INTCTL_PCIE2 (1<<25)
+#define RALINK_INTCTL_UART1 (1<<26)
+#define RALINK_INTCTL_UART2 (1<<27)
+#define RALINK_INTCTL_UART3 (1<<28)
+#define RALINK_INTCTL_WDTIMER (1<<29)
+#define RALINK_INTCTL_TIMER0 (1<<30)
+#define RALINK_INTCTL_TIMER1 (1<<31)
+
+// Reset Control Register
+#define RALINK_SYS_RST (1<<0)
+#define RALINK_MCM_RST (1<<2)
+#define RALINK_HSDMA_RST (1<<5)
+#define RALINK_FE_RST (1<<6)
+#define RALINK_SPDIF_RST (1<<7)
+#define RALINK_TIMER_RST (1<<8)
+#define RALINK_INTC_RST (1<<9)
+#define RALINK_MC_RST (1<<10)
+#define RALINK_PCM_RST (1<<11)
+#define RALINK_PIO_RST (1<<13)
+#define RALINK_DMA_RST (1<<14)
+#define RALINK_NAND_RST (1<<15)
+#define RALINK_I2C_RST (1<<16)
+#define RALINK_I2S_RST (1<<17)
+#define RALINK_SPI_RST (1<<18)
+#define RALINK_UART1_RST (1<<19)
+#define RALINK_UART2_RST (1<<20)
+#define RALINK_UART3_RST (1<<21)
+#define RALINK_ETH_RST (1<<23)
+#define RALINK_PCIE0_RST (1<<24)
+#define RALINK_PCIE1_RST (1<<25)
+#define RALINK_PCIE2_RST (1<<26)
+#define RALINK_AUX_STCK_RST (1<<28)
+#define RALINK_CRYPTO_RST (1<<29)
+#define RALINK_SDXC_RST (1<<30)
+#define RALINK_PPE_RST (1<<31)
+
+// Clock Conf Register
+#define RALINK_SPDIF_CLK_EN (1<<7)
+#define RALINK_PCM_CLK_EN (1<<11)
+#define RALINK_NAND_CLK_EN (1<<15)
+#define RALINK_I2S_CLK_EN (1<<17)
+#define RALINK_PCIE0_CLK_EN (1<<24)
+#define RALINK_PCIE1_CLK_EN (1<<25)
+#define RALINK_PCIE2_CLK_EN (1<<26)
+#define RALINK_CRYPTO_CLK_EN (1<<29)
+#define RALINK_SDXC_CLK_EN (1<<30)
+
+// CPU PLL CFG Register
+#define CPLL_SW_CONFIG (0x1UL << 31)
+#define CPLL_MULT_RATIO_SHIFT 16
+#define CPLL_MULT_RATIO (0x7UL << CPLL_MULT_RATIO_SHIFT)
+#define CPLL_DIV_RATIO_SHIFT 10
+#define CPLL_DIV_RATIO (0x3UL << CPLL_DIV_RATIO_SHIFT)
+#define BASE_CLOCK 50 /* Mhz */
+
+#define RALINK_TESTSTAT 0xBE000018
+#define RALINK_TESTSTAT2 0xBE00001C
+
+#elif defined(CONFIG_RALINK_MT7628)
+
+#define RALINK_SYSCTL_BASE 0xB0000000
+#define RALINK_TIMER_BASE 0xB0000100
+#define RALINK_INTCL_BASE 0xB0000200
+#define RALINK_MEMCTRL_BASE 0xB0000300
+#define RALINK_RBUS_MATRIXCTL_BASE 0xB0000400
+#define RALINK_MIPS_CNT_BASE 0x10000500
+#define RALINK_PIO_BASE 0xB0000600
+#define RALINK_SPI_SLAVE_BASE 0xB0000700
+#define RALINK_I2C_BASE 0xB0000900
+#define RALINK_I2S_BASE 0xB0000A00
+#define RALINK_SPI_BASE 0xB0000B00
+#define RALINK_UART_LITE1_BASE 0x10000C00
+#define RALINK_UART_LITE_BASE RALINK_UART_LITE1_BASE
+#define RALINK_UART_LITE2_BASE 0x10000D00
+#define RALINK_UART_BASE RALINK_UART_LITE2_BASE
+#define RALINK_UART_LITE3_BASE 0x10000E00
+#define RALINK_PCM_BASE 0xB0002000
+#define RALINK_GDMA_BASE 0xB0002800
+#define RALINK_AES_ENGINE_BASE 0xB0004000
+#define RALINK_FRAME_ENGINE_BASE 0xB0100000
+#define RALINK_ETH_SW_BASE 0xB0110000
+#define RALINK_USB_DEV_BASE 0xB0120000
+#define RALINK_MSDC_BASE 0xB0130000
+#define RALINK_PCI_BASE 0xB0140000
+#define RALINK_11N_MAC_BASE 0xB0180000
+#define RALINK_USB_HOST_BASE 0x101C0000
+
+#define RALINK_CPU_CLK_AUTO_CFG 0xB0000444
+#define RALINK_MCNT_CFG 0xB0000500
+#define RALINK_COMPARE 0xB0000504
+#define RALINK_COUNT 0xB0000508
+
+// Interrupt Controller
+#define RALINK_INTCTL_SYSCTL (1<<0)
+#define RALINK_INTCTL_TIMER0 (1<<1)
+#define RALINK_INTCTL_WDTIMER (1<<2)
+#define RALINK_INTCTL_ILL_ACCESS (1<<3)
+#define RALINK_INTCTL_PCM (1<<4)
+#define RALINK_INTCTL_UART (1<<5)
+#define RALINK_INTCTL_PIO (1<<6)
+#define RALINK_INTCTL_DMA (1<<7)
+#define RALINK_INTCTL_PC (1<<9)
+#define RALINK_INTCTL_I2S (1<<10)
+#define RALINK_INTCTL_SPI (1<<11)
+#define RALINK_INTCTL_UARTLITE (1<<12)
+#define RALINK_INTCTL_CRYPTO (1<<13)
+#define RALINK_INTCTL_SDXC (1<<14)
+#define RALINK_INTCTL_ESW (1<<17)
+#define RALINK_INTCTL_UHST (1<<18)
+#define RALINK_INTCTL_UDEV (1<<19)
+#define RALINK_INTCTL_GLOBAL (1<<31)
+
+// Reset Control Register
+#define RALINK_SYS_RST (1<<0)
+#define RALINK_TIMER_RST (1<<8)
+#define RALINK_INTC_RST (1<<9)
+#define RALINK_MC_RST (1<<10)
+#define RALINK_PCM_RST (1<<11)
+#define RALINK_UART_RST (1<<12)
+#define RALINK_PIO_RST (1<<13)
+#define RALINK_DMA_RST (1<<14)
+#define RALINK_I2C_RST (1<<16)
+#define RALINK_I2S_RST (1<<17)
+#define RALINK_SPI_RST (1<<18)
+#define RALINK_UARTL_RST (1<<19)
+#define RALINK_FE_RST (1<<21)
+#define RALINK_UHST_RST (1<<22)
+#define RALINK_ESW_RST (1<<23)
+#define RALINK_EPHY_RST (1<<24)
+#define RALINK_UDEV_RST (1<<25)
+#define RALINK_PCIE0_RST (1<<26)
+#define RALINK_PCIE1_RST (1<<27)
+#define RALINK_MIPS_CNT_RST (1<<28)
+#define RALINK_CRYPTO_RST (1<<29)
+#define RALINK_SDXC_RST (1<<30)
+
+// Clock Conf Register
+#define RALINK_PCM_CLK_EN (1<<11)
+#define RALINK_I2S_CLK_EN (1<<17)
+#define RALINK_UPHY0_CLK_EN (1<<25)
+#define RALINK_UPHY1_CLK_EN (1<<22)
+#define RALINK_PCIE0_CLK_EN (1<<26)
+#define RALINK_PCIE1_CLK_EN (1<<27)
+#define RALINK_CRYPTO_CLK_EN (1<<29)
+#define RALINK_SDXC_CLK_EN (1<<30)
+
+// CPU PLL CFG Register
+#define CPLL_SW_CONFIG (0x1UL << 31)
+#define CPLL_MULT_RATIO_SHIFT 16
+#define CPLL_MULT_RATIO (0x7UL << CPLL_MULT_RATIO_SHIFT)
+#define CPLL_DIV_RATIO_SHIFT 10
+#define CPLL_DIV_RATIO (0x3UL << CPLL_DIV_RATIO_SHIFT)
+#define BASE_CLOCK 40 /* Mhz */
+
+// AGPIO
+#define MT7628_P0_EPHY_AIO_EN (0x1<<16)
+#define MT7628_P1_EPHY_AIO_EN (0x1<<17)
+#define MT7628_P2_EPHY_AIO_EN (0x1<<18)
+#define MT7628_P3_EPHY_AIO_EN (0x1<<19)
+#define MT7628_P4_EPHY_AIO_EN (0x1<<20)
+
+#elif defined(CONFIG_ECONET_EN75XX_MP)
+
+#define RALINK_SYSCTL_BASE 0xBFB00000
+#define RALINK_TIMER_BASE 0xBFBF0100
+#define RALINK_MEMCTRL_BASE 0xBFB20000
+#define RALINK_PIO_BASE 0xBFBF0200
+#define RALINK_I2C_BASE 0xBFBF8000
+#define RALINK_UART_LITE_BASE 0xBFBF0000
+#define RALINK_UART_LITE2_BASE 0xBFBF0300
+#define RALINK_PCM_BASE 0xBFBD0000
+#define RALINK_GDMA_BASE 0xBFB30000
+#define RALINK_FRAME_ENGINE_BASE 0xBFB50000
+#define RALINK_ETH_SW_BASE 0xBFB58000
+#define RALINK_CRYPTO_ENGINE_BASE 0xBFB70000
+#define RALINK_PCI_BASE 0xBFB80000
+#define RALINK_PCI_PHY0_BASE 0xBFAF2000
+#define RALINK_PCI_PHY1_BASE 0xBFAC0000
+#define RALINK_USB_HOST_BASE 0x1FB90000
+#define RALINK_XHCI_HOST_BASE 0xBFB90000
+#define RALINK_XHCI_UPHY_BASE 0xBFA80000
+#define RALINK_SFC_BASE 0xBFA10000
+#define RALINK_CHIP_SCU_BASE 0xBFA20000
+#define RALINK_11N_MAC_BASE 0xBFB00000 // Unused
+
+#if defined(CONFIG_ECONET_EN7528)
+#define RALINK_USB_HOST_SIZE 0x00003E00
+#define RALINK_USB_IPPC_BASE 0x1FB93E00
+#else
+#define RALINK_USB_HOST_SIZE 0x00004000
+#define RALINK_USB_IPPC_BASE 0x1FA80700
+#endif
+
+#ifdef CONFIG_MIPS_TC3262_1004K
+/* GIC */
+#define RALINK_GIC_BASE 0x1F8C0000
+#define RALINK_GIC_ADDRSPACE_SZ 0x20000
+
+/* CPC */
+#define RALINK_CPC_BASE 0x1F8E8000
+#define RALINK_CPC_ADDRSPACE_SZ 0x8000
+
+/* GCMP */
+#define RALINK_GCMP_BASE 0x1F8E0000
+#define RALINK_GCMP_ADDRSPACE_SZ 0x8000
+
+/* CM */
+#define CM_GCR_REG0_BASE_VALUE 0x1C000000 /* CM region 0 base address (Palmbus) */
+#define CM_GCR_REG0_MASK_VALUE 0x0000FC00 /* CM region 0 mask (64M) */
+
+#define CM_GCR_REG1_BASE_VALUE 0x20000000 /* CM region 1 base address (PCIe) */
+#define CM_GCR_REG1_MASK_VALUE 0x0000F000 /* CM region 1 mask (256M) */
+#else
+/* Interrupt Controller */
+#define RALINK_INTCL_BASE 0xBFB40000
+#define RALINK_INTCTL_UARTLITE (1<<0)
+#define RALINK_INTCTL_PIO (1<<10)
+#define RALINK_INTCTL_PCM (1<<11)
+#define RALINK_INTCTL_DMA (1<<14)
+#define RALINK_INTCTL_GSW (1<<15)
+#define RALINK_INTCTL_UHST (1<<17)
+#define RALINK_INTCTL_FE (1<<21)
+#define RALINK_INTCTL_QDMA (1<<22)
+#define RALINK_INTCTL_PCIE0 (1<<23)
+#define RALINK_INTCTL_PCIE1 (1<<24)
+
+/* Reset Control Register */
+#define RALINK_INTC_RST (1<<9)
+#endif
+
+/* Reset Control Register */
+#define RALINK_I2S1_RST (1<<0)
+#define RALINK_FE_QDMA_LAN_RST (1<<1)
+#define RALINK_FE_QDMA_WAN_RST (1<<2)
+#define RALINK_PCM2_RST (1<<4)
+#define RALINK_PTM_MAC_RST (1<<5)
+#define RALINK_CRYPTO_RST (1<<6)
+#define RALINK_SAR_RST (1<<7)
+#define RALINK_TIMER_RST (1<<8)
+#define RALINK_BONDING_RST (1<<10)
+#define RALINK_PCM1_RST (1<<11)
+#define RALINK_UART_RST (1<<12)
+#define RALINK_PIO_RST (1<<13)
+#define RALINK_DMA_RST (1<<14)
+#define RALINK_I2C_RST (1<<16)
+#define RALINK_I2S2_RST (1<<17)
+#define RALINK_SPI_RST (1<<18)
+#define RALINK_UARTL_RST (1<<19)
+#define RALINK_FE_RST (1<<21)
+#define RALINK_UHST_RST (1<<22)
+#define RALINK_ESW_RST (1<<23)
+#define RALINK_SFC2_RST (1<<25)
+#define RALINK_PCIE0_RST (1<<26)
+#define RALINK_PCIE1_RST (1<<27)
+#define RALINK_PCIEHB_RST (1<<29)
+
+#else
+#error "Ralink chip undefined for MEM map"
+#endif
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/rt_serial.h b/arch/mips/include/asm/rt2880/rt_serial.h
new file mode 100644
index 000000000000..b4ddc14f913f
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/rt_serial.h
@@ -0,0 +1,380 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * serial port definition for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+#ifndef __ASM_MACH_MIPS_RT2880_RT_SERIAL_H
+#define __ASM_MACH_MIPS_RT2880_RT_SERIAL_H
+
+#define RT2880_UART_RBR_OFFSET 0x00
+#define RT2880_UART_TBR_OFFSET 0x00
+#define RT2880_UART_IER_OFFSET 0x04
+#define RT2880_UART_IIR_OFFSET 0x08
+#define RT2880_UART_FCR_OFFSET 0x08
+#define RT2880_UART_LCR_OFFSET 0x0C
+#define RT2880_UART_MCR_OFFSET 0x10
+#define RT2880_UART_LSR_OFFSET 0x14
+#define RT2880_UART_DLL_OFFSET 0x00
+#define RT2880_UART_DLM_OFFSET 0x04
+
+#define RBR(x) *(volatile u32 *)((x)+RT2880_UART_RBR_OFFSET)
+#define TBR(x) *(volatile u32 *)((x)+RT2880_UART_TBR_OFFSET)
+#define IER(x) *(volatile u32 *)((x)+RT2880_UART_IER_OFFSET)
+#define IIR(x) *(volatile u32 *)((x)+RT2880_UART_IIR_OFFSET)
+#define FCR(x) *(volatile u32 *)((x)+RT2880_UART_FCR_OFFSET)
+#define LCR(x) *(volatile u32 *)((x)+RT2880_UART_LCR_OFFSET)
+#define MCR(x) *(volatile u32 *)((x)+RT2880_UART_MCR_OFFSET)
+#define LSR(x) *(volatile u32 *)((x)+RT2880_UART_LSR_OFFSET)
+#define DLL(x) *(volatile u32 *)((x)+RT2880_UART_DLL_OFFSET)
+#define DLM(x) *(volatile u32 *)((x)+RT2880_UART_DLM_OFFSET)
+
+#define RT2880_UART_RX 0 /* In: Receive buffer */
+#define RT2880_UART_TX 0 /* Out: Transmit buffer */
+#define RT2880_UART_DLL 0 /* Out: Divisor Latch Low */
+#define RT2880_UART_TRG 0 /* FCTR bit 7 selects Rx or Tx
+ * In: Fifo count
+ * Out: Fifo custom trigger levels */
+
+#define RT2880_UART_DLM 4 /* Out: Divisor Latch High */
+#define RT2880_UART_IER 4 /* Out: Interrupt Enable Register */
+#define RT2880_UART_FCTR 4 /* Feature Control Register */
+
+#define RT2880_UART_IIR 8 /* In: Interrupt ID Register */
+#define RT2880_UART_FCR 8 /* Out: FIFO Control Register */
+#define RT2880_UART_EFR 8 /* I/O: Extended Features Register */
+
+#define RT2880_UART_LCR 12 /* Out: Line Control Register */
+#define RT2880_UART_MCR 16 /* Out: Modem Control Register */
+#define RT2880_UART_LSR 20 /* In: Line Status Register */
+#define RT2880_UART_MSR 24 /* In: Modem Status Register */
+#define RT2880_UART_SCR 28 /* I/O: Scratch Register */
+#define RT2880_UART_EMSR 28 /* Extended Mode Select Register */
+
+/*
+ * DLAB=0
+ */
+#define RT2880_UART_IER_MSI 0x08 /* Enable Modem status interrupt */
+#define RT2880_UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
+#define RT2880_UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
+#define RT2880_UART_IER_RDI 0x01 /* Enable receiver data interrupt */
+/*
+ * Sleep mode for ST16650 and TI16750. For the ST16650, EFR[4]=1
+ */
+#define RT2880_UART_IERX_SLEEP 0x10 /* Enable sleep mode */
+
+#define RT2880_UART_IIR_NO_INT 0x01 /* No interrupts pending */
+#define RT2880_UART_IIR_ID 0x06 /* Mask for the interrupt ID */
+#define RT2880_UART_IIR_MSI 0x00 /* Modem status interrupt */
+#define RT2880_UART_IIR_THRI 0x02 /* Transmitter holding register empty */
+#define RT2880_UART_IIR_RDI 0x04 /* Receiver data interrupt */
+#define RT2880_UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
+
+#define RT2880_UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
+#define RT2880_UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
+#define RT2880_UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
+#define RT2880_UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
+/*
+ * Note: The FIFO trigger levels are chip specific:
+ * RX:76 = 00 01 10 11 TX:54 = 00 01 10 11
+ * PC16550D: 1 4 8 14 xx xx xx xx
+ * TI16C550A: 1 4 8 14 xx xx xx xx
+ * TI16C550C: 1 4 8 14 xx xx xx xx
+ * ST16C550: 1 4 8 14 xx xx xx xx
+ * ST16C650: 8 16 24 28 16 8 24 30 PORT_16650V2
+ * NS16C552: 1 4 8 14 xx xx xx xx
+ * ST16C654: 8 16 56 60 8 16 32 56 PORT_16654
+ * TI16C750: 1 16 32 56 xx xx xx xx PORT_16750
+ * TI16C752: 8 16 56 60 8 16 32 56
+ */
+#define RT2880_UART_FCR_R_TRIG_00 0x00
+#define RT2880_UART_FCR_R_TRIG_01 0x40
+#define RT2880_UART_FCR_R_TRIG_10 0x80
+#define RT2880_UART_FCR_R_TRIG_11 0xc0
+#define RT2880_UART_FCR_T_TRIG_00 0x00
+#define RT2880_UART_FCR_T_TRIG_01 0x10
+#define RT2880_UART_FCR_T_TRIG_10 0x20
+#define RT2880_UART_FCR_T_TRIG_11 0x30
+
+#define RT2880_UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
+#define RT2880_UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
+#define RT2880_UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
+#define RT2880_UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
+#define RT2880_UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
+/* 16650 definitions */
+#define RT2880_UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
+#define RT2880_UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */
+#define RT2880_UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */
+#define RT2880_UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */
+#define RT2880_UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */
+#define RT2880_UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
+#define RT2880_UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */
+#define RT2880_UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
+#define RT2880_UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode (TI16C750) */
+
+//#define UART_LCR 3 /* Out: Line Control Register */
+/*
+ * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
+ * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
+ */
+#define RT2880_UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+#define RT2880_UART_LCR_SBC 0x40 /* Set break control */
+#define RT2880_UART_LCR_SPAR 0x20 /* Stick parity (?) */
+#define RT2880_UART_LCR_EPAR 0x10 /* Even parity select */
+#define RT2880_UART_LCR_PARITY 0x08 /* Parity Enable */
+#define RT2880_UART_LCR_STOP 0x04 /* Stop bits: 0=1 bit, 1=2 bits */
+#define RT2880_UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
+#define RT2880_UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
+#define RT2880_UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
+#define RT2880_UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
+
+//#define RT2880_UART_MCR 4 /* Out: Modem Control Register */
+#define RT2880_UART_MCR_CLKSEL 0x80 /* Divide clock by 4 (TI16C752, EFR[4]=1) */
+#define RT2880_UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
+#define RT2880_UART_MCR_XONANY 0x20 /* Enable Xon Any (TI16C752, EFR[4]=1) */
+#define RT2880_UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C550C/TI16C750) */
+#define RT2880_UART_MCR_LOOP 0x10 /* Enable loopback test mode */
+#define RT2880_UART_MCR_OUT2 0x08 /* Out2 complement */
+#define RT2880_UART_MCR_OUT1 0x04 /* Out1 complement */
+#define RT2880_UART_MCR_RTS 0x02 /* RTS complement */
+#define RT2880_UART_MCR_DTR 0x01 /* DTR complement */
+
+//#define RT2880_UART_LSR 5 /* In: Line Status Register */
+#define RT2880_UART_LSR_TEMT 0x40 /* Transmitter empty */
+#define RT2880_UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define RT2880_UART_LSR_BI 0x10 /* Break interrupt indicator */
+#define RT2880_UART_LSR_FE 0x08 /* Frame error indicator */
+#define RT2880_UART_LSR_PE 0x04 /* Parity error indicator */
+#define RT2880_UART_LSR_OE 0x02 /* Overrun error indicator */
+#define RT2880_UART_LSR_DR 0x01 /* Receiver data ready */
+
+//#define RT2880_UART_MSR 6 /* In: Modem Status Register */
+#define RT2880_UART_MSR_DCD 0x80 /* Data Carrier Detect */
+#define RT2880_UART_MSR_RI 0x40 /* Ring Indicator */
+#define RT2880_UART_MSR_DSR 0x20 /* Data Set Ready */
+#define RT2880_UART_MSR_CTS 0x10 /* Clear to Send */
+#define RT2880_UART_MSR_DDCD 0x08 /* Delta DCD */
+#define RT2880_UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
+#define RT2880_UART_MSR_DDSR 0x02 /* Delta DSR */
+#define RT2880_UART_MSR_DCTS 0x01 /* Delta CTS */
+#define RT2880_UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
+
+//#define RT2880_UART_SCR 7 /* I/O: Scratch Register */
+
+/*
+ * DLAB=1
+ */
+//#define RT2880_UART_DLL 0 /* Out: Divisor Latch Low */
+//#define RT2880_UART_DLM 1 /* Out: Divisor Latch High */
+
+/*
+ * LCR=0xBF (or DLAB=1 for 16C660)
+ */
+//#define RT2880_UART_EFR 2 /* I/O: Extended Features Register */
+#define RT2880_UART_EFR_CTS 0x80 /* CTS flow control */
+#define RT2880_UART_EFR_RTS 0x40 /* RTS flow control */
+#define RT2880_UART_EFR_SCD 0x20 /* Special character detect */
+#define RT2880_UART_EFR_ECB 0x10 /* Enhanced control bit */
+/*
+ * the low four bits control software flow control
+ */
+
+/*
+ * LCR=0xBF, TI16C752, ST16650, ST16650A, ST16654
+ */
+#define RT2880_UART_XON1 4 /* I/O: Xon character 1 */
+#define RT2880_UART_XON2 5 /* I/O: Xon character 2 */
+#define RT2880_UART_XOFF1 6 /* I/O: Xoff character 1 */
+#define RT2880_UART_XOFF2 7 /* I/O: Xoff character 2 */
+
+/*
+ * EFR[4]=1 MCR[6]=1, TI16C752
+ */
+#define RT2880_UART_TI752_TCR 6 /* I/O: transmission control register */
+#define RT2880_UART_TI752_TLR 7 /* I/O: trigger level register */
+
+/*
+ * LCR=0xBF, XR16C85x
+ */
+//#define RT2880_UART_TRG 0 /* FCTR bit 7 selects Rx or Tx
+/*
+ * These are the definitions for the Programmable Trigger Register
+ */
+#define RT2880_UART_TRG_1 0x01
+#define RT2880_UART_TRG_4 0x04
+#define RT2880_UART_TRG_8 0x08
+#define RT2880_UART_TRG_16 0x10
+#define RT2880_UART_TRG_32 0x20
+#define RT2880_UART_TRG_64 0x40
+#define RT2880_UART_TRG_96 0x60
+#define RT2880_UART_TRG_120 0x78
+#define RT2880_UART_TRG_128 0x80
+
+//#define RT2880_UART_FCTR 1 /* Feature Control Register */
+#define RT2880_UART_FCTR_RTS_NODELAY 0x00 /* RTS flow control delay */
+#define RT2880_UART_FCTR_RTS_4DELAY 0x01
+#define RT2880_UART_FCTR_RTS_6DELAY 0x02
+#define RT2880_UART_FCTR_RTS_8DELAY 0x03
+#define RT2880_UART_FCTR_IRDA 0x04 /* IrDa data encode select */
+#define RT2880_UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */
+#define RT2880_UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */
+#define RT2880_UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */
+#define RT2880_UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */
+#define RT2880_UART_FCTR_TRGD 0x30 /* Tx/Rx 850 programmable trigger select */
+#define RT2880_UART_FCTR_SCR_SWAP 0x40 /* Scratch pad register swap */
+#define RT2880_UART_FCTR_RX 0x00 /* Programmable trigger mode select */
+#define RT2880_UART_FCTR_TX 0x80 /* Programmable trigger mode select */
+
+/*
+ * LCR=0xBF, FCTR[6]=1
+ */
+//#define RT2880_UART_EMSR 7 /* Extended Mode Select Register */
+#define RT2880_UART_EMSR_FIFO_COUNT 0x01 /* Rx/Tx select */
+#define RT2880_UART_EMSR_ALT_COUNT 0x02 /* Alternating count select */
+
+/*
+ * The Intel XScale on-chip UARTs define these bits
+ */
+#define RT2880_UART_IER_DMAE 0x80 /* DMA Requests Enable */
+#define RT2880_UART_IER_UUE 0x40 /* UART Unit Enable */
+#define RT2880_UART_IER_NRZE 0x20 /* NRZ coding Enable */
+#define RT2880_UART_IER_RTOIE 0x10 /* Receiver Time Out Interrupt Enable */
+
+#define RT2880_UART_IIR_TOD 0x08 /* Character Timeout Indication Detected */
+
+#define RT2880_UART_FCR_PXAR1 0x00 /* receive FIFO treshold = 1 */
+#define RT2880_UART_FCR_PXAR8 0x40 /* receive FIFO treshold = 8 */
+#define RT2880_UART_FCR_PXAR16 0x80 /* receive FIFO treshold = 16 */
+#define RT2880_UART_FCR_PXAR32 0xc0 /* receive FIFO treshold = 32 */
+
+/*
+ * These register definitions are for the 16C950
+ */
+#define RT2880_UART_ASR 0x01 /* Additional Status Register */
+#define RT2880_UART_RFL 0x03 /* Receiver FIFO level */
+#define RT2880_UART_TFL 0x04 /* Transmitter FIFO level */
+#define RT2880_UART_ICR 0x05 /* Index Control Register */
+
+/* The 16950 ICR registers */
+#define RT2880_UART_ACR 0x00 /* Additional Control Register */
+#define RT2880_UART_CPR 0x01 /* Clock Prescalar Register */
+#define RT2880_UART_TCR 0x02 /* Times Clock Register */
+#define RT2880_UART_CKS 0x03 /* Clock Select Register */
+#define RT2880_UART_TTL 0x04 /* Transmitter Interrupt Trigger Level */
+#define RT2880_UART_RTL 0x05 /* Receiver Interrupt Trigger Level */
+#define RT2880_UART_FCL 0x06 /* Flow Control Level Lower */
+#define RT2880_UART_FCH 0x07 /* Flow Control Level Higher */
+#define RT2880_UART_ID1 0x08 /* ID #1 */
+#define RT2880_UART_ID2 0x09 /* ID #2 */
+#define RT2880_UART_ID3 0x0A /* ID #3 */
+#define RT2880_UART_REV 0x0B /* Revision */
+#define RT2880_UART_CSR 0x0C /* Channel Software Reset */
+#define RT2880_UART_NMR 0x0D /* Nine-bit Mode Register */
+#define RT2880_UART_CTR 0xFF
+
+/*
+ * The 16C950 Additional Control Reigster
+ */
+#define RT2880_UART_ACR_RXDIS 0x01 /* Receiver disable */
+#define RT2880_UART_ACR_TXDIS 0x02 /* Receiver disable */
+#define RT2880_UART_ACR_DSRFC 0x04 /* DSR Flow Control */
+#define RT2880_UART_ACR_TLENB 0x20 /* 950 trigger levels enable */
+#define RT2880_UART_ACR_ICRRD 0x40 /* ICR Read enable */
+#define RT2880_UART_ACR_ASREN 0x80 /* Additional status enable */
+
+/*
+ * These definitions are for the RSA-DV II/S card, from
+ *
+ * Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
+ */
+
+#define RT2880_UART_RSA_BASE (-8)
+
+#define RT2880_UART_RSA_MSR ((UART_RSA_BASE) + 0) /* I/O: Mode Select Register */
+
+#define RT2880_UART_RSA_MSR_SWAP (1 << 0) /* Swap low/high 8 bytes in I/O port addr */
+#define RT2880_UART_RSA_MSR_FIFO (1 << 2) /* Enable the external FIFO */
+#define RT2880_UART_RSA_MSR_FLOW (1 << 3) /* Enable the auto RTS/CTS flow control */
+#define RT2880_UART_RSA_MSR_ITYP (1 << 4) /* Level (1) / Edge triger (0) */
+
+#define RT2880_UART_RSA_IER ((UART_RSA_BASE) + 1) /* I/O: Interrupt Enable Register */
+
+#define RT2880_UART_RSA_IER_Rx_FIFO_H (1 << 0) /* Enable Rx FIFO half full int. */
+#define RT2880_UART_RSA_IER_Tx_FIFO_H (1 << 1) /* Enable Tx FIFO half full int. */
+#define RT2880_UART_RSA_IER_Tx_FIFO_E (1 << 2) /* Enable Tx FIFO empty int. */
+#define RT2880_UART_RSA_IER_Rx_TOUT (1 << 3) /* Enable char receive timeout int */
+#define RT2880_UART_RSA_IER_TIMER (1 << 4) /* Enable timer interrupt */
+
+#define RT2880_UART_RSA_SRR ((UART_RSA_BASE) + 2) /* IN: Status Read Register */
+
+#define RT2880_UART_RSA_SRR_Tx_FIFO_NEMP (1 << 0) /* Tx FIFO is not empty (1) */
+#define RT2880_UART_RSA_SRR_Tx_FIFO_NHFL (1 << 1) /* Tx FIFO is not half full (1) */
+#define RT2880_UART_RSA_SRR_Tx_FIFO_NFUL (1 << 2) /* Tx FIFO is not full (1) */
+#define RT2880_UART_RSA_SRR_Rx_FIFO_NEMP (1 << 3) /* Rx FIFO is not empty (1) */
+#define RT2880_UART_RSA_SRR_Rx_FIFO_NHFL (1 << 4) /* Rx FIFO is not half full (1) */
+#define RT2880_UART_RSA_SRR_Rx_FIFO_NFUL (1 << 5) /* Rx FIFO is not full (1) */
+#define RT2880_UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occurred (1) */
+#define RT2880_UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occurred */
+
+#define RT2880_UART_RSA_FRR ((UART_RSA_BASE) + 2) /* OUT: FIFO Reset Register */
+
+#define RT2880_UART_RSA_TIVSR ((UART_RSA_BASE) + 3) /* I/O: Timer Interval Value Set Register */
+
+#define RT2880_UART_RSA_TCR ((UART_RSA_BASE) + 4) /* OUT: Timer Control Register */
+
+#define RT2880_UART_RSA_TCR_SWITCH (1 << 0) /* Timer on */
+
+/*
+ * The RSA DSV/II board has two fixed clock frequencies. One is the
+ * standard rate, and the other is 8 times faster.
+ */
+#define SERIAL_RSA_BAUD_BASE (921600)
+#define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8)
+
+/*
+ * Extra serial register definitions for the internal UARTs
+ * in TI OMAP processors.
+ */
+#define RT2880_UART_OMAP_MDR1 0x08 /* Mode definition register */
+#define RT2880_UART_OMAP_MDR2 0x09 /* Mode definition register 2 */
+#define RT2880_UART_OMAP_SCR 0x10 /* Supplementary control register */
+#define RT2880_UART_OMAP_SSR 0x11 /* Supplementary status register */
+#define RT2880_UART_OMAP_EBLR 0x12 /* BOF length register */
+#define RT2880_UART_OMAP_OSC_12M_SEL 0x13 /* OMAP1510 12MHz osc select */
+#define RT2880_UART_OMAP_MVER 0x14 /* Module version register */
+#define RT2880_UART_OMAP_SYSC 0x15 /* System configuration register */
+#define RT2880_UART_OMAP_SYSS 0x16 /* System status register */
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/surfboard.h b/arch/mips/include/asm/rt2880/surfboard.h
new file mode 100644
index 000000000000..8e0f99a0cf63
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/surfboard.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2001 Palmchip Corporation. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ */
+#ifndef __ASM_MACH_MIPS_RT2880_SURFBOARD_H
+#define __ASM_MACH_MIPS_RT2880_SURFBOARD_H
+
+/*
+ * Surfboard UART base baud rate = System Clock / 16.
+ * Ex. (14.7456 MHZ / 16) = 921600
+ * (32.0000 MHZ / 16) = 2000000
+ */
+#define SURFBOARD_BAUD_DIV (16)
+
+extern unsigned int get_surfboard_sysclk(void);
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/surfboardint.h b/arch/mips/include/asm/rt2880/surfboardint.h
new file mode 100644
index 000000000000..15c9e8911f8c
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/surfboardint.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2001 Palmchip Corporation. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Defines for the Surfboard interrupt controller.
+ *
+ */
+#ifndef __ASM_MACH_MIPS_RT2880_SURFBOARDINT_H
+#define __ASM_MACH_MIPS_RT2880_SURFBOARDINT_H
+
+#if defined(CONFIG_RALINK_MT7621)
+
+#ifdef CONFIG_MIPS_GIC
+#include <linux/irqchip/mips-gic.h>
+#else
+#define GIC_NUM_LOCAL_INTRS 7
+#define GIC_SHARED_HWIRQ_BASE GIC_NUM_LOCAL_INTRS
+#define GIC_SHARED_TO_HWIRQ(x) (GIC_SHARED_HWIRQ_BASE + (x))
+#endif
+
+/* MIPS GIC controller */
+#define GIC_NUM_INTRS 64
+#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
+
+#define SURFBOARDINT_FE (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(3)) /* FE */
+#define SURFBOARDINT_PCIE0 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(4)) /* PCIE0 */
+#define SURFBOARDINT_AUX_TIMER (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(5)) /* AUX timer (systick) */
+#define SURFBOARDINT_SYSCTL (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(6)) /* SYSCTL */
+#define SURFBOARDINT_I2C (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(8)) /* I2C */
+#define SURFBOARDINT_DRAMC (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(9)) /* DRAMC */
+#define SURFBOARDINT_PCM (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(10)) /* PCM */
+#define SURFBOARDINT_HSGDMA (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(11)) /* HSGDMA */
+#define SURFBOARDINT_GPIO (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(12)) /* GPIO */
+#define SURFBOARDINT_DMA (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(13)) /* GDMA */
+#define SURFBOARDINT_NAND (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(14)) /* NAND */
+#define SURFBOARDINT_NAND_ECC (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(15)) /* NFI ECC */
+#define SURFBOARDINT_I2S (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(16)) /* I2S */
+#define SURFBOARDINT_SPI (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(17)) /* SPI */
+#define SURFBOARDINT_SPDIF (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(18)) /* SPDIF */
+#define SURFBOARDINT_CRYPTO (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(19)) /* CryptoEngine */
+#define SURFBOARDINT_SDXC (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(20)) /* SDXC */
+#define SURFBOARDINT_R2P (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(21)) /* Rbus to Pbus */
+#define SURFBOARDINT_USB (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(22)) /* USB */
+#define SURFBOARDINT_ESW (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(23)) /* Switch */
+#define SURFBOARDINT_PCIE1 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(24)) /* PCIE1 */
+#define SURFBOARDINT_PCIE2 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(25)) /* PCIE2 */
+#define SURFBOARDINT_UART_LITE1 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(26)) /* UART Lite */
+#define SURFBOARDINT_UART_LITE2 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(27)) /* UART Lite */
+#define SURFBOARDINT_UART_LITE3 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(28)) /* UART Lite */
+#define SURFBOARDINT_WDG (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(29)) /* WDG timer */
+#define SURFBOARDINT_TIMER0 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(30)) /* Timer0 */
+#define SURFBOARDINT_TIMER1 (MIPS_GIC_IRQ_BASE + GIC_SHARED_TO_HWIRQ(31)) /* Timer1 */
+#define SURFBOARDINT_UART1 SURFBOARDINT_UART_LITE1
+#define SURFBOARDINT_UART2 SURFBOARDINT_UART_LITE2
+
+#define SURFBOARDINT_END (MIPS_GIC_IRQ_BASE + GIC_NUM_LOCAL_INTRS + GIC_NUM_INTRS - 1)
+
+#elif defined(CONFIG_RALINK_MT7628)
+
+#define MIPS_INTC_CHAIN_HW0 (MIPS_CPU_IRQ_BASE + 2) /* Chain IP2 */
+#define MIPS_INTC_CHAIN_HW1 (MIPS_CPU_IRQ_BASE + 3) /* Chain IP3 */
+#define SURFBOARDINT_PCIE0 (MIPS_CPU_IRQ_BASE + 4) /* PCIe Slot0 */
+#define SURFBOARDINT_FE (MIPS_CPU_IRQ_BASE + 5) /* Frame Engine */
+#define SURFBOARDINT_WLAN (MIPS_CPU_IRQ_BASE + 6) /* Wireless */
+#define SURFBOARDINT_MIPS_TIMER (MIPS_CPU_IRQ_BASE + 7) /* MIPS Timer */
+
+#define INTC_NUM_INTRS 32
+#define MIPS_INTC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
+
+#define SURFBOARDINT_SYSCTL (MIPS_INTC_IRQ_BASE + 0) /* SYSCTL */
+#define SURFBOARDINT_ILL_ACC (MIPS_INTC_IRQ_BASE + 3) /* Illegal access */
+#define SURFBOARDINT_PCM (MIPS_INTC_IRQ_BASE + 4) /* PCM */
+#define SURFBOARDINT_GPIO (MIPS_INTC_IRQ_BASE + 6) /* GPIO */
+#define SURFBOARDINT_DMA (MIPS_INTC_IRQ_BASE + 7) /* DMA */
+#define SURFBOARDINT_NAND (MIPS_INTC_IRQ_BASE + 8) /* NAND */
+#define SURFBOARDINT_PCTRL (MIPS_INTC_IRQ_BASE + 9) /* Performance counter */
+#define SURFBOARDINT_I2S (MIPS_INTC_IRQ_BASE + 10) /* I2S */
+#define SURFBOARDINT_SPI (MIPS_INTC_IRQ_BASE + 11) /* SPI */
+
+#define SURFBOARDINT_SDXC (MIPS_INTC_IRQ_BASE + 14) /* SDXC */
+#define SURFBOARDINT_R2P (MIPS_INTC_IRQ_BASE + 15) /* Rbus to Pbus */
+
+#define SURFBOARDINT_AESENGINE (MIPS_INTC_IRQ_BASE + 13) /* AES Engine */
+#define SURFBOARDINT_UART_LITE1 (MIPS_INTC_IRQ_BASE + 20) /* UART Lite 1 */
+#define SURFBOARDINT_UART_LITE2 (MIPS_INTC_IRQ_BASE + 21) /* UART Lite 2 */
+#define SURFBOARDINT_UART_LITE3 (MIPS_INTC_IRQ_BASE + 22) /* UART Lite 3 */
+#define SURFBOARDINT_WDG (MIPS_INTC_IRQ_BASE + 23) /* WDG timer */
+#define SURFBOARDINT_TIMER0 (MIPS_INTC_IRQ_BASE + 24) /* Timer0 */
+#define SURFBOARDINT_TIMER1 (MIPS_INTC_IRQ_BASE + 25) /* Timer1 */
+#define SURFBOARDINT_PWM (MIPS_INTC_IRQ_BASE + 26) /* PWM */
+#define SURFBOARDINT_WWAKE (MIPS_INTC_IRQ_BASE + 27) /* WLAN Wake */
+#define SURFBOARDINT_UART1 SURFBOARDINT_UART_LITE1
+#define SURFBOARDINT_UART2 SURFBOARDINT_UART_LITE2
+
+#define SURFBOARDINT_ESW (MIPS_INTC_IRQ_BASE + 17) /* Embedded Switch */
+#define SURFBOARDINT_UHST (MIPS_INTC_IRQ_BASE + 18) /* USB Host */
+#define SURFBOARDINT_UDEV (MIPS_INTC_IRQ_BASE + 19) /* USB Device */
+
+#define SURFBOARDINT_END (MIPS_INTC_IRQ_BASE + INTC_NUM_INTRS - 1)
+
+#elif defined(CONFIG_MIPS_TC3262_1004K)
+
+#include <asm/tc3162/tc3262_int_source.h>
+
+/* MIPS GIC controller (via EIC) */
+#define GIC_NUM_INTRS 64
+#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 0)
+
+#define SURFBOARDINT_UART_LITE1 UART_INT /* UART Lite1 */
+#define SURFBOARDINT_TIMER0 TIMER0_INT, /* Timer0 */
+#define SURFBOARDINT_TIMER1 TIMER1_INT /* Timer1 */
+#define SURFBOARDINT_TIMER2 TIMER2_INT /* Timer2 */
+#define SURFBOARDINT_WDG TIMER5_INT /* WDG timer */
+#define SURFBOARDINT_GPIO GPIO_INT /* GPIO */
+#define SURFBOARDINT_PCM PCM1_INT /* PCM */
+#define SURFBOARDINT_ESW MAC1_INT /* ESW */
+#define SURFBOARDINT_UART_LITE2 UART2_INT /* UART Lite2 */
+#define SURFBOARDINT_USB IRQ_RT3XXX_USB /* USB */
+#define SURFBOARDINT_DMT DMT_INT /* xDSL DMT */
+#define SURFBOARDINT_QDMA1 QDMA_LAN0_INTR /* QDMA1, INT0 */
+#define SURFBOARDINT_QDMA2 QDMA_WAN0_INTR /* QDMA2, INT0 */
+#define SURFBOARDINT_PCIE0 PCIE_0_INT /* PCIE0 */
+#define SURFBOARDINT_PCIE1 PCIE_A_INT /* PCIE1 */
+#define SURFBOARDINT_CRYPTO CRYPTO_INT /* CryptoEngine */
+#define SURFBOARDINT_QDMA1_INT1 QDMA_LAN1_INTR /* QDMA1, INT1 */
+#define SURFBOARDINT_QDMA1_INT2 QDMA_LAN2_INTR /* QDMA1, INT2 */
+#define SURFBOARDINT_QDMA1_INT3 QDMA_LAN3_INTR /* QDMA1, INT3 */
+#define SURFBOARDINT_QDMA2_INT1 QDMA_WAN1_INTR /* QDMA2, INT1 */
+#define SURFBOARDINT_QDMA2_INT2 QDMA_WAN2_INTR /* QDMA2, INT2 */
+#define SURFBOARDINT_QDMA2_INT3 QDMA_WAN3_INTR /* QDMA2, INT3 */
+#define SURFBOARDINT_UART1 SURFBOARDINT_UART_LITE1
+#define SURFBOARDINT_UART2 SURFBOARDINT_UART_LITE2
+
+#define SURFBOARDINT_END (INTR_SOURCES_NUM - 1)
+
+#elif defined(CONFIG_MIPS_TC3262_34K)
+
+#include <asm/tc3162/tc3262_int_source.h>
+
+#define SURFBOARDINT_UART1 UART_INT /* UART1 */
+#define SURFBOARDINT_GPIO GPIO_INT /* GPIO */
+#define SURFBOARDINT_PCM PCM1_INT /* PCM1 */
+#define SURFBOARDINT_DMA APB_DMA0_INT /* DMA */
+#define SURFBOARDINT_ESW ESW_INT /* ESW */
+#define SURFBOARDINT_USB IRQ_RT3XXX_USB /* USB */
+#define SURFBOARDINT_FE FE_MAC_INT /* Frame Engine */
+#define SURFBOARDINT_QDMA SAR_INT /* QDMA */
+#define SURFBOARDINT_PCIE0 PCIE_0_INT /* PCIe0 */
+#define SURFBOARDINT_PCIE1 PCIE_A_INT /* PCIe1 */
+#define SURFBOARDINT_CRYPTO CRYPTO_INT /* CryptoEngine */
+
+#define SURFBOARDINT_END 40 /* 1 offset + 40 TC */
+
+#else
+#error "Ralink chip undefined for INT map"
+#endif
+
+/*
+ * Surfboard registers are memory mapped on 32-bit aligned boundaries and
+ * only word access are allowed.
+ */
+#ifndef CONFIG_MIPS_TC3262
+#define RALINK_IRQ0STAT (RALINK_INTCL_BASE + 0x9C) //IRQ_STAT
+#define RALINK_IRQ1STAT (RALINK_INTCL_BASE + 0xA0) //FIQ_STAT
+#define RALINK_INTTYPE (RALINK_INTCL_BASE + 0x6C) //FIQ_SEL
+#define RALINK_INTRAW (RALINK_INTCL_BASE + 0xA4) //INT_PURE
+#define RALINK_INTENA (RALINK_INTCL_BASE + 0x80) //IRQ_MASK_SET
+#define RALINK_FIQENA (RALINK_INTCL_BASE + 0x84) //FIQ_MASK_SET
+#define RALINK_INTDIS (RALINK_INTCL_BASE + 0x78) //IRQ_MASK_CLR
+#define RALINK_FIQDIS (RALINK_INTCL_BASE + 0x7C) //FIQ_MASK_CLR
+#endif
+
+/* bobtseng added ++, 2006.3.6. */
+#define read_32bit_cp0_register(source) \
+({ int __res; \
+ __asm__ __volatile__( \
+ ".set\tpush\n\t" \
+ ".set\treorder\n\t" \
+ "mfc0\t%0,"STR(source)"\n\t" \
+ ".set\tpop" \
+ : "=r" (__res)); \
+ __res;})
+
+#define write_32bit_cp0_register(register,value) \
+ __asm__ __volatile__( \
+ "mtc0\t%0,"STR(register)"\n\t" \
+ "nop" \
+ : : "r" (value));
+
+/* bobtseng added --, 2006.3.6. */
+
+#endif
diff --git a/arch/mips/include/asm/rt2880/war.h b/arch/mips/include/asm/rt2880/war.h
new file mode 100644
index 000000000000..581de3f8c738
--- /dev/null
+++ b/arch/mips/include/asm/rt2880/war.h
@@ -0,0 +1,26 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2008 Cavium Networks <support@caviumnetworks.com>
+ */
+#ifndef __ASM_MACH_MIPS_RT2880_WAR_H
+#define __ASM_MACH_MIPS_RT2880_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif
diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index db7c322f057f..e5f49dd453c7 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -26,7 +26,7 @@ struct plat_smp_ops {
void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
void (*init_secondary)(void);
void (*smp_finish)(void);
- void (*boot_secondary)(int cpu, struct task_struct *idle);
+ int (*boot_secondary)(int cpu, struct task_struct *idle);
void (*smp_setup)(void);
void (*prepare_cpus)(unsigned int max_cpus);
#ifdef CONFIG_HOTPLUG_CPU
@@ -35,11 +35,11 @@ struct plat_smp_ops {
#endif
};
-extern void register_smp_ops(struct plat_smp_ops *ops);
+extern void register_smp_ops(const struct plat_smp_ops *ops);
static inline void plat_smp_setup(void)
{
- extern struct plat_smp_ops *mp_ops; /* private */
+ extern const struct plat_smp_ops *mp_ops; /* private */
mp_ops->smp_setup();
}
@@ -57,7 +57,7 @@ static inline void plat_smp_setup(void)
/* UP, nothing to do ... */
}
-static inline void register_smp_ops(struct plat_smp_ops *ops)
+static inline void register_smp_ops(const struct plat_smp_ops *ops)
{
}
@@ -66,7 +66,7 @@ static inline void register_smp_ops(struct plat_smp_ops *ops)
static inline int register_up_smp_ops(void)
{
#ifdef CONFIG_SMP_UP
- extern struct plat_smp_ops up_smp_ops;
+ extern const struct plat_smp_ops up_smp_ops;
register_smp_ops(&up_smp_ops);
@@ -79,7 +79,7 @@ static inline int register_up_smp_ops(void)
static inline int register_cmp_smp_ops(void)
{
#ifdef CONFIG_MIPS_CMP
- extern struct plat_smp_ops cmp_smp_ops;
+ extern const struct plat_smp_ops cmp_smp_ops;
if (!mips_cm_present())
return -ENODEV;
@@ -95,7 +95,7 @@ static inline int register_cmp_smp_ops(void)
static inline int register_vsmp_smp_ops(void)
{
#ifdef CONFIG_MIPS_MT_SMP
- extern struct plat_smp_ops vsmp_smp_ops;
+ extern const struct plat_smp_ops vsmp_smp_ops;
register_smp_ops(&vsmp_smp_ops);
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 258158c34df1..6d4ac5465864 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -52,11 +52,7 @@ extern int __cpu_logical_map[NR_CPUS];
#define SMP_CALL_FUNCTION 0x2
/* Octeon - Tell another core to flush its icache */
#define SMP_ICACHE_FLUSH 0x4
-/* Used by kexec crashdump to save all cpu's state */
-#define SMP_DUMP 0x8
-#define SMP_ASK_C0COUNT 0x10
-
-extern cpumask_t cpu_callin_map;
+#define SMP_ASK_C0COUNT 0x8
/* Mask of CPUs which are currently definitely operating coherently */
extern cpumask_t cpu_coherent_mask;
@@ -72,7 +68,7 @@ extern void calculate_cpu_foreign_map(void);
*/
static inline void smp_send_reschedule(int cpu)
{
- extern struct plat_smp_ops *mp_ops; /* private */
+ extern const struct plat_smp_ops *mp_ops; /* private */
mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF);
}
@@ -80,14 +76,14 @@ static inline void smp_send_reschedule(int cpu)
#ifdef CONFIG_HOTPLUG_CPU
static inline int __cpu_disable(void)
{
- extern struct plat_smp_ops *mp_ops; /* private */
+ extern const struct plat_smp_ops *mp_ops; /* private */
return mp_ops->cpu_disable();
}
static inline void __cpu_die(unsigned int cpu)
{
- extern struct plat_smp_ops *mp_ops; /* private */
+ extern const struct plat_smp_ops *mp_ops; /* private */
mp_ops->cpu_die(cpu);
}
@@ -111,20 +107,16 @@ int mips_smp_ipi_free(const struct cpumask *mask);
static inline void arch_send_call_function_single_ipi(int cpu)
{
- extern struct plat_smp_ops *mp_ops; /* private */
+ extern const struct plat_smp_ops *mp_ops; /* private */
mp_ops->send_ipi_mask(cpumask_of(cpu), SMP_CALL_FUNCTION);
}
static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
- extern struct plat_smp_ops *mp_ops; /* private */
+ extern const struct plat_smp_ops *mp_ops; /* private */
mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
}
-#if defined(CONFIG_KEXEC)
-extern void (*dump_ipi_function_ptr)(void *);
-void dump_send_ipi(void (*dump_ipi_callback)(void *));
-#endif
#endif /* __ASM_SMP_H */
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 2f182bdf024f..16f022942274 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -383,14 +383,6 @@
RESTORE_SP
.endm
- .macro RESTORE_ALL_AND_RET
- RESTORE_TEMP
- RESTORE_STATIC
- RESTORE_AT
- RESTORE_SOME
- RESTORE_SP_AND_RET
- .endm
-
/*
* Move to kernel mode and disable interrupts.
* Set cp0 enable bit as sign that we're running on the kernel stack
diff --git a/arch/mips/include/asm/string.h b/arch/mips/include/asm/string.h
index 29030cb398ee..7b737f9b6d58 100644
--- a/arch/mips/include/asm/string.h
+++ b/arch/mips/include/asm/string.h
@@ -140,4 +140,42 @@ extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
#define __HAVE_ARCH_MEMMOVE
extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
+#ifndef __ZBOOT__
+#define memset(__s, __c, len) \
+({ \
+ size_t __len = (len); \
+ void *__ret; \
+ if (__builtin_constant_p(len) && __len >= 64) \
+ __ret = memset((__s), (__c), __len); \
+ else \
+ __ret = __builtin_memset((__s), (__c), __len); \
+ __ret; \
+})
+
+#define memcpy(dst, src, len) \
+({ \
+ size_t __len = (len); \
+ void *__ret; \
+ if (__builtin_constant_p(len) && __len >= 64) \
+ __ret = memcpy((dst), (src), __len); \
+ else \
+ __ret = __builtin_memcpy((dst), (src), __len); \
+ __ret; \
+})
+
+#define memmove(dst, src, len) \
+({ \
+ size_t __len = (len); \
+ void *__ret; \
+ if (__builtin_constant_p(len) && __len >= 64) \
+ __ret = memmove((dst), (src), __len); \
+ else \
+ __ret = __builtin_memmove((dst), (src), __len); \
+ __ret; \
+})
+
+#define __HAVE_ARCH_MEMCMP
+#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len))
+#endif
+
#endif /* _ASM_STRING_H */
diff --git a/arch/mips/include/asm/tc3162/cpu-feature-overrides.h b/arch/mips/include/asm/tc3162/cpu-feature-overrides.h
new file mode 100644
index 000000000000..8801b853cac9
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/cpu-feature-overrides.h
@@ -0,0 +1,86 @@
+/*
+ * Ralink specific CPU feature overrides
+ *
+ * This file was derived from: include/asm-mips/cpu-features.h
+ * Copyright (C) 2003, 2004 Ralf Baechle
+ * Copyright (C) 2004 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MACH_MIPS_TC3262_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_MIPS_TC3262_CPU_FEATURE_OVERRIDES_H
+
+/* EN75xx */
+
+/* CPU options */
+#define cpu_has_tlb 1
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 1
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 0
+#define cpu_has_32fpr 0
+#define cpu_has_counter 1
+
+#define cpu_has_watch 1
+#define cpu_has_divec 1
+#define cpu_has_vce 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_cache_cdex_s 0
+#define cpu_has_mcheck 1
+#define cpu_has_ejtag 1
+#define cpu_has_nofpuex 0
+
+#define cpu_has_llsc 1
+#define cpu_has_inclusive_pcaches 0
+#define cpu_has_prefetch 1
+#define cpu_has_vint 1
+#define cpu_has_veic 1
+#define cpu_has_userlocal 1
+#define cpu_has_perf_cntr_intr_bit 1
+#define cpu_has_rixi 0
+
+/* CPU ases */
+#define cpu_has_mips16 1
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+#define cpu_has_dsp 1
+#define cpu_has_mipsmt 1
+#define cpu_has_dsp2 0
+#define cpu_has_vz 0
+
+/* CPU ISA level */
+#define cpu_has_mips_2 1
+#define cpu_has_mips_3 0
+#define cpu_has_mips_4 0
+#define cpu_has_mips_5 0
+#define cpu_has_mips32r1 1
+#define cpu_has_mips32r2 1
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
+#define cpu_has_mips32r6 0
+#define cpu_has_mips64r6 0
+
+#define cpu_has_64bits 0
+#define cpu_has_64bit_zero_reg 0
+#define cpu_has_64bit_gp_regs 0
+#define cpu_has_64bit_addresses 0
+
+/* CPU cache info */
+#define cpu_has_vtag_icache 0
+#define cpu_has_ic_fills_f_dc 0
+#ifdef CONFIG_MIPS_TC3262_1004K
+#define cpu_has_dc_aliases 0
+#else
+#define cpu_icache_snoops_remote_store 1
+#define cpu_has_dc_aliases 1
+#endif
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 32
+
+#endif
diff --git a/arch/mips/include/asm/tc3162/irq.h b/arch/mips/include/asm/tc3162/irq.h
new file mode 100644
index 000000000000..5e6868b5e432
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/irq.h
@@ -0,0 +1,19 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_MIPS_TC3262_IRQ_H
+#define __ASM_MACH_MIPS_TC3262_IRQ_H
+
+#define MIPS_CPU_IRQ_BASE 0
+
+#include <asm/tc3162/surfboardint.h>
+
+#define NR_IRQS (SURFBOARDINT_END + 1)
+
+#include_next <irq.h>
+
+#endif
diff --git a/arch/mips/include/asm/tc3162/launch.h b/arch/mips/include/asm/tc3162/launch.h
new file mode 100644
index 000000000000..b26c4dbf9bea
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/launch.h
@@ -0,0 +1,42 @@
+/*
+ *
+ */
+
+#ifndef _ASSEMBLER_
+
+struct cpulaunch {
+ unsigned long pc;
+ unsigned long gp;
+ unsigned long sp;
+ unsigned long a0;
+ unsigned long _pad[3]; /* pad to cache line size to avoid thrashing */
+ unsigned long flags;
+};
+
+#else
+
+#define LOG2CPULAUNCH 5
+#define LAUNCH_PC 0
+#define LAUNCH_GP 4
+#define LAUNCH_SP 8
+#define LAUNCH_A0 12
+#define LAUNCH_FLAGS 28
+
+#endif
+
+#define LAUNCH_FREADY 1
+#define LAUNCH_FGO 2
+#define LAUNCH_FGONE 4
+
+#define CPULAUNCH 0x00000f00
+#define NCPULAUNCH 8
+
+/* Polling period in count cycles for secondary CPU's */
+#define LAUNCHPERIOD 10000
+
+/* use GDMP SRAM for CPU 1,2,3's waiting code and launch flags */
+#define GDMP_SRAM_BASE 0xBFA40000
+#define BUSY_WAIT_ZONE_START 0x040
+#define BUSY_WAIT_ZONE_SIZE 0x100
+#define BUSY_WAIT_ZONE_BASE (GDMP_SRAM_BASE + BUSY_WAIT_ZONE_START) /* 0xbfa40040 */
+#define CPU_LAUNCH_BASE (GDMP_SRAM_BASE + BUSY_WAIT_ZONE_START + BUSY_WAIT_ZONE_SIZE) /* 0xbfa40140 */
diff --git a/arch/mips/include/asm/tc3162/pbus-timer.h b/arch/mips/include/asm/tc3162/pbus-timer.h
new file mode 100644
index 000000000000..6d02ebcb2748
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/pbus-timer.h
@@ -0,0 +1,139 @@
+#ifndef __ASM_MACH_TC3262_PBUS_TIMER_H
+#define __ASM_MACH_TC3262_PBUS_TIMER_H
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <asm/tc3162/tc3162.h>
+#include <asm/tc3162/tc3262_int_source.h>
+
+#define PBUS_TIMER_0 (0)
+#define PBUS_TIMER_1 (1)
+#define PBUS_TIMER_2 (2)
+#define PBUS_TIMER_3 (5)
+
+#define PBUS_TIMER_WATCHDOG (PBUS_TIMER_3)
+
+#define PBUS_TIMER_0_IRQ (TIMER0_INT)
+#define PBUS_TIMER_1_IRQ (TIMER1_INT)
+#define PBUS_TIMER_2_IRQ (TIMER2_INT)
+#define PBUS_TIMER_3_IRQ (TIMER5_INT)
+
+#define PBUS_TIMER_CTRL (0xbfbf0100)
+#define PBUS_TIMER_LVR(n) (0xbfbf0104 + (n) * 8)
+#define PBUS_TIMER_CVR(n) (0xbfbf0108 + (n) * 8)
+#define PBUS_TIMER_WDOGTHSLD (0xbfbf0134)
+#define PBUS_TIMER_RLDWDOG (0xbfbf0138)
+
+#define PBUS_TIMER_CTRL_HALT(n) (1U << (26 + (n)))
+#define PBUS_TIMER_CTRL_WDG_ENABLE (1U << (25))
+#define PBUS_TIMER_CTRL_INT_ACK(n) (1U << (16 + (n)))
+#define PBUS_TIMER_CTRL_PERIODIC(n) (1U << (8 + (n)))
+#define PBUS_TIMER_CTRL_ENABLE(n) (1U << (0 + (n)))
+
+#define PBUS_TIMER_CTRL_INT_ACK_MASK \
+ (PBUS_TIMER_CTRL_INT_ACK(PBUS_TIMER_0) | \
+ PBUS_TIMER_CTRL_INT_ACK(PBUS_TIMER_1) | \
+ PBUS_TIMER_CTRL_INT_ACK(PBUS_TIMER_2) | \
+ PBUS_TIMER_CTRL_INT_ACK(PBUS_TIMER_3))
+
+#define PBUS_TIMER_TICKS_IN_MSEC ((SYS_HCLK) / 2 * 1000)
+
+static inline void
+pbus_timer_w32(const u32 reg, const u32 val)
+{
+ __raw_writel(val, (void __iomem *)(unsigned long)reg);
+}
+
+static inline u32
+pbus_timer_r32(const u32 reg)
+{
+ return __raw_readl((void __iomem *)(unsigned long)reg);
+}
+
+static inline bool
+pbus_timer_enable(const unsigned int n,
+ const unsigned int interval_ms,
+ const enum pbus_timer_mode mode)
+{
+ u32 ctrl;
+
+ /* an interval is too large */
+ if (U32_MAX / interval_ms < PBUS_TIMER_TICKS_IN_MSEC)
+ return false;
+
+ ctrl = pbus_timer_r32(PBUS_TIMER_CTRL);
+
+ if (mode == PBUS_TIMER_MODE_WATCHDOG) {
+ /* enable a watchdog function for a timer
+ * that does not support it
+ */
+ if (n != PBUS_TIMER_WATCHDOG)
+ return false;
+
+ ctrl |= PBUS_TIMER_CTRL_WDG_ENABLE;
+ pbus_timer_w32(PBUS_TIMER_WDOGTHSLD, U32_MAX);
+ } else {
+ /* use a watchdog timer as an interval or periodic timer
+ */
+ if (n == PBUS_TIMER_WATCHDOG)
+ ctrl &= ~PBUS_TIMER_CTRL_WDG_ENABLE;
+ }
+
+ pbus_timer_w32(PBUS_TIMER_LVR(n),
+ interval_ms * PBUS_TIMER_TICKS_IN_MSEC);
+
+ ctrl &= ~PBUS_TIMER_CTRL_INT_ACK_MASK;
+ ctrl &= ~PBUS_TIMER_CTRL_HALT(n);
+ ctrl |= PBUS_TIMER_CTRL_ENABLE(n);
+
+ if (mode == PBUS_TIMER_MODE_PERIODIC)
+ ctrl |= PBUS_TIMER_CTRL_PERIODIC(n);
+ else
+ ctrl &= ~PBUS_TIMER_CTRL_PERIODIC(n);
+
+ pbus_timer_w32(PBUS_TIMER_CTRL, ctrl);
+
+ return true;
+}
+
+static inline void
+pbus_timer_disable(const unsigned int n)
+{
+ u32 ctrl = pbus_timer_r32(PBUS_TIMER_CTRL);
+
+ ctrl &= ~PBUS_TIMER_CTRL_INT_ACK_MASK;
+ ctrl &= ~PBUS_TIMER_CTRL_ENABLE(n);
+ pbus_timer_w32(PBUS_TIMER_CTRL, ctrl);
+}
+
+static inline void
+pbus_timer_restart(const unsigned int n)
+{
+ u32 ctrl = pbus_timer_r32(PBUS_TIMER_CTRL);
+
+ ctrl &= ~PBUS_TIMER_CTRL_INT_ACK_MASK;
+ ctrl &= ~PBUS_TIMER_CTRL_ENABLE(n);
+ pbus_timer_w32(PBUS_TIMER_CTRL, ctrl);
+
+ ctrl |= PBUS_TIMER_CTRL_ENABLE(n);
+ pbus_timer_w32(PBUS_TIMER_CTRL, ctrl);
+}
+
+static inline void
+pbus_timer_int_ack(const unsigned int n)
+{
+ u32 ctrl = pbus_timer_r32(PBUS_TIMER_CTRL);
+
+ ctrl &= ~PBUS_TIMER_CTRL_INT_ACK_MASK;
+ ctrl |= PBUS_TIMER_CTRL_INT_ACK(n);
+ pbus_timer_w32(PBUS_TIMER_CTRL, ctrl);
+}
+
+static inline unsigned int
+pbus_timer_get(const unsigned int n)
+{
+ return pbus_timer_r32(PBUS_TIMER_CVR(n)) / PBUS_TIMER_TICKS_IN_MSEC;
+}
+
+#endif /* __ASM_MACH_TC3262_PBUS_TIMER_H */
+
diff --git a/arch/mips/include/asm/tc3162/prom.h b/arch/mips/include/asm/tc3162/prom.h
new file mode 100644
index 000000000000..89009c93d472
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/prom.h
@@ -0,0 +1,35 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * MIPS boards bootprom interface for the Linux kernel.
+ *
+ */
+
+#ifndef _MIPS_PROM_H
+#define _MIPS_PROM_H
+
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *name);
+extern void prom_printf(char *fmt, ...);
+extern void prom_init_cmdline(void);
+extern void prom_free_prom_memory(void);
+
+#endif
diff --git a/arch/mips/include/asm/tc3162/rt_mmap.h b/arch/mips/include/asm/tc3162/rt_mmap.h
new file mode 100644
index 000000000000..5744a1aa00c8
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/rt_mmap.h
@@ -0,0 +1,115 @@
+#ifndef __ASM_MACH_MIPS_TC3262_RT_MMAP_H
+#define __ASM_MACH_MIPS_TC3262_RT_MMAP_H
+
+/* EN7512(3)/EN7516/EN7527/EN7528 */
+
+#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
+#define sysRegRead(phys) (*(volatile unsigned int *)PHYS_TO_K1(phys))
+#define sysRegWrite(phys, val) ((*(volatile unsigned int *)PHYS_TO_K1(phys)) = (val))
+
+#define RALINK_SYSCTL_BASE 0xBFB00000
+#define RALINK_TIMER_BASE 0xBFBF0100
+#define RALINK_MEMCTRL_BASE 0xBFB20000
+#define RALINK_PIO_BASE 0xBFBF0200
+#define RALINK_I2C_BASE 0xBFBF8000
+#define RALINK_UART_LITE_BASE 0xBFBF0000
+#define RALINK_UART_LITE2_BASE 0xBFBF0300
+#define RALINK_PCM_BASE 0xBFBD0000
+#define RALINK_GDMA_BASE 0xBFB30000
+#define RALINK_FRAME_ENGINE_BASE 0xBFB50000
+#define RALINK_ETH_SW_BASE 0xBFB58000
+#define RALINK_CRYPTO_ENGINE_BASE 0xBFB70000
+#define RALINK_PCI_BASE 0xBFB80000
+#define RALINK_PCI_PHY0_BASE 0xBFAF2000
+#define RALINK_PCI_PHY1_BASE 0xBFAC0000
+#define RALINK_USB_HOST_BASE 0x1FB90000
+#define RALINK_XHCI_HOST_BASE 0xBFB90000
+#define RALINK_XHCI_UPHY_BASE 0xBFA80000
+#define RALINK_SFC_BASE 0xBFA10000
+#define RALINK_CHIP_SCU_BASE 0xBFA20000
+#define RALINK_11N_MAC_BASE 0xBFB00000 // Unused
+
+#if defined(CONFIG_ECONET_EN7528)
+#define RALINK_USB_HOST_SIZE 0x00003E00
+#define RALINK_USB_IPPC_BASE 0x1FB93E00
+#define RALINK_USB_UPHY_P0_BASE (RALINK_XHCI_UPHY_BASE + 0x0300)
+#define RALINK_USB_UPHY_P1_BASE (RALINK_XHCI_UPHY_BASE + 0x1300)
+#else
+#define RALINK_USB_HOST_SIZE 0x00004000
+#define RALINK_USB_IPPC_BASE 0x1FA80700
+#define RALINK_USB_UPHY_P0_BASE (RALINK_XHCI_UPHY_BASE + 0x0800)
+#define RALINK_USB_UPHY_P1_BASE (RALINK_XHCI_UPHY_BASE + 0x1000)
+#endif
+
+#if defined(CONFIG_ECONET_EN7528)
+#define RALINK_WOE0_BASE 0x1FA02000
+#define RALINK_WOE1_BASE 0x1FA03000
+
+#define RALINK_WDMA0_BASE 0x1FA06000
+#define RALINK_WDMA1_BASE 0x1FA06400
+#endif
+
+#ifdef CONFIG_MIPS_TC3262_1004K
+/* GIC */
+#define RALINK_GIC_BASE 0x1F8C0000
+#define RALINK_GIC_ADDRSPACE_SZ 0x20000
+
+/* CPC */
+#define RALINK_CPC_BASE 0x1F8E8000
+#define RALINK_CPC_ADDRSPACE_SZ 0x8000
+
+/* GCMP */
+#define RALINK_GCMP_BASE 0x1F8E0000
+#define RALINK_GCMP_ADDRSPACE_SZ 0x8000
+
+/* CM */
+#define CM_GCR_REG0_BASE_VALUE 0x1C000000 /* CM region 0 base address (Palmbus) */
+#define CM_GCR_REG0_MASK_VALUE 0x0000FC00 /* CM region 0 mask (64M) */
+
+#define CM_GCR_REG1_BASE_VALUE 0x20000000 /* CM region 1 base address (PCIe) */
+#define CM_GCR_REG1_MASK_VALUE 0x0000F000 /* CM region 1 mask (256M) */
+#else
+/* Interrupt Controller */
+#define RALINK_INTCL_BASE 0xBFB40000
+#define RALINK_INTCTL_UARTLITE (1<<0)
+#define RALINK_INTCTL_PIO (1<<10)
+#define RALINK_INTCTL_PCM (1<<11)
+#define RALINK_INTCTL_DMA (1<<14)
+#define RALINK_INTCTL_GSW (1<<15)
+#define RALINK_INTCTL_UHST (1<<17)
+#define RALINK_INTCTL_FE (1<<21)
+#define RALINK_INTCTL_QDMA (1<<22)
+#define RALINK_INTCTL_PCIE0 (1<<23)
+#define RALINK_INTCTL_PCIE1 (1<<24)
+
+/* Reset Control Register */
+#define RALINK_INTC_RST (1<<9)
+#endif
+
+/* Reset Control Register */
+#define RALINK_I2S1_RST (1<<0)
+#define RALINK_FE_QDMA_LAN_RST (1<<1)
+#define RALINK_FE_QDMA_WAN_RST (1<<2)
+#define RALINK_PCM2_RST (1<<4)
+#define RALINK_PTM_MAC_RST (1<<5)
+#define RALINK_CRYPTO_RST (1<<6)
+#define RALINK_SAR_RST (1<<7)
+#define RALINK_TIMER_RST (1<<8)
+#define RALINK_BONDING_RST (1<<10)
+#define RALINK_PCM1_RST (1<<11)
+#define RALINK_UART_RST (1<<12)
+#define RALINK_PIO_RST (1<<13)
+#define RALINK_DMA_RST (1<<14)
+#define RALINK_I2C_RST (1<<16)
+#define RALINK_I2S2_RST (1<<17)
+#define RALINK_SPI_RST (1<<18)
+#define RALINK_UARTL_RST (1<<19)
+#define RALINK_FE_RST (1<<21)
+#define RALINK_UHST_RST (1<<22)
+#define RALINK_ESW_RST (1<<23)
+#define RALINK_SFC2_RST (1<<25)
+#define RALINK_PCIE0_RST (1<<26)
+#define RALINK_PCIE1_RST (1<<27)
+#define RALINK_PCIEHB_RST (1<<29)
+
+#endif
diff --git a/arch/mips/include/asm/tc3162/spaces.h b/arch/mips/include/asm/tc3162/spaces.h
new file mode 100644
index 000000000000..30a39e17b7b9
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/spaces.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_MACH_MIPS_TC3262_SPACES_H
+#define __ASM_MACH_MIPS_TC3262_SPACES_H
+
+#define EN75XX_PALMBUS_START 0x1c000000
+
+#if defined(CONFIG_ECONET_EN7512)
+#define EN75XX_HIGHMEM_START 0x40000000
+#else
+#define EN75XX_HIGHMEM_START 0x9c000000
+#endif
+
+#define HIGHMEM_START _AC(EN75XX_HIGHMEM_START, UL)
+
+#include <asm/mach-generic/spaces.h>
+
+#endif
diff --git a/arch/mips/include/asm/tc3162/surfboardint.h b/arch/mips/include/asm/tc3162/surfboardint.h
new file mode 100644
index 000000000000..5e9ef691d6ec
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/surfboardint.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2001 Palmchip Corporation. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Defines for the Surfboard interrupt controller.
+ *
+ */
+#ifndef __ASM_MACH_MIPS_TC3262_SURFBOARDINT_H
+#define __ASM_MACH_MIPS_TC3262_SURFBOARDINT_H
+
+#include "tc3262_int_source.h"
+
+#if defined(CONFIG_MIPS_TC3262_1004K)
+
+/* MIPS GIC controller (via EIC) */
+#define GIC_NUM_INTRS 64
+#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 0)
+
+#define SURFBOARDINT_UART_LITE1 UART_INT /* UART Lite1 */
+#define SURFBOARDINT_TIMER0 TIMER0_INT, /* Timer0 */
+#define SURFBOARDINT_TIMER1 TIMER1_INT /* Timer1 */
+#define SURFBOARDINT_TIMER2 TIMER2_INT /* Timer2 */
+#define SURFBOARDINT_WDG TIMER5_INT /* WDG timer */
+#define SURFBOARDINT_GPIO GPIO_INT /* GPIO */
+#define SURFBOARDINT_PCM PCM1_INT /* PCM */
+#define SURFBOARDINT_ESW MAC1_INT /* ESW */
+#define SURFBOARDINT_UART_LITE2 UART2_INT /* UART Lite2 */
+#define SURFBOARDINT_USB IRQ_RT3XXX_USB /* USB */
+#define SURFBOARDINT_DMT DMT_INT /* xDSL DMT */
+#define SURFBOARDINT_QDMA1 QDMA_LAN0_INTR /* QDMA1, INT0 */
+#define SURFBOARDINT_QDMA2 QDMA_WAN0_INTR /* QDMA2, INT0 */
+#define SURFBOARDINT_PCIE0 PCIE_0_INT /* PCIE0 */
+#define SURFBOARDINT_PCIE1 PCIE_A_INT /* PCIE1 */
+#define SURFBOARDINT_CRYPTO CRYPTO_INT /* CryptoEngine */
+#define SURFBOARDINT_QDMA1_INT1 QDMA_LAN1_INTR /* QDMA1, INT1 */
+#define SURFBOARDINT_QDMA1_INT2 QDMA_LAN2_INTR /* QDMA1, INT2 */
+#define SURFBOARDINT_QDMA1_INT3 QDMA_LAN3_INTR /* QDMA1, INT3 */
+#define SURFBOARDINT_QDMA2_INT1 QDMA_WAN1_INTR /* QDMA2, INT1 */
+#define SURFBOARDINT_QDMA2_INT2 QDMA_WAN2_INTR /* QDMA2, INT2 */
+#define SURFBOARDINT_QDMA2_INT3 QDMA_WAN3_INTR /* QDMA2, INT3 */
+#define SURFBOARDINT_UART1 SURFBOARDINT_UART_LITE1
+#define SURFBOARDINT_UART2 SURFBOARDINT_UART_LITE2
+
+#define SURFBOARDINT_END (INTR_SOURCES_NUM - 1)
+
+#elif defined(CONFIG_MIPS_TC3262_34K)
+
+#define SURFBOARDINT_UART1 UART_INT /* UART1 */
+#define SURFBOARDINT_GPIO GPIO_INT /* GPIO */
+#define SURFBOARDINT_PCM PCM1_INT /* PCM1 */
+#define SURFBOARDINT_DMA APB_DMA0_INT /* DMA */
+#define SURFBOARDINT_ESW ESW_INT /* ESW */
+#define SURFBOARDINT_USB IRQ_RT3XXX_USB /* USB */
+#define SURFBOARDINT_FE FE_MAC_INT /* Frame Engine */
+#define SURFBOARDINT_QDMA SAR_INT /* QDMA */
+#define SURFBOARDINT_PCIE0 PCIE_0_INT /* PCIe0 */
+#define SURFBOARDINT_PCIE1 PCIE_A_INT /* PCIe1 */
+#define SURFBOARDINT_CRYPTO CRYPTO_INT /* CryptoEngine */
+
+#define SURFBOARDINT_END 40 /* 1 offset + 40 TC */
+
+#endif
+#endif
diff --git a/arch/mips/include/asm/tc3162/tc3162.h b/arch/mips/include/asm/tc3162/tc3162.h
new file mode 100644
index 000000000000..d30e49b57c6f
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/tc3162.h
@@ -0,0 +1,912 @@
+/*
+** $Id: tc3162.h,v 1.7 2011/01/07 06:05:58 pork Exp $
+*/
+/************************************************************************
+ *
+ * Copyright (C) 2006 Trendchip Technologies, Corp.
+ * All Rights Reserved.
+ *
+ * Trendchip Confidential; Need to Know only.
+ * Protected as an unpublished work.
+ *
+ * The computer program listings, specifications and documentation
+ * herein are the property of Trendchip Technologies, Co. and shall
+ * not be reproduced, copied, disclosed, or used in whole or in part
+ * for any reason without the prior express written permission of
+ * Trendchip Technologeis, Co.
+ *
+ *************************************************************************/
+/*
+** $Log: tc3162.h,v $
+** Revision 1.7 2011/01/07 06:05:58 pork
+** add the definition of INT!16,INT32,SINT15,SINT7
+**
+** Revision 1.6 2010/09/20 07:08:02 shnwind
+** decrease nf_conntrack buffer size
+**
+** Revision 1.5 2010/09/03 16:43:07 here
+** [Ehance] TC3182 GMAC Driver is support TC-Console & WAN2LAN function & update the tc3182 dmt version (3.12.8.83)
+**
+** Revision 1.4 2010/09/02 07:04:50 here
+** [Ehance] Support TC3162U/TC3182 Auto-Bench
+**
+** Revision 1.3 2010/08/30 07:53:02 lino
+** add power saving mode kernel module support
+**
+** Revision 1.2 2010/06/05 05:40:29 lino
+** add tc3182 asic board support
+**
+** Revision 1.1.1.1 2010/04/09 09:39:21 feiyan
+** New TC Linux Make Flow Trunk
+**
+** Revision 1.4 2010/01/14 10:56:42 shnwind
+** recommit
+**
+** Revision 1.3 2010/01/14 08:00:10 shnwind
+** add TC3182 support
+**
+** Revision 1.2 2010/01/10 15:27:26 here
+** [Ehancement]TC3162U MAC EEE is operated at 100M-FD, SAR interface is accroding the SAR_CLK to calculate atm rate.
+**
+** Revision 1.1.1.1 2009/12/17 01:42:47 josephxu
+** 20091217, from Hinchu ,with VoIP
+**
+** Revision 1.2 2006/07/06 07:24:57 lino
+** update copyright year
+**
+** Revision 1.1.1.1 2005/11/02 05:45:38 lino
+** no message
+**
+** Revision 1.5 2005/09/27 08:01:38 bread.hsu
+** adding IMEM support for Tc3162L2
+**
+** Revision 1.4 2005/09/14 11:06:20 bread.hsu
+** new definition for TC3162L2
+**
+** Revision 1.3 2005/06/17 16:26:16 jasonlin
+** Remove redundant code to gain extra 100K bytes free memory.
+** Add "CODE_REDUCTION" definition to switch
+**
+** Revision 1.2 2005/06/14 10:02:01 jasonlin
+** Merge TC3162L2 source code into new main trunk
+**
+** Revision 1.1.1.1 2005/03/30 14:04:22 jasonlin
+** Import Linos source code
+**
+** Revision 1.4 2004/11/15 03:43:17 lino
+** rename ATM SAR max packet length register
+**
+** Revision 1.3 2004/09/01 13:15:47 lino
+** fixed when pc shutdown, system will reboot
+**
+** Revision 1.2 2004/08/27 12:16:37 lino
+** change SYS_HCLK to 96Mhz
+**
+** Revision 1.1 2004/07/02 08:03:04 lino
+** tc3160 and tc3162 code merge
+**
+*/
+
+#ifndef _TC3162_H_
+#define _TC3162_H_
+
+#include <asm/setup.h>
+
+#include "tc3262_int_source.h"
+
+#ifndef INT32
+#define INT32
+typedef signed long int int32; /* 32-bit signed integer */
+#endif
+
+#ifndef SINT31
+#define SINT31
+typedef signed long int sint31; /* 32-bit signed integer */
+#endif
+
+#ifndef UINT32
+#define UINT32
+typedef unsigned long int uint32; /* 32-bit unsigned integer */
+#endif
+
+#ifndef SINT15
+#define SINT15
+typedef signed short sint15; /* 16-bit signed integer */
+#endif
+
+#ifndef INT16
+#define INT16
+typedef signed short int int16; /* 16-bit signed integer */
+#endif
+
+#ifndef UINT16
+#define UINT16
+typedef unsigned short uint16; /* 16-bit unsigned integer */
+#endif
+
+#ifndef SINT7
+#define SINT7
+typedef signed char sint7; /* 8-bit signed integer */
+#endif
+
+#ifndef UINT8
+#define UINT8
+typedef unsigned char uint8; /* 8-bit unsigned integer */
+#endif
+
+#ifndef VPint
+#define VPint *(volatile unsigned long int *)
+#endif
+#ifndef VPshort
+#define VPshort *(volatile unsigned short *)
+#endif
+#ifndef VPchar
+#define VPchar *(volatile unsigned char *)
+#endif
+
+static inline uint32 regRead32(uint32 reg)
+{
+ return VPint(reg);
+}
+
+static inline void regWrite32(uint32 reg, uint32 val)
+{
+ VPint(reg) = val;
+}
+
+#define isRT63365 (((VPint(0xbfb00064) & 0xffff0000)) == 0x00040000)
+#define isMT751020 (((VPint(0xbfb00064) & 0xffff0000)) == 0x00050000)
+#define isMT7505 (((VPint(0xbfb00064) & 0xffff0000)) == 0x00060000)
+#define isEN7526c (((VPint(0xbfb00064) & 0xffff0000)) == 0x00080000)
+#define isEN751221 ((((VPint(0xbfb00064) & 0xffff0000)) == 0x00070000) || isEN7526c)
+#define isEN7528 (((VPint(0xbfb00064) & 0xffff0000)) == 0x000B0000)
+#ifdef CONFIG_ECONET_EN7528
+#define isEN751627 ((((VPint(0xbfb00064) & 0xffff0000)) == 0x00090000) || isEN7528)
+#else
+#define isEN751627 (((VPint(0xbfb00064) & 0xffff0000)) == 0x00090000)
+#endif
+#define isEN7580 (((VPint(0xbfb00064) & 0xffff0000)) == 0x000A0000)
+
+/* Support old xDSL chips */
+#define isTC3162L2P2 ((((unsigned char)(VPint(0xbfb0008c)>>12)&0xff)!=0)&&(((VPint(0xbfb00064)&0xffffffff))==0x00000000)?1:0)
+#define isTC3162L3P3 ((((unsigned char)(VPint(0xbfb0008c)>>12)&0xff)==7)&&(((VPint(0xbfb00064)&0xffffffff))==0x00000000)?1:0)
+#define isTC3162L4P4 ((((unsigned char)(VPint(0xbfb0008c)>>12)&0xff)==8)&&(((VPint(0xbfb00064)&0xffffffff))==0x00000000)?1:0)
+#define isTC3162L5P5E2 ((((unsigned char)(VPint(0xbfb0008c)>>12)&0xff)==0xa)&&(((VPint(0xbfb00064)&0xffffffff))==0x00000000)?1:0)
+#define isTC3162L5P5E3 ((((unsigned char)(VPint(0xbfb0008c)>>12)&0xff)==0xb)&&(((VPint(0xbfb00064)&0xffffffff))==0x00000000)?1:0)
+#define isTC3162L5P5 (isTC3162L5P5E2 || isTC3162L5P5E3)
+#define isTC3162U ((((unsigned char)(VPint(0xbfb0008c)>>12)&0xff)==0x10)&&(((VPint(0xbfb00064)&0xffffffff))==0x00000000)?1:0)
+#define isRT63260 ((((unsigned char)(VPint(0xbfb0008c)>>12)&0xff)==0x20)&&(((VPint(0xbfb00064)&0xffffffff))==0x00000000)?1:0)
+#define isTC3169 (((VPint(0xbfb00064)&0xffff0000))==0x00000000)
+#define isTC3182 (((VPint(0xbfb00064)&0xffff0000))==0x00010000)
+#define isRT65168 (((VPint(0xbfb00064)&0xffff0000))==0x00020000)
+#define isRT63165 (((VPint(0xbfb00064)&0xffff0000))==0x00030000)
+
+#define PDIDR (VPint(0xBFB0005C)&0xFFFF)
+#define isEN751221FPGA ((VPint(0xBFB0008C) & (1 << 29)) ? 0 : 1) //used for 7512/7521
+#define isGenernalFPGA ((VPint(0xBFB0008C) & (1 << 31)) ? 1 : 0) //used for 63365/751020
+#define isGenernalFPGA_2 (((VPint(CR_AHB_SSTR) & 0x1) == 0) ? 1 : 0) //used for EN7526c and later version
+#if defined(CONFIG_ECONET_EN7516) || \
+ defined(CONFIG_ECONET_EN7527) || \
+ defined(CONFIG_ECONET_EN7528)
+#define isFPGA 0 // GET_IS_FPGA
+#define SYNC_TYPE4() __asm__ volatile ("sync 0x4")
+#else
+#define isFPGA 0 //(isEN7526c ? isGenernalFPGA_2 : (isEN751221 ? isEN751221FPGA : isGenernalFPGA))
+#endif
+
+#define isEN751627QFP (((VPint(0xbfa20174) & 0x8000) == 0x8000) ? 1 : 0)
+
+#define EFUSE_VERIFY_DATA0 (0xBFBF8214)
+#define EFUSE_VERIFY_DATA1 (0xBFBF8218)
+#define EFUSE_PKG_MASK_7516 (0xC0000)
+#define EFUSE_REMARK_BIT_7516 (1 << 0)
+#define EFUSE_PKG_REMARK_SHITF_7516 2
+#define EFUSE_PKG_MASK (0x3F)
+#define EFUSE_REMARK_BIT (1 << 6)
+#define EFUSE_PKG_REMARK_SHITF 7
+
+#define EFUSE_EN7512 (0x4)
+#define EFUSE_EN7513 (0x5)
+#define EFUSE_EN7513G (0x6)
+#define EFUSE_EN7516G (0x80000)
+#define EFUSE_EN7561G (0xC0000)
+#define EFUSE_EN7527H (0x0)
+#define EFUSE_EN7527G (0x0)
+
+#define isEN7512 (isEN751221 && \
+ ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT)? \
+ (((VPint(EFUSE_VERIFY_DATA0) >> EFUSE_PKG_REMARK_SHITF) & EFUSE_PKG_MASK) == EFUSE_EN7512): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_PKG_MASK) == EFUSE_EN7512)))
+
+#define isEN7513 (isEN751221 && \
+ ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT)? \
+ (((VPint(EFUSE_VERIFY_DATA0) >> EFUSE_PKG_REMARK_SHITF) & EFUSE_PKG_MASK) == EFUSE_EN7513): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_PKG_MASK) == EFUSE_EN7513)))
+
+#define isEN7513G (isEN751221 && \
+ ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT)? \
+ (((VPint(EFUSE_VERIFY_DATA0) >> EFUSE_PKG_REMARK_SHITF) & EFUSE_PKG_MASK) == EFUSE_EN7513G): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_PKG_MASK) == EFUSE_EN7513G)))
+
+#define isEN7516G (isEN751627 && \
+ ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT_7516)? \
+ (((VPint(EFUSE_VERIFY_DATA0) >> EFUSE_PKG_REMARK_SHITF_7516) & EFUSE_PKG_MASK_7516) == EFUSE_EN7516G): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_PKG_MASK_7516) == EFUSE_EN7516G)))
+
+#define isEN7561G (isEN751627 && !isEN751627QFP && \
+ ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT_7516)? \
+ (((VPint(EFUSE_VERIFY_DATA0) >> EFUSE_PKG_REMARK_SHITF_7516) & EFUSE_PKG_MASK_7516) == EFUSE_EN7561G): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_PKG_MASK_7516) == EFUSE_EN7516G)))
+
+#define isEN7527H (isEN751627 && isEN751627QFP && \
+ ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT_7516)? \
+ (((VPint(EFUSE_VERIFY_DATA0) >> EFUSE_PKG_REMARK_SHITF_7516) & EFUSE_PKG_MASK_7516) == EFUSE_EN7527H): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_PKG_MASK_7516) == EFUSE_EN7527H)))
+
+#define isEN7527G (isEN751627 && !isEN751627QFP && \
+ ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT_7516)? \
+ (((VPint(EFUSE_VERIFY_DATA0) >> EFUSE_PKG_REMARK_SHITF_7516) & EFUSE_PKG_MASK_7516) == EFUSE_EN7527G): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_PKG_MASK_7516) == EFUSE_EN7527G)))
+
+#define isEN7528HU (isEN7528 && (GET_PACKAGE_ID == 0x0))
+#define isEN7528DU (isEN7528 && (GET_PACKAGE_ID == 0x1))
+#define isEN7561DU (isEN7528 && (GET_PACKAGE_ID == 0x2))
+#define isEN7526FH_EN7528DU (isEN7528 && (GET_PACKAGE_ID == 0x3))
+#define isEN7521G_EN7528DU (isEN7528 && (GET_PACKAGE_ID == 0x7))
+
+#define EFUSE_DDR3_BIT (1 << 23)
+#define EFUSE_DDR3_REMARK_BIT (1 << 24)
+#define EFUSE_IS_DDR3 ( (VPint(EFUSE_VERIFY_DATA0) & EFUSE_REMARK_BIT)? \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_DDR3_REMARK_BIT)): \
+ ((VPint(EFUSE_VERIFY_DATA0) & EFUSE_DDR3_BIT)))
+
+#define REG_SAVE_INFO 0xBFB00284
+#define GET_REG_SAVE_INFO_POINT ((volatile SYS_GLOBAL_PARM_T *)REG_SAVE_INFO)
+
+typedef union {
+ struct {
+ uint32 packageID : 4;
+ uint32 isDDR4 : 1;
+ uint32 isSecureHwTrapEn : 1; /* detect secure HW trap */
+ uint32 isSecureModeEn : 1; /* RSA key has been written or not */
+ uint32 isFlashBoot : 1;
+ uint32 isCtrlEcc : 1;
+ uint32 isFpga : 1;
+ uint32 sys_clk : 10; /* bus clock can support up to 1024MHz */
+ uint32 dram_size : 12; /* DRAM size can support up to 2048MB */
+ } raw ;
+ uint32 word;
+} SYS_GLOBAL_PARM_T ;
+
+#define GET_IS_DDR4 (GET_REG_SAVE_INFO_POINT->raw.isDDR4)
+#define GET_DRAM_SIZE (GET_REG_SAVE_INFO_POINT->raw.dram_size)
+#define GET_SYS_CLK (GET_REG_SAVE_INFO_POINT->raw.sys_clk)
+#define GET_IS_FPGA (GET_REG_SAVE_INFO_POINT->raw.isFpga)
+#define GET_IS_SPI_ECC (GET_REG_SAVE_INFO_POINT->raw.isCtrlEcc)
+#define GET_PACKAGE_ID (GET_REG_SAVE_INFO_POINT->raw.packageID)
+#define GET_IS_SECURE_MODE (GET_REG_SAVE_INFO_POINT->raw.isSecureModeEn)
+#define GET_IS_SECURE_HWTRAP (GET_REG_SAVE_INFO_POINT->raw.isSecureHwTrapEn)
+
+#define SYS_HCLK (GET_SYS_CLK)
+#define SAR_CLK ((SYS_HCLK)/(4.0)) //more accurate if 4.0 not 4
+
+/* define CPU timer clock, FPGA is 50Mhz, ASIC is 200Mhz */
+#define CPUTMR_CLK (isFPGA ? (50*1000000) : (200*1000000))
+
+#define isMT7530 (((VPint(0xbfb58000 + 0x7ffc) & 0xffff0000)) == 0x75300000)
+
+#define DSPRAM_BASE 0x9c000000
+
+#define ENABLE 1
+#define DISABLE 0
+
+#define WAN2LAN_CH_ID (1<<31)
+
+#define tc_inb(offset) (*(volatile unsigned char *)(offset))
+#define tc_inw(offset) (*(volatile unsigned short *)(offset))
+#define tc_inl(offset) (*(volatile unsigned long *)(offset))
+
+#define tc_outb(offset,val) (*(volatile unsigned char *)(offset) = val)
+#define tc_outw(offset,val) (*(volatile unsigned short *)(offset) = val)
+#define tc_outl(offset,val) (*(volatile unsigned long *)(offset) = val)
+
+#define IS_SPIFLASH ((~(VPint(0xBFA10114))) & 0x2)
+#define IS_NANDFLASH (VPint(0xBFA10114) & 0x2)
+#ifdef TCSUPPORT_SPI_CONTROLLER_ECC
+#define isSpiControllerECC (GET_IS_SPI_ECC)
+#else
+#define isSpiControllerECC (0)
+#endif
+#define isSpiNandAndCtrlECC (IS_NANDFLASH && isSpiControllerECC)
+
+/*****************************
+ * RBUS CORE Module Registers *
+ *****************************/
+#define ARB_CFG 0xBFA00008
+#define ROUND_ROBIN_ENABLE (1<<30)
+#define ROUND_ROBIN_DISABLE ~(1<<30)
+
+#if defined(CONFIG_ECONET_EN7528)
+#define RBUS_TIMEOUT_STS0 0xBFA000D0
+#define RBUS_TIMEOUT_CFG0 0xBFA000D8
+#define RBUS_TIMEOUT_CFG1 0xBFA000DC
+#define RBUS_TIMEOUT_CFG2 0xBFA000E0
+#endif
+
+/*****************************
+ * DMC Module Registers *
+ *****************************/
+
+#define CR_DMC_BASE 0xBFB20000
+#define CR_DMC_SRT (0x00 | CR_DMC_BASE)
+#define CR_DMC_STC (0x01 | CR_DMC_BASE)
+#define CR_DMC_SAMT (0x02 | CR_DMC_BASE)
+#define CR_DMC_SCR (0x03 | CR_DMC_BASE)
+
+/* RT63165 specific */
+/* DDR self refresh control register */
+#define CR_DMC_DDR_SR (0x18 | CR_DMC_BASE)
+/* DDR self refresh target count */
+#define CR_DMC_DDR_SR_CNT (0x1c | CR_DMC_BASE)
+#define CR_DMC_DDR_CFG0 (0x40 | CR_DMC_BASE)
+#define CR_DMC_DDR_CFG1 (0x44 | CR_DMC_BASE)
+#define CR_DMC_DDR_CFG2 (0x48 | CR_DMC_BASE)
+#define CR_DMC_DDR_CFG3 (0x4c | CR_DMC_BASE)
+#define CR_DMC_DDR_CFG4 (0x50 | CR_DMC_BASE)
+#define CR_DMC_DDR_CFG8 (0x60 | CR_DMC_BASE)
+#define CR_DMC_DDR_CFG9 (0x64 | CR_DMC_BASE)
+
+#define CR_DMC_CTL0 (0x70 | CR_DMC_BASE)
+#define CR_DMC_CTL1 (0x74 | CR_DMC_BASE)
+#define CR_DMC_CTL2 (0x78 | CR_DMC_BASE)
+#define CR_DMC_CTL3 (0x7c | CR_DMC_BASE)
+#define CR_DMC_CTL4 (0x80 | CR_DMC_BASE)
+
+#define CR_DMC_DCSR (0xb0 | CR_DMC_BASE)
+
+#define CR_DMC_ISPCFGR (0xc0 | CR_DMC_BASE)
+#define CR_DMC_DSPCFGR (0xc4 | CR_DMC_BASE)
+/*****************************
+ * GDMA Module Registers *
+ *****************************/
+
+#define CR_GDMA_BASE 0xBFB30000
+#define CR_GDMA_DCSA (0x00 | CR_GDMA_BASE)
+#define CR_GDMA_DCDA (0x04 | CR_GDMA_BASE)
+#define CR_GDMA_DCBT (0x08 | CR_GDMA_BASE)
+#define CR_GDMA_DCBL (0x0a | CR_GDMA_BASE)
+#define CR_GDMA_DCC (0x0c | CR_GDMA_BASE)
+#define CR_GDMA_DCS (0x0e | CR_GDMA_BASE)
+#define CR_GDMA_DCKSUM (0x10 | CR_GDMA_BASE)
+
+/*****************************
+ * SPI Module Registers *
+ *****************************/
+
+#define CR_SPI_BASE 0xBFBC0000
+#define CR_SPI_CTL (0x00 | CR_SPI_BASE)
+#define CR_SPI_OPCODE (0x04 | CR_SPI_BASE)
+#define CR_SPI_DATA (0x08 | CR_SPI_BASE)
+
+/*****************************
+ * Ethernet Module Registers *
+ *****************************/
+
+#define CR_MAC_BASE 0xBFB50000
+#define CR_MAC_ISR (0x00 | CR_MAC_BASE)// --- Interrupt Status Register ---
+#define CR_MAC_IMR (0x04 | CR_MAC_BASE)// --- Interrupt Mask Register ---
+#define CR_MAC_MADR (0x08 | CR_MAC_BASE)// --- MAC Address Register [47:32] ---
+#define CR_MAC_LADR (0x0c | CR_MAC_BASE)// --- MAC Address Register [31:0] ---
+#define CR_MAC_EEE (0x10 | CR_MAC_BASE)
+#define CR_MAC_TXPD (0x18 | CR_MAC_BASE)// --- Transmit Poll Demand Register ---
+#define CR_MAC_RXPD (0x1c | CR_MAC_BASE)// --- Receive Poll Demand Register ---
+#define CR_MAC_TXR_BADR (0x20 | CR_MAC_BASE)// --- Transmit Ring Base Address Register ---
+#define CR_MAC_RXR_BADR (0x24 | CR_MAC_BASE)// --- Receive Ring Base Address Register ---
+#define CR_MAC_ITC (0x28 | CR_MAC_BASE)// --- Interrupt Timer Control Register ---
+#define CR_MAC_TXR_SIZE (0x2c | CR_MAC_BASE)// --- Transmit Ring Size Register ---
+#define CR_MAC_RXR_SIZE (0x30 | CR_MAC_BASE)// --- Receive Ring Size Register ---
+#define CR_MAC_RXR_SWIDX (0x34 | CR_MAC_BASE)// --- Receive Ring Software Index Register ---
+#define CR_MAC_TXDESP_SIZE (0x38 | CR_MAC_BASE)// --- Transmit Descriptor Size Register ---
+#define CR_MAC_RXDESP_SIZE (0x3c | CR_MAC_BASE)// --- Receive Descriptor Size Register ---
+#define CR_MAC_PRIORITY_CFG (0x50 | CR_MAC_BASE)// --- Priority Configuration Register ---
+#define CR_MAC_VLAN_CFG (0x54 | CR_MAC_BASE)// --- VLAN Configuration Register ---
+#define CR_MAC_TOS0_CFG (0x58 | CR_MAC_BASE)// --- TOS 0 Configuration Register ---
+#define CR_MAC_TOS1_CFG (0x5c | CR_MAC_BASE)// --- TOS 1 Configuration Register ---
+#define CR_MAC_TOS2_CFG (0x60 | CR_MAC_BASE)// --- TOS 2 Configuration Register ---
+#define CR_MAC_TOS3_CFG (0x64 | CR_MAC_BASE)// --- TOS 3 Configuration Register ---
+#define CR_MAC_TCP_CFG (0x68 | CR_MAC_BASE)// --- TCP Configuration Register ---
+#define CR_MAC_SWTAG_CFG (0x6c | CR_MAC_BASE)// --- Software Tagging Configuration Register ---
+#define CR_MAC_PMBL_CYC_NUM (0x70 | CR_MAC_BASE)// --- Preamble Cycle Number Register ---
+#define CR_MAC_FCTL_CYC_NUM (0x74 | CR_MAC_BASE)// --- Flow Control Cycle Number Register ---
+#define CR_MAC_JAM_CYC_NUM (0x78 | CR_MAC_BASE)// --- JAM Cycle Number Register ---
+#define CR_MAC_DEFER_VAL (0x7c | CR_MAC_BASE)// --- Defer Value Register ---
+#define CR_MAC_RANDOM_POLY (0x80 | CR_MAC_BASE)// --- Random Polynomial Register ---
+#define CR_MAC_MACCR (0x88 | CR_MAC_BASE)// --- MAC Control Register ---
+#define CR_MAC_MACSR (0x8c | CR_MAC_BASE)// --- MAC Status Register ---
+#define CR_MAC_PHYCR (0x90 | CR_MAC_BASE)// --- PHY Control Register ---
+#define CR_MAC_PHYWDATA (0x94 | CR_MAC_BASE)// --- PHY Write Data Register ---
+#define CR_MAC_FCR (0x98 | CR_MAC_BASE)// --- Flow Control Register ---
+#define CR_MAC_BPR (0x9c | CR_MAC_BASE)// --- Back Pressure Register ---
+#define CR_MAC_DESP_IDX (0xc4 | CR_MAC_BASE)// --- Current Tx/Rx Descriptor Index ---
+#define CR_MAC_WOLCR (0xa0 | CR_MAC_BASE)// --- Wake-On-LAN Control Register ---
+#define CR_MAC_WOLSR (0xa4 | CR_MAC_BASE)// --- Wake-On-LAN Status Register ---
+#define CR_MAC_WFCRC (0xa8 | CR_MAC_BASE)// --- Wake-up Frame CRC Register ---
+#define CR_MAC_WFBM1 (0xb0 | CR_MAC_BASE)// --- Wake-up Frame Byte Mask 1st Double Word Register ---
+#define CR_MAC_WFBM2 (0xb4 | CR_MAC_BASE)// --- Wake-up Frame Byte Mask 2nd Double Word Register ---
+#define CR_MAC_WFBM3 (0xb8 | CR_MAC_BASE)// --- Wake-up Frame Byte Mask 3rd Double Word Register ---
+#define CR_MAC_WFBM4 (0xbc | CR_MAC_BASE)// --- Wake-up Frame Byte Mask 4th Double Word Register ---
+#define CR_MAC_DMA_FSM (0xc8 | CR_MAC_BASE)// --- DMA State Machine
+#define CR_MAC_TM (0xcc | CR_MAC_BASE)// --- Test Mode Register ---
+#define CR_MAC_XMPG_CNT (0xdc | CR_MAC_BASE)// --- XM and PG Counter Register ---
+#define CR_MAC_RUNT_TLCC_CNT (0xe0 | CR_MAC_BASE)// --- Receive Runt and Transmit Late Collision Packet Counter Register ---
+#define CR_MAC_RCRC_RLONG_CNT (0xe4 | CR_MAC_BASE)// --- Receive CRC Error and Long Packet Counter Register ---
+#define CR_MAC_RLOSS_RCOL_CNT (0xe8 | CR_MAC_BASE)// --- Receive Packet Loss and Receive Collision Counter Register ---
+#define CR_MAC_BROADCAST_CNT (0xec | CR_MAC_BASE)// --- Receive Broadcast Counter Register ---
+#define CR_MAC_MULTICAST_CNT (0xf0 | CR_MAC_BASE)// --- Receive Multicast Counter Register ---
+#define CR_MAC_RX_CNT (0xf4 | CR_MAC_BASE)// --- Receive Good Packet Counter Register ---
+#define CR_MAC_TX_CNT (0xf8 | CR_MAC_BASE)// --- Transmit Good Packet Counter Register ---
+
+/*************************
+ * UART Module Registers *
+ *************************/
+#ifdef __BIG_ENDIAN
+#define CR_UART_OFFSET (0x03)
+#else
+#define CR_UART_OFFSET (0x0)
+#endif
+
+#define CR_UART_BASE 0xBFBF0000
+#define CR_UART_RBR (0x00+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_THR (0x00+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_IER (0x04+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_IIR (0x08+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_FCR (0x08+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_LCR (0x0c+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_MCR (0x10+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_LSR (0x14+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_MSR (0x18+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_SCR (0x1c+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_BRDL (0x00+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_BRDH (0x04+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_WORDA (0x20+CR_UART_BASE+0x00)
+#define CR_UART_HWORDA (0x28+CR_UART_BASE+0x00)
+#define CR_UART_MISCC (0x24+CR_UART_BASE+CR_UART_OFFSET)
+#define CR_UART_XYD (0x2c+CR_UART_BASE)
+
+#define UART_BRD_ACCESS 0x80
+#define UART_XYD_Y 65000
+#define UART_UCLK_115200 0
+#define UART_UCLK_57600 1
+#define UART_UCLK_38400 2
+#define UART_UCLK_28800 3
+#define UART_UCLK_19200 4
+#define UART_UCLK_14400 5
+#define UART_UCLK_9600 6
+#define UART_UCLK_4800 7
+#define UART_UCLK_2400 8
+#define UART_UCLK_1200 9
+#define UART_UCLK_600 10
+#define UART_UCLK_300 11
+#define UART_UCLK_110 12
+#define UART_BRDL 0x03
+#define UART_BRDH 0x00
+#define UART_BRDL_20M 0x01
+#define UART_BRDH_20M 0x00
+#define UART_LCR 0x03
+#define UART_FCR 0x0f
+#define UART_WATERMARK (0x0<<6)
+#define UART_MCR 0x0
+#define UART_MISCC 0x0
+#define UART_IER 0x01
+
+#define IER_RECEIVED_DATA_INTERRUPT_ENABLE 0x01
+#define IER_THRE_INTERRUPT_ENABLE 0x02
+#define IER_LINE_STATUS_INTERRUPT_ENABLE 0x04
+
+#define IIR_INDICATOR VPchar(CR_UART_IIR)
+#define IIR_RECEIVED_LINE_STATUS 0x06
+#define IIR_RECEIVED_DATA_AVAILABLE 0x04
+#define IIR_RECEIVER_IDLE_TRIGGER 0x0C
+#define IIR_TRANSMITTED_REGISTER_EMPTY 0x02
+#define LSR_INDICATOR VPchar(CR_UART_LSR)
+#define LSR_RECEIVED_DATA_READY 0x01
+#define LSR_OVERRUN 0x02
+#define LSR_PARITY_ERROR 0x04
+#define LSR_FRAME_ERROR 0x08
+#define LSR_BREAK 0x10
+#define LSR_THRE 0x20
+#define LSR_THE 0x40
+#define LSR_RFIFO_FLAG 0x80
+
+#define uartTxIntOn() VPchar(CR_UART_IER) |= IER_THRE_INTERRUPT_ENABLE
+#define uartTxIntOff() VPchar(CR_UART_IER) &= ~IER_THRE_INTERRUPT_ENABLE
+#define uartRxIntOn() VPchar(CR_UART_IER) |= IER_RECEIVED_DATA_INTERRUPT_ENABLE
+#define uartRxIntOff() VPchar(CR_UART_IER) &= ~IER_RECEIVED_DATA_INTERRUPT_ENABLE
+
+/*************************
+ * UART2 Module Registers *
+ *************************/
+#if defined(CONFIG_ECONET_EN7516) || \
+ defined(CONFIG_ECONET_EN7527) || \
+ defined(CONFIG_ECONET_EN7528)
+#define CR_UART3_BASE 0xBFBE1000
+#endif
+#define CR_UART2_BASE 0xBFBF0300
+#define CR_UART2_RBR (0x00+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_THR (0x00+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_IER (0x04+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_IIR (0x08+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_FCR (0x08+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_LCR (0x0c+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_MCR (0x10+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_LSR (0x14+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_MSR (0x18+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_SCR (0x1c+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_BRDL (0x00+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_BRDH (0x04+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_WORDA (0x20+CR_UART2_BASE+0x00)
+#define CR_UART2_HWORDA (0x28+CR_UART2_BASE+0x00)
+#define CR_UART2_MISCC (0x24+CR_UART2_BASE+CR_UART_OFFSET)
+#define CR_UART2_XYD (0x2c+CR_UART2_BASE)
+
+#define IIR_INDICATOR2 VPchar(CR_UART2_IIR)
+#define LSR_INDICATOR2 VPchar(CR_UART2_LSR)
+
+/*************************
+ * HSUART Module Registers *
+ *************************/
+#define CR_HSUART_BASE 0xBFBF0300
+#define CR_HSUART_RBR (0x00+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_THR (0x00+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_IER (0x04+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_IIR (0x08+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_FCR (0x08+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_LCR (0x0c+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_MCR (0x10+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_LSR (0x14+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_MSR (0x18+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_SCR (0x1c+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_BRDL (0x00+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_BRDH (0x04+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_WORDA (0x20+CR_HSUART_BASE+0x00)
+#define CR_HSUART_HWORDA (0x28+CR_HSUART_BASE+0x00)
+#define CR_HSUART_MISCC (0x24+CR_HSUART_BASE+CR_UART_OFFSET)
+#define CR_HSUART_XYD (0x2c+CR_HSUART_BASE)
+
+/**********************************
+ * Interrupt Controller Registers *
+ **********************************/
+#define CR_INTC_BASE 0xBFB40000
+ // --- Interrupt Type Register ---
+#define CR_INTC_ITR (CR_INTC_BASE+0x0000)
+ // --- Interrupt Mask Register ---
+#define CR_INTC_IMR (CR_INTC_BASE+0x0004)
+ // --- Interrupt Pending Register ---
+#define CR_INTC_IPR (CR_INTC_BASE+0x0008)
+ // --- Interrupt Set Register ---
+#define CR_INTC_ISR (CR_INTC_BASE+0x000c)
+ // --- Interrupt Priority Register 0 ---
+#define CR_INTC_IPR0 (CR_INTC_BASE+0x0010)
+ // --- Interrupt Priority Register 1 ---
+#define CR_INTC_IPR1 (CR_INTC_BASE+0x0014)
+ // --- Interrupt Priority Register 2 ---
+#define CR_INTC_IPR2 (CR_INTC_BASE+0x0018)
+ // --- Interrupt Priority Register 3 ---
+#define CR_INTC_IPR3 (CR_INTC_BASE+0x001c)
+ // --- Interrupt Priority Register 4 ---
+#define CR_INTC_IPR4 (CR_INTC_BASE+0x0020)
+ // --- Interrupt Priority Register 5 ---
+#define CR_INTC_IPR5 (CR_INTC_BASE+0x0024)
+ // --- Interrupt Priority Register 6 ---
+#define CR_INTC_IPR6 (CR_INTC_BASE+0x0028)
+ // --- Interrupt Priority Register 7 ---
+#define CR_INTC_IPR7 (CR_INTC_BASE+0x002c)
+ // --- Interrupt Vector egister ---
+
+ // --- Interrupt VPE and SRS Register 0 ---
+#define CR_INTC_IVSR0 (CR_INTC_BASE+0x0030)
+ // --- Interrupt VPE and SRS Register 1 ---
+#define CR_INTC_IVSR1 (CR_INTC_BASE+0x0034)
+ // --- Interrupt VPE and SRS Register 2 ---
+#define CR_INTC_IVSR2 (CR_INTC_BASE+0x0038)
+ // --- Interrupt VPE and SRS Register 3 ---
+#define CR_INTC_IVSR3 (CR_INTC_BASE+0x003c)
+ // --- Interrupt VPE and SRS Register 4 ---
+#define CR_INTC_IVSR4 (CR_INTC_BASE+0x0040)
+ // --- Interrupt VPE and SRS Register 5 ---
+#define CR_INTC_IVSR5 (CR_INTC_BASE+0x0044)
+ // --- Interrupt VPE and SRS Register 6 ---
+#define CR_INTC_IVSR6 (CR_INTC_BASE+0x0048)
+ // --- Interrupt VPE and SRS Register 7 ---
+#define CR_INTC_IVSR7 (CR_INTC_BASE+0x004c)
+ // --- Interrupt Vector egister ---
+#define CR_INTC_IVR (CR_INTC_BASE+0x0050)
+
+/* RT63165 */
+ // --- Interrupt Mask Register ---
+#define CR_INTC_IMR_1 (CR_INTC_BASE+0x0050)
+ // --- Interrupt Pending Register ---
+#define CR_INTC_IPR_1 (CR_INTC_BASE+0x0054)
+ // --- Interrupt Priority Register 8 ---
+#define CR_INTC_IPSR8 (CR_INTC_BASE+0x0058)
+ // --- Interrupt Priority Register 9 ---
+#define CR_INTC_IPSR9 (CR_INTC_BASE+0x005c)
+ // --- Interrupt VPE and SRS Register 8 ---
+#define CR_INTC_IVSR8 (CR_INTC_BASE+0x0060)
+ // --- Interrupt VPE and SRS Register 9 ---
+#define CR_INTC_IVSR9 (CR_INTC_BASE+0x0064)
+
+enum
+interrupt_priority
+{
+ IPL0, IPL1, IPL2, IPL3, IPL4,
+ IPL5, IPL6, IPL7, IPL8, IPL9,
+ IPL10, IPL11, IPL12, IPL13, IPL14,
+ IPL15, IPL16, IPL17, IPL18, IPL19,
+ IPL20, IPL21, IPL22, IPL23, IPL24,
+ IPL25, IPL26, IPL27, IPL28, IPL29,
+ IPL30, IPL31
+};
+
+/**************************
+ * Timer Module Registers *
+ **************************/
+#define CR_CPUTMR_BASE 0xBFBF0400
+#define CR_CPUTMR_CTL (CR_CPUTMR_BASE + 0x00)
+#define CR_CPUTMR_CMR0 (CR_CPUTMR_BASE + 0x04)
+#define CR_CPUTMR_CNT0 (CR_CPUTMR_BASE + 0x08)
+#define CR_CPUTMR_CMR1 (CR_CPUTMR_BASE + 0x0c)
+#define CR_CPUTMR_CNT1 (CR_CPUTMR_BASE + 0x10)
+
+#ifdef CONFIG_MIPS_TC3262_1004K
+#define CR_CPUTMR_23_BASE 0xBFBE0000
+#define CR_CPUTMR_23_CTL (CR_CPUTMR_23_BASE + 0x00)
+#define CR_CPUTMR_CMR2 (CR_CPUTMR_23_BASE + 0x04)
+#define CR_CPUTMR_CNT2 (CR_CPUTMR_23_BASE + 0x08)
+#define CR_CPUTMR_CMR3 (CR_CPUTMR_23_BASE + 0x0c)
+#define CR_CPUTMR_CNT3 (CR_CPUTMR_23_BASE + 0x10)
+#endif
+
+/*************************
+ * GPIO Module Registers *
+ *************************/
+#define CR_GPIO_BASE 0xBFBF0200
+#define CR_GPIO_CTRL (CR_GPIO_BASE + 0x00)
+#define CR_GPIO_DATA (CR_GPIO_BASE + 0x04)
+#define CR_GPIO_INTS (CR_GPIO_BASE + 0x08)
+#define CR_GPIO_EDET (CR_GPIO_BASE + 0x0C)
+#define CR_GPIO_LDET (CR_GPIO_BASE + 0x10)
+#define CR_GPIO_ODRAIN (CR_GPIO_BASE + 0x14)
+#define CR_GPIO_CTRL1 (CR_GPIO_BASE + 0x20)
+
+#define GPIO_IN 0x0
+#define GPIO_OUT 0x1
+#define GPIO_ALT_IN 0x2
+#define GPIO_ALT_OUT 0x3
+
+#define GPIO_E_DIS 0x0
+#define GPIO_E_RISE 0x1
+#define GPIO_E_FALL 0x2
+#define GPIO_E_BOTH 0x3
+
+#define GPIO_L_DIS 0x0
+#define GPIO_L_HIGH 0x1
+#define GPIO_L_LOW 0x2
+#define GPIO_L_BOTH 0x3
+
+/*****************************
+ * Arbiter/Decoder Registers *
+ *****************************/
+#define CR_AHB_BASE 0xBFB00000
+#define CR_AHB_AACS (CR_AHB_BASE + 0x00)
+#define CR_AHB_ABEM (CR_AHB_BASE + 0x08)
+#define CR_AHB_ABEA (CR_AHB_BASE + 0x0C)
+#define CR_AHB_DMB0 (CR_AHB_BASE + 0x10)
+#define CR_AHB_DMB1 (CR_AHB_BASE + 0x14)
+#define CR_AHB_DMB2 (CR_AHB_BASE + 0x18)
+#define CR_AHB_DMB3 (CR_AHB_BASE + 0x1C)
+#define CR_AHB_SMB0 (CR_AHB_BASE + 0x20)
+#define CR_AHB_SMB1 (CR_AHB_BASE + 0x24)
+#define CR_AHB_SMB2 (CR_AHB_BASE + 0x28)
+#define CR_AHB_SMB3 (CR_AHB_BASE + 0x2C)
+#define CR_AHB_SMB4 (CR_AHB_BASE + 0x30)
+#define CR_AHB_SMB5 (CR_AHB_BASE + 0x34)
+
+/* RT63165 */
+#define CR_ERR_ADDR (CR_AHB_BASE + 0x3c)
+#define CR_PRATIR (CR_AHB_BASE + 0x58)
+#define CR_MON_TMR (CR_AHB_BASE + 0x60)
+
+#define CR_AHB_RSTCR (CR_AHB_BASE + 0x40)
+
+#define CR_AHB_PMCR (CR_AHB_BASE + 0x80)
+#define CR_AHB_DMTCR (CR_AHB_BASE + 0x84)
+#define CR_AHB_PCIC (CR_AHB_BASE + 0x88)
+
+#if defined(CONFIG_ECONET_EN7528)
+#define BOOT_TRAP_CONF (0xBFB000B8)
+#endif
+
+#if defined(CONFIG_ECONET_EN7516) || \
+ defined(CONFIG_ECONET_EN7527) || \
+ defined(CONFIG_ECONET_EN7528)
+#define CR_AHB_HWCONF (0xBFA20174)
+#else
+#define CR_AHB_HWCONF (CR_AHB_BASE + 0x8C)
+#endif
+#define CR_AHB_SSR (CR_AHB_BASE + 0x90)
+#define CR_AHB_SSTR (CR_AHB_BASE + 0x9C)
+#define CR_IMEM (CR_AHB_BASE + 0x9C)
+#define CR_DMEM (CR_AHB_BASE + 0xA0)
+
+/* RT63365 */
+#define CR_CRCC_REG (CR_AHB_BASE + 0xA0)
+#define CR_AHB_UHCR (CR_AHB_BASE + 0xA8)
+#define CR_AHB_ABMR (CR_AHB_BASE + 0xB8)
+#define CR_CKGEN_CONF (CR_AHB_BASE + 0xC0)
+#define CR_PSMCR (CR_AHB_BASE + 0xCC)
+#define CR_PSMDR (CR_AHB_BASE + 0xD0)
+#define CR_PSMMR (CR_AHB_BASE + 0xD0)
+
+/* RT63165 */
+#define CR_SRAM (CR_AHB_BASE + 0xF4)
+
+/* RT63365 */
+#define CR_AHB_CLK (CR_AHB_BASE + 0x1c0)
+#define CR_CLK_CFG (CR_AHB_BASE + 0x82c)
+#define CR_RSTCTRL2 (CR_AHB_BASE + 0x834)
+#define CR_GPIO_SHR (CR_AHB_BASE + 0x860)
+
+#define CR_BUSTIMEOUT_SWITCH (CR_AHB_BASE + 0x92c)
+
+/*************************************************
+ * SRAM/FLASH/ROM Controller Operation Registers *
+ *************************************************/
+#define CR_SMC_BASE 0xBFB10000
+#define CR_SMC_BCR0 (CR_SMC_BASE + 0x00)
+#define CR_SMC_BCR1 (CR_SMC_BASE + 0x04)
+#define CR_SMC_BCR2 (CR_SMC_BASE + 0x08)
+#define CR_SMC_BCR3 (CR_SMC_BASE + 0x0C)
+#define CR_SMC_BCR4 (CR_SMC_BASE + 0x10)
+#define CR_SMC_BCR5 (CR_SMC_BASE + 0x14)
+
+/*****************************
+ * Clock Generator Registers *
+ *****************************/
+
+/****************************
+ * USB Module Registers *
+ ****************************/
+
+/*************************
+ * HOST BRIDGE Registers *
+ * ***********************/
+#define HOST_BRIDGE_BASE 0xBFB80000
+#define CR_CFG_ADDR_REG (HOST_BRIDGE_BASE+0x0020)
+#define CR_CFG_DATA_REG (HOST_BRIDGE_BASE+0x0024)
+/****************************
+ * ATM SAR Module Registers *
+ ****************************/
+#define TSCONTROL_BASE 0xBFB00000
+#define TSARM_REGISTER_BASE (TSCONTROL_BASE + 0x00060000)
+
+/* ----- General configuration registers ----- */
+
+/* ----- Reset And Identify register ----- */
+#define TSARM_RAI VPint(TSARM_REGISTER_BASE + 0x0000)
+/* ----- General Configuration register ----- */
+#define TSARM_GFR VPint(TSARM_REGISTER_BASE + 0x0004)
+/* ----- Traffic Scheduler Timer Base Counter register ----- */
+#define TSARM_TSTBR VPint(TSARM_REGISTER_BASE + 0x0008)
+/* ----- Receive Maximum Packet Length register ----- */
+#define TSARM_RMPLR VPint(TSARM_REGISTER_BASE + 0x000c)
+/* ----- Transmit Priority 0/1 Data Buffer Control and Status Register ----- */
+#define TSARM_TXDBCSR_P01 VPint(TSARM_REGISTER_BASE + 0x0010)
+/* ----- TX OAM Buffer Control and Status register ----- */
+#define TSARM_TXMBCSR VPint(TSARM_REGISTER_BASE + 0x0014)
+/* ----- RX Data Buffer Control and Status register ----- */
+#define TSARM_RXDBCSR VPint(TSARM_REGISTER_BASE + 0x0018)
+/* ----- RX OAM Buffer Control and Status register ----- */
+#define TSARM_RXMBCSR VPint(TSARM_REGISTER_BASE + 0x001c)
+/* ----- Last IRQ Status register ----- */
+#define TSARM_LIRQ VPint(TSARM_REGISTER_BASE + 0x0020)
+/* ----- IRQ Queue Base Address register ----- */
+#define TSARM_IRQBA VPint(TSARM_REGISTER_BASE + 0x0024)
+/* ----- IRQ Queue Entry Length register ----- */
+#define TSARM_IRQLEN VPint(TSARM_REGISTER_BASE + 0x0028)
+/* ----- IRQ Head Indication register ----- */
+#define TSARM_IRQH VPint(TSARM_REGISTER_BASE + 0x002c)
+/* ----- Clear IRQ Entry register ----- */
+#define TSARM_IRQC VPint(TSARM_REGISTER_BASE + 0x0030)
+//Traffic Scheduler Line Rate Counter Register
+#define TSARM_TXSLRC VPint(TSARM_REGISTER_BASE + 0x0034)
+//Transmit Priority 2/3 Data Buffer Control and Status Register
+#define TSARM_TXDBCSR_P23 VPint(TSARM_REGISTER_BASE + 0x0038)
+
+/* ----- VC IRQ Mask register ----- */
+#define TSARM_IRQM_BASE (TSARM_REGISTER_BASE + 0x0040)
+#define TSARM_IRQM(vc) VPint(TSARM_IRQM_BASE + (vc * 4))
+#define TSARM_IRQMCC VPint(TSARM_IRQM_BASE + 0x0040)
+#define TSARM_IRQ_QUE_THRE VPint(TSARM_REGISTER_BASE + 0x0084) //IRQ Queue Threshold Register
+#define TSARM_IRQ_TIMEOUT_CTRL VPint(TSARM_REGISTER_BASE + 0x0088) //IRQ Timeout Control Register
+
+/* ----- VC Configuration register ----- */
+#define TSARM_VCCR_BASE (TSARM_REGISTER_BASE + 0x0100)
+#define TSARM_VCCR(vc) VPint(TSARM_VCCR_BASE + (vc * 4))
+#define TSARM_CCCR VPint(TSARM_VCCR_BASE + 0x0040)
+
+/* ----- DMA WRR Configuration Register (DMA_WRR_WEIT) (for TC3162L4) ----- */
+#define TSARM_DMAWRRCR VPint(TSARM_REGISTER_BASE + 0x0150)
+
+/* ----- Transmit Buffer Descriptor register ----- */
+#define TSARM_TXDCBDA_BASE (TSARM_REGISTER_BASE + 0x0200)
+#define TSARM_TXDCBDA(vc) VPint(TSARM_TXDCBDA_BASE + (vc * 4))
+#define TSARM_TXMCBDA_BASE (TSARM_REGISTER_BASE + 0x0240)
+#define TSARM_TXMCBDA(vc) VPint(TSARM_TXMCBDA_BASE + (vc * 4))
+
+#define TSARM_CC_TX_BD_BASE VPint(TSARM_REGISTER_BASE + 0x0228) //Control Channel Transmit BD Base Address 0x228
+#define TSARM_CC_TX_BD_MNG_BASE VPint(TSARM_REGISTER_BASE + 0x0268) //Control Channel Transmit BD Management Base
+#define TSARM_VC_TX_BD_PRIORITY01_BASE (TSARM_REGISTER_BASE + 0x0280)
+#define TSARM_VC_TX_BD_PRIORITY01(vc) VPint(TSARM_VC_TX_BD_PRIORITY01_BASE + vc * 4) //VC0 Transmit BD Data Priority 0/1 Base 280
+#define TSARM_VC_TX_BD_PRIORITY23_BASE (TSARM_REGISTER_BASE + 0x02c0)
+#define TSARM_VC_TX_BD_PRIORITY23(vc) VPint(TSARM_VC_TX_BD_PRIORITY23_BASE + vc * 4) //VC0 Transmit BD Data Priority 0/1 Base 280
+
+/* ----- Receive Buffer Descriptor register ----- */
+#define TSARM_RXDCBDA_BASE (TSARM_REGISTER_BASE + 0x0300)
+#define TSARM_RXDCBDA(vc) VPint(TSARM_RXDCBDA_BASE + (vc * 4))
+#define TSARM_RXMCBDA_BASE (TSARM_REGISTER_BASE + 0x0340)
+#define TSARM_RXMCBDA(vc) VPint(TSARM_RXMCBDA_BASE + (vc * 4))
+
+#define TSARM_CC_RX_BD_BASE VPint(TSARM_REGISTER_BASE + 0x328) //Control Channel Receive BD Base Address 0x328
+#define TSARM_CC_RX_BD_MNG_BASE VPint(TSARM_REGISTER_BASE + 0x368) //Control Channel Receive BD Management Base 0x368
+#define TSARM_VC_RX_DATA_BASE (TSARM_REGISTER_BASE + 0x380)
+#define TSARM_VC_RX_DATA(vc) VPint(TSARM_VC_RX_DATA_BASE + vc * 4) //VC0 Receive BD Data Base 0x380
+
+/* ----- Traffic Scheduler register ----- */
+#define TSARM_PCR_BASE (TSARM_REGISTER_BASE + 0x0400)
+#define TSARM_PCR(vc) VPint(TSARM_PCR_BASE + (vc * 4))
+#define TSARM_SCR_BASE (TSARM_REGISTER_BASE + 0x0440)
+#define TSARM_SCR(vc) VPint(TSARM_SCR_BASE + (vc * 4))
+#define TSARM_MBSTP_BASE (TSARM_REGISTER_BASE + 0x0480)
+#define TSARM_MBSTP(vc) VPint(TSARM_MBSTP_BASE + (vc * 4))
+
+#define TSARM_MAX_FRAME_SIZE_BASE (TSARM_REGISTER_BASE + 0x04c0)
+#define TSARM_MAX_FRAME_SIZE(vc) VPint(TSARM_MAX_FRAME_SIZE_BASE + (vc * 4))
+/* define for TC3162L4 */
+#define TSARM_TRAFFIC_SHAPER_WEIGHT_BASE (TSARM_REGISTER_BASE + 0x0500)
+#define TSARM_TRAFFIC_SHAPER_WEIGHT(vc) VPint(TSARM_TRAFFIC_SHAPER_WEIGHT_BASE + (vc * 4))
+
+/* ----- TX Statistic Counter register ----- */
+#define TSARM_TDCNT_BASE (TSARM_REGISTER_BASE + 0x0600)
+#define TSARM_TDCNT(vc) VPint(TSARM_TDCNT_BASE + (vc * 4))
+#define TSARM_TDCNTCC VPint(TSARM_TDCNT_BASE + 0x0040)
+
+/* ----- RX Statistic Counter register ----- */
+#define TSARM_RDCNT_BASE (TSARM_REGISTER_BASE + 0x0700)
+#define TSARM_RDCNT(vc) VPint(TSARM_RDCNT_BASE + (vc * 4))
+#define TSARM_RDCNTCC VPint(TSARM_RDCNT_BASE + 0x0040)
+#define TSARM_MISCNT VPint(TSARM_RDCNT_BASE + 0x0044)
+
+#define TSARM_MPOA_GCR VPint(TSARM_REGISTER_BASE + 0x0800) //MPOA global control register
+#define TSARM_VC_MPOA_CTRL_BASE (TSARM_REGISTER_BASE + 0x0810) //VC0 ~9 MPOA Control register
+#define TSARM_VC_MPOA_CTRL(vc) VPint(TSARM_VC_MPOA_CTRL_BASE + vc * 4)
+#define TSARM_MPOA_HFIV11 VPint(TSARM_REGISTER_BASE + 0x0850) //MPOA header Field1 Insertion Value1
+#define TSARM_MPOA_HFIV12 VPint(TSARM_REGISTER_BASE + 0x0854) //MPOA header Field1 Insertion Value2
+#define TSARM_MPOA_HFIV13 VPint(TSARM_REGISTER_BASE + 0x0858) //MPOA header Field2 Insertion Value1
+#define TSARM_MPOA_HFIV21 VPint(TSARM_REGISTER_BASE + 0x0860) //MPOA header Field2 Insertion Value2
+#define TSARM_MPOA_HFIV22 VPint(TSARM_REGISTER_BASE + 0x0864) //MPOA header Field2 Insertion Value2
+#define TSARM_MPOA_HFIV23 VPint(TSARM_REGISTER_BASE + 0x0868) //MPOA header Field2 Insertion Value2
+#define TSARM_MPOA_HFIV31 VPint(TSARM_REGISTER_BASE + 0x0870) //MPOA header Field3 Insertion Value1
+#define TSARM_MPOA_HFIV32 VPint(TSARM_REGISTER_BASE + 0x0874) //MPOA header Field3 Insertion Value2
+#define TSARM_MPOA_HFIV33 VPint(TSARM_REGISTER_BASE + 0x0878) //MPOA header Field3 Insertion Value3
+#define TSARM_MPOA_HFIV41 VPint(TSARM_REGISTER_BASE + 0x0880) //MPOA header Field4 Insertion Value1
+#define TSARM_MPOA_HFIV42 VPint(TSARM_REGISTER_BASE + 0x0884) //MPOA header Field4 Insertion Value2
+#define TSARM_MPOA_HFIV43 VPint(TSARM_REGISTER_BASE + 0x0888) //MPOA header Field4 Insertion Value2
+
+/**************************
+ * USB Module Registers *
+ **************************/
+
+#define LA_DEBUG_TRIGGER(addr,val) VPint(0xbfc00000+addr) = val
+
+#endif /* _TC3162_H_ */
diff --git a/arch/mips/include/asm/tc3162/tc3262_int_source.h b/arch/mips/include/asm/tc3162/tc3262_int_source.h
new file mode 100644
index 000000000000..a953a39f9e6b
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/tc3262_int_source.h
@@ -0,0 +1,135 @@
+/************************************************************************
+ *
+ * Copyright (C) 2006 Trendchip Technologies, Corp.
+ * All Rights Reserved.
+ *
+ * Trendchip Confidential; Need to Know only.
+ * Protected as an unpublished work.
+ *
+ * The computer program listings, specifications and documentation
+ * herein are the property of Trendchip Technologies, Co. and shall
+ * not be reproduced, copied, disclosed, or used in whole or in part
+ * for any reason without the prior express written permission of
+ * Trendchip Technologeis, Co.
+ *
+ *************************************************************************/
+
+#ifndef _TC3262_INT_SOURCE_H_
+#define _TC3262_INT_SOURCE_H_
+
+enum interrupt_source
+{
+#if defined(CONFIG_MIPS_TC3262_1004K)
+ /* intrName irqNum Source fullName */
+ DUMMY=0, /* n/a n/a dummy */
+ UART5_INT, /* 1 46 UART5 */
+ UART4_INT, /* 2 45 UART4 */
+ UART3_INT, /* 3 38 UART3 */
+ UART2_INT, /* 4 16 UART2 */
+ UART_INT, /* 5 2 UART */
+ GPIO_INT, /* 6 10 GPIO */
+ GDMA_INTR, /* 7 14 GDMA */
+ CRYPTO_INT, /* 8 28 Crypto engine */
+ USB_HOST_2, /* 9 48 USB host 2 (port1) */
+ IRQ_RT3XXX_USB, /* 10 17 USB host (port0)*/
+ HSDMA_INTR, /* 11 47 High Speed DMA */
+ WDMA1_WOE_INTR, /* 12 58 WIFI DMA 1 for WOE */
+ WDMA1_P1_INTR, /* 13 57 WIFI DMA 1 port 1 */
+ WDMA1_P0_INTR, /* 14 56 WIFI DMA 1 port 0 */
+ WDMA0_WOE_INTR, /* 15 55 WIFI DMA 1 for WOE */
+ WDMA0_P1_INTR, /* 16 54 WIFI DMA 1 port 1 */
+ WDMA0_P0_INTR, /* 17 53 WIFI DMA 1 port 0 */
+ WOE1_INTR, /* 18 52 WIFI Offload Engine 1 */
+ WOE0_INTR, /* 19 51 WIFI Offload Engine 0 */
+ PCIE_A_INT, /* 20 24 PCIE port 1 */
+ PCIE_0_INT, /* 21 23 PCIE port 0 */
+ MAC1_INT, /* 22 15 Giga Switch */
+ XSI_PHY_INTR, /* 23 50 XFI/HGSMII PHY interface */
+ XSI_MAC_INTR, /* 24 49 XFI/HGSMII MAC interface */
+ QDMA_LAN3_INTR, /* 25 41 QDMA LAN 3 */
+ QDMA_LAN2_INTR, /* 26 40 QDMA LAN 2 */
+ QDMA_LAN1_INTR, /* 27 39 QDMA LAN 1 */
+ QDMA_LAN0_INTR, /* 28 21 QDMA LAN 0 */
+ QDMA_WAN3_INTR, /* 29 44 QDMA WAN 3 */
+ QDMA_WAN2_INTR, /* 30 43 QDMA WAN 2 */
+ QDMA_WAN1_INTR, /* 31 42 QDMA WAN 1 */
+ QDMA_WAN0_INTR, /* 32 22 QDMA WAN 0 */
+ TIMER2_INT, /* 33 6 timer 2 */
+ TIMER1_INT, /* 34 5 timer 1 */
+ TIMER0_INT, /* 35 4 timer 0 */
+ PCM2_INT, /* 36 32 PCM 2 */
+ PCM1_INT, /* 37 11 PCM 1 */
+ XPON_PHY_INTR, /* 38 27 XPON PHY */
+ XPON_MAC_INTR, /* 39 26 XPON MAC */
+ DMT_INT, /* 40 19 xDSL DMT */
+ DYINGGASP_INT, /* 41 18 Dying gasp */
+ CPU_CM_PCINT, /* 42 1 CPU CM Perf Cnt overflow */
+ CPU_CM_ERR, /* 43 0 CPU Coherence Manager Error */
+ FE_ERR_INTR, /* 44 33 Frame Engine Error */
+ EFUSE_ERR1_INTR, /* 45 60 efuse error for prev action not finished */
+#ifdef CONFIG_ECONET_EN7528
+ RBUS_TOUT_INTR, /* 46 59 rbus timeout interrupt */
+#else
+ EFUSE_ERR0_INTR, /* 46 59 efuse error for not setting key */
+#endif
+ AUTO_MANUAL_INT, /* 47 35 SPI Controller Error */
+ PCIE_SERR_INT, /* 48 25 PCIE error */
+ DRAM_PROTECTION, /* 49 3 dram illegal access*/
+ BUS_TOUT_INT, /* 50 31 Pbus timeout */
+ TIMER5_INT, /* 51 9 timer 3 (watchdog) */
+ SI_TIMER_INT, /* 52 30/29/37/36 external CPU timers 0/1/2/3 */
+ GIC_EDGE_NMI, /* 53 20 send NMI to CPU by gic edge register */
+ RESVINT1, /* 54 n/a n/a */
+ RESVINT2, /* 55 n/a n/a */
+ IPI_RESCHED_INT0, /* 56 7 ipi resched 0 */
+ IPI_RESCHED_INT1, /* 57 8 ipi resched 1 */
+ IPI_RESCHED_INT2, /* 58 12 ipi resched 2 */
+ IPI_RESCHED_INT3, /* 59 13 ipi resched 3 */
+ IPI_CALL_INT0, /* 60 34 ipi call 0 */
+ IPI_CALL_INT1, /* 61 61 ipi call 0 */
+ IPI_CALL_INT2, /* 62 62 ipi call 0 */
+ IPI_CALL_INT3, /* 63 63 ipi call 0 */
+#elif defined(CONFIG_MIPS_TC3262_34K)
+ DUMMY_INT,
+ UART_INT, //0 IPL10
+ PTM_B0_INT, //1
+ SI_SWINT1_INT0, //2
+ SI_SWINT1_INT1, //3
+ TIMER0_INT, //4 IPL1
+ TIMER1_INT, //5 IPL5
+ TIMER2_INT, //6 IPL6
+ SI_SWINT_INT0, //7
+ SI_SWINT_INT1, //8
+ TIMER5_INT, //9 IPL9
+ GPIO_INT, //10 IPL11
+ PCM1_INT, //11 IPL20
+ SI_PC1_INT, //12
+ SI_PC_INT, //13
+ APB_DMA0_INT, //14 IPL12
+ ESW_INT, //15 IPL13
+ HSUART_INT, //16 IPL23
+ IRQ_RT3XXX_USB, //17 IPL24
+ DYINGGASP_INT, //18 IPL25
+ DMT_INT, //19 IPL26
+ UNUSED0_INT, //20
+ FE_MAC_INT, //21 IPL3
+ SAR_INT, //22 IPL2
+ PCIE_0_INT, //23
+ PCIE_A_INT, //24
+ PCIE_SERR_INT, //25
+ PTM_B1_INT, //26 IPL15
+ SPI_MC_INT, //27 IPL16
+ CRYPTO_INT, //28 IPL17
+ SI_TIMER1_INT, //29
+ SI_TIMER_INT, //30
+ SWR_INT, //31 IPL4
+ BUS_TOUT_INT, //32
+ PCM2_INT, //33
+ RESERVE_B_INT, //34
+ RESERVE_C_INT, //35
+ AUTO_MANUAL_INT, //36
+#endif
+ INTR_SOURCES_NUM
+};
+
+#endif /* _TC3262_INT_SOURCE_H_ */
diff --git a/arch/mips/include/asm/tc3162/war.h b/arch/mips/include/asm/tc3162/war.h
new file mode 100644
index 000000000000..85912cd1055b
--- /dev/null
+++ b/arch/mips/include/asm/tc3162/war.h
@@ -0,0 +1,26 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2008 Cavium Networks <support@caviumnetworks.com>
+ */
+#ifndef __ASM_MACH_MIPS_TC3262_WAR_H
+#define __ASM_MACH_MIPS_TC3262_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index da1cb0499d6c..0f81f3a48ba4 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -81,6 +81,9 @@ static inline struct thread_info *current_thread_info(void)
#endif /* !__ASSEMBLY__ */
/* thread information allocation */
+#if defined(CONFIG_THREAD_STACK_SIZE_ADJUSTMENT)
+#define THREAD_SIZE_ORDER (CONFIG_THREAD_SIZE_ORDER)
+#else
#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT)
#define THREAD_SIZE_ORDER (1)
#endif
@@ -99,6 +102,7 @@ static inline struct thread_info *current_thread_info(void)
#ifdef CONFIG_PAGE_SIZE_64KB
#define THREAD_SIZE_ORDER (0)
#endif
+#endif
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define THREAD_MASK (THREAD_SIZE - 1UL)
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 2f106d0357f4..82efef2ded20 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -110,4 +110,6 @@
#define SO_COOKIE 57
+#define SO_NDMMARK 127
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 4a603a3ea657..71d1a43193e5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
obj-$(CONFIG_MIPS_MSC) += irq-msc01.o
obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o
obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o
+obj-$(CONFIG_IRQ_GIC) += irq-gic.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_32BIT) += scall32-o32.o
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index dd6a18bc10ab..53bc5f1697bc 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -250,7 +250,7 @@ unsigned int __weak get_c0_compare_int(void)
return MIPS_CPU_IRQ_BASE + cp0_compare_irq;
}
-int r4k_clockevent_init(void)
+int __weak r4k_clockevent_init(void)
{
unsigned int cpu = smp_processor_id();
struct clock_event_device *cd;
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 921211bcd2ba..4edfd9540b64 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -32,6 +32,12 @@
#include <asm/spram.h>
#include <asm/uaccess.h>
+#if defined(CONFIG_RALINK_MT7621) || \
+ defined(CONFIG_RALINK_MT7628) || \
+ defined(CONFIG_MIPS_TC3262)
+#define PROBE_ONLY_ARCH_MIPS
+#endif
+
/* Hardware capabilities */
unsigned int elf_hwcap __read_mostly;
@@ -1152,6 +1158,7 @@ static inline void cpu_probe_vz(struct cpuinfo_mips *c)
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
| MIPS_CPU_COUNTER)
+#ifndef PROBE_ONLY_ARCH_MIPS
static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
{
switch (c->processor_id & PRID_IMP_MASK) {
@@ -1510,6 +1517,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
break;
}
}
+#endif /* !PROBE_ONLY_ARCH_MIPS */
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
{
@@ -1640,6 +1648,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
spram_config();
}
+#ifndef PROBE_ONLY_ARCH_MIPS
static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
{
decode_configs(c);
@@ -1931,6 +1940,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
}
c->kscratch_mask = 0xf;
}
+#endif /* !PROBE_ONLY_ARCH_MIPS */
#ifdef CONFIG_64BIT
/* For use by uaccess.h */
@@ -1956,12 +1966,15 @@ void cpu_probe(void)
c->processor_id = read_c0_prid();
switch (c->processor_id & PRID_COMP_MASK) {
+#ifndef PROBE_ONLY_ARCH_MIPS
case PRID_COMP_LEGACY:
cpu_probe_legacy(c, cpu);
break;
+#endif /* !PROBE_ONLY_ARCH_MIPS */
case PRID_COMP_MIPS:
cpu_probe_mips(c, cpu);
break;
+#ifndef PROBE_ONLY_ARCH_MIPS
case PRID_COMP_ALCHEMY:
cpu_probe_alchemy(c, cpu);
break;
@@ -1991,6 +2004,7 @@ void cpu_probe(void)
case PRID_COMP_NETLOGIC:
cpu_probe_netlogic(c, cpu);
break;
+#endif /* !PROBE_ONLY_ARCH_MIPS */
}
BUG_ON(!__cpu_name[cpu]);
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
index e757f36cea6f..6a8b094129c9 100644
--- a/arch/mips/kernel/crash.c
+++ b/arch/mips/kernel/crash.c
@@ -59,7 +59,7 @@ static void crash_kexec_prepare_cpus(void)
ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
- dump_send_ipi(crash_shutdown_secondary);
+ smp_call_function(crash_shutdown_secondary, NULL, 0);
smp_wmb();
/*
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index d76275da54cb..1372d2526ab8 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -65,7 +65,7 @@ static bool rdhwr_count_usable(void)
return false;
}
-int __init init_r4k_clocksource(void)
+int __init __weak init_r4k_clocksource(void)
{
if (!cpu_has_counter || !mips_hpt_frequency)
return -ENXIO;
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index d1bb506adc10..cdabe6c899e7 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -23,6 +23,7 @@
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
+#include <asm/cacheops.h>
#include <kernel-entry-init.h>
@@ -87,6 +88,48 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
setup_c0_status_pri
+#ifdef CONFIG_MIPS_L2_CACHE_ER35
+ /* Set L2 CCA Override to WT on lowest 256MB */
+
+ /* Jump to KSEG1 so that we can perform cache related operations */
+ PTR_LA t0, 0f
+ li t1, 5
+ ins t0, t1, 29, 3
+ jr t0
+ nop
+0:
+
+ /* Flush L2 Cache before setting CCA overrides */
+ /* Define L2 Cache Line Size 32 */
+#define L2_LINE_SIZE 32
+ /* Define L2 Size 256K */
+#define L2_SIZE (256 << 10)
+ li t0, L2_SIZE
+ move t1, zero
+
+1:
+ cache Index_Writeback_Inv_SD, 0(t1)
+ addiu t1, t1, L2_LINE_SIZE /* Increase Index */
+ bne t1, t0, 1b
+ nop
+
+ sync
+
+ /* Override bottom half of DDR to uncached (DMA zone) */
+ PTR_LI t0, 0xbfbf8000
+
+ lui t1, (~((CONFIG_ZONE_DMA_SIZE - 1) >> 16)) & 0xffff
+ ori t1, t1, 0x0051
+ sw t1, 0xb8(t0)
+
+ /* Base */
+ sw zero, 0xb0(t0)
+
+ /* Set default override to WT */
+ PTR_LI t1, 0x1fbf8010
+ sw t1, 0x08(t0)
+#endif
+
/* We might not get launched at the address the kernel is linked to,
so we jump there. */
PTR_LA t0, 0f
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
new file mode 100644
index 000000000000..26f8969651a5
--- /dev/null
+++ b/arch/mips/kernel/irq-gic.c
@@ -0,0 +1,574 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/bitmap.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/gic.h>
+#include <asm/setup.h>
+
+#include <asm/traps.h>
+#include <asm/mips-cpc.h>
+#include <asm/smp-ops.h>
+
+#include <linux/ioport.h>
+#include <linux/hardirq.h>
+#include <linux/sched.h>
+#include <asm-generic/bitops/find.h>
+
+unsigned int gic_present;
+unsigned int gic_irq_base;
+unsigned long _gic_base;
+
+static unsigned long __gic_base_addr;
+static unsigned int gic_irq_flags[GIC_NUM_INTRS];
+
+#ifdef CONFIG_IRQ_GIC_EIC
+#define EIC_NUM_VECTORS (64 + GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET)
+
+/* The index into this array is the vector # of the interrupt. */
+static struct gic_shared_intr_map gic_shared_intr_map[EIC_NUM_VECTORS];
+#else
+struct gic_pcpu_mask {
+ DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
+};
+
+static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
+#endif
+
+int gic_get_usm_range(struct resource *gic_usm_res)
+{
+ if (!gic_present)
+ return -1;
+
+ gic_usm_res->start = __gic_base_addr + USM_VISIBLE_SECTION_OFS;
+ gic_usm_res->end = gic_usm_res->start + (USM_VISIBLE_SECTION_SIZE - 1);
+
+ return 0;
+}
+
+unsigned gic_read_local_vp_id(void)
+{
+ unsigned int ident;
+
+ GICREAD(GIC_REG(VPE_LOCAL, GIC_VP_IDENT), ident);
+ return ident & GIC_VP_IDENT_VCNUM_MSK;
+}
+
+#ifdef CONFIG_IRQ_GIC_EIC
+static void gic_bind_eic_interrupt(int irq, int regset)
+{
+ /* Convert irq vector # to hw int # */
+ irq -= GIC_PIN_TO_VEC_OFFSET;
+
+ /* Set irq to use shadow set */
+ GICWRITE(GIC_REG_ADDR(VPE_LOCAL, GIC_VPE_EIC_SS(irq)), regset);
+}
+
+static void gic_eic_irq_dispatch(void)
+{
+ unsigned int cause = read_c0_cause();
+ int irq;
+
+ irq = (cause & ST0_IM) >> STATUSB_IP2;
+ if (irq == 0)
+ irq = -1;
+
+ if (irq >= 0)
+ do_IRQ(gic_irq_base + irq);
+ else
+ spurious_interrupt();
+}
+#else
+void gic_irq_dispatch(void)
+{
+ unsigned int i, intr;
+ unsigned long *pcpu_mask;
+ unsigned long *pending_abs, *intrmask_abs;
+ DECLARE_BITMAP(pending, GIC_NUM_INTRS);
+ DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
+
+ /* Get per-cpu bitmaps */
+ pcpu_mask = pcpu_masks[smp_processor_id()].pcpu_mask;
+
+ pending_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
+ GIC_SH_PEND_31_0_OFS);
+ intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
+ GIC_SH_MASK_31_0_OFS);
+
+ for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) {
+ GICREAD(*pending_abs, pending[i]);
+ GICREAD(*intrmask_abs, intrmask[i]);
+ pending_abs++;
+ intrmask_abs++;
+ }
+
+ bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
+ bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
+
+ intr = find_first_bit(pending, GIC_NUM_INTRS);
+ while (intr < GIC_NUM_INTRS) {
+ do_IRQ(gic_irq_base + intr);
+
+ /* go to next pending bit */
+ bitmap_clear(pending, intr, 1);
+ intr = find_first_bit(pending, GIC_NUM_INTRS);
+ }
+}
+#endif
+
+static inline void gic_send_ipi(unsigned int intr)
+{
+ GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(intr));
+}
+
+static void __init vpe_local_setup(unsigned int numvpes)
+{
+ unsigned int timer_intr = GIC_INT_TMR;
+ unsigned int perf_intr = GIC_INT_PERFCTR;
+ unsigned int vpe_ctl;
+ int i;
+
+#ifdef CONFIG_IRQ_GIC_EIC
+ if (cpu_has_veic) {
+ /*
+ * GIC timer interrupt -> CPU HW Int X (vector X+2) ->
+ * map to pin X+2-1 (since GIC adds 1)
+ */
+ timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
+ /*
+ * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) ->
+ * map to pin X+2-1 (since GIC adds 1)
+ */
+ perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
+ }
+#endif
+
+ /*
+ * Setup the default performance counter timer interrupts
+ * for all VPEs
+ */
+ for (i = 0; i < numvpes; i++) {
+ GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
+
+ /* Are Interrupts locally routable? */
+ GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
+ if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
+ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
+ GIC_MAP_TO_PIN_MSK | timer_intr);
+
+ if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
+ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
+ GIC_MAP_TO_PIN_MSK | perf_intr);
+ }
+
+#ifdef CONFIG_IRQ_GIC_EIC
+ if (cpu_has_veic) {
+ int veic;
+
+ veic = timer_intr + GIC_PIN_TO_VEC_OFFSET;
+ set_vi_handler(veic, gic_eic_irq_dispatch);
+ gic_shared_intr_map[veic].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK;
+
+ veic = perf_intr + GIC_PIN_TO_VEC_OFFSET;
+ set_vi_handler(veic, gic_eic_irq_dispatch);
+ gic_shared_intr_map[veic].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK;
+ }
+#endif
+}
+
+static void gic_mask_irq(struct irq_data *d)
+{
+ int intr = (d->irq - gic_irq_base);
+#ifdef CONFIG_IRQ_GIC_EIC
+ struct gic_shared_intr_map *map_ptr;
+
+ map_ptr = &gic_shared_intr_map[intr];
+ if (map_ptr->shared_intr_flags & GIC_FLAG_PERCPU)
+ intr = map_ptr->shared_intr_list[smp_processor_id()];
+ else
+ intr = map_ptr->shared_intr_list[0];
+#endif
+ /* disable interrupt */
+ GIC_CLR_INTR_MASK(intr);
+}
+
+static void gic_unmask_irq(struct irq_data *d)
+{
+ int intr = (d->irq - gic_irq_base);
+#ifdef CONFIG_IRQ_GIC_EIC
+ struct gic_shared_intr_map *map_ptr;
+
+ map_ptr = &gic_shared_intr_map[intr];
+ if (map_ptr->shared_intr_flags & GIC_FLAG_PERCPU)
+ intr = map_ptr->shared_intr_list[smp_processor_id()];
+ else
+ intr = map_ptr->shared_intr_list[0];
+#endif
+ /* enable interrupt */
+ GIC_SET_INTR_MASK(intr);
+}
+
+static void gic_mask_ack_irq(struct irq_data *d)
+{
+ int intr = (d->irq - gic_irq_base);
+#ifdef CONFIG_IRQ_GIC_EIC
+ struct gic_shared_intr_map *map_ptr;
+
+ map_ptr = &gic_shared_intr_map[intr];
+ if (map_ptr->shared_intr_flags & GIC_FLAG_PERCPU)
+ intr = map_ptr->shared_intr_list[smp_processor_id()];
+ else
+ intr = map_ptr->shared_intr_list[0];
+#endif
+ /* disable interrupt */
+ GIC_CLR_INTR_MASK(intr);
+
+ /* clear edge detector */
+ if (gic_irq_flags[intr] & GIC_TRIG_EDGE)
+ GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_CLR(intr));
+}
+
+static void gic_ack_irq(struct irq_data *d)
+{
+ int intr = (d->irq - gic_irq_base);
+#ifdef CONFIG_IRQ_GIC_EIC
+ struct gic_shared_intr_map *map_ptr;
+
+ map_ptr = &gic_shared_intr_map[intr];
+ if (map_ptr->shared_intr_flags & GIC_FLAG_PERCPU)
+ intr = map_ptr->shared_intr_list[smp_processor_id()];
+ else
+ intr = map_ptr->shared_intr_list[0];
+#endif
+ /* clear edge detector */
+ if (gic_irq_flags[intr] & GIC_TRIG_EDGE)
+ GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_CLR(intr));
+}
+
+#ifdef CONFIG_SMP
+static DEFINE_SPINLOCK(gic_lock);
+
+static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
+ bool force)
+{
+ int intr = (d->irq - gic_irq_base);
+ cpumask_t tmp = CPU_MASK_NONE;
+ unsigned long flags;
+#ifdef CONFIG_IRQ_GIC_EIC
+ struct gic_shared_intr_map *map_ptr;
+
+ map_ptr = &gic_shared_intr_map[intr];
+ if (map_ptr->shared_intr_flags & GIC_FLAG_PERCPU)
+ return -EINVAL;
+
+ intr = map_ptr->shared_intr_list[0];
+#else
+ int i;
+#endif
+
+ cpumask_and(&tmp, cpumask, cpu_online_mask);
+ if (cpumask_empty(&tmp))
+ return -EINVAL;
+
+ /* Assumption : cpumask refers to a single CPU */
+ spin_lock_irqsave(&gic_lock, flags);
+
+ /* Re-route this IRQ */
+ GIC_SH_MAP_TO_VPE_SMASK(intr, cpumask_first(&tmp));
+
+#ifndef CONFIG_IRQ_GIC_EIC
+ /* Update the pcpu_masks */
+ for (i = 0; i < NR_CPUS; i++)
+ clear_bit(intr, pcpu_masks[i].pcpu_mask);
+ set_bit(intr, pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
+#endif
+ cpumask_copy(d->common->affinity, cpumask);
+
+ spin_unlock_irqrestore(&gic_lock, flags);
+
+ return IRQ_SET_MASK_OK_NOCOPY;
+}
+#endif
+
+static struct irq_chip gic_irq_controller = {
+ .name = "MIPS GIC",
+ .irq_ack = gic_ack_irq,
+ .irq_mask = gic_mask_irq,
+ .irq_mask_ack = gic_mask_ack_irq,
+ .irq_unmask = gic_unmask_irq,
+ .irq_eoi = gic_unmask_irq,
+ .irq_disable = gic_mask_irq,
+ .irq_enable = gic_unmask_irq,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = gic_set_affinity,
+#endif
+};
+
+static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
+ unsigned int pin, unsigned int polarity, unsigned int trigtype,
+ unsigned int flags)
+{
+ /* Setup Intr to Pin mapping */
+ if (pin & GIC_MAP_TO_NMI_MSK) {
+ int i;
+
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
+ /* FIXME: hack to route NMI to all cpu's */
+ for (i = 0; i < NR_CPUS; i += 32) {
+ GICWRITE(GIC_REG_ADDR(SHARED,
+ GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
+ 0xffffffff);
+ }
+ } else {
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
+ GIC_MAP_TO_PIN_MSK | pin);
+ /* Setup Intr to CPU mapping */
+ GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
+#ifdef CONFIG_IRQ_GIC_EIC
+ if (cpu_has_veic) {
+ struct gic_shared_intr_map *map_ptr;
+
+ set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET,
+ gic_eic_irq_dispatch);
+ map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET];
+ map_ptr->shared_intr_flags = flags;
+ if (flags & GIC_FLAG_PERCPU) {
+ if (cpu < NR_CPUS)
+ map_ptr->shared_intr_list[cpu] = intr;
+ } else
+ map_ptr->shared_intr_list[0] = intr;
+ }
+#endif
+ }
+
+ /* Setup Intr Polarity */
+ GIC_SET_POLARITY(intr, polarity);
+
+ /* Setup Intr Trigger Type */
+ GIC_SET_TRIGGER(intr, trigtype);
+
+ /* Init Intr Masks */
+ GIC_CLR_INTR_MASK(intr);
+
+#ifndef CONFIG_IRQ_GIC_EIC
+ /* Initialise per-cpu Interrupt software masks */
+ set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+#endif
+ if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
+ GIC_SET_INTR_MASK(intr);
+ if (trigtype == GIC_TRIG_EDGE)
+ gic_irq_flags[intr] |= GIC_TRIG_EDGE;
+}
+
+#ifdef CONFIG_MIPS_MT_SMP
+static int gic_resched_int_base;
+static int gic_call_int_base;
+
+static inline unsigned int plat_ipi_resched_int_xlate(int cpu)
+{
+ unsigned int intr = gic_resched_int_base + cpu;
+#ifdef CONFIG_IRQ_GIC_EIC
+ struct gic_shared_intr_map *map_ptr;
+
+ map_ptr = &gic_shared_intr_map[intr];
+ intr = map_ptr->shared_intr_list[0];
+#endif
+ return intr;
+}
+
+static inline unsigned int plat_ipi_call_int_xlate(int cpu)
+{
+ unsigned int intr = gic_call_int_base + cpu;
+#ifdef CONFIG_IRQ_GIC_EIC
+ struct gic_shared_intr_map *map_ptr;
+
+ map_ptr = &gic_shared_intr_map[intr];
+ intr = map_ptr->shared_intr_list[0];
+#endif
+ return intr;
+}
+
+void mips_smp_send_ipi_single(int cpu, unsigned int action)
+{
+ unsigned long flags;
+ unsigned int intr;
+ unsigned int core = cpu_data[cpu].core;
+
+ local_irq_save(flags);
+
+ switch (action) {
+ case SMP_CALL_FUNCTION:
+ intr = plat_ipi_call_int_xlate(cpu);
+ break;
+
+ case SMP_RESCHEDULE_YOURSELF:
+ intr = plat_ipi_resched_int_xlate(cpu);
+ break;
+
+ default:
+ BUG();
+ }
+
+ gic_send_ipi(intr);
+
+ if (mips_cpc_present() && (core != current_cpu_data.core)) {
+ while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+ mips_cm_lock_other(core, 0);
+ mips_cpc_lock_other(core);
+ write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
+ mips_cpc_unlock_other();
+ mips_cm_unlock_other();
+ }
+ }
+
+ local_irq_restore(flags);
+}
+
+void mips_smp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu(i, mask)
+ mips_smp_send_ipi_single(i, action);
+}
+
+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
+{
+ scheduler_ipi();
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
+{
+ generic_smp_call_function_interrupt();
+ return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+ .handler = ipi_resched_interrupt,
+ .flags = IRQF_PERCPU,
+ .name = "IPI_resched"
+};
+
+static struct irqaction irq_call = {
+ .handler = ipi_call_interrupt,
+ .flags = IRQF_PERCPU,
+ .name = "IPI_call"
+};
+
+static __init void gic_ipi_init_one(unsigned int irq, struct irqaction *action)
+{
+ irq_set_handler(gic_irq_base + irq, handle_percpu_irq);
+ setup_irq(gic_irq_base + irq, action);
+}
+
+static inline void gic_ipi_init(int intnumintrs, int numvpes)
+{
+ int cpu;
+
+ gic_call_int_base = intnumintrs - numvpes;
+ gic_resched_int_base = gic_call_int_base - numvpes;
+
+ for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
+ gic_ipi_init_one(gic_resched_int_base + cpu, &irq_resched);
+ gic_ipi_init_one(gic_call_int_base + cpu, &irq_call);
+ }
+}
+#else
+static inline void gic_ipi_init(int intnumintrs, int numvpes)
+{
+}
+#endif
+
+static void __init gic_basic_init(int numintrs,
+ int numvpes,
+ const struct gic_intr_map *intrmap,
+ unsigned int mapsize)
+{
+ unsigned int i, cpu;
+ unsigned int pin_offset = 0;
+
+ /* Setup defaults */
+ for (i = 0; i < numintrs; i++) {
+ GIC_SET_POLARITY(i, GIC_POL_POS);
+ GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
+ GIC_CLR_INTR_MASK(i);
+ if (i < GIC_NUM_INTRS)
+ gic_irq_flags[i] = 0;
+ }
+
+#ifdef CONFIG_IRQ_GIC_EIC
+ board_bind_eic_interrupt = gic_bind_eic_interrupt;
+
+ for (i = 0; i < EIC_NUM_VECTORS; i++) {
+ gic_shared_intr_map[i].shared_intr_flags = 0;
+ gic_shared_intr_map[i].local_intr_mask = 0;
+ }
+
+ /*
+ * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
+ * one because the GIC will add one (since 0=no intr).
+ */
+ if (cpu_has_veic)
+ pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
+#endif
+
+ /* Setup specifics */
+ for (i = 0; i < mapsize; i++) {
+ cpu = intrmap[i].cpunum;
+ if (cpu == GIC_UNUSED)
+ continue;
+ gic_setup_intr(i,
+ intrmap[i].cpunum,
+ intrmap[i].pin + pin_offset,
+ intrmap[i].polarity,
+ intrmap[i].trigtype,
+ intrmap[i].flags);
+ }
+
+ vpe_local_setup(numvpes);
+}
+
+void __init gic_init(unsigned long gic_base_addr,
+ unsigned long gic_addrspace_size,
+ const struct gic_intr_map *intr_map,
+ unsigned int intr_map_size,
+ unsigned int irqbase)
+{
+ unsigned int gicconfig, gicrev;
+ int numvpes, numintrs;
+
+ __gic_base_addr = gic_base_addr;
+
+ _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
+ gic_addrspace_size);
+ gic_irq_base = irqbase;
+
+ GICREAD(GIC_REG(SHARED, GIC_SH_REVISIONID), gicrev);
+ pr_info("MIPS GIC RevID: %d.%d\n", (gicrev >> 8) & 0xff, gicrev & 0xff);
+
+ GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
+ numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
+ GIC_SH_CONFIG_NUMINTRS_SHF;
+ numintrs = ((numintrs + 1) * 8);
+
+ numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
+ GIC_SH_CONFIG_NUMVPES_SHF;
+ numvpes = numvpes + 1;
+
+ gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
+
+ gic_platform_init(numintrs, &gic_irq_controller);
+
+ gic_ipi_init(numintrs, numvpes);
+}
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 50fb62544df7..6fa6cdfa6e22 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -64,15 +64,10 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags, unsigned long, fd,
unsigned long, pgoff)
{
- unsigned long error;
-
- error = -EINVAL;
if (pgoff & (~PAGE_MASK >> 12))
- goto out;
- error = sys_mmap_pgoff(addr, len, prot, flags, fd,
- pgoff >> (PAGE_SHIFT-12));
-out:
- return error;
+ return -EINVAL;
+ return sys_mmap_pgoff(addr, len, prot, flags, fd,
+ pgoff >> (PAGE_SHIFT-12));
}
#define RLIM_INFINITY32 0x7fffffff
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index df65516778a2..31e645d62794 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -232,6 +232,7 @@ int mips_cm_probe(void)
return -ENODEV;
}
+#if !defined(CONFIG_MIPS_L2_CACHE_ER35)
/* set default target to memory */
base_reg &= ~CM_GCR_BASE_CMDEFTGT_MSK;
base_reg |= CM_GCR_BASE_CMDEFTGT_MEM;
@@ -246,6 +247,7 @@ int mips_cm_probe(void)
write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR_MSK);
write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK);
+#endif
/* probe for an L2-only sync region */
mips_cm_probe_l2sync();
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 789d7bf4fef3..ddde22787287 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -99,9 +99,10 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
retval = -ENOMEM;
goto out_free_new_mask;
}
- retval = -EPERM;
- if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
+ if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) {
+ retval = -EPERM;
goto out_unlock;
+ }
retval = security_task_setscheduler(p);
if (retval)
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index 88b1ef5f868a..13d90f59d669 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -118,18 +118,20 @@ void mips_mt_regdump(unsigned long mvpctl)
local_irq_restore(flags);
}
-static int mt_opt_norps;
static int mt_opt_rpsctl = -1;
static int mt_opt_nblsu = -1;
static int mt_opt_forceconfig7;
static int mt_opt_config7 = -1;
+#ifdef CONFIG_MIPS_TC3262_34K
+static int mt_opt_es;
-static int __init rps_disable(char *s)
+static int __init es_set(char *str)
{
- mt_opt_norps = 1;
+ get_option(&str, &mt_opt_es);
return 1;
}
-__setup("norps", rps_disable);
+__setup("es=", es_set);
+#endif
static int __init rpsctl_set(char *str)
{
@@ -153,40 +155,6 @@ static int __init config7_set(char *str)
}
__setup("config7=", config7_set);
-/* Experimental cache flush control parameters that should go away some day */
-int mt_protiflush;
-int mt_protdflush;
-int mt_n_iflushes = 1;
-int mt_n_dflushes = 1;
-
-static int __init set_protiflush(char *s)
-{
- mt_protiflush = 1;
- return 1;
-}
-__setup("protiflush", set_protiflush);
-
-static int __init set_protdflush(char *s)
-{
- mt_protdflush = 1;
- return 1;
-}
-__setup("protdflush", set_protdflush);
-
-static int __init niflush(char *s)
-{
- get_option(&s, &mt_n_iflushes);
- return 1;
-}
-__setup("niflush=", niflush);
-
-static int __init ndflush(char *s)
-{
- get_option(&s, &mt_n_dflushes);
- return 1;
-}
-__setup("ndflush=", ndflush);
-
static unsigned int itc_base;
static int __init set_itc_base(char *str)
@@ -202,9 +170,15 @@ void mips_mt_set_cpuoptions(void)
unsigned int oconfig7 = read_c0_config7();
unsigned int nconfig7 = oconfig7;
- if (mt_opt_norps) {
- printk("\"norps\" option deprecated: use \"rpsctl=\"\n");
+#ifdef CONFIG_MIPS_TC3262_34K
+ if (mt_opt_es >= 0) {
+ if (mt_opt_es)
+ nconfig7 |= (1 << 8);
+ else
+ nconfig7 &= ~(1 << 8);
}
+#endif
+
if (mt_opt_rpsctl >= 0) {
printk("34K return prediction stack override set to %d.\n",
mt_opt_rpsctl);
@@ -231,16 +205,6 @@ void mips_mt_set_cpuoptions(void)
printk("Config7: 0x%08x\n", read_c0_config7());
}
- /* Report Cache management debug options */
- if (mt_protiflush)
- printk("I-cache flushes single-threaded\n");
- if (mt_protdflush)
- printk("D-cache flushes single-threaded\n");
- if (mt_n_iflushes != 1)
- printk("I-Cache Flushes Repeated %d times\n", mt_n_iflushes);
- if (mt_n_dflushes != 1)
- printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
-
if (itc_base != 0) {
/*
* Configure ITC mapping. This code is very
@@ -282,21 +246,6 @@ void mips_mt_set_cpuoptions(void)
}
}
-/*
- * Function to protect cache flushes from concurrent execution
- * depends on MP software model chosen.
- */
-
-void mt_cflush_lockdown(void)
-{
- /* FILL IN VSMP and AP/SP VERSIONS HERE */
-}
-
-void mt_cflush_release(void)
-{
- /* FILL IN VSMP and AP/SP VERSIONS HERE */
-}
-
struct class *mt_class;
static int __init mt_init(void)
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 94627a3a6a0d..947981a9aa72 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -44,14 +44,221 @@ struct mips_hi16 {
static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock);
-#ifdef MODULE_START
+/*
+ * Get the potential max trampolines size required of the init and
+ * non-init sections. Only used if we cannot find enough contiguous
+ * physically mapped memory to put the module into.
+ */
+static unsigned int
+get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ const char *secstrings, unsigned int symindex, bool is_init)
+{
+ unsigned long ret = 0;
+ unsigned int i, j;
+ Elf_Sym *syms;
+
+ /* Everything marked ALLOC (this includes the exported symbols) */
+ for (i = 1; i < hdr->e_shnum; ++i) {
+ unsigned int info = sechdrs[i].sh_info;
+
+ if (sechdrs[i].sh_type != SHT_REL
+ && sechdrs[i].sh_type != SHT_RELA)
+ continue;
+
+ /* Not a valid relocation section? */
+ if (info >= hdr->e_shnum)
+ continue;
+
+ /* Don't bother with non-allocated sections */
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+ continue;
+
+ /* If it's called *.init*, and we're not init, we're
+ not interested */
+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
+ != is_init)
+ continue;
+
+ syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
+ if (sechdrs[i].sh_type == SHT_REL) {
+ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
+
+ for (j = 0; j < size; ++j) {
+ Elf_Sym *sym;
+
+ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
+ continue;
+
+ sym = syms + ELF_MIPS_R_SYM(rel[j]);
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
+ continue;
+
+ ret += 4 * sizeof(int);
+ }
+ } else {
+ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
+
+ for (j = 0; j < size; ++j) {
+ Elf_Sym *sym;
+
+ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
+ continue;
+
+ sym = syms + ELF_MIPS_R_SYM(rela[j]);
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
+ continue;
+
+ ret += 4 * sizeof(int);
+ }
+ }
+ }
+
+ return ret;
+}
+
+#ifndef MODULE_START
+static void *alloc_phys(unsigned long size)
+{
+ unsigned order;
+ struct page *page;
+ struct page *p;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
+ __GFP_THISNODE, order);
+ if (!page)
+ return NULL;
+
+ split_page(page, order);
+
+ /* mark all pages except for the last one */
+ for (p = page; p + 1 < page + (size >> PAGE_SHIFT); ++p)
+ set_bit(PG_owner_priv_1, &p->flags);
+
+ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
+ __free_page(p);
+
+ return page_address(page);
+}
+#endif
+
+static void free_phys(void *ptr)
+{
+ struct page *page;
+ bool free;
+
+ page = virt_to_page(ptr);
+ do {
+ free = test_and_clear_bit(PG_owner_priv_1, &page->flags);
+ __free_page(page);
+ page++;
+ } while (free);
+}
+
+
void *module_alloc(unsigned long size)
{
+#ifdef MODULE_START
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
__builtin_return_address(0));
+#else
+ void *ptr;
+
+ if (size == 0)
+ return NULL;
+
+ ptr = alloc_phys(size);
+
+ /* If we failed to allocate physically contiguous memory,
+ * fall back to regular vmalloc. The module loader code will
+ * create jump tables to handle long jumps */
+ if (!ptr)
+ return vmalloc(size);
+
+ return ptr;
+#endif
}
+
+static inline bool is_phys_addr(void *ptr)
+{
+#ifdef CONFIG_64BIT
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
+#else
+ return (KSEGX(ptr) == KSEG0);
#endif
+}
+
+/* Free memory returned from module_alloc */
+void module_memfree(void *module_region)
+{
+ if (is_phys_addr(module_region))
+ free_phys(module_region);
+ else
+ vfree(module_region);
+}
+
+static void *__module_alloc(int size, bool phys)
+{
+ void *ptr;
+
+ if (phys)
+ ptr = kmalloc(size, GFP_KERNEL);
+ else
+ ptr = vmalloc(size);
+ return ptr;
+}
+
+static void __module_free(void *ptr)
+{
+ if (is_phys_addr(ptr))
+ kfree(ptr);
+ else
+ vfree(ptr);
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+ char *secstrings, struct module *mod)
+{
+ unsigned int symindex = 0;
+ unsigned int core_size, init_size;
+ int i;
+
+ mod->arch.phys_plt_offset = 0;
+ mod->arch.virt_plt_offset = 0;
+ mod->arch.phys_plt_tbl = NULL;
+ mod->arch.virt_plt_tbl = NULL;
+
+ if (IS_ENABLED(CONFIG_64BIT))
+ return 0;
+
+ for (i = 1; i < hdr->e_shnum; i++)
+ if (sechdrs[i].sh_type == SHT_SYMTAB)
+ symindex = i;
+
+ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
+ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
+
+ if ((core_size + init_size) == 0)
+ return 0;
+
+ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
+ if (!mod->arch.phys_plt_tbl)
+ return -ENOMEM;
+
+ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
+ if (!mod->arch.virt_plt_tbl) {
+ __module_free(mod->arch.phys_plt_tbl);
+ mod->arch.phys_plt_tbl = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
{
@@ -65,8 +272,39 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v)
return 0;
}
+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
+ void *start, Elf_Addr v)
+{
+ unsigned *tramp = start + *plt_offset;
+ *plt_offset += 4 * sizeof(int);
+
+ /* adjust carry for addiu */
+ if (v & 0x00008000)
+ v += 0x10000;
+
+ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */
+ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */
+ tramp[2] = 0x03200008; /* jr t9 */
+ tramp[3] = 0x00000000; /* nop */
+
+ return (Elf_Addr) tramp;
+}
+
+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
+{
+ if (is_phys_addr(location))
+ return add_plt_entry_to(&me->arch.phys_plt_offset,
+ me->arch.phys_plt_tbl, v);
+ else
+ return add_plt_entry_to(&me->arch.virt_plt_offset,
+ me->arch.virt_plt_tbl, v);
+
+}
+
static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
{
+ u32 ofs = *location & 0x03ffffff;
+
if (v % 4) {
pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
me->name);
@@ -74,13 +312,17 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
}
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
- pr_err("module %s: relocation overflow\n",
- me->name);
- return -ENOEXEC;
+ v = add_plt_entry(me, location, v + (ofs << 2));
+ if (!v) {
+ pr_err("module %s: relocation overflow\n",
+ me->name);
+ return -ENOEXEC;
+ }
+ ofs = 0;
}
*location = (*location & ~0x03ffffff) |
- ((*location + (v >> 2)) & 0x03ffffff);
+ ((ofs + (v >> 2)) & 0x03ffffff);
return 0;
}
@@ -349,9 +591,36 @@ int module_finalize(const Elf_Ehdr *hdr,
list_add(&me->arch.dbe_list, &dbe_list);
spin_unlock_irq(&dbe_lock);
}
+
+ /* Get rid of the fixup trampoline if we're running the module
+ * from physically mapped address space */
+ if (me->arch.phys_plt_offset == 0) {
+ __module_free(me->arch.phys_plt_tbl);
+ me->arch.phys_plt_tbl = NULL;
+ }
+ if (me->arch.virt_plt_offset == 0) {
+ __module_free(me->arch.virt_plt_tbl);
+ me->arch.virt_plt_tbl = NULL;
+ }
+
return 0;
}
+void module_arch_freeing_init(struct module *mod)
+{
+ if (mod->state == MODULE_STATE_LIVE)
+ return;
+
+ if (mod->arch.phys_plt_tbl) {
+ __module_free(mod->arch.phys_plt_tbl);
+ mod->arch.phys_plt_tbl = NULL;
+ }
+ if (mod->arch.virt_plt_tbl) {
+ __module_free(mod->arch.virt_plt_tbl);
+ mod->arch.virt_plt_tbl = NULL;
+ }
+}
+
void module_arch_cleanup(struct module *mod)
{
spin_lock_irq(&dbe_lock);
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 2c3b89a65317..576c44752203 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -375,6 +375,9 @@ static void __init bootmem_init(void)
unsigned long bootmap_size;
bool bootmap_valid = false;
int i;
+#if defined(CONFIG_MIPS_L2_CACHE_ER35)
+ unsigned long kernel_load_paddr;
+#endif
/*
* Sanity check any INITRD first. We don't take it into account
@@ -609,6 +612,14 @@ static void __init bootmem_init(void)
}
#endif
+#if defined(CONFIG_MIPS_L2_CACHE_ER35)
+ /* Free memory up to start of kernel image */
+ kernel_load_paddr = CPHYSADDR((unsigned long) &_text);
+ if (kernel_load_paddr > CONFIG_ZONE_DMA_SIZE)
+ free_bootmem(kernel_load_paddr - CONFIG_ZONE_DMA_SIZE,
+ CONFIG_ZONE_DMA_SIZE);
+#endif
+
/*
* Reserve initrd memory if needed.
*/
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 6e3671752775..b0c80dcbed30 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -177,7 +177,7 @@ static void bmips_prepare_cpus(unsigned int max_cpus)
/*
* Tell the hardware to boot CPUx - runs on CPU0
*/
-static void bmips_boot_secondary(int cpu, struct task_struct *idle)
+static int bmips_boot_secondary(int cpu, struct task_struct *idle)
{
bmips_smp_boot_sp = __KSTK_TOS(idle);
bmips_smp_boot_gp = (unsigned long)task_thread_info(idle);
@@ -229,6 +229,8 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
}
cpumask_set_cpu(cpu, &bmips_booted_mask);
}
+
+ return 0;
}
/*
@@ -366,7 +368,6 @@ static int bmips_cpu_disable(void)
set_cpu_online(cpu, false);
calculate_cpu_foreign_map();
- cpumask_clear_cpu(cpu, &cpu_callin_map);
clear_c0_status(IE_IRQ5);
local_flush_tlb_all();
@@ -409,7 +410,7 @@ void __ref play_dead(void)
#endif /* CONFIG_HOTPLUG_CPU */
-struct plat_smp_ops bmips43xx_smp_ops = {
+const struct plat_smp_ops bmips43xx_smp_ops = {
.smp_setup = bmips_smp_setup,
.prepare_cpus = bmips_prepare_cpus,
.boot_secondary = bmips_boot_secondary,
@@ -423,7 +424,7 @@ struct plat_smp_ops bmips43xx_smp_ops = {
#endif
};
-struct plat_smp_ops bmips5000_smp_ops = {
+const struct plat_smp_ops bmips5000_smp_ops = {
.smp_setup = bmips_smp_setup,
.prepare_cpus = bmips_prepare_cpus,
.boot_secondary = bmips_boot_secondary,
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index 76923349b4fe..e751e4b90799 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -24,7 +24,9 @@
#include <linux/cpumask.h>
#include <linux/interrupt.h>
#include <linux/compiler.h>
+#ifndef CONFIG_IRQ_GIC
#include <linux/irqchip/mips-gic.h>
+#endif
#include <linux/atomic.h>
#include <asm/cacheflush.h>
@@ -38,14 +40,21 @@
#include <asm/mipsmtregs.h>
#include <asm/mips_mt.h>
#include <asm/amon.h>
+#ifdef CONFIG_IRQ_GIC
+#include <asm/gic.h>
+#endif
static void cmp_init_secondary(void)
{
struct cpuinfo_mips *c __maybe_unused = &current_cpu_data;
/* Assume GIC is present */
- change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
- STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7);
+ if (cpu_has_veic)
+ clear_c0_status(ST0_IM);
+ else
+ change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 |
+ STATUSF_IP4 | STATUSF_IP5 |
+ STATUSF_IP6 | STATUSF_IP7);
/* Enable per-cpu interrupts: platform specific */
@@ -78,7 +87,7 @@ static void cmp_smp_finish(void)
* __KSTK_TOS(idle) is apparently the stack pointer
* (unsigned long)idle->thread_info the gp
*/
-static void cmp_boot_secondary(int cpu, struct task_struct *idle)
+static int cmp_boot_secondary(int cpu, struct task_struct *idle)
{
struct thread_info *gp = task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle);
@@ -95,6 +104,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle)
#endif
amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0);
+ return 0;
}
/*
@@ -148,7 +158,7 @@ void __init cmp_prepare_cpus(unsigned int max_cpus)
}
-struct plat_smp_ops cmp_smp_ops = {
+const struct plat_smp_ops cmp_smp_ops = {
.send_ipi_single = mips_smp_send_ipi_single,
.send_ipi_mask = mips_smp_send_ipi_mask,
.init_secondary = cmp_init_secondary,
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 6183ad84cc73..91907a4a1b2e 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -10,7 +10,9 @@
#include <linux/delay.h>
#include <linux/io.h>
+#ifndef CONFIG_IRQ_GIC
#include <linux/irqchip/mips-gic.h>
+#endif
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp.h>
@@ -26,6 +28,9 @@
#include <asm/smp-cps.h>
#include <asm/time.h>
#include <asm/uasm.h>
+#ifdef CONFIG_IRQ_GIC
+#include <asm/gic.h>
+#endif
static bool threads_disabled;
static DECLARE_BITMAP(core_power, NR_CPUS);
@@ -56,6 +61,11 @@ static unsigned core_vpe_count(unsigned core)
return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
}
+bool __weak plat_cpu_core_present(int core)
+{
+ return true;
+}
+
static void __init cps_smp_setup(void)
{
unsigned int ncores, nvpes, core_vpes;
@@ -66,6 +76,8 @@ static void __init cps_smp_setup(void)
ncores = mips_cm_numcores();
pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE");
for (c = nvpes = 0; c < ncores; c++) {
+ if (!plat_cpu_core_present(c))
+ continue;
core_vpes = core_vpe_count(c);
pr_cont("%c%u", c ? ',' : '{', core_vpes);
@@ -287,7 +299,7 @@ static void remote_vpe_boot(void *dummy)
mips_cps_boot_vpes(core_cfg, cpu_vpe_id(&current_cpu_data));
}
-static void cps_boot_secondary(int cpu, struct task_struct *idle)
+static int cps_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned core = cpu_data[cpu].core;
unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
@@ -326,7 +338,11 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
if (cpu_online(remote))
break;
}
- BUG_ON(remote >= NR_CPUS);
+ if (remote >= NR_CPUS) {
+ pr_crit("No online CPU in core %u to start CPU%d\n",
+ core, cpu);
+ goto out;
+ }
err = smp_call_function_single(remote, remote_vpe_boot,
NULL, 1);
@@ -341,6 +357,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
mips_cps_boot_vpes(core_cfg, vpe_id);
out:
preempt_enable();
+ return 0;
}
static void cps_init_secondary(void)
@@ -399,7 +416,6 @@ static int cps_cpu_disable(void)
smp_mb__after_atomic();
set_cpu_online(cpu, false);
calculate_cpu_foreign_map();
- cpumask_clear_cpu(cpu, &cpu_callin_map);
return 0;
}
@@ -418,13 +434,12 @@ void play_dead(void)
local_irq_disable();
idle_task_exit();
cpu = smp_processor_id();
+ core = cpu_data[cpu].core;
cpu_death = CPU_DEATH_POWER;
pr_debug("CPU%d going offline\n", cpu);
if (cpu_has_mipsmt || cpu_has_vp) {
- core = cpu_data[cpu].core;
-
/* Look for another online VPE within the core */
for_each_online_cpu(cpu_death_sibling) {
if (cpu_data[cpu_death_sibling].core != core)
@@ -546,7 +561,7 @@ static void cps_cpu_die(unsigned int cpu)
#endif /* CONFIG_HOTPLUG_CPU */
-static struct plat_smp_ops cps_smp_ops = {
+static const struct plat_smp_ops cps_smp_ops = {
.smp_setup = cps_smp_setup,
.prepare_cpus = cps_prepare_cpus,
.boot_secondary = cps_boot_secondary,
@@ -562,7 +577,7 @@ static struct plat_smp_ops cps_smp_ops = {
bool mips_cps_smp_in_use(void)
{
- extern struct plat_smp_ops *mp_ops;
+ extern const struct plat_smp_ops *mp_ops;
return mp_ops == &cps_smp_ops;
}
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index e077ea3e11fb..705248e3955f 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -21,7 +21,9 @@
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/interrupt.h>
+#ifndef CONFIG_IRQ_GIC
#include <linux/irqchip/mips-gic.h>
+#endif
#include <linux/compiler.h>
#include <linux/smp.h>
@@ -35,6 +37,9 @@
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/mips_mt.h>
+#ifdef CONFIG_IRQ_GIC
+#include <asm/gic.h>
+#endif
static void __init smvp_copy_vpe_config(void)
{
@@ -119,7 +124,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action)
unsigned long flags;
int vpflags;
-#ifdef CONFIG_MIPS_GIC
+#if defined(CONFIG_MIPS_GIC) || defined(CONFIG_IRQ_GIC)
if (gic_present) {
mips_smp_send_ipi_single(cpu, action);
return;
@@ -158,7 +163,11 @@ static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
static void vsmp_init_secondary(void)
{
-#ifdef CONFIG_MIPS_GIC
+#ifdef CONFIG_MIPS_TC3262_34K
+ write_c0_status((read_c0_status() & ~ST0_IM ) |
+ (STATUSF_IP0 | STATUSF_IP1));
+#else
+#if defined(CONFIG_MIPS_GIC) || defined(CONFIG_IRQ_GIC)
/* This is Malta specific: IPI,performance and timer interrupts */
if (gic_present)
change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 |
@@ -168,6 +177,7 @@ static void vsmp_init_secondary(void)
#endif
change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 |
STATUSF_IP6 | STATUSF_IP7);
+#endif
}
static void vsmp_smp_finish(void)
@@ -192,7 +202,7 @@ static void vsmp_smp_finish(void)
* (unsigned long)idle->thread_info the gp
* assumes a 1:1 mapping of TC => VPE
*/
-static void vsmp_boot_secondary(int cpu, struct task_struct *idle)
+static int vsmp_boot_secondary(int cpu, struct task_struct *idle)
{
struct thread_info *gp = task_thread_info(idle);
dvpe();
@@ -224,6 +234,8 @@ static void vsmp_boot_secondary(int cpu, struct task_struct *idle)
clear_c0_mvpcontrol(MVPCONTROL_VPC);
evpe(EVPE_ENABLE);
+
+ return 0;
}
/*
@@ -279,7 +291,7 @@ static void __init vsmp_prepare_cpus(unsigned int max_cpus)
mips_mt_set_cpuoptions();
}
-struct plat_smp_ops vsmp_smp_ops = {
+const struct plat_smp_ops vsmp_smp_ops = {
.send_ipi_single = vsmp_send_ipi_single,
.send_ipi_mask = vsmp_send_ipi_mask,
.init_secondary = vsmp_init_secondary,
diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c
index 17878d71ef2b..525d3196f793 100644
--- a/arch/mips/kernel/smp-up.c
+++ b/arch/mips/kernel/smp-up.c
@@ -39,8 +39,9 @@ static void up_smp_finish(void)
/*
* Firmware CPU startup hook
*/
-static void up_boot_secondary(int cpu, struct task_struct *idle)
+static int up_boot_secondary(int cpu, struct task_struct *idle)
{
+ return 0;
}
static void __init up_smp_setup(void)
@@ -63,7 +64,7 @@ static void up_cpu_die(unsigned int cpu)
}
#endif
-struct plat_smp_ops up_smp_ops = {
+const struct plat_smp_ops up_smp_ops = {
.send_ipi_single = up_send_ipi_single,
.send_ipi_mask = up_send_ipi_mask,
.init_secondary = up_init_secondary,
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 01aa8d6da4b9..9177472b2570 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -48,8 +48,6 @@
#include <asm/setup.h>
#include <asm/maar.h>
-cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
-
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
EXPORT_SYMBOL(__cpu_number_map);
@@ -149,10 +147,10 @@ void calculate_cpu_foreign_map(void)
&temp_foreign_map, &cpu_sibling_map[i]);
}
-struct plat_smp_ops *mp_ops;
+const struct plat_smp_ops *mp_ops;
EXPORT_SYMBOL(mp_ops);
-void register_smp_ops(struct plat_smp_ops *ops)
+void register_smp_ops(const struct plat_smp_ops *ops)
{
if (mp_ops)
printk(KERN_WARNING "Overriding previously set SMP ops\n");
@@ -357,7 +355,9 @@ asmlinkage void start_secondary(void)
mips_clockevent_init();
mp_ops->init_secondary();
cpu_report();
+#if defined(CONFIG_CPU_MIPS32_R5_FEATURES)
maar_init();
+#endif
/*
* XXX parity protection should be folded in here when it's converted
@@ -446,7 +446,11 @@ void smp_prepare_boot_cpu(void)
int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
- mp_ops->boot_secondary(cpu, tidle);
+ int err;
+
+ err = mp_ops->boot_secondary(cpu, tidle);
+ if (err)
+ return err;
/* Wait for CPU to start and be ready to sync counters */
if (!wait_for_completion_timeout(&cpu_starting,
@@ -650,23 +654,6 @@ void flush_tlb_one(unsigned long vaddr)
EXPORT_SYMBOL(flush_tlb_page);
EXPORT_SYMBOL(flush_tlb_one);
-#if defined(CONFIG_KEXEC)
-void (*dump_ipi_function_ptr)(void *) = NULL;
-void dump_send_ipi(void (*dump_ipi_callback)(void *))
-{
- int i;
- int cpu = smp_processor_id();
-
- dump_ipi_function_ptr = dump_ipi_callback;
- smp_mb();
- for_each_online_cpu(i)
- if (i != cpu)
- mp_ops->send_ipi_single(i, SMP_DUMP);
-
-}
-EXPORT_SYMBOL(dump_send_ipi);
-#endif
-
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static DEFINE_PER_CPU(atomic_t, tick_broadcast_count);
diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
index d6e6cf75114d..bdc7e9bba1d9 100644
--- a/arch/mips/kernel/spram.c
+++ b/arch/mips/kernel/spram.c
@@ -17,6 +17,13 @@
#include <asm/r4kcache.h>
#include <asm/hazards.h>
+#ifdef CONFIG_TC3262_IMEM
+#include <asm/tc3162/tc3162.h>
+
+#define MIPS34K_Index_Store_Data_I 0x0c
+extern int __imem;
+#endif
+
/*
* These definitions are correct for the 24K/34K/74K SPRAM sample
* implementation. The 4KS interpreted the tags differently...
@@ -81,6 +88,7 @@ static unsigned int ispram_load_tag(unsigned int offset)
return data;
}
+#ifndef CONFIG_TC3262_IMEM
static void dspram_store_tag(unsigned int offset, unsigned int data)
{
unsigned int errctl;
@@ -113,6 +121,7 @@ static unsigned int dspram_load_tag(unsigned int offset)
return data;
}
+#endif
static void probe_spram(char *type,
unsigned int base,
@@ -195,6 +204,61 @@ static void probe_spram(char *type,
offset += 2 * SPRAM_TAG_STRIDE;
}
}
+
+#ifdef CONFIG_TC3262_IMEM
+static void
+ispram_store_data(unsigned int offset, unsigned int datalo, unsigned int datahi)
+{
+ unsigned int errctl;
+
+ /* enable SPRAM tag access */
+ errctl = bis_c0_errctl(ERRCTL_SPRAM);
+ ehb();
+
+#ifdef __BIG_ENDIAN
+ write_c0_idatalo(datahi);
+ ehb();
+
+ write_c0_idatahi(datalo);
+ ehb();
+#else
+ write_c0_idatalo(datalo);
+ ehb();
+
+ write_c0_idatahi(datahi);
+ ehb();
+#endif
+
+ cache_op(MIPS34K_Index_Store_Data_I, CKSEG0|offset);
+ ehb();
+
+ write_c0_errctl(errctl);
+ ehb();
+}
+
+static void ispram_fill(void)
+{
+ unsigned int pa, size, tag0, tag1;
+ unsigned int offset;
+ unsigned int datalo, datahi;
+
+ tag0 = ispram_load_tag(0);
+ tag1 = ispram_load_tag(0 + SPRAM_TAG_STRIDE);
+
+ pa = tag0 & SPRAM_TAG0_PA_MASK;
+ size = tag1 & SPRAM_TAG1_SIZE_MASK;
+
+ if (size == 0)
+ return;
+
+ for (offset = 0; offset < size; offset += 8) {
+ datalo = *(unsigned int *) ((unsigned int)PHYS_TO_K0(pa + offset));
+ datahi = *(unsigned int *) ((unsigned int)PHYS_TO_K0(pa + offset + 4));
+ ispram_store_data(offset, datalo, datahi);
+ }
+}
+#endif
+
void spram_config(void)
{
unsigned int config0;
@@ -212,6 +276,13 @@ void spram_config(void)
case CPU_I6400:
case CPU_P6600:
config0 = read_c0_config();
+#ifdef CONFIG_TC3262_IMEM
+ if (config0 & (1<<24)) {
+ probe_spram("ISPRAM", CPHYSADDR(&__imem),
+ &ispram_load_tag, &ispram_store_tag);
+ ispram_fill();
+ }
+#else
/* FIXME: addresses are Malta specific */
if (config0 & (1<<24)) {
probe_spram("ISPRAM", 0x1c000000,
@@ -220,5 +291,6 @@ void spram_config(void)
if (config0 & (1<<23))
probe_spram("DSPRAM", 0x1c100000,
&dspram_load_tag, &dspram_store_tag);
+#endif
}
}
diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
index 4472a7f98577..1992c79af721 100644
--- a/arch/mips/kernel/sync-r4k.c
+++ b/arch/mips/kernel/sync-r4k.c
@@ -29,7 +29,7 @@ void synchronise_count_master(int cpu)
int i;
unsigned long flags;
- printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu);
+ pr_info("Synchronize counters for CPU %u: ", cpu);
local_irq_save(flags);
@@ -83,12 +83,15 @@ void synchronise_count_master(int cpu)
* count registers were almost certainly out of sync
* so no point in alarming people
*/
- printk("done.\n");
+ pr_cont("done.\n");
}
void synchronise_count_slave(int cpu)
{
int i;
+ unsigned long flags;
+
+ local_irq_save(flags);
/*
* Not every cpu is online at the time this gets called,
@@ -112,5 +115,7 @@ void synchronise_count_slave(int cpu)
}
/* Arrange for an interrupt in a short while */
write_c0_compare(read_c0_count() + COUNTON);
+
+ local_irq_restore(flags);
}
#undef NR_LOOPS
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 67d3cba60c9f..0c5b9af24aea 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -61,16 +61,9 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags, unsigned long,
fd, off_t, offset)
{
- unsigned long result;
-
- result = -EINVAL;
if (offset & ~PAGE_MASK)
- goto out;
-
- result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
-
-out:
- return result;
+ return -EINVAL;
+ return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
}
SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index c6297a03d945..62689a604314 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -13,7 +13,9 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#ifndef CONFIG_IRQ_GIC
#include <linux/irqchip/mips-gic.h>
+#endif
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
@@ -23,6 +25,9 @@
#include <asm/abi.h>
#include <asm/page.h>
#include <asm/vdso.h>
+#ifdef CONFIG_IRQ_GIC
+#include <asm/gic.h>
+#endif
/* Kernel-provided data used by the VDSO. */
static union mips_vdso_data vdso_data __page_aligned_data;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 23c5509f3b51..b334e6fbff05 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -11,6 +11,10 @@
#include <asm-generic/vmlinux.lds.h>
+#ifdef CONFIG_TC3262_IMEM
+#define TC3262_IMEM_SIZE 65536
+#endif
+
#undef mips
#define mips mips
OUTPUT_ARCH(mips)
@@ -53,25 +57,40 @@ SECTIONS
/* read-only */
_text = .; /* Text and read-only data */
.text : {
+#ifdef CONFIG_RALINK_MT7628
+ . = . + 0x8000;
+#endif
TEXT_TEXT
SCHED_TEXT
CPUIDLE_TEXT
LOCK_TEXT
KPROBES_TEXT
+#ifndef CONFIG_TC3262_IMEM
IRQENTRY_TEXT
SOFTIRQENTRY_TEXT
+#endif
*(.text.*)
*(.fixup)
*(.gnu.warning)
} :text = 0
+
+#ifdef CONFIG_TC3262_IMEM
+ . = ALIGN(32768);
+ __imem = . ;
+ .imem_text : { *(.imem_text) }
+ _imem_end = .;
+ _etext = (__imem + TC3262_IMEM_SIZE) > . ? (__imem + TC3262_IMEM_SIZE) : .;
+ . = _etext;
+#else
_etext = .; /* End of text section */
+#endif
EXCEPTION_TABLE(16)
/* Exception table for data bus errors */
__dbe_table : {
__start___dbe_table = .;
- *(__dbe_table)
+ KEEP(*(__dbe_table))
__stop___dbe_table = .;
}
@@ -122,7 +141,7 @@ SECTIONS
. = ALIGN(4);
.mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) {
__mips_machines_start = .;
- *(.mips.machines.init)
+ KEEP(*(.mips.machines.init))
__mips_machines_end = .;
}
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index fba4ca56e46a..3053677fb236 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -4,7 +4,7 @@
lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \
mips-atomic.o strlen_user.o strncpy_user.o \
- strnlen_user.o uncached.o
+ strnlen_user.o uncached.o memcmp.o
obj-y += iomap.o
obj-$(CONFIG_PCI) += iomap-pci.o
diff --git a/arch/mips/lib/memcmp.c b/arch/mips/lib/memcmp.c
new file mode 100644
index 000000000000..35ef1646286e
--- /dev/null
+++ b/arch/mips/lib/memcmp.c
@@ -0,0 +1,22 @@
+/*
+ * copied from linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#undef memcmp
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+EXPORT_SYMBOL(memcmp);
+
diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
index 99aab9f85904..8bffc04581e7 100644
--- a/arch/mips/loongson64/loongson-3/smp.c
+++ b/arch/mips/loongson64/loongson-3/smp.c
@@ -381,7 +381,7 @@ static void __init loongson3_prepare_cpus(unsigned int max_cpus)
/*
* Setup the PC, SP, and GP of a secondary processor and start it runing!
*/
-static void loongson3_boot_secondary(int cpu, struct task_struct *idle)
+static int loongson3_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned long startargs[4];
@@ -404,6 +404,7 @@ static void loongson3_boot_secondary(int cpu, struct task_struct *idle)
(void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x8));
loongson3_ipi_write64(startargs[0],
(void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0));
+ return 0;
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -418,7 +419,6 @@ static int loongson3_cpu_disable(void)
set_cpu_online(cpu, false);
calculate_cpu_foreign_map();
- cpumask_clear_cpu(cpu, &cpu_callin_map);
local_irq_save(flags);
fixup_irqs();
local_irq_restore(flags);
@@ -716,7 +716,7 @@ early_initcall(register_loongson3_notifier);
#endif
-struct plat_smp_ops loongson3_smp_ops = {
+const struct plat_smp_ops loongson3_smp_ops = {
.send_ipi_single = loongson3_send_ipi_single,
.send_ipi_mask = loongson3_send_ipi_mask,
.init_secondary = loongson3_init_secondary,
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index 0e45b061e514..8064821e9805 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -127,23 +127,6 @@ static void octeon_flush_icache_range(unsigned long start, unsigned long end)
}
-/**
- * Flush the icache for a trampoline. These are used for interrupt
- * and exception hooking.
- *
- * @addr: Address to flush
- */
-static void octeon_flush_cache_sigtramp(unsigned long addr)
-{
- struct vm_area_struct *vma;
-
- down_read(&current->mm->mmap_sem);
- vma = find_vma(current->mm, addr);
- octeon_flush_icache_all_cores(vma);
- up_read(&current->mm->mmap_sem);
-}
-
-
/**
* Flush a range out of a vma
*
@@ -289,7 +272,6 @@ void octeon_cache_init(void)
flush_cache_mm = octeon_flush_cache_mm;
flush_cache_page = octeon_flush_cache_page;
flush_cache_range = octeon_flush_cache_range;
- flush_cache_sigtramp = octeon_flush_cache_sigtramp;
flush_icache_all = octeon_flush_icache_all;
flush_data_cache_page = octeon_flush_data_cache_page;
flush_icache_range = octeon_flush_icache_range;
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 21e4e662c1fa..432b8c8a588c 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -273,30 +273,6 @@ static void r3k_flush_data_cache_page(unsigned long addr)
{
}
-static void r3k_flush_cache_sigtramp(unsigned long addr)
-{
- unsigned long flags;
-
- pr_debug("csigtramp[%08lx]\n", addr);
-
- flags = read_c0_status();
-
- write_c0_status(flags&~ST0_IEC);
-
- /* Fill the TLB to avoid an exception with caches isolated. */
- asm( "lw\t$0, 0x000(%0)\n\t"
- "lw\t$0, 0x004(%0)\n\t"
- : : "r" (addr) );
-
- write_c0_status((ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
-
- asm( "sb\t$0, 0x000(%0)\n\t"
- "sb\t$0, 0x004(%0)\n\t"
- : : "r" (addr) );
-
- write_c0_status(flags);
-}
-
static void r3k_flush_kernel_vmap_range(unsigned long vaddr, int size)
{
BUG();
@@ -330,7 +306,6 @@ void r3k_cache_init(void)
__flush_kernel_vmap_range = r3k_flush_kernel_vmap_range;
- flush_cache_sigtramp = r3k_flush_cache_sigtramp;
local_flush_data_cache_page = local_r3k_flush_data_cache_page;
flush_data_cache_page = r3k_flush_data_cache_page;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index b9dea4ce290c..741569afd9f6 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -109,7 +109,9 @@ static inline void r4k_on_each_cpu(unsigned int type,
*/
static unsigned long icache_size __read_mostly;
static unsigned long dcache_size __read_mostly;
+#if defined(CONFIG_CPU_LOONGSON3)
static unsigned long vcache_size __read_mostly;
+#endif
static unsigned long scache_size __read_mostly;
/*
@@ -320,8 +322,10 @@ static void r4k_blast_icache_page_setup(void)
r4k_blast_icache_page = (void *)cache_noop;
else if (ic_lsize == 16)
r4k_blast_icache_page = blast_icache16_page;
+#if defined(CONFIG_CPU_LOONGSON2)
else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2)
r4k_blast_icache_page = loongson2_blast_icache32_page;
+#endif
else if (ic_lsize == 32)
r4k_blast_icache_page = blast_icache32_page;
else if (ic_lsize == 64)
@@ -369,9 +373,11 @@ static void r4k_blast_icache_page_indexed_setup(void)
else if (TX49XX_ICACHE_INDEX_INV_WAR)
r4k_blast_icache_page_indexed =
tx49_blast_icache32_page_indexed;
+#if defined(CONFIG_CPU_LOONGSON2)
else if (current_cpu_type() == CPU_LOONGSON2)
r4k_blast_icache_page_indexed =
loongson2_blast_icache32_page_indexed;
+#endif
else
r4k_blast_icache_page_indexed =
blast_icache32_page_indexed;
@@ -395,8 +401,10 @@ static void r4k_blast_icache_setup(void)
r4k_blast_icache = blast_r4600_v1_icache32;
else if (TX49XX_ICACHE_INDEX_INV_WAR)
r4k_blast_icache = tx49_blast_icache32;
+#if defined(CONFIG_CPU_LOONGSON2)
else if (current_cpu_type() == CPU_LOONGSON2)
r4k_blast_icache = loongson2_blast_icache32;
+#endif
else
r4k_blast_icache = blast_icache32;
} else if (ic_lsize == 64)
@@ -462,6 +470,10 @@ static void r4k_blast_scache_setup(void)
static inline void local_r4k___flush_cache_all(void * args)
{
switch (current_cpu_type()) {
+#if defined(CONFIG_CPU_LOONGSON3) || \
+ defined(CONFIG_CPU_LOONGSON2) || \
+ defined(CONFIG_CPU_R4X00) || \
+ defined(CONFIG_CPU_R10000)
case CPU_LOONGSON2:
case CPU_LOONGSON3:
case CPU_R4000SC:
@@ -479,11 +491,14 @@ static inline void local_r4k___flush_cache_all(void * args)
*/
r4k_blast_scache();
break;
+#endif
+#if defined(CONFIG_CPU_BMIPS5000)
case CPU_BMIPS5000:
r4k_blast_scache();
__sync();
break;
+#endif
default:
r4k_blast_dcache();
@@ -584,6 +599,7 @@ static inline void local_r4k_flush_cache_mm(void * args)
if (!has_valid_asid(mm, R4K_INDEX))
return;
+#if defined(CONFIG_CPU_R4X00)
/*
* Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we
* only flush the primary caches but R1x000 behave sane ...
@@ -597,6 +613,7 @@ static inline void local_r4k_flush_cache_mm(void * args)
r4k_blast_scache();
return;
}
+#endif
r4k_blast_dcache();
}
@@ -748,9 +765,11 @@ static inline void __local_r4k_flush_icache_range(unsigned long start,
r4k_blast_icache();
else {
switch (boot_cpu_type()) {
+#if defined(CONFIG_CPU_LOONGSON2)
case CPU_LOONGSON2:
protected_loongson2_blast_icache_range(start, end);
break;
+#endif
default:
if (user)
@@ -832,6 +851,7 @@ static void r4k_flush_icache_user_range(unsigned long start, unsigned long end)
#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
+__IMEM
static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
/* Catch bad driver code */
@@ -869,6 +889,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
__sync();
}
+__IMEM
static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
{
/* Catch bad driver code */
@@ -908,119 +929,6 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
}
#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
-struct flush_cache_sigtramp_args {
- struct mm_struct *mm;
- struct page *page;
- unsigned long addr;
-};
-
-/*
- * While we're protected against bad userland addresses we don't care
- * very much about what happens in that case. Usually a segmentation
- * fault will dump the process later on anyway ...
- */
-static void local_r4k_flush_cache_sigtramp(void *args)
-{
- struct flush_cache_sigtramp_args *fcs_args = args;
- unsigned long addr = fcs_args->addr;
- struct page *page = fcs_args->page;
- struct mm_struct *mm = fcs_args->mm;
- int map_coherent = 0;
- void *vaddr;
-
- unsigned long ic_lsize = cpu_icache_line_size();
- unsigned long dc_lsize = cpu_dcache_line_size();
- unsigned long sc_lsize = cpu_scache_line_size();
-
- /*
- * If owns no valid ASID yet, cannot possibly have gotten
- * this page into the cache.
- */
- if (!has_valid_asid(mm, R4K_HIT))
- return;
-
- if (mm == current->active_mm) {
- vaddr = NULL;
- } else {
- /*
- * Use kmap_coherent or kmap_atomic to do flushes for
- * another ASID than the current one.
- */
- map_coherent = (cpu_has_dc_aliases &&
- page_mapcount(page) &&
- !Page_dcache_dirty(page));
- if (map_coherent)
- vaddr = kmap_coherent(page, addr);
- else
- vaddr = kmap_atomic(page);
- addr = (unsigned long)vaddr + (addr & ~PAGE_MASK);
- }
-
- R4600_HIT_CACHEOP_WAR_IMPL;
- if (!cpu_has_ic_fills_f_dc) {
- if (dc_lsize)
- vaddr ? flush_dcache_line(addr & ~(dc_lsize - 1))
- : protected_writeback_dcache_line(
- addr & ~(dc_lsize - 1));
- if (!cpu_icache_snoops_remote_store && scache_size)
- vaddr ? flush_scache_line(addr & ~(sc_lsize - 1))
- : protected_writeback_scache_line(
- addr & ~(sc_lsize - 1));
- }
- if (ic_lsize)
- vaddr ? flush_icache_line(addr & ~(ic_lsize - 1))
- : protected_flush_icache_line(addr & ~(ic_lsize - 1));
-
- if (vaddr) {
- if (map_coherent)
- kunmap_coherent();
- else
- kunmap_atomic(vaddr);
- }
-
- if (MIPS4K_ICACHE_REFILL_WAR) {
- __asm__ __volatile__ (
- ".set push\n\t"
- ".set noat\n\t"
- ".set "MIPS_ISA_LEVEL"\n\t"
-#ifdef CONFIG_32BIT
- "la $at,1f\n\t"
-#endif
-#ifdef CONFIG_64BIT
- "dla $at,1f\n\t"
-#endif
- "cache %0,($at)\n\t"
- "nop; nop; nop\n"
- "1:\n\t"
- ".set pop"
- :
- : "i" (Hit_Invalidate_I));
- }
- if (MIPS_CACHE_SYNC_WAR)
- __asm__ __volatile__ ("sync");
-}
-
-static void r4k_flush_cache_sigtramp(unsigned long addr)
-{
- struct flush_cache_sigtramp_args args;
- int npages;
-
- down_read(&current->mm->mmap_sem);
-
- npages = get_user_pages_fast(addr, 1, 0, &args.page);
- if (npages < 1)
- goto out;
-
- args.mm = current->mm;
- args.addr = addr;
-
- r4k_on_each_cpu(R4K_HIT, local_r4k_flush_cache_sigtramp, &args);
-
- put_page(args.page);
-out:
- up_read(&current->mm->mmap_sem);
-}
-
static void r4k_flush_icache_all(void)
{
if (cpu_has_vtag_icache)
@@ -1137,6 +1045,7 @@ static inline int alias_74k_erratum(struct cpuinfo_mips *c)
return present;
}
+#if defined(CONFIG_CPU_BMIPS5000)
static void b5k_instruction_hazard(void)
{
__sync();
@@ -1148,6 +1057,7 @@ static void b5k_instruction_hazard(void)
" nop; nop; nop; nop; nop; nop; nop; nop\n"
: : : "memory");
}
+#endif
static char *way_string[] = { NULL, "direct mapped", "2-way",
"3-way", "4-way", "5-way", "6-way", "7-way", "8-way",
@@ -1197,6 +1107,7 @@ static void probe_pcache(void)
c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH;
break;
+#if defined(CONFIG_CPU_TX49XX)
case CPU_TX49XX:
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
@@ -1211,7 +1122,10 @@ static void probe_pcache(void)
c->options |= MIPS_CPU_CACHE_CDEX_P;
c->options |= MIPS_CPU_PREFETCH;
break;
+#endif
+#if defined(CONFIG_CPU_R4X00) || \
+ defined(CONFIG_CPU_R4300)
case CPU_R4000PC:
case CPU_R4000SC:
case CPU_R4000MC:
@@ -1231,7 +1145,9 @@ static void probe_pcache(void)
c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
+#endif
+#if defined(CONFIG_CPU_R10000)
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
@@ -1248,7 +1164,9 @@ static void probe_pcache(void)
c->options |= MIPS_CPU_PREFETCH;
break;
+#endif
+#if defined(CONFIG_CPU_VR41XX)
case CPU_VR4133:
write_c0_config(config & ~VR41_CONF_P4K);
case CPU_VR4131:
@@ -1291,7 +1209,9 @@ static void probe_pcache(void)
c->options |= MIPS_CPU_CACHE_CDEX_P;
break;
+#endif
+#if defined(CONFIG_CPU_RM7000)
case CPU_RM7000:
rm7k_erratum31();
@@ -1308,7 +1228,9 @@ static void probe_pcache(void)
c->options |= MIPS_CPU_CACHE_CDEX_P;
c->options |= MIPS_CPU_PREFETCH;
break;
+#endif
+#if defined(CONFIG_CPU_LOONGSON2)
case CPU_LOONGSON2:
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
@@ -1326,7 +1248,9 @@ static void probe_pcache(void)
c->dcache.ways = 2;
c->dcache.waybit = 0;
break;
+#endif
+#if defined(CONFIG_CPU_LOONGSON3)
case CPU_LOONGSON3:
config1 = read_c0_config1();
lsize = (config1 >> 19) & 7;
@@ -1355,7 +1279,9 @@ static void probe_pcache(void)
if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2)
c->options |= MIPS_CPU_PREFETCH;
break;
+#endif
+#if defined(CONFIG_CPU_CAVIUM_OCTEON)
case CPU_CAVIUM_OCTEON3:
/* For now lie about the number of ways. */
c->icache.linesz = 128;
@@ -1370,6 +1296,7 @@ static void probe_pcache(void)
dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz;
c->options |= MIPS_CPU_PREFETCH;
break;
+#endif
default:
if (!(config & MIPS_CONF_M))
@@ -1502,6 +1429,18 @@ static void probe_pcache(void)
c->dcache.flags |= MIPS_CACHE_ALIASES;
}
+ /* Physically indexed caches don't suffer from virtual aliasing */
+ if (c->dcache.flags & MIPS_CACHE_PINDEX)
+ c->dcache.flags &= ~MIPS_CACHE_ALIASES;
+
+ /*
+ * In systems with CM the icache fills from L2 or closer caches, and
+ * thus sees remote stores without needing to write them back any
+ * further than that.
+ */
+ if (mips_cm_present())
+ c->icache.flags |= MIPS_IC_SNOOPS_REMOTE;
+
switch (current_cpu_type()) {
case CPU_20KC:
/*
@@ -1530,19 +1469,20 @@ static void probe_pcache(void)
c->icache.ways = 1;
}
- printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
- icache_size >> 10,
- c->icache.flags & MIPS_CACHE_VTAG ? "VIVT" : "VIPT",
- way_string[c->icache.ways], c->icache.linesz);
+ pr_info("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
+ icache_size >> 10,
+ c->icache.flags & MIPS_CACHE_VTAG ? "VIVT" : "VIPT",
+ way_string[c->icache.ways], c->icache.linesz);
- printk("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes\n",
- dcache_size >> 10, way_string[c->dcache.ways],
- (c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT",
- (c->dcache.flags & MIPS_CACHE_ALIASES) ?
+ pr_info("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes\n",
+ dcache_size >> 10, way_string[c->dcache.ways],
+ (c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT",
+ (c->dcache.flags & MIPS_CACHE_ALIASES) ?
"cache aliases" : "no aliases",
- c->dcache.linesz);
+ c->dcache.linesz);
}
+#if defined(CONFIG_CPU_LOONGSON3)
static void probe_vcache(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -1568,7 +1508,11 @@ static void probe_vcache(void)
pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n",
vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz);
}
+#else
+static inline void probe_vcache(void) {}
+#endif
+#if defined(CONFIG_CPU_R4X00)
/*
* If you even _breathe_ on this function, look at the gcc output and make sure
* it does not pop things on and off the stack for the cache sizing loop that
@@ -1629,7 +1573,9 @@ static int probe_scache(void)
return 1;
}
+#endif
+#if defined(CONFIG_CPU_LOONGSON2)
static void loongson2_sc_init(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -1641,11 +1587,13 @@ static void loongson2_sc_init(void)
c->scache.waysize = scache_size / (c->scache.ways);
c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
- scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
}
+#endif
+#if defined(CONFIG_CPU_LOONGSON3)
static void __init loongson3_sc_init(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -1668,11 +1616,12 @@ static void __init loongson3_sc_init(void)
c->scache.waybit = 0;
c->scache.waysize = scache_size / c->scache.ways;
pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
- scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
if (scache_size)
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
return;
}
+#endif
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
@@ -1681,7 +1630,9 @@ extern int mips_sc_init(void);
static void setup_scache(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
+#if defined(CONFIG_CPU_R10000)
unsigned int config = read_c0_config();
+#endif
int sc_present = 0;
/*
@@ -1690,6 +1641,7 @@ static void setup_scache(void)
* Linux memory management.
*/
switch (current_cpu_type()) {
+#if defined(CONFIG_CPU_R4X00)
case CPU_R4000SC:
case CPU_R4000MC:
case CPU_R4400SC:
@@ -1698,7 +1650,9 @@ static void setup_scache(void)
if (sc_present)
c->options |= MIPS_CPU_CACHE_CDEX_S;
break;
+#endif
+#if defined(CONFIG_CPU_R10000)
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
@@ -1709,6 +1663,7 @@ static void setup_scache(void)
c->scache.waybit= 0;
sc_present = 1;
break;
+#endif
case CPU_R5000:
case CPU_NEVADA:
@@ -1724,11 +1679,15 @@ static void setup_scache(void)
return;
case CPU_LOONGSON2:
+#if defined(CONFIG_CPU_LOONGSON2)
loongson2_sc_init();
+#endif
return;
case CPU_LOONGSON3:
+#if defined(CONFIG_CPU_LOONGSON3)
loongson3_sc_init();
+#endif
return;
case CPU_CAVIUM_OCTEON3:
@@ -1743,9 +1702,9 @@ static void setup_scache(void)
#ifdef CONFIG_MIPS_CPU_SCACHE
if (mips_sc_init ()) {
scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
- printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
- scache_size >> 10,
- way_string[c->scache.ways], c->scache.linesz);
+ pr_info("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
+ scache_size >> 10,
+ way_string[c->scache.ways], c->scache.linesz);
if (current_cpu_type() == CPU_BMIPS5000)
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
@@ -1768,8 +1727,8 @@ static void setup_scache(void)
c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
- printk("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
- scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+ pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
}
@@ -1849,6 +1808,7 @@ static void coherency_setup(void)
* silly idea of putting something else there ...
*/
switch (current_cpu_type()) {
+#if defined(CONFIG_CPU_R4X00)
case CPU_R4000PC:
case CPU_R4000SC:
case CPU_R4000MC:
@@ -1857,6 +1817,7 @@ static void coherency_setup(void)
case CPU_R4400MC:
clear_c0_config(CONF_CU);
break;
+#endif
/*
* We need to catch the early Alchemy SOCs with
* the write-only co_config.od bit and set it back to one on:
@@ -1936,7 +1897,6 @@ void r4k_cache_init(void)
__flush_kernel_vmap_range = r4k_flush_kernel_vmap_range;
- flush_cache_sigtramp = r4k_flush_cache_sigtramp;
flush_icache_all = r4k_flush_icache_all;
local_flush_data_cache_page = local_r4k_flush_data_cache_page;
flush_data_cache_page = r4k_flush_data_cache_page;
@@ -1984,6 +1944,7 @@ void r4k_cache_init(void)
/* No IPI is needed because all CPUs share the same D$ */
flush_data_cache_page = r4k_blast_dcache_page;
break;
+#if defined(CONFIG_CPU_BMIPS5000)
case CPU_BMIPS5000:
/* We lose our superpowers if L2 is disabled */
if (c->scache.flags & MIPS_CACHE_NOT_PRESENT)
@@ -1992,7 +1953,6 @@ void r4k_cache_init(void)
/* I$ fills from D$ just by emptying the write buffers */
flush_cache_page = (void *)b5k_instruction_hazard;
flush_cache_range = (void *)b5k_instruction_hazard;
- flush_cache_sigtramp = (void *)b5k_instruction_hazard;
local_flush_data_cache_page = (void *)b5k_instruction_hazard;
flush_data_cache_page = (void *)b5k_instruction_hazard;
flush_icache_range = (void *)b5k_instruction_hazard;
@@ -2002,6 +1962,8 @@ void r4k_cache_init(void)
/* Optimization: an L2 flush implicitly flushes the L1 */
current_cpu_data.options |= MIPS_CPU_INCLUSIVE_CACHES;
break;
+#endif
+#if defined(CONFIG_CPU_LOONGSON3)
case CPU_LOONGSON3:
/* Loongson-3 maintains cache coherency by hardware */
__flush_cache_all = cache_noop;
@@ -2011,11 +1973,11 @@ void r4k_cache_init(void)
flush_cache_mm = (void *)cache_noop;
flush_cache_page = (void *)cache_noop;
flush_cache_range = (void *)cache_noop;
- flush_cache_sigtramp = (void *)cache_noop;
flush_icache_all = (void *)cache_noop;
flush_data_cache_page = (void *)cache_noop;
local_flush_data_cache_page = (void *)cache_noop;
break;
+#endif
}
}
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index 5c282583edf1..f9c7e2a0cc51 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -289,25 +289,6 @@ static void tx39_dma_cache_inv(unsigned long addr, unsigned long size)
}
}
-static void tx39_flush_cache_sigtramp(unsigned long addr)
-{
- unsigned long ic_lsize = current_cpu_data.icache.linesz;
- unsigned long dc_lsize = current_cpu_data.dcache.linesz;
- unsigned long config;
- unsigned long flags;
-
- protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
-
- /* disable icache (set ICE#) */
- local_irq_save(flags);
- config = read_c0_conf();
- write_c0_conf(config & ~TX39_CONF_ICE);
- TX39_STOP_STREAMING();
- protected_flush_icache_line(addr & ~(ic_lsize - 1));
- write_c0_conf(config);
- local_irq_restore(flags);
-}
-
static __init void tx39_probe_cache(void)
{
unsigned long config;
@@ -367,7 +348,6 @@ void tx39_cache_init(void)
flush_icache_range = (void *) tx39h_flush_icache_all;
local_flush_icache_range = (void *) tx39h_flush_icache_all;
- flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
local_flush_data_cache_page = (void *) tx39h_flush_icache_all;
flush_data_cache_page = (void *) tx39h_flush_icache_all;
@@ -396,7 +376,6 @@ void tx39_cache_init(void)
__flush_kernel_vmap_range = tx39_flush_kernel_vmap_range;
- flush_cache_sigtramp = tx39_flush_cache_sigtramp;
local_flush_data_cache_page = local_tx39_flush_data_cache_page;
flush_data_cache_page = tx39_flush_data_cache_page;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 6db341347202..f913394478dc 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -43,10 +43,8 @@ void (*__flush_cache_vunmap)(void);
void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
-void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
/* MIPS specific cache operations */
-void (*flush_cache_sigtramp)(unsigned long addr);
void (*local_flush_data_cache_page)(void * addr);
void (*flush_data_cache_page)(unsigned long addr);
void (*flush_icache_all)(void);
@@ -63,6 +61,9 @@ void (*_dma_cache_wback)(unsigned long start, unsigned long size);
void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
+#ifdef CONFIG_MIPS_TC3262
+EXPORT_SYMBOL(_dma_cache_inv);
+#endif
#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 46d5696c4f27..cca82ad8d223 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -106,7 +106,11 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
dma_flag = __GFP_DMA;
else
#endif
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_MIPS_L2_CACHE_ER35)
+ dma_flag = __GFP_DMA;
+#else
dma_flag = 0;
+#endif
/* Don't invoke OOM killer */
gfp |= __GFP_NORETRY;
@@ -270,13 +274,8 @@ static inline void __dma_sync(struct page *page,
if (PageHighMem(page)) {
void *addr;
- if (offset + len > PAGE_SIZE) {
- if (offset >= PAGE_SIZE) {
- page += offset >> PAGE_SHIFT;
- offset &= ~PAGE_MASK;
- }
+ if (offset + len > PAGE_SIZE)
len = PAGE_SIZE - offset;
- }
addr = kmap_atomic(page);
__dma_sync_virtual(addr + offset, len, direction);
@@ -290,8 +289,9 @@ static inline void __dma_sync(struct page *page,
} while (left);
}
-static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction, unsigned long attrs)
+static void __maybe_unused
+mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction, unsigned long attrs)
{
if (cpu_needs_post_dma_flush(dev))
__dma_sync(dma_addr_to_page(dev, dma_addr),
@@ -346,8 +346,9 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
}
}
-static void mips_dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
+static void __maybe_unused
+mips_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
{
if (cpu_needs_post_dma_flush(dev))
__dma_sync(dma_addr_to_page(dev, dma_handle),
@@ -363,9 +364,9 @@ static void mips_dma_sync_single_for_device(struct device *dev,
dma_handle & ~PAGE_MASK, size, direction);
}
-static void mips_dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sglist, int nelems,
- enum dma_data_direction direction)
+static void __maybe_unused
+mips_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist,
+ int nelems, enum dma_data_direction direction)
{
int i;
struct scatterlist *sg;
@@ -394,11 +395,6 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
}
}
-int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
- return 0;
-}
-
int mips_dma_supported(struct device *dev, u64 mask)
{
return plat_dma_supported(dev, mask);
@@ -420,14 +416,15 @@ static struct dma_map_ops mips_default_dma_map_ops = {
.free = mips_dma_free_coherent,
.mmap = mips_dma_mmap,
.map_page = mips_dma_map_page,
- .unmap_page = mips_dma_unmap_page,
.map_sg = mips_dma_map_sg,
.unmap_sg = mips_dma_unmap_sg,
+#ifdef CONFIG_DMA_UNMAP_POST_FLUSH
+ .unmap_page = mips_dma_unmap_page,
.sync_single_for_cpu = mips_dma_sync_single_for_cpu,
- .sync_single_for_device = mips_dma_sync_single_for_device,
.sync_sg_for_cpu = mips_dma_sync_sg_for_cpu,
+#endif
+ .sync_single_for_device = mips_dma_sync_single_for_device,
.sync_sg_for_device = mips_dma_sync_sg_for_device,
- .mapping_error = mips_dma_mapping_error,
.dma_supported = mips_dma_supported
};
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 3bef306cdfdb..03c2ca7a0e69 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -209,15 +209,15 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
if (show_unhandled_signals &&
unhandled_signal(tsk, SIGSEGV) &&
__ratelimit(&ratelimit_state)) {
- pr_info("do_page_fault(): sending SIGSEGV to %s for invalid %s %0*lx\n",
+ pr_warn("do_page_fault(): sending SIGSEGV to %s for invalid %s %0*lx\n",
tsk->comm,
write ? "write access to" : "read access from",
field, address);
- pr_info("epc = %0*lx in", field,
+ pr_warn("epc = %0*lx in", field,
(unsigned long) regs->cp0_epc);
print_vma_addr(KERN_CONT " ", regs->cp0_epc);
pr_cont("\n");
- pr_info("ra = %0*lx in", field,
+ pr_warn("ra = %0*lx in", field,
(unsigned long) regs->regs[31]);
print_vma_addr(KERN_CONT " ", regs->regs[31]);
pr_cont("\n");
@@ -267,20 +267,27 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
/* Kernel mode? Handle exceptions or die */
if (!user_mode(regs))
goto no_context;
- else
+
/*
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
-#if 0
- printk("do_page_fault() #3: sending SIGBUS to %s for "
- "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
- tsk->comm,
- write ? "write access to" : "read access from",
- field, address,
- field, (unsigned long) regs->cp0_epc,
- field, (unsigned long) regs->regs[31]);
-#endif
+ if (show_unhandled_signals &&
+ unhandled_signal(tsk, SIGBUS) &&
+ __ratelimit(&ratelimit_state)) {
+ pr_warn("do_page_fault(): sending SIGBUS to %s for invalid %s %0*lx\n",
+ tsk->comm,
+ write ? "write access to" : "read access from",
+ field, address);
+ pr_warn("epc = %0*lx in", field,
+ (unsigned long) regs->cp0_epc);
+ print_vma_addr(KERN_CONT " ", regs->cp0_epc);
+ pr_cont("\n");
+ pr_warn("ra = %0*lx in", field,
+ (unsigned long) regs->regs[31]);
+ print_vma_addr(KERN_CONT " ", regs->regs[31]);
+ pr_cont("\n");
+ }
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
tsk->thread.cp0_badvaddr = address;
info.si_signo = SIGBUS;
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index e86ebcf5c071..367d506bfe68 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -257,6 +257,7 @@ void __init fixrange_init(unsigned long start, unsigned long end,
#endif
}
+#if defined(CONFIG_CPU_MIPS32_R5_FEATURES)
unsigned __weak platform_maar_init(unsigned num_pairs)
{
struct maar_config cfg[BOOT_MEM_MAP_MAX];
@@ -368,6 +369,7 @@ void maar_init(void)
}
}
}
+#endif
#ifndef CONFIG_NEED_MULTIPLE_NODES
int page_is_ram(unsigned long pagenr)
@@ -466,7 +468,9 @@ void __init mem_init(void)
#endif
high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
+#if defined(CONFIG_CPU_MIPS32_R5_FEATURES)
maar_init();
+#endif
free_all_bootmem();
setup_zero_pages(); /* Setup zeroed pages. */
mem_init_free_highmem();
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index f625fd20b21e..6a64998017ca 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -406,6 +406,7 @@ static void build_restore_work_registers(u32 **p)
*/
extern unsigned long pgd_current[];
+#ifndef CONFIG_CPU_MIPS32_R2
/*
* The R3000 TLB handler is simple.
*/
@@ -446,6 +447,7 @@ static void build_r3000_tlb_refill_handler(void)
dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
}
+#endif /* !CONFIG_CPU_MIPS32_R2 */
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
/*
@@ -839,9 +841,11 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
if (pgd_reg != -1) {
/* pgd is in pgd_reg */
+#ifdef CONFIG_CPU_LOONGSON3
if (cpu_has_ldpte)
UASM_i_MFC0(p, ptr, C0_PWBASE);
else
+#endif
UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
} else {
#if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
@@ -1461,6 +1465,7 @@ static void build_r4000_tlb_refill_handler(void)
dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
}
+#ifdef CONFIG_CPU_LOONGSON3
static void setup_pw(void)
{
unsigned long pgd_i, pgd_w;
@@ -1562,6 +1567,7 @@ static void build_loongson3_tlb_refill_handler(void)
local_flush_icache_range(ebase + 0x80, ebase + 0x100);
dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32);
}
+#endif
extern u32 handle_tlbl[], handle_tlbl_end[];
extern u32 handle_tlbs[], handle_tlbs_end[];
@@ -1610,9 +1616,11 @@ static void build_setup_pgd(void)
uasm_i_ehb(&p);
} else {
/* PGD in c0_KScratch */
+#ifdef CONFIG_CPU_LOONGSON3
if (cpu_has_ldpte)
UASM_i_MTC0(&p, a0, C0_PWBASE);
else
+#endif
UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
uasm_i_jr(&p, 31);
uasm_i_ehb(&p);
@@ -1850,7 +1858,7 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r,
}
}
-#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+#if !defined(CONFIG_MIPS_PGD_C0_CONTEXT) && !defined(CONFIG_CPU_MIPS32_R2)
/*
@@ -2007,7 +2015,7 @@ static void build_r3000_tlb_modify_handler(void)
dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_size);
}
-#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
+#endif /* !CONFIG_MIPS_PGD_C0_CONTEXT && !CONFIG_CPU_MIPS32_R2 */
/*
* R4000 style TLB load/store/modify handlers.
@@ -2076,7 +2084,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
static void build_r4000_tlb_load_handler(void)
{
- u32 *p = handle_tlbl;
+ u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbl);
const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
@@ -2259,7 +2267,7 @@ static void build_r4000_tlb_load_handler(void)
static void build_r4000_tlb_store_handler(void)
{
- u32 *p = handle_tlbs;
+ u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbs);
const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
@@ -2314,7 +2322,7 @@ static void build_r4000_tlb_store_handler(void)
static void build_r4000_tlb_modify_handler(void)
{
- u32 *p = handle_tlbm;
+ u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbm);
const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
struct uasm_label *l = labels;
struct uasm_reloc *r = relocs;
@@ -2491,9 +2499,9 @@ static void config_htw_params(void)
print_htw_config();
}
+#ifdef CONFIG_XPA
static void config_xpa_params(void)
{
-#ifdef CONFIG_XPA
unsigned int pagegrain;
if (mips_xpa_disabled) {
@@ -2510,8 +2518,8 @@ static void config_xpa_params(void)
pr_info("Extended Physical Addressing (XPA) enabled\n");
else
panic("Extended Physical Addressing (XPA) disabled");
-#endif
}
+#endif
static void check_pabits(void)
{
@@ -2568,6 +2576,7 @@ void build_tlb_refill_handler(void)
#endif
switch (current_cpu_type()) {
+#ifndef CONFIG_CPU_MIPS32_R2
case CPU_R2000:
case CPU_R3000:
case CPU_R3000A:
@@ -2576,12 +2585,9 @@ void build_tlb_refill_handler(void)
case CPU_TX3922:
case CPU_TX3927:
#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
- if (cpu_has_local_ebase)
- build_r3000_tlb_refill_handler();
if (!run_once) {
- if (!cpu_has_local_ebase)
- build_r3000_tlb_refill_handler();
build_setup_pgd();
+ build_r3000_tlb_refill_handler();
build_r3000_tlb_load_handler();
build_r3000_tlb_store_handler();
build_r3000_tlb_modify_handler();
@@ -2602,9 +2608,12 @@ void build_tlb_refill_handler(void)
panic("No R8000 TLB refill handler yet");
break;
+#endif /* !CONFIG_CPU_MIPS32_R2 */
default:
+#ifdef CONFIG_CPU_LOONGSON3
if (cpu_has_ldpte)
setup_pw();
+#endif
if (!run_once) {
scratch_reg = allocate_kscratch();
@@ -2612,17 +2621,19 @@ void build_tlb_refill_handler(void)
build_r4000_tlb_load_handler();
build_r4000_tlb_store_handler();
build_r4000_tlb_modify_handler();
+#ifdef CONFIG_CPU_LOONGSON3
if (cpu_has_ldpte)
build_loongson3_tlb_refill_handler();
- else if (!cpu_has_local_ebase)
+ else
+#endif
build_r4000_tlb_refill_handler();
flush_tlb_handlers();
run_once++;
}
- if (cpu_has_local_ebase)
- build_r4000_tlb_refill_handler();
+#ifdef CONFIG_XPA
if (cpu_has_xpa)
config_xpa_params();
+#endif
if (cpu_has_htw)
config_htw_params();
}
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 10d86d54880a..70a703c42014 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -146,7 +146,7 @@ unsigned long nlm_next_gp;
unsigned long nlm_next_sp;
static cpumask_t phys_cpu_present_mask;
-void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
+int nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
{
uint64_t picbase;
int hwtid;
@@ -160,6 +160,8 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
/* barrier for sp/gp store above */
__sync();
nlm_pic_send_ipi(picbase, hwtid, 1, 1); /* NMI */
+
+ return 0;
}
void __init nlm_smp_setup(void)
@@ -271,7 +273,7 @@ int nlm_wakeup_secondary_cpus(void)
return 0;
}
-struct plat_smp_ops nlm_smp_ops = {
+const struct plat_smp_ops nlm_smp_ops = {
.send_ipi_single = nlm_send_ipi_single,
.send_ipi_mask = nlm_send_ipi_mask,
.init_secondary = nlm_init_secondary,
diff --git a/arch/mips/paravirt/paravirt-smp.c b/arch/mips/paravirt/paravirt-smp.c
index f8d3e081b2eb..324630445ad9 100644
--- a/arch/mips/paravirt/paravirt-smp.c
+++ b/arch/mips/paravirt/paravirt-smp.c
@@ -99,11 +99,12 @@ static void paravirt_smp_finish(void)
local_irq_enable();
}
-static void paravirt_boot_secondary(int cpu, struct task_struct *idle)
+static int paravirt_boot_secondary(int cpu, struct task_struct *idle)
{
paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle);
smp_wmb();
paravirt_smp_sp[cpu] = __KSTK_TOS(idle);
+ return 0;
}
static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id)
@@ -132,7 +133,7 @@ static void paravirt_prepare_cpus(unsigned int max_cpus)
}
}
-struct plat_smp_ops paravirt_smp_ops = {
+const struct plat_smp_ops paravirt_smp_ops = {
.send_ipi_single = paravirt_send_ipi_single,
.send_ipi_mask = paravirt_send_ipi_mask,
.init_secondary = paravirt_init_secondary,
diff --git a/arch/mips/paravirt/setup.c b/arch/mips/paravirt/setup.c
index cb8448b373a7..d2ffec1409a7 100644
--- a/arch/mips/paravirt/setup.c
+++ b/arch/mips/paravirt/setup.c
@@ -14,7 +14,7 @@
#include <asm/smp-ops.h>
#include <asm/time.h>
-extern struct plat_smp_ops paravirt_smp_ops;
+extern const struct plat_smp_ops paravirt_smp_ops;
const char *get_system_type(void)
{
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
index 1c02f5737367..b4c263f16b15 100644
--- a/arch/mips/pci/fixup-capcella.c
+++ b/arch/mips/pci/fixup-capcella.c
@@ -32,13 +32,13 @@
#define INTC PC104PLUS_INTC_IRQ
#define INTD PC104PLUS_INTD_IRQ
-static char irq_tab_capcella[][5] __initdata = {
+static char irq_tab_capcella[][5] = {
[11] = { -1, INT1, INT1, INT1, INT1 },
[12] = { -1, INT2, INT2, INT2, INT2 },
[14] = { -1, INTA, INTB, INTC, INTD }
};
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_capcella[slot][pin];
}
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index b3ab59318d91..44be65c3e6bb 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -147,7 +147,7 @@ static void qube_raq_via_board_id_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0,
qube_raq_via_board_id_fixup);
-static char irq_tab_qube1[] __initdata = {
+static char irq_tab_qube1[] = {
[COBALT_PCICONF_CPU] = 0,
[COBALT_PCICONF_ETH0] = QUBE1_ETH0_IRQ,
[COBALT_PCICONF_RAQSCSI] = SCSI_IRQ,
@@ -156,7 +156,7 @@ static char irq_tab_qube1[] __initdata = {
[COBALT_PCICONF_ETH1] = 0
};
-static char irq_tab_cobalt[] __initdata = {
+static char irq_tab_cobalt[] = {
[COBALT_PCICONF_CPU] = 0,
[COBALT_PCICONF_ETH0] = ETH0_IRQ,
[COBALT_PCICONF_RAQSCSI] = SCSI_IRQ,
@@ -165,7 +165,7 @@ static char irq_tab_cobalt[] __initdata = {
[COBALT_PCICONF_ETH1] = ETH1_IRQ
};
-static char irq_tab_raq2[] __initdata = {
+static char irq_tab_raq2[] = {
[COBALT_PCICONF_CPU] = 0,
[COBALT_PCICONF_ETH0] = ETH0_IRQ,
[COBALT_PCICONF_RAQSCSI] = RAQ2_SCSI_IRQ,
@@ -174,7 +174,7 @@ static char irq_tab_raq2[] __initdata = {
[COBALT_PCICONF_ETH1] = ETH1_IRQ
};
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (cobalt_board_id <= COBALT_BRD_ID_QUBE1)
return irq_tab_qube1[slot];
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
index 19caf775c206..c31cb6af1cd0 100644
--- a/arch/mips/pci/fixup-emma2rh.c
+++ b/arch/mips/pci/fixup-emma2rh.c
@@ -43,7 +43,7 @@
*/
#define MAX_SLOT_NUM 10
-static unsigned char irq_map[][5] __initdata = {
+static unsigned char irq_map[][5] = {
[3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC,
MARKEINS_PCI_IRQ_INTD, 0,},
[4] = {0, MARKEINS_PCI_IRQ_INTA, 0, 0, 0,},
@@ -85,7 +85,7 @@ static void emma2rh_pci_host_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
emma2rh_pci_host_fixup);
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_map[slot][pin];
}
diff --git a/arch/mips/pci/fixup-fuloong2e.c b/arch/mips/pci/fixup-fuloong2e.c
index 50da773faede..b47c2771dc99 100644
--- a/arch/mips/pci/fixup-fuloong2e.c
+++ b/arch/mips/pci/fixup-fuloong2e.c
@@ -19,7 +19,7 @@
/* South bridge slot number is set by the pci probe process */
static u8 sb_slot = 5;
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = 0;
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
index 133685e215ee..c6ec18a07e63 100644
--- a/arch/mips/pci/fixup-ip32.c
+++ b/arch/mips/pci/fixup-ip32.c
@@ -21,7 +21,7 @@
#define INTB MACEPCI_SHARED0_IRQ
#define INTC MACEPCI_SHARED1_IRQ
#define INTD MACEPCI_SHARED2_IRQ
-static char irq_tab_mace[][5] __initdata = {
+static char irq_tab_mace[][5] = {
/* Dummy INT#A INT#B INT#C INT#D */
{0, 0, 0, 0, 0}, /* This is placeholder row - never used */
{0, SCSI0, SCSI0, SCSI0, SCSI0},
@@ -39,7 +39,7 @@ static char irq_tab_mace[][5] __initdata = {
* irqs. I suppose a device without a pin A will thank us for doing it
* right if there exists such a broken piece of crap.
*/
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_mace[slot][pin];
}
diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c
index 0f1069527cba..d3102eeea898 100644
--- a/arch/mips/pci/fixup-jmr3927.c
+++ b/arch/mips/pci/fixup-jmr3927.c
@@ -31,7 +31,7 @@
#include <asm/txx9/pci.h>
#include <asm/txx9/jmr3927.h>
-int __init jmr3927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int jmr3927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq = pin;
diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c
index 2b5427d3f35c..81530a13b349 100644
--- a/arch/mips/pci/fixup-lantiq.c
+++ b/arch/mips/pci/fixup-lantiq.c
@@ -23,7 +23,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
return 0;
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return of_irq_parse_and_map_pci(dev, slot, pin);
}
diff --git a/arch/mips/pci/fixup-lemote2f.c b/arch/mips/pci/fixup-lemote2f.c
index 95ab9a1bd010..20cdfdc08938 100644
--- a/arch/mips/pci/fixup-lemote2f.c
+++ b/arch/mips/pci/fixup-lemote2f.c
@@ -30,7 +30,7 @@
#define PCID 7
/* all the pci device has the PCIA pin, check the datasheet. */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
/* INTA INTB INTC INTD */
{0, 0, 0, 0, 0}, /* 11: Unused */
{0, 0, 0, 0, 0}, /* 12: Unused */
@@ -51,7 +51,7 @@ static char irq_tab[][5] __initdata = {
{0, 0, 0, 0, 0}, /* 27: Unused */
};
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int virq;
diff --git a/arch/mips/pci/fixup-loongson3.c b/arch/mips/pci/fixup-loongson3.c
index 2b6d5e196f99..8a741c2c6685 100644
--- a/arch/mips/pci/fixup-loongson3.c
+++ b/arch/mips/pci/fixup-loongson3.c
@@ -32,7 +32,7 @@ static void print_fixup_info(const struct pci_dev *pdev)
pdev->vendor, pdev->device, pdev->irq);
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
print_fixup_info(dev);
return dev->irq;
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index 40e920c653cc..3ec85331795e 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -12,7 +12,7 @@
static char pci_irq[5] = {
};
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
/* INTA INTB INTC INTD */
{0, 0, 0, 0, 0 }, /* 0: GT64120 PCI bridge */
{0, 0, 0, 0, 0 }, /* 1: Unused */
@@ -38,7 +38,7 @@ static char irq_tab[][5] __initdata = {
{0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */
};
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int virq;
virq = irq_tab[slot][pin];
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 8e4f8288eca2..66eaf456bc89 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -22,19 +22,19 @@
#include <asm/vr41xx/mpc30x.h>
-static const int internal_func_irqs[] __initconst = {
+static const int internal_func_irqs[] = {
VRC4173_CASCADE_IRQ,
VRC4173_AC97_IRQ,
VRC4173_USB_IRQ,
};
-static const int irq_tab_mpc30x[] __initconst = {
+static const int irq_tab_mpc30x[] = {
[12] = VRC4173_PCMCIA1_IRQ,
[13] = VRC4173_PCMCIA2_IRQ,
[29] = MQ200_IRQ,
};
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (slot == 30)
return internal_func_irqs[PCI_FUNC(dev->devfn)];
diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c
index fab405c21c2f..4ad2ef02087b 100644
--- a/arch/mips/pci/fixup-pmcmsp.c
+++ b/arch/mips/pci/fixup-pmcmsp.c
@@ -47,7 +47,7 @@
#if defined(CONFIG_PMC_MSP7120_GW)
/* Garibaldi Board IRQ wiring to PCI slots */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
/* INTA INTB INTC INTD */
{0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
{0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
@@ -86,7 +86,7 @@ static char irq_tab[][5] __initdata = {
#elif defined(CONFIG_PMC_MSP7120_EVAL)
/* MSP7120 Eval Board IRQ wiring to PCI slots */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
/* INTA INTB INTC INTD */
{0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
{0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
@@ -125,7 +125,7 @@ static char irq_tab[][5] __initdata = {
#else
/* Unknown board -- don't assign any IRQs */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
/* INTA INTB INTC INTD */
{0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
{0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
@@ -202,7 +202,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
* RETURNS: IRQ number
*
****************************************************************************/
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
#if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL)
printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n");
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c
index 321db265829c..d6aaed1d6be9 100644
--- a/arch/mips/pci/fixup-rbtx4927.c
+++ b/arch/mips/pci/fixup-rbtx4927.c
@@ -36,7 +36,7 @@
#include <asm/txx9/pci.h>
#include <asm/txx9/rbtx4927.h>
-int __init rbtx4927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int rbtx4927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq = pin;
diff --git a/arch/mips/pci/fixup-rbtx4938.c b/arch/mips/pci/fixup-rbtx4938.c
index a80579af609b..ff22a22db73e 100644
--- a/arch/mips/pci/fixup-rbtx4938.c
+++ b/arch/mips/pci/fixup-rbtx4938.c
@@ -13,7 +13,7 @@
#include <asm/txx9/pci.h>
#include <asm/txx9/rbtx4938.h>
-int __init rbtx4938_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int rbtx4938_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = tx4938_pcic1_map_irq(dev, slot);
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index f67ebeeb4200..adb9a58641e8 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -40,7 +40,7 @@
* seem to be a documentation error. At least on my RM200C the Cirrus
* Logic CL-GD5434 VGA is device 3.
*/
-static char irq_tab_rm200[8][5] __initdata = {
+static char irq_tab_rm200[8][5] = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* EISA bridge */
{ SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
@@ -57,7 +57,7 @@ static char irq_tab_rm200[8][5] __initdata = {
*
* The VGA card is optional for RM300 systems.
*/
-static char irq_tab_rm300d[8][5] __initdata = {
+static char irq_tab_rm300d[8][5] = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* EISA bridge */
{ SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
@@ -69,7 +69,7 @@ static char irq_tab_rm300d[8][5] __initdata = {
{ 0, INTD, INTA, INTB, INTC }, /* Slot 4 */
};
-static char irq_tab_rm300e[5][5] __initdata = {
+static char irq_tab_rm300e[5][5] = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* HOST bridge */
{ SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
@@ -96,7 +96,7 @@ static char irq_tab_rm300e[5][5] __initdata = {
#define INTC PCIT_IRQ_INTC
#define INTD PCIT_IRQ_INTD
-static char irq_tab_pcit[13][5] __initdata = {
+static char irq_tab_pcit[13][5] = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* HOST bridge */
{ SCSI0, SCSI0, SCSI0, SCSI0, SCSI0 }, /* SCSI */
@@ -113,7 +113,7 @@ static char irq_tab_pcit[13][5] __initdata = {
{ 0, INTA, INTB, INTC, INTD }, /* Slot 5 */
};
-static char irq_tab_pcit_cplus[13][5] __initdata = {
+static char irq_tab_pcit_cplus[13][5] = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* HOST bridge */
{ 0, INTB, INTC, INTD, INTA }, /* PCI Slot 9 */
@@ -130,7 +130,7 @@ static inline int is_rm300_revd(void)
return (csmsr & 0xa0) == 0x20;
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (sni_brd_type) {
case SNI_BRD_PCI_TOWER_CPLUS:
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index d0b0083fbd27..cc581535f257 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -23,7 +23,7 @@
#include <asm/vr41xx/tb0219.h>
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = -1;
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
index 4196ccf3ea3d..b827b5cad5fd 100644
--- a/arch/mips/pci/fixup-tb0226.c
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -23,7 +23,7 @@
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/tb0226.h>
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = -1;
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
index 8c5039ed75d7..98f26285f2e3 100644
--- a/arch/mips/pci/fixup-tb0287.c
+++ b/arch/mips/pci/fixup-tb0287.c
@@ -22,7 +22,7 @@
#include <asm/vr41xx/tb0287.h>
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char bus;
int irq = -1;
diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c
index e99ca7702d8a..f15ec98de2de 100644
--- a/arch/mips/pci/pci-alchemy.c
+++ b/arch/mips/pci/pci-alchemy.c
@@ -522,7 +522,7 @@ static int __init alchemy_pci_init(void)
arch_initcall(alchemy_pci_init);
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct alchemy_pci_context *ctx = dev->sysdata;
if (ctx && ctx->board_map_irq)
diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c
index 76f16eaed0ad..230d7dd273e2 100644
--- a/arch/mips/pci/pci-bcm47xx.c
+++ b/arch/mips/pci/pci-bcm47xx.c
@@ -28,7 +28,7 @@
#include <linux/bcma/bcma.h>
#include <bcm47xx.h>
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return 0;
}
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
index 40d2797d2bc4..47f4ee6bbb3b 100644
--- a/arch/mips/pci/pci-lasat.c
+++ b/arch/mips/pci/pci-lasat.c
@@ -61,7 +61,7 @@ arch_initcall(lasat_pci_setup);
#define LASAT_IRQ_PCIC (LASAT_IRQ_BASE + 7)
#define LASAT_IRQ_PCID (LASAT_IRQ_BASE + 8)
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (slot) {
case 1:
diff --git a/arch/mips/pci/pci-legacy.c b/arch/mips/pci/pci-legacy.c
index 009b840ee5ef..5db63d9836ed 100644
--- a/arch/mips/pci/pci-legacy.c
+++ b/arch/mips/pci/pci-legacy.c
@@ -78,6 +78,12 @@ static void pcibios_scanbus(struct pci_controller *hose)
static int need_domain_info;
LIST_HEAD(resources);
struct pci_bus *bus;
+ struct pci_host_bridge *bridge;
+ int ret;
+
+ bridge = pci_alloc_host_bridge(0);
+ if (!bridge)
+ return;
if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY))
next_busno = (*hose->get_busno)();
@@ -86,20 +92,25 @@ static void pcibios_scanbus(struct pci_controller *hose)
hose->mem_resource, hose->mem_offset);
pci_add_resource_offset(&resources,
hose->io_resource, hose->io_offset);
- pci_add_resource_offset(&resources,
- hose->busn_resource, hose->busn_offset);
- bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
- &resources);
- hose->bus = bus;
+ pci_add_resource(&resources, hose->busn_resource);
+ list_splice_init(&resources, &bridge->windows);
+ bridge->dev.parent = NULL;
+ bridge->sysdata = hose;
+ bridge->busnr = next_busno;
+ bridge->ops = hose->pci_ops;
+ bridge->swizzle_irq = pci_common_swizzle;
+ bridge->map_irq = pcibios_map_irq;
+ ret = pci_scan_root_bus_bridge(bridge);
+ if (ret) {
+ pci_free_host_bridge(bridge);
+ return;
+ }
+
+ hose->bus = bus = bridge->bus;
need_domain_info = need_domain_info || pci_domain_nr(bus);
set_pci_need_domain_info(hose, need_domain_info);
- if (!bus) {
- pci_free_resource_list(&resources);
- return;
- }
-
next_busno = bus->busn_res.end + 1;
/* Don't allow 8-bit bus number overflow inside the hose -
reserve some space for bridges. */
@@ -199,7 +210,7 @@ void register_pci_controller(struct pci_controller *hose)
}
INIT_LIST_HEAD(&hose->list);
- list_add(&hose->list, &controllers);
+ list_add_tail(&hose->list, &controllers);
/*
* Do not panic here but later - this might happen before console init.
@@ -234,8 +245,6 @@ static int __init pcibios_init(void)
list_for_each_entry(hose, &controllers, list)
pcibios_scanbus(hose);
- pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq);
-
pci_initialized = 1;
return 0;
@@ -274,7 +283,7 @@ static int pcibios_enable_resources(struct pci_dev *dev, int mask)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != old_cmd) {
- printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n",
pci_name(dev), old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
diff --git a/arch/mips/pci/pci-mt7620.c b/arch/mips/pci/pci-mt7620.c
index a7962f79c4fe..cc3ddf434efe 100644
--- a/arch/mips/pci/pci-mt7620.c
+++ b/arch/mips/pci/pci-mt7620.c
@@ -361,7 +361,7 @@ static int mt7620_pci_probe(struct platform_device *pdev)
return 0;
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
u16 cmd;
u32 val;
diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c
index 7c512834a8f1..5f8107116334 100644
--- a/arch/mips/pci/pci-octeon.c
+++ b/arch/mips/pci/pci-octeon.c
@@ -59,8 +59,7 @@ union octeon_pci_address {
} s;
};
-int __initconst (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
- u8 slot, u8 pin);
+int (*octeon_pcibios_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
/**
@@ -74,7 +73,7 @@ enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
* as it goes through each bridge.
* Returns Interrupt number for the device
*/
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (octeon_pcibios_map_irq)
return octeon_pcibios_map_irq(dev, slot, pin);
diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c
index d6360fe73d05..711cdccdf65b 100644
--- a/arch/mips/pci/pci-rt2880.c
+++ b/arch/mips/pci/pci-rt2880.c
@@ -181,7 +181,7 @@ static inline void rt2880_pci_write_u32(unsigned long reg, u32 val)
spin_unlock_irqrestore(&rt2880_pci_lock, flags);
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
u16 cmd;
int irq = -1;
diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c
index 3520e9b414e7..e8597d39cd5b 100644
--- a/arch/mips/pci/pci-rt3883.c
+++ b/arch/mips/pci/pci-rt3883.c
@@ -565,7 +565,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
return err;
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return of_irq_parse_and_map_pci(dev, slot, pin);
}
diff --git a/arch/mips/pci/pci-tx4938.c b/arch/mips/pci/pci-tx4938.c
index 141bba562488..d0aceb4d81fe 100644
--- a/arch/mips/pci/pci-tx4938.c
+++ b/arch/mips/pci/pci-tx4938.c
@@ -112,7 +112,7 @@ int __init tx4938_pciclk66_setup(void)
return pciclk;
}
-int __init tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
+int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
{
if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) {
switch (slot) {
diff --git a/arch/mips/pci/pci-tx4939.c b/arch/mips/pci/pci-tx4939.c
index cd8ed09c4f53..8801571ddc73 100644
--- a/arch/mips/pci/pci-tx4939.c
+++ b/arch/mips/pci/pci-tx4939.c
@@ -48,7 +48,7 @@ void __init tx4939_report_pci1clk(void)
((pciclk + 50000) / 100000) % 10);
}
-int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
+int tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
{
if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4939_pcic1ptr) {
switch (slot) {
@@ -68,7 +68,7 @@ int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
return -1;
}
-int __init tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = tx4939_pcic1_map_irq(dev, slot);
diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c
index 7babf01600cb..9eff9137f78e 100644
--- a/arch/mips/pci/pci-xlp.c
+++ b/arch/mips/pci/pci-xlp.c
@@ -205,7 +205,7 @@ int xlp_socdev_to_node(const struct pci_dev *lnkdev)
return PCI_SLOT(lnkdev->devfn) / 8;
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_dev *lnkdev;
int lnkfunc, node;
diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c
index 26d2dabef281..2a1c81a129ba 100644
--- a/arch/mips/pci/pci-xlr.c
+++ b/arch/mips/pci/pci-xlr.c
@@ -315,7 +315,7 @@ static void xls_pcie_ack_b(struct irq_data *d)
}
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return get_irq_vector(dev);
}
diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c
index 9f672ceb089b..aebef6e33000 100644
--- a/arch/mips/pci/pcie-octeon.c
+++ b/arch/mips/pci/pcie-octeon.c
@@ -1464,8 +1464,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port)
* as it goes through each bridge.
* Returns Interrupt number for the device
*/
-int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
- u8 slot, u8 pin)
+int octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
/*
* The EBH5600 board with the PCI to PCIe bridge mistakenly
diff --git a/arch/mips/rt2880/Kconfig b/arch/mips/rt2880/Kconfig
new file mode 100644
index 000000000000..94d6dffe777b
--- /dev/null
+++ b/arch/mips/rt2880/Kconfig
@@ -0,0 +1,110 @@
+
+if RALINK_MT7621
+
+choice
+ prompt "Soc Hardware Type"
+ default MT7621_ASIC
+
+config MT7621_ASIC
+ bool "MT7621-ASIC"
+endchoice
+
+config PCIE_PORT0
+ bool "PCIe Port0 support"
+ default y
+
+config PCIE_PORT1
+ bool "PCIe Port1 support"
+ default n
+
+config PCIE_PORT2
+ bool "PCIe Port2 support"
+ default n
+
+config PCIE_PERST_ONLY
+ bool "Use single PERST_N pin (GPIO19) to reset PCIe peripherals"
+ default y
+endif
+
+#--------------------------
+
+if RALINK_MT7628
+
+choice
+ prompt "Soc Hardware Type"
+ default MT7628_ASIC
+
+config MT7628_ASIC
+ bool "MT7628/MT7688-ASIC"
+endchoice
+
+endif
+
+#--------------------------
+
+config CLKSRC_MIPS_GIC
+ bool "Use MIPS GIC Counter (64 bit)"
+ depends on MIPS_GIC
+ default n
+
+#--------------------------
+
+choice
+ prompt "DRAM Size"
+ default RT2880_DRAM_64M
+
+config RT2880_DRAM_16M
+ bool "16M"
+
+config RT2880_DRAM_32M
+ bool "32M"
+
+config RT2880_DRAM_64M
+ bool "64M"
+
+config RT2880_DRAM_128M
+ bool "128M"
+
+config RT2880_DRAM_256M
+ bool "256M"
+
+config RT2880_DRAM_512M
+ bool "512M (448M + 64M Highmem)"
+ depends on (RALINK_MT7621 || MIPS_TC3262_1004K)
+ select LONG_CALLS
+
+endchoice
+
+config RALINK_RAM_SIZE
+ int
+ default 16 if RT2880_DRAM_16M
+ default 32 if RT2880_DRAM_32M
+ default 64 if RT2880_DRAM_64M
+ default 128 if RT2880_DRAM_128M
+ default 256 if RT2880_DRAM_256M
+ default 512 if RT2880_DRAM_512M
+
+#--------------------------
+
+if MTD
+source "drivers/mtd/ralink/Kconfig"
+endif
+
+#--------------------------
+
+choice
+ prompt "UART Baud Rate"
+ default RT2880_UART_57600
+
+config RT2880_UART_57600
+ bool "57600"
+
+config RT2880_UART_115200
+ bool "115200"
+
+endchoice
+
+config RALINK_UART_BRATE
+ int
+ default 57600 if RT2880_UART_57600
+ default 115200 if RT2880_UART_115200
diff --git a/arch/mips/rt2880/Makefile b/arch/mips/rt2880/Makefile
new file mode 100644
index 000000000000..e5e8d37c5113
--- /dev/null
+++ b/arch/mips/rt2880/Makefile
@@ -0,0 +1,43 @@
+###############################################################################
+# Jan 2007 Bruce Chang
+#
+# Initial Release
+#
+#
+#
+###############################################################################
+
+.S.s:
+ $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+ $(CC) $(CFLAGS) -c $< -o $*.o
+
+obj-y := reset.o init.o memory.o printf.o cmdline.o setup.o time.o
+
+ifdef CONFIG_MIPS_GIC
+obj-y += irqchip-gic.o
+else
+ifdef CONFIG_IRQ_GIC
+obj-y += irq-gic.o
+else
+obj-y += irq.o
+endif
+endif
+
+obj-$(CONFIG_MIPS_CMP) += malta-amon.o
+
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_MTD_NAND_MT7621) += dev-nand.o
+
+ifdef CONFIG_USB_EHCI_HCD_PLATFORM
+obj-y += dev-ehci_ohci.o uphy.o
+endif
+
+ifdef CONFIG_USB_XHCI_MTK
+obj-y += dev-xhci.o uphy.o
+endif
+
+ifdef CONFIG_MTK_MMC
+obj-y += dev-mmc.o
+endif
+
diff --git a/arch/mips/rt2880/Platform b/arch/mips/rt2880/Platform
new file mode 100644
index 000000000000..ba7da7174641
--- /dev/null
+++ b/arch/mips/rt2880/Platform
@@ -0,0 +1,15 @@
+#
+## Ralink MT7621 board
+#
+platform-$(CONFIG_RALINK_MT7621)+= rt2880/
+cflags-$(CONFIG_RALINK_MT7621) += -mtune=1004kc
+cflags-$(CONFIG_RALINK_MT7621) += -I$(srctree)/arch/mips/include/asm/rt2880
+load-$(CONFIG_RALINK_MT7621) += 0xffffffff80001000+$(CONFIG_ZONE_DMA_SIZE)
+
+#
+## Ralink MT7628 board
+#
+platform-$(CONFIG_RALINK_MT7628)+= rt2880/
+cflags-$(CONFIG_RALINK_MT7628) += -mtune=24kec
+cflags-$(CONFIG_RALINK_MT7628) += -I$(srctree)/arch/mips/include/asm/rt2880
+load-$(CONFIG_RALINK_MT7628) += 0xffffffff80000000
diff --git a/arch/mips/rt2880/cmdline.c b/arch/mips/rt2880/cmdline.c
new file mode 100644
index 000000000000..d54744f65d72
--- /dev/null
+++ b/arch/mips/rt2880/cmdline.c
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * cmdline parsing for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#if defined(CONFIG_RT2880_UART_115200)
+#define TTY_UART_CONSOLE "console=ttyS0,115200n8"
+#else
+#define TTY_UART_CONSOLE "console=ttyS0,57600n8"
+#endif
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+extern int prom_argc;
+extern int *_prom_argv;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
+#endif
+
+extern char arcs_cmdline[COMMAND_LINE_SIZE];
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+void __init uboot_cmdline(char *s, size_t size)
+{
+ int i;
+
+ for (i = 1; i < prom_argc; i++) { /* Skip argv[0] */
+ strlcat(s, prom_argv(i), size);
+
+ /* Prevent last space */
+ if (i != prom_argc - 1)
+ strlcat(s, " ", size);
+ }
+}
+#else
+static inline void uboot_cmdline(char *s, size_t size) {}
+#endif
+
+static inline void fixup_cmdline(char *s, size_t size)
+{
+ const char *p = TTY_UART_CONSOLE;
+
+ if (strstr(s, "console="))
+ return;
+
+ /* Add space if there are symbols in buffer */
+ if (*s)
+ strlcat(s, " ", size);
+ strlcat(s, p, size);
+}
+
+void __init prom_init_cmdline(void)
+{
+ uboot_cmdline(arcs_cmdline, sizeof(arcs_cmdline));
+ fixup_cmdline(arcs_cmdline, sizeof(arcs_cmdline));
+}
diff --git a/arch/mips/rt2880/dev-ehci_ohci.c b/arch/mips/rt2880/dev-ehci_ohci.c
new file mode 100644
index 000000000000..f0144c3b8648
--- /dev/null
+++ b/arch/mips/rt2880/dev-ehci_ohci.c
@@ -0,0 +1,212 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * EHCI/OHCI init for Ralink RT3xxx
+ *
+ * Copyright 2009 Ralink Inc. (yyhuang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * March 2009 YYHuang Initial Release
+ **************************************************************************
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM)
+#include <linux/usb/ehci_pdriver.h>
+#endif
+#if IS_ENABLED(CONFIG_USB_OHCI_HCD_PLATFORM)
+#include <linux/usb/ohci_pdriver.h>
+#endif
+
+#include <asm/irq.h>
+#include <asm/rt2880/rt_mmap.h>
+
+#define RT3XXX_EHCI_MEM_START (RALINK_USB_HOST_BASE)
+#define RT3XXX_OHCI_MEM_START (RALINK_USB_HOST_BASE + 0x1000)
+
+static struct resource rt3xxx_ehci_resources[] = {
+ [0] = {
+ .start = RT3XXX_EHCI_MEM_START,
+ .end = RT3XXX_EHCI_MEM_START + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SURFBOARDINT_UHST,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource rt3xxx_ohci_resources[] = {
+ [0] = {
+ .start = RT3XXX_OHCI_MEM_START,
+ .end = RT3XXX_OHCI_MEM_START + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SURFBOARDINT_UHST,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 rt3xxx_ehci_dmamask = DMA_BIT_MASK(32);
+static u64 rt3xxx_ohci_dmamask = DMA_BIT_MASK(32);
+
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) || IS_ENABLED(CONFIG_USB_OHCI_HCD_PLATFORM)
+static atomic_t rt3xxx_power_instance = ATOMIC_INIT(0);
+
+extern void uphy_init(void);
+
+#define SYSCFG1_REG (RALINK_SYSCTL_BASE + 0x14)
+#define RALINK_UHST_MODE (1UL<<10)
+
+#define CLKCFG1_REG (RALINK_SYSCTL_BASE + 0x30)
+#define RSTCTRL_REG (RALINK_SYSCTL_BASE + 0x34)
+
+static void rt_usb_wake_up(void)
+{
+ u32 val;
+
+ /* enable PHY0/1 clock */
+ val = le32_to_cpu(*(volatile u32 *)(CLKCFG1_REG));
+ val |= (RALINK_UPHY0_CLK_EN | RALINK_UPHY1_CLK_EN);
+ *(volatile u32 *)(CLKCFG1_REG) = cpu_to_le32(val);
+
+ mdelay(10);
+
+ /* set HOST mode */
+ val = le32_to_cpu(*(volatile u32 *)(SYSCFG1_REG));
+ val |= (RALINK_UHST_MODE);
+ *(volatile u32 *)(SYSCFG1_REG) = cpu_to_le32(val);
+
+ mdelay(1);
+
+ /* release reset */
+ val = le32_to_cpu(*(volatile u32 *)(RSTCTRL_REG));
+ val &= ~(RALINK_UHST_RST | RALINK_UDEV_RST);
+ *(volatile u32 *)(RSTCTRL_REG) = cpu_to_le32(val);
+
+ mdelay(100);
+
+ uphy_init();
+}
+
+static void rt_usb_sleep(void)
+{
+ u32 val;
+
+ /* raise reset */
+ val = le32_to_cpu(*(volatile u32 *)(RSTCTRL_REG));
+ val |= (RALINK_UHST_RST | RALINK_UDEV_RST);
+ *(volatile u32 *)(RSTCTRL_REG) = cpu_to_le32(val);
+
+ mdelay(10);
+
+ /* disable PHY0/1 clock */
+ val = le32_to_cpu(*(volatile u32 *)(CLKCFG1_REG));
+ val &= ~(RALINK_UPHY0_CLK_EN | RALINK_UPHY1_CLK_EN);
+ *(volatile u32 *)(CLKCFG1_REG) = cpu_to_le32(val);
+
+ udelay(10);
+}
+
+static int rt3xxx_power_on(struct platform_device *pdev)
+{
+ if (atomic_inc_return(&rt3xxx_power_instance) == 1)
+ rt_usb_wake_up();
+
+ return 0;
+}
+
+static void rt3xxx_power_off(struct platform_device *pdev)
+{
+ if (atomic_dec_return(&rt3xxx_power_instance) == 0)
+ rt_usb_sleep();
+}
+
+static struct usb_ehci_pdata rt3xxx_ehci_pdata = {
+ .caps_offset = 0,
+ .has_synopsys_hc_bug = 1,
+ .power_on = rt3xxx_power_on,
+ .power_off = rt3xxx_power_off,
+};
+
+static struct usb_ohci_pdata rt3xxx_ohci_pdata = {
+ .power_on = rt3xxx_power_on,
+ .power_off = rt3xxx_power_off,
+};
+#endif
+
+static struct platform_device rt3xxx_ehci_device = {
+ .name = "ehci-platform",
+ .id = -1,
+ .dev = {
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM)
+ .platform_data = &rt3xxx_ehci_pdata,
+#endif
+ .dma_mask = &rt3xxx_ehci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(rt3xxx_ehci_resources),
+ .resource = rt3xxx_ehci_resources,
+};
+
+static struct platform_device rt3xxx_ohci_device = {
+ .name = "ohci-platform",
+ .id = -1,
+ .dev = {
+#if IS_ENABLED(CONFIG_USB_OHCI_HCD_PLATFORM)
+ .platform_data = &rt3xxx_ohci_pdata,
+#endif
+ .dma_mask = &rt3xxx_ohci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(rt3xxx_ohci_resources),
+ .resource = rt3xxx_ohci_resources,
+};
+
+static struct platform_device *rt3xxx_devices[] __initdata = {
+ &rt3xxx_ehci_device,
+ &rt3xxx_ohci_device,
+};
+
+int __init init_rt3xxx_ehci_ohci(void)
+{
+ int retval = 0;
+
+ retval = platform_add_devices(rt3xxx_devices, ARRAY_SIZE(rt3xxx_devices));
+ if (retval != 0) {
+ printk(KERN_ERR "register %s device fail!\n", "EHCI/OHCI");
+ return retval;
+ }
+
+ return retval;
+}
+
+device_initcall(init_rt3xxx_ehci_ohci);
diff --git a/arch/mips/rt2880/dev-mmc.c b/arch/mips/rt2880/dev-mmc.c
new file mode 100644
index 000000000000..319ec992fd25
--- /dev/null
+++ b/arch/mips/rt2880/dev-mmc.c
@@ -0,0 +1,108 @@
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/rt2880/rt_mmap.h>
+
+#include <ralink/mtk_mmc_dev.h>
+
+#define MTK_SDXC_MEM_START RALINK_MSDC_BASE
+
+static struct resource mtk_mmc_resources[] = {
+ [0] = {
+ .start = MTK_SDXC_MEM_START,
+ .end = MTK_SDXC_MEM_START + 0x3fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SURFBOARDINT_SDXC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+#define CLKCFG1_REG (RALINK_SYSCTL_BASE + 0x30)
+#define RSTCTRL_REG (RALINK_SYSCTL_BASE + 0x34)
+
+static void mtk_mmc_power_on(void)
+{
+ u32 val;
+
+ /* enable SDXC clock */
+ val = le32_to_cpu(*(volatile u32 *)(CLKCFG1_REG));
+ val |= (RALINK_SDXC_CLK_EN);
+ *(volatile u32 *)(CLKCFG1_REG) = cpu_to_le32(val);
+
+ mdelay(1);
+
+ /* release SDXC reset */
+ val = le32_to_cpu(*(volatile u32 *)(RSTCTRL_REG));
+ val &= ~(RALINK_SDXC_RST);
+ *(volatile u32 *)(RSTCTRL_REG) = cpu_to_le32(val);
+
+ mdelay(10);
+}
+
+static void mtk_mmc_power_off(void)
+{
+ u32 val;
+
+ /* raise SDXC reset */
+ val = le32_to_cpu(*(volatile u32 *)(RSTCTRL_REG));
+ val |= (RALINK_SDXC_RST);
+ *(volatile u32 *)(RSTCTRL_REG) = cpu_to_le32(val);
+
+ udelay(100);
+
+ /* disable SDXC clock */
+ val = le32_to_cpu(*(volatile u32 *)(CLKCFG1_REG));
+ val &= ~(RALINK_SDXC_CLK_EN);
+ *(volatile u32 *)(CLKCFG1_REG) = cpu_to_le32(val);
+}
+
+static struct msdc_hw mtk_mmc_hw = {
+ .clk_src = 0,
+ .cmd_edge = MSDC_SMPL_FALLING,
+ .data_edge = MSDC_SMPL_FALLING,
+ .crc_edge = MSDC_SMPL_FALLING,
+ .clk_drv = 4,
+ .cmd_drv = 4,
+ .dat_drv = 4,
+#if defined(CONFIG_MTK_MMC_EMMC_8BIT)
+ .data_pins = 8,
+#else
+ .data_pins = 4,
+#endif
+ .flags = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED,
+ .ext_power_on = mtk_mmc_power_on,
+ .ext_power_off = mtk_mmc_power_off,
+};
+
+static struct platform_device mtk_mmc_device = {
+ .name = MMC_DRV_NAME,
+ .id = 0,
+ .dev = {
+ .platform_data = &mtk_mmc_hw,
+ },
+ .num_resources = ARRAY_SIZE(mtk_mmc_resources),
+ .resource = mtk_mmc_resources,
+};
+
+int __init init_mtk_mmc(void)
+{
+ int retval = 0;
+
+ retval = platform_device_register(&mtk_mmc_device);
+ if (retval != 0) {
+ printk(KERN_ERR "register %s device fail!\n", "MMC");
+ return retval;
+ }
+
+ return retval;
+}
+
+device_initcall(init_mtk_mmc);
diff --git a/arch/mips/rt2880/dev-nand.c b/arch/mips/rt2880/dev-nand.c
new file mode 100644
index 000000000000..48c9b28e1d6e
--- /dev/null
+++ b/arch/mips/rt2880/dev-nand.c
@@ -0,0 +1,57 @@
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/rt2880/rt_mmap.h>
+
+#include <soc/ralink/dev_nand.h>
+
+#define NFI_BASE RALINK_NAND_CTRL_BASE
+#define NFIECC_BASE RALINK_NANDECC_CTRL_BASE
+
+static struct resource mt7621_nand_resource[] = {
+ {
+ .start = NFI_BASE,
+ .end = NFI_BASE + 0x1A0,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = NFIECC_BASE,
+ .end = NFIECC_BASE + 0x150,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SURFBOARDINT_NAND,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = SURFBOARDINT_NAND_ECC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mt7621_nand_device = {
+ .name = MTK_NAND_DRV_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mt7621_nand_resource),
+ .resource = mt7621_nand_resource,
+};
+
+int __init mtk_nand_register(void)
+{
+ int retval = 0;
+
+ retval = platform_device_register(&mt7621_nand_device);
+ if (retval != 0) {
+ printk(KERN_ERR "register %s device fail!\n", "NAND");
+ return retval;
+ }
+
+ return retval;
+}
+
+arch_initcall(mtk_nand_register);
diff --git a/arch/mips/rt2880/dev-xhci.c b/arch/mips/rt2880/dev-xhci.c
new file mode 100644
index 000000000000..87cabfe229ac
--- /dev/null
+++ b/arch/mips/rt2880/dev-xhci.c
@@ -0,0 +1,67 @@
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/rt2880/rt_mmap.h>
+
+#include <soc/ralink/dev_xhci.h>
+
+static struct resource mt7621_xhci_resources[] = {
+ [0] = {
+ .start = RALINK_USB_HOST_BASE,
+ .end = RALINK_USB_HOST_BASE + RALINK_USB_HOST_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "mac",
+ },
+ [1] = {
+ .start = RALINK_USB_IPPC_BASE,
+ .end = RALINK_USB_IPPC_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ .name = "ippc",
+ },
+ [2] = {
+ .start = SURFBOARDINT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 mt7621_xhci_dmamask = DMA_BIT_MASK(32);
+
+extern void uphy_init(void);
+
+static struct xhci_mtk_pdata mt7621_xhci_pdata = {
+ .uphy_init = uphy_init,
+ .usb3_lpm_capable = true,
+};
+
+static struct platform_device mt7621_xhci_device = {
+ .name = XHCI_MTK_DRV_NAME,
+ .id = -1,
+ .dev = {
+ .platform_data = &mt7621_xhci_pdata,
+ .dma_mask = &mt7621_xhci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(mt7621_xhci_resources),
+ .resource = mt7621_xhci_resources,
+};
+
+int __init init_mt7621_xhci(void)
+{
+ int retval = 0;
+
+ retval = platform_device_register(&mt7621_xhci_device);
+ if (retval != 0) {
+ printk(KERN_ERR "register %s device fail!\n", "xHCI");
+ return retval;
+ }
+
+ return retval;
+}
+
+device_initcall(init_mt7621_xhci);
diff --git a/arch/mips/rt2880/init.c b/arch/mips/rt2880/init.c
new file mode 100644
index 000000000000..253f372f0e1f
--- /dev/null
+++ b/arch/mips/rt2880/init.c
@@ -0,0 +1,590 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * init setup for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/serial_8250.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_RALINK_MT7621)
+#include <asm/smp-ops.h>
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
+#include <asm/mips-boards/launch.h>
+#endif
+
+#include <asm/rt2880/prom.h>
+#include <asm/rt2880/generic.h>
+#include <asm/rt2880/surfboard.h>
+#include <asm/rt2880/surfboardint.h>
+#include <asm/rt2880/rt_mmap.h>
+#include <asm/rt2880/rt_serial.h>
+#include <asm/rt2880/eureka_ep430.h>
+
+#define UART_BAUDRATE CONFIG_RALINK_UART_BRATE
+
+#define RALINK_CLKCFG1 *(volatile u32 *)(RALINK_SYSCTL_BASE + 0x30)
+#define RALINK_RSTCTRL *(volatile u32 *)(RALINK_SYSCTL_BASE + 0x34)
+#define RALINK_RSTSTAT *(volatile u32 *)(RALINK_SYSCTL_BASE + 0x38)
+
+u32 mips_cpu_feq;
+u32 surfboard_sysclk;
+u32 ralink_asic_rev_id;
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+/* Environment variable */
+typedef struct {
+ char *name;
+ char *val;
+} t_env_var;
+
+int prom_argc;
+int *_prom_argv, *_prom_envp;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension, if running in 64-bit mode.
+ */
+#define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)]))
+#endif
+
+char *prom_getenv(char *envname)
+{
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+ /*
+ * Return a pointer to the given environment variable.
+ * In 64-bit mode: we're using 64-bit pointers, but all pointers
+ * in the PROM structures are only 32-bit, so we need some
+ * workarounds, if we are running in 64-bit mode.
+ */
+ int i, index=0;
+ char *p, *q;
+
+ i = strlen(envname);
+ while (prom_envp(index)) {
+ p = (char*) KSEG0ADDR(prom_envp(index));
+ if(!strncmp(envname, p, i)) {
+ q = strchr(p, '=');
+ if (q)
+ q++;
+ return q;
+ }
+ index++;
+ }
+#endif
+ return NULL;
+}
+
+static inline void prom_show_pstat(void)
+{
+ unsigned long status;
+ const char *const s = prom_getenv("pstat");
+
+ if (!s)
+ return;
+
+ status = simple_strtoul(s, NULL, 0);
+
+ switch (status) {
+ default:
+ pr_err("SoC power status: unknown (%08lx)\n", status);
+ break;
+ case 3:
+ pr_warn("SoC power status: hardware watchdog reset\n");
+ break;
+ case 2:
+ pr_info("SoC power status: software reset\n");
+ break;
+ case 1:
+ pr_info("SoC power status: power-on reset\n");
+ break;
+ }
+}
+
+#if defined(CONFIG_RALINK_MT7621)
+
+phys_addr_t mips_cpc_default_phys_base(void)
+{
+ return RALINK_CPC_BASE;
+}
+
+static inline void prom_init_cm(void)
+{
+ /* early detection of CMP support */
+ mips_cm_probe();
+ mips_cpc_probe();
+
+ if (mips_cm_numiocu()) {
+ /* Palmbus CM region */
+ write_gcr_reg0_base(CM_GCR_REG0_BASE_VALUE);
+ write_gcr_reg0_mask((CM_GCR_REG0_MASK_VALUE << 16) | CM_GCR_REGn_MASK_CMTGT_IOCU0);
+#ifdef CONFIG_PCI
+ /* PCIe CM region */
+ write_gcr_reg1_base(CM_GCR_REG1_BASE_VALUE);
+ write_gcr_reg1_mask((CM_GCR_REG1_MASK_VALUE << 16) | CM_GCR_REGn_MASK_CMTGT_IOCU0);
+#endif
+ __sync();
+ }
+
+ if (register_cps_smp_ops() == 0)
+ return;
+ if (register_cmp_smp_ops() == 0)
+ return;
+ if (register_vsmp_smp_ops() == 0)
+ return;
+}
+
+bool plat_cpu_core_present(int core)
+{
+ struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
+
+ if (!core)
+ return true;
+
+ launch += core * 2; /* 2 VPEs per core */
+ if (!(launch->flags & LAUNCH_FREADY))
+ return false;
+
+ if (launch->flags & (LAUNCH_FGO | LAUNCH_FGONE))
+ return false;
+
+ return true;
+}
+#endif
+
+static inline void prom_init_pcie(void)
+{
+#if defined(CONFIG_RALINK_MT7628)
+ /* assert PCIe RC RST */
+ RALINK_RSTCTRL |= RALINK_PCIE0_RST;
+
+ /* disable PCIe clock */
+ RALINK_CLKCFG1 &= ~RALINK_PCIE0_CLK_EN;
+
+#if !defined(CONFIG_PCI)
+ /* set PCIe PHY to 1.3mA for power saving */
+ (*((volatile u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET))) = 0x10;
+#endif
+#elif defined(CONFIG_RALINK_MT7621)
+ u32 val = 0;
+#if !defined(CONFIG_PCI) || !defined(CONFIG_PCIE_PORT0)
+ val |= RALINK_PCIE0_RST;
+#endif
+#if !defined(CONFIG_PCI) || !defined(CONFIG_PCIE_PORT1)
+ val |= RALINK_PCIE1_RST;
+#endif
+#if !defined(CONFIG_PCI) || !defined(CONFIG_PCIE_PORT2)
+ val |= RALINK_PCIE2_RST;
+#endif
+ if (val) {
+ /* deassert PCIe RC RST for disabled ports */
+ if ((ralink_asic_rev_id & 0xFFFF) == 0x0101)
+ RALINK_RSTCTRL &= ~(val);
+ else
+ RALINK_RSTCTRL |= (val);
+ udelay(100);
+ }
+#if !defined(CONFIG_PCI) || !(defined(CONFIG_PCIE_PORT0) || defined(CONFIG_PCIE_PORT1))
+ /* set PCIe PHY P0P1 to 1.3mA for power saving */
+ (*((volatile u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET))) = 0x10;
+#endif
+#if !defined(CONFIG_PCI) || !defined(CONFIG_PCIE_PORT2)
+ /* set PCIe PHY P2 to 1.3mA for power saving */
+ (*((volatile u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET))) = 0x10;
+#endif
+#if !defined(CONFIG_PCI)
+ /* assert PCIe RC RST for disabled ports */
+ if ((ralink_asic_rev_id & 0xFFFF) == 0x0101)
+ RALINK_RSTCTRL |= (val);
+ else
+ RALINK_RSTCTRL &= ~(val);
+ /* disable PCIe clock for disabled ports */
+ RALINK_CLKCFG1 &= ~val;
+#endif
+#endif
+}
+
+static inline void prom_init_usb(void)
+{
+#if defined(CONFIG_RALINK_MT7628)
+ u32 reg;
+
+ /* raise USB reset */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34));
+ reg |= (RALINK_UDEV_RST | RALINK_UHST_RST);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34))= reg;
+
+ /* disable PHY0/1 clock */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30));
+ reg &= ~(RALINK_UPHY0_CLK_EN | RALINK_UPHY1_CLK_EN);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30)) = reg;
+#endif
+}
+
+static inline void prom_init_sdxc(void)
+{
+#if defined(CONFIG_RALINK_MT7621) || defined(CONFIG_RALINK_MT7628)
+ u32 reg;
+
+ /* raise SDXC reset */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34));
+ reg |= (RALINK_SDXC_RST);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34))= reg;
+
+ /* disable SDXC clock */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30));
+ reg &= ~(RALINK_SDXC_CLK_EN);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30)) = reg;
+#endif
+}
+
+static inline void prom_init_nand(void)
+{
+#if !defined(CONFIG_MTD_NAND_MT7621)
+#if defined(CONFIG_RALINK_MT7621)
+ u32 reg;
+
+ /* raise NAND reset */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34));
+ reg |= (RALINK_NAND_RST);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34))= reg;
+
+ /* disable NAND clock */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30));
+ reg &= ~(RALINK_NAND_CLK_EN);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30)) = reg;
+#endif
+#endif
+}
+
+static inline void prom_init_spdif(void)
+{
+#if !defined(CONFIG_RALINK_SPDIF)
+#if defined(CONFIG_RALINK_MT7621)
+ u32 reg;
+
+ /* raise SPDIF reset */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34));
+ reg |= (RALINK_SPDIF_RST);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x34))= reg;
+
+ /* disable SPDIF clock */
+ reg = *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30));
+ reg &= ~(RALINK_SPDIF_CLK_EN);
+ *(volatile u32 *)KSEG1ADDR((RALINK_SYSCTL_BASE + 0x30)) = reg;
+#endif
+#endif
+}
+
+static void prom_init_sysclk(void)
+{
+ const char *vendor_name, *ram_type = "DDR2";
+ char asic_id[8];
+ int xtal = 40;
+ u32 reg, ocp_freq;
+ u8 clk_sel;
+#if defined(CONFIG_MT7621_ASIC) || defined(CONFIG_MT7628_ASIC)
+ u8 clk_sel2;
+#endif
+#if defined(CONFIG_RALINK_MT7621)
+ u32 cpu_fdiv = 0;
+ u32 cpu_ffrac = 0;
+ u32 fbdiv = 0;
+#endif
+
+ reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x00));
+ memcpy(asic_id, &reg, 4);
+ reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x04));
+ memcpy(asic_id+4, &reg, 4);
+ asic_id[6] = '\0';
+ asic_id[7] = '\0';
+
+ ralink_asic_rev_id = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x0c));
+
+#if defined(CONFIG_RALINK_MT7621)
+ /* CORE_NUM [17:17], 0: Single Core (S), 1: Dual Core (A) */
+ if (ralink_asic_rev_id & (1UL<<17))
+ asic_id[6] = 'A';
+ else
+ asic_id[6] = 'S';
+#elif defined(CONFIG_RALINK_MT7628)
+ /* Detect MT7688 via FUSE EE_CFG bit 20 */
+ reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x08));
+ if (reg & (1UL<<20))
+ asic_id[4] = '8';
+
+ /* PKG_ID [16:16], 0: DRQFN-120 (KN), 1: DRQFN-156 (AN) */
+ if (ralink_asic_rev_id & (1UL<<16))
+ asic_id[6] = 'A';
+ else
+ asic_id[6] = 'K';
+#endif
+
+ reg = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x10)));
+
+#if defined(CONFIG_MT7621_ASIC)
+ clk_sel = 0; /* GPLL (500MHz) */
+ clk_sel2 = (reg>>4) & 0x03;
+ reg = (reg >> 6) & 0x7;
+ if (reg >= 6)
+ xtal = 25;
+ else if (reg <= 2)
+ xtal = 20;
+ reg = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x2C)));
+ if (reg & (0x1UL << 30))
+ clk_sel = 1; /* CPU PLL */
+#elif defined(CONFIG_MT7628_ASIC)
+ clk_sel = 0; /* CPU PLL (580/575MHz) */
+ clk_sel2 = reg & 0x01;
+ if (!(reg & (1UL<<6)))
+ xtal = 25;
+ reg = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x2C)));
+ if (reg & (0x1UL << 1))
+ clk_sel = 1; /* BBP PLL (480MHz) */
+#else
+#error Please Choice System Type
+#endif
+
+ switch(clk_sel) {
+#if defined(CONFIG_RALINK_MT7621)
+ case 0: /* GPLL (500MHz) */
+ reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x44));
+ cpu_fdiv = ((reg >> 8) & 0x1F);
+ cpu_ffrac = (reg & 0x1F);
+ mips_cpu_feq = (500 * cpu_ffrac / cpu_fdiv) * 1000 * 1000;
+ break;
+ case 1: /* CPU PLL */
+ reg = (*(volatile u32 *)(RALINK_MEMCTRL_BASE + 0x648));
+ fbdiv = ((reg >> 4) & 0x7F) + 1;
+ if (xtal == 25)
+ mips_cpu_feq = 25 * fbdiv * 1000 * 1000; /* 25Mhz Xtal */
+ else
+ mips_cpu_feq = 20 * fbdiv * 1000 * 1000; /* 20/40Mhz Xtal */
+ break;
+#elif defined(CONFIG_RALINK_MT7628)
+ case 0:
+ if (xtal == 25)
+ mips_cpu_feq = 575 * 1000 * 1000; /* 25MHZ Xtal */
+ else
+ mips_cpu_feq = 580 * 1000 * 1000; /* 40MHz Xtal */
+ break;
+ case 1:
+ mips_cpu_feq = (480*1000*1000);
+ break;
+#else
+#error Please Choice Chip Type
+#endif
+ }
+
+#if defined(CONFIG_RALINK_MT7621)
+ if (clk_sel2 & 0x01)
+ ram_type = "DDR2";
+ else
+ ram_type = "DDR3";
+ if (clk_sel2 & 0x02)
+ ocp_freq = mips_cpu_feq/4; /* OCP_RATIO 1:4 */
+ else
+ ocp_freq = mips_cpu_feq/3; /* OCP_RATIO 1:3 */
+ surfboard_sysclk = mips_cpu_feq/4;
+#elif defined(CONFIG_RALINK_MT7628)
+ surfboard_sysclk = mips_cpu_feq/3;
+ if (clk_sel2)
+ ram_type = "DDR1";
+ else
+ ram_type = "DDR2";
+ /* set CPU ratio for sleep mode (USB OCP must be >= 30MHz) */
+ reg = (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x440)));
+ reg &= ~0x0f0f;
+ reg |= 0x0606; /* CPU ratio 1/6 for sleep mode (OCP: 575/6/3 = 31 MHz) */
+ (*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x440))) = reg;
+ udelay(10);
+
+ /* disable request preemption */
+ reg = (*((volatile u32 *)(RALINK_RBUS_MATRIXCTL_BASE + 0x0)));
+ reg &= ~0x04000000;
+ (*((volatile u32 *)(RALINK_RBUS_MATRIXCTL_BASE + 0x0))) = reg;
+
+ /* MIPS reset apply to Andes */
+ RALINK_RSTSTAT |= (1U << 9);
+#else
+ surfboard_sysclk = mips_cpu_feq/3;
+#endif
+
+#if !defined(CONFIG_RALINK_MT7621)
+ ocp_freq = surfboard_sysclk;
+#endif
+
+ vendor_name = "MediaTek";
+
+ printk(KERN_INFO "%s SoC: %s, RevID: %04X, RAM: %s, XTAL: %dMHz\n",
+ vendor_name,
+ asic_id,
+ ralink_asic_rev_id & 0xffff,
+ ram_type,
+ xtal
+ );
+
+ printk(KERN_INFO "CPU/OCP/SYS frequency: %d/%d/%d MHz\n",
+ mips_cpu_feq / 1000 / 1000,
+ ocp_freq / 1000 / 1000,
+ surfboard_sysclk / 1000 / 1000
+ );
+}
+
+/*
+** This function sets up the local prom_rs_table used only for the fake console
+** console (mainly prom_printf for debug display and no input processing)
+** and also sets up the global rs_table used for the actual serial console.
+** To get the correct baud_base value, prom_init_sysclk() must be called before
+** this function is called.
+*/
+
+static void __init prom_init_serial_port(void)
+{
+ unsigned int uartclk;
+ unsigned int clock_divisor;
+ struct uart_port serial_req[2];
+
+ /*
+ * baud rate = system clock freq / (CLKDIV * 16)
+ * CLKDIV=system clock freq/16/baud rate
+ */
+#if defined(CONFIG_RALINK_MT7621)
+ uartclk = 50000000;
+#else
+ uartclk = 40000000;
+#endif
+ clock_divisor = (uartclk / SURFBOARD_BAUD_DIV / UART_BAUDRATE);
+
+ memset(serial_req, 0, sizeof(serial_req));
+
+ // fixed 8n1
+ IER(RALINK_SYSCTL_BASE + 0xC00) = 0;
+ LCR(RALINK_SYSCTL_BASE + 0xC00) = RT2880_UART_LCR_WLEN8;
+ DLL(RALINK_SYSCTL_BASE + 0xC00) = (clock_divisor & 0xFF);
+ DLM(RALINK_SYSCTL_BASE + 0xC00) = (clock_divisor >> 8) & 0xFF;
+ FCR(RALINK_SYSCTL_BASE + 0xC00) = 7; /* reset TX and RX */
+
+ // fixed 8n1
+ IER(RALINK_SYSCTL_BASE + 0xD00) = 0;
+ LCR(RALINK_SYSCTL_BASE + 0xD00) = RT2880_UART_LCR_WLEN8;
+ DLL(RALINK_SYSCTL_BASE + 0xD00) = (clock_divisor & 0xFF);
+ DLM(RALINK_SYSCTL_BASE + 0xD00) = (clock_divisor >> 8) & 0xFF;
+ FCR(RALINK_SYSCTL_BASE + 0xD00) = 7; /* reset TX and RX */
+
+ serial_req[0].line = 0;
+ serial_req[0].type = PORT_16550A;
+ serial_req[0].iotype = UPIO_MEM32;
+ serial_req[0].irq = SURFBOARDINT_UART1;
+ serial_req[0].flags = UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ serial_req[0].uartclk = uartclk;
+ serial_req[0].regshift = 2;
+ serial_req[0].mapbase = RALINK_UART_LITE_BASE;
+ serial_req[0].membase = ioremap_nocache(serial_req[0].mapbase, 0x0100);
+ serial_req[0].mapsize = 0x0100;
+ early_serial_setup(&serial_req[0]);
+
+#if !defined(CONFIG_RALINK_GPIOMODE_UARTF) && (CONFIG_SERIAL_8250_NR_UARTS > 1)
+ serial_req[1].line = 1;
+ serial_req[1].type = PORT_16550A;
+ serial_req[1].iotype = UPIO_MEM32;
+ serial_req[1].irq = SURFBOARDINT_UART2;
+ serial_req[1].flags = UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ serial_req[1].uartclk = uartclk;
+ serial_req[1].regshift = 2;
+ serial_req[1].mapbase = RALINK_UART_BASE;
+ serial_req[1].membase = ioremap_nocache(serial_req[1].mapbase, 0x0100);
+ serial_req[1].mapsize = 0x0100;
+ early_serial_setup(&serial_req[1]);
+#endif
+}
+
+int __init prom_get_ttysnum(void)
+{
+ char *argptr;
+ int ttys_num = 0; /* default UART Lite */
+
+ /* get ttys_num to use with the fake console/prom_printf */
+ argptr = prom_getcmdline();
+
+ if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
+ argptr += strlen("console=ttyS");
+ if (argptr[0] == '0') /* ttyS0 */
+ ttys_num = 0; /* happens to be rs_table[0] */
+ else if (argptr[0] == '1') /* ttyS1 */
+ ttys_num = 1; /* happens to be rs_table[1] */
+ }
+
+ return (ttys_num);
+}
+
+void __init prom_init(void)
+{
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+ prom_argc = fw_arg0;
+ _prom_argv = (int*) fw_arg1;
+ _prom_envp = (int*) fw_arg2;
+#endif
+
+ set_io_port_base(KSEG1);
+
+ /* remove all wired TLB entries */
+ write_c0_wired(0);
+
+ prom_init_cmdline();
+ prom_init_printf(prom_get_ttysnum());
+ prom_init_sysclk();
+ prom_init_serial_port(); /* Needed for Serial Console */
+ prom_init_usb(); /* USB power saving */
+ prom_init_pcie(); /* PCIe power saving */
+ prom_init_sdxc(); /* SDXC power saving */
+ prom_init_nand(); /* NAND power saving */
+ prom_init_spdif(); /* SPDIF power saving */
+ prom_meminit();
+#if defined(CONFIG_RALINK_MT7621)
+ prom_init_cm();
+#endif
+
+ prom_show_pstat();
+
+ prom_printf("Linux kernel started.\n");
+}
+
diff --git a/arch/mips/rt2880/irq-gic.c b/arch/mips/rt2880/irq-gic.c
new file mode 100644
index 000000000000..44ab12669dc5
--- /dev/null
+++ b/arch/mips/rt2880/irq-gic.c
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Interrupt routines for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ * Initial Release
+ *
+ * May 2009 Bruce Chang
+ * support RT3883 PCIe
+ *
+ **************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/mips-cm.h>
+#include <asm/irq_cpu.h>
+#include <asm/gic.h>
+
+#include <asm/rt2880/rt_mmap.h>
+#include <asm/rt2880/surfboardint.h>
+
+#define X GIC_UNUSED
+static const struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 00: CPU Coherence Manager Error
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 01: CPU CM Perf Cnt overflow
+ { X, X, X, X, 0 }, // 02: N/A
+ { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 03: FE
+ { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 04: PCIe0
+ { X, X, X, X, 0 }, // 05: AUX_STCK
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 06: SYSCTL
+ { X, X, X, X, 0 }, // 07: N/A
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 08: I2C
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 09: DRAMC
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 10: PCM
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 11: HS GDMA
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 12: GPIO
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 13: GDMA
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 14: NFI NAND
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 15: NFI ECC
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 16: I2S
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 17: SPI
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 18: SPDIF
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 19: CryptoEngine
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 20: SDXC
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 21: Rbus to Pbus
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 22: USB XHCI
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 23: ESW MT7530
+ { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 24: PCIe1
+ { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 25: PCIe2
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 26: UART 1
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 27: UART 2
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 28: UART 3
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 29: Timer WDG
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 30: Timer0
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, // 31: Timer1
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 32: PCIE_P0_LINT_DOWN_RST
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 33: PCIE_P1_LINT_DOWN_RST
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 34: PCIE_P2_LINT_DOWN_RST
+ { X, X, X, X, 0 }, // 35: N/A
+ { X, X, X, X, 0 }, // 36: N/A
+ { X, X, X, X, 0 }, // 37: N/A
+ { X, X, X, X, 0 }, // 38: N/A
+ { X, X, X, X, 0 }, // 39: N/A
+ { X, X, X, X, 0 }, // 40: N/A
+ { X, X, X, X, 0 }, // 41: N/A
+ { X, X, X, X, 0 }, // 42: N/A
+ { X, X, X, X, 0 }, // 43: N/A
+ { X, X, X, X, 0 }, // 44: N/A
+ { X, X, X, X, 0 }, // 45: N/A
+ { X, X, X, X, 0 }, // 46: N/A
+ { X, X, X, X, 0 }, // 47: N/A
+ { X, X, X, X, 0 }, // 48: N/A
+ { X, X, X, X, 0 }, // 49: N/A
+ { X, X, X, X, 0 }, // 50: N/A
+ { X, X, X, X, 0 }, // 51: N/A
+ { X, X, X, X, 0 }, // 52: N/A
+ { X, X, X, X, 0 }, // 53: N/A
+ { X, X, X, X, 0 }, // 54: N/A
+ { X, X, X, X, 0 }, // 55: N/A
+ { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 56: IPI resched 0
+ { 1, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 57: IPI resched 1
+ { 2, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 58: IPI resched 2
+ { 3, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 59: IPI resched 3
+ { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 60: IPI call 0
+ { 1, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 61: IPI call 1
+ { 2, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, // 62: IPI call 2
+ { 3, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 0 } // 63: IPI call 3
+};
+#undef X
+
+static int mips_cpu_timer_irq = CP0_LEGACY_COMPARE_IRQ;
+
+static void mips_timer_dispatch(void)
+{
+ do_IRQ(mips_cpu_timer_irq);
+}
+
+unsigned int get_c0_compare_int(void)
+{
+ mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+
+ return mips_cpu_timer_irq;
+}
+
+void mtk_disable_irq_all(void)
+{
+ unsigned long flags;
+
+ if (!gic_present)
+ return;
+
+ local_irq_save(flags);
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 0x00), 0xffffffff);
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 0x04), 0xffffffff);
+ local_irq_restore(flags);
+}
+
+void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
+{
+ int i;
+
+ for (i = 0; i < irqs; i++)
+ irq_set_chip(gic_irq_base + i, irq_controller);
+
+ for (i = 0; i < (GIC_NUM_INTRS - 8); i++) {
+ if (gic_intr_map[i].cpunum == GIC_UNUSED)
+ continue;
+
+ if (gic_intr_map[i].trigtype == GIC_TRIG_EDGE)
+ irq_set_handler(gic_irq_base + i, handle_edge_irq);
+ else
+ irq_set_handler(gic_irq_base + i, handle_level_irq);
+ }
+}
+
+void __init arch_init_irq(void)
+{
+ phys_addr_t gic_base = RALINK_GIC_BASE;
+
+ mips_cpu_irq_init();
+
+ if (mips_cm_present()) {
+ gic_base = read_gcr_gic_base() & ~CM_GCR_GIC_BASE_GICEN_MSK;
+
+ write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK);
+ __sync();
+ }
+
+ gic_present = true;
+
+ gic_init(gic_base, RALINK_GIC_ADDRSPACE_SZ, gic_intr_map,
+ ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE + GIC_SHARED_HWIRQ_BASE);
+
+ if (cpu_has_vint) {
+ set_vi_handler(GIC_CPU_PIN_OFFSET + GIC_CPU_INT0, gic_irq_dispatch); // Other
+#ifdef CONFIG_MIPS_MT_SMP
+ set_vi_handler(GIC_CPU_PIN_OFFSET + GIC_CPU_INT1, gic_irq_dispatch); // IPI resched
+ set_vi_handler(GIC_CPU_PIN_OFFSET + GIC_CPU_INT2, gic_irq_dispatch); // IPI call
+#endif
+ set_vi_handler(GIC_CPU_PIN_OFFSET + GIC_CPU_INT3, gic_irq_dispatch); // FE
+ set_vi_handler(GIC_CPU_PIN_OFFSET + GIC_CPU_INT4, gic_irq_dispatch); // PCIe
+ set_vi_handler(GIC_CPU_PIN_OFFSET + GIC_CPU_INT5, mips_timer_dispatch);
+ }
+
+#ifdef CONFIG_MIPS_MT_SMP
+ set_c0_status(STATUSF_IP7 | STATUSF_IP6 | STATUSF_IP5 | STATUSF_IP2 |
+ STATUSF_IP4 | STATUSF_IP3);
+#else
+ set_c0_status(STATUSF_IP7 | STATUSF_IP6 | STATUSF_IP5 | STATUSF_IP2);
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending;
+
+ pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ if (unlikely(!pending)) {
+ spurious_interrupt();
+ return;
+ }
+
+ if (pending & CAUSEF_IP7)
+ mips_timer_dispatch();
+
+ if (pending & (CAUSEF_IP6 | CAUSEF_IP5 | CAUSEF_IP4 | CAUSEF_IP3 | CAUSEF_IP2))
+ gic_irq_dispatch();
+}
diff --git a/arch/mips/rt2880/irq.c b/arch/mips/rt2880/irq.c
new file mode 100644
index 000000000000..9f563c48d7f3
--- /dev/null
+++ b/arch/mips/rt2880/irq.c
@@ -0,0 +1,236 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Interrupt routines for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ * Initial Release
+ *
+ * May 2009 Bruce Chang
+ * support RT3883 PCIe
+ *
+ **************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/irq_cpu.h>
+
+#include <asm/rt2880/rt_mmap.h>
+
+static unsigned int fiq_mask;
+
+unsigned int get_c0_compare_int(void)
+{
+ return SURFBOARDINT_MIPS_TIMER;
+}
+
+#if IS_ENABLED(CONFIG_HW_PERF_EVENTS) || IS_ENABLED(CONFIG_OPROFILE)
+int get_c0_perfcount_int(void)
+{
+ return SURFBOARDINT_PCTRL;
+}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
+#endif
+
+static void mask_ralink_irq(struct irq_data *id)
+{
+ unsigned int irq_mask = BIT(id->hwirq);
+
+ if (irq_mask & fiq_mask)
+ *(volatile u32 *)(RALINK_FIQDIS) = irq_mask;
+ else
+ *(volatile u32 *)(RALINK_INTDIS) = irq_mask;
+}
+
+static void unmask_ralink_irq(struct irq_data *id)
+{
+ unsigned int irq_mask = BIT(id->hwirq);
+
+ if (irq_mask & fiq_mask)
+ *(volatile u32 *)(RALINK_FIQENA) = irq_mask;
+ else
+ *(volatile u32 *)(RALINK_INTENA) = irq_mask;
+}
+
+static struct irq_chip ralink_irq_chip = {
+ .name = "INTC",
+ .irq_mask = mask_ralink_irq,
+ .irq_mask_ack = mask_ralink_irq,
+ .irq_unmask = unmask_ralink_irq,
+ .irq_disable = mask_ralink_irq,
+ .irq_enable = unmask_ralink_irq,
+};
+
+static int ralink_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &ralink_irq_chip, handle_level_irq);
+ return 0;
+}
+
+static const struct irq_domain_ops ralink_intc_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = ralink_intc_map,
+};
+
+static void ralink_intc_irq_handler(struct irq_desc *desc)
+{
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
+ u32 pending;
+
+ if (irq_desc_get_irq(desc) == MIPS_INTC_CHAIN_HW1)
+ pending = *(volatile u32 *)(RALINK_IRQ1STAT);
+ else
+ pending = *(volatile u32 *)(RALINK_IRQ0STAT);
+
+ if (unlikely(!pending)) {
+ spurious_interrupt();
+ return;
+ }
+
+ generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
+}
+
+static void dispatch_mips_line_timer(void)
+{
+ do_IRQ(SURFBOARDINT_MIPS_TIMER);
+}
+
+static void dispatch_mips_line_wlan(void)
+{
+ do_IRQ(SURFBOARDINT_WLAN);
+}
+
+static void dispatch_mips_line_fe(void)
+{
+ do_IRQ(SURFBOARDINT_FE);
+}
+
+static void dispatch_mips_line_pci(void)
+{
+ do_IRQ(SURFBOARDINT_PCIE0);
+}
+
+static void dispatch_mips_chain_hw1(void)
+{
+ do_IRQ(MIPS_INTC_CHAIN_HW1);
+}
+
+static void dispatch_mips_chain_hw0(void)
+{
+ do_IRQ(MIPS_INTC_CHAIN_HW0);
+}
+
+void mtk_disable_irq_all(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *(volatile u32 *)(RALINK_FIQDIS) = ~0u;
+ *(volatile u32 *)(RALINK_INTDIS) = ~0u;
+ local_irq_restore(flags);
+}
+
+void __init arch_init_irq(void)
+{
+ struct irq_domain *domain;
+ unsigned int int_type = 0;
+
+ mips_cpu_irq_init();
+
+ /* disable all interrupts */
+ *(volatile u32 *)(RALINK_FIQDIS) = ~0u;
+ *(volatile u32 *)(RALINK_INTDIS) = ~0u;
+
+ /* route some INTC interrupts to MIPS HW1 interrupt (high priority) */
+#ifdef RALINK_INTCTL_UHST
+ int_type |= RALINK_INTCTL_UHST;
+#endif
+#ifdef RALINK_INTCTL_SDXC
+ int_type |= RALINK_INTCTL_SDXC;
+#endif
+#ifdef RALINK_INTCTL_CRYPTO
+ int_type |= RALINK_INTCTL_CRYPTO;
+#endif
+ int_type |= RALINK_INTCTL_DMA;
+ *(volatile u32 *)(RALINK_INTTYPE) = int_type;
+
+ if (cpu_has_vint) {
+ pr_info("Setting up vectored interrupts\n");
+ set_vi_handler(SURFBOARDINT_MIPS_TIMER, dispatch_mips_line_timer);
+ set_vi_handler(SURFBOARDINT_WLAN, dispatch_mips_line_wlan);
+ set_vi_handler(SURFBOARDINT_FE, dispatch_mips_line_fe);
+ set_vi_handler(SURFBOARDINT_PCIE0, dispatch_mips_line_pci);
+ set_vi_handler(MIPS_INTC_CHAIN_HW1, dispatch_mips_chain_hw1);
+ set_vi_handler(MIPS_INTC_CHAIN_HW0, dispatch_mips_chain_hw0);
+ }
+
+ domain = irq_domain_add_legacy(NULL, INTC_NUM_INTRS, MIPS_INTC_IRQ_BASE, 0, &ralink_intc_domain_ops, NULL);
+ if (!domain)
+ panic("Failed to add irqdomain");
+
+ irq_set_chained_handler_and_data(MIPS_INTC_CHAIN_HW0, ralink_intc_irq_handler, domain);
+ irq_set_chained_handler_and_data(MIPS_INTC_CHAIN_HW1, ralink_intc_irq_handler, domain);
+
+ /* enable global interrupt bit */
+ fiq_mask = int_type;
+ *(volatile u32 *)(RALINK_FIQENA) = BIT(31);
+ *(volatile u32 *)(RALINK_INTENA) = BIT(31);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending;
+
+ pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ if (unlikely(!pending)) {
+ spurious_interrupt();
+ return;
+ }
+
+ if (pending & CAUSEF_IP7)
+ do_IRQ(SURFBOARDINT_MIPS_TIMER);
+
+ if (pending & CAUSEF_IP5)
+ do_IRQ(SURFBOARDINT_FE);
+
+ if (pending & CAUSEF_IP6)
+ do_IRQ(SURFBOARDINT_WLAN);
+
+ if (pending & CAUSEF_IP4)
+ do_IRQ(SURFBOARDINT_PCIE0);
+
+ if (pending & CAUSEF_IP3)
+ do_IRQ(MIPS_INTC_CHAIN_HW1);
+
+ if (pending & CAUSEF_IP2)
+ do_IRQ(MIPS_INTC_CHAIN_HW0);
+}
+
diff --git a/arch/mips/rt2880/irqchip-gic.c b/arch/mips/rt2880/irqchip-gic.c
new file mode 100644
index 000000000000..62961cbcdc90
--- /dev/null
+++ b/arch/mips/rt2880/irqchip-gic.c
@@ -0,0 +1,63 @@
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/irq_cpu.h>
+
+#include <asm/rt2880/rt_mmap.h>
+
+#ifndef CONFIG_CLKSRC_MIPS_GIC
+unsigned int get_c0_compare_int(void)
+{
+ return gic_get_c0_compare_int();
+}
+#endif
+
+#if IS_ENABLED(CONFIG_HW_PERF_EVENTS) || IS_ENABLED(CONFIG_OPROFILE)
+int get_c0_perfcount_int(void)
+{
+ /*
+ * Performance counter events are routed through GIC.
+ * Prevent them from firing on CPU IRQ7 as well
+ */
+ clear_c0_status(IE_SW0 << 7);
+
+ return gic_get_c0_perfcount_int();
+}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
+#endif
+
+#ifdef CONFIG_MIPS_EJTAG_FDC_TTY
+int get_c0_fdc_int(void)
+{
+ return gic_get_c0_fdc_int();
+}
+#endif
+
+void mtk_disable_irq_all(void)
+{
+}
+
+void __init arch_init_irq(void)
+{
+ phys_addr_t gic_base = RALINK_GIC_BASE;
+ size_t gic_len = RALINK_GIC_ADDRSPACE_SZ;
+
+ mips_cpu_irq_init();
+
+ if (mips_cm_present()) {
+ gic_base = read_gcr_gic_base() & ~CM_GCR_GIC_BASE_GICEN_MSK;
+
+ write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK);
+ __sync();
+ }
+
+ gic_present = true;
+
+ gic_init(gic_base, gic_len, GIC_CPU_PIN_OFFSET, 0);
+
+ /* set EDGE type int for MT7530 MCM (prevent race) */
+ irq_set_irq_type(SURFBOARDINT_ESW, IRQ_TYPE_EDGE_RISING);
+}
+
diff --git a/arch/mips/rt2880/malta-amon.c b/arch/mips/rt2880/malta-amon.c
new file mode 100644
index 000000000000..84ac523b0ce0
--- /dev/null
+++ b/arch/mips/rt2880/malta-amon.c
@@ -0,0 +1,88 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * Arbitrary Monitor Interface
+ */
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/addrspace.h>
+#include <asm/mipsmtregs.h>
+#include <asm/mips-boards/launch.h>
+#include <asm/vpe.h>
+
+int amon_cpu_avail(int cpu)
+{
+ struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
+
+ if (cpu < 0 || cpu >= NCPULAUNCH) {
+ pr_debug("avail: cpu%d is out of range\n", cpu);
+ return 0;
+ }
+
+ launch += cpu;
+ if (!(launch->flags & LAUNCH_FREADY)) {
+ pr_debug("avail: cpu%d is not ready\n", cpu);
+ return 0;
+ }
+ if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
+ pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
+ return 0;
+ }
+
+ return 1;
+}
+
+int amon_cpu_start(int cpu,
+ unsigned long pc, unsigned long sp,
+ unsigned long gp, unsigned long a0)
+{
+ volatile struct cpulaunch *launch =
+ (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
+
+ if (!amon_cpu_avail(cpu))
+ return -1;
+ if (cpu == smp_processor_id()) {
+ pr_debug("launch: I am cpu%d!\n", cpu);
+ return -1;
+ }
+ launch += cpu;
+
+ pr_debug("launch: starting cpu%d\n", cpu);
+
+ launch->pc = pc;
+ launch->gp = gp;
+ launch->sp = sp;
+ launch->a0 = a0;
+
+ smp_wmb(); /* Target must see parameters before go */
+ launch->flags |= LAUNCH_FGO;
+ smp_wmb(); /* Target must see go before we poll */
+
+ while ((launch->flags & LAUNCH_FGONE) == 0)
+ ;
+ smp_rmb(); /* Target will be updating flags soon */
+ pr_debug("launch: cpu%d gone!\n", cpu);
+
+ return 0;
+}
+
+#ifdef CONFIG_MIPS_VPE_LOADER_CMP
+int vpe_run(struct vpe *v)
+{
+ struct vpe_notifications *n;
+
+ if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0)
+ return -1;
+
+ list_for_each_entry(n, &v->notify, list)
+ n->start(VPE_MODULE_MINOR);
+
+ return 0;
+}
+#endif
diff --git a/arch/mips/rt2880/memory.c b/arch/mips/rt2880/memory.c
new file mode 100644
index 000000000000..3f1c92bb8bc4
--- /dev/null
+++ b/arch/mips/rt2880/memory.c
@@ -0,0 +1,122 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * memory setup for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <asm/rt2880/prom.h>
+
+//#define DEBUG
+
+#define RAM_BASE 0x00000000
+#define RAM_SIZE (CONFIG_RALINK_RAM_SIZE*1024*1024)
+#define RAM_SIZE_MIN (8*1024*1024)
+
+#if defined(CONFIG_RALINK_MT7621)
+#define RAM_SIZE_MAX (512*1024*1024)
+#else
+#define RAM_SIZE_MAX (256*1024*1024)
+#endif
+
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+static unsigned int __init prom_get_ramsize(void)
+{
+ char *argptr;
+ unsigned int ramsize = 0;
+
+ argptr = prom_getcmdline();
+
+ if ((argptr = strstr(argptr, "ramsize=")) != NULL) {
+ argptr += strlen("ramsize=");
+ ramsize = simple_strtoul(&argptr[0], NULL, 0);
+ }
+
+ return ramsize;
+}
+#endif
+
+void __init prom_meminit(void)
+{
+ phys_addr_t ramsize = 0;
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+ ramsize = (phys_addr_t)prom_get_ramsize();
+#endif
+ if (ramsize < RAM_SIZE_MIN || ramsize > RAM_SIZE_MAX)
+ ramsize = RAM_SIZE;
+
+#if defined(CONFIG_RALINK_MT7621)
+ if (ramsize > 0x1c000000) {
+ /* 1. Normal region 0..448MB */
+ add_memory_region(RAM_BASE, 0x1c000000, BOOT_MEM_RAM);
+
+#ifdef CONFIG_HIGHMEM
+ /* 2. Highmem region */
+ add_memory_region(0x20000000, (ramsize - 0x1c000000), BOOT_MEM_RAM);
+#endif
+ } else
+#endif
+ add_memory_region(RAM_BASE, ramsize, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+#ifdef DEBUG
+ /* Nothing to do! Need only for DEBUG. */
+ /* This is may be corrupt working memory. */
+
+ unsigned long addr;
+ int i;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+ continue;
+
+ addr = boot_mem_map.map[i].addr;
+ free_init_pages("prom memory", addr, addr + boot_mem_map.map[i].size);
+ }
+#endif
+}
+
diff --git a/arch/mips/rt2880/pci.c b/arch/mips/rt2880/pci.c
new file mode 100644
index 000000000000..bc4b8cf54736
--- /dev/null
+++ b/arch/mips/rt2880/pci.c
@@ -0,0 +1,808 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PCI init for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ * Initial Release
+ *
+ * May 2009 Bruce Chang
+ * support RT2880/RT3883 PCIe
+ *
+ * May 2011 Bruce Chang
+ * support RT6855/MT7620 PCIe
+ *
+ **************************************************************************
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/rt2880/eureka_ep430.h>
+
+#ifdef CONFIG_PCI
+
+//#define RAPCI_DEBUG
+
+#if defined(CONFIG_RT2880_DRAM_512M)
+#define BAR0_MASK 0x1FFF0000
+#elif defined(CONFIG_RT2880_DRAM_256M)
+#define BAR0_MASK 0x0FFF0000
+#elif defined(CONFIG_RT2880_DRAM_128M)
+#define BAR0_MASK 0x07FF0000
+#elif defined(CONFIG_RT2880_DRAM_64M)
+#define BAR0_MASK 0x03FF0000
+#elif defined(CONFIG_RT2880_DRAM_32M)
+#define BAR0_MASK 0x01FF0000
+#else
+#define BAR0_MASK 0x7FFF0000 /* 2G */
+#endif
+
+/*
+ * These functions and structures provide the BIOS scan and mapping of the PCI
+ * devices.
+ */
+
+#if defined(CONFIG_RALINK_MT7621)
+#define RALINK_SYSTEM_CONTROL_BASE 0xbe000000
+#define RALINK_PCI_MM_MAP_BASE 0x60000000
+#define RALINK_PCI_IO_MAP_BASE 0x1e160000
+#else
+#define RALINK_SYSTEM_CONTROL_BASE 0xb0000000
+#define RALINK_PCI_MM_MAP_BASE 0x20000000
+#define RALINK_PCI_IO_MAP_BASE 0x10160000
+#endif
+
+#define BAR0_MEMORY_BASE 0x0
+
+#if defined(CONFIG_RALINK_MT7621)
+extern u32 ralink_asic_rev_id;
+static int pcie_link_status = 0;
+
+/* use GPIO control instead of PERST_N (pulse from driver) */
+#define GPIO_PERST
+
+/* uncomment this to enable PCIe ports Spread Spectrum (MT7603E Ch14 Rx De-sense issue) */
+//#define PCIE_PHY_SSC
+
+#define PCIE_SHARE_PIN_SW 10 // PERST_N GPIO Mode
+#if defined(GPIO_PERST)
+#define GPIO_PCIE_PORT0 19 // PERST_N
+#if defined(CONFIG_RALINK_I2S) || defined(CONFIG_RALINK_I2S_MODULE) || defined(CONFIG_PCIE_PERST_ONLY)
+#define UARTL3_SHARE_PIN_SW PCIE_SHARE_PIN_SW
+#define GPIO_PCIE_PORT1 GPIO_PCIE_PORT0
+#define GPIO_PCIE_PORT2 GPIO_PCIE_PORT0
+#else
+#define UARTL3_SHARE_PIN_SW 3 // UART3 GPIO Mode
+#define GPIO_PCIE_PORT1 8 // RXD3 (I2S_SDI)
+#define GPIO_PCIE_PORT2 7 // TXD3 (I2S_WS)
+#endif
+#define RALINK_GPIO_CTRL0 *(volatile u32 *)(RALINK_PIO_BASE + 0x00)
+#define RALINK_GPIO_DATA0 *(volatile u32 *)(RALINK_PIO_BASE + 0x20)
+#endif
+
+#define ASSERT_SYSRST_PCIE(val) do { \
+ if ((ralink_asic_rev_id & 0xFFFF) == 0x0101) \
+ RALINK_RSTCTRL |= val; \
+ else \
+ RALINK_RSTCTRL &= ~val; \
+ } while(0)
+#define DEASSERT_SYSRST_PCIE(val) do { \
+ if ((ralink_asic_rev_id & 0xFFFF) == 0x0101) \
+ RALINK_RSTCTRL &= ~val; \
+ else \
+ RALINK_RSTCTRL |= val; \
+ } while(0)
+#endif
+
+#define RALINK_SYSCFG1 *(volatile u32 *)(RALINK_SYSTEM_CONTROL_BASE + 0x14)
+#define RALINK_CLKCFG1 *(volatile u32 *)(RALINK_SYSTEM_CONTROL_BASE + 0x30)
+#define RALINK_RSTCTRL *(volatile u32 *)(RALINK_SYSTEM_CONTROL_BASE + 0x34)
+#define RALINK_GPIOMODE *(volatile u32 *)(RALINK_SYSTEM_CONTROL_BASE + 0x60)
+
+#define PCI_ACCESS_READ_1 0
+#define PCI_ACCESS_READ_2 1
+#define PCI_ACCESS_READ_4 2
+#define PCI_ACCESS_WRITE_1 3
+#define PCI_ACCESS_WRITE_2 4
+#define PCI_ACCESS_WRITE_4 5
+
+static DEFINE_SPINLOCK(asic_pcr_lock);
+
+static int config_access(int access_type, u32 busn, u32 slot, u32 func, u32 where, u32 *data)
+{
+ unsigned int address, shift, tmp;
+ unsigned long flags;
+
+ /* setup PCR address */
+ address = (1u << 31) | (((where & 0xf00) >> 8) << 24) | (busn << 16) | (slot << 11) | (func << 8) | (where & 0xfc);
+
+ shift = (where & 0x3) << 3;
+
+ spin_lock_irqsave(&asic_pcr_lock, flags);
+
+ /* start the configuration cycle */
+ RALINK_PCI_PCR_ADDR = address;
+
+ switch (access_type) {
+ case PCI_ACCESS_WRITE_1:
+ tmp = RALINK_PCI_PCR_DATA;
+ tmp &= ~(0xff << shift);
+ tmp |= ((*data & 0xff) << shift);
+ RALINK_PCI_PCR_DATA = tmp;
+ break;
+ case PCI_ACCESS_WRITE_2:
+ tmp = RALINK_PCI_PCR_DATA;
+ if (shift > 16)
+ shift = 16;
+ tmp &= ~(0xffff << shift);
+ tmp |= ((*data & 0xffff) << shift);
+ RALINK_PCI_PCR_DATA = tmp;
+ break;
+ case PCI_ACCESS_WRITE_4:
+ RALINK_PCI_PCR_DATA = *data;
+ break;
+ case PCI_ACCESS_READ_1:
+ tmp = RALINK_PCI_PCR_DATA;
+ *data = (tmp >> shift) & 0xff;
+ break;
+ case PCI_ACCESS_READ_2:
+ tmp = RALINK_PCI_PCR_DATA;
+ if (shift > 16)
+ shift = 16;
+ *data = (tmp >> shift) & 0xffff;
+ break;
+ case PCI_ACCESS_READ_4:
+ *data = RALINK_PCI_PCR_DATA;
+ break;
+ }
+
+ spin_unlock_irqrestore(&asic_pcr_lock, flags);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int ralink_pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
+{
+ u32 busn = bus->number;
+ u32 slot = PCI_SLOT(devfn);
+ u32 func = PCI_FUNC(devfn);
+ int access_type = PCI_ACCESS_READ_4;
+
+ switch (size) {
+ case 1:
+ access_type = PCI_ACCESS_READ_1;
+ break;
+ case 2:
+ access_type = PCI_ACCESS_READ_2;
+ break;
+ }
+
+ return config_access(access_type, busn, slot, func, (u32)where, val);
+}
+
+static int ralink_pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+ u32 busn = bus->number;
+ u32 slot = PCI_SLOT(devfn);
+ u32 func = PCI_FUNC(devfn);
+ int access_type = PCI_ACCESS_WRITE_4;
+
+ switch (size) {
+ case 1:
+ access_type = PCI_ACCESS_WRITE_1;
+ break;
+ case 2:
+ access_type = PCI_ACCESS_WRITE_2;
+ break;
+ }
+
+ return config_access(access_type, busn, slot, func, (u32)where, &val);
+}
+
+/*
+ * General-purpose PCI functions.
+ */
+
+struct pci_ops ralink_pci_ops = {
+ .read = ralink_pci_config_read,
+ .write = ralink_pci_config_write,
+};
+
+static struct resource ralink_res_pci_mem1 = {
+ .name = "PCI MEM1",
+ .start = RALINK_PCI_MM_MAP_BASE,
+ .end = (RALINK_PCI_MM_MAP_BASE + 0x0fffffff),
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource ralink_res_pci_io1 = {
+ .name = "PCI I/O1",
+ .start = RALINK_PCI_IO_MAP_BASE,
+ .end = (RALINK_PCI_IO_MAP_BASE + 0x0ffff),
+ .flags = IORESOURCE_IO,
+};
+
+struct pci_controller ralink_pci_controller = {
+ .pci_ops = &ralink_pci_ops,
+ .mem_resource = &ralink_res_pci_mem1,
+ .io_resource = &ralink_res_pci_io1,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ u32 __maybe_unused val;
+#ifdef RAPCI_DEBUG
+ int i;
+ struct resource *res;
+
+ printk("%s: ** bus: %d, slot: 0x%x\n", __FUNCTION__, dev->bus->number, PCI_SLOT(dev->devfn));
+
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val);
+ printk(" PCI_BASE_ADDRESS_0: 0x%08X\n", val);
+
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, &val);
+ printk(" PCI_BASE_ADDRESS_1: 0x%08X\n", val);
+
+ pci_read_config_dword(dev, PCI_IO_BASE, &val);
+ printk(" PCI_IO_BASE: 0x%08X\n", val);
+
+ for (i = 0; i < 2; i++) {
+ res = (struct resource*)&dev->resource[i];
+ printk(" res[%d]->start = %x\n", i, res->start);
+ printk(" res[%d]->end = %x\n", i, res->end);
+ }
+#endif
+
+ /* P2P bridge */
+ if (dev->bus->number == 0) {
+ /* set N_FTS 0x28 -> 0x50 */
+ val = 0;
+ pci_read_config_dword(dev, 0x70c, &val);
+ val &= ~(0xff<<8);
+ val |= (0x50<<8);
+ pci_write_config_dword(dev, 0x70c, val);
+
+ /* set CLS */
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES >> 2));
+ }
+
+ return 0;
+}
+
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int pci_irq = 0;
+#if defined(CONFIG_RALINK_MT7621)
+ if ((dev->bus->number == 1) && (slot == 0x0)) {
+ switch (pcie_link_status) {
+ case 0x2:
+ case 0x6:
+ pci_irq = SURFBOARDINT_PCIE1;
+ break;
+ case 0x4:
+ pci_irq = SURFBOARDINT_PCIE2;
+ break;
+ default:
+ pci_irq = SURFBOARDINT_PCIE0;
+ }
+ } else if ((dev->bus->number == 2) && (slot == 0x0)) {
+ switch (pcie_link_status) {
+ case 0x5:
+ case 0x6:
+ pci_irq = SURFBOARDINT_PCIE2;
+ break;
+ default:
+ pci_irq = SURFBOARDINT_PCIE1;
+ }
+ } else if ((dev->bus->number == 2) && (slot == 0x1)) {
+ switch (pcie_link_status) {
+ case 0x5:
+ case 0x6:
+ pci_irq = SURFBOARDINT_PCIE2;
+ break;
+ default:
+ pci_irq = SURFBOARDINT_PCIE1;
+ }
+ } else if ((dev->bus->number == 3) && (slot == 0x0)) {
+ pci_irq = SURFBOARDINT_PCIE2;
+ } else if ((dev->bus->number == 3) && (slot == 0x1)) {
+ pci_irq = SURFBOARDINT_PCIE2;
+ } else if ((dev->bus->number == 3) && (slot == 0x2)) {
+ pci_irq = SURFBOARDINT_PCIE2;
+ }
+#elif defined(CONFIG_RALINK_MT7628)
+ if ((dev->bus->number == 1) && (slot == 0x0)) {
+ pci_irq = SURFBOARDINT_PCIE0;
+ }
+#endif
+
+#ifdef RAPCI_DEBUG
+ printk("%s: ** bus: %d, slot: 0x%x -> irq: %d\n", __FUNCTION__, dev->bus->number, slot, pci_irq);
+#endif
+
+ return pci_irq;
+}
+
+static void set_pcie_phy(u32 *addr, int start_b, int bits, int val)
+{
+ *(volatile u32 *)(addr) &= ~(((1<<bits) - 1)<<start_b);
+ *(volatile u32 *)(addr) |= val << start_b;
+}
+
+#if defined(CONFIG_RALINK_MT7621)
+static void bypass_pipe_rst(void)
+{
+#if defined(CONFIG_PCIE_PORT0)
+ /* PCIe Port 0 */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4]
+#endif
+#if defined(CONFIG_PCIE_PORT1)
+ /* PCIe Port 1 */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 12, 1, 0x01); // rg_pe1_pipe_rst_b
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4]
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ /* PCIe Port 2 */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4]
+#endif
+}
+
+static void set_phy_for_ssc(void)
+{
+ u32 reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10));
+
+ reg = (reg >> 6) & 0x7;
+#if defined(CONFIG_PCIE_PORT0) || defined(CONFIG_PCIE_PORT1)
+ /* Set PCIe Port0 & Port1 PHY to disable SSC */
+ /* Debug Xtal Type */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 1 enable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x00); // rg_pe1_phy_en //Port 1 disable
+ if (reg <= 5 && reg >= 3) {
+ /* 40MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+
+ /* SSC option tune from -5000ppm to -1000ppm */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x1a); // RG_LC_DDS_SSC_DELTA
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x1a); // RG_LC_DDS_SSC_DELTA1
+ } else {
+ /* 25MHz or 20MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+ if (reg >= 6) {
+ /* 25MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode)
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial
+
+ /* SSC option tune from -5000ppm to -1000ppm */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x11); // RG_LC_DDS_SSC_DELTA
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x11); // RG_LC_DDS_SSC_DELTA1
+ } else {
+ /* 20MHz Xtal */
+
+ /* SSC option tune from -5000ppm to -1000ppm */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x1a); // RG_LC_DDS_SSC_DELTA
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x1a); // RG_LC_DDS_SSC_DELTA1
+ }
+ }
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN
+ if (reg <= 5 && reg >= 3) {
+ /* 40MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv
+ }
+#ifdef PCIE_PHY_SSC
+ /* Enable Port0&Port1 SSC */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 28, 2, 0x1); // rg_pe1_frc_lcdds_ssc_en //value of da_pe1_mstckdiv when force mode enable
+#else
+ /* Disable Port0&Port1 SSC */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 28, 2, 0x0); // rg_pe1_frc_lcdds_ssc_en //value of da_pe1_mstckdiv when force mode enable
+#endif
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x040), 17, 4, 0x07); // rg_pe1_crtmsel //value of da[x]_pe1_crtmsel when force mode enable for Port 0
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x040), 16, 1, 0x01); // rg_pe1_frc_crtmsel //force mode enable of da[x]_pe1_crtmsel for Port 0
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x140), 17, 4, 0x07); // rg_pe1_crtmsel //value of da[x]_pe1_crtmsel when force mode enable for Port 1
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x140), 16, 1, 0x01); // rg_pe1_frc_crtmsel //force mode enable of da[x]_pe1_crtmsel for Port 1
+ /* Enable PHY and disable force mode */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x01); // rg_pe1_phy_en //Port 1 enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 1 disable control
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ /* Set PCIe Port2 PHY to disable SSC */
+ /* Debug Xtal Type */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable
+ if (reg <= 5 && reg >= 3) {
+ /* 40MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+
+ /* SSC option tune from -5000ppm to -1000ppm */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x1a); // RG_LC_DDS_SSC_DELTA
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x1a); // RG_LC_DDS_SSC_DELTA1
+ } else {
+ /* 25MHz or 20MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+ if (reg >= 6) {
+ /* 25MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode)
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial
+
+ /* SSC option tune from -5000ppm to -1000ppm */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x11); // RG_LC_DDS_SSC_DELTA
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x11); // RG_LC_DDS_SSC_DELTA1
+ } else {
+ /* 20MHz Xtal */
+
+ /* SSC option tune from -5000ppm to -1000ppm */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x1a); // RG_LC_DDS_SSC_DELTA
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x1a); // RG_LC_DDS_SSC_DELTA1
+ }
+ }
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN
+ if (reg <= 5 && reg >= 3) {
+ /* 40MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv
+ }
+#ifdef PCIE_PHY_SSC
+ /* Enable Port2 SSC */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 28, 2, 0x1); // rg_pe1_frc_lcdds_ssc_en //value of da_pe1_mstckdiv when force mode enable
+#else
+ /* Disable Port2 SSC */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 28, 2, 0x0); // rg_pe1_frc_lcdds_ssc_en //value of da_pe1_mstckdiv when force mode enable
+#endif
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x040), 17, 4, 0x07); // rg_pe1_crtmsel //value of da[x]_pe1_crtmsel when force mode enable for Port 0
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x040), 16, 1, 0x01); // rg_pe1_frc_crtmsel //force mode enable of da[x]_pe1_crtmsel for Port 0
+ /* Enable PHY and disable force mode */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control
+#endif
+}
+#endif
+
+#if defined(CONFIG_MT7628_ASIC)
+void pcie_phy_config(void)
+{
+ u32 reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10));
+
+ reg = (reg >> 6) & 0x1;
+
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x400), 8, 1, 0x01); // [rg_pe1_frc_h_xtal_type]: Enable Crystal type force mode
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x400), 9, 2, 0x00); // [rg_pe1_h_xtal_type]: Force Crystal type = 20MHz
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x000), 4, 1, 0x01); // [rg_pe1_frc_phy_en]: Enable Port 0 force mode
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x000), 5, 1, 0x00); // [rg_pe1_phy_en]: Port 0 disable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4AC),16, 3, 0x03); // [RG_PE1_H_PLL_BR]
+ if (reg == 1) {
+ /* 40MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4BC),24, 8, 0x7D); // [RG_PE1_H_PLL_FBKDIV]
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x490),12, 4, 0x08); // [RG_PE1_H_PLL_IR]
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x490), 6, 2, 0x01); // [RG_PE1_H_PLL_PREDIV]: Pre-divider ratio (for host mode)
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4C0), 0,32, 0x1F400000); // [RG_PE1_H_LCDDS_PCW_NCPO]: For 40MHz crystal input
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4A4), 0,16, 0x013D); // [RG_PE1_H_LCDDS_SSC_PRD]
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4A8),16,16, 0x74); // [RG_PE1_H_LCDDS_SSC_DELTA1]: For SSC=4500ppm
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4A8), 0,16, 0x74); // [RG_PE1_H_LCDDS_SSC_DELTA]: For SSC=4500ppm
+ } else {
+ /* 25MHz Xtal */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4BC),24, 8, 0x64); // [RG_PE1_H_PLL_FBKDIV]
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x490),12, 4, 0x0A); // [RG_PE1_H_PLL_IR]
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x490), 6, 2, 0x00); // [RG_PE1_H_PLL_PREDIV]: Pre-divider ratio (for host mode)
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4C0), 0,32, 0x19000000); // [RG_PE1_H_LCDDS_PCW_NCPO]: For 25MHz crystal input
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4A4), 0,16, 0x018D); // [RG_PE1_H_LCDDS_SSC_PRD]
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4A8),16,16, 0x4A); // [RG_PE1_H_LCDDS_SSC_DELTA1]: For SSC=4500ppm
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x4A8), 0,16, 0x4A); // [RG_PE1_H_LCDDS_SSC_DELTA]: For SSC=4500ppm
+ }
+ /* MT7628 PCIe PHY LDO setting: 0x1 -> 0x5 (1.0V -> 1.2V) */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x498), 0, 8, 0x05);
+
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x000), 5, 1, 0x01); // Port 0 enable [rg_pe1_phy_en]
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0_CTL_OFFSET + 0x000), 4, 1, 0x00); // Disable Port 0 force mode [rg_pe1_frc_phy_en]
+}
+#endif
+
+int __init init_ralink_pci(void)
+{
+ u32 __maybe_unused val;
+
+ PCIBIOS_MIN_IO = 0;
+ PCIBIOS_MIN_MEM = 0;
+
+#if defined(CONFIG_RALINK_MT7621)
+ pcie_link_status = 0;
+ val = RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIE2_RST;
+ ASSERT_SYSRST_PCIE(val); // raise reset all PCIe ports
+ udelay(100);
+#if defined(GPIO_PERST)
+ val = RALINK_GPIOMODE;
+ val &= ~((0x3<<PCIE_SHARE_PIN_SW) | (0x3<<UARTL3_SHARE_PIN_SW));
+ val |= ((0x1<<PCIE_SHARE_PIN_SW) | (0x1<<UARTL3_SHARE_PIN_SW));
+ if (RALINK_GPIOMODE != val) {
+ RALINK_GPIOMODE = val;
+ mdelay(100);
+ }
+ val = 0;
+#if defined(CONFIG_PCIE_PORT0)
+ val |= (0x1<<GPIO_PCIE_PORT0);
+#endif
+#if defined(CONFIG_PCIE_PORT1)
+ val |= (0x1<<GPIO_PCIE_PORT1);
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ val |= (0x1<<GPIO_PCIE_PORT2);
+#endif
+ RALINK_GPIO_CTRL0 |= val; // switch PERST_N pin to output mode
+ mdelay(100);
+ RALINK_GPIO_DATA0 &= ~(val); // fall PERST_N pin (reset peripherals)
+#else /* !defined(GPIO_PERST) */
+ RALINK_GPIOMODE &= ~(0x3<<PCIE_SHARE_PIN_SW); // fall PERST_N pin (reset peripherals)
+#endif
+ mdelay(100); // wait 100 ms pulse
+
+ val = 0;
+#if defined(CONFIG_PCIE_PORT0)
+ val |= RALINK_PCIE0_RST;
+#endif
+#if defined(CONFIG_PCIE_PORT1)
+ val |= RALINK_PCIE1_RST;
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ val |= RALINK_PCIE2_RST;
+#endif
+ DEASSERT_SYSRST_PCIE(val); // release reset for needed PCIe ports
+
+ val = RALINK_CLKCFG1;
+ val &= ~(RALINK_PCIE0_CLK_EN | RALINK_PCIE1_CLK_EN | RALINK_PCIE2_CLK_EN);
+#if defined(CONFIG_PCIE_PORT0)
+ val |= RALINK_PCIE0_CLK_EN;
+#endif
+#if defined(CONFIG_PCIE_PORT1)
+ val |= RALINK_PCIE1_CLK_EN;
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ val |= RALINK_PCIE2_CLK_EN;
+#endif
+ RALINK_CLKCFG1 = val; // enable clock for needed PCIe ports
+
+ mdelay(10);
+
+ if ((ralink_asic_rev_id & 0xFFFF) == 0x0101) // MT7621 E2
+ bypass_pipe_rst();
+
+ set_phy_for_ssc();
+
+ mdelay(100);
+
+#if defined(GPIO_PERST)
+ val = 0;
+#if defined(CONFIG_PCIE_PORT0)
+ val |= (0x1<<GPIO_PCIE_PORT0);
+#endif
+#if defined(CONFIG_PCIE_PORT1)
+ val |= (0x1<<GPIO_PCIE_PORT1);
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ val |= (0x1<<GPIO_PCIE_PORT2);
+#endif
+ RALINK_GPIO_DATA0 |= val; // rise PERST_N pin (complete reset peripherals)
+#else /* !defined(GPIO_PERST) */
+ RALINK_PCI_PCICFG_ADDR &= ~(1<<1); // release PCIRST
+#endif
+
+#elif defined(CONFIG_RALINK_MT7628)
+ RALINK_GPIOMODE &= ~(0x01<<16); // PERST_GPIO_MODE = 1'b0
+
+ RALINK_RSTCTRL &= ~RALINK_PCIE0_RST;
+ RALINK_CLKCFG1 |= RALINK_PCIE0_CLK_EN;
+
+ mdelay(100);
+
+ pcie_phy_config();
+
+ mdelay(10);
+
+ RALINK_PCI_PCICFG_ADDR &= ~(1<<1); // release PCIRST
+#endif
+
+ /* wait before detect card in slots */
+ mdelay(500);
+
+#if defined(CONFIG_RALINK_MT7621)
+#if defined(CONFIG_PCIE_PORT0)
+ if ((RALINK_PCI0_STATUS & 0x1) == 0) {
+ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST);
+ RALINK_CLKCFG1 &= ~RALINK_PCIE0_CLK_EN;
+ printk("%s: no card, disable it (RST&CLK)\n", "PCIe0");
+ } else {
+ pcie_link_status |= (1<<0);
+ }
+#endif
+#if defined(CONFIG_PCIE_PORT1)
+ if ((RALINK_PCI1_STATUS & 0x1) == 0) {
+ ASSERT_SYSRST_PCIE(RALINK_PCIE1_RST);
+ RALINK_CLKCFG1 &= ~RALINK_PCIE1_CLK_EN;
+ printk("%s: no card, disable it (RST&CLK)\n", "PCIe1");
+ } else {
+ pcie_link_status |= (1<<1);
+ }
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ if ((RALINK_PCI2_STATUS & 0x1) == 0) {
+ ASSERT_SYSRST_PCIE(RALINK_PCIE2_RST);
+ RALINK_CLKCFG1 &= ~RALINK_PCIE2_CLK_EN;
+ printk("%s: no card, disable it (RST&CLK)\n", "PCIe2");
+ } else {
+ pcie_link_status |= (1<<2);
+ }
+#endif
+
+ /* No cards, exit */
+ if (pcie_link_status == 0)
+ return 0;
+
+/*
+ pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num
+ 3'b000 x x x
+ 3'b001 x x 0
+ 3'b010 x 0 x
+ 3'b011 x 1 0
+ 3'b100 0 x x
+ 3'b101 1 x 0
+ 3'b110 1 0 x
+ 3'b111 2 1 0
+*/
+ switch (pcie_link_status) {
+ case 0x2:
+ /* PCIe1 only */
+ RALINK_PCI_PCICFG_ADDR &= ~0x00ff0000;
+ RALINK_PCI_PCICFG_ADDR |= (0x1 << 16); // PCIe0 -> port1
+ RALINK_PCI_PCICFG_ADDR |= (0x0 << 20); // PCIe1 -> port0 (*)
+ break;
+ case 0x4:
+ /* PCIe2 only */
+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000;
+ RALINK_PCI_PCICFG_ADDR |= (0x1 << 16); // PCIe0 -> port1
+ RALINK_PCI_PCICFG_ADDR |= (0x2 << 20); // PCIe1 -> port2
+ RALINK_PCI_PCICFG_ADDR |= (0x0 << 24); // PCIe2 -> port0 (*)
+ break;
+ case 0x5:
+ /* PCIe0 + PCIe2 */
+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000;
+ RALINK_PCI_PCICFG_ADDR |= (0x0 << 16); // PCIe0 -> port0 (*)
+ RALINK_PCI_PCICFG_ADDR |= (0x2 << 20); // PCIe1 -> port2
+ RALINK_PCI_PCICFG_ADDR |= (0x1 << 24); // PCIe2 -> port1 (*)
+ break;
+ case 0x6:
+ /* PCIe1 + PCIe2 */
+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000;
+ RALINK_PCI_PCICFG_ADDR |= (0x2 << 16); // PCIe0 -> port2
+ RALINK_PCI_PCICFG_ADDR |= (0x0 << 20); // PCIe1 -> port0 (*)
+ RALINK_PCI_PCICFG_ADDR |= (0x1 << 24); // PCIe2 -> port1 (*)
+ break;
+ }
+#elif defined(CONFIG_RALINK_MT7628)
+ if ((RALINK_PCI0_STATUS & 0x1) == 0) {
+ RALINK_RSTCTRL |= RALINK_PCIE0_RST;
+ RALINK_CLKCFG1 &= ~RALINK_PCIE0_CLK_EN;
+ printk("%s: no card, disable it (RST&CLK)\n", "PCIe0");
+ return 0;
+ }
+#endif
+
+ RALINK_PCI_MEMBASE = 0xffffffff; // valid for PCI host mode only
+ RALINK_PCI_IOBASE = RALINK_PCI_IO_MAP_BASE; // valid for PCI host mode only
+
+#if defined(CONFIG_RALINK_MT7621)
+#if defined(CONFIG_PCIE_PORT0)
+ // PCIe0
+ if ((pcie_link_status & 0x1) != 0) {
+ RALINK_PCI0_BAR0SETUP_ADDR = 0x7fff0001; // open BAR0 (2GB)
+ RALINK_PCI0_BAR1SETUP_ADDR = 0x00000000; // disable BAR1 (used in EP mode)
+ RALINK_PCI0_IMBASEBAR0_ADDR = BAR0_MEMORY_BASE; // make BAR0
+ RALINK_PCI0_CLASS = 0x06040001;
+ RALINK_PCI_PCIMSK_ADDR |= (1<<20); // enable PCIe0 interrupt
+ }
+#endif
+#if defined(CONFIG_PCIE_PORT1)
+ // PCIe1
+ if ((pcie_link_status & 0x2) != 0) {
+ RALINK_PCI1_BAR0SETUP_ADDR = 0x7fff0001; // open BAR0 (2GB)
+ RALINK_PCI1_BAR1SETUP_ADDR = 0x00000000; // disable BAR1 (used in EP mode)
+ RALINK_PCI1_IMBASEBAR0_ADDR = BAR0_MEMORY_BASE; // make BAR0
+ RALINK_PCI1_CLASS = 0x06040001;
+ RALINK_PCI_PCIMSK_ADDR |= (1<<21); // enable PCIe1 interrupt
+ }
+#endif
+#if defined(CONFIG_PCIE_PORT2)
+ // PCIe2
+ if ((pcie_link_status & 0x4) != 0) {
+ RALINK_PCI2_BAR0SETUP_ADDR = 0x7fff0001; // open BAR0 (2GB)
+ RALINK_PCI2_BAR1SETUP_ADDR = 0x00000000; // disable BAR1 (used in EP mode)
+ RALINK_PCI2_IMBASEBAR0_ADDR = BAR0_MEMORY_BASE; // make BAR0
+ RALINK_PCI2_CLASS = 0x06040001;
+ RALINK_PCI_PCIMSK_ADDR |= (1<<22); // enable PCIe2 interrupt
+ }
+#endif
+#elif defined(CONFIG_RALINK_MT7628)
+ //PCIe0
+ RALINK_PCI0_BAR0SETUP_ADDR = 0x7fff0001; // open BAR0 (2GB)
+ RALINK_PCI0_BAR1SETUP_ADDR = 0x00000000; // disable BAR1 (used in EP mode)
+ RALINK_PCI0_IMBASEBAR0_ADDR = BAR0_MEMORY_BASE; // make BAR0
+ RALINK_PCI0_CLASS = 0x06040001;
+ RALINK_PCI_PCIMSK_ADDR = (1<<20); // enable PCIe0 interrupt
+#endif
+
+ ralink_pci_controller.io_map_base = mips_io_port_base;
+
+ register_pci_controller(&ralink_pci_controller);
+
+ return 0;
+}
+
+#if defined(CONFIG_RALINK_MT7621) || defined(CONFIG_RALINK_MT7628)
+arch_initcall(init_ralink_pci);
+#else
+#error Please disable CONFIG_PCI for unsupported SoC!
+#endif
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/rt2880/printf.c b/arch/mips/rt2880/printf.c
new file mode 100644
index 000000000000..26acd164d1b5
--- /dev/null
+++ b/arch/mips/rt2880/printf.c
@@ -0,0 +1,118 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * prom_printf for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#include <asm/rt2880/rt_mmap.h>
+#include <asm/rt2880/rt_serial.h>
+
+static DEFINE_SPINLOCK(con_lock);
+static char buf[256];
+static unsigned int uart_base;
+
+static inline unsigned int serial_in(int offset)
+{
+ return inl(uart_base + offset);
+}
+
+static inline void serial_out(int offset, int value)
+{
+ outl(value, uart_base + offset);
+}
+
+#ifdef CONFIG_EARLY_PRINTK
+void prom_putchar(unsigned char c)
+{
+ while ((serial_in(RT2880_UART_LSR) & RT2880_UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(RT2880_UART_TX, c);
+}
+#endif
+
+int putPromChar(char c)
+{
+ while ((serial_in(RT2880_UART_LSR) & RT2880_UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(RT2880_UART_TX, c);
+
+ return 1;
+}
+
+char getPromChar(void)
+{
+ while (!(serial_in(RT2880_UART_LSR) & 1))
+ ;
+
+ return serial_in(RT2880_UART_RX);
+}
+
+void __init prom_init_printf(int tty_no)
+{
+#if !defined(CONFIG_RALINK_GPIOMODE_UARTF) && (CONFIG_SERIAL_8250_NR_UARTS > 1)
+ if (tty_no == 1)
+ uart_base = RALINK_UART_BASE;
+ else
+#endif
+ uart_base = RALINK_UART_LITE_BASE;
+}
+
+void __init prom_printf(char *fmt, ...)
+{
+ va_list args;
+ int l;
+ char *p, *buf_end;
+ unsigned long flags;
+
+ spin_lock_irqsave(&con_lock, flags);
+ va_start(args, fmt);
+ l = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ buf_end = buf + l;
+ for (p = buf; p < buf_end; p++) {
+ /* Crude cr/nl handling is better than none */
+ if (*p == '\n')
+ putPromChar('\r');
+ putPromChar(*p);
+ }
+ spin_unlock_irqrestore(&con_lock, flags);
+}
diff --git a/arch/mips/rt2880/reset.c b/arch/mips/rt2880/reset.c
new file mode 100644
index 000000000000..65a8511d6976
--- /dev/null
+++ b/arch/mips/rt2880/reset.c
@@ -0,0 +1,124 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * reboot/reset setting for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+
+#include <asm/time.h>
+#include <asm/reboot.h>
+#include <asm/pbus-timer.h>
+
+#include <asm/rt2880/generic.h>
+
+extern void mtk_disable_irq_all(void);
+
+static void hw_uninit(bool do_reboot)
+{
+ mtk_disable_irq_all();
+
+ /* stop all APB module timers except an active watchdog */
+ pbus_timer_disable(PBUS_TIMER_0);
+ pbus_timer_disable(PBUS_TIMER_2);
+
+ /* timer 3 is in a non-watchdog mode */
+ if (!(pbus_timer_r32(RSTSTAT) & RSTSTAT_WDT_EN))
+ pbus_timer_disable(PBUS_TIMER_1);
+
+#if defined(CONFIG_RALINK_MT7628)
+ /* reset PCIe */
+ *(volatile u32 *)(SOFTRES_REG) = RALINK_PCIE0_RST;
+
+ if (do_reboot)
+ mdelay(10);
+#endif
+
+ if (do_reboot) {
+ /* system software reset */
+ *(volatile u32 *)(SOFTRES_REG) = GORESET;
+ *(volatile u32 *)(SOFTRES_REG) = 0;
+ }
+}
+
+static void mips_machine_restart(char *command)
+{
+ printk(KERN_WARNING "Machine restart ... \n");
+
+ hw_uninit(true);
+}
+
+static void mips_machine_halt(void)
+{
+ printk(KERN_WARNING "Machine halted ... \n");
+
+ hw_uninit(false);
+}
+
+static void mips_machine_power_off(void)
+{
+ printk(KERN_WARNING "Machine poweroff ... \n");
+
+ *(volatile u32*)(POWER_DIR_REG) = POWER_DIR_OUTPUT;
+ *(volatile u32*)(POWER_POL_REG) = 0;
+ *(volatile u32*)(POWEROFF_REG) = POWEROFF;
+}
+
+static int mtk_panic_event(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ if (action == PANIC_ACTION_RESTART)
+ mips_machine_restart(NULL);
+ else
+ mips_machine_halt();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block mtk_panic_block = {
+ .notifier_call = mtk_panic_event,
+};
+
+void mips_reboot_setup(void)
+{
+ _machine_restart = mips_machine_restart;
+ _machine_halt = mips_machine_halt;
+ pm_power_off = mips_machine_power_off;
+
+ atomic_notifier_chain_register(&panic_notifier_list, &mtk_panic_block);
+}
diff --git a/arch/mips/rt2880/setup.c b/arch/mips/rt2880/setup.c
new file mode 100644
index 000000000000..3d71e8b995eb
--- /dev/null
+++ b/arch/mips/rt2880/setup.c
@@ -0,0 +1,115 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * board setup for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
+#include <asm/bootinfo.h>
+#ifdef CONFIG_DMA_MAYBE_COHERENT
+#include <asm/mips-cm.h>
+#include <asm/dma-coherence.h>
+#endif
+
+#include <asm/rt2880/prom.h>
+
+extern void mips_reboot_setup(void);
+
+const char *get_system_type(void)
+{
+#if defined(CONFIG_RALINK_MT7621)
+ return "MediaTek MT7621 SoC";
+#elif defined(CONFIG_RALINK_MT7628)
+ return "MediaTek MT7628 SoC";
+#else
+ return "MediaTek SoC";
+#endif
+}
+
+#ifdef CONFIG_DMA_MAYBE_COHERENT
+static inline int plat_enable_iocoherency(void)
+{
+ int supported = 0;
+
+ if (mips_cm_numiocu()) {
+ pr_info("GCMP IOCU detected\n");
+#if defined(CONFIG_RALINK_MT7621)
+ /* MT7621 GCMP reported about IOCU=1, but IOCU switch disabled by default */
+// supported = 1;
+#endif
+ }
+
+ return supported;
+}
+
+static void __init plat_setup_iocoherency(void)
+{
+ /*
+ * Kernel has been configured with software coherency
+ * but we might choose to turn it off and use hardware
+ * coherency instead.
+ */
+ if (plat_enable_iocoherency()) {
+ coherentio = 1;
+ hw_coherentio = 1;
+ pr_info("Hardware DMA cache coherency enabled\n");
+ }
+}
+#endif
+
+void __init plat_mem_setup(void)
+{
+ char *argptr;
+
+ iomem_resource.start = 0;
+ iomem_resource.end = ~0;
+ ioport_resource.start = 0;
+ ioport_resource.end = 0x1fffffff;
+
+ argptr = prom_getcmdline();
+
+ if ((argptr = strstr(argptr, "nofpu")) != NULL)
+ cpu_data[0].options &= ~MIPS_CPU_FPU;
+
+#ifdef CONFIG_DMA_MAYBE_COHERENT
+ plat_setup_iocoherency();
+#endif
+ mips_reboot_setup();
+}
+
diff --git a/arch/mips/rt2880/time.c b/arch/mips/rt2880/time.c
new file mode 100644
index 000000000000..b72d721e1faa
--- /dev/null
+++ b/arch/mips/rt2880/time.c
@@ -0,0 +1,93 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * timer setup for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ *
+ * Initial Release
+ *
+ *
+ *
+ **************************************************************************
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/timex.h>
+
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+
+#include <asm/mipsregs.h>
+#include <asm/hardirq.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+#include <linux/irqchip/mips-gic.h>
+#endif
+
+#include <asm/rt2880/generic.h>
+#include <asm/rt2880/prom.h>
+#include <asm/rt2880/rt_mmap.h>
+
+extern unsigned int mips_hpt_frequency;
+extern u32 mips_cpu_feq;
+extern u32 surfboard_sysclk;
+
+#if defined(CONFIG_RALINK_MT7621)
+static int udelay_recal(void)
+{
+ unsigned int i;
+
+ for (i = 1; i < num_present_cpus(); i++)
+ cpu_data[i].udelay_val = cpu_data[0].udelay_val;
+
+ return 0;
+}
+postcore_initcall(udelay_recal);
+#endif
+
+void __init plat_time_init(void)
+{
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+ gic_clocksource_init(mips_cpu_feq);
+#else
+ mips_hpt_frequency = mips_cpu_feq / 2;
+#endif
+}
+
+u32 get_surfboard_sysclk(void)
+{
+ return surfboard_sysclk;
+}
+
+EXPORT_SYMBOL(get_surfboard_sysclk);
+
diff --git a/arch/mips/rt2880/uphy.c b/arch/mips/rt2880/uphy.c
new file mode 100644
index 000000000000..c987d7be0e60
--- /dev/null
+++ b/arch/mips/rt2880/uphy.c
@@ -0,0 +1,214 @@
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/rt2880/rt_mmap.h>
+
+#if defined(CONFIG_RALINK_MT7621)
+
+#define ADDR_SIFSLV_BASE RALINK_XHCI_UPHY_BASE
+#define ADDR_SIFSLV_FMREG_BASE (ADDR_SIFSLV_BASE+0x0100)
+#define ADDR_U2_PHY_P0_BASE (ADDR_SIFSLV_BASE+0x0800)
+#define ADDR_U2_PHY_P1_BASE (ADDR_SIFSLV_BASE+0x1000)
+#define U2_SR_COEFF 28
+
+#elif defined(CONFIG_RALINK_MT7628)
+
+#define ADDR_SIFSLV_FMREG_BASE (RALINK_USB_DEV_BASE+0xf00)
+#define ADDR_U2_PHY_P0_BASE (RALINK_USB_DEV_BASE+0x800)
+#define U2_SR_COEFF 32
+
+#endif
+
+#define REG_SIFSLV_FMREG_FMCR0 (ADDR_SIFSLV_FMREG_BASE+0x00)
+#define REG_SIFSLV_FMREG_FMCR1 (ADDR_SIFSLV_FMREG_BASE+0x04)
+#define REG_SIFSLV_FMREG_FMCR2 (ADDR_SIFSLV_FMREG_BASE+0x08)
+#define REG_SIFSLV_FMREG_FMMONR0 (ADDR_SIFSLV_FMREG_BASE+0x0C)
+#define REG_SIFSLV_FMREG_FMMONR1 (ADDR_SIFSLV_FMREG_BASE+0x10)
+
+/* SIFSLV_FMREG_FMCR0 */
+#define RG_LOCKTH (0xf<<28)
+#define RG_MONCLK_SEL (0x3<<26)
+#define RG_FM_MODE (0x1<<25)
+#define RG_FREQDET_EN (0x1<<24)
+#define RG_CYCLECNT (0x00ffffff)
+
+/* SIFSLV_FMREG_FMMONR1 */
+#define RG_MONCLK_SEL_3 (0x1<<9)
+#define RG_FRCK_EN (0x1<<8)
+#define USBPLL_LOCK (0x1<<1)
+#define USB_FM_VLD (0x1<<0)
+
+#define OFS_U2_PHY_AC0 0x00
+#define OFS_U2_PHY_AC1 0x04
+#define OFS_U2_PHY_AC2 0x08
+#define OFS_U2_PHY_ACR0 0x10
+#define OFS_U2_PHY_ACR1 0x14
+#define OFS_U2_PHY_ACR2 0x18
+#define OFS_U2_PHY_ACR3 0x1C
+#define OFS_U2_PHY_ACR4 0x20
+#define OFS_U2_PHY_AMON0 0x24
+#define OFS_U2_PHY_DCR0 0x60
+#define OFS_U2_PHY_DCR1 0x64
+#define OFS_U2_PHY_DTM0 0x68
+#define OFS_U2_PHY_DTM1 0x6C
+
+/* U2_PHY_ACR0 */
+#define RG_USB20_ICUSB_EN (0x1<<24)
+#define RG_USB20_HSTX_SRCAL_EN (0x1<<23)
+#define RG_USB20_HSTX_SRCTRL (0x7<<16)
+#define RG_USB20_LS_CR (0x7<<12)
+#define RG_USB20_FS_CR (0x7<<8)
+#define RG_USB20_LS_SR (0x7<<4)
+#define RG_USB20_FS_SR (0x7<<0)
+
+static atomic_t uphy_init_instance = ATOMIC_INIT(0);
+
+static void
+u2_slew_rate_calibration(int port_id, u32 u2_phy_reg_base)
+{
+ int i;
+ u32 reg_val;
+ u32 u4FmOut = 0;
+
+ // => RG_USB20_HSTX_SRCAL_EN = 1
+ // enable HS TX SR calibration
+ reg_val = sysRegRead(u2_phy_reg_base + OFS_U2_PHY_ACR0);
+ reg_val |= RG_USB20_HSTX_SRCAL_EN;
+ sysRegWrite(u2_phy_reg_base + OFS_U2_PHY_ACR0, reg_val);
+ msleep(1);
+
+ // => RG_FRCK_EN = 1
+ // Enable free run clock
+ reg_val = sysRegRead(REG_SIFSLV_FMREG_FMMONR1);
+ reg_val |= RG_FRCK_EN;
+ sysRegWrite(REG_SIFSLV_FMREG_FMMONR1, reg_val);
+
+ // MT6290 HS signal quality patch
+ // => RG_CYCLECNT = 400
+ // Setting cyclecnt = 400
+ reg_val = sysRegRead(REG_SIFSLV_FMREG_FMCR0);
+ reg_val &= ~RG_CYCLECNT;
+ reg_val |= 0x400;
+ sysRegWrite(REG_SIFSLV_FMREG_FMCR0, reg_val);
+
+ // => RG_FREQDET_EN = 1
+ // Enable frequency meter
+ reg_val = sysRegRead(REG_SIFSLV_FMREG_FMCR0);
+ reg_val |= RG_FREQDET_EN;
+ sysRegWrite(REG_SIFSLV_FMREG_FMCR0, reg_val);
+
+ // wait for FM detection done, set 10ms timeout
+ for (i = 0; i < 10; i++) {
+ // => u4FmOut = USB_FM_OUT
+ // read FM_OUT
+ u4FmOut = sysRegRead(REG_SIFSLV_FMREG_FMMONR0);
+
+ // check if FM detection done
+ if (u4FmOut != 0)
+ break;
+
+ msleep(1);
+ }
+
+ // => RG_FREQDET_EN = 0
+ // disable frequency meter
+ reg_val = sysRegRead(REG_SIFSLV_FMREG_FMCR0);
+ reg_val &= ~RG_FREQDET_EN;
+ sysRegWrite(REG_SIFSLV_FMREG_FMCR0, reg_val);
+
+ // => RG_FRCK_EN = 0
+ // disable free run clock
+ reg_val = sysRegRead(REG_SIFSLV_FMREG_FMMONR1);
+ reg_val &= ~RG_FRCK_EN;
+ sysRegWrite(REG_SIFSLV_FMREG_FMMONR1, reg_val);
+
+ // => RG_USB20_HSTX_SRCAL_EN = 0
+ // disable HS TX SR calibration
+ reg_val = sysRegRead(u2_phy_reg_base + OFS_U2_PHY_ACR0);
+ reg_val &= ~RG_USB20_HSTX_SRCAL_EN;
+ sysRegWrite(u2_phy_reg_base + OFS_U2_PHY_ACR0, reg_val);
+ msleep(1);
+
+ // => RG_USB20_HSTX_SRCTRL
+ reg_val = sysRegRead(u2_phy_reg_base + OFS_U2_PHY_ACR0);
+ reg_val &= ~RG_USB20_HSTX_SRCTRL;
+ if (u4FmOut != 0) {
+ // set reg = (1024/FM_OUT) * 25 * 0.028 (round to the nearest digits)
+ u32 u4Tmp = (((1024 * 25 * U2_SR_COEFF) / u4FmOut) + 500) / 1000;
+ reg_val |= ((u4Tmp & 0x07)<<16);
+ printk(KERN_INFO "U2PHY P%d set SRCTRL %s value: %d\n", port_id, "calibration", u4Tmp);
+ } else {
+ reg_val |= (0x4<<16);
+ printk(KERN_INFO "U2PHY P%d set SRCTRL %s value: %d\n", port_id, "default", 4);
+ }
+ sysRegWrite(u2_phy_reg_base + OFS_U2_PHY_ACR0, reg_val);
+}
+
+#if defined(CONFIG_RALINK_MT7621)
+
+static void
+u2_phy_init(u32 u2_phy_reg_base)
+{
+ u32 reg_val;
+
+ /* set SW PLL Stable mode to 1 for U2 LPM device remote wakeup */
+ reg_val = sysRegRead(u2_phy_reg_base + OFS_U2_PHY_DCR1);
+ reg_val &= ~(0x3 << 18);
+ reg_val |= (0x1 << 18);
+ sysRegWrite(u2_phy_reg_base + OFS_U2_PHY_DCR1, reg_val);
+}
+
+void
+uphy_init(void)
+{
+ if (atomic_inc_return(&uphy_init_instance) != 1)
+ return;
+
+ u2_phy_init(ADDR_U2_PHY_P0_BASE);
+ u2_phy_init(ADDR_U2_PHY_P1_BASE);
+
+ u2_slew_rate_calibration(0, ADDR_U2_PHY_P0_BASE);
+ u2_slew_rate_calibration(1, ADDR_U2_PHY_P1_BASE);
+}
+
+#elif defined(CONFIG_RALINK_MT7628)
+
+static inline void
+u2_phy_init(void)
+{
+ u32 reg_val;
+
+ reg_val = sysRegRead(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_AC2);
+ reg_val = sysRegRead(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_ACR0);
+ reg_val = sysRegRead(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0);
+
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0, 0x00ffff02);
+ reg_val = sysRegRead(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0);
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0, 0x00555502);
+ reg_val = sysRegRead(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0);
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0, 0x00aaaa02);
+ reg_val = sysRegRead(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0);
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0, 0x00000402);
+ reg_val = sysRegRead(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DCR0);
+
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_AC0, 0x0048086a);
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_AC1, 0x4400001c);
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_ACR3, 0xc0200000);
+ sysRegWrite(ADDR_U2_PHY_P0_BASE + OFS_U2_PHY_DTM0, 0x02000000);
+}
+
+void
+uphy_init(void)
+{
+ if (atomic_inc_return(&uphy_init_instance) != 1)
+ return;
+
+ u2_phy_init();
+ u2_slew_rate_calibration(0, ADDR_U2_PHY_P0_BASE);
+}
+
+#endif
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
index f9ae6a8fa7c7..bb8a96b3d3bf 100644
--- a/arch/mips/sgi-ip27/ip27-smp.c
+++ b/arch/mips/sgi-ip27/ip27-smp.c
@@ -191,7 +191,7 @@ static void ip27_smp_finish(void)
* set sp to the kernel stack of the newly created idle process, gp to the proc
* struct so that current_thread_info() will work.
*/
-static void ip27_boot_secondary(int cpu, struct task_struct *idle)
+static int ip27_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned long gp = (unsigned long)task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle);
@@ -199,6 +199,7 @@ static void ip27_boot_secondary(int cpu, struct task_struct *idle)
LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
0, (void *) sp, (void *) gp);
+ return 0;
}
static void __init ip27_smp_setup(void)
@@ -227,7 +228,7 @@ static void __init ip27_prepare_cpus(unsigned int max_cpus)
/* We already did everything necessary earlier */
}
-struct plat_smp_ops ip27_smp_ops = {
+const struct plat_smp_ops ip27_smp_ops = {
.send_ipi_single = ip27_send_ipi_single,
.send_ipi_mask = ip27_send_ipi_mask,
.init_secondary = ip27_init_secondary,
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index 4c71aea25663..03a4cdde5ad2 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -116,7 +116,7 @@ static void bcm1480_smp_finish(void)
* Setup the PC, SP, and GP of a secondary processor and start it
* running!
*/
-static void bcm1480_boot_secondary(int cpu, struct task_struct *idle)
+static int bcm1480_boot_secondary(int cpu, struct task_struct *idle)
{
int retval;
@@ -125,6 +125,7 @@ static void bcm1480_boot_secondary(int cpu, struct task_struct *idle)
(unsigned long)task_thread_info(idle), 0);
if (retval != 0)
printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
+ return retval;
}
/*
@@ -156,7 +157,7 @@ static void __init bcm1480_prepare_cpus(unsigned int max_cpus)
{
}
-struct plat_smp_ops bcm1480_smp_ops = {
+const struct plat_smp_ops bcm1480_smp_ops = {
.send_ipi_single = bcm1480_send_ipi_single,
.send_ipi_mask = bcm1480_send_ipi_mask,
.init_secondary = bcm1480_init_secondary,
diff --git a/arch/mips/sibyte/common/cfe.c b/arch/mips/sibyte/common/cfe.c
index c1a11a11db7f..115399202eab 100644
--- a/arch/mips/sibyte/common/cfe.c
+++ b/arch/mips/sibyte/common/cfe.c
@@ -229,8 +229,8 @@ static int __init initrd_setup(char *str)
#endif
-extern struct plat_smp_ops sb_smp_ops;
-extern struct plat_smp_ops bcm1480_smp_ops;
+extern const struct plat_smp_ops sb_smp_ops;
+extern const struct plat_smp_ops bcm1480_smp_ops;
/*
* prom_init is called just after the cpu type is determined, from setup_arch()
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index 1cf66f5ff23d..1308d564a6d3 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -106,7 +106,7 @@ static void sb1250_smp_finish(void)
* Setup the PC, SP, and GP of a secondary processor and start it
* running!
*/
-static void sb1250_boot_secondary(int cpu, struct task_struct *idle)
+static int sb1250_boot_secondary(int cpu, struct task_struct *idle)
{
int retval;
@@ -115,6 +115,7 @@ static void sb1250_boot_secondary(int cpu, struct task_struct *idle)
(unsigned long)task_thread_info(idle), 0);
if (retval != 0)
printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
+ return retval;
}
/*
@@ -146,7 +147,7 @@ static void __init sb1250_prepare_cpus(unsigned int max_cpus)
{
}
-struct plat_smp_ops sb_smp_ops = {
+const struct plat_smp_ops sb_smp_ops = {
.send_ipi_single = sb1250_send_ipi_single,
.send_ipi_mask = sb1250_send_ipi_mask,
.init_secondary = sb1250_init_secondary,
diff --git a/arch/mips/tc3262/Kconfig b/arch/mips/tc3262/Kconfig
new file mode 100644
index 000000000000..873635341569
--- /dev/null
+++ b/arch/mips/tc3262/Kconfig
@@ -0,0 +1,49 @@
+if MIPS_TC3262
+
+config PCIE_PORT1
+ bool "Second PCIe port support"
+ default n
+
+#--------------------------
+
+if (ECONET_EN7512 || ECONET_EN7516)
+
+config TC3162_ADSL
+ bool "Enable ADSL support"
+ default n
+
+config RALINK_VDSL
+ bool "Enable VDSL support"
+ default n
+
+endif
+
+#--------------------------
+
+if !MIPS_TC3262_1004K
+
+config TC3262_IMEM
+ bool "Enable SPRAM IMEM"
+ default y
+
+endif
+
+config TC3262_CPU_TIMER
+ bool "Use CPU External Timer (per-VPE)"
+ default y
+
+choice
+ prompt "HWFQ flat buffer allocation mode"
+ default TC3262_HWFQ_ALLOC
+
+ config TC3262_HWFQ_ALLOC
+ bool "Use dma_alloc_coherent (fragmentation issue)"
+ config TC3262_HWFQ_MAP_4M
+ bool "Map 4MB beyond RAM size"
+ config TC3262_HWFQ_MAP_8M
+ bool "Map 8MB beyond RAM size"
+ config TC3262_HWFQ_MAP_16M
+ bool "Map 16MB beyond RAM size"
+endchoice
+
+endif # MIPS_TC3262
diff --git a/arch/mips/tc3262/Makefile b/arch/mips/tc3262/Makefile
new file mode 100644
index 000000000000..baaf984417b1
--- /dev/null
+++ b/arch/mips/tc3262/Makefile
@@ -0,0 +1,26 @@
+
+obj-y := prom.o cmdline.o printf.o setup.o time.o
+
+ifdef CONFIG_IRQ_GIC
+obj-y += irq-gic.o
+else
+obj-y += irq.o
+endif
+
+obj-$(CONFIG_TC3262_CPU_TIMER) += hpt.o
+obj-$(CONFIG_PCI) += pci_en75xx.o
+obj-$(CONFIG_MIPS_CMP) += malta-amon.o
+
+ifdef CONFIG_MIPS_MT_SMP
+obj-$(CONFIG_MIPS_TC3262_34K) += malta-smp.o
+endif
+
+ifdef CONFIG_USB_XHCI_MTK
+obj-y += dev-xhci.o uphy.o
+endif
+
+ifneq ($(strip \
+ $(CONFIG_MT7615_WHNAT_SUPPORT) \
+ $(CONFIG_MT7915_WHNAT_SUPPORT)),)
+obj-y += dev-woe.o
+endif
diff --git a/arch/mips/tc3262/Platform b/arch/mips/tc3262/Platform
new file mode 100644
index 000000000000..1a03feabe82a
--- /dev/null
+++ b/arch/mips/tc3262/Platform
@@ -0,0 +1,9 @@
+#
+# Econet EN75xx boards
+#
+platform-$(CONFIG_MIPS_TC3262) += tc3262/
+cflags-$(CONFIG_MIPS_TC3262) += -I$(srctree)/arch/mips/include/asm/tc3162/
+cflags-$(CONFIG_MIPS_TC3262_34K) += -mtune=34kc
+cflags-$(CONFIG_MIPS_TC3262_1004K) += -mtune=1004kc
+load-$(CONFIG_MIPS_TC3262) += 0xffffffff80020000
+all-$(CONFIG_MIPS_TC3262) := $(COMPRESSION_FNAME).bin
diff --git a/arch/mips/tc3262/cmdline.c b/arch/mips/tc3262/cmdline.c
new file mode 100644
index 000000000000..82851a9565c7
--- /dev/null
+++ b/arch/mips/tc3262/cmdline.c
@@ -0,0 +1,64 @@
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#if defined(CONFIG_RT2880_UART_115200)
+#define TTY_UART_CONSOLE "console=ttyS0,115200n8"
+#else
+#define TTY_UART_CONSOLE "console=ttyS0,57600n8"
+#endif
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+extern int prom_argc;
+extern int *_prom_argv;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
+#endif
+
+extern char arcs_cmdline[COMMAND_LINE_SIZE];
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+void __init uboot_cmdline(char *s, size_t size)
+{
+ int i;
+
+ for (i = 1; i < prom_argc; i++) { /* Skip argv[0] */
+ strlcat(s, prom_argv(i), size);
+
+ /* Prevent last space */
+ if (i != prom_argc - 1)
+ strlcat(s, " ", size);
+ }
+}
+#else
+static inline void uboot_cmdline(char *s, size_t size) {}
+#endif
+
+static inline void fixup_cmdline(char *s, size_t size)
+{
+ const char *p = TTY_UART_CONSOLE;
+
+ if (strstr(s, "console="))
+ return;
+
+ /* Add space if there are symbols in buffer */
+ if (*s)
+ strlcat(s, " ", size);
+ strlcat(s, p, size);
+}
+
+void __init prom_init_cmdline(void)
+{
+ uboot_cmdline(arcs_cmdline, sizeof(arcs_cmdline));
+ fixup_cmdline(arcs_cmdline, sizeof(arcs_cmdline));
+}
diff --git a/arch/mips/tc3262/dev-woe.c b/arch/mips/tc3262/dev-woe.c
new file mode 100644
index 000000000000..1264c4648a6c
--- /dev/null
+++ b/arch/mips/tc3262/dev-woe.c
@@ -0,0 +1,72 @@
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/tc3162/rt_mmap.h>
+
+#include <soc/ralink/dev_woe.h>
+
+static struct resource en75xx_woe_resources[] = {
+ [0] = {
+ .start = RALINK_WOE0_BASE,
+ .end = RALINK_WOE0_BASE + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = RALINK_WOE1_BASE,
+ .end = RALINK_WOE1_BASE + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = WOE0_INTR,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = WOE1_INTR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct whnat_mtk_pdata en75xx_woe_pdata = {
+ .wdma_base = {
+ RALINK_WDMA0_BASE,
+ RALINK_WDMA1_BASE
+ },
+ .wdma_irq = {
+ { WDMA0_P0_INTR, WDMA0_P1_INTR, WDMA0_WOE_INTR },
+ { WDMA1_P0_INTR, WDMA1_P1_INTR, WDMA1_WOE_INTR }
+ },
+};
+
+static u64 en75xx_woe_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device en75xx_woe_device = {
+ .name = WHNAT_MTK_DRV_NAME,
+ .id = -1,
+ .dev = {
+ .platform_data = &en75xx_woe_pdata,
+ .dma_mask = &en75xx_woe_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(en75xx_woe_resources),
+ .resource = en75xx_woe_resources,
+};
+
+int __init init_en75xx_woe(void)
+{
+ int retval = 0;
+
+ retval = platform_device_register(&en75xx_woe_device);
+ if (retval != 0) {
+ printk(KERN_ERR "register %s device fail!\n", "WoE");
+ return retval;
+ }
+
+ return retval;
+}
+
+device_initcall(init_en75xx_woe);
diff --git a/arch/mips/tc3262/dev-xhci.c b/arch/mips/tc3262/dev-xhci.c
new file mode 100644
index 000000000000..ffde30f048bc
--- /dev/null
+++ b/arch/mips/tc3262/dev-xhci.c
@@ -0,0 +1,66 @@
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/tc3162/rt_mmap.h>
+
+#include <soc/ralink/dev_xhci.h>
+
+static struct resource en75xx_xhci_resources[] = {
+ [0] = {
+ .start = RALINK_USB_HOST_BASE,
+ .end = RALINK_USB_HOST_BASE + RALINK_USB_HOST_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "mac",
+ },
+ [1] = {
+ .start = RALINK_USB_IPPC_BASE,
+ .end = RALINK_USB_IPPC_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ .name = "ippc",
+ },
+ [2] = {
+ .start = SURFBOARDINT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 en75xx_xhci_dmamask = DMA_BIT_MASK(32);
+
+extern void uphy_init(void);
+
+static struct xhci_mtk_pdata en75xx_xhci_pdata = {
+ .uphy_init = uphy_init,
+ .usb3_lpm_capable = true,
+};
+
+static struct platform_device en75xx_xhci_device = {
+ .name = XHCI_MTK_DRV_NAME,
+ .id = -1,
+ .dev = {
+ .platform_data = &en75xx_xhci_pdata,
+ .dma_mask = &en75xx_xhci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(en75xx_xhci_resources),
+ .resource = en75xx_xhci_resources,
+};
+
+int __init init_en75xx_xhci(void)
+{
+ int retval = 0;
+
+ retval = platform_device_register(&en75xx_xhci_device);
+ if (retval != 0) {
+ printk(KERN_ERR "register %s device fail!\n", "xHCI");
+ return retval;
+ }
+
+ return retval;
+}
+
+device_initcall(init_en75xx_xhci);
diff --git a/arch/mips/tc3262/hpt.c b/arch/mips/tc3262/hpt.c
new file mode 100644
index 000000000000..8e83c0b1421d
--- /dev/null
+++ b/arch/mips/tc3262/hpt.c
@@ -0,0 +1,238 @@
+#define pr_fmt(fmt) "hpt: " fmt
+
+#include <linux/io.h>
+#include <linux/cache.h>
+#include <linux/kernel.h>
+#include <linux/atomic.h>
+#include <linux/cpumask.h>
+#include <linux/irqflags.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/sched_clock.h>
+#include <asm/tc3162/tc3162.h>
+
+#define HPT_BITS 32
+
+#define HPT_MIN_DELTA 0x00000300
+#define HPT_MAX_DELTA GENMASK(HPT_BITS - 1, 0)
+
+#define HPT_IRQ SI_TIMER_INT
+
+static inline void hpt_w32(const u32 reg, const u32 val)
+{
+ __raw_writel(val, (void __iomem *)(unsigned long)reg);
+}
+
+static inline u32 hpt_r32(const u32 reg)
+{
+ return __raw_readl((void __iomem *)(unsigned long)reg);
+}
+
+struct hpt_regs {
+ u32 lvr; /* compare value */
+ u32 cvr; /* count */
+ u32 ctl; /* control */
+ u32 ctl_enabled; /* enabled mask */
+ u32 ctl_pending; /* pending mask */
+};
+
+struct hpt {
+ struct clock_event_device cd;
+ struct hpt_regs regs;
+} ____cacheline_aligned_in_smp;
+
+static inline u32 hpt_read_count(const struct hpt *hpt)
+{
+ return hpt_r32(hpt->regs.cvr);
+}
+
+static inline void hpt_write_compare(const struct hpt *hpt,
+ const u32 lvr)
+{
+ hpt_w32(hpt->regs.lvr, lvr);
+}
+
+static inline bool hpt_is_pending(const struct hpt *hpt)
+{
+ const struct hpt_regs *regs = &hpt->regs;
+
+ return hpt_r32(regs->ctl) & regs->ctl_pending;
+}
+
+static void hpt_init(const struct hpt *hpt)
+{
+ const struct hpt_regs *regs = &hpt->regs;
+
+ hpt_w32(regs->cvr, 0);
+ hpt_w32(regs->lvr, HPT_MAX_DELTA);
+}
+
+static void hpt_enable(const struct hpt *hpt)
+{
+ const struct hpt_regs *regs = &hpt->regs;
+ u32 ctl = hpt_r32(regs->ctl);
+
+ ctl |= regs->ctl_enabled;
+ hpt_w32(regs->ctl, ctl);
+}
+
+static DEFINE_PER_CPU(struct hpt, hpt_pcpu);
+
+static irqreturn_t hpt_compare_interrupt(int irq, void *dev_id)
+{
+ struct hpt *hpt = dev_id;
+
+ if (!hpt_is_pending(hpt))
+ return IRQ_NONE;
+
+ hpt_write_compare(hpt, hpt_read_count(hpt));
+ hpt->cd.event_handler(&hpt->cd);
+
+ return IRQ_HANDLED;
+}
+
+static int hpt_set_next_event(unsigned long delta,
+ struct clock_event_device *cd)
+{
+ /* called by the kernel with disabled local hardware interrupts */
+ const struct hpt *hpt = container_of(cd, struct hpt, cd);
+ const u32 next = hpt_read_count(hpt) + delta;
+ u32 cnt;
+
+ hpt_write_compare(hpt, next);
+ cnt = hpt_read_count(hpt);
+
+ if (next >= cnt)
+ return 0; /* next - cnt <= delta */
+
+ if (HPT_MAX_DELTA - cnt + next > delta)
+ return -ETIME;
+
+ return 0;
+}
+
+static void hpt_event_handler(struct clock_event_device *cd)
+{
+}
+
+int r4k_clockevent_init(void)
+{
+ static struct irqaction hpt_compare_irqaction = {
+ .handler = hpt_compare_interrupt,
+ .percpu_dev_id = &hpt_pcpu,
+ .flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED,
+ .name = "timer"
+ };
+ static atomic_t irq_installed = ATOMIC_INIT(0);
+ const unsigned int irq = HPT_IRQ;
+ const unsigned int cpu = smp_processor_id();
+ struct hpt *hpt = &per_cpu(hpt_pcpu, cpu);
+ struct clock_event_device *cd = &hpt->cd;
+
+ cd->name = "hpt";
+ cd->features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_C3STOP |
+ CLOCK_EVT_FEAT_PERCPU;
+ cd->rating = 300;
+ cd->irq = irq;
+ cd->cpumask = cpumask_of(cpu);
+ cd->set_next_event = hpt_set_next_event;
+ cd->event_handler = hpt_event_handler;
+
+ clockevents_config_and_register(cd, CPUTMR_CLK,
+ HPT_MIN_DELTA,
+ HPT_MAX_DELTA);
+
+ hpt_enable(hpt);
+
+ if (atomic_cmpxchg(&irq_installed, 0, 1) == 0) {
+ int rc = irq_set_percpu_devid(irq);
+
+ if (rc) {
+ pr_err("unable to configure IRQ%u (%i)\n", irq, rc);
+ return rc;
+ }
+
+ rc = setup_percpu_irq(irq, &hpt_compare_irqaction);
+ if (rc) {
+ pr_err("unable to setup IRQ%u (%i)\n", irq, rc);
+ return rc;
+ }
+ }
+
+ enable_percpu_irq(irq, IRQ_TYPE_NONE);
+
+ return 0;
+}
+
+/* the monotonic clocksource and the scheduler clock are global
+ * objects and must use the same value for all threads */
+static inline u32 hpt_read(void)
+{
+ return hpt_read_count(&per_cpu(hpt_pcpu, 0));
+}
+
+static u64 notrace hpt_read_sched_clock(void)
+{
+ return (u64)hpt_read();
+}
+
+static cycle_t hpt_clocksource_read(struct clocksource *cs)
+{
+ return (cycle_t)hpt_read();
+}
+
+int __init init_r4k_clocksource(void)
+{
+ static struct clocksource hpt_clocksource = {
+ .name = "hpt",
+ .mask = CLOCKSOURCE_MASK(HPT_BITS),
+ .read = hpt_clocksource_read,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .rating = 300
+ };
+ const int rc = clocksource_register_hz(&hpt_clocksource, CPUTMR_CLK);
+
+ if (rc) {
+ pr_err("unable to register a clocksource (%i)\n", rc);
+ return rc;
+ }
+
+#ifndef CONFIG_CPU_FREQ
+ sched_clock_register(hpt_read_sched_clock, HPT_BITS, CPUTMR_CLK);
+#endif
+
+ return 0;
+}
+
+#define HPT_REGS_DEF(cmr, cnt, ctl, enabled_bit, pending_bit) \
+ CR_CPUTMR_##cmr, \
+ CR_CPUTMR_##cnt, \
+ CR_CPUTMR_##ctl, \
+ 1U << enabled_bit, \
+ 1U << pending_bit
+
+void __init plat_hpt_init(void)
+{
+ unsigned int i;
+ const unsigned int freq = CPUTMR_CLK;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ static const struct hpt_regs HPT_REGS[] = {
+ { HPT_REGS_DEF(CMR0, CNT0, CTL, 0, 16) },
+ { HPT_REGS_DEF(CMR1, CNT1, CTL, 1, 17) },
+#ifdef CONFIG_MIPS_TC3262_1004K
+ { HPT_REGS_DEF(CMR2, CNT2, 23_CTL, 0, 16) },
+ { HPT_REGS_DEF(CMR3, CNT3, 23_CTL, 1, 17) },
+#endif
+ };
+ struct hpt *hpt = &per_cpu(hpt_pcpu, i);
+
+ hpt->regs = HPT_REGS[i];
+ hpt_init(hpt);
+ }
+
+ pr_info("using %u.%03u MHz high precision timer\n",
+ ((freq + 500) / 1000) / 1000,
+ ((freq + 500) / 1000) % 1000);
+}
diff --git a/arch/mips/tc3262/irq-gic.c b/arch/mips/tc3262/irq-gic.c
new file mode 100644
index 000000000000..5e533adc59a0
--- /dev/null
+++ b/arch/mips/tc3262/irq-gic.c
@@ -0,0 +1,211 @@
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/mips-cm.h>
+#include <asm/gic.h>
+
+#include <asm/tc3162/tc3162.h>
+#include <asm/tc3162/rt_mmap.h>
+#include <asm/tc3162/surfboardint.h>
+
+#include "irq.h"
+
+#define X GIC_UNUSED
+
+static const struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
+/* cpu, irqNum - 1, polarity, triggerType, flags, Src Name */
+ { 0, CPU_CM_ERR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 0 CPU Coherence Manager Error */
+ { 0, CPU_CM_PCINT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 1 CPU CM Perf Cnt overflow */
+ { 0, UART_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 2 uart */
+ { X, DRAM_PROTECTION - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 3 dram illegal access */
+ { 0, TIMER0_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 4 timer 0 */
+ { 0, TIMER1_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 5 timer 1 */
+ { 0, TIMER2_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 6 timer 2 */
+ { 0, IPI_RESCHED_INT0 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 7 ipi resched 0 */
+ { 1, IPI_RESCHED_INT1 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 8 ipi resched 1 */
+ { 0, TIMER5_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 9 timer 3 for wdog */
+ { 0, GPIO_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 10 GPIO */
+ { 0, PCM1_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 11 PCM 1 */
+ { 2, IPI_RESCHED_INT2 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 12 ipi resched 2 */
+ { 3, IPI_RESCHED_INT3 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 13 ipi resched 3 */
+ { 0, GDMA_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 14 GDMA */
+ { 0, MAC1_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 15 LAN Giga Switch */
+ { 0, UART2_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 16 uart 2 */
+ { 0, IRQ_RT3XXX_USB - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 17 USB host */
+ { 0, DYINGGASP_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 18 Dying gasp */
+ { 0, DMT_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 19 xDSL DMT */
+ { 0, GIC_EDGE_NMI - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 20 gic edge NMI */
+ { 0, QDMA_LAN0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 21 QDMA LAN 0 */
+ { 0, QDMA_WAN0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 22 QDMA WAN 0 */
+ { 0, PCIE_0_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 23 PCIE port 0 */
+ { 0, PCIE_A_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 24 PCIE port 1 */
+ { 0, PCIE_SERR_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 25 PCIE error */
+ { 0, XPON_MAC_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 26 XPON MAC */
+ { 0, XPON_PHY_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 27 XPON PHY */
+ { 0, CRYPTO_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 28 Crypto engine */
+ { 1, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 29 external CPU timer 1 when bfbf0400[1]=1 */
+ { 0, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 30 external CPU timer 0 when bfbf0400[0]=1 */
+ { 0, BUS_TOUT_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 31 Pbus timeout */
+ { 0, PCM2_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 32 PCM 2 */
+ { 0, FE_ERR_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 33 Frame Engine Error */
+ { 0, IPI_CALL_INT0 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 34 ipi call 0 */
+ { 0, AUTO_MANUAL_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 35 SPI */
+ { 3, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 36 external CPU timer 3 when bfbe0000[1]=1 */
+ { 2, SI_TIMER_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_PERCPU }, /* 37 external CPU timer 2 when bfbe0000[1]=1 */
+ { 0, UART3_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 38 UART3 */
+ { 0, QDMA_LAN1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 39 QDMA LAN 1 */
+ { 0, QDMA_LAN2_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 40 QDMA LAN 2 */
+ { 0, QDMA_LAN3_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 41 QDMA LAN 3 */
+ { 0, QDMA_WAN1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 42 QDMA WAN 1 */
+ { 0, QDMA_WAN2_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 43 QDMA WAN 2 */
+ { 0, QDMA_WAN3_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 44 QDMA WAN 3 */
+ { 0, UART4_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 45 UART 4 */
+ { 0, UART5_INT - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 46 UART 5 */
+ { 0, HSDMA_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 47 High Speed DMA */
+ { 0, USB_HOST_2 - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 48 USB host 2 (port1) */
+ { 0, XSI_MAC_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 49 XFI/HGSMII MAC interface */
+ { 0, XSI_PHY_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 50 XFI/HGSMII PHY interface */
+ { 0, WOE0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 51 WIFI Offload Engine 0 */
+ { 0, WOE1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 52 WIFI Offload Engine 1 */
+ { 0, WDMA0_P0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 53 WIFI DMA 0 port 0 */
+ { 0, WDMA0_P1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 54 WIFI DMA 0 port 1 */
+ { 0, WDMA0_WOE_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 55 WIFI DMA 0 for WOE */
+ { 0, WDMA1_P0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 56 WIFI DMA 1 port 0 */
+ { 0, WDMA1_P1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 56 WIFI DMA 1 port 1 */
+ { 0, WDMA1_WOE_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 58 WIFI DMA 1 for WOE */
+#ifdef CONFIG_ECONET_EN7528
+ { 2, RBUS_TOUT_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 59 rbus timeout interrupt */
+#else
+ { 0, EFUSE_ERR0_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 59 efuse error for not setting key */
+#endif
+ { 0, EFUSE_ERR1_INTR - 1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, /* 60 efuse error for prev action not finished */
+ { 1, IPI_CALL_INT1 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 61 ipi call 1 */
+ { 2, IPI_CALL_INT2 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 }, /* 62 ipi call 2 */
+ { 3, IPI_CALL_INT3 - 1, GIC_POL_POS, GIC_TRIG_EDGE, 0 } /* 63 ipi call 3 */
+};
+
+#undef X
+
+static int get_gic_shared_intr(unsigned int irqNum)
+{
+ int intSrc;
+
+ for (intSrc = 0; intSrc < GIC_NUM_INTRS; intSrc++) {
+ if ((gic_intr_map[intSrc].pin + 1) == irqNum)
+ return intSrc;
+ }
+
+ return -1;
+}
+
+void tc_disable_irq_all(void)
+{
+ unsigned long flags;
+
+ if (!gic_present)
+ return;
+
+ local_irq_save(flags);
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 0x00), 0xffffffff);
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 0x04), 0xffffffff);
+ local_irq_restore(flags);
+}
+
+static irqreturn_t cpu_cm_err_interrupt(int irq, void *dev_id)
+{
+ /* clear CM2 error cause */
+ VPint(KSEG1ADDR(RALINK_GCMP_BASE) + 0x0048) = 0;
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cpu_cm_pcint_interrupt(int irq, void *dev_id)
+{
+ /* clear CM2 Performance Counter Overflow Status Register */
+ VPint(KSEG1ADDR(RALINK_GCMP_BASE) + 0x6120) = 0x7;
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction cpu_cm_err_irqaction = {
+ .handler = cpu_cm_err_interrupt,
+ .flags = IRQF_NO_THREAD,
+ .name = "cpu_cm_err",
+};
+
+static struct irqaction cpu_cm_pcint_irqaction = {
+ .handler = cpu_cm_pcint_interrupt,
+ .flags = IRQF_NO_THREAD,
+ .name = "cpu_cm_pcint",
+};
+
+void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
+{
+ int i, intSrc;
+
+ /* irqVec starts from 1 and ends at 63 */
+ for (i = 1; i < INTR_SOURCES_NUM; i++)
+ irq_set_chip(gic_irq_base + i, irq_controller);
+
+ /* Initialize IRQ action handlers */
+ for (i = 1; i < INTR_SOURCES_NUM; i++) {
+ unsigned int irq;
+
+ if (i >= IPI_RESCHED_INT0)
+ break;
+
+ irq = gic_irq_base + i;
+
+ if (i == SI_TIMER_INT)
+ irq_set_handler(irq, handle_percpu_devid_irq);
+ else if (i == GIC_EDGE_NMI)
+ irq_set_handler(irq, handle_edge_irq);
+ else
+ irq_set_handler(irq, handle_level_irq);
+ }
+
+ /* bind watchdog Intr to CPU1 */
+ intSrc = get_gic_shared_intr(TIMER5_INT);
+ if (intSrc >= 0)
+ GIC_SH_MAP_TO_VPE_SMASK(intSrc, 1);
+
+#ifdef CONFIG_ECONET_EN7528
+ /* set rbus timeout intr as NMI */
+ intSrc = get_gic_shared_intr(RBUS_TOUT_INTR);
+ if (intSrc >= 0)
+ GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intSrc)), GIC_MAP_TO_NMI_MSK);
+#endif
+}
+
+void __init arch_init_irq(void)
+{
+ phys_addr_t gic_base = RALINK_GIC_BASE;
+
+ /* Disable all hardware interrupts */
+ clear_c0_status(ST0_IM);
+ clear_c0_cause(CAUSEF_IP);
+
+ if (mips_cm_present()) {
+ gic_base = read_gcr_gic_base() & ~CM_GCR_GIC_BASE_GICEN_MSK;
+
+ write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK);
+ __sync();
+ }
+
+ gic_present = true;
+
+ gic_init(gic_base, RALINK_GIC_ADDRSPACE_SZ, gic_intr_map,
+ ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
+
+ setup_irq(CPU_CM_ERR, &cpu_cm_err_irqaction);
+ setup_irq(CPU_CM_PCINT, &cpu_cm_pcint_irqaction);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int irq = (read_c0_cause() & ST0_IM) >> 10;
+
+ do_IRQ(irq);
+}
diff --git a/arch/mips/tc3262/irq.c b/arch/mips/tc3262/irq.c
new file mode 100644
index 000000000000..15b9a71f60ef
--- /dev/null
+++ b/arch/mips/tc3262/irq.c
@@ -0,0 +1,306 @@
+/*
+ * Interrupt service routines for Trendchip board
+ */
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+
+#include <asm/tc3162/tc3162.h>
+
+#include "irq.h"
+
+extern void vsmp_int_init(void);
+extern int plat_set_irq_affinity(struct irq_data *d,
+ const struct cpumask *affinity, bool force);
+
+__IMEM
+static inline bool mips_mt_cpu_is_irq0(const struct irq_data *d)
+{
+ return d->irq == SI_SWINT_INT0 || d->irq == SI_SWINT1_INT0;
+}
+
+__IMEM
+static inline unsigned long mips_mt_cpu_irq_mask(const struct irq_data *d)
+{
+ if (mips_mt_cpu_is_irq0(d))
+ return CAUSEF_IP0;
+
+ return CAUSEF_IP1;
+}
+
+__IMEM
+static inline void unmask_mips_mt_irq(struct irq_data *d)
+{
+ const unsigned int vpflags = dvpe();
+
+ set_c0_status(mips_mt_cpu_irq_mask(d));
+ irq_enable_hazard();
+ evpe(vpflags);
+}
+
+__IMEM
+static inline void mask_mips_mt_irq(struct irq_data *d)
+{
+ const unsigned int vpflags = dvpe();
+
+ clear_c0_status(mips_mt_cpu_irq_mask(d));
+ irq_disable_hazard();
+ evpe(vpflags);
+}
+
+__IMEM
+static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
+{
+ const unsigned int vpflags = dvpe();
+ const unsigned int mask = mips_mt_cpu_irq_mask(d);
+ unsigned int reg_imr = VPint(CR_INTC_IMR);
+
+ if (mips_mt_cpu_is_irq0(d))
+ reg_imr |= (1u << (SI_SWINT_INT0 - 1)) |
+ (1u << (SI_SWINT1_INT0 - 1));
+ else
+ reg_imr |= (1u << (SI_SWINT_INT1 - 1)) |
+ (1u << (SI_SWINT1_INT1 - 1));
+
+ VPint(CR_INTC_IMR) = reg_imr;
+
+ clear_c0_cause(mask);
+ set_c0_status(mask);
+ irq_enable_hazard();
+ evpe(vpflags);
+
+ return 0;
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for mips_cpu_irq_end.
+ */
+__IMEM
+static void mips_mt_cpu_irq_ack(struct irq_data *d)
+{
+ const unsigned int vpflags = dvpe();
+ const unsigned int mask = mips_mt_cpu_irq_mask(d);
+
+ clear_c0_cause(mask);
+ clear_c0_status(mask);
+ irq_disable_hazard();
+ evpe(vpflags);
+}
+
+static struct irq_chip mips_mt_cpu_irq_controller = {
+ .name = "MIPS",
+ .irq_startup = mips_mt_cpu_irq_startup,
+ .irq_ack = mips_mt_cpu_irq_ack,
+ .irq_mask = mask_mips_mt_irq,
+ .irq_mask_ack = mips_mt_cpu_irq_ack,
+ .irq_unmask = unmask_mips_mt_irq,
+ .irq_eoi = unmask_mips_mt_irq,
+ .irq_disable = mask_mips_mt_irq,
+ .irq_enable = unmask_mips_mt_irq,
+};
+
+static DEFINE_SPINLOCK(tc3262_irq_lock);
+
+__IMEM
+static inline void unmask_mips_irq(struct irq_data *d)
+{
+ unsigned long flags;
+ unsigned int irq = d->irq;
+
+ spin_lock_irqsave(&tc3262_irq_lock, flags);
+
+ if (smp_processor_id() != 0 && irq == SI_TIMER_INT)
+ irq = SI_TIMER1_INT;
+
+ if (irq <= 32)
+ VPint(CR_INTC_IMR) |= (1u << (irq - 1));
+ else
+ VPint(CR_INTC_IMR_1) |= (1u << (irq - 33));
+
+ spin_unlock_irqrestore(&tc3262_irq_lock, flags);
+}
+
+__IMEM
+static inline void mask_mips_irq(struct irq_data *d)
+{
+ unsigned long flags;
+ unsigned int irq = d->irq;
+
+ spin_lock_irqsave(&tc3262_irq_lock, flags);
+
+ if (smp_processor_id() != 0 && irq == SI_TIMER_INT)
+ irq = SI_TIMER1_INT;
+
+ if (irq <= 32)
+ VPint(CR_INTC_IMR) &= ~(1u << (irq - 1));
+ else
+ VPint(CR_INTC_IMR_1) &= ~(1u << (irq - 33));
+
+ spin_unlock_irqrestore(&tc3262_irq_lock, flags);
+}
+
+static struct irq_chip tc3262_irq_chip = {
+ .name = "INTC",
+ .irq_ack = mask_mips_irq,
+ .irq_mask = mask_mips_irq,
+ .irq_mask_ack = mask_mips_irq,
+ .irq_unmask = unmask_mips_irq,
+ .irq_eoi = unmask_mips_irq,
+ .irq_disable = mask_mips_irq,
+ .irq_enable = unmask_mips_irq,
+#ifdef CONFIG_MIPS_MT_SMP
+ .irq_set_affinity = plat_set_irq_affinity,
+#endif
+};
+
+#define __BUILD_IRQ_DISPATCH(irq_n) \
+__IMEM \
+static void __tc3262_irq_dispatch##irq_n(void) \
+{ \
+ do_IRQ(irq_n); \
+}
+
+#define __BUILD_IRQ_DISPATCH_FUNC(irq_n) __tc3262_irq_dispatch##irq_n
+
+/* pre-built 41 irq dispatch function */
+__BUILD_IRQ_DISPATCH(0)
+__BUILD_IRQ_DISPATCH(1)
+__BUILD_IRQ_DISPATCH(2)
+__BUILD_IRQ_DISPATCH(3)
+__BUILD_IRQ_DISPATCH(4)
+__BUILD_IRQ_DISPATCH(5)
+__BUILD_IRQ_DISPATCH(6)
+__BUILD_IRQ_DISPATCH(7)
+__BUILD_IRQ_DISPATCH(8)
+__BUILD_IRQ_DISPATCH(9)
+__BUILD_IRQ_DISPATCH(10)
+__BUILD_IRQ_DISPATCH(11)
+__BUILD_IRQ_DISPATCH(12)
+__BUILD_IRQ_DISPATCH(13)
+__BUILD_IRQ_DISPATCH(14)
+__BUILD_IRQ_DISPATCH(15)
+__BUILD_IRQ_DISPATCH(16)
+__BUILD_IRQ_DISPATCH(17)
+__BUILD_IRQ_DISPATCH(18)
+__BUILD_IRQ_DISPATCH(19)
+__BUILD_IRQ_DISPATCH(20)
+__BUILD_IRQ_DISPATCH(21)
+__BUILD_IRQ_DISPATCH(22)
+__BUILD_IRQ_DISPATCH(23)
+__BUILD_IRQ_DISPATCH(24)
+__BUILD_IRQ_DISPATCH(25)
+__BUILD_IRQ_DISPATCH(26)
+__BUILD_IRQ_DISPATCH(27)
+__BUILD_IRQ_DISPATCH(28)
+__BUILD_IRQ_DISPATCH(29)
+__BUILD_IRQ_DISPATCH(30)
+__BUILD_IRQ_DISPATCH(31)
+__BUILD_IRQ_DISPATCH(32)
+__BUILD_IRQ_DISPATCH(33)
+__BUILD_IRQ_DISPATCH(34)
+__BUILD_IRQ_DISPATCH(35)
+__BUILD_IRQ_DISPATCH(36)
+__BUILD_IRQ_DISPATCH(37)
+__BUILD_IRQ_DISPATCH(38)
+__BUILD_IRQ_DISPATCH(39)
+__BUILD_IRQ_DISPATCH(40)
+
+/* register pre-built 41 irq dispatch function */
+static void (*irq_dispatch_tab[])(void) =
+{
+__BUILD_IRQ_DISPATCH_FUNC(0),
+__BUILD_IRQ_DISPATCH_FUNC(1),
+__BUILD_IRQ_DISPATCH_FUNC(2),
+__BUILD_IRQ_DISPATCH_FUNC(3),
+__BUILD_IRQ_DISPATCH_FUNC(4),
+__BUILD_IRQ_DISPATCH_FUNC(5),
+__BUILD_IRQ_DISPATCH_FUNC(6),
+__BUILD_IRQ_DISPATCH_FUNC(7),
+__BUILD_IRQ_DISPATCH_FUNC(8),
+__BUILD_IRQ_DISPATCH_FUNC(9),
+__BUILD_IRQ_DISPATCH_FUNC(10),
+__BUILD_IRQ_DISPATCH_FUNC(11),
+__BUILD_IRQ_DISPATCH_FUNC(12),
+__BUILD_IRQ_DISPATCH_FUNC(13),
+__BUILD_IRQ_DISPATCH_FUNC(14),
+__BUILD_IRQ_DISPATCH_FUNC(15),
+__BUILD_IRQ_DISPATCH_FUNC(16),
+__BUILD_IRQ_DISPATCH_FUNC(17),
+__BUILD_IRQ_DISPATCH_FUNC(18),
+__BUILD_IRQ_DISPATCH_FUNC(19),
+__BUILD_IRQ_DISPATCH_FUNC(20),
+__BUILD_IRQ_DISPATCH_FUNC(21),
+__BUILD_IRQ_DISPATCH_FUNC(22),
+__BUILD_IRQ_DISPATCH_FUNC(23),
+__BUILD_IRQ_DISPATCH_FUNC(24),
+__BUILD_IRQ_DISPATCH_FUNC(25),
+__BUILD_IRQ_DISPATCH_FUNC(26),
+__BUILD_IRQ_DISPATCH_FUNC(27),
+__BUILD_IRQ_DISPATCH_FUNC(28),
+__BUILD_IRQ_DISPATCH_FUNC(29),
+__BUILD_IRQ_DISPATCH_FUNC(30),
+__BUILD_IRQ_DISPATCH_FUNC(31),
+__BUILD_IRQ_DISPATCH_FUNC(32),
+__BUILD_IRQ_DISPATCH_FUNC(33),
+__BUILD_IRQ_DISPATCH_FUNC(34),
+__BUILD_IRQ_DISPATCH_FUNC(35),
+__BUILD_IRQ_DISPATCH_FUNC(36),
+__BUILD_IRQ_DISPATCH_FUNC(37),
+__BUILD_IRQ_DISPATCH_FUNC(38),
+__BUILD_IRQ_DISPATCH_FUNC(39),
+__BUILD_IRQ_DISPATCH_FUNC(40)
+};
+
+void tc_disable_irq_all(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc3262_irq_lock, flags);
+ VPint(CR_INTC_IMR) = 0x0;
+ VPint(CR_INTC_IMR_1) = 0x0;
+ spin_unlock_irqrestore(&tc3262_irq_lock, flags);
+}
+
+void __init arch_init_irq(void)
+{
+ unsigned int i;
+
+ /* disable all hardware interrupts */
+ clear_c0_status(ST0_IM);
+ clear_c0_cause(CAUSEF_IP);
+
+ for (i = 0; i < NR_IRQS; i++) {
+ if (i == SI_SWINT_INT0 || i == SI_SWINT1_INT0 ||
+ i == SI_SWINT_INT1 || i == SI_SWINT1_INT1) {
+ irq_set_chip(i, &mips_mt_cpu_irq_controller);
+ } else if (i == SI_TIMER_INT || i == SI_TIMER1_INT)
+ irq_set_chip_and_handler(i, &tc3262_irq_chip,
+ handle_percpu_devid_irq);
+ else
+ irq_set_chip_and_handler(i, &tc3262_irq_chip,
+ handle_level_irq);
+ set_vi_handler(i, irq_dispatch_tab[i]);
+ }
+
+#ifdef CONFIG_MIPS_MT_SMP
+ vsmp_int_init();
+#endif
+
+ /* enable MIPS IRQ0 and IRQ1 */
+ write_c0_status((read_c0_status() & ~ST0_IM) |
+ (STATUSF_IP0 | STATUSF_IP1));
+}
+
+__IMEM
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int irq = (read_c0_cause() & ST0_IM) >> 10;
+
+ do_IRQ(irq);
+}
diff --git a/arch/mips/tc3262/irq.h b/arch/mips/tc3262/irq.h
new file mode 100644
index 000000000000..109686797c4c
--- /dev/null
+++ b/arch/mips/tc3262/irq.h
@@ -0,0 +1,6 @@
+#ifndef _TC3262_IRQ_H
+#define _TC3262_IRQ_H
+
+void tc_disable_irq_all(void);
+
+#endif
diff --git a/arch/mips/tc3262/malta-amon.c b/arch/mips/tc3262/malta-amon.c
new file mode 100644
index 000000000000..24c637b04987
--- /dev/null
+++ b/arch/mips/tc3262/malta-amon.c
@@ -0,0 +1,88 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ *
+ * Arbitrary Monitor Interface
+ */
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/addrspace.h>
+#include <asm/mipsmtregs.h>
+#include <asm/tc3162/launch.h>
+#include <asm/vpe.h>
+
+int amon_cpu_avail(int cpu)
+{
+ struct cpulaunch *launch = (struct cpulaunch *)CPU_LAUNCH_BASE;
+
+ if (cpu < 0 || cpu >= NCPULAUNCH) {
+ pr_debug("avail: cpu%d is out of range\n", cpu);
+ return 0;
+ }
+
+ launch += cpu;
+ if (!(launch->flags & LAUNCH_FREADY)) {
+ pr_debug("avail: cpu%d is not ready\n", cpu);
+ return 0;
+ }
+ if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
+ pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
+ return 0;
+ }
+
+ return 1;
+}
+
+int amon_cpu_start(int cpu,
+ unsigned long pc, unsigned long sp,
+ unsigned long gp, unsigned long a0)
+{
+ volatile struct cpulaunch *launch =
+ (struct cpulaunch *)CPU_LAUNCH_BASE;
+
+ if (!amon_cpu_avail(cpu))
+ return -1;
+ if (cpu == smp_processor_id()) {
+ pr_debug("launch: I am cpu%d!\n", cpu);
+ return -1;
+ }
+ launch += cpu;
+
+ pr_debug("launch: starting cpu%d\n", cpu);
+
+ launch->pc = pc;
+ launch->gp = gp;
+ launch->sp = sp;
+ launch->a0 = a0;
+
+ smp_wmb(); /* Target must see parameters before go */
+ launch->flags |= LAUNCH_FGO;
+ smp_wmb(); /* Target must see go before we poll */
+
+ while ((launch->flags & LAUNCH_FGONE) == 0)
+ ;
+ smp_rmb(); /* Target will be updating flags soon */
+ pr_debug("launch: cpu%d gone!\n", cpu);
+
+ return 0;
+}
+
+#ifdef CONFIG_MIPS_VPE_LOADER_CMP
+int vpe_run(struct vpe *v)
+{
+ struct vpe_notifications *n;
+
+ if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0)
+ return -1;
+
+ list_for_each_entry(n, &v->notify, list)
+ n->start(VPE_MODULE_MINOR);
+
+ return 0;
+}
+#endif
diff --git a/arch/mips/tc3262/malta-smp.c b/arch/mips/tc3262/malta-smp.c
new file mode 100644
index 000000000000..00f6c9665ed5
--- /dev/null
+++ b/arch/mips/tc3262/malta-smp.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ * Copyright (C) 2010 PMC-Sierra, Inc.
+ *
+ * VSMP support for MSP platforms . Derived from malta vsmp support.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/tc3162/tc3162.h>
+
+#ifdef CONFIG_MIPS_MT_SMP
+
+#define MIPS_CPU_IPI_RESCHED_IRQ SI_SWINT_INT0 /* SW int 0 for resched */
+#define MIPS_CPU_IPI_CALL_IRQ SI_SWINT_INT1 /* SW int 1 for call */
+
+static void ipi_resched_dispatch(void)
+{
+ do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ);
+}
+
+static void ipi_call_dispatch(void)
+{
+ do_IRQ(MIPS_CPU_IPI_CALL_IRQ);
+}
+
+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
+{
+ scheduler_ipi();
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
+{
+ generic_smp_call_function_interrupt();
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+ .handler = ipi_resched_interrupt,
+ .flags = IRQF_PERCPU,
+ .name = "ipi_resched"
+};
+
+static struct irqaction irq_call = {
+ .handler = ipi_call_interrupt,
+ .flags = IRQF_PERCPU,
+ .name = "ipi_call"
+};
+
+void __init arch_init_ipiirq(int irq, struct irqaction *action)
+{
+ setup_irq(irq, action);
+ irq_set_handler(irq, handle_percpu_irq);
+}
+
+void __init vsmp_int_init(void)
+{
+ set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
+ set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
+
+ arch_init_ipiirq(MIPS_CPU_IPI_RESCHED_IRQ, &irq_resched);
+ arch_init_ipiirq(MIPS_CPU_IPI_CALL_IRQ, &irq_call);
+}
+
+/*
+ * IRQ affinity hook
+ */
+int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
+ bool force)
+{
+ cpumask_t tmask;
+ int cpu = 0;
+ int irq_vpe0 = 0;
+ int irq_vpe1 = 0;
+ unsigned int offset1, offset2;
+
+ /*
+ * On the legacy Malta development board, all I/O interrupts
+ * are routed through the 8259 and combined in a single signal
+ * to the CPU daughterboard, and on the CoreFPGA2/3 34K models,
+ * that signal is brought to IP2 of both VPEs. To avoid racing
+ * concurrent interrupt service events, IP2 is enabled only on
+ * one VPE, by convention VPE0. So long as no bits are ever
+ * cleared in the affinity mask, there will never be any
+ * interrupt forwarding. But as soon as a program or operator
+ * sets affinity for one of the related IRQs, we need to make
+ * sure that we don't ever try to forward across the VPE boundry,
+ * at least not until we engineer a system where the interrupt
+ * _ack() or _end() function can somehow know that it corresponds
+ * to an interrupt taken on another VPE, and perform the appropriate
+ * restoration of Status.IM state using MFTR/MTTR instead of the
+ * normal local behavior. We also ensure that no attempt will
+ * be made to forward to an offline "CPU".
+ */
+
+ cpumask_copy(&tmask, affinity);
+ for_each_cpu(cpu, affinity) {
+ if (!cpu_online(cpu)) {
+ cpumask_clear_cpu(cpu, &tmask);
+ } else {
+ if (cpu == 0)
+ irq_vpe0++;
+ else
+ irq_vpe1++;
+ }
+ }
+
+ cpumask_copy(irq_data_get_affinity_mask(d), &tmask);
+
+ /* change IRQ binding to VPE0 or VPE1 */
+ offset1 = 32 - d->irq;
+ offset2 = ((d->irq - 1) % 4) * 8 + 4;
+ offset1 = (offset1 >> 2) << 2;
+ if (irq_vpe0 >= irq_vpe1)
+ VPint(CR_INTC_IVSR0 + offset1) &= ~(1u << offset2);
+ else
+ VPint(CR_INTC_IVSR0 + offset1) |= (1u << offset2);
+
+ if (cpumask_empty(&tmask)) {
+ /*
+ * We could restore a default mask here, but the
+ * runtime code can anyway deal with the null set
+ */
+ printk(KERN_WARNING
+ "IRQ affinity leaves no legal CPU for IRQ %d\n", d->irq);
+ }
+
+ return IRQ_SET_MASK_OK_NOCOPY;
+}
+
+#endif /* CONFIG_MIPS_MT_SMP */
+
diff --git a/arch/mips/tc3262/pci_en75xx.c b/arch/mips/tc3262/pci_en75xx.c
new file mode 100644
index 000000000000..598d08546e3d
--- /dev/null
+++ b/arch/mips/tc3262/pci_en75xx.c
@@ -0,0 +1,643 @@
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_PCI
+#include <asm/tc3162/rt_mmap.h>
+#include <asm/tc3162/surfboardint.h>
+#include <asm/tc3162/tc3162.h>
+
+#define ECONET_RSTCTRL_REG (RALINK_SYSCTL_BASE + 0x834)
+#define ECONET_PCIEC_REG (RALINK_SYSCTL_BASE + 0x088)
+
+#define ECONET_PCIE_ERR_IRQ_EN (RALINK_PCI_BASE + 0x0040)
+#define ECONET_PCIE_LINKUP (RALINK_PCI_BASE + 0x0050)
+#define ECONET_PCIE0_MAC_BASE (RALINK_PCI_BASE + 0x1000)
+#define ECONET_PCIE1_MAC_BASE (RALINK_PCI_BASE + 0x3000)
+
+#define ECONET_PCI_MM_MAP_BASE 0x20000000
+#define ECONET_PCI_IO_MAP_BASE 0x1F600000
+
+static int pcie_link_status;
+static DEFINE_SPINLOCK(asic_pcr_lock);
+
+static u32 en75xx_get_rc_port(u32 busn, u32 slot)
+{
+ u32 rc = 2;
+
+ if (busn == 0 && slot < 2)
+ rc = slot;
+ else if (busn == 1 && slot == 0 && (pcie_link_status & 0x1))
+ rc = 0;
+ else if (busn == 2 && slot == 0 && (pcie_link_status & 0x2))
+ rc = 1;
+
+ return rc;
+}
+
+static int
+en75xx_write_config_word(u32 busn, u32 slot, u32 func, u32 reg, u32 value)
+{
+ u32 val, rc, mac_offset;
+
+ rc = en75xx_get_rc_port(busn, slot);
+ if (rc == 0)
+ mac_offset = ECONET_PCIE0_MAC_BASE;
+ else if (rc == 1)
+ mac_offset = ECONET_PCIE1_MAC_BASE;
+ else
+ return -1;
+
+ /* fmt=2 | type=4 | length=1 */
+ val = (2 << 29) | (4 << 24) | 1;
+
+ /* write TLP header offset 0..3 */
+ sysRegWrite(mac_offset + 0x0460, val);
+
+ /* write requester ID */
+ val = (rc << 19) | 0x070f;
+
+ /* write TLP header offset 4..7 */
+ sysRegWrite(mac_offset + 0x0464, val);
+
+ val = (busn << 24) | (slot << 19) | (func << 16) | (reg & 0xffc);
+
+ /* write TLP header offset 8..11 */
+ sysRegWrite(mac_offset + 0x0468, val);
+
+ /* write TLP data */
+ sysRegWrite(mac_offset + 0x0470, value);
+
+ /* start TLP request */
+ sysRegWrite(mac_offset + 0x0488, 0x1);
+
+ udelay(10);
+
+ /* polling TLP request status (max 10ms) */
+ val = 1000;
+ while ((val--) > 0) {
+ /* TLP request finished or timeout */
+ if ((sysRegRead(mac_offset + 0x0488) & 0x1) == 0)
+ break;
+ udelay(10);
+ }
+
+ if (val == 0) {
+ printk(KERN_ERR "PCR %s err: bus = %d, dev = %d, func = %d, reg = 0x%08X\n",
+ "write", busn, slot, func, reg);
+ return -1;
+ }
+
+ return 0;
+}
+
+static u32
+en75xx_read_config_word(u32 busn, u32 slot, u32 func, u32 reg)
+{
+ u32 val, rc, mac_offset;
+
+ rc = en75xx_get_rc_port(busn, slot);
+ if (rc == 0)
+ mac_offset = ECONET_PCIE0_MAC_BASE;
+ else if (rc == 1)
+ mac_offset = ECONET_PCIE1_MAC_BASE;
+ else
+ return 0xffffffff;
+
+ /* initialize the data reg */
+ sysRegWrite(mac_offset + 0x048c, 0xffffffff);
+
+ /* fmt=0 | type=4 | length=1 */
+ val = (4 << 24) | 1;
+
+ /* write TLP header offset 0..3 */
+ sysRegWrite(mac_offset + 0x0460, val);
+
+ /* write requester ID */
+ val = (rc << 19) | 0x070f;
+
+ /* write TLP header offset 4..7 */
+ sysRegWrite(mac_offset + 0x0464, val);
+
+ val = (busn << 24) | (slot << 19) | (func << 16) | (reg & 0xffc);
+
+ /* write TLP header offset 8..11 */
+ sysRegWrite(mac_offset + 0x0468, val);
+
+ /* start TLP requuest */
+ sysRegWrite(mac_offset + 0x0488, 0x1);
+
+ udelay(10);
+
+ /* polling TLP request status (max 10ms) */
+ val = 1000;
+ while ((val--) > 0) {
+ /* TLP request finished or timeout */
+ if ((sysRegRead(mac_offset + 0x0488) & 0x1) == 0)
+ break;
+ udelay(10);
+ }
+
+ if (val == 0) {
+ printk(KERN_ERR "PCR %s err: bus = %d, dev = %d, func = %d, reg = 0x%08X\n",
+ "read", busn, slot, func, reg);
+ return 0xffffffff;
+ }
+
+ /* return the data from data reg */
+ return sysRegRead(mac_offset + 0x048c);
+}
+
+static int
+en75xx_pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val)
+{
+ u32 busn = bus->number;
+ u32 slot = PCI_SLOT(devfn);
+ u32 func = PCI_FUNC(devfn);
+ u32 shift, reg, tmp;
+ unsigned long flags;
+
+ reg = (u32)where;
+
+ spin_lock_irqsave(&asic_pcr_lock, flags);
+
+ tmp = en75xx_read_config_word(busn, slot, func, reg);
+
+ spin_unlock_irqrestore(&asic_pcr_lock, flags);
+
+ switch (size) {
+ case 1:
+ shift = (reg & 0x3) << 3;
+ *val = (tmp >> shift) & 0xff;
+ break;
+ case 2:
+ shift = (reg & 0x2) << 3;
+ *val = (tmp >> shift) & 0xffff;
+ break;
+ default:
+ *val = tmp;
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+en75xx_pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+ u32 busn = bus->number;
+ u32 slot = PCI_SLOT(devfn);
+ u32 func = PCI_FUNC(devfn);
+ u32 shift, reg, tmp;
+ unsigned long flags;
+
+ reg = (u32)where;
+
+ spin_lock_irqsave(&asic_pcr_lock, flags);
+
+ switch (size) {
+ case 1:
+ tmp = en75xx_read_config_word(busn, slot, func, reg);
+ shift = (reg & 0x3) << 3;
+ tmp &= ~(0xff << shift);
+ tmp |= ((val & 0xff) << shift);
+ break;
+ case 2:
+ tmp = en75xx_read_config_word(busn, slot, func, reg);
+ shift = (reg & 0x2) << 3;
+ tmp &= ~(0xffff << shift);
+ tmp |= ((val & 0xffff) << shift);
+ break;
+ default:
+ tmp = val;
+ break;
+ }
+
+ en75xx_write_config_word(busn, slot, func, reg, tmp);
+
+ spin_unlock_irqrestore(&asic_pcr_lock, flags);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * General-purpose PCI functions.
+ */
+
+struct pci_ops en75xx_pci_ops = {
+ .read = en75xx_pci_config_read,
+ .write = en75xx_pci_config_write,
+};
+
+static struct resource en75xx_res_pci_mem1 = {
+ .name = "PCI MEM1",
+ .start = ECONET_PCI_MM_MAP_BASE,
+ .end = ECONET_PCI_MM_MAP_BASE + 0x0fffffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource en75xx_res_pci_io1 = {
+ .name = "PCI I/O1",
+ .start = ECONET_PCI_IO_MAP_BASE,
+ .end = ECONET_PCI_IO_MAP_BASE + 0xffff,
+ .flags = IORESOURCE_IO,
+};
+
+struct pci_controller en75xx_pci_controller = {
+ .pci_ops = &en75xx_pci_ops,
+ .mem_resource = &en75xx_res_pci_mem1,
+ .io_resource = &en75xx_res_pci_io1,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+#if defined(CONFIG_ECONET_EN7516) || \
+ defined(CONFIG_ECONET_EN7527) || \
+ defined(CONFIG_PCIE_PORT1)
+static u32 en75xx_pcie_get_pos(u32 busn, u32 slot)
+{
+ u32 val, pos;
+
+ val = en75xx_read_config_word(busn, slot, 0, 0x34);
+ pos = val & 0xff;
+
+ while (pos && pos != 0xff) {
+ val = en75xx_read_config_word(busn, slot, 0, pos);
+ if ((val & 0xff) == 0x10)
+ return pos;
+
+ pos = (val >> 0x08) & 0xff;
+ }
+
+ return 0;
+}
+#endif
+
+static inline void en75xx_pcie_rc0_retrain(void)
+{
+#if defined(CONFIG_ECONET_EN7516) || \
+ defined(CONFIG_ECONET_EN7527)
+ u32 pos, ppos;
+ u32 linkcap, plinkcap, plinksta[2];
+ unsigned long flags;
+
+ spin_lock_irqsave(&asic_pcr_lock, flags);
+
+ ppos = en75xx_pcie_get_pos(0, 0);
+ pos = en75xx_pcie_get_pos(1, 0);
+
+ if (pos < 0x40 || ppos < 0x40)
+ goto exit_unlock;
+
+ plinkcap = en75xx_read_config_word(0, 0, 0, ppos + 0x0c);
+ linkcap = en75xx_read_config_word(1, 0, 0, pos + 0x0c);
+
+ if ((linkcap & 0x0f) == 1 || (plinkcap & 0x0f) == 1)
+ goto exit_unlock;
+
+ plinksta[0] = en75xx_read_config_word(0, 0, 0, ppos + 0x10);
+ if (((plinksta[0] >> 16) & 0x0f) == (plinkcap & 0x0f))
+ goto exit_unlock;
+
+ /* train link Gen1 -> Gen2 */
+ plinksta[0] = en75xx_read_config_word(0, 0, 0, ppos + 0x10);
+ plinksta[0] |= 0x20;
+ en75xx_write_config_word(0, 0, 0, ppos + 0x10, plinksta[0]);
+
+ spin_unlock_irqrestore(&asic_pcr_lock, flags);
+
+ msleep(250);
+
+ spin_lock_irqsave(&asic_pcr_lock, flags);
+ plinksta[1] = en75xx_read_config_word(0, 0, 0, ppos + 0x10);
+
+ printk(KERN_INFO "PCIe RC0 link trained: %x -> %x\n",
+ ((plinksta[0] >> 16) & 0x0f), ((plinksta[1] >> 16) & 0x0f));
+
+exit_unlock:
+ spin_unlock_irqrestore(&asic_pcr_lock, flags);
+#endif
+}
+
+#ifdef CONFIG_PCIE_PORT1
+static inline void en75xx_pcie_rc1_retrain(void)
+{
+ u32 pos, ppos;
+ u32 linkcap, plinkcap, plinksta[2];
+ unsigned long flags;
+
+ spin_lock_irqsave(&asic_pcr_lock, flags);
+
+ ppos = en75xx_pcie_get_pos(0, 1);
+ pos = en75xx_pcie_get_pos(2, 0);
+
+ if (pos < 0x40 || ppos < 0x40)
+ goto exit_unlock;
+
+ plinkcap = en75xx_read_config_word(0, 1, 0, ppos + 0x0c);
+ linkcap = en75xx_read_config_word(2, 0, 0, pos + 0x0c);
+
+ if ((linkcap & 0x0f) == 1 || (plinkcap & 0x0f) == 1)
+ goto exit_unlock;
+
+ plinksta[0] = en75xx_read_config_word(0, 1, 0, ppos + 0x10);
+ if (((plinksta[0] >> 16) & 0x0f) == (plinkcap & 0x0f))
+ goto exit_unlock;
+
+ /* train link Gen1 -> Gen2 */
+ plinksta[0] = en75xx_read_config_word(0, 1, 0, ppos + 0x10);
+ plinksta[0] |= 0x20;
+ en75xx_write_config_word(0, 1, 0, ppos + 0x10, plinksta[0]);
+
+ spin_unlock_irqrestore(&asic_pcr_lock, flags);
+
+ msleep(250);
+
+ spin_lock_irqsave(&asic_pcr_lock, flags);
+ plinksta[1] = en75xx_read_config_word(0, 1, 0, ppos + 0x10);
+
+ printk(KERN_INFO "PCIe RC1 link trained: %x -> %x\n",
+ ((plinksta[0] >> 16) & 0x0f), ((plinksta[1] >> 16) & 0x0f));
+
+exit_unlock:
+ spin_unlock_irqrestore(&asic_pcr_lock, flags);
+}
+#endif
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ u32 busn = dev->bus->number;
+ u32 slot = PCI_SLOT(dev->devfn);
+ u32 i, val, tmp;
+
+ /* P2P bridge */
+ if (busn == 0) {
+ /* set CLS */
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+ (L1_CACHE_BYTES >> 2));
+ }
+
+ if (busn == 0 && slot == 0 && (pcie_link_status & 0x1)) {
+ val = 0;
+ pci_read_config_dword(dev, 0x20, &val);
+ tmp = (val & 0xffff) << 16;
+ val = (val & 0xffff0000) + 0x100000;
+ val = val - tmp;
+
+ i = 0;
+ while (i < 32) {
+ if ((1u << i) >= val)
+ break;
+ i++;
+ }
+
+ /* config RC0 to EP addr window */
+ sysRegWrite(ECONET_PCIE0_MAC_BASE + 0x438, tmp | i);
+ mdelay(1);
+
+ /* enable EP to RC0 access */
+ sysRegWrite(ECONET_PCIE0_MAC_BASE + 0x448, 0x80);
+
+ en75xx_pcie_rc0_retrain();
+ }
+
+#ifdef CONFIG_PCIE_PORT1
+ if (busn == 0 && slot == 1 && (pcie_link_status & 0x2)) {
+ val = 0;
+ pci_read_config_dword(dev, 0x20, &val);
+ tmp = (val & 0xffff) << 16;
+ val = (val & 0xffff0000) + 0x100000;
+ val = val - tmp;
+
+ i = 0;
+ while (i < 32) {
+ if ((1 << i) >= val)
+ break;
+ i++;
+ }
+
+ /* config RC1 to EP addr window */
+ sysRegWrite(ECONET_PCIE1_MAC_BASE + 0x438, tmp | i);
+ mdelay(1);
+
+ /* enable EP to RC1 access */
+ sysRegWrite(ECONET_PCIE1_MAC_BASE + 0x448, 0x80);
+
+ en75xx_pcie_rc1_retrain();
+ }
+#endif
+
+ return 0;
+}
+
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int pci_irq = 0;
+
+ if (slot == 0x0)
+ pci_irq = SURFBOARDINT_PCIE0;
+ else if (slot == 0x1)
+ pci_irq = SURFBOARDINT_PCIE1;
+
+ return pci_irq;
+}
+
+static inline void en75xx_pcie_init_phy(void)
+{
+ u32 __maybe_unused reg_val;
+
+#if defined(CONFIG_ECONET_EN7512)
+
+ /* LCDDS_CLK_PH_INV */
+ reg_val = sysRegRead(RALINK_PCI_PHY0_BASE + 0x04a0);
+ reg_val |= (0x1 << 5);
+ sysRegWrite(RALINK_PCI_PHY0_BASE + 0x04a0, reg_val);
+ mdelay(1);
+
+ /* Patch TxDetRx Timing for 7512 E1, from DR 20160421, Biker_20160516 */
+ reg_val = sysRegRead(RALINK_PCI_PHY1_BASE + 0x0a28);
+ reg_val &= ~(0x1ff << 9);
+ reg_val |= (0x010 << 9);
+ sysRegWrite(RALINK_PCI_PHY1_BASE + 0x0a28, reg_val);
+ mdelay(1);
+
+ reg_val = sysRegRead(RALINK_PCI_PHY1_BASE + 0x0a2c);
+ reg_val &= ~0x1ff;
+ reg_val |= 0x010;
+ sysRegWrite(RALINK_PCI_PHY1_BASE + 0x0a2c, reg_val);
+ mdelay(1);
+
+#ifdef CONFIG_PCIE_PORT1
+ if (isEN7512)
+#endif
+ {
+ /* disable gen2 port PHY for COC test */
+ reg_val = sysRegRead(RALINK_PCI_PHY1_BASE + 0x030c);
+ reg_val |= (1u << 31); /* IP_SW_RESET */
+ sysRegWrite(RALINK_PCI_PHY1_BASE + 0x030c, reg_val);
+ mdelay(1);
+ }
+
+#elif defined(CONFIG_ECONET_EN7528)
+
+ /* LCDDS_CLK_PH_INV */
+ reg_val = sysRegRead(RALINK_PCI_PHY0_BASE + 0x04a0);
+ reg_val |= (0x1 << 5);
+ sysRegWrite(RALINK_PCI_PHY0_BASE + 0x04a0, reg_val);
+ mdelay(1);
+
+ /* combo phy Rx R FT mean value too high, tune target R -5 Ohm */
+ reg_val = sysRegRead(RALINK_PCI_PHY1_BASE + 0x0b2c);
+ reg_val &= ~(0x3 << 12);
+ reg_val |= (0x1 << 12);
+ sysRegWrite(RALINK_PCI_PHY1_BASE + 0x0b2c, reg_val);
+ mdelay(1);
+
+#endif
+}
+
+int __init init_en75xx_pci(void)
+{
+ u32 i, reg_val;
+
+ /* reset PCIe devices by pulse low */
+ reg_val = sysRegRead(ECONET_PCIEC_REG);
+ reg_val &= ~((1 << 29) | (1 << 26));
+ sysRegWrite(ECONET_PCIEC_REG, reg_val);
+ mdelay(1);
+
+ en75xx_pcie_init_phy();
+
+ /* enabled PCIe RC1 clock */
+ reg_val = sysRegRead(ECONET_PCIEC_REG);
+ reg_val |= (1 << 22);
+ sysRegWrite(ECONET_PCIEC_REG, reg_val);
+ mdelay(1);
+
+ /* de-assert PCIe RC0/RC1/HB reset signal */
+ reg_val = sysRegRead(ECONET_RSTCTRL_REG);
+ reg_val &= ~(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIEHB_RST);
+ sysRegWrite(ECONET_RSTCTRL_REG, reg_val);
+ mdelay(1);
+
+ /* assert PCIe RC0/RC1/HB reset signal */
+ reg_val |= (RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIEHB_RST);
+ sysRegWrite(ECONET_RSTCTRL_REG, reg_val);
+ mdelay(100);
+
+ /* de-assert PCIe RC0/RC1/HB reset signal */
+ reg_val &= ~(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIEHB_RST);
+ sysRegWrite(ECONET_RSTCTRL_REG, reg_val);
+ mdelay(10);
+
+ /* release PCIe devices reset */
+ reg_val = sysRegRead(ECONET_PCIEC_REG);
+ reg_val |= ((1 << 29) | (1 << 26));
+ sysRegWrite(ECONET_PCIEC_REG, reg_val);
+
+ /* wait before detect card in slots */
+ mdelay(250);
+ for (i = 0; i < 20; i++) {
+ pcie_link_status = (sysRegRead(ECONET_PCIE_LINKUP) >> 1) & 0x3;
+
+ if ((pcie_link_status & 0x1)
+#ifdef CONFIG_PCIE_PORT1
+ && (pcie_link_status & 0x2)
+#endif
+ )
+ break;
+ msleep(20);
+ }
+
+ if ((pcie_link_status & 0x1) == 0) {
+ printk(KERN_WARNING "PCIe RC%d no card, disable PHY\n", 0);
+
+ /* disable gen1 port PHY */
+ reg_val = sysRegRead(RALINK_PCI_PHY0_BASE);
+ reg_val &= ~(1 << 5); /* rg_pe1_phy_en */
+ reg_val |= (1 << 4); /* rg_pe1_frc_phy_en */
+ sysRegWrite(RALINK_PCI_PHY0_BASE, reg_val);
+ mdelay(1);
+ }
+
+#ifdef CONFIG_PCIE_PORT1
+ if ((pcie_link_status & 0x2) == 0) {
+ printk(KERN_WARNING "PCIe RC%d no card, disable PHY\n", 1);
+
+ /* disable gen2 port PHY */
+ reg_val = sysRegRead(RALINK_PCI_PHY1_BASE + 0x030c);
+ reg_val |= (1u << 31); /* IP_SW_RESET */
+ sysRegWrite(RALINK_PCI_PHY1_BASE + 0x030c, reg_val);
+ mdelay(1);
+ }
+#endif
+
+ if (!pcie_link_status)
+ return 0;
+
+ /* change class to pci-pci class */
+ sysRegWrite(ECONET_PCIE0_MAC_BASE + 0x104, 0x06040001);
+ sysRegWrite(ECONET_PCIE1_MAC_BASE + 0x104, 0x06040001);
+ mdelay(1);
+
+ /* set host mode */
+ sysRegWrite(ECONET_PCIE0_MAC_BASE, 0x00804201);
+ sysRegWrite(ECONET_PCIE1_MAC_BASE, 0x00804201);
+ mdelay(1);
+
+ /* disable MSI interrupt */
+ reg_val = sysRegRead(ECONET_PCIE0_MAC_BASE + 0x11c);
+ reg_val &= ~(1 << 5);
+ sysRegWrite(ECONET_PCIE0_MAC_BASE + 0x11c, reg_val);
+
+ reg_val = sysRegRead(ECONET_PCIE1_MAC_BASE + 0x11c);
+ reg_val &= ~(1 << 5);
+ sysRegWrite(ECONET_PCIE1_MAC_BASE + 0x11c, reg_val);
+
+ /* setup PCIe port0 MAC */
+ if (pcie_link_status & 0x1) {
+ /* enable interrupt */
+ reg_val = sysRegRead(ECONET_PCIE0_MAC_BASE + 0x420);
+ reg_val &= ~(1 << 16);
+ sysRegWrite(ECONET_PCIE0_MAC_BASE + 0x420, reg_val);
+
+ /* enable error interrupt */
+ reg_val = sysRegRead(ECONET_PCIE_ERR_IRQ_EN);
+ reg_val |= 0x03;
+ sysRegWrite(ECONET_PCIE_ERR_IRQ_EN, reg_val);
+ }
+
+#ifdef CONFIG_PCIE_PORT1
+ /* setup PCIe port1 MAC */
+ if (pcie_link_status & 0x2) {
+ /* enable interrupt */
+ reg_val = sysRegRead(ECONET_PCIE1_MAC_BASE + 0x420);
+ reg_val &= ~(1 << 16);
+ sysRegWrite(ECONET_PCIE1_MAC_BASE + 0x420, reg_val);
+
+ /* enable error interrupt */
+ reg_val = sysRegRead(ECONET_PCIE_ERR_IRQ_EN);
+ reg_val |= (0x03 << 2);
+ sysRegWrite(ECONET_PCIE_ERR_IRQ_EN, reg_val);
+ }
+#endif
+
+ en75xx_pci_controller.io_map_base = mips_io_port_base;
+
+ register_pci_controller(&en75xx_pci_controller);
+
+ return 0;
+}
+
+arch_initcall(init_en75xx_pci);
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/tc3262/printf.c b/arch/mips/tc3262/printf.c
new file mode 100644
index 000000000000..e941d01d26c4
--- /dev/null
+++ b/arch/mips/tc3262/printf.c
@@ -0,0 +1,47 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#include <asm/tc3162/tc3162.h>
+
+static char ppbuf[1024];
+
+void prom_putchar(char data)
+{
+ while (!(LSR_INDICATOR & LSR_THRE))
+ ;
+ VPchar(CR_UART_THR) = data;
+}
+
+char prom_getchar(void)
+{
+ while (!(LSR_INDICATOR & LSR_RECEIVED_DATA_READY))
+ ;
+ return VPchar(CR_UART_RBR);
+}
+
+static void uart_write_buf(const char *buf, unsigned int n)
+{
+ char ch;
+
+ while (n != 0) {
+ --n;
+ if ((ch = *buf++) == '\n')
+ prom_putchar('\r');
+ prom_putchar(ch);
+ }
+}
+
+void prom_printf(const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args);
+ va_end(args);
+
+ uart_write_buf(ppbuf, i);
+}
+EXPORT_SYMBOL(prom_printf);
diff --git a/arch/mips/tc3262/prom.c b/arch/mips/tc3262/prom.c
new file mode 100644
index 000000000000..78220aa30acb
--- /dev/null
+++ b/arch/mips/tc3262/prom.c
@@ -0,0 +1,432 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_MIPS_MT_SMP
+#include <asm/smp-ops.h>
+#include <asm/mips-cm.h>
+#include <asm/mips-cpc.h>
+#include <asm/tc3162/launch.h>
+#endif
+
+#include <asm/tc3162/prom.h>
+#include <asm/tc3162/rt_mmap.h>
+#include <asm/tc3162/tc3162.h>
+
+unsigned int surfboard_sysclk;
+unsigned int tc_mips_cpu_freq;
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+int prom_argc;
+int *_prom_argv, *_prom_envp;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension, if running in 64-bit mode.
+ */
+#define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)]))
+#endif
+
+char *prom_getenv(char *envname)
+{
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+ /*
+ * Return a pointer to the given environment variable.
+ * In 64-bit mode: we're using 64-bit pointers, but all pointers
+ * in the PROM structures are only 32-bit, so we need some
+ * workarounds, if we are running in 64-bit mode.
+ */
+ int i, index=0;
+ char *p, *q;
+
+ i = strlen(envname);
+ while (prom_envp(index)) {
+ p = (char*) KSEG0ADDR(prom_envp(index));
+ if(!strncmp(envname, p, i)) {
+ q = strchr(p, '=');
+ if (q)
+ q++;
+ return q;
+ }
+ index++;
+ }
+#endif
+ return NULL;
+}
+
+const char *get_system_type(void)
+{
+#ifdef CONFIG_ECONET_EN7528
+ if (isEN7561DU)
+ return "EcoNet EN7561DU SoC";
+ if (isEN7528DU)
+ return "EcoNet EN7528DU SoC";
+ if (isEN7528)
+ return "EcoNet EN7528 SoC";
+#endif
+#ifdef CONFIG_ECONET_EN7527
+ if (isEN7561G)
+ return "EcoNet EN7561G SoC";
+ if (isEN7527G)
+ return "EcoNet EN7527G SoC";
+ if (isEN7527H)
+ return "EcoNet EN7527H SoC";
+#endif
+#ifdef CONFIG_ECONET_EN7516
+ if (isEN7516G)
+ return "EcoNet EN7516G SoC";
+#endif
+#ifdef CONFIG_ECONET_EN7512
+ if (isEN7513G)
+ return "EcoNet EN7513G SoC";
+ if (isEN7513)
+ return "EcoNet EN7513 SoC";
+ if (isEN7512)
+ return "EcoNet EN7512 SoC";
+#endif
+ return "EcoNet SoC";
+}
+
+static inline void prom_show_pstat(void)
+{
+ unsigned long status;
+ const char *const s = prom_getenv("pstat");
+
+ if (!s)
+ return;
+
+ status = simple_strtoul(s, NULL, 0);
+
+ switch (status) {
+ default:
+ pr_err("SoC power status: unknown (%08lx)\n", status);
+ break;
+ case 3:
+ pr_warn("SoC power status: hardware watchdog reset\n");
+ break;
+ case 2:
+ pr_info("SoC power status: software reset\n");
+ break;
+ case 1:
+ pr_info("SoC power status: power-on reset\n");
+ break;
+ }
+}
+
+static inline void tc_mips_setup(void)
+{
+#ifdef CONFIG_MIPS_TC3262_34K
+ /* enable 34K external sync */
+#ifndef CONFIG_SMP
+ unsigned int oconfig7 = read_c0_config7();
+ unsigned int nconfig7 = oconfig7;
+
+ nconfig7 |= (1 << 8);
+ if (oconfig7 != nconfig7) {
+ __asm__ __volatile("sync");
+ write_c0_config7(nconfig7);
+ }
+#else
+ strcat(arcs_cmdline, " es=1");
+#endif
+#endif
+}
+
+#if defined(CONFIG_MIPS_CMP) || \
+ defined(CONFIG_MIPS_CPS)
+phys_addr_t mips_cpc_default_phys_base(void)
+{
+ return RALINK_CPC_BASE;
+}
+
+static inline void prom_init_cm(void)
+{
+ /* early detection of CMP support */
+ mips_cm_probe();
+ mips_cpc_probe();
+
+#ifdef CONFIG_MIPS_MT_SMP
+ if (register_cps_smp_ops() == 0)
+ return;
+ if (register_cmp_smp_ops() == 0)
+ return;
+ if (register_vsmp_smp_ops() == 0)
+ return;
+#endif
+}
+
+bool plat_cpu_core_present(int core)
+{
+ struct cpulaunch *launch = (struct cpulaunch *)CPU_LAUNCH_BASE;
+
+ if (!core)
+ return true;
+
+ launch += core * 2; /* 2 VPEs per core */
+ if (!(launch->flags & LAUNCH_FREADY))
+ return false;
+
+ if (launch->flags & (LAUNCH_FGO | LAUNCH_FGONE))
+ return false;
+
+ return true;
+}
+#endif
+
+static inline void tc_uart_setup(void)
+{
+ unsigned int div_x, div_y, word;
+
+ /* Set FIFO controo enable, reset RFIFO, TFIFO, 16550 mode, watermark=0x00 (1 byte) */
+ VPchar(CR_HSUART_FCR) = UART_FCR | UART_WATERMARK;
+
+ /* Set modem control to 0 */
+ VPchar(CR_HSUART_MCR) = UART_MCR;
+
+ /* Disable IRDA, Disable Power Saving Mode, RTS , CTS flow control */
+ VPchar(CR_HSUART_MISCC) = UART_MISCC;
+
+ /* Access the baudrate divider */
+ VPchar(CR_HSUART_LCR) = UART_BRD_ACCESS;
+
+ div_y = UART_XYD_Y;
+#if defined(CONFIG_RT2880_UART_115200)
+ div_x = 59904; // Baud rate 115200
+#else
+ div_x = 29952; // Baud rate 57600
+#endif
+ word = (div_x << 16) | div_y;
+ VPint(CR_HSUART_XYD) = word;
+
+ /* Set Baud Rate Divisor to 1*16 */
+ VPchar(CR_HSUART_BRDL) = UART_BRDL_20M;
+ VPchar(CR_HSUART_BRDH) = UART_BRDH_20M;
+
+ /* Set DLAB = 0, clength = 8, stop = 1, no parity check */
+ VPchar(CR_HSUART_LCR) = UART_LCR;
+}
+
+static inline void tc_ahb_setup(void)
+{
+ /* setup bus timeout value */
+ VPint(CR_AHB_AACS) = 0xffff;
+}
+
+static inline void tc_usb_setup(void)
+{
+#if !IS_ENABLED(CONFIG_USB)
+ /* disable both ports UPHY */
+ VPint(RALINK_USB_UPHY_P0_BASE + 0x1c) = 0xC0241580;
+ VPint(RALINK_USB_UPHY_P1_BASE + 0x1c) = 0xC0241580;
+
+ /* assert USB host reset */
+ VPint(CR_AHB_BASE + 0x834) |= (1U << 22);
+#endif
+}
+
+static inline void tc_dmt_setup(void)
+{
+ /* assert DMT reset */
+ VPint(CR_AHB_DMTCR) = 0x1;
+
+#if !defined(CONFIG_TC3162_ADSL) && \
+ !defined(CONFIG_RALINK_VDSL)
+ udelay(100);
+
+ /* disable DMT clock to power save */
+ VPint(CR_AHB_DMTCR) = 0x3;
+#endif
+
+#if defined(CONFIG_ECONET_EN7512)
+ /* Power down SIMLDO */
+ VPint(0xBFA20168) |= (1 << 8);
+#endif
+
+ /* assert PON PHY reset */
+ VPint(CR_AHB_BASE + 0x830) |= (1U << 0);
+
+ /* assert PON MAC reset */
+ VPint(CR_AHB_BASE + 0x834) |= (1U << 31);
+}
+
+static inline void tc_pcm_setup(void)
+{
+ /* assert PCM/ZSI/ICI reset */
+ VPint(CR_AHB_BASE + 0x834) |= (1U << 0) | (1U << 4) | (1U << 17);
+
+ /* assert SFC2 reset */
+ VPint(CR_AHB_BASE + 0x834) |= (1U << 25);
+}
+
+static inline void tc_fe_setup(void)
+{
+ unsigned int reg_val;
+
+ reg_val = VPint(CR_AHB_BASE + 0x834);
+
+ /* check GSW not in reset state */
+ if (!(reg_val & (1U << 23))) {
+ /* disable GSW P6 link */
+ VPint(RALINK_ETH_SW_BASE + 0x3600) = 0x8000;
+ }
+
+ /* assert FE, QDMA2, QDMA1 reset */
+ reg_val |= ((1U << 21) | (1U << 2) | (1U << 1));
+ VPint(CR_AHB_BASE + 0x834) = reg_val;
+ udelay(100);
+
+ /* de-assert FE, QDMA2, QDMA1 reset */
+ reg_val &= ~((1U << 21) | (1U << 2) | (1U << 1));
+ VPint(CR_AHB_BASE + 0x834) = reg_val;
+}
+
+#define VECTORSPACING 0x100 /* for EI/VI mode */
+
+void __init mips_nmi_setup(void)
+{
+ void *base;
+ extern char except_vec_nmi;
+
+ base = cpu_has_veic ?
+ (void *)(ebase + 0x200 + VECTORSPACING * 64) :
+ (void *)(ebase + 0x380);
+
+ pr_info("NMI base is %08x\n", (unsigned int)base);
+
+ /*
+ * Fill the NMI_Handler address in a register, which is a R/W register
+ * start.S will read it, then jump to NMI_Handler address
+ */
+ VPint(0xbfb00244) = (unsigned int)base;
+
+ memcpy(base, &except_vec_nmi, 0x80);
+ flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
+static inline void cpu_dma_round_robin(int mode)
+{
+ unsigned int reg_arb;
+
+ reg_arb = VPint(ARB_CFG);
+
+ if (mode == ENABLE)
+ reg_arb |= ROUND_ROBIN_ENABLE;
+ else
+ reg_arb &= ROUND_ROBIN_DISABLE;
+
+ VPint(ARB_CFG) = reg_arb;
+}
+
+void __init prom_init(void)
+{
+ unsigned long memsize, memresv, memregn, memoffs, memhigh = 0;
+ unsigned int bus_freq, cpu_freq, cpu_ratio;
+ const char *ram_type;
+
+ /* Test supported hardware */
+#if defined(CONFIG_ECONET_EN7512)
+ if (!isEN751221)
+#elif defined(CONFIG_ECONET_EN7516) || \
+ defined(CONFIG_ECONET_EN7527)
+ if (!isEN751627)
+#elif defined(CONFIG_ECONET_EN7528)
+ if (!isEN7528)
+#endif
+ BUG();
+
+#ifdef CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER
+ prom_argc = fw_arg0;
+ _prom_argv = (int*) fw_arg1;
+ _prom_envp = (int*) fw_arg2;
+#endif
+
+ set_io_port_base(KSEG1);
+
+ prom_init_cmdline();
+
+ tc_mips_setup();
+ tc_uart_setup();
+ tc_ahb_setup();
+ tc_usb_setup();
+ tc_dmt_setup();
+ tc_pcm_setup();
+ tc_fe_setup();
+
+ ram_type = (VPint(CR_DMC_BASE + 0xE4) & (1 << 7)) ? "DDR3" : "DDR2";
+ memsize = (GET_DRAM_SIZE) << 20;
+ cpu_ratio = 4;
+
+ memresv = 0;
+#if defined(CONFIG_TC3262_HWFQ_MAP_4M)
+ memresv = 4 << 20;
+#elif defined(CONFIG_TC3262_HWFQ_MAP_8M)
+ memresv = 8 << 20;
+#elif defined(CONFIG_TC3262_HWFQ_MAP_16M)
+ memresv = 16 << 20;
+#endif
+
+#if defined(CONFIG_ECONET_EN7512)
+ memoffs = 0x20000;
+#else
+ memoffs = 0x02000;
+#endif
+
+ if (memsize > EN75XX_PALMBUS_START) {
+ memhigh = memsize - EN75XX_PALMBUS_START;
+ memsize = EN75XX_PALMBUS_START;
+ }
+
+ /* 1. Initial reserved region. */
+ if (memoffs != 0)
+ add_memory_region(0, memoffs, BOOT_MEM_RESERVED);
+
+ /* 2. Normal region. */
+ memregn = memsize - memoffs - memresv;
+ add_memory_region(memoffs, memregn, BOOT_MEM_RAM);
+
+ /* 3. HWQ reserved region. */
+ if (memresv != 0)
+ add_memory_region(memoffs + memregn, memresv,
+ BOOT_MEM_RESERVED);
+
+#ifdef CONFIG_HIGHMEM
+ /* 4. Highmem region. */
+ if (memhigh != 0)
+ add_memory_region(EN75XX_HIGHMEM_START, memhigh,
+ BOOT_MEM_RAM);
+#endif
+
+ bus_freq = SYS_HCLK;
+ cpu_freq = bus_freq * cpu_ratio;
+ if (cpu_freq % 2)
+ cpu_freq += 1;
+
+ surfboard_sysclk = bus_freq * 1000 * 1000;
+ tc_mips_cpu_freq = cpu_freq * 1000 * 1000;
+
+ pr_info("%s: RAM: %s %i MB\n",
+ get_system_type(), ram_type, GET_DRAM_SIZE);
+ pr_info("CPU/SYS frequency: %u/%u MHz\n", cpu_freq, bus_freq);
+
+ board_nmi_handler_setup = mips_nmi_setup;
+ cpu_dma_round_robin(ENABLE);
+
+#if defined(CONFIG_MIPS_CMP) || \
+ defined(CONFIG_MIPS_CPS)
+ prom_init_cm();
+#elif defined(CONFIG_MIPS_MT_SMP)
+ register_vsmp_smp_ops();
+#endif
+ prom_show_pstat();
+}
+
+void __init prom_free_prom_memory(void)
+{
+ /* We do not have any memory to free */
+}
diff --git a/arch/mips/tc3262/setup.c b/arch/mips/tc3262/setup.c
new file mode 100644
index 000000000000..85e5981dfbf9
--- /dev/null
+++ b/arch/mips/tc3262/setup.c
@@ -0,0 +1,134 @@
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <asm/cpu.h>
+#include <asm/cpu-info.h>
+#include <asm/bootinfo.h>
+
+#include <asm/time.h>
+#include <asm/reboot.h>
+#include <asm/pbus-timer.h>
+
+#include <asm/tc3162/tc3162.h>
+
+#include "irq.h"
+
+#if defined(CONFIG_TC3162_ADSL) || \
+ defined(CONFIG_RALINK_VDSL)
+struct sk_buff;
+
+#define ADSL_SET_DMT_CLOSE (0x001a)
+
+typedef struct {
+ void (*query)(unsigned short query_id, void *result1, void *result2);
+ void (*set)(unsigned short set_id, void *value1, void *value2);
+
+ void (*rts_rcv)(struct sk_buff *skb);
+
+ int (*rts_cmd)(int argc,char *argv[],void *p);
+ int (*dmt_cmd)(int argc,char *argv[],void *p);
+ int (*dmt2_cmd)(int argc,char *argv[],void *p);
+ int (*hw_cmd)(int argc,char *argv[],void *p);
+ int (*sw_cmd)(int argc,char *argv[],void *p);
+ int (*ghs_cmd)(int argc,char *argv[],void *p);
+ int (*tcif_cmd)(int argc,char *argv[],void *p);
+} adsldev_ops;
+
+adsldev_ops *adsl_dev_ops = NULL;
+EXPORT_SYMBOL(adsl_dev_ops);
+
+static inline void stop_dsl_dmt(void)
+{
+ if (adsl_dev_ops)
+ adsl_dev_ops->set(ADSL_SET_DMT_CLOSE, NULL, NULL);
+}
+#else
+static inline void stop_dsl_dmt(void) {}
+#endif
+
+static inline void hw_uninit(void)
+{
+ /* stop the DMT module */
+ stop_dsl_dmt();
+
+ /* stop each module dma task */
+ tc_disable_irq_all();
+
+#if !defined(CONFIG_ECONET_EN7528)
+ /* stop atm sar dma */
+ TSARM_GFR &= ~((1 << 1) | (1 << 0));
+#endif
+
+ /* stop all APB module timers except an active watchdog */
+ pbus_timer_disable(PBUS_TIMER_0);
+ pbus_timer_disable(PBUS_TIMER_1);
+ pbus_timer_disable(PBUS_TIMER_2);
+
+ /* timer 3 is in a non-watchdog mode */
+ if (!(pbus_timer_r32(PBUS_TIMER_CTRL) & PBUS_TIMER_CTRL_WDG_ENABLE))
+ pbus_timer_disable(PBUS_TIMER_3);
+}
+
+static void hw_reset(bool do_reboot)
+{
+ hw_uninit();
+
+ if (do_reboot) {
+ /* system software reset */
+ VPint(CR_AHB_RSTCR) |= (1U << 31);
+ }
+}
+
+static void tc_machine_restart(char *command)
+{
+ pr_warn("Machine restart...\n");
+ hw_reset(true);
+}
+
+static void tc_machine_halt(void)
+{
+ pr_warn("Machine halted...\n");
+ hw_reset(false);
+}
+
+static void tc_machine_power_off(void)
+{
+ pr_warn("Machine poweroff...\n");
+ hw_reset(false);
+}
+
+static int tc_panic_event(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ if (action == PANIC_ACTION_RESTART)
+ tc_machine_restart(NULL);
+ else
+ tc_machine_halt();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block tc_panic_block = {
+ .notifier_call = tc_panic_event,
+};
+
+static void tc_reboot_setup(void)
+{
+ _machine_restart = tc_machine_restart;
+ _machine_halt = tc_machine_halt;
+ pm_power_off = tc_machine_power_off;
+
+ atomic_notifier_chain_register(&panic_notifier_list, &tc_panic_block);
+}
+
+void __init plat_mem_setup(void)
+{
+ iomem_resource.start = 0;
+ iomem_resource.end = ~0;
+
+ ioport_resource.start = 0;
+ ioport_resource.end = 0x1fffffff;
+
+ tc_reboot_setup();
+}
diff --git a/arch/mips/tc3262/time.c b/arch/mips/tc3262/time.c
new file mode 100644
index 000000000000..d6a20dc295c5
--- /dev/null
+++ b/arch/mips/tc3262/time.c
@@ -0,0 +1,94 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <asm/time.h>
+#include <asm/pbus-timer.h>
+#include <asm/tc3162/tc3162.h>
+
+extern unsigned int surfboard_sysclk;
+extern unsigned int tc_mips_cpu_freq;
+
+static irqreturn_t tc_bus_timeout_interrupt(int irq, void *dev_id)
+{
+ /* clear an interrupt */
+ VPint(CR_PRATIR) = 1;
+
+ pr_warn("bus timeout interrupt, error address is %08lx\n",
+ VPint(CR_ERR_ADDR) & 0x3fffffff);
+
+ dump_stack();
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_ECONET_EN7528
+irqreturn_t rbus_timeout_interrupt(int irq, void *dev_id)
+{
+ /*
+ * no chance to run this ISR because rbus timeout interrupt
+ * will be set as NMI
+ */
+ return IRQ_HANDLED;
+}
+
+static struct irqaction rbus_timeout_irqaction = {
+ .handler = rbus_timeout_interrupt,
+ .flags = IRQF_NO_THREAD,
+ .name = "rbus timeout",
+};
+#endif
+
+static struct irqaction tc_bus_timeout_irqaction = {
+ .handler = tc_bus_timeout_interrupt,
+ .flags = IRQF_NO_THREAD,
+ .name = "bus timeout",
+};
+
+void __init __weak plat_hpt_init(void)
+{
+}
+
+void __init plat_time_init(void)
+{
+ mips_hpt_frequency = tc_mips_cpu_freq / 2;
+
+ /* enable a CPU external timer */
+ plat_hpt_init();
+
+#if defined(CONFIG_TC3162_ADSL) || \
+ defined(CONFIG_RALINK_VDSL)
+ /*
+ * Configure first timer to 10 ms. periodic infinite mode.
+ * The active timer used in the DMT module
+ * to implement a microsecond delay function.
+ */
+ pbus_timer_enable(PBUS_TIMER_1, 10, PBUS_TIMER_MODE_PERIODIC);
+#endif
+
+ /* setup a bus timeout interrupt */
+ setup_irq(BUS_TOUT_INT, &tc_bus_timeout_irqaction);
+
+#ifdef CONFIG_ECONET_EN7528
+ setup_irq(RBUS_TOUT_INTR, &rbus_timeout_irqaction);
+
+ /* ASIC bus_clk: 235MHz */
+ VPint(CR_MON_TMR) = 0x10000000; /* unit: one bus clock */
+ VPint(CR_MON_TMR) = 0x50000000; /* enable it */
+
+ /* enable rbus timeout mechanism */
+ regWrite32(RBUS_TIMEOUT_CFG0, 0x3ffffff);
+ regWrite32(RBUS_TIMEOUT_CFG1, 0x3ffffff);
+ regWrite32(RBUS_TIMEOUT_CFG2, 0x3ffffff);
+ regWrite32(RBUS_TIMEOUT_STS0, 0x80000000);
+#else
+ VPint(CR_MON_TMR) = 0xcfffffff;
+ VPint(CR_BUSTIMEOUT_SWITCH) = 0xffffffff;
+#endif
+}
+
+unsigned int get_surfboard_sysclk(void)
+{
+ return surfboard_sysclk;
+}
+EXPORT_SYMBOL(get_surfboard_sysclk);
diff --git a/arch/mips/tc3262/uphy.c b/arch/mips/tc3262/uphy.c
new file mode 100644
index 000000000000..a5c1daf29c8e
--- /dev/null
+++ b/arch/mips/tc3262/uphy.c
@@ -0,0 +1,287 @@
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/tc3162/rt_mmap.h>
+#include <asm/tc3162/tc3162.h>
+
+#define ADDR_SIFSLV_BASE RALINK_XHCI_UPHY_BASE
+#define ADDR_SIFSLV_FMREG_BASE (ADDR_SIFSLV_BASE + 0x0100)
+#define ADDR_SIFSLV_PHYD_BASE (ADDR_SIFSLV_BASE + 0x0900)
+#define ADDR_SIFSLV_PHYD_B2_BASE (ADDR_SIFSLV_BASE + 0x0a00)
+#define ADDR_SIFSLV_PHYA_BASE (ADDR_SIFSLV_BASE + 0x0b00)
+#define ADDR_SIFSLV_PHYA_DA_BASE (ADDR_SIFSLV_BASE + 0x0c00)
+
+#define ADDR_U2_PHY_P0_BASE RALINK_USB_UPHY_P0_BASE
+#define ADDR_U2_PHY_P1_BASE RALINK_USB_UPHY_P1_BASE
+
+#define U2_SR_COEFF 28
+#define REF_CK 20
+
+#define REG_SIFSLV_FMREG_FMCR0 (ADDR_SIFSLV_FMREG_BASE + 0x00)
+#define REG_SIFSLV_FMREG_FMCR1 (ADDR_SIFSLV_FMREG_BASE + 0x04)
+#define REG_SIFSLV_FMREG_FMCR2 (ADDR_SIFSLV_FMREG_BASE + 0x08)
+#define REG_SIFSLV_FMREG_FMMONR0 (ADDR_SIFSLV_FMREG_BASE + 0x0C)
+#define REG_SIFSLV_FMREG_FMMONR1 (ADDR_SIFSLV_FMREG_BASE + 0x10)
+
+/* SIFSLV_FMREG_FMCR0 */
+#define RG_LOCKTH (0xf << 28)
+#define RG_MONCLK_SEL (0x3 << 26)
+#define RG_FM_MODE (0x1 << 25)
+#define RG_FREQDET_EN (0x1 << 24)
+#define RG_CYCLECNT (0x00ffffff)
+
+/* SIFSLV_FMREG_FMMONR1 */
+#define RG_MONCLK_SEL_3 (0x1 << 9)
+#define RG_FRCK_EN (0x1 << 8)
+#define USBPLL_LOCK (0x1 << 1)
+#define USB_FM_VLD (0x1 << 0)
+
+#define OFS_U2_PHY_AC0 0x00
+#define OFS_U2_PHY_AC1 0x04
+#define OFS_U2_PHY_AC2 0x08
+#define OFS_U2_PHY_ACR0 0x10
+#define OFS_U2_PHY_ACR1 0x14
+#define OFS_U2_PHY_ACR2 0x18
+#define OFS_U2_PHY_ACR3 0x1C
+#define OFS_U2_PHY_ACR4 0x20
+#define OFS_U2_PHY_AMON0 0x24
+#define OFS_U2_PHY_DCR0 0x60
+#define OFS_U2_PHY_DCR1 0x64
+#define OFS_U2_PHY_DTM0 0x68
+#define OFS_U2_PHY_DTM1 0x6C
+
+/* U2_PHY_ACR0 */
+#define RG_USB20_ICUSB_EN (0x1 << 24)
+#define RG_USB20_HSTX_SRCAL_EN (0x1 << 23)
+#define RG_USB20_HSTX_SRCTRL (0x7 << 16)
+#define RG_USB20_LS_CR (0x7 << 12)
+#define RG_USB20_FS_CR (0x7 << 8)
+#define RG_USB20_LS_SR (0x7 << 4)
+#define RG_USB20_FS_SR (0x7 << 0)
+
+static atomic_t uphy_init_instance = ATOMIC_INIT(0);
+
+static inline u32
+uphy_read32(u32 reg_addr)
+{
+ return sysRegRead(reg_addr);
+}
+
+static inline void
+uphy_write32(u32 reg_addr, u32 reg_data)
+{
+ sysRegWrite(reg_addr, reg_data);
+}
+
+static void
+uphy_write8(u32 reg_addr, u32 reg_data)
+{
+ u32 reg_sfl = (reg_addr % 4) * 8;
+ u32 reg_a32 = reg_addr & 0xfffffffc;
+ u32 reg_msk = 0xff << reg_sfl;
+ u32 reg_tmp = uphy_read32(reg_a32);
+
+ reg_tmp &= ~reg_msk;
+ reg_tmp |= ((reg_data << reg_sfl) & reg_msk);
+
+ uphy_write32(reg_a32, reg_tmp);
+}
+
+static void
+u2_slew_rate_calibration(int port_id, u32 u2_phy_reg_base)
+{
+ u32 reg_val, i;
+ u32 u4Tmp, u4FmOut = 0;
+
+ /* enable HS TX SR calibration */
+ reg_val = uphy_read32(u2_phy_reg_base + OFS_U2_PHY_ACR0);
+ reg_val |= RG_USB20_HSTX_SRCAL_EN;
+ uphy_write32(u2_phy_reg_base + OFS_U2_PHY_ACR0, reg_val);
+ msleep(1);
+
+ /* enable free run clock */
+ reg_val = uphy_read32(REG_SIFSLV_FMREG_FMMONR1);
+ reg_val |= RG_FRCK_EN;
+ uphy_write32(REG_SIFSLV_FMREG_FMMONR1, reg_val);
+
+ /* setting MONCLK_SEL 0x0/0x1 for port0/port1 */
+ reg_val = uphy_read32(REG_SIFSLV_FMREG_FMCR0);
+ reg_val &= ~RG_MONCLK_SEL;
+ reg_val |= (port_id << 26);
+ uphy_write32(REG_SIFSLV_FMREG_FMCR0, reg_val);
+
+ /* setting cyclecnt = 400 */
+ reg_val = uphy_read32(REG_SIFSLV_FMREG_FMCR0);
+ reg_val &= ~RG_CYCLECNT;
+ reg_val |= 0x400;
+ uphy_write32(REG_SIFSLV_FMREG_FMCR0, reg_val);
+
+ /* enable frequency meter */
+ reg_val = uphy_read32(REG_SIFSLV_FMREG_FMCR0);
+ reg_val |= RG_FREQDET_EN;
+ uphy_write32(REG_SIFSLV_FMREG_FMCR0, reg_val);
+
+ /* wait for FM detection done, set 10ms timeout */
+ for (i = 0; i < 10; i++) {
+ /* read FM_OUT */
+ u4FmOut = uphy_read32(REG_SIFSLV_FMREG_FMMONR0);
+
+ /* check if FM detection done */
+ if (u4FmOut != 0)
+ break;
+
+ msleep(1);
+ }
+
+ /* disable frequency meter */
+ reg_val = uphy_read32(REG_SIFSLV_FMREG_FMCR0);
+ reg_val &= ~RG_FREQDET_EN;
+ uphy_write32(REG_SIFSLV_FMREG_FMCR0, reg_val);
+
+ /* disable free run clock */
+ reg_val = uphy_read32(REG_SIFSLV_FMREG_FMMONR1);
+ reg_val &= ~RG_FRCK_EN;
+ uphy_write32(REG_SIFSLV_FMREG_FMMONR1, reg_val);
+
+ /* disable HS TX SR calibration */
+ reg_val = uphy_read32(u2_phy_reg_base + OFS_U2_PHY_ACR0);
+ reg_val &= ~RG_USB20_HSTX_SRCAL_EN;
+ uphy_write32(u2_phy_reg_base + OFS_U2_PHY_ACR0, reg_val);
+ msleep(1);
+
+ /* update RG_USB20_HSTX_SRCTRL */
+ reg_val = uphy_read32(u2_phy_reg_base + OFS_U2_PHY_ACR0);
+ reg_val &= ~RG_USB20_HSTX_SRCTRL;
+ if (u4FmOut != 0) {
+ /* set reg = (1024/FM_OUT) * 20 * 0.028 (round to the nearest digits) */
+ u4Tmp = (((1024 * REF_CK * U2_SR_COEFF) / u4FmOut) + 500) / 1000;
+ reg_val |= ((u4Tmp & 0x07) << 16);
+ printk(KERN_INFO "U2PHY P%d set SRCTRL %s value: %d\n", port_id, "calibration", u4Tmp);
+ } else {
+ reg_val |= (0x4 << 16);
+ printk(KERN_INFO "U2PHY P%d set SRCTRL %s value: %d\n", port_id, "default", 4);
+ }
+ uphy_write32(u2_phy_reg_base + OFS_U2_PHY_ACR0, reg_val);
+}
+
+static inline void
+u2_phy_init(u32 u2_phy_reg_base)
+{
+ u32 reg_val;
+
+ /* set SW PLL Stable mode to 1 for U2 LPM device remote wakeup */
+ reg_val = uphy_read32(u2_phy_reg_base + OFS_U2_PHY_DCR1);
+ reg_val &= ~(0x3 << 18);
+ reg_val |= (0x1 << 18);
+ uphy_write32(u2_phy_reg_base + OFS_U2_PHY_DCR1, reg_val);
+}
+
+static inline void
+uphy_setup_25mhz_xtal(void)
+{
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x1c, 0x18);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x1d, 0x18);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x1f, 0x18);
+ uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x24, 0x18000000);
+ uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x28, 0x18000000);
+ uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x30, 0x18000000);
+ uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x38, 0x004a004a);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x3e, 0x4a);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x3f, 0x0);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x42, 0x48);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x43, 0x0);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x44, 0x48);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x45, 0x0);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x48, 0x48);
+ uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x49, 0x0);
+
+ uphy_write8(ADDR_SIFSLV_PHYA_BASE + 0x24, 0x90);
+ uphy_write8(ADDR_SIFSLV_PHYA_BASE + 0x25, 0x1);
+ uphy_write32(ADDR_SIFSLV_PHYA_BASE + 0x10, 0x1c000000);
+ uphy_write8(ADDR_SIFSLV_PHYA_BASE + 0x0b, 0xe);
+}
+
+void uphy_init(void)
+{
+ u32 reg_val;
+
+ if (atomic_inc_return(&uphy_init_instance) != 1)
+ return;
+
+#if defined(CONFIG_ECONET_EN7512)
+
+ /* patch TxDetRx Timing for E1, from DR 20160421, Biker_20160516 */
+ reg_val = uphy_read32(ADDR_SIFSLV_PHYD_B2_BASE + 0x28);
+ reg_val &= ~(0x1ff << 9);
+ reg_val |= (0x010 << 9);
+ uphy_write32(ADDR_SIFSLV_PHYD_B2_BASE + 0x28, reg_val);
+
+ reg_val = uphy_read32(ADDR_SIFSLV_PHYD_B2_BASE + 0x2c);
+ reg_val &= ~0x1ff;
+ reg_val |= 0x010;
+ uphy_write32(ADDR_SIFSLV_PHYD_B2_BASE + 0x2c, reg_val);
+
+ /* patch LFPS Filter Threshold for E1, from DR 20160421, Biker_20160516 */
+ reg_val = uphy_read32(ADDR_SIFSLV_PHYD_BASE + 0x0c);
+ reg_val &= ~(0x3f << 16);
+ reg_val |= (0x34 << 16);
+ uphy_write32(ADDR_SIFSLV_PHYD_BASE + 0x0c, reg_val);
+
+ /* configure for XTAL 25MHz */
+ if (VPint(CR_AHB_HWCONF) & 0x01)
+ uphy_setup_25mhz_xtal();
+
+ if (isEN7513 || isEN7513G) {
+ printk(KERN_INFO "%s USB PHY config\n", "EN7513 (BGA)");
+
+ uphy_write32(ADDR_U2_PHY_P0_BASE + 0x1c, 0xC0240008); /* enable port 0 */
+ uphy_write32(ADDR_U2_PHY_P1_BASE + 0x1c, 0xC0240000); /* enable port 1 */
+ } else if (isEN7512) {
+ printk(KERN_INFO "%s USB PHY config\n", "EN7512 (QFP)");
+
+ uphy_write32(ADDR_U2_PHY_P0_BASE + 0x1c, 0xC0241580); /* disable port 0 */
+ uphy_write32(ADDR_U2_PHY_P1_BASE + 0x1c, 0xC0240000); /* enable port 1 */
+ }
+
+#elif defined(CONFIG_ECONET_EN7516) || \
+ defined(CONFIG_ECONET_EN7527)
+
+ /* configure for XTAL 25MHz */
+ reg_val = VPint(CR_AHB_HWCONF);
+ if (!(reg_val & 0x40000))
+ uphy_setup_25mhz_xtal();
+
+ uphy_write32(ADDR_U2_PHY_P0_BASE + 0x1c, 0xC0240008); /* enable port 0 */
+ uphy_write32(ADDR_U2_PHY_P1_BASE + 0x1c, 0xC0240000); /* enable port 1 */
+
+ printk(KERN_INFO "%s USB PHY config\n", "EN7516/EN7527");
+
+#elif defined(CONFIG_ECONET_EN7528)
+
+ uphy_write32(ADDR_U2_PHY_P0_BASE + 0x1c, 0xC0240000); /* enable port 0 */
+ uphy_write32(ADDR_U2_PHY_P1_BASE + 0x1c, 0xC0240000); /* enable port 1 */
+
+ /* combo phy Rx R FT mean value too high, tune target R -5 Ohm */
+ reg_val = uphy_read32(ADDR_SIFSLV_PHYA_BASE + 0x2c);
+ reg_val &= ~(0x3 << 12);
+ reg_val |= (0x1 << 12);
+ uphy_write32(ADDR_SIFSLV_PHYA_BASE + 0x2c, reg_val);
+
+ printk(KERN_INFO "%s USB PHY config\n", "EN7528");
+
+#endif
+
+#if !defined(CONFIG_ECONET_EN7528)
+ /* init UPHY */
+ u2_phy_init(ADDR_U2_PHY_P0_BASE);
+ u2_phy_init(ADDR_U2_PHY_P1_BASE);
+#endif
+
+ /* calibrate UPHY */
+ u2_slew_rate_calibration(0, ADDR_U2_PHY_P0_BASE);
+ u2_slew_rate_calibration(1, ADDR_U2_PHY_P1_BASE);
+}
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c
index 285d84e5c7b9..1c4f0604f48c 100644
--- a/arch/mips/txx9/generic/pci.c
+++ b/arch/mips/txx9/generic/pci.c
@@ -388,9 +388,10 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
return 0;
}
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int (*txx9_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
- return txx9_board_vec->pci_map_irq(dev, slot, pin);
+ return txx9_pci_map_irq(dev, slot, pin);
}
char * (*txx9_board_pcibios_setup)(char *str) __initdata;
@@ -426,5 +427,8 @@ char *__init txx9_pcibios_setup(char *str)
txx9_pci_err_action = TXX9_PCI_ERR_IGNORE;
return NULL;
}
+
+ txx9_pci_map_irq = txx9_board_vec->pci_map_irq;
+
return str;
}
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
index adfaee2dce34..f5b74c52cfe4 100644
--- a/arch/mips/vdso/Makefile
+++ b/arch/mips/vdso/Makefile
@@ -44,6 +44,7 @@ VDSO_LDFLAGS := \
$(call cc-ldoption, -Wl$(comma)--build-id)
GCOV_PROFILE := n
+UBSAN_SANITIZE := n
#
# Shared build commands.
diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr
deleted file mode 100644
index 862d74808236..000000000000
--- a/arch/sh/boot/compressed/vmlinux.scr
+++ /dev/null
@@ -1,10 +0,0 @@
-SECTIONS
-{
- .rodata..compressed : {
- input_len = .;
- LONG(input_data_end - input_data) input_data = .;
- *(.data)
- output_len = . - 4;
- input_data_end = .;
- }
-}
diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr
deleted file mode 100644
index 590394e2f5f2..000000000000
--- a/arch/sh/boot/romimage/vmlinux.scr
+++ /dev/null
@@ -1,8 +0,0 @@
-SECTIONS
-{
- .text : {
- zero_page_pos = .;
- *(.data)
- end_data = .;
- }
-}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6219401ae324..dc2b12049749 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -272,9 +272,6 @@ config ZONE_DMA32
config AUDIT_ARCH
def_bool y if X86_64
-config ARCH_SUPPORTS_OPTIMIZED_INLINING
- def_bool y
-
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
def_bool y
@@ -2813,3 +2810,5 @@ source "crypto/Kconfig"
source "arch/x86/kvm/Kconfig"
source "lib/Kconfig"
+
+source "ndm/Kconfig"
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index f09a192260f8..5b98030f7c38 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -287,20 +287,6 @@ config CPA_DEBUG
---help---
Do change_page_attr() self-tests every 30 seconds.
-config OPTIMIZE_INLINING
- bool "Allow gcc to uninline functions marked 'inline'"
- ---help---
- This option determines if the kernel forces gcc to inline the functions
- developers have marked 'inline'. Doing so takes away freedom from gcc to
- do what it thinks is best, which is desirable for the gcc 3.x series of
- compilers. The gcc 4.x series have a rewritten inlining algorithm and
- enabling this option will generate a smaller kernel there. Hopefully
- this algorithm is so good that allowing gcc 4.x and above to make the
- decision will become the default in the future. Until then this option
- is there to test gcc for this.
-
- If unsure, say N.
-
config DEBUG_ENTRY
bool "Debug low-level entry code"
depends on DEBUG_KERNEL
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 60ece1b8bfd3..36709c68c6e4 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -32,7 +32,7 @@ config CRYPTO_FIPS
this is.
config CRYPTO_ALGAPI
- tristate
+ tristate "ALGAPI"
select CRYPTO_ALGAPI2
help
This option provides the API for cryptographic algorithms.
@@ -41,7 +41,7 @@ config CRYPTO_ALGAPI2
tristate
config CRYPTO_AEAD
- tristate
+ tristate "AEAD"
select CRYPTO_AEAD2
select CRYPTO_ALGAPI
@@ -52,7 +52,7 @@ config CRYPTO_AEAD2
select CRYPTO_RNG2
config CRYPTO_BLKCIPHER
- tristate
+ tristate "BLKCIPHER"
select CRYPTO_BLKCIPHER2
select CRYPTO_ALGAPI
@@ -63,7 +63,7 @@ config CRYPTO_BLKCIPHER2
select CRYPTO_WORKQUEUE
config CRYPTO_HASH
- tristate
+ tristate "HASH"
select CRYPTO_HASH2
select CRYPTO_ALGAPI
@@ -72,7 +72,7 @@ config CRYPTO_HASH2
select CRYPTO_ALGAPI2
config CRYPTO_RNG
- tristate
+ tristate "RNG"
select CRYPTO_RNG2
select CRYPTO_ALGAPI
@@ -132,12 +132,12 @@ config CRYPTO_MANAGER
cbc(aes).
config CRYPTO_MANAGER2
- def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y)
- select CRYPTO_AEAD2
- select CRYPTO_HASH2
- select CRYPTO_BLKCIPHER2
- select CRYPTO_AKCIPHER2
- select CRYPTO_KPP2
+ def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y && !CRYPTO_MANAGER_DISABLE_TESTS)
+ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_BLKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_AKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS
+ select CRYPTO_KPP2 if !CRYPTO_MANAGER_DISABLE_TESTS
config CRYPTO_USER
tristate "Userspace cryptographic algorithm configuration"
@@ -150,7 +150,6 @@ config CRYPTO_USER
config CRYPTO_MANAGER_DISABLE_TESTS
bool "Disable run-time self tests"
default y
- depends on CRYPTO_MANAGER2
help
Disable run-time self tests that normally take place at
algorithm registration.
diff --git a/crypto/algboss.c b/crypto/algboss.c
index 5cbc588555ca..31e049b1b604 100644
--- a/crypto/algboss.c
+++ b/crypto/algboss.c
@@ -246,12 +246,16 @@ static int cryptomgr_schedule_test(struct crypto_alg *alg)
type = alg->cra_flags;
/* This piece of crap needs to disappear into per-type test hooks. */
+#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
+ type |= CRYPTO_ALG_TESTED;
+#else
if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
alg->cra_ablkcipher.ivsize))
type |= CRYPTO_ALG_TESTED;
+#endif
param->type = type;
diff --git a/crypto/hmac.c b/crypto/hmac.c
index ba07fb6221ae..e74730224f0a 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -16,6 +16,7 @@
*
*/
+#include <crypto/hmac.h>
#include <crypto/internal/hash.h>
#include <crypto/scatterwalk.h>
#include <linux/err.h>
@@ -74,8 +75,8 @@ static int hmac_setkey(struct crypto_shash *parent,
memcpy(opad, ipad, bs);
for (i = 0; i < bs; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
+ ipad[i] ^= HMAC_IPAD_VALUE;
+ opad[i] ^= HMAC_OPAD_VALUE;
}
return crypto_shash_init(shash) ?:
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 898ef4d736be..5a291dfd4749 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2226,6 +2226,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
+ }, {
+ .alg = "authenc(hmac(md5),cbc(aes))",
+ .test = alg_test_aead,
+ .suite = {
+ .aead = {
+ .enc = {
+ .vecs = hmac_md5_aes_cbc_enc_tv_temp,
+ .count = 2
+ },
+ .dec = {
+ .vecs = hmac_md5_aes_cbc_dec_tv_temp,
+ .count = 2
+ }
+ }
+ }
}, {
.alg = "authenc(hmac(sha1),cbc(aes))",
.test = alg_test_aead,
@@ -2236,6 +2251,10 @@ static const struct alg_test_desc alg_test_descs[] = {
hmac_sha1_aes_cbc_enc_tv_temp,
.count =
HMAC_SHA1_AES_CBC_ENC_TEST_VEC
+ },
+ .dec = {
+ .vecs = hmac_sha1_aes_cbc_dec_tv_temp,
+ .count = 2
}
}
}
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 125669f1e725..0da3eb1587be 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -16449,7 +16449,7 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
#define HMAC_MD5_ECB_CIPHER_NULL_DEC_TEST_VECTORS 2
#define HMAC_SHA1_ECB_CIPHER_NULL_ENC_TEST_VEC 2
#define HMAC_SHA1_ECB_CIPHER_NULL_DEC_TEST_VEC 2
-#define HMAC_SHA1_AES_CBC_ENC_TEST_VEC 7
+#define HMAC_SHA1_AES_CBC_ENC_TEST_VEC 8
#define HMAC_SHA256_AES_CBC_ENC_TEST_VEC 7
#define HMAC_SHA512_AES_CBC_ENC_TEST_VEC 7
#define AES_LRW_ENC_TEST_VECTORS 8
@@ -17345,6 +17345,183 @@ static struct aead_testvec hmac_md5_ecb_cipher_null_dec_tv_template[] = {
},
};
+static struct aead_testvec hmac_md5_aes_cbc_dec_tv_temp[] = {
+ { /* RFC 3602 Case 1 */
+#ifdef __LITTLE_ENDIAN
+ .key = "\x08\x00" /* rta length */
+ "\x01\x00" /* rta type */
+#else
+ .key = "\x00\x08" /* rta length */
+ "\x00\x01" /* rta type */
+#endif
+ "\x00\x00\x00\x10" /* enc key length */
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 8 + 20 + 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .assoc = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .alen = 16,
+ .input = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a"
+ "\x22\x10\xf2\x25\x7f\xe9\x0d\x92"
+ "\xfc\x00\x55\xb1\xd0\xb5\x3a\x74",
+ .ilen = 16 + 16,
+ .result = "Single block msg",
+ .rlen = 16,
+ },
+ { /* RFC 3602 Case 1 (ICV = 96 bits) */
+#ifdef __LITTLE_ENDIAN
+ .key = "\x08\x00" /* rta length */
+ "\x01\x00" /* rta type */
+#else
+ .key = "\x00\x08" /* rta length */
+ "\x00\x01" /* rta type */
+#endif
+ "\x00\x00\x00\x10" /* enc key length */
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 8 + 20 + 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .assoc = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .alen = 16,
+ .input = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a"
+ "\x22\x10\xf2\x25\x7f\xe9\x0d\x92"
+ "\xfc\x00\x55\xb1",
+ .ilen = 16 + 12,
+ .result = "Single block msg",
+ .rlen = 16,
+ }
+};
+
+static struct aead_testvec hmac_md5_aes_cbc_enc_tv_temp[] = {
+ { /* RFC 3602 Case 1 */
+#ifdef __LITTLE_ENDIAN
+ .key = "\x08\x00" /* rta length */
+ "\x01\x00" /* rta type */
+#else
+ .key = "\x00\x08" /* rta length */
+ "\x00\x01" /* rta type */
+#endif
+ "\x00\x00\x00\x10" /* enc key length */
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 8 + 20 + 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .assoc = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .alen = 16,
+ .input = "Single block msg",
+ .ilen = 16,
+ .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a"
+ "\x22\x10\xf2\x25\x7f\xe9\x0d\x92"
+ "\xfc\x00\x55\xb1\xd0\xb5\x3a\x74",
+ .rlen = 16 + 16,
+ }, { /* RFC 3602 Case 1 (ICV = 96 bits) */
+#ifdef __LITTLE_ENDIAN
+ .key = "\x08\x00" /* rta length */
+ "\x01\x00" /* rta type */
+#else
+ .key = "\x00\x08" /* rta length */
+ "\x00\x01" /* rta type */
+#endif
+ "\x00\x00\x00\x10" /* enc key length */
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 8 + 20 + 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .assoc = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .alen = 16,
+ .input = "Single block msg",
+ .ilen = 16,
+ .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a"
+ "\x22\x10\xf2\x25\x7f\xe9\x0d\x92"
+ "\xfc\x00\x55\xb1",
+ .rlen = 16 + 12,
+ }
+};
+
+static struct aead_testvec hmac_sha1_aes_cbc_dec_tv_temp[] = {
+ { /* RFC 3602 Case 1 */
+#ifdef __LITTLE_ENDIAN
+ .key = "\x08\x00" /* rta length */
+ "\x01\x00" /* rta type */
+#else
+ .key = "\x00\x08" /* rta length */
+ "\x00\x01" /* rta type */
+#endif
+ "\x00\x00\x00\x10" /* enc key length */
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 8 + 20 + 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .assoc = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .alen = 16,
+ .input = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a"
+ "\x1b\x13\xcb\xaf\x89\x5e\xe1\x2c"
+ "\x13\xc5\x2e\xa3\xcc\xed\xdc\xb5"
+ "\x03\x71\xa2\x06",
+ .ilen = 16 + 20,
+ .result = "Single block msg",
+ .rlen = 16,
+ },
+ { /* RFC 3602 Case 1 (ICV = 96 bits) */
+#ifdef __LITTLE_ENDIAN
+ .key = "\x08\x00" /* rta length */
+ "\x01\x00" /* rta type */
+#else
+ .key = "\x00\x08" /* rta length */
+ "\x00\x01" /* rta type */
+#endif
+ "\x00\x00\x00\x10" /* enc key length */
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 8 + 20 + 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .assoc = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .alen = 16,
+ .input = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a"
+ "\x1b\x13\xcb\xaf\x89\x5e\xe1\x2c"
+ "\x13\xc5\x2e\xa3",
+ .ilen = 16 + 12,
+ .result = "Single block msg",
+ .rlen = 16,
+ }
+};
+
static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
{ /* RFC 3602 Case 1 */
#ifdef __LITTLE_ENDIAN
@@ -17374,6 +17551,33 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
"\x13\xc5\x2e\xa3\xcc\xed\xdc\xb5"
"\x03\x71\xa2\x06",
.rlen = 16 + 20,
+ }, { /* RFC 3602 Case 1 (ICV = 96 bits) */
+#ifdef __LITTLE_ENDIAN
+ .key = "\x08\x00" /* rta length */
+ "\x01\x00" /* rta type */
+#else
+ .key = "\x00\x08" /* rta length */
+ "\x00\x01" /* rta type */
+#endif
+ "\x00\x00\x00\x10" /* enc key length */
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 8 + 20 + 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .assoc = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .alen = 16,
+ .input = "Single block msg",
+ .ilen = 16,
+ .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a"
+ "\x1b\x13\xcb\xaf\x89\x5e\xe1\x2c"
+ "\x13\xc5\x2e\xa3",
+ .rlen = 16 + 12,
}, { /* RFC 3602 Case 2 */
#ifdef __LITTLE_ENDIAN
.key = "\x08\x00" /* rta length */
diff --git a/crypto/zstd.c b/crypto/zstd.c
index 9bfd28f8cc77..b13c029e595f 100644
--- a/crypto/zstd.c
+++ b/crypto/zstd.c
@@ -22,7 +22,7 @@
#include <linux/zstd.h>
-#define ZSTD_DEF_LEVEL 3
+#define ZSTD_DEF_LEVEL 5
struct zstd_ctx {
ZSTD_CCtx *cctx;
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index a8d4f4b5a77e..9604b2b83d0f 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -143,6 +143,18 @@ config AHCI_CEVA
If unsure, say N.
+config AHCI_MTK
+ tristate "MTK AHCI SATA support"
+ depends on OF
+ help
+ This option enables support for Mediatek
+ AHCI Serial ATA controllers.
+ Its default value is no. Set the value to
+ yes when support SATA device in Mediatek
+ platform.
+
+ If unsure, say N.
+
config AHCI_MVEBU
tristate "Marvell EBU AHCI SATA support"
depends on ARCH_MVEBU
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index a46e6b784bda..e013b602096b 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_AHCI_BRCM) += ahci_brcm.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_CEVA) += ahci_ceva.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_MTK) += ahci_mtk.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_OCTEON) += ahci_octeon.o
obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 0cc08f892fea..6f13719da955 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -54,7 +54,7 @@
enum {
AHCI_MAX_PORTS = 32,
- AHCI_MAX_CLKS = 5,
+ AHCI_MAX_CLKS = 6,
AHCI_MAX_SG = 168, /* hardware max is 64K */
AHCI_DMA_BOUNDARY = 0xffffffff,
AHCI_MAX_CMDS = 32,
diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c
new file mode 100644
index 000000000000..3d071776115d
--- /dev/null
+++ b/drivers/ata/ahci_mtk.c
@@ -0,0 +1,202 @@
+/*
+ * MediaTek AHCI SATA driver
+ *
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/ahci_platform.h>
+#include <linux/kernel.h>
+#include <linux/libata.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include "ahci.h"
+
+#define DRV_NAME "ahci-mtk"
+
+#define SYS_CFG0 0x10
+#define SYS_CFG0_SATA_MSK GENMASK(1, 0)
+#define SYS_CFG0_SATA_GEN3 BIT(1)
+#define SYS_CFG1 0x14
+#define SYS_CFG1_SATA_MSK GENMASK(31, 30)
+#define SYS_CFG1_SATA_EN BIT(31)
+
+struct mtk_ahci_plat {
+ struct regmap *mode;
+ struct reset_control *axi_rst;
+ struct reset_control *sw_rst;
+ struct reset_control *reg_rst;
+};
+
+static const struct ata_port_info ahci_port_info = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_platform_ops,
+};
+
+static struct scsi_host_template ahci_platform_sht = {
+ AHCI_SHT(DRV_NAME),
+};
+
+static int mtk_ahci_platform_resets(struct ahci_host_priv *hpriv,
+ struct device *dev)
+{
+ struct mtk_ahci_plat *plat = hpriv->plat_data;
+ int err;
+
+ /* reset AXI bus and PHY part */
+ plat->axi_rst = devm_reset_control_get_optional_exclusive(dev, "axi");
+ if (PTR_ERR(plat->axi_rst) == -EPROBE_DEFER)
+ return PTR_ERR(plat->axi_rst);
+
+ plat->sw_rst = devm_reset_control_get_optional_exclusive(dev, "sw");
+ if (PTR_ERR(plat->sw_rst) == -EPROBE_DEFER)
+ return PTR_ERR(plat->sw_rst);
+
+ plat->reg_rst = devm_reset_control_get_optional_exclusive(dev, "reg");
+ if (PTR_ERR(plat->reg_rst) == -EPROBE_DEFER)
+ return PTR_ERR(plat->reg_rst);
+
+ err = reset_control_assert(plat->axi_rst);
+ if (err) {
+ dev_err(dev, "failed to assert AXI bus\n");
+ return err;
+ }
+
+ err = reset_control_assert(plat->sw_rst);
+ if (err) {
+ dev_err(dev, "failed to assert PHY digital part\n");
+ return err;
+ }
+
+ err = reset_control_assert(plat->reg_rst);
+ if (err) {
+ dev_err(dev, "failed to assert PHY register part\n");
+ return err;
+ }
+
+ err = reset_control_deassert(plat->reg_rst);
+ if (err) {
+ dev_err(dev, "failed to deassert PHY register part\n");
+ return err;
+ }
+
+ err = reset_control_deassert(plat->sw_rst);
+ if (err) {
+ dev_err(dev, "failed to deassert PHY digital part\n");
+ return err;
+ }
+
+ err = reset_control_deassert(plat->axi_rst);
+ if (err) {
+ dev_err(dev, "failed to deassert AXI bus\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int mtk_ahci_parse_property(struct ahci_host_priv *hpriv,
+ struct device *dev)
+{
+ struct mtk_ahci_plat *plat = hpriv->plat_data;
+ struct device_node *np = dev->of_node;
+
+ /* enable SATA function if needed */
+ if (of_find_property(np, "mediatek,phy-mode", NULL)) {
+ plat->mode = syscon_regmap_lookup_by_phandle(
+ np, "mediatek,phy-mode");
+ if (IS_ERR(plat->mode)) {
+ dev_err(dev, "missing phy-mode phandle\n");
+ return PTR_ERR(plat->mode);
+ }
+
+ regmap_update_bits(plat->mode, SYS_CFG0, SYS_CFG0_SATA_MSK,
+ SYS_CFG0_SATA_GEN3);
+
+ regmap_update_bits(plat->mode, SYS_CFG1, SYS_CFG1_SATA_MSK,
+ SYS_CFG1_SATA_EN);
+ }
+
+ of_property_read_u32(np, "ports-implemented", &hpriv->force_port_map);
+
+ return 0;
+}
+
+static int mtk_ahci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_ahci_plat *plat;
+ struct ahci_host_priv *hpriv;
+ int err;
+
+ plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
+ if (!plat)
+ return -ENOMEM;
+
+ hpriv = ahci_platform_get_resources(pdev);
+ if (IS_ERR(hpriv))
+ return PTR_ERR(hpriv);
+
+ hpriv->plat_data = plat;
+
+ err = mtk_ahci_parse_property(hpriv, dev);
+ if (err)
+ return err;
+
+ err = mtk_ahci_platform_resets(hpriv, dev);
+ if (err)
+ return err;
+
+ err = ahci_platform_enable_resources(hpriv);
+ if (err)
+ return err;
+
+ err = ahci_platform_init_host(pdev, hpriv, &ahci_port_info,
+ &ahci_platform_sht);
+ if (err)
+ goto disable_resources;
+
+ return 0;
+
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
+ return err;
+}
+
+static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
+ ahci_platform_resume);
+
+static const struct of_device_id ahci_of_match[] = {
+ { .compatible = "mediatek,mtk-ahci", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ahci_of_match);
+
+static struct platform_driver mtk_ahci_driver = {
+ .probe = mtk_ahci_probe,
+ .remove = ata_platform_remove_one,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = ahci_of_match,
+ .pm = &ahci_pm_ops,
+ },
+};
+module_platform_driver(mtk_ahci_driver);
+
+MODULE_DESCRIPTION("MediaTek SATA AHCI Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index a95e1e572697..b6a0b3b654b7 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -291,9 +291,11 @@ static void fw_free_buf(struct firmware_buf *buf)
static char fw_path_para[256];
static const char * const fw_path[] = {
fw_path_para,
+#ifndef CONFIG_EMBEDDED
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
+#endif
"/lib/firmware"
};
@@ -604,11 +606,6 @@ static ssize_t firmware_loading_show(struct device *dev,
return sprintf(buf, "%d\n", loading);
}
-/* Some architectures don't have PAGE_KERNEL_RO */
-#ifndef PAGE_KERNEL_RO
-#define PAGE_KERNEL_RO PAGE_KERNEL
-#endif
-
/* one pages buffer should be mapped/unmapped only once */
static int fw_map_pages_buf(struct firmware_buf *buf)
{
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index e494a938a9f1..309de35d57cb 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -1519,6 +1519,83 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
return r;
}
+/*
+ * dev_pm_opp_adjust_voltage() - helper to change the voltage of an OPP
+ * @dev: device for which we do this operation
+ * @freq: OPP frequency to adjust voltage of
+ * @u_volt: new OPP voltage
+ *
+ * Change the voltage of an OPP with an RCU operation.
+ *
+ * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
+ * copy operation, returns 0 if no modifcation was done OR modification was
+ * successful.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks to
+ * keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex locking or synchronize_rcu() blocking calls cannot be used.
+ */
+int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
+ unsigned long u_volt)
+{
+ struct opp_table *opp_table;
+ struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+ int r = 0;
+
+ /* keep the node allocated */
+ new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
+ if (!new_opp)
+ return -ENOMEM;
+
+ mutex_lock(&opp_table_lock);
+
+ /* Find the device_opp */
+ opp_table = _find_opp_table(dev);
+ if (IS_ERR(opp_table)) {
+ r = PTR_ERR(opp_table);
+ dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
+ goto unlock;
+ }
+
+ /* Do we have the frequency? */
+ list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
+ if (tmp_opp->rate == freq) {
+ opp = tmp_opp;
+ break;
+ }
+ }
+ if (IS_ERR(opp)) {
+ r = PTR_ERR(opp);
+ goto unlock;
+ }
+
+ /* Is update really needed? */
+ if (opp->u_volt == u_volt)
+ goto unlock;
+ /* copy the old data over */
+ *new_opp = *opp;
+
+ /* plug in new node */
+ new_opp->u_volt = u_volt;
+
+ list_replace_rcu(&opp->node, &new_opp->node);
+ mutex_unlock(&opp_table_lock);
+ call_srcu(&opp_table->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
+
+ /* Notify the change of the OPP */
+ srcu_notifier_call_chain(&opp_table->srcu_head, OPP_EVENT_ADJUST_VOLTAGE,
+ new_opp);
+
+ return 0;
+
+unlock:
+ mutex_unlock(&opp_table_lock);
+ kfree(new_opp);
+ return r;
+}
+
/**
* dev_pm_opp_enable() - Enable a specific OPP
* @dev: device for which we do this operation
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index db9d00c36a3e..48b3fc1ee514 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -4,9 +4,12 @@
config REGMAP
default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ)
+ select IRQ_DOMAIN if REGMAP_IRQ
+ bool
+
+config REGCACHE_COMPRESSED
select LZO_COMPRESS
select LZO_DECOMPRESS
- select IRQ_DOMAIN if REGMAP_IRQ
bool
config REGMAP_AC97
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index 609e4c84f485..6271ea9b758a 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -2,7 +2,8 @@
CFLAGS_regmap.o := -I$(src)
obj-$(CONFIG_REGMAP) += regmap.o regcache.o
-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o
+obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o
+obj-$(CONFIG_REGCACHE_COMPRESSED) += regcache-lzo.o
obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index c0fdbb392758..86466acab563 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -33,7 +33,7 @@ struct regcache_rbtree_node {
unsigned int blklen;
/* the actual rbtree node holding this block */
struct rb_node node;
-} __attribute__ ((packed));
+};
struct regcache_rbtree_ctx {
struct rb_root root;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 4e582561e1e7..3644fe8b27c3 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -21,7 +21,9 @@
static const struct regcache_ops *cache_types[] = {
&regcache_rbtree_ops,
+#if IS_ENABLED(CONFIG_REGCACHE_COMPRESSED)
&regcache_lzo_ops,
+#endif
&regcache_flat_ops,
};
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 5189fd6182f6..38d418418a62 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -363,4 +363,13 @@ struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
+void __iomem *regmap_get_iomem(struct regmap *map)
+{
+ if (map->bus != &regmap_mmio)
+ return ERR_PTR(-EINVAL);
+
+ return ((struct regmap_mmio_context *)map->bus_context)->regs;
+}
+EXPORT_SYMBOL(regmap_get_iomem);
+
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 40a9e5378633..0f247fb9f597 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2908,6 +2908,18 @@ int regmap_parse_val(struct regmap *map, const void *buf,
}
EXPORT_SYMBOL_GPL(regmap_parse_val);
+void regmap_lock_map(struct regmap *map)
+{
+ map->lock(map->lock_arg);
+}
+EXPORT_SYMBOL(regmap_lock_map);
+
+void regmap_unlock_map(struct regmap *map)
+{
+ map->unlock(map->lock_arg);
+}
+EXPORT_SYMBOL(regmap_unlock_map);
+
static int __init regmap_initcall(void)
{
regmap_debugfs_initcall();
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index b5c48a8d485f..f7d5f1febb04 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -1,7 +1,7 @@
config BCMA_POSSIBLE
bool
depends on HAS_IOMEM && HAS_DMA
- default y
+ default n
menu "Broadcom specific AMBA"
depends on BCMA_POSSIBLE
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index dece26f119d4..ab62b81c2ca7 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -1070,7 +1070,7 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned
.done = 0,
.flags = flags,
.error = 0,
- .kref = KREF_INIT(2),
+ .kref = { ATOMIC_INIT(2) },
};
if (!get_ldev_if_state(device, D_ATTACHING)) { /* put is in drbd_bm_aio_ctx_destroy() */
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 29abf344a4b6..40325d7527b2 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/major.h>
#include <linux/bio.h>
#include <linux/bitops.h>
#include <linux/blkdev.h>
@@ -2119,8 +2120,8 @@ static int __init zram_init(void)
}
zram_debugfs_create();
- zram_major = register_blkdev(0, "zram");
- if (zram_major <= 0) {
+ zram_major = ZRAM_MAJOR;
+ if (register_blkdev(zram_major, "zram")) {
pr_err("Unable to get major number\n");
class_unregister(&zram_control_class);
return -EBUSY;
@@ -2156,3 +2157,4 @@ MODULE_PARM_DESC(num_devices, "Number of pre-created zram devices");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
MODULE_DESCRIPTION("Compressed RAM Block Device");
+MODULE_ALIAS_BLOCKDEV_MAJOR(ZRAM_MAJOR);
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 78751057164a..3c1a88472244 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -167,4 +167,14 @@ config VEXPRESS_CONFIG
help
Platform configuration infrastructure for the ARM Ltd.
Versatile Express.
+
+config MTK_SUBSYS_IOC
+ bool "MediaTek Subsys IO Coherence"
+ depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
+ depends on OF
+ select REGMAP
+ select MFD_SYSCON
+ help
+ Say yes here to add support IO coherence feature for the MediaTek
+ peripheral device.
endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b2606e..b1af1f451bfc 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
obj-$(CONFIG_IMX_WEIM) += imx-weim.o
obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
+obj-$(CONFIG_MTK_SUBSYS_IOC) += mtk-subsys-ioc.o
+obj-$(CONFIG_ARCH_MEDIATEK) += mtk-rbus.o
# Interconnect bus driver for OMAP SoCs.
obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
diff --git a/drivers/bus/mtk-rbus.c b/drivers/bus/mtk-rbus.c
new file mode 100644
index 000000000000..9a383a7ef24d
--- /dev/null
+++ b/drivers/bus/mtk-rbus.c
@@ -0,0 +1,76 @@
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <linux/mtk-rbus.h>
+
+int rbus_driver_register(struct platform_driver *drv, struct module *owner)
+{
+ return __platform_driver_register(drv, owner);
+}
+EXPORT_SYMBOL(rbus_driver_register);
+
+void rbus_driver_unregister(struct platform_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(rbus_driver_unregister);
+
+struct platform_device *rbus_device_alloc(const char *name, int id)
+{
+ return platform_device_alloc(name, id);
+}
+EXPORT_SYMBOL(rbus_device_alloc);
+
+void rbus_device_put(struct platform_device *pdev)
+{
+ return platform_device_put(pdev);
+}
+EXPORT_SYMBOL(rbus_device_put);
+
+int rbus_get_irq(struct platform_device *pdev, unsigned int num)
+{
+ return platform_get_irq(pdev, num);
+}
+EXPORT_SYMBOL(rbus_get_irq);
+
+int rbus_init_dummy_netdev(struct net_device *dev)
+{
+ return init_dummy_netdev(dev);
+}
+EXPORT_SYMBOL(rbus_init_dummy_netdev);
+
+int rbus_clk_enable(struct clk *clk, bool enable)
+{
+ if (enable)
+ return clk_prepare_enable(clk);
+
+ clk_disable_unprepare(clk);
+
+ return 0;
+}
+EXPORT_SYMBOL(rbus_clk_enable);
+
+void rbus_pm_runtime_enable(struct device *dev, bool enable)
+{
+ if (enable) {
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+ } else {
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+ }
+}
+EXPORT_SYMBOL(rbus_pm_runtime_enable);
+
+int rbus_init_wakeup(struct device *dev, bool enable)
+{
+ return device_init_wakeup(dev, enable);
+}
+EXPORT_SYMBOL(rbus_init_wakeup);
+
+void rbus_set_dma_coherent(struct device *dev, bool coherent)
+{
+ arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
+}
+EXPORT_SYMBOL(rbus_set_dma_coherent);
+
diff --git a/drivers/bus/mtk-subsys-ioc.c b/drivers/bus/mtk-subsys-ioc.c
new file mode 100644
index 000000000000..51618b5dbbd1
--- /dev/null
+++ b/drivers/bus/mtk-subsys-ioc.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+
+#define CCI400_S4_OF_NODE "arm,cci-400-s4"
+#define CCI400_SCR_OFFS 0x000
+#define CCI400_SCR_SNOOP BIT(0)
+#define CCI400_SCR_DVM BIT(1)
+
+#define WBSYS_OF_NODE "mediatek,wbsys"
+#define WBSYS_IOC_PDMA BIT(31)
+
+#define HIFSYS_OF_NODE "mediatek,hifsys"
+#define HIFSYS_IOC_PCIE0 BIT(0)
+#define HIFSYS_IOC_PCIE1_SATA BIT(1)
+#define HIFSYS_IOC_PCIE_SATA_MASK GENMASK(1, 0)
+
+#define HIFSYS_IOC_SSUSB_XHCI_MAS BIT(2)
+#define HIFSYS_IOC_SSUSB_XHCI_U3DATA BIT(3)
+#define HIFSYS_IOC_SSUSB_DEV BIT(4)
+#define HIFSYS_IOC_SSUSB_MASK GENMASK(4, 2)
+
+#define ETHSYS_OF_NODE "mediatek,ethsys"
+#define ETHSYS_IOC_PDMA BIT(0)
+#define ETHSYS_IOC_QDMA BIT(1)
+#define ETHSYS_IOC_PPE BIT(2)
+#define ETHSYS_IOC_WDMA0 BIT(3)
+#define ETHSYS_IOC_HSDMA BIT(4)
+#define ETHSYS_IOC_GDMA BIT(5)
+#define ETHSYS_IOC_WDMA1 BIT(6)
+#define ETHSYS_IOC_ETH_MASK GENMASK(1, 0)
+
+struct mtk_subsys_ioc_pdata {
+ bool has_wbsys;
+ bool has_hifsys;
+ bool has_ethsys;
+
+ unsigned int wb_ioc_off;
+ unsigned int hif_ioc_off;
+ unsigned int eth_ioc_off;
+};
+
+static int arm_cci400_slave_snoop(struct device_node *np, const char *sp)
+{
+ struct device_node *sl_np;
+ void __iomem *sl_base;
+ u32 reg_val;
+
+ sl_np = of_parse_phandle(np, sp, 0);
+ if (!sl_np)
+ return -ENODEV;
+
+ sl_base = of_iomap(sl_np, 0);
+ of_node_put(sl_np);
+
+ if (!sl_base)
+ return -ENOMEM;
+
+ reg_val = __raw_readl(sl_base + CCI400_SCR_OFFS);
+ if (!(reg_val & CCI400_SCR_DVM) ||
+ !(reg_val & CCI400_SCR_SNOOP)) {
+ reg_val |= (CCI400_SCR_DVM | CCI400_SCR_SNOOP);
+ __raw_writel(reg_val, sl_base + CCI400_SCR_OFFS);
+ }
+
+ iounmap(sl_base);
+
+ return 0;
+}
+
+static bool of_dma_coherent(struct device_node *np, const char *sp)
+{
+ struct device_node *dma_np;
+ bool dma_ioc = false;
+
+ dma_np = of_parse_phandle(np, sp, 0);
+ if (dma_np) {
+ dma_ioc = of_property_read_bool(dma_np, "dma-coherent");
+ of_node_put(dma_np);
+ }
+
+ return dma_ioc;
+}
+
+static int mtk_subsys_ioc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct mtk_subsys_ioc_pdata *data;
+ struct regmap *wbsys, *hifsys, *ethsys;
+ bool is_wbsys_ioc = false;
+ bool is_ethsys_ioc = false;
+
+ data = of_device_get_match_data(dev);
+ if (!data)
+ return -ENODEV;
+
+ if (data->has_wbsys)
+ is_wbsys_ioc = of_dma_coherent(np, "mediatek,wifi");
+
+ if (data->has_ethsys)
+ is_ethsys_ioc = of_dma_coherent(np, "mediatek,eth");
+
+ /* enable Snoop & DVM message requests on ARM CCI slave interface 4 */
+ if (is_wbsys_ioc || is_ethsys_ioc)
+ arm_cci400_slave_snoop(np, CCI400_S4_OF_NODE);
+
+ /* enable wbsys IOC if needed */
+ if (is_wbsys_ioc) {
+ wbsys = syscon_regmap_lookup_by_phandle(np, WBSYS_OF_NODE);
+ if (!IS_ERR(wbsys)) {
+ regmap_update_bits(wbsys, data->wb_ioc_off,
+ WBSYS_IOC_PDMA,
+ WBSYS_IOC_PDMA);
+ }
+ }
+
+ /* enable ethernet IOC if needed */
+ if (is_ethsys_ioc) {
+ ethsys = syscon_regmap_lookup_by_phandle(np, ETHSYS_OF_NODE);
+ if (!IS_ERR(ethsys)) {
+ unsigned int reg_val = ETHSYS_IOC_PDMA;
+
+ /* hwnat HWFQ path is SW coherence only */
+ if (!IS_ENABLED(CONFIG_RA_HW_NAT_QDMA))
+ reg_val |= ETHSYS_IOC_QDMA;
+
+ regmap_update_bits(ethsys, data->eth_ioc_off,
+ ETHSYS_IOC_ETH_MASK,
+ reg_val);
+ }
+ }
+
+ /* enable USB/PCIe/SATA IOC if needed */
+ if (data->has_hifsys) {
+ hifsys = syscon_regmap_lookup_by_phandle(np, HIFSYS_OF_NODE);
+ if (!IS_ERR(hifsys)) {
+ if (of_property_read_bool(np, "mediatek,en_usb"))
+ regmap_update_bits(hifsys, data->hif_ioc_off,
+ HIFSYS_IOC_SSUSB_MASK,
+ HIFSYS_IOC_SSUSB_XHCI_MAS |
+ HIFSYS_IOC_SSUSB_XHCI_U3DATA |
+ HIFSYS_IOC_SSUSB_DEV);
+
+ if (of_property_read_bool(np, "mediatek,en_pcie_sata"))
+ regmap_update_bits(hifsys, data->hif_ioc_off,
+ HIFSYS_IOC_PCIE_SATA_MASK,
+ HIFSYS_IOC_PCIE0 |
+ HIFSYS_IOC_PCIE1_SATA);
+ }
+ }
+
+ return 0;
+}
+
+static const struct mtk_subsys_ioc_pdata subsys_ioc_v1 = {
+ .has_wbsys = true,
+ .has_hifsys = true,
+ .has_ethsys = true,
+ .wb_ioc_off = 0x320,
+ .hif_ioc_off = 0x08,
+ .eth_ioc_off = 0x408,
+};
+
+static const struct of_device_id of_subsys_ioc_id_table[] = {
+ {
+ .compatible = "mediatek,mt7622-subsys-ioc",
+ .data = &subsys_ioc_v1,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_driver mtk_subsys_ioc_driver = {
+ .probe = mtk_subsys_ioc_probe,
+ .driver = {
+ .name = "mtk_subsys_ioc",
+ .of_match_table = of_subsys_ioc_id_table,
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_platform_driver(mtk_subsys_ioc_driver);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 200dab5136a7..a15dcefaad29 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -423,6 +423,20 @@ config HW_RANDOM_CAVIUM
If unsure, say Y.
+config HW_RANDOM_MTK
+ tristate "Mediatek Random Number Generator support"
+ depends on HW_RANDOM
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ default y
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Mediatek SoCs.
+
+ To compile this driver as a module, choose M here. the
+ module will be called mtk-rng.
+
+ If unsure, say Y.
+
endif # HW_RANDOM
config UML_RANDOM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 5f52b1e4e7be..59eacb79ac1a 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
+obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
new file mode 100644
index 000000000000..7f99cd52b40e
--- /dev/null
+++ b/drivers/char/hw_random/mtk-rng.c
@@ -0,0 +1,211 @@
+/*
+ * Driver for Mediatek Hardware Random Number Generator
+ *
+ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#define MTK_RNG_DEV KBUILD_MODNAME
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+/* Runtime PM autosuspend timeout: */
+#define RNG_AUTOSUSPEND_TIMEOUT 100
+
+#define USEC_POLL 2
+#define TIMEOUT_POLL 20
+
+#define RNG_CTRL 0x00
+#define RNG_EN BIT(0)
+#define RNG_READY BIT(31)
+
+#define RNG_DATA 0x08
+
+#define to_mtk_rng(p) container_of(p, struct mtk_rng, rng)
+
+struct mtk_rng {
+ void __iomem *base;
+ struct clk *clk;
+ struct hwrng rng;
+};
+
+static int mtk_rng_init(struct hwrng *rng)
+{
+ struct mtk_rng *priv = to_mtk_rng(rng);
+ u32 val;
+ int err;
+
+ err = clk_prepare_enable(priv->clk);
+ if (err)
+ return err;
+
+ val = readl(priv->base + RNG_CTRL);
+ val |= RNG_EN;
+ writel(val, priv->base + RNG_CTRL);
+
+ return 0;
+}
+
+static void mtk_rng_cleanup(struct hwrng *rng)
+{
+ struct mtk_rng *priv = to_mtk_rng(rng);
+ u32 val;
+
+ val = readl(priv->base + RNG_CTRL);
+ val &= ~RNG_EN;
+ writel(val, priv->base + RNG_CTRL);
+
+ clk_disable_unprepare(priv->clk);
+}
+
+static bool mtk_rng_wait_ready(struct hwrng *rng, bool wait)
+{
+ struct mtk_rng *priv = to_mtk_rng(rng);
+ int ready;
+
+ ready = readl(priv->base + RNG_CTRL) & RNG_READY;
+ if (!ready && wait)
+ readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready,
+ ready & RNG_READY, USEC_POLL,
+ TIMEOUT_POLL);
+ return !!ready;
+}
+
+static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ struct mtk_rng *priv = to_mtk_rng(rng);
+ int retval = 0;
+
+ pm_runtime_get_sync((struct device *)priv->rng.priv);
+
+ while (max >= sizeof(u32)) {
+ if (!mtk_rng_wait_ready(rng, wait))
+ break;
+
+ *(u32 *)buf = readl(priv->base + RNG_DATA);
+ retval += sizeof(u32);
+ buf += sizeof(u32);
+ max -= sizeof(u32);
+ }
+
+ pm_runtime_mark_last_busy((struct device *)priv->rng.priv);
+ pm_runtime_put_sync_autosuspend((struct device *)priv->rng.priv);
+
+ return retval || !wait ? retval : -EIO;
+}
+
+static int mtk_rng_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret;
+ struct mtk_rng *priv;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no iomem resource\n");
+ return -ENXIO;
+ }
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->rng.name = pdev->name;
+#ifndef CONFIG_PM
+ priv->rng.init = mtk_rng_init;
+ priv->rng.cleanup = mtk_rng_cleanup;
+#endif
+ priv->rng.read = mtk_rng_read;
+ priv->rng.priv = (unsigned long)&pdev->dev;
+ priv->rng.quality = 900;
+
+ priv->clk = devm_clk_get(&pdev->dev, "rng");
+ if (IS_ERR(priv->clk)) {
+ ret = PTR_ERR(priv->clk);
+ dev_err(&pdev->dev, "no clock for device: %d\n", ret);
+ return ret;
+ }
+
+ priv->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ ret = devm_hwrng_register(&pdev->dev, &priv->rng);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register rng device: %d\n",
+ ret);
+ return ret;
+ }
+
+ dev_set_drvdata(&pdev->dev, priv);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ dev_info(&pdev->dev, "registered RNG driver\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mtk_rng_runtime_suspend(struct device *dev)
+{
+ struct mtk_rng *priv = dev_get_drvdata(dev);
+
+ mtk_rng_cleanup(&priv->rng);
+
+ return 0;
+}
+
+static int mtk_rng_runtime_resume(struct device *dev)
+{
+ struct mtk_rng *priv = dev_get_drvdata(dev);
+
+ return mtk_rng_init(&priv->rng);
+}
+
+static UNIVERSAL_DEV_PM_OPS(mtk_rng_pm_ops, mtk_rng_runtime_suspend,
+ mtk_rng_runtime_resume, NULL);
+#define MTK_RNG_PM_OPS (&mtk_rng_pm_ops)
+#else /* CONFIG_PM */
+#define MTK_RNG_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct of_device_id mtk_rng_match[] = {
+ { .compatible = "mediatek,mt7623-rng" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_rng_match);
+
+static struct platform_driver mtk_rng_driver = {
+ .probe = mtk_rng_probe,
+ .driver = {
+ .name = MTK_RNG_DEV,
+ .pm = MTK_RNG_PM_OPS,
+ .of_match_table = mtk_rng_match,
+ },
+};
+
+module_platform_driver(mtk_rng_driver);
+
+MODULE_DESCRIPTION("Mediatek Random Number Generator Driver");
+MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 5c877ec9c6a8..dd82479bc0a3 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -823,7 +823,7 @@ static int crng_fast_load(const char *cp, size_t len)
if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
crng_init = 1;
wake_up_interruptible(&crng_init_wait);
- pr_notice("random: fast init done\n");
+ pr_info("random: fast init done\n");
}
spin_unlock_irqrestore(&primary_crng.lock, flags);
return 1;
@@ -914,7 +914,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
spin_unlock_irqrestore(&crng->lock, flags);
process_random_ready_list();
wake_up_interruptible(&crng_init_wait);
- pr_notice("random: crng init done\n");
+ pr_info("random: crng init done\n");
if (unseeded_warning.missed) {
pr_notice("random: %d get_random_xx warning(s) missed "
"due to ratelimiting\n",
@@ -1971,6 +1971,24 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
return urandom_read(NULL, buf, count, NULL);
}
+#ifdef CONFIG_NDM_RNG_SEED
+int random_add_entropy(void *p, size_t size, size_t ent_count)
+{
+ int retval = write_pool(&input_pool, p, size);
+
+ if (retval < 0)
+ return retval;
+
+ return credit_entropy_bits_safe(&input_pool, ent_count);
+}
+
+void crng_wait_ready_external(void)
+{
+ if (!crng_ready())
+ crng_wait_ready();
+}
+#endif
+
/********************************************************************
*
* Sysctl interface
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index f042bd2a6a99..1a1dff0c4fba 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -6,6 +6,22 @@ config COMMON_CLK_MEDIATEK
---help---
Mediatek SoCs' clock support.
+config COMMON_CLK_MT2701
+ bool "Clock driver for Mediatek MT2701"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ default ARCH_MEDIATEK
+ ---help---
+ This driver supports Mediatek MT2701 clocks.
+
+config COMMON_CLK_MT7622
+ bool "Clock driver for Mediatek MT7622"
+ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ default ARCH_MEDIATEK && ARM64
+ ---help---
+ This driver supports Mediatek MT7622 clocks.
+
config COMMON_CLK_MT8135
bool "Clock driver for Mediatek MT8135"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 32e7222e7305..92a58b9d1662 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,4 +1,12 @@
-obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
+obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
+obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o clkchk-mt7622.o
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
+obj-y += clk-bringup.o
+
+ifeq ($(CONFIG_DEBUG_FS),y)
+#obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clkdbg.o
+#obj-$(CONFIG_COMMON_CLK_MT7622) += clkdbg-mt7622.o
+endif
diff --git a/drivers/clk/mediatek/clk-bringup.c b/drivers/clk/mediatek/clk-bringup.c
new file mode 100644
index 000000000000..8ca6ad36fabc
--- /dev/null
+++ b/drivers/clk/mediatek/clk-bringup.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+static const struct of_device_id bring_up_id_table[] = {
+ { .compatible = "mediatek,clk-bring-up",},
+ { .compatible = "mediatek,mt8163-bring-up",},
+ { .compatible = "mediatek,mt8173-bring-up",},
+ { },
+};
+
+static int bring_up_probe(struct platform_device *pdev)
+{
+ const int NR_CLKS = 300;
+ char clk_name_buf[16];
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < NR_CLKS; i++) {
+ sprintf(clk_name_buf, "%d", i);
+
+ clk = devm_clk_get(&pdev->dev, clk_name_buf);
+ if (!IS_ERR(clk))
+ clk_prepare_enable(clk);
+ }
+
+ return 0;
+}
+
+static int bring_up_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver bring_up = {
+ .probe = bring_up_probe,
+ .remove = bring_up_remove,
+ .driver = {
+ .name = "bring_up",
+ .owner = THIS_MODULE,
+ .of_match_table = bring_up_id_table,
+ },
+};
+
+builtin_platform_driver(bring_up);
diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c
new file mode 100644
index 000000000000..347d7990b30f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-cpumux.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-cpumux.h"
+
+static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw)
+{
+ return container_of(_hw, struct mtk_clk_cpumux, hw);
+}
+
+static u8 clk_cpumux_get_parent(struct clk_hw *hw)
+{
+ struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw);
+ unsigned int val;
+
+ regmap_read(mux->regmap, mux->reg, &val);
+
+ val >>= mux->shift;
+ val &= mux->mask;
+
+ return val;
+}
+
+static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw);
+ u32 mask, val;
+
+ val = index << mux->shift;
+ mask = mux->mask << mux->shift;
+
+ return regmap_update_bits(mux->regmap, mux->reg, mask, val);
+}
+
+static const struct clk_ops clk_cpumux_ops = {
+ .get_parent = clk_cpumux_get_parent,
+ .set_parent = clk_cpumux_set_parent,
+};
+
+static struct clk __init *
+mtk_clk_register_cpumux(const struct mtk_composite *mux,
+ struct regmap *regmap)
+{
+ struct mtk_clk_cpumux *cpumux;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL);
+ if (!cpumux)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = mux->name;
+ init.ops = &clk_cpumux_ops;
+ init.parent_names = mux->parent_names;
+ init.num_parents = mux->num_parents;
+ init.flags = mux->flags;
+
+ cpumux->reg = mux->mux_reg;
+ cpumux->shift = mux->mux_shift;
+ cpumux->mask = BIT(mux->mux_width) - 1;
+ cpumux->regmap = regmap;
+ cpumux->hw.init = &init;
+
+ clk = clk_register(NULL, &cpumux->hw);
+ if (IS_ERR(clk))
+ kfree(cpumux);
+
+ return clk;
+}
+
+int __init mtk_clk_register_cpumuxes(struct device_node *node,
+ const struct mtk_composite *clks, int num,
+ struct clk_onecell_data *clk_data)
+{
+ int i;
+ struct clk *clk;
+ struct regmap *regmap;
+
+ regmap = syscon_node_to_regmap(node);
+ if (IS_ERR(regmap)) {
+ pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+ PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_composite *mux = &clks[i];
+
+ clk = mtk_clk_register_cpumux(mux, regmap);
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ mux->name, PTR_ERR(clk));
+ continue;
+ }
+
+ clk_data->clks[mux->id] = clk;
+ }
+
+ return 0;
+}
diff --git a/drivers/clk/mediatek/clk-cpumux.h b/drivers/clk/mediatek/clk-cpumux.h
new file mode 100644
index 000000000000..dddaad57454d
--- /dev/null
+++ b/drivers/clk/mediatek/clk-cpumux.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_CPUMUX_H
+#define __DRV_CLK_CPUMUX_H
+
+struct mtk_clk_cpumux {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ u32 reg;
+ u32 mask;
+ u8 shift;
+};
+
+int mtk_clk_register_cpumuxes(struct device_node *node,
+ const struct mtk_composite *clks, int num,
+ struct clk_onecell_data *clk_data);
+
+#endif /* __DRV_CLK_CPUMUX_H */
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index d8787bf444eb..934bf0e45e26 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -61,6 +61,22 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
}
+static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+ u32 cgbit = BIT(cg->bit);
+
+ regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
+}
+
+static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+ u32 cgbit = BIT(cg->bit);
+
+ regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
+}
+
static int mtk_cg_enable(struct clk_hw *hw)
{
mtk_cg_clr_bit(hw);
@@ -85,6 +101,30 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
mtk_cg_clr_bit(hw);
}
+static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_clr_bit_no_setclr(hw);
+
+ return 0;
+}
+
+static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_set_bit_no_setclr(hw);
+}
+
+static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_set_bit_no_setclr(hw);
+
+ return 0;
+}
+
+static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
+{
+ mtk_cg_clr_bit_no_setclr(hw);
+}
+
const struct clk_ops mtk_clk_gate_ops_setclr = {
.is_enabled = mtk_cg_bit_is_cleared,
.enable = mtk_cg_enable,
@@ -97,6 +137,18 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
.disable = mtk_cg_disable_inv,
};
+const struct clk_ops mtk_clk_gate_ops_no_setclr = {
+ .is_enabled = mtk_cg_bit_is_cleared,
+ .enable = mtk_cg_enable_no_setclr,
+ .disable = mtk_cg_disable_no_setclr,
+};
+
+const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
+ .is_enabled = mtk_cg_bit_is_set,
+ .enable = mtk_cg_enable_inv_no_setclr,
+ .disable = mtk_cg_disable_inv_no_setclr,
+};
+
struct clk *mtk_clk_register_gate(
const char *name,
const char *parent_name,
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index b1821603b887..72ef89b3ad7b 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw)
extern const struct clk_ops mtk_clk_gate_ops_setclr;
extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
struct clk *mtk_clk_register_gate(
const char *name,
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
new file mode 100644
index 000000000000..0f8a7c65d597
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -0,0 +1,1404 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+#include "clk-cpumux.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+#define DUMMY_RATE 0
+
+static DEFINE_SPINLOCK(lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] __initconst = {
+ FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m",
+ 108 * MHZ),
+ FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m",
+ 400 * MHZ),
+ FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m",
+ 295750000),
+ FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m",
+ 340 * MHZ),
+ FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m",
+ 340 * MHZ),
+ FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m",
+ 340 * MHZ),
+ FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m",
+ 27 * MHZ),
+ FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m",
+ 416 * MHZ),
+ FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, "dsi0_lntc_dsi", "clk26m",
+ 143 * MHZ),
+ FIXED_CLK(CLK_TOP_HDMI_SCL_RX, "hdmi_scl_rx", "clk26m",
+ 27 * MHZ),
+ FIXED_CLK(CLK_TOP_AUD_EXT1, "aud_ext1", "clk26m",
+ DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_AUD_EXT2, "aud_ext2", "clk26m",
+ DUMMY_RATE),
+ FIXED_CLK(CLK_TOP_NFI1X_PAD, "nfi1x_pad", "clk26m",
+ DUMMY_RATE),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] __initconst = {
+ FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+
+ FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+ FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52),
+ FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108),
+ FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26),
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+ FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1),
+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16),
+ FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
+ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+
+ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+ FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
+
+ FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+ FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2),
+ FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4),
+ FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1),
+
+ FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+
+ FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1),
+ FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1),
+ FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2),
+
+ FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1),
+ FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2),
+ FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4),
+
+ FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1),
+ FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2),
+ FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3),
+
+ FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1),
+
+ FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1),
+ FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4),
+ FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8),
+ FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16),
+ FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24),
+
+ FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3),
+ FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3),
+ FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3),
+ FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1),
+ FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1),
+ FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8),
+ FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793),
+ FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1),
+ FACTOR(CLK_TOP_AXISEL_D4, "axisel_d4", "axi_sel", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "mmpll_d2",
+ "dmpll_d2"
+};
+
+static const char * const mem_parents[] __initconst = {
+ "clk26m",
+ "dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d8"
+};
+
+static const char * const mm_parents[] __initconst = {
+ "clk26m",
+ "vencpll_ck",
+ "syspll1_d2",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll1_d2",
+ "univpll2_d2",
+ "dmpll_ck"
+};
+
+static const char * const pwm_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d4",
+ "univpll3_d2",
+ "univpll1_d4",
+};
+
+static const char * const vdec_parents[] __initconst = {
+ "clk26m",
+ "vdecpll_ck",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "vencpll_ck",
+ "msdcpll_d2",
+ "mmpll_d2"
+};
+
+static const char * const mfg_parents[] __initconst = {
+ "clk26m",
+ "mmpll_ck",
+ "dmpll_x2_ck",
+ "msdcpll_ck",
+ "clk26m",
+ "syspll_d3",
+ "univpll_d3",
+ "univpll1_d2"
+};
+
+static const char * const camtg_parents[] __initconst = {
+ "clk26m",
+ "univpll_d26",
+ "univpll2_d2",
+ "syspll3_d2",
+ "syspll3_d4",
+ "msdcpll_d2",
+ "mmpll_d2"
+};
+
+static const char * const uart_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d8"
+};
+
+static const char * const spi_parents[] __initconst = {
+ "clk26m",
+ "syspll3_d2",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8"
+};
+
+static const char * const usb20_parents[] __initconst = {
+ "clk26m",
+ "univpll1_d8",
+ "univpll3_d4"
+};
+
+static const char * const msdc30_parents[] __initconst = {
+ "clk26m",
+ "msdcpll_d2",
+ "syspll2_d2",
+ "syspll1_d4",
+ "univpll1_d4",
+ "univpll2_d4"
+};
+
+static const char * const audio_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d4",
+ "syspll3_d2",
+ "syspll4_d2",
+ "univpll3_d2",
+ "univpll2_d4"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d8",
+ "syspll2_d4",
+ "syspll4_d2",
+ "syspll3_d4",
+ "syspll2_d8",
+ "syspll1_d16",
+ "univpll3_d4",
+ "univpll_d26",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const scp_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d8",
+ "dmpll_d2",
+ "dmpll_d4"
+};
+
+static const char * const dpi0_parents[] __initconst = {
+ "clk26m",
+ "mipipll",
+ "mipipll_d2",
+ "mipipll_d4",
+ "clk26m",
+ "tvdpll_ck",
+ "tvdpll_d2",
+ "tvdpll_d4"
+};
+
+static const char * const dpi1_parents[] __initconst = {
+ "clk26m",
+ "tvdpll_ck",
+ "tvdpll_d2",
+ "tvdpll_d4"
+};
+
+static const char * const tve_parents[] __initconst = {
+ "clk26m",
+ "mipipll",
+ "mipipll_d2",
+ "mipipll_d4",
+ "clk26m",
+ "tvdpll_ck",
+ "tvdpll_d2",
+ "tvdpll_d4"
+};
+
+static const char * const hdmi_parents[] __initconst = {
+ "clk26m",
+ "hdmitx_dig_cts",
+ "hdmipll_ck",
+ "hdmipll_d2",
+ "hdmipll_d3"
+};
+
+static const char * const apll_parents[] __initconst = {
+ "clk26m",
+ "audpll",
+ "audpll_d4",
+ "audpll_d8",
+ "audpll_d16",
+ "audpll_d24",
+ "clk26m",
+ "clk26m"
+};
+
+static const char * const rtc_parents[] __initconst = {
+ "32k_internal",
+ "32k_external",
+ "clk26m",
+ "univpll3_d8"
+};
+
+static const char * const nfi2x_parents[] __initconst = {
+ "clk26m",
+ "syspll2_d2",
+ "syspll_d7",
+ "univpll3_d2",
+ "syspll2_d4",
+ "univpll3_d4",
+ "syspll4_d4",
+ "clk26m"
+};
+
+static const char * const emmc_hclk_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll1_d4",
+ "syspll2_d2"
+};
+
+static const char * const flash_parents[] __initconst = {
+ "clk26m_d8",
+ "clk26m",
+ "syspll2_d8",
+ "syspll3_d4",
+ "univpll3_d4",
+ "syspll4_d2",
+ "syspll2_d4",
+ "univpll2_d4"
+};
+
+static const char * const di_parents[] __initconst = {
+ "clk26m",
+ "tvd2pll_ck",
+ "tvd2pll_d2",
+ "clk26m"
+};
+
+static const char * const nr_osd_parents[] __initconst = {
+ "clk26m",
+ "vencpll_ck",
+ "syspll1_d2",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll1_d2",
+ "univpll2_d2",
+ "dmpll_ck"
+};
+
+static const char * const hdmirx_bist_parents[] __initconst = {
+ "clk26m",
+ "syspll_d3",
+ "clk26m",
+ "syspll1_d16",
+ "syspll4_d2",
+ "syspll1_d4",
+ "vencpll_ck",
+ "clk26m"
+};
+
+static const char * const intdir_parents[] __initconst = {
+ "clk26m",
+ "mmpll_ck",
+ "syspll_d2",
+ "univpll_d2"
+};
+
+static const char * const asm_parents[] __initconst = {
+ "clk26m",
+ "univpll2_d4",
+ "univpll2_d2",
+ "syspll_d5"
+};
+
+static const char * const ms_card_parents[] __initconst = {
+ "clk26m",
+ "univpll3_d8",
+ "syspll4_d4"
+};
+
+static const char * const ethif_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll1_d2",
+ "dmpll_ck",
+ "dmpll_d2"
+};
+
+static const char * const hdmirx_parents[] __initconst = {
+ "clk26m",
+ "univpll_d52"
+};
+
+static const char * const cmsys_parents[] __initconst = {
+ "clk26m",
+ "syspll1_d2",
+ "univpll1_d2",
+ "univpll_d5",
+ "syspll_d5",
+ "syspll2_d2",
+ "syspll1_d4",
+ "syspll3_d2",
+ "syspll2_d4",
+ "syspll1_d8",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m",
+ "clk26m"
+};
+
+static const char * const clk_8bdac_parents[] __initconst = {
+ "32k_internal",
+ "8bdac_ck",
+ "clk26m",
+ "clk26m"
+};
+
+static const char * const aud2dvd_parents[] __initconst = {
+ "a1sys_hp_ck",
+ "a2sys_hp_ck"
+};
+
+static const char * const padmclk_parents[] __initconst = {
+ "clk26m",
+ "univpll_d26",
+ "univpll_d52",
+ "univpll_d108",
+ "univpll2_d8",
+ "univpll2_d16",
+ "univpll2_d32"
+};
+
+static const char * const aud_mux_parents[] __initconst = {
+ "clk26m",
+ "aud1pll_98m_ck",
+ "aud2pll_90m_ck",
+ "hadds2pll_98m",
+ "audio_ext1_ck",
+ "audio_ext2_ck"
+};
+
+static const char * const aud_src_parents[] __initconst = {
+ "aud_mux1_sel",
+ "aud_mux2_sel"
+};
+
+static const char * const cpu_parents[] __initconst = {
+ "clk26m",
+ "armpll",
+ "mainpll",
+ "mmpll"
+};
+
+static const struct mtk_composite cpu_muxes[] __initconst = {
+ MUX(CLK_INFRA_CPUSEL, "infra_cpu_sel", cpu_parents, 0x0000, 2, 2),
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+ MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+ 0x0040, 0, 3, INVALID_MUX_GATE_BIT),
+ MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
+ 0x0040, 8, 1, 15),
+ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
+ 0x0040, 16, 1, 23),
+ MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
+ 0x0040, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
+ 0x0050, 0, 2, 7),
+ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents,
+ 0x0050, 8, 4, 15),
+ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents,
+ 0x0050, 16, 3, 23),
+ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents,
+ 0x0050, 24, 3, 31),
+ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
+ 0x0060, 0, 1, 7),
+
+ MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents,
+ 0x0060, 8, 3, 15),
+ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents,
+ 0x0060, 16, 2, 23),
+ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents,
+ 0x0060, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents,
+ 0x0070, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents,
+ 0x0070, 8, 3, 15),
+ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents,
+ 0x0070, 16, 1, 23),
+ MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+ 0x0070, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
+ 0x0080, 0, 4, 7),
+ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents,
+ 0x0080, 8, 2, 15),
+ MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents,
+ 0x0080, 16, 3, 23),
+ MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents,
+ 0x0080, 24, 2, 31),
+
+ MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents,
+ 0x0090, 0, 3, 7),
+ MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents,
+ 0x0090, 8, 2, 15),
+ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents,
+ 0x0090, 16, 3, 23),
+
+ MUX_GATE(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents,
+ 0x00A0, 0, 2, 7),
+ MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents,
+ 0x00A0, 8, 3, 15),
+ MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents,
+ 0x00A0, 24, 2, 31),
+
+ MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
+ 0x00B0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents,
+ 0x00B0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents,
+ 0x00B0, 16, 3, 23),
+ MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents,
+ 0x00B0, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel",
+ hdmirx_bist_parents, 0x00C0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
+ 0x00C0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents,
+ 0x00C0, 16, 2, 23),
+ MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents,
+ 0x00C0, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents,
+ 0x00D0, 0, 2, 7),
+ MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents,
+ 0x00D0, 16, 2, 23),
+ MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents,
+ 0x00D0, 24, 3, 31),
+
+ MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents,
+ 0x00E0, 0, 1, 7),
+ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents,
+ 0x00E0, 8, 3, 15),
+ MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents,
+ 0x00E0, 16, 4, 23),
+
+ MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents,
+ 0x00E0, 24, 3, 31),
+ MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents,
+ 0x00F0, 0, 3, 7),
+ MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents,
+ 0x00F0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents,
+ 0x00F0, 16, 1, 23),
+
+ MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents,
+ 0x0100, 0, 3),
+
+ MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents,
+ 0x012c, 0, 3),
+ MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents,
+ 0x012c, 3, 3),
+ MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents,
+ 0x012c, 6, 3),
+ MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents,
+ 0x012c, 15, 1, 23),
+ MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents,
+ 0x012c, 16, 1, 24),
+ MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents,
+ 0x012c, 17, 1, 25),
+ MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents,
+ 0x012c, 18, 1, 26),
+ MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents,
+ 0x012c, 19, 1, 27),
+ MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents,
+ 0x012c, 20, 1, 28),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] __initconst = {
+ DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext1",
+ 0x0120, 0, 8),
+ DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext2",
+ 0x0120, 8, 8),
+ DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel",
+ 0x0120, 16, 8),
+ DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel",
+ 0x0120, 24, 8),
+ DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel",
+ 0x0124, 0, 8),
+ DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel",
+ 0x0124, 8, 8),
+ DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel",
+ 0x0124, 16, 8),
+ DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel",
+ 0x0124, 24, 8),
+ DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel",
+ 0x0128, 0, 8),
+ DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel",
+ 0x0128, 8, 8),
+};
+
+static const struct mtk_gate_regs top_aud_cg_regs __initconst = {
+ .sta_ofs = 0x012C,
+};
+
+#define GATE_TOP_AUD(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top_aud_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+static const struct mtk_gate top_clks[] __initconst = {
+ GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div",
+ 21),
+ GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div",
+ 22),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div",
+ 23),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div",
+ 24),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div",
+ 25),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div",
+ 26),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div",
+ 27),
+ GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div",
+ 28),
+};
+
+static struct clk_onecell_data *top_clk_data __initdata;
+static struct clk_onecell_data *pll_clk_data __initdata;
+
+static void __init mtk_clk_enable_critical(void)
+{
+ if (!top_clk_data || !pll_clk_data)
+ return;
+
+ clk_prepare_enable(pll_clk_data->clks[CLK_APMIXED_ARMPLL]);
+ clk_prepare_enable(top_clk_data->clks[CLK_TOP_AXI_SEL]);
+ clk_prepare_enable(top_clk_data->clks[CLK_TOP_MEM_SEL]);
+ clk_prepare_enable(top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]);
+ clk_prepare_enable(top_clk_data->clks[CLK_TOP_RTC_SEL]);
+}
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ int r;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+
+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+ clk_data);
+
+ mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+ clk_data);
+
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
+ base, &lock, clk_data);
+
+ mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
+ base, &lock, clk_data);
+
+ mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_clk_enable_critical();
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt2701-topckgen", mtk_topckgen_init);
+
+static const struct mtk_gate_regs infra_cg_regs __initconst = {
+ .set_ofs = 0x0040,
+ .clr_ofs = 0x0044,
+ .sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate infra_clks[] __initconst = {
+ GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0),
+ GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1),
+ GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2),
+ GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2pll_294m", 4),
+ GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk26m", 5),
+ GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6),
+ GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7),
+ GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+ GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12),
+ GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13),
+ GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14),
+ GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15),
+ GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+ GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18),
+ GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19),
+ GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+ GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23),
+ GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24),
+};
+
+static const struct mtk_fixed_factor infra_fixed_divs[] __initconst = {
+ FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+
+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+ clk_data);
+ mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+ clk_data);
+
+ mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt2701-infracfg", mtk_infrasys_init);
+
+static const struct mtk_gate_regs peri0_cg_regs __initconst = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x0010,
+ .sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs __initconst = {
+ .set_ofs = 0x000c,
+ .clr_ofs = 0x0014,
+ .sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_PERI1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate peri_clks[] __initconst = {
+ GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31),
+ GATE_PERI0(CLK_PERI_ETH, "eth_ck", "clk26m", 30),
+ GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29),
+ GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28),
+ GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27),
+ GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26),
+ GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25),
+ GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24),
+ GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23),
+ GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22),
+ GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21),
+ GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20),
+ GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19),
+ GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18),
+ GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17),
+ GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16),
+ GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15),
+ GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14),
+ GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13),
+ GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+ GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+ GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+ GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+ GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axisel_d4", 8),
+ GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axisel_d4", 7),
+ GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axisel_d4", 6),
+ GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axisel_d4", 5),
+ GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axisel_d4", 4),
+ GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axisel_d4", 3),
+ GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axisel_d4", 2),
+ GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+ GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0),
+
+ GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card_sel", 11),
+ GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10),
+ GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9),
+ GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8),
+ GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7),
+ GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6),
+ GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5),
+ GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi1x_pad", 4),
+ GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi1x_pad", 3),
+ GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2),
+ GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1),
+ GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+ "clk26m",
+ "uart_sel",
+};
+
+static const struct mtk_composite peri_muxs[] __initconst = {
+ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents,
+ 0x40c, 0, 1),
+ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents,
+ 0x40c, 1, 1),
+ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents,
+ 0x40c, 2, 1),
+ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents,
+ 0x40c, 3, 1),
+};
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ void __iomem *base;
+ int r;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+
+ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+ clk_data);
+
+ mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base,
+ &lock, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 2, 0x0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt2701-pericfg", mtk_pericfg_init);
+
+static const struct mtk_gate_regs disp0_cg_regs __initconst = {
+ .set_ofs = 0x0104,
+ .clr_ofs = 0x0108,
+ .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs disp1_cg_regs __initconst = {
+ .set_ofs = 0x0114,
+ .clr_ofs = 0x0118,
+ .sta_ofs = 0x0110,
+};
+
+#define GATE_DISP0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &disp0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_DISP1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &disp1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate mm_clks[] __initconst = {
+ GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
+ GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+ GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2),
+ GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3),
+ GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4),
+ GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5),
+ GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6),
+ GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7),
+ GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8),
+ GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+ GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10),
+ GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+ GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12),
+ GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13),
+ GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14),
+ GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15),
+ GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16),
+ GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17),
+ GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18),
+ GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+ GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20),
+ GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0),
+ GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1),
+ GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
+ GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
+ GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
+ GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
+ GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
+ GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
+ GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
+ GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
+ GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
+ GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
+ GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
+};
+
+static void __init mtk_mmsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+
+ mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+
+static const struct mtk_gate_regs img_cg_regs __initconst = {
+ .set_ofs = 0x0004,
+ .clr_ofs = 0x0008,
+ .sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &img_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate img_clks[] __initconst = {
+ GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
+ GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
+ GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
+ GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6),
+ GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8),
+ GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9),
+};
+
+static void __init mtk_imgsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+
+ mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+
+static const struct mtk_gate_regs vdec0_cg_regs __initconst = {
+ .set_ofs = 0x0000,
+ .clr_ofs = 0x0004,
+ .sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs __initconst = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x000c,
+ .sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate vdec_clks[] __initconst = {
+ GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
+};
+
+static void __init mtk_vdecsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+
+ mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+
+static const struct mtk_gate_regs hif_cg_regs __initconst = {
+ .sta_ofs = 0x0030,
+};
+
+#define GATE_HIF(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &hif_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate hif_clks[] __initconst = {
+ GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21),
+ GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22),
+ GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24),
+ GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25),
+ GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26),
+};
+
+static void __init mtk_hifsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
+
+ mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 1, 0x34);
+}
+
+static const struct mtk_gate_regs eth_cg_regs __initconst = {
+ .sta_ofs = 0x0030,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &eth_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate eth_clks[] __initconst = {
+ GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5),
+ GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6),
+ GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7),
+ GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8),
+ GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11),
+ GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14),
+ GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17),
+ GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29),
+};
+
+static void __init mtk_ethsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
+
+ mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 1, 0x34);
+}
+
+static const struct mtk_gate_regs bdp0_cg_regs __initconst = {
+ .set_ofs = 0x0104,
+ .clr_ofs = 0x0108,
+ .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs bdp1_cg_regs __initconst = {
+ .set_ofs = 0x0114,
+ .clr_ofs = 0x0118,
+ .sta_ofs = 0x0110,
+};
+
+#define GATE_BDP0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &bdp0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+#define GATE_BDP1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &bdp1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate bdp_clks[] __initconst = {
+ GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
+ GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
+ GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
+ GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3),
+ GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4),
+ GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5),
+ GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6),
+ GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7),
+ GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8),
+ GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9),
+ GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10),
+ GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11),
+ GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12),
+ GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13),
+ GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14),
+ GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15),
+ GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16),
+ GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17),
+ GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18),
+ GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19),
+ GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20),
+ GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21),
+ GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22),
+ GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23),
+ GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24),
+ GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25),
+ GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26),
+ GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27),
+ GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28),
+ GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29),
+ GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30),
+ GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31),
+ GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0),
+ GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1),
+ GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2),
+ GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3),
+ GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4),
+ GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5),
+ GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6),
+ GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7),
+ GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8),
+ GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9),
+ GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10),
+ GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11),
+ GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
+ GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
+ GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
+ GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
+ GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
+};
+
+static void __init mtk_bdpsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
+
+ mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+
+#define MT8590_PLL_FMAX (2000 * MHZ)
+#define CON0_MT8590_RST_BAR BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
+ _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = CON0_MT8590_RST_BAR, \
+ .fmax = MT8590_PLL_FMAX, \
+ .pcwbits = _pcwbits, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ }
+
+static const struct mtk_pll_data apmixed_plls[] = {
+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001, 0,
+ 21, 0x204, 24, 0x0, 0x204, 0),
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001,
+ HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0),
+ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001,
+ HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14),
+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0,
+ 21, 0x230, 4, 0x0, 0x234, 0),
+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0,
+ 21, 0x240, 4, 0x0, 0x244, 0),
+ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0,
+ 21, 0x250, 4, 0x0, 0x254, 0),
+ PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0,
+ 31, 0x270, 4, 0x0, 0x274, 0),
+ PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0,
+ 31, 0x280, 4, 0x0, 0x284, 0),
+ PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0,
+ 31, 0x290, 4, 0x0, 0x294, 0),
+ PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0,
+ 31, 0x2a0, 4, 0x0, 0x2a4, 0),
+ PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0,
+ 31, 0x2b0, 4, 0x0, 0x2b4, 0),
+ PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0,
+ 31, 0x2c0, 4, 0x0, 0x2c4, 0),
+ PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0,
+ 21, 0x2d0, 4, 0x0, 0x2d4, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ struct clk *clk;
+ void __iomem *base;
+ int r;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+ if (!clk_data)
+ return;
+
+ mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls),
+ clk_data);
+
+ clk = clk_register_divider(NULL, "hdmi_ref", "tvdpll", 0, base + 0x40,
+ 16, 3, CLK_DIVIDER_POWER_OF_TWO, NULL);
+
+ clk_data->clks[CLK_APMIXED_HDMI_REF] = clk;
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_clk_enable_critical();
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt2701-apmixedsys",
+ mtk_apmixedsys_init);
+
+static const struct of_device_id of_clk_match_tbl[] = {
+ {
+ .compatible = "mediatek,mt2701-mmsys",
+ .data = mtk_mmsys_init,
+ }, {
+ .compatible = "mediatek,mt2701-imgsys",
+ .data = mtk_imgsys_init,
+ }, {
+ .compatible = "mediatek,mt2701-vdecsys",
+ .data = mtk_vdecsys_init,
+ }, {
+ .compatible = "mediatek,mt2701-hifsys",
+ .data = mtk_hifsys_init,
+ }, {
+ .compatible = "mediatek,mt2701-ethsys",
+ .data = mtk_ethsys_init,
+ }, {
+ .compatible = "mediatek,mt2701-bdpsys",
+ .data = mtk_bdpsys_init,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int __init clk_probe(struct platform_device *pdev)
+{
+ void (*clk_init)(struct device_node *);
+ const struct of_device_id *of_id;
+
+ of_id = of_match_node(of_clk_match_tbl, pdev->dev.of_node);
+ if (!of_id || !of_id->data)
+ return -EINVAL;
+
+ clk_init = of_id->data;
+ clk_init(pdev->dev.of_node);
+
+ return 0;
+}
+
+static struct platform_driver clk_drv = {
+ .driver = {
+ .name = "mtk-clk",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(of_clk_match_tbl),
+ },
+};
+
+builtin_platform_driver_probe(clk_drv, clk_probe);
diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c
new file mode 100644
index 000000000000..8d0dd8fc146e
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt7622.c
@@ -0,0 +1,958 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt7622-clk.h>
+
+static DEFINE_SPINLOCK(mt7622_clk_lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] __initconst = {
+ FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal", 31250000),
+ FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal", 31250000),
+ FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal", 125000000),
+ FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal", 125000000),
+ FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal", 250000000),
+ FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal", 250000000),
+ FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal", 33333333),
+ FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal", 50000000),
+ FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal", 50000000),
+ FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal", 50000000),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+ FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4),
+ FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500),
+ FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125),
+ FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500),
+ FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1),
+ FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024),
+ FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1),
+ FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1),
+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4),
+ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8),
+ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16),
+ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12),
+ FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24),
+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10),
+ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20),
+ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14),
+ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28),
+ FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112),
+ FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4),
+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8),
+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16),
+ FACTOR(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32),
+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6),
+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12),
+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24),
+ FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48),
+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10),
+ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20),
+ FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80),
+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320),
+ FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25),
+ FACTOR(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1),
+ FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2),
+ FACTOR(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1),
+ FACTOR(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1),
+ FACTOR(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2),
+ FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4),
+ FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1),
+ FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1),
+ FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1),
+};
+
+static const char * const axi_parents[] __initconst = {
+ "clkxtal",
+ "syspll1_d2",
+ "syspll_d5",
+ "syspll1_d4",
+ "univpll_d5",
+ "univpll2_d2",
+ "univpll_d7"
+};
+
+static const char * const mem_parents[] __initconst = {
+ "clkxtal",
+ "dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+ "clkxtal",
+ "syspll1_d8"
+};
+
+static const char * const eth_parents[] __initconst = {
+ "clkxtal",
+ "syspll1_d2",
+ "univpll1_d2",
+ "syspll1_d4",
+ "univpll_d5",
+ "clk_null",
+ "univpll_d7"
+};
+
+static const char * const pwm_parents[] __initconst = {
+ "clkxtal",
+ "univpll2_d4"
+};
+
+static const char * const f10m_ref_parents[] __initconst = {
+ "clkxtal",
+ "syspll4_d16"
+};
+
+static const char * const nfi_infra_parents[] __initconst = {
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "clkxtal",
+ "univpll2_d8",
+ "syspll1_d8",
+ "univpll1_d8",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll3_d2",
+ "syspll1_d4"
+};
+
+static const char * const flash_parents[] __initconst = {
+ "clkxtal",
+ "univpll_d80_d4",
+ "syspll2_d8",
+ "syspll3_d4",
+ "univpll3_d4",
+ "univpll1_d8",
+ "syspll2_d4",
+ "univpll2_d4"
+};
+
+static const char * const uart_parents[] __initconst = {
+ "clkxtal",
+ "univpll2_d8"
+};
+
+static const char * const spi0_parents[] __initconst = {
+ "clkxtal",
+ "syspll3_d2",
+ "clkxtal",
+ "syspll2_d4",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8",
+ "clkxtal"
+};
+
+static const char * const spi1_parents[] __initconst = {
+ "clkxtal",
+ "syspll3_d2",
+ "clkxtal",
+ "syspll4_d4",
+ "syspll4_d2",
+ "univpll2_d4",
+ "univpll1_d8",
+ "clkxtal"
+};
+
+static const char * const msdc30_0_parents[] __initconst = {
+ "clkxtal",
+ "univpll2_d16",
+ "univ48m"
+};
+
+static const char * const a1sys_hp_parents[] __initconst = {
+ "clkxtal",
+ "aud1pll_ck",
+ "aud2pll_ck",
+ "clkxtal"
+};
+
+static const char * const intdir_parents[] __initconst = {
+ "clkxtal",
+ "syspll_d2",
+ "univpll_d2",
+ "sgmiipll_ck"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+ "clkxtal",
+ "syspll1_d4",
+ "syspll4_d2",
+ "syspll3_d2"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+ "clkxtal",
+ "clk_null",
+ "clk_null",
+ "clk_null",
+ "clk_null",
+ "univpll2_d16"
+};
+
+static const char * const atb_parents[] __initconst = {
+ "clkxtal",
+ "syspll1_d2",
+ "syspll_d5"
+};
+
+static const char * const audio_parents[] __initconst = {
+ "clkxtal",
+ "syspll3_d4",
+ "syspll4_d4",
+ "univpll1_d16"
+};
+
+static const char * const usb20_parents[] __initconst = {
+ "clkxtal",
+ "univpll3_d4",
+ "syspll1_d8",
+ "clkxtal"
+};
+
+static const char * const aud1_parents[] __initconst = {
+ "clkxtal",
+ "aud1pll_ck"
+};
+
+static const char * const aud2_parents[] __initconst = {
+ "clkxtal",
+ "aud2pll_ck"
+};
+
+static const char * const asm_l_parents[] __initconst = {
+ "clkxtal",
+ "syspll_d5",
+ "univpll2_d2",
+ "univpll2_d4"
+};
+
+static const char * const apll1_ck_parents[] __initconst = {
+ "aud1_sel",
+ "aud2_sel"
+};
+
+static struct mtk_composite top_muxes[] __initdata = {
+ /* CLK_CFG_0 */
+ MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x040, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, 8, 1, 15),
+ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x040, 16, 1, 23),
+ MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, 0x040, 24, 3, 31),
+ /* CLK_CFG_1 */
+ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x050, 0, 2, 7),
+ MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents, 0x050, 8, 1, 15),
+ MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents, 0x050, 16, 4, 23),
+ MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, 0x050, 24, 3, 31),
+ /* CLK_CFG_2 */
+ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x060, 0, 1, 7),
+ MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents, 0x060, 8, 3, 15),
+ MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents, 0x060, 16, 3, 23),
+ MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents, 0x060, 24, 3, 31),
+ /* CLK_CFG_3 */
+ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents, 0x070, 0, 3, 7),
+ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_0_parents, 0x070, 8, 3, 15),
+ MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", a1sys_hp_parents, 0x070, 16, 2, 23),
+ MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", a1sys_hp_parents, 0x070, 24, 2, 31),
+ /* CLK_CFG_4 */
+ MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents, 0x080, 0, 2, 7),
+ MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x080, 8, 2, 15),
+ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x080, 16, 3, 23),
+ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", ddrphycfg_parents, 0x080, 24, 2, 31),
+ /* CLK_CFG_5 */
+ MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x090, 0, 2, 7),
+ MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", eth_parents, 0x090, 8, 3, 15),
+ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x090, 16, 2, 23),
+ MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents, 0x090, 24, 2, 31),
+ /* CLK_CFG_6 */
+ MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, 0x0A0, 0, 1, 7),
+ MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, 0x0A0, 8, 1, 15),
+ MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", f10m_ref_parents, 0x0A0, 16, 1, 23),
+ MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", f10m_ref_parents, 0x0A0, 24, 1, 31),
+ /* CLK_CFG_7 */
+ MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", asm_l_parents, 0x0B0, 0, 2, 7),
+ MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_l_parents, 0x0B0, 8, 2, 15),
+ MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_l_parents, 0x0B0, 16, 2, 23),
+ /* CLK_AUDDIV_0 */
+ MUX(CLK_TOP_APLL1_SEL, "apll1_ck_sel", apll1_ck_parents, 0x120, 6, 1),
+ MUX(CLK_TOP_APLL2_SEL, "apll2_ck_sel", apll1_ck_parents, 0x120, 7, 1),
+ MUX(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", apll1_ck_parents, 0x120, 8, 1),
+ MUX(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", apll1_ck_parents, 0x120, 9, 1),
+ MUX(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", apll1_ck_parents, 0x120, 10, 1),
+ MUX(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", apll1_ck_parents, 0x120, 11, 1),
+};
+
+static const char * const peribus_ck_parents[] __initconst = {
+ "syspll1_d8",
+ "syspll1_d4"
+};
+
+static struct mtk_composite peri_muxes[] __initdata = {
+ /* PERI_GLOBALCON_CKSEL */
+ MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1),
+};
+
+static const char * const infra_mux1_parents[] __initconst = {
+ "clkxtal",
+ "armpll",
+ "main_core_en",
+ "armpll"
+};
+
+static struct mtk_composite infra_muxes[] __initdata = {
+ /* INFRA_TOPCKGEN_CKMUXSEL */
+ MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents, 0x000, 2, 2),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+ DIV_ADJ(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_sel", 0x120, 24, 3),
+ DIV_ADJ(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_sel", 0x120, 28, 3),
+ DIV_ADJ(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_sel", 0x124, 0, 7),
+ DIV_ADJ(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_sel", 0x124, 8, 7),
+ DIV_ADJ(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "aud_i2s2_mck", 0x124, 16, 7),
+ DIV_ADJ(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_sel", 0x124, 24, 7),
+ DIV_ADJ(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel", 0x128, 8, 7),
+ DIV_ADJ(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel", 0x128, 24, 7),
+};
+
+static const struct mtk_gate_regs top0_cg_regs = {
+ .set_ofs = 0x120,
+ .clr_ofs = 0x120,
+ .sta_ofs = 0x120,
+};
+
+static const struct mtk_gate_regs top1_cg_regs = {
+ .set_ofs = 0x128,
+ .clr_ofs = 0x128,
+ .sta_ofs = 0x128,
+};
+
+#define GATE_TOP0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+#define GATE_TOP1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &top1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+static const struct mtk_gate top_clks[] __initconst = {
+ /* TOP0 */
+ GATE_TOP0(CLK_TOP_APLL1_DIV_PD, "apll1_ck_div_pd", "apll1_ck_div", 0),
+ GATE_TOP0(CLK_TOP_APLL2_DIV_PD, "apll2_ck_div_pd", "apll2_ck_div", 1),
+ GATE_TOP0(CLK_TOP_I2S0_MCK_DIV_PD, "i2s0_mck_div_pd", "i2s0_mck_div", 2),
+ GATE_TOP0(CLK_TOP_I2S1_MCK_DIV_PD, "i2s1_mck_div_pd", "i2s1_mck_div", 3),
+ GATE_TOP0(CLK_TOP_I2S2_MCK_DIV_PD, "i2s2_mck_div_pd", "i2s2_mck_div", 4),
+ GATE_TOP0(CLK_TOP_I2S3_MCK_DIV_PD, "i2s3_mck_div_pd", "i2s3_mck_div", 5),
+ /* TOP1 */
+ GATE_TOP1(CLK_TOP_A1SYS_HP_DIV_PD, "a1sys_div_pd", "a1sys_div", 0),
+ GATE_TOP1(CLK_TOP_A2SYS_HP_DIV_PD, "a2sys_div_pd", "a2sys_div", 16),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+ .set_ofs = 0x40,
+ .clr_ofs = 0x44,
+ .sta_ofs = 0x48,
+};
+
+#define GATE_INFRA(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &infra_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate infra_clks[] __initconst = {
+ GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0),
+ GATE_INFRA(CLK_INFRA_TRNG_PD, "infra_trng_pd", "axi_sel", 2),
+ GATE_INFRA(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 5),
+ GATE_INFRA(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 16),
+ GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 18),
+ GATE_INFRA(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 22),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x10,
+ .sta_ofs = 0x18,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+ .set_ofs = 0xC,
+ .clr_ofs = 0x14,
+ .sta_ofs = 0x1C,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_PERI1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &peri1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate peri_clks[] __initconst = {
+ /* PERI0 */
+ GATE_PERI0(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", 1),
+ GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", 2),
+ GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", 3),
+ GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", 4),
+ GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", 5),
+ GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", 6),
+ GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", 7),
+ GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", 8),
+ GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", 9),
+ GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", 12),
+ GATE_PERI0(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", 13),
+ GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", 14),
+ GATE_PERI0(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", 17),
+ GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", 18),
+ GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", 19),
+ GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", 20),
+ GATE_PERI0(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", 21),
+ GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", 22),
+ GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", 23),
+ GATE_PERI0(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", 24),
+ GATE_PERI0(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", 25),
+ GATE_PERI0(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", 26),
+ GATE_PERI0(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", 27),
+ GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", 28),
+ GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "nfi_infra_sel", 29),
+ GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", 30),
+ GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", 31),
+ /* PERI1 */
+ GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", 1),
+ GATE_PERI1(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", 2),
+};
+
+static const struct mtk_gate_regs apmixed_cg_regs = {
+ .set_ofs = 0x8,
+ .clr_ofs = 0x8,
+ .sta_ofs = 0x8,
+};
+
+#define GATE_APMIXED(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &apmixed_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate apmixed_clks[] __initconst = {
+ GATE_APMIXED(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5),
+};
+
+static const struct mtk_gate_regs audio0_cg_regs = {
+ .set_ofs = 0x0,
+ .clr_ofs = 0x0,
+ .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs audio1_cg_regs = {
+ .set_ofs = 0x10,
+ .clr_ofs = 0x10,
+ .sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs audio2_cg_regs = {
+ .set_ofs = 0x14,
+ .clr_ofs = 0x14,
+ .sta_ofs = 0x14,
+};
+
+static const struct mtk_gate_regs audio3_cg_regs = {
+ .set_ofs = 0x634,
+ .clr_ofs = 0x634,
+ .sta_ofs = 0x634,
+};
+
+#define GATE_AUDIO0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &audio0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+#define GATE_AUDIO1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &audio1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+#define GATE_AUDIO2(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &audio2_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+#define GATE_AUDIO3(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &audio3_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr, \
+ }
+
+static const struct mtk_gate audio_clks[] __initconst = {
+ /* AUDIO0 */
+ GATE_AUDIO0(CLK_AUDIO_AFE, "audio_afe", "rtc", 2),
+ GATE_AUDIO0(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 20),
+ GATE_AUDIO0(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 21),
+ GATE_AUDIO0(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 23),
+ /* AUDIO1 */
+ GATE_AUDIO1(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0),
+ GATE_AUDIO1(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 1),
+ GATE_AUDIO1(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 2),
+ GATE_AUDIO1(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 3),
+ GATE_AUDIO1(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 6),
+ GATE_AUDIO1(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 7),
+ GATE_AUDIO1(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 8),
+ GATE_AUDIO1(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 9),
+ GATE_AUDIO1(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 12),
+ GATE_AUDIO1(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 13),
+ GATE_AUDIO1(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 14),
+ GATE_AUDIO1(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 15),
+ GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20),
+ GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21),
+ GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22),
+ /* AUDIO2 */
+ GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0),
+ GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1),
+ GATE_AUDIO2(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 2),
+ GATE_AUDIO2(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 3),
+ GATE_AUDIO2(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 4),
+ GATE_AUDIO2(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 5),
+ GATE_AUDIO2(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 6),
+ GATE_AUDIO2(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 7),
+ GATE_AUDIO2(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 8),
+ GATE_AUDIO2(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 9),
+ GATE_AUDIO2(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 10),
+ GATE_AUDIO2(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 11),
+ GATE_AUDIO2(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 12),
+ GATE_AUDIO2(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 13),
+ GATE_AUDIO2(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 14),
+ GATE_AUDIO2(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 15),
+ GATE_AUDIO2(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 16),
+ GATE_AUDIO2(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 17),
+ /* AUDIO3 */
+ GATE_AUDIO3(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 2),
+ GATE_AUDIO3(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 3),
+ GATE_AUDIO3(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 6),
+ GATE_AUDIO3(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 7),
+ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10),
+ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11),
+ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12),
+ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13),
+ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14),
+};
+
+static const struct mtk_gate_regs ssusb_cg_regs = {
+ .set_ofs = 0x30,
+ .clr_ofs = 0x30,
+ .sta_ofs = 0x30,
+};
+
+#define GATE_SSUSB(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &ssusb_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate ssusb_clks[] __initconst = {
+ GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p", "to_u2_phy_1p", 0),
+ GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1),
+ GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5),
+ GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6),
+ GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 7),
+ GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 8),
+};
+
+static const struct mtk_gate_regs pcie_cg_regs = {
+ .set_ofs = 0x30,
+ .clr_ofs = 0x30,
+ .sta_ofs = 0x30,
+};
+
+#define GATE_PCIE(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &pcie_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate pcie_clks[] __initconst = {
+ GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12),
+ GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13),
+ GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 14),
+ GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 15),
+ GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16),
+ GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17),
+ GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18),
+ GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19),
+ GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 20),
+ GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 21),
+ GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22),
+ GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23),
+ GATE_PCIE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 26),
+ GATE_PCIE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 27),
+ GATE_PCIE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 28),
+ GATE_PCIE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 29),
+ GATE_PCIE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 30),
+};
+
+static const struct mtk_gate_regs eth_cg_regs = {
+ .set_ofs = 0x30,
+ .clr_ofs = 0x30,
+ .sta_ofs = 0x30,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &eth_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate eth_clks[] __initconst = {
+ GATE_ETH(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 5),
+ GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 6),
+ GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7),
+ GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8),
+ GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9),
+};
+
+static const struct mtk_gate_regs sgmii_cg_regs = {
+ .set_ofs = 0xE4,
+ .clr_ofs = 0xE4,
+ .sta_ofs = 0xE4,
+};
+
+#define GATE_SGMII(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &sgmii_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \
+ }
+
+static const struct mtk_gate sgmii_clks[] __initconst = {
+ GATE_SGMII(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en", "ssusb_tx250m", 2),
+ GATE_SGMII(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en", "ssusb_eq_rx250m", 3),
+ GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref", "ssusb_cdr_ref", 4),
+ GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb", "ssusb_cdr_fb", 5),
+};
+
+#define MT7622_PLL_FMAX (2500UL * MHZ)
+
+#define CON0_MT7622_RST_BAR BIT(27)
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
+ _pcw_shift, _div_table, _parent_name) { \
+ .id = _id, \
+ .name = _name, \
+ .reg = _reg, \
+ .pwr_reg = _pwr_reg, \
+ .en_mask = _en_mask, \
+ .flags = _flags, \
+ .rst_bar_mask = CON0_MT7622_RST_BAR, \
+ .fmax = MT7622_PLL_FMAX, \
+ .pcwbits = _pcwbits, \
+ .pd_reg = _pd_reg, \
+ .pd_shift = _pd_shift, \
+ .tuner_reg = _tuner_reg, \
+ .pcw_reg = _pcw_reg, \
+ .pcw_shift = _pcw_shift, \
+ .div_table = _div_table, \
+ .parent_name = _parent_name, \
+ }
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
+ _pcw_shift, _parent_name) \
+ PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
+ NULL, _parent_name)
+
+static const struct mtk_pll_data plls[] = {
+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001,
+ 0, 21, 0x0204, 24, 0, 0x0204, 0, "clksrc_pll"),
+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001,
+ HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0, "clksrc_pll"),
+ PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001,
+ HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14, "clksrc_pll"),
+ PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001,
+ 0, 21, 0x0300, 1, 0, 0x0304, 0, "clksrc_pll"),
+ PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001,
+ 0, 21, 0x0314, 1, 0, 0x0318, 0, "clksrc_pll"),
+ PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0x00000001,
+ 0, 31, 0x0324, 1, 0, 0x0328, 0, "clksrc_pll"),
+ PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0x00000001,
+ 0, 31, 0x0334, 1, 0, 0x0338, 0, "clksrc_pll"),
+ PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0x00000001,
+ 0, 21, 0x0344, 1, 0, 0x0348, 0, "clksrc_pll"),
+ PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001,
+ 0, 21, 0x0358, 1, 0, 0x035C, 0, "clksrc_pll"),
+};
+
+static struct clk_onecell_data *mt7622_top_clk_data __initdata;
+static struct clk_onecell_data *mt7622_pll_clk_data __initdata;
+
+static void __init mtk_clk_enable_critical(void)
+{
+ if (!mt7622_top_clk_data || !mt7622_pll_clk_data)
+ return;
+
+ clk_prepare_enable(mt7622_pll_clk_data->clks[CLK_APMIXED_ARMPLL]);
+ clk_prepare_enable(mt7622_top_clk_data->clks[CLK_TOP_AXI_SEL]);
+ clk_prepare_enable(mt7622_top_clk_data->clks[CLK_TOP_MEM_SEL]);
+ clk_prepare_enable(mt7622_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]);
+}
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+ int r;
+ void __iomem *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ mt7622_top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), mt7622_top_clk_data);
+ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), mt7622_top_clk_data);
+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt7622_clk_lock, mt7622_top_clk_data);
+ mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, &mt7622_clk_lock, mt7622_top_clk_data);
+ mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), mt7622_top_clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, mt7622_top_clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_clk_enable_critical();
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt7622-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infracfg_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ void __iomem *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+ mtk_clk_register_composites(infra_muxes, ARRAY_SIZE(infra_muxes), base, &mt7622_clk_lock, clk_data);
+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_infracfg, "mediatek,mt7622-infracfg", mtk_infracfg_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+ void __iomem *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+ mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, &mt7622_clk_lock, clk_data);
+ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt7622-pericfg", mtk_pericfg_init);
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+ int r;
+
+ mt7622_pll_clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+
+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), mt7622_pll_clk_data);
+ mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), mt7622_pll_clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, mt7622_pll_clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_clk_enable_critical();
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt7622-apmixedsys", mtk_apmixedsys_init);
+
+static void __init mtk_audiosys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK);
+
+ mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_audiosys, "mediatek,mt7622-audiosys", mtk_audiosys_init);
+
+static void __init mtk_ssusbsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK);
+
+ mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_ssusbsys, "mediatek,mt7622-ssusbsys", mtk_ssusbsys_init);
+
+static void __init mtk_pciesys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK);
+
+ mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 1, 0x34);
+}
+CLK_OF_DECLARE(mtk_pciesys, "mediatek,mt7622-pciesys", mtk_pciesys_init);
+
+static void __init mtk_ethsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
+
+ mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+
+ mtk_register_reset_controller(node, 1, 0x34);
+}
+CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7622-ethsys", mtk_ethsys_init);
+
+static void __init mtk_sgmiisys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
+
+ mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_sgmiisys, "mediatek,mt7622-sgmiisys", mtk_sgmiisys_init);
+
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 0ac3aee87726..7929e5f9497e 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -525,6 +525,25 @@ static const char * const i2s3_b_ck_parents[] __initconst = {
"apll2_div5"
};
+static const char * const ca53_parents[] __initconst = {
+ "clk26m",
+ "armca7pll",
+ "mainpll",
+ "univpll"
+};
+
+static const char * const ca57_parents[] __initconst = {
+ "clk26m",
+ "armca15pll",
+ "mainpll",
+ "univpll"
+};
+
+static const struct mtk_composite cpu_muxes[] __initconst = {
+ MUX(CLK_INFRA_CA53SEL, "infra_ca53_sel", ca53_parents, 0x0000, 0, 2),
+ MUX(CLK_INFRA_CA57SEL, "infra_ca57_sel", ca57_parents, 0x0000, 2, 2),
+};
+
static const struct mtk_composite top_muxes[] __initconst = {
/* CLK_CFG_0 */
MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
@@ -940,14 +959,24 @@ CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
static void __init mtk_infrasys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
+ void __iomem *base;
int r;
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
clk_data);
mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
+ mtk_clk_register_composites(cpu_muxes, ARRAY_SIZE(cpu_muxes), base,
+ &mt8173_clk_lock, clk_data);
+
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
@@ -1096,11 +1125,6 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
clk_data->clks[cku->id] = clk;
}
- clk = clk_register_divider(NULL, "hdmi_ref", "tvdpll_594m", 0,
- base + 0x40, 16, 3, CLK_DIVIDER_POWER_OF_TWO,
- NULL);
- clk_data->clks[CLK_APMIXED_HDMI_REF] = clk;
-
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index bb30f7063569..20f792d8e196 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -244,3 +244,28 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
clk_data->clks[mc->id] = clk;
}
}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+ int num, void __iomem *base, spinlock_t *lock,
+ struct clk_onecell_data *clk_data)
+{
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ const struct mtk_clk_divider *mcd = &mcds[i];
+
+ clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
+ mcd->flags, base + mcd->div_reg, mcd->div_shift,
+ mcd->div_width, mcd->clk_divider_flags, lock);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n",
+ mcd->name, PTR_ERR(clk));
+ continue;
+ }
+
+ if (clk_data)
+ clk_data->clks[mcd->id] = clk;
+ }
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index e425e50173c5..72db918790e2 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -121,7 +121,8 @@ struct mtk_composite {
.flags = CLK_SET_RATE_PARENT, \
}
-#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \
+ _div_width, _div_shift) { \
.id = _id, \
.parent = _parent, \
.name = _name, \
@@ -156,8 +157,35 @@ struct mtk_gate {
const struct clk_ops *ops;
};
-int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
- int num, struct clk_onecell_data *clk_data);
+int mtk_clk_register_gates(struct device_node *node,
+ const struct mtk_gate *clks, int num,
+ struct clk_onecell_data *clk_data);
+
+struct mtk_clk_divider {
+ int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+
+ uint32_t div_reg;
+ unsigned char div_shift;
+ unsigned char div_width;
+ unsigned char clk_divider_flags;
+ const struct clk_div_table *clk_div_table;
+};
+
+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .div_reg = _reg, \
+ .div_shift = _shift, \
+ .div_width = _width, \
+}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+ int num, void __iomem *base, spinlock_t *lock,
+ struct clk_onecell_data *clk_data);
struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
diff --git a/drivers/clk/mediatek/clkchk-mt7622.c b/drivers/clk/mediatek/clkchk-mt7622.c
new file mode 100644
index 000000000000..5ffef15bf7fa
--- /dev/null
+++ b/drivers/clk/mediatek/clkchk-mt7622.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/syscore_ops.h>
+#include <linux/version.h>
+
+#define WARN_ON_CHECK_PLL_FAIL 0
+#define CLKDBG_CCF_API_4_4 1
+
+#define TAG "[clkchk] "
+
+#define clk_warn(fmt, args...) pr_warn(TAG fmt, ##args)
+
+#if !CLKDBG_CCF_API_4_4
+
+/* backward compatible */
+
+static const char *clk_hw_get_name(const struct clk_hw *hw)
+{
+ return __clk_get_name(hw->clk);
+}
+
+static bool clk_hw_is_prepared(const struct clk_hw *hw)
+{
+ return __clk_is_prepared(hw->clk);
+}
+
+static bool clk_hw_is_enabled(const struct clk_hw *hw)
+{
+ return __clk_is_enabled(hw->clk);
+}
+
+#endif /* !CLKDBG_CCF_API_4_4 */
+
+static const char * const *get_all_clk_names(void)
+{
+ static const char * const clks[] = {
+ /* plls */
+ "armpll",
+ "mainpll",
+ "univ2pll",
+ "eth1pll",
+ "eth2pll",
+ "aud1pll",
+ "aud2pll",
+ "trgpll",
+ "sgmipll",
+ /* topckgen */
+ "to_u2_phy",
+ "to_u2_phy_1p",
+ "pcie0_pipe_en",
+ "pcie1_pipe_en",
+ "ssusb_tx250m",
+ "ssusb_eq_rx250m",
+ "ssusb_cdr_ref",
+ "ssusb_cdr_fb",
+ "sata_asic",
+ "sata_rbc",
+ "to_usb3_sys",
+ "p1_1mhz",
+ "free_run_4mhz",
+ "p0_1mhz",
+ "txclk_src_pre",
+ "rtc",
+ "mempll",
+ "dmpll_ck",
+ "syspll_d2",
+ "syspll1_d2",
+ "syspll1_d4",
+ "syspll1_d8",
+ "syspll2_d4",
+ "syspll2_d8",
+ "syspll_d5",
+ "syspll3_d2",
+ "syspll3_d4",
+ "syspll4_d2",
+ "syspll4_d4",
+ "syspll4_d16",
+ "univpll",
+ "univpll_d2",
+ "univpll1_d2",
+ "univpll1_d4",
+ "univpll1_d8",
+ "univpll1_d16",
+ "univpll2_d2",
+ "univpll2_d4",
+ "univpll2_d8",
+ "univpll2_d16",
+ "univpll_d5",
+ "univpll3_d2",
+ "univpll3_d4",
+ "univpll3_d16",
+ "univpll_d7",
+ "univpll_d80_d4",
+ "univ48m",
+ "sgmiipll_ck",
+ "sgmiipll_d2",
+ "aud1pll_ck",
+ "aud2pll_ck",
+ "aud_i2s2_mck",
+ "to_usb3_ref",
+ "pcie1_mac_en",
+ "pcie0_mac_en",
+ "eth_500m",
+ "axi_sel",
+ "mem_sel",
+ "ddrphycfg_sel",
+ "eth_sel",
+ "pwm_sel",
+ "f10m_ref_sel",
+ "nfi_infra_sel",
+ "flash_sel",
+ "uart_sel",
+ "spi0_sel",
+ "spi1_sel",
+ "msdc50_0_sel",
+ "msdc30_0_sel",
+ "msdc30_1_sel",
+ "a1sys_hp_sel",
+ "a2sys_hp_sel",
+ "intdir_sel",
+ "aud_intbus_sel",
+ "pmicspi_sel",
+ "scp_sel",
+ "atb_sel",
+ "hif_sel",
+ "audio_sel",
+ "usb20_sel",
+ "aud1_sel",
+ "aud2_sel",
+ "irrx_sel",
+ "irtx_sel",
+ "asm_l_sel",
+ "asm_m_sel",
+ "asm_h_sel",
+ "apll1_ck_sel",
+ "apll2_ck_sel",
+ "i2s0_mck_sel",
+ "i2s1_mck_sel",
+ "i2s2_mck_sel",
+ "i2s3_mck_sel",
+ "apll1_ck_div",
+ "apll2_ck_div",
+ "i2s0_mck_div",
+ "i2s1_mck_div",
+ "i2s2_mck_div",
+ "i2s3_mck_div",
+ "a1sys_div",
+ "a2sys_div",
+ "apll1_ck_div_pd",
+ "apll2_ck_div_pd",
+ "i2s0_mck_div_pd",
+ "i2s1_mck_div_pd",
+ "i2s2_mck_div_pd",
+ "i2s3_mck_div_pd",
+ "a1sys_div_pd",
+ "a2sys_div_pd",
+ /* infracfg */
+ "infra_mux1_sel",
+ "infra_dbgclk_pd",
+ "infra_audio_pd",
+ "infra_irrx_pd",
+ "infra_apxgpt_pd",
+ "infra_pmic_pd",
+ /* pericfg */
+ "peribus_ck_sel",
+ "peri_therm_pd",
+ "peri_pwm1_pd",
+ "peri_pwm2_pd",
+ "peri_pwm3_pd",
+ "peri_pwm4_pd",
+ "peri_pwm5_pd",
+ "peri_pwm6_pd",
+ "peri_pwm7_pd",
+ "peri_pwm_pd",
+ "peri_ap_dma_pd",
+ "peri_msdc30_0",
+ "peri_msdc30_1",
+ "peri_uart0_pd",
+ "peri_uart1_pd",
+ "peri_uart2_pd",
+ "peri_uart3_pd",
+ "peri_uart4_pd",
+ "peri_btif_pd",
+ "peri_i2c0_pd",
+ "peri_i2c1_pd",
+ "peri_i2c2_pd",
+ "peri_spi1_pd",
+ "peri_auxadc_pd",
+ "peri_spi0_pd",
+ "peri_snfi_pd",
+ "peri_nfi_pd",
+ "peri_nfiecc_pd",
+ "peri_flash_pd",
+ "peri_irtx_pd",
+ /* audiosys */
+ "audio_afe",
+ "audio_hdmi",
+ "audio_spdf",
+ "audio_apll",
+ "audio_i2sin1",
+ "audio_i2sin2",
+ "audio_i2sin3",
+ "audio_i2sin4",
+ "audio_i2so1",
+ "audio_i2so2",
+ "audio_i2so3",
+ "audio_i2so4",
+ "audio_asrci1",
+ "audio_asrci2",
+ "audio_asrco1",
+ "audio_asrco2",
+ "audio_intdir",
+ "audio_a1sys",
+ "audio_a2sys",
+ "audio_ul1",
+ "audio_ul2",
+ "audio_ul3",
+ "audio_ul4",
+ "audio_ul5",
+ "audio_ul6",
+ "audio_dl1",
+ "audio_dl2",
+ "audio_dl3",
+ "audio_dl4",
+ "audio_dl5",
+ "audio_dl6",
+ "audio_dlmch",
+ "audio_arb1",
+ "audio_awb",
+ "audio_awb2",
+ "audio_dai",
+ "audio_mod",
+ "audio_asrci3",
+ "audio_asrci4",
+ "audio_asrco3",
+ "audio_asrco4",
+ "audio_mem_asrc1",
+ "audio_mem_asrc2",
+ "audio_mem_asrc3",
+ "audio_mem_asrc4",
+ "audio_mem_asrc5",
+ /* ssusbsys */
+ "ssusb_u2_phy_1p",
+ "ssusb_u2_phy_en",
+ "ssusb_ref_en",
+ "ssusb_sys_en",
+ "ssusb_mcu_en",
+ "ssusb_dma_en",
+ /* pciesys */
+ "pcie_p1_aux_en",
+ "pcie_p1_obff_en",
+ "pcie_p1_ahb_en",
+ "pcie_p1_axi_en",
+ "pcie_p1_mac_en",
+ "pcie_p1_pipe_en",
+ "pcie_p0_aux_en",
+ "pcie_p0_obff_en",
+ "pcie_p0_ahb_en",
+ "pcie_p0_axi_en",
+ "pcie_p0_mac_en",
+ "pcie_p0_pipe_en",
+ "sata_ahb_en",
+ "sata_axi_en",
+ "sata_asic_en",
+ "sata_rbc_en",
+ "sata_pm_en",
+ /* ethsys */
+ "eth_hsdma_en",
+ "eth_esw_en",
+ "eth_gp2_en",
+ "eth_gp1_en",
+ "eth_gp0_en",
+ /* sgmiisys */
+ "sgmii_tx250m_en",
+ "sgmii_rx250m_en",
+ "sgmii_cdr_ref",
+ "sgmii_cdr_fb",
+ /* end */
+ NULL
+ };
+
+ return clks;
+}
+
+static const char *ccf_state(struct clk_hw *hw)
+{
+ if (__clk_get_enable_count(hw->clk))
+ return "enabled";
+
+ if (clk_hw_is_prepared(hw))
+ return "prepared";
+
+ return "disabled";
+}
+
+static void print_enabled_clks(void)
+{
+ const char * const *cn = get_all_clk_names();
+
+ clk_warn("enabled clks:\n");
+
+ for (; *cn; cn++) {
+ struct clk *c = __clk_lookup(*cn);
+ struct clk_hw *c_hw = __clk_get_hw(c);
+ struct clk_hw *p_hw;
+
+ if (IS_ERR_OR_NULL(c) || !c_hw)
+ continue;
+
+ p_hw = clk_hw_get_parent(c_hw);
+
+ if (!p_hw)
+ continue;
+
+ if (!clk_hw_is_prepared(c_hw) && !__clk_get_enable_count(c))
+ continue;
+
+ clk_warn("[%-17s: %8s, %3d, %3d, %10ld, %17s]\n",
+ clk_hw_get_name(c_hw),
+ ccf_state(c_hw),
+ clk_hw_is_prepared(c_hw),
+ __clk_get_enable_count(c),
+ clk_hw_get_rate(c_hw),
+ p_hw ? clk_hw_get_name(p_hw) : "- ");
+ }
+}
+
+static void check_pll_off(void)
+{
+ static const char * const off_pll_names[] = {
+ "univ2pll",
+ "eth1pll",
+ "eth2pll",
+ "aud1pll",
+ "aud2pll",
+ "trgpll",
+ "sgmipll",
+ NULL
+ };
+
+ static struct clk *off_plls[ARRAY_SIZE(off_pll_names)];
+
+ struct clk **c;
+ int invalid = 0;
+ char buf[128] = {0};
+ int n = 0;
+
+ if (!off_plls[0]) {
+ const char * const *pn;
+
+ for (pn = off_pll_names, c = off_plls; *pn; pn++, c++)
+ *c = __clk_lookup(*pn);
+ }
+
+ for (c = off_plls; *c; c++) {
+ struct clk_hw *c_hw = __clk_get_hw(*c);
+
+ if (!c_hw)
+ continue;
+
+ if (!clk_hw_is_prepared(c_hw) && !clk_hw_is_enabled(c_hw))
+ continue;
+
+ n += snprintf(buf + n, sizeof(buf) - n, "%s ",
+ clk_hw_get_name(c_hw));
+
+ invalid++;
+ }
+
+ if (invalid) {
+ clk_warn("unexpected unclosed PLL: %s\n", buf);
+ print_enabled_clks();
+
+#if WARN_ON_CHECK_PLL_FAIL
+ WARN_ON(1);
+#endif
+ }
+}
+
+static int clkchk_syscore_suspend(void)
+{
+ check_pll_off();
+
+ return 0;
+}
+
+static void clkchk_syscore_resume(void)
+{
+}
+
+static struct syscore_ops clkchk_syscore_ops = {
+ .suspend = clkchk_syscore_suspend,
+ .resume = clkchk_syscore_resume,
+};
+
+static int __init clkchk_init(void)
+{
+ if (!of_machine_is_compatible("mediatek,mt7622"))
+ return -ENODEV;
+
+ register_syscore_ops(&clkchk_syscore_ops);
+
+ return 0;
+}
+subsys_initcall(clkchk_init);
diff --git a/drivers/clk/mediatek/clkdbg-mt7622.c b/drivers/clk/mediatek/clkdbg-mt7622.c
new file mode 100644
index 000000000000..dae6b1656410
--- /dev/null
+++ b/drivers/clk/mediatek/clkdbg-mt7622.c
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+
+#include "clkdbg.h"
+
+#define DUMP_INIT_STATE 0
+
+/*
+ * clkdbg dump_regs
+ */
+
+enum {
+ infrasys,
+ perisys,
+ scpsys,
+ apmixed,
+ fhctl,
+ topckgen,
+ audio,
+ ssusb,
+ pcie,
+ ethdma,
+ sgmii,
+};
+
+#define REGBASE_V(_phys, _id_name) { .phys = _phys, .name = #_id_name }
+
+/*
+ * checkpatch.pl ERROR:COMPLEX_MACRO
+ *
+ * #define REGBASE(_phys, _id_name) [_id_name] = REGBASE_V(_phys, _id_name)
+ */
+
+static struct regbase rb[] = {
+ [infrasys] = REGBASE_V(0x10000000, infrasys),
+ [perisys] = REGBASE_V(0x10002000, perisys),
+ [scpsys] = REGBASE_V(0x10006000, scpsys),
+ [apmixed] = REGBASE_V(0x10209000, apmixed),
+ [fhctl] = REGBASE_V(0x10209f00, fhctl),
+ [topckgen] = REGBASE_V(0x10210000, topckgen),
+ [audio] = REGBASE_V(0x11220000, audio),
+ [ssusb] = REGBASE_V(0x1A000000, ssusb),
+ [pcie] = REGBASE_V(0x1A100800, pcie),
+ [ethdma] = REGBASE_V(0x1B000000, ethdma),
+ [sgmii] = REGBASE_V(0x1B128000, sgmii),
+};
+
+#define REGNAME(_base, _ofs, _name) \
+ { .base = &rb[_base], .ofs = _ofs, .name = #_name }
+
+static struct regname rn[] = {
+ REGNAME(infrasys, 0x040, INFRA_GLOBALCON_PDN0),
+ REGNAME(infrasys, 0x044, INFRA_GLOBALCON_PDN1),
+ REGNAME(infrasys, 0x048, INFRA_PDN_STA),
+ REGNAME(perisys, 0x008, PERI_GLOBALCON_PDN0_SET),
+ REGNAME(perisys, 0x00C, PERI_GLOBALCON_PDN1_SET),
+ REGNAME(perisys, 0x010, PERI_GLOBALCON_PDN0_CLR),
+ REGNAME(perisys, 0x014, PERI_GLOBALCON_PDN1_CLR),
+ REGNAME(perisys, 0x018, PERI_GLOBALCON_PDN0_STA),
+ REGNAME(perisys, 0x01C, PERI_GLOBALCON_PDN1_STA),
+ REGNAME(scpsys, 0x2E0, SPM_ETH_PWR_CON),
+ REGNAME(scpsys, 0x2E4, SPM_HIF0_PWR_CON),
+ REGNAME(scpsys, 0x2E8, SPM_HIF1_PWR_CON),
+ REGNAME(scpsys, 0x60c, SPM_PWR_STATUS),
+ REGNAME(scpsys, 0x610, SPM_PWR_STATUS_2ND),
+ REGNAME(apmixed, 0x200, ARMPLL_CON0),
+ REGNAME(apmixed, 0x204, ARMPLL_CON1),
+ REGNAME(apmixed, 0x20C, ARMPLL_PWR_CON0),
+ REGNAME(apmixed, 0x210, MAINPLL_CON0),
+ REGNAME(apmixed, 0x214, MAINPLL_CON1),
+ REGNAME(apmixed, 0x21C, MAINPLL_PWR_CON0),
+ REGNAME(apmixed, 0x220, UNIVPLL_CON0),
+ REGNAME(apmixed, 0x224, UNIVPLL_CON1),
+ REGNAME(apmixed, 0x22C, UNIVPLL_PWR_CON0),
+ REGNAME(apmixed, 0x300, ETH1PLL_CON0),
+ REGNAME(apmixed, 0x304, ETH1PLL_CON1),
+ REGNAME(apmixed, 0x310, ETH1PLL_PWR_CON0),
+ REGNAME(apmixed, 0x314, ETH2PLL_CON0),
+ REGNAME(apmixed, 0x318, ETH2PLL_CON1),
+ REGNAME(apmixed, 0x320, ETH2PLL_PWR_CON0),
+ REGNAME(apmixed, 0x324, APLL1_CON0),
+ REGNAME(apmixed, 0x328, APLL1_CON1),
+ REGNAME(apmixed, 0x330, APLL1_PWR_CON0),
+ REGNAME(apmixed, 0x334, APLL2_CON0),
+ REGNAME(apmixed, 0x338, APLL2_CON1),
+ REGNAME(apmixed, 0x340, APLL2_PWR_CON0),
+ REGNAME(apmixed, 0x344, TRGPLL_CON0),
+ REGNAME(apmixed, 0x348, TRGPLL_CON1),
+ REGNAME(apmixed, 0x354, TRGPLL_PWR_CON0),
+ REGNAME(apmixed, 0x358, SGMIPLL_CON0),
+ REGNAME(apmixed, 0x35C, SGMIPLL_CON1),
+ REGNAME(apmixed, 0x368, SGMIPLL_PWR_CON0),
+ REGNAME(topckgen, 0x040, CLK_CFG_0),
+ REGNAME(topckgen, 0x050, CLK_CFG_1),
+ REGNAME(topckgen, 0x060, CLK_CFG_2),
+ REGNAME(topckgen, 0x070, CLK_CFG_3),
+ REGNAME(topckgen, 0x080, CLK_CFG_4),
+ REGNAME(topckgen, 0x090, CLK_CFG_5),
+ REGNAME(topckgen, 0x0A0, CLK_CFG_6),
+ REGNAME(topckgen, 0x0B0, CLK_CFG_7),
+ REGNAME(topckgen, 0x120, CLK_AUDDIV_0),
+ REGNAME(topckgen, 0x128, CLK_AUDDIV_2),
+ REGNAME(audio, 0x000, AUDIO_TOP_CON0),
+ REGNAME(audio, 0x010, AUDIO_TOP_CON4),
+ REGNAME(audio, 0x014, AUDIO_TOP_CON5),
+ REGNAME(audio, 0x634, PWR2_TOP_CON),
+ REGNAME(ssusb, 0x30, USB23_CSR_O_CLKCFG1),
+ REGNAME(pcie, 0x30, COMBO_CSR_O_CLKCFG1),
+ REGNAME(ethdma, 0x30, ETHDMACTL_CLKCFG1),
+ REGNAME(sgmii, 0xE4, SGMII_QPHY_CTRL),
+ {NULL, 0, NULL}
+};
+
+static const struct regname *get_all_regnames(void)
+{
+ return rn;
+}
+
+static void __init init_regbase(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rb); i++)
+ rb[i].virt = ioremap(rb[i].phys, PAGE_SIZE);
+}
+
+/*
+ * clkdbg fmeter
+ */
+
+#include <linux/delay.h>
+
+#ifndef GENMASK
+#define GENMASK(h, l) (((1U << ((h) - (l) + 1)) - 1) << (l))
+#endif
+
+#define ALT_BITS(o, h, l, v) \
+ (((o) & ~GENMASK(h, l)) | (((v) << (l)) & GENMASK(h, l)))
+
+#define clk_readl(addr) readl(addr)
+#define clk_writel(addr, val) \
+ do { writel(val, addr); wmb(); } while (0) /* sync write */
+#define clk_writel_mask(addr, mask, val) \
+ clk_writel(addr, (clk_readl(addr) & ~(mask)) | (val))
+
+#define ABS_DIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
+
+enum FMETER_TYPE {
+ FT_NULL,
+ ABIST,
+ CKGEN
+};
+
+#define FMCLK(_t, _i, _n) { .type = _t, .id = _i, .name = _n }
+
+static const struct fmeter_clk fclks[] = {
+ FMCLK(ABIST, 1, "AD_MEMPLL2_CKOUT0_PRE_ISO"),
+ FMCLK(ABIST, 2, "AD_MAIN_DIV2_CK"),
+ FMCLK(ABIST, 3, "AD_MAIN_DIV3_CK"),
+ FMCLK(ABIST, 4, "AD_MAIN_DIV5_CK"),
+ FMCLK(ABIST, 5, "AD_MAIN_DIV7_CK"),
+ FMCLK(ABIST, 6, "AD_UNIV_DIV2_CK"),
+ FMCLK(ABIST, 7, "AD_UNIV_DIV3_CK"),
+ FMCLK(ABIST, 8, "AD_UNIV_DIV5_CK"),
+ FMCLK(ABIST, 9, "AD_UNIV_DIV7_CK"),
+ FMCLK(ABIST, 10, "AD_UNIV_DIV80_CK"),
+ FMCLK(ABIST, 11, "AD_UNIV_48M_CK"),
+ FMCLK(ABIST, 12, "AD_SGMIIPLL_CK"),
+ FMCLK(ABIST, 13, "XTAL"),
+ FMCLK(ABIST, 14, "AD_AUD1PLL_CK"),
+ FMCLK(ABIST, 15, "AD_AUD2PLL_CK"),
+ FMCLK(ABIST, 16, "RTC"),
+ FMCLK(ABIST, 17, "AD_ARMPLL_TOP_TST_CK"),
+ FMCLK(ABIST, 18, "AD_USB_48M_CK"),
+ FMCLK(ABIST, 19, "AD_MAINPLL_CORE_CK"),
+ FMCLK(ABIST, 20, "AD_TRGPLL_CK"),
+ FMCLK(ABIST, 21, "AD_MEM_25M_CK"),
+ FMCLK(ABIST, 22, "AD_PLLGP_TST_CK"),
+ FMCLK(ABIST, 23, "AD_ETH1PLL_CK"),
+ FMCLK(ABIST, 24, "AD_ETH2PLL_CK"),
+ FMCLK(ABIST, 25, "AD_UNIVPLL_CK"),
+ FMCLK(ABIST, 26, "AD_MEM2MIPI_26M_CK"),
+ FMCLK(ABIST, 27, "AD_MEMPLL_MONCLK"),
+ FMCLK(ABIST, 28, "AD_MEMPLL2_MONCLK"),
+ FMCLK(ABIST, 29, "AD_MEMPLL3_MONCLK"),
+ FMCLK(ABIST, 30, "AD_MEMPLL4_MONCLK"),
+ FMCLK(ABIST, 31, "AD_MEMPLL_REFCLK_BUF"),
+ FMCLK(ABIST, 32, "AD_MEMPLL_FBCLK_BUF"),
+ FMCLK(ABIST, 33, "AD_MEMPLL2_REFCLK_BUF"),
+ FMCLK(ABIST, 34, "AD_MEMPLL2_FBCLK_BUF"),
+ FMCLK(ABIST, 35, "AD_MEMPLL3_REFCLK_BUF"),
+ FMCLK(ABIST, 36, "AD_MEMPLL3_FBCLK_BUF"),
+ FMCLK(ABIST, 37, "AD_MEMPLL4_REFCLK_BUF"),
+ FMCLK(ABIST, 38, "AD_MEMPLL4_FBCLK_BUF"),
+ FMCLK(ABIST, 39, "AD_MEMPLL_TSTDIV2_CK"),
+ FMCLK(CKGEN, 1, "hf_fmem_ck"),
+ FMCLK(CKGEN, 2, "hf_fddrphycfg_ck"),
+ FMCLK(CKGEN, 3, "hf_feth_ck"),
+ FMCLK(CKGEN, 4, "f_fpwm_ck"),
+ FMCLK(CKGEN, 5, "hf_f10m_ck"),
+ FMCLK(CKGEN, 6, "hf_fspinfi_infra_bclk_ck"),
+ FMCLK(CKGEN, 7, "hf_fflash_ck"),
+ FMCLK(CKGEN, 8, "f_fuart_ck"),
+ FMCLK(CKGEN, 9, "hf_fspi0_ck"),
+ FMCLK(CKGEN, 10, "hf_fspi1_ck"),
+ FMCLK(CKGEN, 11, "hf_fmsdc50_0_ck"),
+ FMCLK(CKGEN, 12, "hf_fmsdc30_0_ck"),
+ FMCLK(CKGEN, 13, "hf_fmsdc30_1_ck"),
+ FMCLK(CKGEN, 14, "f_fa1sys_hp_ck"),
+ FMCLK(CKGEN, 15, "f_fa2sys_hp_ck"),
+ FMCLK(CKGEN, 16, "hf_fintdir_ck"),
+ FMCLK(CKGEN, 17, "hf_faud_intbus_ck"),
+ FMCLK(CKGEN, 18, "hf_fpmicspi_ck"),
+ FMCLK(CKGEN, 19, "hf_fscp_ck"),
+ FMCLK(CKGEN, 20, "hf_fatb_ck"),
+ FMCLK(CKGEN, 21, "hf_fhif_ck"),
+ FMCLK(CKGEN, 22, "hf_faudio_ck"),
+ FMCLK(CKGEN, 23, "hf_fusb20_ck"),
+ FMCLK(CKGEN, 24, "f_faud1_ck"),
+ FMCLK(CKGEN, 25, "f_faud2_ck"),
+ FMCLK(CKGEN, 26, "hf_firrx_ck"),
+ FMCLK(CKGEN, 27, "hf_firtx_ck"),
+ FMCLK(CKGEN, 28, "hf_fasm_l_ck"),
+ FMCLK(CKGEN, 29, "hf_fasm_m_ck"),
+ FMCLK(CKGEN, 30, "hf_fasm_h_ck"),
+ FMCLK(CKGEN, 31, "f_faud26m_ck"),
+ FMCLK(CKGEN, 32, "hf_fpmicspi_ck_scan"),
+ FMCLK(CKGEN, 33, "hf_fsgmii_ref_ck"),
+ FMCLK(CKGEN, 34, "f_fsata_ck"),
+ FMCLK(CKGEN, 35, "f_f75k_ck"),
+ FMCLK(CKGEN, 36, "f_fmsdc_ext_ck"),
+ FMCLK(CKGEN, 37, "hf_fddrphycfg_ck_scan"),
+ FMCLK(CKGEN, 38, "f_frtc_fddrphyperi_ck"),
+ FMCLK(CKGEN, 39, "f_fddrphyperi_ck_scan"),
+ FMCLK(CKGEN, 40, "f_fckrtc_ck_scan"),
+ FMCLK(CKGEN, 41, "f_frtc_ck"),
+ FMCLK(CKGEN, 42, "f_fxtal_ck"),
+ FMCLK(CKGEN, 43, "f_fckbus_ck_scan"),
+ FMCLK(CKGEN, 44, "f_fxtal_ck_cg"),
+ FMCLK(CKGEN, 45, "hd_qaxidcm_ck"),
+ FMCLK(CKGEN, 46, "hf_fspi0_pad_ck"),
+ FMCLK(CKGEN, 47, "hf_fspi1_pad_ck"),
+ FMCLK(CKGEN, 48, "f_fefuse_ck"),
+ FMCLK(CKGEN, 49, "f_fapmixed_ck"),
+ FMCLK(CKGEN, 50, "f_fclkmux_ck"),
+ FMCLK(CKGEN, 51, "f_frtc_apmixed_ck"),
+ FMCLK(CKGEN, 52, "f_fsata_ref_ck"),
+ FMCLK(CKGEN, 53, "f_fpcie_ref_ck"),
+ FMCLK(CKGEN, 54, "f_fssusb_ref_ck"),
+ FMCLK(CKGEN, 55, "f_funivpll3_d16_ck"),
+ FMCLK(CKGEN, 56, "f_fauxadc_ck"),
+ FMCLK(CKGEN, 57, "hf_fap2wbmcu_ck"),
+ FMCLK(CKGEN, 58, "hf_fap2wbhif_ck"),
+ FMCLK(CKGEN, 59, "hf_fsata_mcu_ck"),
+ FMCLK(CKGEN, 60, "hf_fpcie0_mcu_ck"),
+ FMCLK(CKGEN, 61, "hf_fpcie1_mcu_ck"),
+ FMCLK(CKGEN, 62, "hf_fssusb_mcu_ck"),
+ FMCLK(CKGEN, 63, "f_fpcie_2ln_ck"),
+ {}
+};
+
+#define FHCTL_HP_EN (rb[fhctl].virt + 0x000)
+#define CLK_CFG_M0 (rb[topckgen].virt + 0x100)
+#define CLK_CFG_M1 (rb[topckgen].virt + 0x104)
+#define CLK_MISC_CFG_1 (rb[topckgen].virt + 0x214)
+#define CLK_MISC_CFG_2 (rb[topckgen].virt + 0x218)
+#define CLK26CALI_0 (rb[topckgen].virt + 0x220)
+#define CLK26CALI_1 (rb[topckgen].virt + 0x224)
+#define CLK26CALI_2 (rb[topckgen].virt + 0x228)
+
+#define RG_FRMTR_WINDOW 1023
+
+static void set_fmeter_divider_arm(u32 k1)
+{
+ u32 v = clk_readl(CLK_MISC_CFG_1);
+
+ v = ALT_BITS(v, 15, 8, k1);
+ clk_writel(CLK_MISC_CFG_1, v);
+}
+
+static void set_fmeter_divider(u32 k1)
+{
+ u32 v = clk_readl(CLK_MISC_CFG_1);
+
+ v = ALT_BITS(v, 7, 0, k1);
+ v = ALT_BITS(v, 31, 24, k1);
+ clk_writel(CLK_MISC_CFG_1, v);
+}
+
+static u8 wait_fmeter_done(u32 tri_bit)
+{
+ static int max_wait_count;
+ int wait_count = (max_wait_count > 0) ? (max_wait_count * 2 + 2) : 100;
+ int i;
+
+ /* wait fmeter */
+ for (i = 0; i < wait_count && (clk_readl(CLK26CALI_0) & tri_bit); i++)
+ udelay(20);
+
+ if (!(clk_readl(CLK26CALI_0) & tri_bit)) {
+ max_wait_count = max(max_wait_count, i);
+ return 1;
+ }
+
+ return 0;
+}
+static u32 fmeter_freq(enum FMETER_TYPE type, int k1, int clk)
+{
+ void __iomem *clk_cfg_reg = (type == CKGEN) ? CLK_CFG_M1 : CLK_CFG_M0;
+ void __iomem *cnt_reg = (type == CKGEN) ? CLK26CALI_2 : CLK26CALI_1;
+ u32 cksw_mask = (type == CKGEN) ? GENMASK(21, 16) : GENMASK(13, 8);
+ u32 cksw_val = (type == CKGEN) ? (clk << 16) : (clk << 8);
+ u32 tri_bit = (type == CKGEN) ? BIT(4) : BIT(0);
+ u32 clk_exc = (type == CKGEN) ? BIT(5) : BIT(2);
+ u32 clk_misc_cfg_1, clk_misc_cfg_2, clk_cfg_val, cnt, freq = 0;
+
+ /* setup fmeter */
+ clk_setl(CLK26CALI_0, BIT(7)); /* enable fmeter_en */
+ clk_clrl(CLK26CALI_0, clk_exc); /* set clk_exc */
+ clk_writel_mask(cnt_reg, GENMASK(25, 16), RG_FRMTR_WINDOW << 16); /* load_cnt */
+
+ clk_misc_cfg_1 = clk_readl(CLK_MISC_CFG_1); /* backup CLK_MISC_CFG_1 value */
+ clk_misc_cfg_2 = clk_readl(CLK_MISC_CFG_2); /* backup CLK_MISC_CFG_2 value */
+ clk_cfg_val = clk_readl(clk_cfg_reg); /* backup clk_cfg_reg value */
+
+ set_fmeter_divider(k1); /* set divider (0 = /1) */
+ set_fmeter_divider_arm(k1);
+ clk_writel_mask(clk_cfg_reg, cksw_mask, cksw_val); /* select cksw */
+
+ clk_setl(CLK26CALI_0, tri_bit); /* start fmeter */
+
+ if (wait_fmeter_done(tri_bit)) {
+ cnt = clk_readl(cnt_reg) & 0xFFFF;
+ freq = (cnt * 25000) * (k1 + 1) / (RG_FRMTR_WINDOW + 1); /* (KHz) ; freq = counter * 26M / 1024 */
+ }
+
+ /* restore register settings */
+ clk_writel(clk_cfg_reg, clk_cfg_val);
+ clk_writel(CLK_MISC_CFG_2, clk_misc_cfg_2);
+ clk_writel(CLK_MISC_CFG_1, clk_misc_cfg_1);
+
+ clk_clrl(CLK26CALI_0, BIT(7)); /* disable fmeter_en */
+
+ return freq;
+}
+
+static u32 measure_stable_fmeter_freq(enum FMETER_TYPE type, int k1, int clk)
+{
+ u32 last_freq = 0;
+ u32 freq = fmeter_freq(type, k1, clk);
+ u32 maxfreq = max(freq, last_freq);
+
+ while (maxfreq > 0 && ABS_DIFF(freq, last_freq) * 100 / maxfreq > 10) {
+ last_freq = freq;
+ freq = fmeter_freq(type, k1, clk);
+ maxfreq = max(freq, last_freq);
+ }
+
+ return freq;
+}
+
+static const struct fmeter_clk *get_all_fmeter_clks(void)
+{
+ return fclks;
+}
+
+struct bak {
+ u32 fhctl_hp_en;
+};
+
+static void *prepare_fmeter(void)
+{
+ static struct bak regs;
+
+ regs.fhctl_hp_en = clk_readl(FHCTL_HP_EN);
+
+ clk_writel(FHCTL_HP_EN, 0x0); /* disable PLL hopping */
+ udelay(10);
+
+ return &regs;
+}
+
+static void unprepare_fmeter(void *data)
+{
+ struct bak *regs = data;
+
+ /* restore old setting */
+ clk_writel(FHCTL_HP_EN, regs->fhctl_hp_en);
+}
+
+static u32 fmeter_freq_op(const struct fmeter_clk *fclk)
+{
+ if (fclk->type)
+ return measure_stable_fmeter_freq(fclk->type, 0, fclk->id);
+
+ return 0;
+}
+
+/*
+ * clkdbg dump_state
+ */
+
+static const char * const *get_all_clk_names(void)
+{
+ static const char * const clks[] = {
+ /* plls */
+ "armpll",
+ "mainpll",
+ "univ2pll",
+ "eth1pll",
+ "eth2pll",
+ "aud1pll",
+ "aud2pll",
+ "trgpll",
+ "sgmipll",
+ /* topckgen */
+ "to_u2_phy",
+ "to_u2_phy_1p",
+ "pcie0_pipe_en",
+ "pcie1_pipe_en",
+ "ssusb_tx250m",
+ "ssusb_eq_rx250m",
+ "ssusb_cdr_ref",
+ "ssusb_cdr_fb",
+ "sata_asic",
+ "sata_rbc",
+ "to_usb3_sys",
+ "p1_1mhz",
+ "free_run_4mhz",
+ "p0_1mhz",
+ "txclk_src_pre",
+ "rtc",
+ "mempll",
+ "dmpll_ck",
+ "syspll_d2",
+ "syspll1_d2",
+ "syspll1_d4",
+ "syspll1_d8",
+ "syspll2_d4",
+ "syspll2_d8",
+ "syspll_d5",
+ "syspll3_d2",
+ "syspll3_d4",
+ "syspll4_d2",
+ "syspll4_d4",
+ "syspll4_d16",
+ "univpll",
+ "univpll_d2",
+ "univpll1_d2",
+ "univpll1_d4",
+ "univpll1_d8",
+ "univpll1_d16",
+ "univpll2_d2",
+ "univpll2_d4",
+ "univpll2_d8",
+ "univpll2_d16",
+ "univpll_d5",
+ "univpll3_d2",
+ "univpll3_d4",
+ "univpll3_d16",
+ "univpll_d7",
+ "univpll_d80_d4",
+ "univ48m",
+ "sgmiipll_ck",
+ "sgmiipll_d2",
+ "aud1pll_ck",
+ "aud2pll_ck",
+ "aud_i2s2_mck",
+ "to_usb3_ref",
+ "pcie1_mac_en",
+ "pcie0_mac_en",
+ "eth_500m",
+ "axi_sel",
+ "mem_sel",
+ "ddrphycfg_sel",
+ "eth_sel",
+ "pwm_sel",
+ "f10m_ref_sel",
+ "nfi_infra_sel",
+ "flash_sel",
+ "uart_sel",
+ "spi0_sel",
+ "spi1_sel",
+ "msdc50_0_sel",
+ "msdc30_0_sel",
+ "msdc30_1_sel",
+ "a1sys_hp_sel",
+ "a2sys_hp_sel",
+ "intdir_sel",
+ "aud_intbus_sel",
+ "pmicspi_sel",
+ "scp_sel",
+ "atb_sel",
+ "hif_sel",
+ "audio_sel",
+ "usb20_sel",
+ "aud1_sel",
+ "aud2_sel",
+ "irrx_sel",
+ "irtx_sel",
+ "asm_l_sel",
+ "asm_m_sel",
+ "asm_h_sel",
+ "apll1_ck_sel",
+ "apll2_ck_sel",
+ "i2s0_mck_sel",
+ "i2s1_mck_sel",
+ "i2s2_mck_sel",
+ "i2s3_mck_sel",
+ "apll1_ck_div",
+ "apll2_ck_div",
+ "i2s0_mck_div",
+ "i2s1_mck_div",
+ "i2s2_mck_div",
+ "i2s3_mck_div",
+ "a1sys_div",
+ "a2sys_div",
+ "apll1_ck_div_pd",
+ "apll2_ck_div_pd",
+ "i2s0_mck_div_pd",
+ "i2s1_mck_div_pd",
+ "i2s2_mck_div_pd",
+ "i2s3_mck_div_pd",
+ "a1sys_div_pd",
+ "a2sys_div_pd",
+ /* infracfg */
+ "infra_mux1_sel",
+ "infra_dbgclk_pd",
+ "infra_audio_pd",
+ "infra_irrx_pd",
+ "infra_apxgpt_pd",
+ "infra_pmic_pd",
+ /* pericfg */
+ "peribus_ck_sel",
+ "peri_therm_pd",
+ "peri_pwm1_pd",
+ "peri_pwm2_pd",
+ "peri_pwm3_pd",
+ "peri_pwm4_pd",
+ "peri_pwm5_pd",
+ "peri_pwm6_pd",
+ "peri_pwm7_pd",
+ "peri_pwm_pd",
+ "peri_ap_dma_pd",
+ "peri_msdc30_0",
+ "peri_msdc30_1",
+ "peri_uart0_pd",
+ "peri_uart1_pd",
+ "peri_uart2_pd",
+ "peri_uart3_pd",
+ "peri_uart4_pd",
+ "peri_btif_pd",
+ "peri_i2c0_pd",
+ "peri_i2c1_pd",
+ "peri_i2c2_pd",
+ "peri_spi1_pd",
+ "peri_auxadc_pd",
+ "peri_spi0_pd",
+ "peri_snfi_pd",
+ "peri_nfi_pd",
+ "peri_nfiecc_pd",
+ "peri_flash_pd",
+ "peri_irtx_pd",
+ /* audiosys */
+ "audio_afe",
+ "audio_hdmi",
+ "audio_spdf",
+ "audio_apll",
+ "audio_i2sin1",
+ "audio_i2sin2",
+ "audio_i2sin3",
+ "audio_i2sin4",
+ "audio_i2so1",
+ "audio_i2so2",
+ "audio_i2so3",
+ "audio_i2so4",
+ "audio_asrci1",
+ "audio_asrci2",
+ "audio_asrco1",
+ "audio_asrco2",
+ "audio_intdir",
+ "audio_a1sys",
+ "audio_a2sys",
+ "audio_ul1",
+ "audio_ul2",
+ "audio_ul3",
+ "audio_ul4",
+ "audio_ul5",
+ "audio_ul6",
+ "audio_dl1",
+ "audio_dl2",
+ "audio_dl3",
+ "audio_dl4",
+ "audio_dl5",
+ "audio_dl6",
+ "audio_dlmch",
+ "audio_arb1",
+ "audio_awb",
+ "audio_awb2",
+ "audio_dai",
+ "audio_mod",
+ "audio_asrci3",
+ "audio_asrci4",
+ "audio_asrco3",
+ "audio_asrco4",
+ "audio_mem_asrc1",
+ "audio_mem_asrc2",
+ "audio_mem_asrc3",
+ "audio_mem_asrc4",
+ "audio_mem_asrc5",
+ /* ssusbsys */
+ "ssusb_u2_phy_1p",
+ "ssusb_u2_phy_en",
+ "ssusb_ref_en",
+ "ssusb_sys_en",
+ "ssusb_mcu_en",
+ "ssusb_dma_en",
+ /* pciesys */
+ "pcie_p1_aux_en",
+ "pcie_p1_obff_en",
+ "pcie_p1_ahb_en",
+ "pcie_p1_axi_en",
+ "pcie_p1_mac_en",
+ "pcie_p1_pipe_en",
+ "pcie_p0_aux_en",
+ "pcie_p0_obff_en",
+ "pcie_p0_ahb_en",
+ "pcie_p0_axi_en",
+ "pcie_p0_mac_en",
+ "pcie_p0_pipe_en",
+ "sata_ahb_en",
+ "sata_axi_en",
+ "sata_asic_en",
+ "sata_rbc_en",
+ "sata_pm_en",
+ /* ethsys */
+ "eth_hsdma_en",
+ "eth_esw_en",
+ "eth_gp2_en",
+ "eth_gp1_en",
+ "eth_gp0_en",
+ /* sgmiisys */
+ "sgmii_tx250m_en",
+ "sgmii_rx250m_en",
+ "sgmii_cdr_ref",
+ "sgmii_cdr_fb",
+ /* end */
+ NULL
+ };
+
+ return clks;
+}
+
+/*
+ * clkdbg pwr_status
+ */
+
+static const char * const *get_pwr_names(void)
+{
+ static const char * const pwr_names[] = {
+ [24] = "ETHSYS",
+ [25] = "HIF0",
+ [26] = "HIF1",
+ };
+
+ return pwr_names;
+}
+
+/*
+ * init functions
+ */
+
+static struct clkdbg_ops clkdbg_mt7622_ops = {
+ .get_all_fmeter_clks = get_all_fmeter_clks,
+ .prepare_fmeter = prepare_fmeter,
+ .unprepare_fmeter = unprepare_fmeter,
+ .fmeter_freq = fmeter_freq_op,
+ .get_all_regnames = get_all_regnames,
+ .get_all_clk_names = get_all_clk_names,
+ .get_pwr_names = get_pwr_names,
+};
+
+static int __init clkdbg_mt7622_init(void)
+{
+ if (!of_machine_is_compatible("mediatek,mt7622"))
+ return -ENODEV;
+
+ init_regbase();
+
+ set_clkdbg_ops(&clkdbg_mt7622_ops);
+
+#if DUMP_INIT_STATE
+ print_regs();
+ print_fmeter_all();
+#endif /* DUMP_INIT_STATE */
+
+ return 0;
+}
+device_initcall(clkdbg_mt7622_init);
diff --git a/drivers/clk/mediatek/clkdbg.c b/drivers/clk/mediatek/clkdbg.c
new file mode 100644
index 000000000000..31be45fe1d9b
--- /dev/null
+++ b/drivers/clk/mediatek/clkdbg.c
@@ -0,0 +1,2165 @@
+/*
+ * Copyright (C) 2015 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/proc_fs.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include "clkdbg.h"
+
+#define CLKDBG_PM_DOMAIN 1
+#define CLKDBG_CCF_API_4_4 1
+#define CLKDBG_HACK_CLK 0
+#define CLKDBG_HACK_CLK_CORE 1
+
+
+#if !CLKDBG_CCF_API_4_4
+
+/* backward compatible */
+
+static const char *clk_hw_get_name(const struct clk_hw *hw)
+{
+ return __clk_get_name(hw->clk);
+}
+
+static bool clk_hw_is_prepared(const struct clk_hw *hw)
+{
+ return __clk_is_prepared(hw->clk);
+}
+
+static bool clk_hw_is_enabled(const struct clk_hw *hw)
+{
+ return __clk_is_enabled(hw->clk);
+}
+
+static unsigned long clk_hw_get_rate(const struct clk_hw *hw)
+{
+ return __clk_get_rate(hw->clk);
+}
+
+static unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
+{
+ return __clk_get_num_parents(hw->clk);
+}
+
+static struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
+ unsigned int index)
+{
+ return __clk_get_hw(clk_get_parent_by_index(hw->clk, index));
+}
+
+#endif /* !CLKDBG_CCF_API_4_4 */
+
+#if CLKDBG_HACK_CLK
+
+#include <linux/clk-private.h>
+
+static int clk_hw_is_on(struct clk_hw *hw)
+{
+ const struct clk_ops *ops = hw->clk->ops;
+
+ if (ops->is_enabled)
+ return clk_hw_is_enabled(hw);
+ else if (ops->is_prepared)
+ return clk_hw_is_prepared(hw);
+ return clk_hw_is_enabled(hw) || clk_hw_is_prepared(hw);
+}
+
+#elif CLKDBG_HACK_CLK_CORE
+
+struct clk_core {
+ const char *name;
+ const struct clk_ops *ops;
+ struct clk_hw *hw;
+};
+
+static int clk_hw_is_on(struct clk_hw *hw)
+{
+ const struct clk_ops *ops = hw->core->ops;
+
+ if (ops->is_enabled)
+ return clk_hw_is_enabled(hw);
+ else if (ops->is_prepared)
+ return clk_hw_is_prepared(hw);
+ return clk_hw_is_enabled(hw) || clk_hw_is_prepared(hw);
+}
+
+#else
+
+static int clk_hw_is_on(struct clk_hw *hw)
+{
+ return __clk_get_enable_count(hw->clk) || clk_hw_is_prepared(hw);
+}
+
+#endif /* !CLKDBG_HACK_CLK && !CLKDBG_HACK_CLK_CORE */
+
+static const struct clkdbg_ops *clkdbg_ops;
+
+void set_clkdbg_ops(const struct clkdbg_ops *ops)
+{
+ clkdbg_ops = ops;
+}
+
+static const struct fmeter_clk *get_all_fmeter_clks(void)
+{
+ if (!clkdbg_ops || !clkdbg_ops->get_all_fmeter_clks)
+ return NULL;
+
+ return clkdbg_ops->get_all_fmeter_clks();
+}
+
+static void *prepare_fmeter(void)
+{
+ if (!clkdbg_ops || !clkdbg_ops->prepare_fmeter)
+ return NULL;
+
+ return clkdbg_ops->prepare_fmeter();
+}
+
+static void unprepare_fmeter(void *data)
+{
+ if (!clkdbg_ops || !clkdbg_ops->unprepare_fmeter)
+ return;
+
+ clkdbg_ops->unprepare_fmeter(data);
+}
+
+static u32 fmeter_freq(const struct fmeter_clk *fclk)
+{
+ if (!clkdbg_ops || !clkdbg_ops->fmeter_freq)
+ return 0;
+
+ return clkdbg_ops->fmeter_freq(fclk);
+}
+
+static const struct regname *get_all_regnames(void)
+{
+ if (!clkdbg_ops || !clkdbg_ops->get_all_regnames)
+ return NULL;
+
+ return clkdbg_ops->get_all_regnames();
+}
+
+static const char * const *get_all_clk_names(void)
+{
+ if (!clkdbg_ops || !clkdbg_ops->get_all_clk_names)
+ return NULL;
+
+ return clkdbg_ops->get_all_clk_names();
+}
+
+static const char * const *get_pwr_names(void)
+{
+ static const char * const default_pwr_names[] = {
+ [0] = "(MD)",
+ [1] = "(CONN)",
+ [2] = "(DDRPHY)",
+ [3] = "(DISP)",
+ [4] = "(MFG)",
+ [5] = "(ISP)",
+ [6] = "(INFRA)",
+ [7] = "(VDEC)",
+ [8] = "(CPU, CA7_CPUTOP)",
+ [9] = "(FC3, CA7_CPU0, CPUTOP)",
+ [10] = "(FC2, CA7_CPU1, CPU3)",
+ [11] = "(FC1, CA7_CPU2, CPU2)",
+ [12] = "(FC0, CA7_CPU3, CPU1)",
+ [13] = "(MCUSYS, CA7_DBG, CPU0)",
+ [14] = "(MCUSYS, VEN, BDP)",
+ [15] = "(CA15_CPUTOP, ETH, MCUSYS)",
+ [16] = "(CA15_CPU0, HIF)",
+ [17] = "(CA15_CPU1, CA15-CX0, INFRA_MISC)",
+ [18] = "(CA15_CPU2, CA15-CX1)",
+ [19] = "(CA15_CPU3, CA15-CPU0)",
+ [20] = "(VEN2, MJC, CA15-CPU1)",
+ [21] = "(VEN, CA15-CPUTOP)",
+ [22] = "(MFG_2D)",
+ [23] = "(MFG_ASYNC, DBG)",
+ [24] = "(AUDIO, MFG_2D)",
+ [25] = "(USB, VCORE_PDN, MFG_ASYNC)",
+ [26] = "(ARMPLL_DIV, CPUTOP_SRM_SLPB)",
+ [27] = "(MD2, CPUTOP_SRM_PDN)",
+ [28] = "(CPU3_SRM_PDN)",
+ [29] = "(CPU2_SRM_PDN)",
+ [30] = "(CPU1_SRM_PDN)",
+ [31] = "(CPU0_SRM_PDN)",
+ };
+
+ if (!clkdbg_ops || !clkdbg_ops->get_pwr_names)
+ return default_pwr_names;
+
+ return clkdbg_ops->get_pwr_names();
+}
+
+static void setup_provider_clk(struct provider_clk *pvdck)
+{
+ if (!clkdbg_ops || !clkdbg_ops->setup_provider_clk)
+ return;
+
+ clkdbg_ops->setup_provider_clk(pvdck);
+}
+
+static bool is_valid_reg(void __iomem *addr)
+{
+#ifdef CONFIG_64BIT
+ return ((u64)addr & 0xf0000000) || (((u64)addr >> 32) & 0xf0000000);
+#else
+ return ((u32)addr & 0xf0000000);
+#endif
+}
+
+enum clkdbg_opt {
+ CLKDBG_EN_SUSPEND_SAVE_1,
+ CLKDBG_EN_SUSPEND_SAVE_2,
+ CLKDBG_EN_SUSPEND_SAVE_3,
+ CLKDBG_EN_LOG_SAVE_POINTS,
+};
+
+static u32 clkdbg_flags;
+
+static void set_clkdbg_flag(enum clkdbg_opt opt)
+{
+ clkdbg_flags |= BIT(opt);
+}
+
+static void clr_clkdbg_flag(enum clkdbg_opt opt)
+{
+ clkdbg_flags &= ~BIT(opt);
+}
+
+static bool has_clkdbg_flag(enum clkdbg_opt opt)
+{
+ return !!(clkdbg_flags & BIT(opt));
+}
+
+typedef void (*fn_fclk_freq_proc)(const struct fmeter_clk *fclk,
+ u32 freq, void *data);
+
+static void proc_all_fclk_freq(fn_fclk_freq_proc proc, void *data)
+{
+ void *fmeter_data;
+ const struct fmeter_clk *fclk;
+
+ fclk = get_all_fmeter_clks();
+
+ if (!fclk || !proc)
+ return;
+
+ fmeter_data = prepare_fmeter();
+
+ for (; fclk->type; fclk++) {
+ u32 freq;
+
+ freq = fmeter_freq(fclk);
+ proc(fclk, freq, data);
+ }
+
+ unprepare_fmeter(fmeter_data);
+}
+
+static void print_fclk_freq(const struct fmeter_clk *fclk, u32 freq, void *data)
+{
+ clk_warn("%2d: %-29s: %u\n", fclk->id, fclk->name, freq);
+}
+
+void print_fmeter_all(void)
+{
+ proc_all_fclk_freq(print_fclk_freq, NULL);
+}
+
+static void seq_print_fclk_freq(const struct fmeter_clk *fclk,
+ u32 freq, void *data)
+{
+ struct seq_file *s = data;
+
+ seq_printf(s, "%2d: %-29s: %u\n", fclk->id, fclk->name, freq);
+}
+
+static int seq_print_fmeter_all(struct seq_file *s, void *v)
+{
+ proc_all_fclk_freq(seq_print_fclk_freq, s);
+
+ return 0;
+}
+
+typedef void (*fn_regname_proc)(const struct regname *rn, void *data);
+
+static void proc_all_regname(fn_regname_proc proc, void *data)
+{
+ const struct regname *rn = get_all_regnames();
+
+ if (!rn)
+ return;
+
+ for (; rn->base; rn++)
+ proc(rn, data);
+}
+
+static void print_reg(const struct regname *rn, void *data)
+{
+ if (!is_valid_reg(ADDR(rn)))
+ return;
+
+ clk_warn("%-21s: [0x%08x][0x%p] = 0x%08x\n",
+ rn->name, PHYSADDR(rn), ADDR(rn), clk_readl(ADDR(rn)));
+}
+
+void print_regs(void)
+{
+ proc_all_regname(print_reg, NULL);
+}
+
+static void seq_print_reg(const struct regname *rn, void *data)
+{
+ struct seq_file *s = data;
+
+ if (!is_valid_reg(ADDR(rn)))
+ return;
+
+ seq_printf(s, "%-21s: [0x%08x][0x%p] = 0x%08x\n",
+ rn->name, PHYSADDR(rn), ADDR(rn), clk_readl(ADDR(rn)));
+}
+
+static int seq_print_regs(struct seq_file *s, void *v)
+{
+ proc_all_regname(seq_print_reg, s);
+
+ return 0;
+}
+
+static void print_reg2(const struct regname *rn, void *data)
+{
+ if (!is_valid_reg(ADDR(rn)))
+ return;
+
+ clk_warn("%-21s: [0x%08x][0x%p] = 0x%08x\n",
+ rn->name, PHYSADDR(rn), ADDR(rn), clk_readl(ADDR(rn)));
+
+ msleep(20);
+}
+
+static int clkdbg_dump_regs2(struct seq_file *s, void *v)
+{
+ proc_all_regname(print_reg2, s);
+
+ return 0;
+}
+
+static u32 read_spm_pwr_status(void)
+{
+ static void __iomem *scpsys_base;
+
+ if (!scpsys_base)
+ scpsys_base = ioremap(0x10006000, PAGE_SIZE);
+
+ return clk_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment