Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/3] arm64: dts: Update Stingray clock DT nodes
From: Ray Jui @ 2018-05-25 16:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527266717-8406-1-git-send-email-ray.jui@broadcom.com>

Update clock output names in the Stingray clock DT nodes so they match
the binding document and the latest ASIC datasheet. Also add entries
for LCPLL2

Signed-off-by: Pramod Kumar <pramod.kumar@broadcom.com>
Signed-off-by: Ray Jui <ray.jui@broadcom.com>
---
 .../boot/dts/broadcom/stingray/stingray-clock.dtsi | 26 ++++++++++++++++------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray-clock.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray-clock.dtsi
index 3a4d452..10a106a 100644
--- a/arch/arm64/boot/dts/broadcom/stingray/stingray-clock.dtsi
+++ b/arch/arm64/boot/dts/broadcom/stingray/stingray-clock.dtsi
@@ -52,12 +52,24 @@
 			reg = <0x0001d104 0x32>,
 			      <0x0001c854 0x4>;
 			clocks = <&osc>;
-			clock-output-names = "genpll0", "clk_125", "clk_scr",
+			clock-output-names = "genpll0", "clk_125m", "clk_scr",
 					     "clk_250", "clk_pcie_axi",
 					     "clk_paxc_axi_x2",
 					     "clk_paxc_axi";
 		};
 
+		genpll2: genpll2 at 1d1ac {
+			#clock-cells = <1>;
+			compatible = "brcm,sr-genpll2";
+			reg = <0x0001d1ac 0x32>,
+			      <0x0001c854 0x4>;
+			clocks = <&osc>;
+			clock-output-names = "genpll2", "clk_nic",
+					     "clk_ts_500_ref", "clk_125_nitro",
+					     "clk_chimp", "clk_nic_flash",
+					     "clk_fs";
+		};
+
 		genpll3: genpll3 at 1d1e0 {
 			#clock-cells = <1>;
 			compatible = "brcm,sr-genpll3";
@@ -75,8 +87,8 @@
 			      <0x0001c854 0x4>;
 			clocks = <&osc>;
 			clock-output-names = "genpll4", "clk_ccn",
-					     "clk_tpiu_pll", "noc_clk",
-					     "pll_chclk_fs4",
+					     "clk_tpiu_pll", "clk_noc",
+					     "clk_chclk_fs4",
 					     "clk_bridge_fscpu";
 		};
 
@@ -86,8 +98,8 @@
 			reg = <0x0001d248 0x32>,
 			      <0x0001c870 0x4>;
 			clocks = <&osc>;
-			clock-output-names = "genpll5", "fs4_hf_clk",
-					     "crypto_ae_clk", "raid_ae_clk";
+			clock-output-names = "genpll5", "clk_fs4_hf",
+					     "clk_crypto_ae", "clk_raid_ae";
 		};
 
 		lcpll0: lcpll0 at 1d0c4 {
@@ -107,9 +119,9 @@
 			reg = <0x0001d138 0x3c>,
 			      <0x0001c870 0x4>;
 			clocks = <&osc>;
-			clock-output-names = "lcpll1", "clk_wanpn",
+			clock-output-names = "lcpll1", "clk_wan",
 					     "clk_usb_ref",
-					     "timesync_evt_clk";
+					     "clk_crmu_ts";
 		};
 
 		hsls_clk: hsls_clk {
-- 
2.1.4

^ permalink raw reply related

* [PATCH 2/3] clk: bcm: Update and add tingray clock entries
From: Ray Jui @ 2018-05-25 16:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527266717-8406-1-git-send-email-ray.jui@broadcom.com>

Update and add Stingray clock definitions and tables so they match the
binding document and the latest ASIC datasheet

Signed-off-by: Pramod Kumar <pramod.kumar@broadcom.com>
Signed-off-by: Ray Jui <ray.jui@broadcom.com>
---
 drivers/clk/bcm/clk-sr.c           | 135 ++++++++++++++++++++++++++++++++-----
 include/dt-bindings/clock/bcm-sr.h |  24 +++++--
 2 files changed, 137 insertions(+), 22 deletions(-)

diff --git a/drivers/clk/bcm/clk-sr.c b/drivers/clk/bcm/clk-sr.c
index adc74f4..7b9efc0 100644
--- a/drivers/clk/bcm/clk-sr.c
+++ b/drivers/clk/bcm/clk-sr.c
@@ -56,8 +56,8 @@ static const struct iproc_pll_ctrl sr_genpll0 = {
 };
 
 static const struct iproc_clk_ctrl sr_genpll0_clk[] = {
-	[BCM_SR_GENPLL0_SATA_CLK] = {
-		.channel = BCM_SR_GENPLL0_SATA_CLK,
+	[BCM_SR_GENPLL0_125M_CLK] = {
+		.channel = BCM_SR_GENPLL0_125M_CLK,
 		.flags = IPROC_CLK_AON,
 		.enable = ENABLE_VAL(0x4, 6, 0, 12),
 		.mdiv = REG_VAL(0x18, 0, 9),
@@ -102,6 +102,65 @@ static int sr_genpll0_clk_init(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct iproc_pll_ctrl sr_genpll2 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
+		IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 1, 13, 12),
+	.reset = RESET_VAL(0x0, 12, 11),
+	.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
+	.sw_ctrl = SW_CTRL_VAL(0x10, 31),
+	.ndiv_int = REG_VAL(0x10, 20, 10),
+	.ndiv_frac = REG_VAL(0x10, 0, 20),
+	.pdiv = REG_VAL(0x14, 0, 4),
+	.status = REG_VAL(0x30, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_genpll2_clk[] = {
+	[BCM_SR_GENPLL2_NIC_CLK] = {
+		.channel = BCM_SR_GENPLL2_NIC_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 6, 0, 12),
+		.mdiv = REG_VAL(0x18, 0, 9),
+	},
+	[BCM_SR_GENPLL2_TS_500_CLK] = {
+		.channel = BCM_SR_GENPLL2_TS_500_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 7, 1, 13),
+		.mdiv = REG_VAL(0x18, 10, 9),
+	},
+	[BCM_SR_GENPLL2_125_NITRO_CLK] = {
+		.channel = BCM_SR_GENPLL2_125_NITRO_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 8, 2, 14),
+		.mdiv = REG_VAL(0x18, 20, 9),
+	},
+	[BCM_SR_GENPLL2_CHIMP_CLK] = {
+		.channel = BCM_SR_GENPLL2_CHIMP_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 9, 3, 15),
+		.mdiv = REG_VAL(0x1c, 0, 9),
+	},
+	[BCM_SR_GENPLL2_NIC_FLASH_CLK] = {
+		.channel = BCM_SR_GENPLL2_NIC_FLASH_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 10, 4, 16),
+		.mdiv = REG_VAL(0x1c, 10, 9),
+	},
+	[BCM_SR_GENPLL2_FS4_CLK] = {
+		.channel = BCM_SR_GENPLL2_FS4_CLK,
+		.enable = ENABLE_VAL(0x4, 11, 5, 17),
+		.mdiv = REG_VAL(0x1c, 20, 9),
+	},
+};
+
+static int sr_genpll2_clk_init(struct platform_device *pdev)
+{
+	iproc_pll_clk_setup(pdev->dev.of_node,
+			    &sr_genpll2, NULL, 0, sr_genpll2_clk,
+			    ARRAY_SIZE(sr_genpll2_clk));
+	return 0;
+}
+
 static const struct iproc_pll_ctrl sr_genpll3 = {
 	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
 		IPROC_CLK_PLL_NEEDS_SW_CFG,
@@ -157,6 +216,30 @@ static const struct iproc_clk_ctrl sr_genpll4_clk[] = {
 		.enable = ENABLE_VAL(0x4, 6, 0, 12),
 		.mdiv = REG_VAL(0x18, 0, 9),
 	},
+	[BCM_SR_GENPLL4_TPIU_PLL_CLK] = {
+		.channel = BCM_SR_GENPLL4_TPIU_PLL_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 7, 1, 13),
+		.mdiv = REG_VAL(0x18, 10, 9),
+	},
+	[BCM_SR_GENPLL4_NOC_CLK] = {
+		.channel = BCM_SR_GENPLL4_NOC_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 8, 2, 14),
+		.mdiv = REG_VAL(0x18, 20, 9),
+	},
+	[BCM_SR_GENPLL4_CHCLK_FS4_CLK] = {
+		.channel = BCM_SR_GENPLL4_CHCLK_FS4_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 9, 3, 15),
+		.mdiv = REG_VAL(0x1c, 0, 9),
+	},
+	[BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK] = {
+		.channel = BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 10, 4, 16),
+		.mdiv = REG_VAL(0x1c, 10, 9),
+	},
 };
 
 static int sr_genpll4_clk_init(struct platform_device *pdev)
@@ -181,18 +264,21 @@ static const struct iproc_pll_ctrl sr_genpll5 = {
 };
 
 static const struct iproc_clk_ctrl sr_genpll5_clk[] = {
-	[BCM_SR_GENPLL5_FS_CLK] = {
-		.channel = BCM_SR_GENPLL5_FS_CLK,
-		.flags = IPROC_CLK_AON,
+	[BCM_SR_GENPLL5_FS4_HF_CLK] = {
+		.channel = BCM_SR_GENPLL5_FS4_HF_CLK,
 		.enable = ENABLE_VAL(0x4, 6, 0, 12),
 		.mdiv = REG_VAL(0x18, 0, 9),
 	},
-	[BCM_SR_GENPLL5_SPU_CLK] = {
-		.channel = BCM_SR_GENPLL5_SPU_CLK,
-		.flags = IPROC_CLK_AON,
-		.enable = ENABLE_VAL(0x4, 6, 0, 12),
+	[BCM_SR_GENPLL5_CRYPTO_AE_CLK] = {
+		.channel = BCM_SR_GENPLL5_CRYPTO_AE_CLK,
+		.enable = ENABLE_VAL(0x4, 7, 1, 12),
 		.mdiv = REG_VAL(0x18, 10, 9),
 	},
+	[BCM_SR_GENPLL5_RAID_AE_CLK] = {
+		.channel = BCM_SR_GENPLL5_RAID_AE_CLK,
+		.enable = ENABLE_VAL(0x4, 8, 2, 14),
+		.mdiv = REG_VAL(0x18, 20, 9),
+	},
 };
 
 static int sr_genpll5_clk_init(struct platform_device *pdev)
@@ -214,24 +300,30 @@ static const struct iproc_pll_ctrl sr_lcpll0 = {
 };
 
 static const struct iproc_clk_ctrl sr_lcpll0_clk[] = {
-	[BCM_SR_LCPLL0_SATA_REF_CLK] = {
-		.channel = BCM_SR_LCPLL0_SATA_REF_CLK,
+	[BCM_SR_LCPLL0_SATA_REFP_CLK] = {
+		.channel = BCM_SR_LCPLL0_SATA_REFP_CLK,
 		.flags = IPROC_CLK_AON,
 		.enable = ENABLE_VAL(0x0, 7, 1, 13),
 		.mdiv = REG_VAL(0x14, 0, 9),
 	},
-	[BCM_SR_LCPLL0_USB_REF_CLK] = {
-		.channel = BCM_SR_LCPLL0_USB_REF_CLK,
+	[BCM_SR_LCPLL0_SATA_REFN_CLK] = {
+		.channel = BCM_SR_LCPLL0_SATA_REFN_CLK,
 		.flags = IPROC_CLK_AON,
 		.enable = ENABLE_VAL(0x0, 8, 2, 14),
 		.mdiv = REG_VAL(0x14, 10, 9),
 	},
-	[BCM_SR_LCPLL0_SATA_REFPN_CLK] = {
-		.channel = BCM_SR_LCPLL0_SATA_REFPN_CLK,
+	[BCM_SR_LCPLL0_SATA_350_CLK] = {
+		.channel = BCM_SR_LCPLL0_SATA_350_CLK,
 		.flags = IPROC_CLK_AON,
 		.enable = ENABLE_VAL(0x0, 9, 3, 15),
 		.mdiv = REG_VAL(0x14, 20, 9),
 	},
+	[BCM_SR_LCPLL0_SATA_500_CLK] = {
+		.channel = BCM_SR_LCPLL0_SATA_500_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 10, 4, 16),
+		.mdiv = REG_VAL(0x18, 0, 9),
+	},
 };
 
 static int sr_lcpll0_clk_init(struct platform_device *pdev)
@@ -259,6 +351,18 @@ static const struct iproc_clk_ctrl sr_lcpll1_clk[] = {
 		.enable = ENABLE_VAL(0x0, 7, 1, 13),
 		.mdiv = REG_VAL(0x14, 0, 9),
 	},
+	[BCM_SR_LCPLL1_USB_REF_CLK] = {
+		.channel = BCM_SR_LCPLL1_USB_REF_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 8, 2, 14),
+		.mdiv = REG_VAL(0x14, 10, 9),
+	},
+	[BCM_SR_LCPLL1_CRMU_TS_CLK] = {
+		.channel = BCM_SR_LCPLL1_CRMU_TS_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 9, 3, 15),
+		.mdiv = REG_VAL(0x14, 20, 9),
+	},
 };
 
 static int sr_lcpll1_clk_init(struct platform_device *pdev)
@@ -298,6 +402,7 @@ static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)
 
 static const struct of_device_id sr_clk_dt_ids[] = {
 	{ .compatible = "brcm,sr-genpll0", .data = sr_genpll0_clk_init },
+	{ .compatible = "brcm,sr-genpll2", .data = sr_genpll2_clk_init },
 	{ .compatible = "brcm,sr-genpll4", .data = sr_genpll4_clk_init },
 	{ .compatible = "brcm,sr-genpll5", .data = sr_genpll5_clk_init },
 	{ .compatible = "brcm,sr-lcpll0", .data = sr_lcpll0_clk_init },
diff --git a/include/dt-bindings/clock/bcm-sr.h b/include/dt-bindings/clock/bcm-sr.h
index cff6c6f..419011b 100644
--- a/include/dt-bindings/clock/bcm-sr.h
+++ b/include/dt-bindings/clock/bcm-sr.h
@@ -35,7 +35,7 @@
 
 /* GENPLL 0 clock channel ID SCR HSLS FS PCIE */
 #define BCM_SR_GENPLL0			0
-#define BCM_SR_GENPLL0_SATA_CLK		1
+#define BCM_SR_GENPLL0_125M_CLK		1
 #define BCM_SR_GENPLL0_SCR_CLK		2
 #define BCM_SR_GENPLL0_250M_CLK		3
 #define BCM_SR_GENPLL0_PCIE_AXI_CLK	4
@@ -50,9 +50,11 @@
 /* GENPLL 2 clock channel ID NITRO MHB*/
 #define BCM_SR_GENPLL2			0
 #define BCM_SR_GENPLL2_NIC_CLK		1
-#define BCM_SR_GENPLL2_250_NITRO_CLK	2
+#define BCM_SR_GENPLL2_TS_500_CLK	2
 #define BCM_SR_GENPLL2_125_NITRO_CLK	3
 #define BCM_SR_GENPLL2_CHIMP_CLK	4
+#define BCM_SR_GENPLL2_NIC_FLASH_CLK	5
+#define BCM_SR_GENPLL2_FS4_CLK		6
 
 /* GENPLL 3 HSLS clock channel ID */
 #define BCM_SR_GENPLL3			0
@@ -62,11 +64,16 @@
 /* GENPLL 4 SCR clock channel ID */
 #define BCM_SR_GENPLL4			0
 #define BCM_SR_GENPLL4_CCN_CLK		1
+#define BCM_SR_GENPLL4_TPIU_PLL_CLK	2
+#define BCM_SR_GENPLL4_NOC_CLK		3
+#define BCM_SR_GENPLL4_CHCLK_FS4_CLK	4
+#define BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK	5
 
 /* GENPLL 5 FS4 clock channel ID */
 #define BCM_SR_GENPLL5			0
-#define BCM_SR_GENPLL5_FS_CLK		1
-#define BCM_SR_GENPLL5_SPU_CLK		2
+#define BCM_SR_GENPLL5_FS4_HF_CLK	1
+#define BCM_SR_GENPLL5_CRYPTO_AE_CLK	2
+#define BCM_SR_GENPLL5_RAID_AE_CLK	3
 
 /* GENPLL 6 NITRO clock channel ID */
 #define BCM_SR_GENPLL6			0
@@ -74,13 +81,16 @@
 
 /* LCPLL0  clock channel ID */
 #define BCM_SR_LCPLL0			0
-#define BCM_SR_LCPLL0_SATA_REF_CLK	1
-#define BCM_SR_LCPLL0_USB_REF_CLK	2
-#define BCM_SR_LCPLL0_SATA_REFPN_CLK	3
+#define BCM_SR_LCPLL0_SATA_REFP_CLK	1
+#define BCM_SR_LCPLL0_SATA_REFN_CLK	2
+#define BCM_SR_LCPLL0_SATA_350_CLK	3
+#define BCM_SR_LCPLL0_SATA_500_CLK	4
 
 /* LCPLL1  clock channel ID */
 #define BCM_SR_LCPLL1			0
 #define BCM_SR_LCPLL1_WAN_CLK		1
+#define BCM_SR_LCPLL1_USB_REF_CLK	2
+#define BCM_SR_LCPLL1_CRMU_TS_CLK	3
 
 /* LCPLL PCIE  clock channel ID */
 #define BCM_SR_LCPLL_PCIE		0
-- 
2.1.4

^ permalink raw reply related

* [PATCH 1/3] dt-bindings: clk: Update Stingray binding doc
From: Ray Jui @ 2018-05-25 16:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527266717-8406-1-git-send-email-ray.jui@broadcom.com>

Update Stingray clock binding document to add additional clock entries
with names matching the latest ASIC datasheet. Also modify a few existing
entries to make their naming more consistent with the rest of the entries

Signed-off-by: Pramod Kumar <pramod.kumar@broadcom.com>
Signed-off-by: Ray Jui <ray.jui@broadcom.com>
---
 .../bindings/clock/brcm,iproc-clocks.txt           | 26 ++++++++++++----------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
index f8e4a93..ab730ea 100644
--- a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
@@ -276,36 +276,38 @@ These clock IDs are defined in:
     clk_ts_500_ref	genpll2		2	BCM_SR_GENPLL2_TS_500_REF_CLK
     clk_125_nitro	genpll2		3	BCM_SR_GENPLL2_125_NITRO_CLK
     clk_chimp		genpll2		4	BCM_SR_GENPLL2_CHIMP_CLK
-    clk_nic_flash	genpll2		5	BCM_SR_GENPLL2_NIC_FLASH
+    clk_nic_flash	genpll2		5	BCM_SR_GENPLL2_NIC_FLASH_CLK
+    clk_fs		genpll2		6	BCM_SR_GENPLL2_FS_CLK
 
     genpll3		crystal		0	BCM_SR_GENPLL3
     clk_hsls		genpll3		1	BCM_SR_GENPLL3_HSLS_CLK
     clk_sdio		genpll3		2	BCM_SR_GENPLL3_SDIO_CLK
 
     genpll4		crystal		0	BCM_SR_GENPLL4
-    ccn			genpll4		1	BCM_SR_GENPLL4_CCN_CLK
+    clk_ccn		genpll4		1	BCM_SR_GENPLL4_CCN_CLK
     clk_tpiu_pll	genpll4		2	BCM_SR_GENPLL4_TPIU_PLL_CLK
-    noc_clk		genpll4		3	BCM_SR_GENPLL4_NOC_CLK
+    clk_noc		genpll4		3	BCM_SR_GENPLL4_NOC_CLK
     clk_chclk_fs4	genpll4		4	BCM_SR_GENPLL4_CHCLK_FS4_CLK
     clk_bridge_fscpu	genpll4		5	BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK
 
-
     genpll5		crystal		0	BCM_SR_GENPLL5
-    fs4_hf_clk		genpll5		1	BCM_SR_GENPLL5_FS4_HF_CLK
-    crypto_ae_clk	genpll5		2	BCM_SR_GENPLL5_CRYPTO_AE_CLK
-    raid_ae_clk		genpll5		3	BCM_SR_GENPLL5_RAID_AE_CLK
+    clk_fs4_hf		genpll5		1	BCM_SR_GENPLL5_FS4_HF_CLK
+    clk_crypto_ae	genpll5		2	BCM_SR_GENPLL5_CRYPTO_AE_CLK
+    clk_raid_ae		genpll5		3	BCM_SR_GENPLL5_RAID_AE_CLK
 
     genpll6		crystal		0	BCM_SR_GENPLL6
-    48_usb		genpll6		1	BCM_SR_GENPLL6_48_USB_CLK
+    clk_48_usb		genpll6		1	BCM_SR_GENPLL6_48_USB_CLK
 
     lcpll0		crystal		0	BCM_SR_LCPLL0
     clk_sata_refp 	lcpll0		1	BCM_SR_LCPLL0_SATA_REFP_CLK
     clk_sata_refn	lcpll0		2	BCM_SR_LCPLL0_SATA_REFN_CLK
-    clk_usb_ref		lcpll0		3	BCM_SR_LCPLL0_USB_REF_CLK
-    sata_refpn		lcpll0		3	BCM_SR_LCPLL0_SATA_REFPN_CLK
+    clk_sata_350	lcpll0		3	BCM_SR_LCPLL0_SATA_350_CLK
+    clk_sata_500	lcpll0		4	BCM_SR_LCPLL0_SATA_500_CLK
 
     lcpll1		crystal		0	BCM_SR_LCPLL1
-    wan 		lcpll1		1	BCM_SR_LCPLL0_WAN_CLK
+    clk_wan		lcpll1		1	BCM_SR_LCPLL1_WAN_CLK
+    clk_usb_ref		lcpll1		2	BCM_SR_LCPLL1_USB_REF_CLK
+    clk_crmu_ts		lcpll1		3	BCM_SR_LCPLL1_CRMU_TS_CLK
 
     lcpll_pcie		crystal		0	BCM_SR_LCPLL_PCIE
-    pcie_phy_ref 	lcpll1		1	BCM_SR_LCPLL_PCIE_PHY_REF_CLK
+    clk_pcie_phy_ref	lcpll1		1	BCM_SR_LCPLL_PCIE_PHY_REF_CLK
-- 
2.1.4

^ permalink raw reply related

* [PATCH 0/3] Update Broadcom Stingray clock entries
From: Ray Jui @ 2018-05-25 16:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series updates Broadcom Stingray clock entries so they match the
latest ASIC datasheet

This patch series is based off v4.17-rc5 and is available on GIHUB:
repo: https://github.com/Broadcom/arm64-linux.git
branch: sr-clk-v1

Ray Jui (3):
  dt-bindings: clk: Update Stingray binding doc
  clk: bcm: Update and add tingray clock entries
  arm64: dts: Update Stingray clock DT nodes

 .../bindings/clock/brcm,iproc-clocks.txt           |  26 ++--
 .../boot/dts/broadcom/stingray/stingray-clock.dtsi |  26 ++--
 drivers/clk/bcm/clk-sr.c                           | 135 ++++++++++++++++++---
 include/dt-bindings/clock/bcm-sr.h                 |  24 ++--
 4 files changed, 170 insertions(+), 41 deletions(-)

-- 
2.1.4

^ permalink raw reply

* [PATCH 08/11] coresight: Add generic TMC sg table framework
From: Mathieu Poirier @ 2018-05-25 16:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <21fef51b-2afe-1a2c-6006-5cf3de4e74e8@arm.com>

On Fri, May 25, 2018 at 05:07:07PM +0100, Suzuki K Poulose wrote:
> On 23/05/18 21:25, Mathieu Poirier wrote:
> >On Fri, May 18, 2018 at 05:39:24PM +0100, Suzuki K Poulose wrote:
> >>This patch introduces a generic sg table data structure and
> >>associated operations. An SG table can be used to map a set
> >>of Data pages where the trace data could be stored by the TMC
> >>ETR. The information about the data pages could be stored in
> >>different formats, depending on the type of the underlying
> >>SG mechanism (e.g, TMC ETR SG vs Coresight CATU). The generic
> >>structure provides book keeping of the pages used for the data
> >>as well as the table contents. The table should be filled by
> >>the user of the infrastructure.
> >>
> >>A table can be created by specifying the number of data pages
> >>as well as the number of table pages required to hold the
> >>pointers, where the latter could be different for different
> >>types of tables. The pages are mapped in the appropriate dma
> >>data direction mode (i.e, DMA_TO_DEVICE for table pages
> >>and DMA_FROM_DEVICE for data pages).  The framework can optionally
> >>accept a set of allocated data pages (e.g, perf ring buffer) and
> >>map them accordingly. The table and data pages are vmap'ed to allow
> >>easier access by the drivers. The framework also provides helpers to
> >>sync the data written to the pages with appropriate directions.
> >>
> >>This will be later used by the TMC ETR SG unit and CATU.
> >>
> >>Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
> >>Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >>---
> >>Changes since v1:
> >>  - Address code style issues, more comments
> >>---
> >>  drivers/hwtracing/coresight/coresight-tmc-etr.c | 290 ++++++++++++++++++++++++
> >>  drivers/hwtracing/coresight/coresight-tmc.h     |  50 ++++
> >>  2 files changed, 340 insertions(+)
> >>
> >>diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> >>index 9780798..1e844f8 100644
> >>--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> >>+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> >>@@ -17,9 +17,299 @@
> 
> 
> >>+static inline dma_addr_t tmc_sg_table_base_paddr(struct tmc_sg_table *sg_table)
> >>+{
> >>+	if (WARN_ON(!sg_table->data_pages.pages[0]))
> >>+		return 0;
> >>+	return sg_table->table_daddr;
> >>+}
> >>+
> >>+static inline void *tmc_sg_table_base_vaddr(struct tmc_sg_table *sg_table)
> >>+{
> >>+	if (WARN_ON(!sg_table->data_pages.pages[0]))
> >>+		return NULL;
> >>+	return sg_table->table_vaddr;
> >>+}
> >
> >The above two functions deal with DMA'able and virtual addresses for the table
> >page buffer.  Yet the test in the WARN_ON is done on the data page array.
> >Shouldn't this be sg_table->table_pages.pages[0] instead?
> 
> The table is as good as empty if there are no data pages associated with
> the table. Hence the data_pages check.

That is correct.  On the flip side you can't have data_pages without table_pages
and vice versa, hence my comment.

> 
> >
> >If not please add a comment justifying your position so that someone else
> >looking at the code does't end up thinking the same in a year from now.
> 
> I will add a comment to reflect the above.
> 
> >
> >>+
> >>+static inline void *
> >>+tmc_sg_table_data_vaddr(struct tmc_sg_table *sg_table)
> >>+{
> >>+	if (WARN_ON(!sg_table->data_pages.nr_pages))
> >>+		return 0;
> >>+	return sg_table->data_vaddr;
> >>+}
> >
> >I see that tmc_sg_table_base_vaddr() and tmc_sg_table_data_vaddr() are both
> >returning the virtual address of the contiguous buffer for table and data
> >respectively.  Yet there is a discrepency in the naming convention.  I would
> >have expected tmc_sg_table_base_vaddr() and tmc_sg_data_base_vaddr() so that
> >there is a little symmetry between them.
> 
> Agree. I will fix it.
> 
> Suzuki

^ permalink raw reply

* [PATCH v3 00/15] ARM Spectre variant 2 fixes
From: Tony Lindgren @ 2018-05-25 16:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525135938.GE17671@n2100.armlinux.org.uk>

* Russell King - ARM Linux <linux@armlinux.org.uk> [180525 07:02]:
> Third version:
> - Remove "PSCI" from the SMC version of the workaround as well.
> - Avoid reporting active workaround if the IBE bit is not set.
> - Only probe for workaround_1 on Cortex A57 and A72, or non-ARM CPUs.
> - Require features probe for workaround_1 to return zero.
> - Validation that all CPUs in the system have the same workaround status.
> - Avoid corrupting r12 in workaround_1 KVM hypervisor implementation.

Looks good to me and things still work for me. I don't really
want to count that as Tested-by though :) But feel free to add:

Boot-tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply

* [GIT PULL v3] arm64: defconfig: hisilicon config updates for v4.18
From: Wei Xu @ 2018-05-25 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Olof, Hi Arnd,

Please help to pull the following changes.
Thanks!

Best Regards,
Wei

---

The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:

  Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)

are available in the Git repository at:

  git://github.com/hisilicon/linux-hisi.git tags/hisi-defconfig-for-4.18v3

for you to fetch changes up to 30480a849820d728c409e90bd6715d11f4071416:

  arm64: defconfig: Enable HISILICON_LPC (2018-05-25 16:58:51 +0100)

----------------------------------------------------------------
ARM64: hisilicon: defconfig updates for 4.18

- Enable the support of ethernet, eMMC, Combo/INNO phy
  and PCIe for Hi3798CV200
- Enable the LPC for hip06 and hip07

----------------------------------------------------------------
John Garry (1):
      arm64: defconfig: Enable HISILICON_LPC

Shawn Guo (1):
      arm64: defconfig: enable drivers for Poplar support

 arch/arm64/configs/defconfig | 6 ++++++
 1 file changed, 6 insertions(+)

^ permalink raw reply

* [GIT PULL v2] arm64: defconfig: hisilicon config updates for v4.18
From: Wei Xu @ 2018-05-25 16:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525120140.d5gtksg62xlr6cz3@localhost>

Hi Olof,

On 2018/5/25 13:01, Olof Johansson wrote:
> On Fri, May 18, 2018 at 11:58:40AM +0100, Wei Xu wrote:
>> Hi Olof, Hi Arnd,
>>
>> Please help to pull the following changes.
>> Thanks!
>>
>> Best Regards,
>> Wei
>>
>> ---
>>
>> The following changes since commit 60cc43fc888428bb2f18f08997432d426a243338:
>>
>>   Linux 4.17-rc1 (2018-04-15 18:24:20 -0700)
>>
>> are available in the Git repository at:
>>
>>   git://github.com/hisilicon/linux-hisi.git tags/hisi-defconfig-for-4.18v2
>>
>> for you to fetch changes up to 9ab1c973324566baa314f8dd4e3827e4076a8675:
>>
>>   arm64: defconfig: Enable HISILICON_LPC (2018-05-11 11:39:01 +0100)
>>
>> ----------------------------------------------------------------
>> ARM64: hisilicon: defconfig updates for 4.18
>>
>> - Sync the arm64 defconfig with savedefconfig
>> - Enable the support of ethernet, eMMC, Combo/INNO phy
>>   and PCIe for Hi3798CV200
>> - Enable the LPC for hip06 and hip07
>>
>> ----------------------------------------------------------------
>> John Garry (1):
>>       arm64: defconfig: Enable HISILICON_LPC
>>
>> Shawn Guo (2):
>>       arm64: defconfig: sync it with savedefconfig
> 
> Same feedback here as for  Gregory on his Marvell pull request -- please don't
> run savedefconfig since it messes up and adds a lot of conflicts for everybody.
> We'll do it in our tree right around the end of the merge window instead.

Got it.

> 
> It's probably easiest to send the patches as patches so we can fix them up if
> needed, so please resend separately and we'll apply. (Or send a new pull
> request with just the two new config changes).

I will send a new pull request with the new config changes.
Thanks!

Best Regards,
Wei

> 
> Thanks!
> 
> 
> -Olof
> 
> .
> 

^ permalink raw reply

* [PATCH v3 08/15] ARM: spectre-v2: harden user aborts in kernel space
From: Tony Lindgren @ 2018-05-25 16:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525160119.GC98604@atomide.com>

* Tony Lindgren <tony@atomide.com> [180525 16:04]:
> * Russell King - ARM Linux <linux@armlinux.org.uk> [180525 15:54]:
> > On Fri, May 25, 2018 at 08:47:42AM -0700, Tony Lindgren wrote:
> > > We can now get this with the whole series applied:
> > > 
> > > CPU0: Spectre v2: firmware did not set auxiliary control register
> > > IBE bit, system vulnerable
> > > CPU: Spectre v2: using ICIALLU workaround
> > > 
> > > So maybe change the wording from "using %s workaround" to
> > > "chosen workaround %s"?
> > > 
> > > Or I guess disabling the pr_info when not functional can
> > > be done in the later patches based on some variable set
> > > by check_spectre_auxcr() would be doable too.
> > 
> > You should not be getting both messages.  It looks like you're using
> > an older series - I assumed you pulled my git tree rather than the
> > patches?  The public git tree isn't up to date with these changes.
> 
> Yes I just fetched your git tree because it allows using
> git mergetool because of the conflicts with next. I'll apply
> manually and test again.

And testing with the correct patches in the $subject series
makes the issue go away.

Regards,

Tony

^ permalink raw reply

* [PATCH v3 7/8] drm/mediatek: Add support for mediatek SOC MT2712
From: kbuild test robot @ 2018-05-25 16:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1527215665-11937-8-git-send-email-stu.hsieh@mediatek.com>

Hi Stu,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.17-rc6 next-20180517]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/stu-hsieh-mediatek-com/Add-support-for-mediatek-SOC-MT2712/20180525-211114
base:   git://people.freedesktop.org/~airlied/linux.git drm-next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:165:2: error: 'DDP_COMPONENT_DPI1' undeclared here (not in a function); did you mean 'DDP_COMPONENT_DSI1'?
     DDP_COMPONENT_DPI1,
     ^~~~~~~~~~~~~~~~~~
     DDP_COMPONENT_DSI1
>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:171:2: error: 'DDP_COMPONENT_DSI2' undeclared here (not in a function); did you mean 'DDP_COMPONENT_DSI1'?
     DDP_COMPONENT_DSI2,
     ^~~~~~~~~~~~~~~~~~
     DDP_COMPONENT_DSI1
>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:171:2: error: incompatible types when initializing type 'enum mtk_ddp_comp_id' using type 'const enum mtk_ddp_comp_id *'
>> drivers/gpu//drm/mediatek/mtk_drm_drv.c:207:16: warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
     .third_path = mt2712_mtk_ddp_third,
                   ^~~~~~~~~~~~~~~~~~~~

vim +165 drivers/gpu//drm/mediatek/mtk_drm_drv.c

   158	
   159	static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = {
   160		DDP_COMPONENT_OVL1,
   161		DDP_COMPONENT_COLOR1,
   162		DDP_COMPONENT_AAL1,
   163		DDP_COMPONENT_OD1,
   164		DDP_COMPONENT_RDMA1,
 > 165		DDP_COMPONENT_DPI1,
   166		DDP_COMPONENT_PWM1,
   167	};
   168	
   169	static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third[] = {
   170		DDP_COMPONENT_RDMA2,
 > 171		DDP_COMPONENT_DSI2,
   172		DDP_COMPONENT_PWM2,
   173	};
   174	
   175	static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
   176		DDP_COMPONENT_OVL0,
   177		DDP_COMPONENT_COLOR0,
   178		DDP_COMPONENT_AAL0,
   179		DDP_COMPONENT_OD0,
   180		DDP_COMPONENT_RDMA0,
   181		DDP_COMPONENT_UFOE,
   182		DDP_COMPONENT_DSI0,
   183		DDP_COMPONENT_PWM0,
   184	};
   185	
   186	static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
   187		DDP_COMPONENT_OVL1,
   188		DDP_COMPONENT_COLOR1,
   189		DDP_COMPONENT_GAMMA,
   190		DDP_COMPONENT_RDMA1,
   191		DDP_COMPONENT_DPI0,
   192	};
   193	
   194	static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
   195		.main_path = mt2701_mtk_ddp_main,
   196		.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
   197		.ext_path = mt2701_mtk_ddp_ext,
   198		.ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
   199		.shadow_register = true,
   200	};
   201	
   202	static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
   203		.main_path = mt2712_mtk_ddp_main,
   204		.main_len = ARRAY_SIZE(mt2712_mtk_ddp_main),
   205		.ext_path = mt2712_mtk_ddp_ext,
   206		.ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext),
 > 207		.third_path = mt2712_mtk_ddp_third,
   208		.third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
   209	};
   210	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 65211 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180526/893bcab4/attachment-0001.gz>

^ permalink raw reply

* [PATCH 2/2] ARM: shmobile: only call secure_cntvoff_init on SMP builds
From: Arnd Bergmann @ 2018-05-25 16:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525161051.187324-1-arnd@arndb.de>

The secure_cntvoff_init() function is not available without CONFIG_SMP,
leading to a link error on shmobile:

arch/arm/mach-shmobile/setup-rcar-gen2.o: In function `rcar_gen2_timer_init':
setup-rcar-gen2.c:(.init.text+0x18): undefined reference to `secure_cntvoff_init'

>From the description in commit 3fd45a136ff6 ("ARM: shmobile: rcar-gen2:
Make sure CNTVOFF is initialized on CA7/15"), I understand that we
don't need to call it on non-SMP builds because the boot CPU is always
initialized by common code, so we can simply avoid the reference by
checking for CONFIG_SMP.

Fixes: cad160ed0a94 ("ARM: shmobile: Convert file to use cntvoff")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-shmobile/setup-rcar-gen2.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index 88fdc1801d90..39085d7a8f37 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -71,7 +71,8 @@ void __init rcar_gen2_timer_init(void)
 	void __iomem *base;
 	u32 freq;
 
-	secure_cntvoff_init();
+	if (IS_ENABLED(CONFIG_SMP))
+		secure_cntvoff_init();
 
 	if (of_machine_is_compatible("renesas,r8a7745") ||
 	    of_machine_is_compatible("renesas,r8a77470") ||
-- 
2.9.0

^ permalink raw reply related

* [PATCH 1/2] ARM: stm32: Don't select DMA unconditionally on STM32MP157C
From: Arnd Bergmann @ 2018-05-25 16:10 UTC (permalink / raw)
  To: linux-arm-kernel

The patch that enabled these had no useful changelog that explains
why it is done, and it causes a build warning:

WARNING: unmet direct dependencies detected for STM32_DMA
  Depends on [n]: DMADEVICES [=n] && (ARCH_STM32 [=y] || COMPILE_TEST [=y])
  Selected by [y]:
  - MACH_STM32MP157 [=y] && ARCH_STM32 [=y] && ARCH_MULTI_V7 [=y]

Generally, platforms should not select arbitrary drivers, so let's
just revert that change.

Fixes: de6037fa207f ("ARM: stm32: Select DMA, DMAMUX and MDMA support on STM32MP157C")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-stm32/Kconfig | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index 82a93b8d9ae6..713c068b953f 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -46,9 +46,6 @@ if ARCH_MULTI_V7
 
 config MACH_STM32MP157
 	bool "STMicroelectronics STM32MP157"
-	select STM32_DMA
-	select STM32_DMAMUX
-	select STM32_MDMA
 	default y
 
 endif # ARMv7-A
-- 
2.9.0

^ permalink raw reply related

* [PATCH 1/2] ARM: stm32: Don't select DMA unconditionally on STM32MP157C
From: Arnd Bergmann @ 2018-05-25 16:09 UTC (permalink / raw)
  To: linux-arm-kernel

The patch that enabled these had no useful changelog that explains
why it is done, and it causes a build warning:

WARNING: unmet direct dependencies detected for STM32_DMA
  Depends on [n]: DMADEVICES [=n] && (ARCH_STM32 [=y] || COMPILE_TEST [=y])
  Selected by [y]:
  - MACH_STM32MP157 [=y] && ARCH_STM32 [=y] && ARCH_MULTI_V7 [=y]

Generally, platforms should not select arbitrary drivers, so let's
just revert that change.

Fixes: de6037fa207f ("ARM: stm32: Select DMA, DMAMUX and MDMA support on STM32MP157C")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-stm32/Kconfig | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index 82a93b8d9ae6..713c068b953f 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -46,9 +46,6 @@ if ARCH_MULTI_V7
 
 config MACH_STM32MP157
 	bool "STMicroelectronics STM32MP157"
-	select STM32_DMA
-	select STM32_DMAMUX
-	select STM32_MDMA
 	default y
 
 endif # ARMv7-A
-- 
2.9.0

^ permalink raw reply related

* [PATCH] arm64: vgic-v2: Fix proxying of cpuif access
From: Andrew Jones @ 2018-05-25 16:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180429140507.60bfe2dc@why.wild-wind.fr.eu.org>

On Sun, Apr 29, 2018 at 02:05:07PM +0100, Marc Zyngier wrote:
> On Sun, 29 Apr 2018 14:34:32 +0200
> Christoffer Dall <christoffer.dall@arm.com> wrote:
> 
> > On Fri, Apr 27, 2018 at 03:51:02PM +0100, Marc Zyngier wrote:
> > > Proxying the cpuif accesses at EL2 makes use of vcpu_data_guest_to_host
> > > and co, which check the endianness, which call into vcpu_read_sys_reg...
> > > which isn't mapped at EL2 (it was inlined before, and got moved OoL
> > > with the VHE optimizations).  
> > 
> > I thought we relied on static inline functions to always be inlined, but
> > apparently not?  Does this mean we have potential other bugs looming
> > depending on the mood of the compiler, or was there something special
> > that went wrong here?
> 
> We do rely on that behaviour. And that was the case until you moved
> vcpu_read_sys_reg() to be entirely out of line (see d47533dab9f5).
> 
> At that point, kvm_vcpu_is_be() becomes a death trap.
> 
> We missed it for two reasons:
> - It was only indirectly called, making it quite hard to notice the
>   potential breakage
> - Nobody gives a damn about 64k pages, specially on something like Juno
> 
> What we'd need is a way to find cross-section calls (text -> hyp-text
> should allowed, but not the reverse). We already have similar things in
> the kernel, it is probably only a matter of reusing the infrastructure
> for our own purpose.
>

Hi all,

While debugging a series backported to the RHEL kernel, I was suspicious
of the problem being an issue like this (a hyp-text to non-hyp-mapped
reference), so I went ahead an implemented the cross-section reference
checking as Marc suggested. I've attached the patch. I don't really
like it though because of all the special casing necessary to kill
false alarms - making it too hacky. Also, the need to inline some
functions just to match their symbol names is pretty lame. Anyway,
maybe it can be helpful, at least as inspiration.

Running it on latest master doesn't produce anything. Running it
without b220244d4179 ("arm64: vgic-v2: Fix proxying of cpuif access")
gives

.hyp.text:__vgic_v2_perform_cpuif_access references .text:vcpu_read_sys_reg

so I guess it works.

Unfortunately it didn't help me with my downstream debug...

drew
-------------- next part --------------
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index bffece27b5c1..7a6364e8312f 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -200,6 +200,7 @@ ENDPROC(\label)
 	invalid_vector	el2h_fiq_invalid
 	invalid_vector	el1_fiq_invalid
 
+hyp_entry_literal_pool:
 	.ltorg
 
 	.align 11
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index d9645236e474..16f063af3bd9 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -86,7 +86,7 @@ static void __hyp_text __deactivate_traps_common(void)
 	write_sysreg(0, pmuserenr_el0);
 }
 
-static void activate_traps_vhe(struct kvm_vcpu *vcpu)
+static noinline void activate_traps_vhe(struct kvm_vcpu *vcpu)
 {
 	u64 val;
 
@@ -125,7 +125,7 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
 		__activate_traps_nvhe(vcpu);
 }
 
-static void deactivate_traps_vhe(void)
+static noinline void deactivate_traps_vhe(void)
 {
 	extern char vectors[];	/* kernel exception vectors */
 	write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
@@ -529,8 +529,8 @@ static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par,
 		       read_sysreg(hpfar_el2), par, vcpu);
 }
 
-static void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par,
-				 struct kvm_cpu_context *host_ctxt)
+static noinline void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par,
+					  struct kvm_cpu_context *host_ctxt)
 {
 	struct kvm_vcpu *vcpu;
 	vcpu = host_ctxt->__hyp_running_vcpu;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 4ff08a0ef5d3..6ba0617df985 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -964,6 +964,7 @@ enum mismatch {
 	ANY_EXIT_TO_ANY_INIT,
 	EXPORT_TO_INIT_EXIT,
 	EXTABLE_TO_NON_TEXT,
+	HYP_TEXT_TO_NON_HYP,
 };
 
 /**
@@ -1003,6 +1004,11 @@ static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
 				     Elf_Rela *r, Elf_Sym *sym,
 				     const char *fromsec);
 
+static void hyp_mismatch_handler(const char *modname, struct elf_info *elf,
+				 const struct sectioncheck* const mismatch,
+				 Elf_Rela *r, Elf_Sym *sym,
+				 const char *fromsec);
+
 static const struct sectioncheck sectioncheck[] = {
 /* Do not reference init/exit code/data from
  * normal code and data
@@ -1090,7 +1096,15 @@ static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
 	.good_tosec = {ALL_TEXT_SECTIONS , NULL},
 	.mismatch = EXTABLE_TO_NON_TEXT,
 	.handler = extable_mismatch_handler,
-}
+},
+{
+	.fromsec = { ".hyp.text", NULL },
+	.good_tosec = { ".hyp.text", ".hyp.idmap.text",
+			".rodata", ".data..ro_after_init",
+			".bss", NULL },
+	.mismatch = HYP_TEXT_TO_NON_HYP,
+	.handler = hyp_mismatch_handler,
+},
 };
 
 static const struct sectioncheck *section_mismatch(
@@ -1525,6 +1539,10 @@ static void report_sec_mismatch(const char *modname,
 		fatal("There's a special handler for this mismatch type, "
 		      "we should never get here.");
 		break;
+	case HYP_TEXT_TO_NON_HYP:
+		fatal("There's a special handler for this mismatch type, "
+		      "we should never get here.");
+		break;
 	}
 	fprintf(stderr, "\n");
 }
@@ -1681,6 +1699,46 @@ static void extable_mismatch_handler(const char* modname, struct elf_info *elf,
 	}
 }
 
+static void hyp_mismatch_handler(const char *modname, struct elf_info *elf,
+				 const struct sectioncheck* const mismatch,
+				 Elf_Rela *r, Elf_Sym *sym,
+				 const char *fromsec)
+{
+	Elf_Sym *from = find_elf_symbol2(elf, r->r_offset, fromsec);
+	Elf_Sym *to = find_elf_symbol(elf, r->r_addend, sym);
+	const char *fromsym = sym_name(elf, from);
+	const char *tosec = sec_name(elf, get_secindex(elf, sym));
+	const char *tosym = sym_name(elf, to);
+	char *s;
+
+	switch (mismatch->mismatch) {
+	case HYP_TEXT_TO_NON_HYP:
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+		if (!is_valid_name(elf, from) || !is_valid_name(elf, to)) {
+			/*
+			 * Skip unknown symbols to reduce false alarms,
+			 * of course at the risk of missing something...
+			 */
+			return;
+		}
+		if (strcmp(tosym, "kvm_arm_hyp_stack_page") == 0 ||
+		    strcmp(tosym, "kvm_host_cpu_state") == 0)
+			return;
+		if (strcmp(fromsym, "hyp_entry_literal_pool") == 0)
+			return;
+		if ((s = strstr(tosym, "_vhe")) &&
+		    (strlen(s) == 4 || s[4] == '.'))
+			return;
+		fprintf(stderr,
+			".hyp.text:%s references %s:%s\n\n",
+			fromsym, tosec, tosym);
+#endif
+		break;
+	default:
+		break;
+	}
+}
+
 static void check_section_mismatch(const char *modname, struct elf_info *elf,
 				   Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
 {

^ permalink raw reply related

* [PATCH] usb/gadget: aspeed-vhub: add USB_LIBCOMPOSITE dependency
From: Arnd Bergmann @ 2018-05-25 16:07 UTC (permalink / raw)
  To: linux-arm-kernel

Without that option, we run into a link failure:

drivers/usb/gadget/udc/aspeed-vhub/hub.o: In function `ast_vhub_std_hub_request':
hub.c:(.text+0x5b0): undefined reference to `usb_gadget_get_string'

Fixes: 7ecca2a4080c ("usb/gadget: Add driver for Aspeed SoC virtual hub")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/usb/gadget/udc/aspeed-vhub/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/gadget/udc/aspeed-vhub/Kconfig b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
index f0cdf89b8503..83ba8a2eb6af 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
+++ b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig
@@ -2,6 +2,7 @@
 config USB_ASPEED_VHUB
 	tristate "Aspeed vHub UDC driver"
 	depends on ARCH_ASPEED || COMPILE_TEST
+	depends on USB_LIBCOMPOSITE
 	help
 	  USB peripheral controller for the Aspeed AST2500 family
 	  SoCs supporting the "vHub" functionality and USB2.0
-- 
2.9.0

^ permalink raw reply related

* [PATCH 08/11] coresight: Add generic TMC sg table framework
From: Suzuki K Poulose @ 2018-05-25 16:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180523202552.GA4609@xps15>

On 23/05/18 21:25, Mathieu Poirier wrote:
> On Fri, May 18, 2018 at 05:39:24PM +0100, Suzuki K Poulose wrote:
>> This patch introduces a generic sg table data structure and
>> associated operations. An SG table can be used to map a set
>> of Data pages where the trace data could be stored by the TMC
>> ETR. The information about the data pages could be stored in
>> different formats, depending on the type of the underlying
>> SG mechanism (e.g, TMC ETR SG vs Coresight CATU). The generic
>> structure provides book keeping of the pages used for the data
>> as well as the table contents. The table should be filled by
>> the user of the infrastructure.
>>
>> A table can be created by specifying the number of data pages
>> as well as the number of table pages required to hold the
>> pointers, where the latter could be different for different
>> types of tables. The pages are mapped in the appropriate dma
>> data direction mode (i.e, DMA_TO_DEVICE for table pages
>> and DMA_FROM_DEVICE for data pages).  The framework can optionally
>> accept a set of allocated data pages (e.g, perf ring buffer) and
>> map them accordingly. The table and data pages are vmap'ed to allow
>> easier access by the drivers. The framework also provides helpers to
>> sync the data written to the pages with appropriate directions.
>>
>> This will be later used by the TMC ETR SG unit and CATU.
>>
>> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>> Changes since v1:
>>   - Address code style issues, more comments
>> ---
>>   drivers/hwtracing/coresight/coresight-tmc-etr.c | 290 ++++++++++++++++++++++++
>>   drivers/hwtracing/coresight/coresight-tmc.h     |  50 ++++
>>   2 files changed, 340 insertions(+)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index 9780798..1e844f8 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -17,9 +17,299 @@


>> +static inline dma_addr_t tmc_sg_table_base_paddr(struct tmc_sg_table *sg_table)
>> +{
>> +	if (WARN_ON(!sg_table->data_pages.pages[0]))
>> +		return 0;
>> +	return sg_table->table_daddr;
>> +}
>> +
>> +static inline void *tmc_sg_table_base_vaddr(struct tmc_sg_table *sg_table)
>> +{
>> +	if (WARN_ON(!sg_table->data_pages.pages[0]))
>> +		return NULL;
>> +	return sg_table->table_vaddr;
>> +}
> 
> The above two functions deal with DMA'able and virtual addresses for the table
> page buffer.  Yet the test in the WARN_ON is done on the data page array.
> Shouldn't this be sg_table->table_pages.pages[0] instead?

The table is as good as empty if there are no data pages associated with
the table. Hence the data_pages check.

> 
> If not please add a comment justifying your position so that someone else
> looking at the code does't end up thinking the same in a year from now.

I will add a comment to reflect the above.

> 
>> +
>> +static inline void *
>> +tmc_sg_table_data_vaddr(struct tmc_sg_table *sg_table)
>> +{
>> +	if (WARN_ON(!sg_table->data_pages.nr_pages))
>> +		return 0;
>> +	return sg_table->data_vaddr;
>> +}
> 
> I see that tmc_sg_table_base_vaddr() and tmc_sg_table_data_vaddr() are both
> returning the virtual address of the contiguous buffer for table and data
> respectively.  Yet there is a discrepency in the naming convention.  I would
> have expected tmc_sg_table_base_vaddr() and tmc_sg_data_base_vaddr() so that
> there is a little symmetry between them.

Agree. I will fix it.

Suzuki

^ permalink raw reply

* [PATCH v1 4/4] MAINTAINERS: Add entry for Mellanox Bluefield Soc
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b143b40446c1870fb8d422b364ead95d54552be9.1527264077.git.lsun@mellanox.com>

Add maintainer information for Mellanox BlueField SoC.

Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 58b9861..85d5639 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1636,6 +1636,14 @@ L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	drivers/phy/mediatek/phy-mtk-tphy.c
 
+ARM/Mellanox BlueField SoC support
+M:	David Woods <dwoods@mellanox.com>
+M:	Liming Sun <lsun@mellanox.com>
+L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/soc/mellanox/*
+F:	Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
+
 ARM/MICREL KS8695 ARCHITECTURE
 M:	Greg Ungerer <gerg@uclinux.org>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v1 3/4] dt-bindings: soc: Add TmFifo binding for Mellanox BlueField SoC
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b143b40446c1870fb8d422b364ead95d54552be9.1527264077.git.lsun@mellanox.com>

Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
 .../devicetree/bindings/soc/mellanox/tmfifo.txt      | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt

diff --git a/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt b/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
new file mode 100644
index 0000000..0a362f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mellanox/tmfifo.txt
@@ -0,0 +1,20 @@
+* Mellanox BlueField SoC TmFifo
+
+BlueField TmFifo provides a shared FIFO between the target and the
+external host machine, which can be accessed via USB or PCIe.
+
+Required properties:
+
+- compatible:	Should be "mellanox,bf-tmfifo"
+- reg:		Physical base address and length of Rx/Tx block
+- interrupts:	The interrupt number of Rx low water mark, Rx high water mark
+		Tx low water mark, Tx high water mark respectively.
+
+Example:
+
+tmfifo at 800a20 {
+	compatible = "mellanox,bf-tmfifo";
+	reg = <0x00800a20 0x00000018
+	       0x00800a40 0x00000018>;
+	interrupts = <41, 42, 43, 44>;
+};
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v1 2/4] arm64: Add Mellanox BlueField SoC config option
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b143b40446c1870fb8d422b364ead95d54552be9.1527264077.git.lsun@mellanox.com>

This commit introduces config option for Mellanox BlueField SoC,
which can be used to build the SoC specific drivers, and enables
it by default in configs/defconfig.

Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
 arch/arm64/Kconfig.platforms | 6 ++++++
 arch/arm64/configs/defconfig | 1 +
 2 files changed, 7 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2b1535c..74ad03f 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -110,6 +110,12 @@ config ARCH_MESON
 	help
 	  This enables support for the Amlogic S905 SoCs.
 
+config ARCH_MLNX_BLUEFIELD
+	bool "Mellanox BlueField SoC Family"
+	select SOC_MLNX
+	help
+	  This enables support for the Mellanox BlueField SoC.
+
 config ARCH_MVEBU
 	bool "Marvell EBU SoC Family"
 	select ARMADA_AP806_SYSCON
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 1c98939..842f607 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -43,6 +43,7 @@ CONFIG_ARCH_LG1K=y
 CONFIG_ARCH_HISI=y
 CONFIG_ARCH_MEDIATEK=y
 CONFIG_ARCH_MESON=y
+CONFIG_ARCH_MLNX_BLUEFIELD=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_ROCKCHIP=y
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v1 1/4] soc: Add TmFifo driver for Mellanox BlueField Soc
From: Liming Sun @ 2018-05-25 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

This commit adds the TmFifo driver for Mellanox BlueField Soc.
TmFifo is a shared FIFO which enables external host machine to
exchange data with the SoC via USB or PCIe. The driver is based on
virtio framework and has console and network access enabled.

Reviewed-by: David Woods <dwoods@mellanox.com>
Signed-off-by: Liming Sun <lsun@mellanox.com>
---
 drivers/soc/Kconfig                |    1 +
 drivers/soc/Makefile               |    1 +
 drivers/soc/mellanox/Kconfig       |   18 +
 drivers/soc/mellanox/Makefile      |    5 +
 drivers/soc/mellanox/tmfifo.c      | 1265 ++++++++++++++++++++++++++++++++++++
 drivers/soc/mellanox/tmfifo_regs.h |  112 ++++
 6 files changed, 1402 insertions(+)
 create mode 100644 drivers/soc/mellanox/Kconfig
 create mode 100644 drivers/soc/mellanox/Makefile
 create mode 100644 drivers/soc/mellanox/tmfifo.c
 create mode 100644 drivers/soc/mellanox/tmfifo_regs.h

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index c07b4a8..fa87dc8 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -7,6 +7,7 @@ source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/imx/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
+source "drivers/soc/mellanox/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/renesas/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 4052357..868163f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_GEMINI)	+= gemini/
 obj-$(CONFIG_ARCH_MXC)		+= imx/
 obj-$(CONFIG_SOC_XWAY)		+= lantiq/
 obj-y				+= mediatek/
+obj-$(CONFIG_SOC_MLNX)		+= mellanox/
 obj-$(CONFIG_ARCH_MESON)	+= amlogic/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-y				+= renesas/
diff --git a/drivers/soc/mellanox/Kconfig b/drivers/soc/mellanox/Kconfig
new file mode 100644
index 0000000..d88efa1
--- /dev/null
+++ b/drivers/soc/mellanox/Kconfig
@@ -0,0 +1,18 @@
+menuconfig SOC_MLNX
+	bool "Mellanox SoC drivers"
+	default y if ARCH_MLNX_BLUEFIELD
+
+if ARCH_MLNX_BLUEFIELD || COMPILE_TEST
+
+config MLNX_BLUEFIELD_TMFIFO
+	tristate "Mellanox BlueField SoC TmFifo driver"
+	depends on ARM64
+	default m
+	select VIRTIO_CONSOLE
+	select VIRTIO_NET
+	help
+	  Say y here to enable TmFifo support. The TmFifo driver provides the
+	  virtio driver framework for the TMFIFO of Mellanox BlueField SoC and
+	  the implementation of a console and network driver.
+
+endif # ARCH_MLNX_BLUEFIELD
diff --git a/drivers/soc/mellanox/Makefile b/drivers/soc/mellanox/Makefile
new file mode 100644
index 0000000..c44c0e2
--- /dev/null
+++ b/drivers/soc/mellanox/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Mellanox SoC drivers.
+#
+obj-$(CONFIG_MLNX_BLUEFIELD_TMFIFO)	+= tmfifo.o
diff --git a/drivers/soc/mellanox/tmfifo.c b/drivers/soc/mellanox/tmfifo.c
new file mode 100644
index 0000000..a3303d1
--- /dev/null
+++ b/drivers/soc/mellanox/tmfifo.c
@@ -0,0 +1,1265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/acpi.h>
+#include <linux/cache.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/efi.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_console.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_ring.h>
+#include <asm/byteorder.h>
+
+#include "tmfifo_regs.h"
+
+/* Several utility macros to get/set the register fields. */
+#define TMFIFO_GET_FIELD(reg, field) \
+	(((reg) >> field##_SHIFT) & ((1UL << field##_WIDTH) - 1))
+
+#define TMFIFO_SET_FIELD(reg, field, value) ({ \
+	u64 _mask = ((1UL << field##_WIDTH) - 1) << field##_SHIFT; \
+	((reg) & ~_mask) | (((value) << field##_SHIFT) & _mask); \
+})
+
+#define TMFIFO_RX_GET_STS_CNT(sts) \
+	TMFIFO_GET_FIELD(sts, TMFIFO_RX_STS__COUNT)
+
+#define TMFIFO_TX_GET_STS_CNT(sts) \
+	TMFIFO_GET_FIELD(sts, TMFIFO_TX_STS__COUNT)
+
+/* Vring size. */
+#define TMFIFO_VRING_SIZE			1024
+
+/* Console Tx buffer size. */
+#define TMFIFO_CONS_TX_BUF_SIZE			(32 * 1024)
+
+/* Use a timer for house-keeping. */
+static int tmfifo_timer_interval = HZ / 10;
+
+/* Global lock. */
+static struct mutex tmfifo_lock;
+
+/* Virtio ring size. */
+static int tmfifo_vring_size = TMFIFO_VRING_SIZE;
+module_param(tmfifo_vring_size, int, 0444);
+MODULE_PARM_DESC(tmfifo_vring_size, "Size of the vring.");
+
+struct tmfifo;
+
+/* A flag to indicate TmFifo ready. */
+static bool tmfifo_ready;
+
+/* Virtual devices sharing the TM FIFO. */
+#define TMFIFO_VDEV_MAX		(VIRTIO_ID_CONSOLE + 1)
+
+/* Spin lock. */
+static DEFINE_SPINLOCK(tmfifo_spin_lock);
+
+/* Structure to maintain the ring state. */
+struct tmfifo_vring {
+	void *va;			/* virtual address */
+	dma_addr_t dma;			/* dma address */
+	struct virtqueue *vq;		/* virtqueue pointer */
+	struct vring_desc *desc;	/* current desc */
+	struct vring_desc *desc_head;	/* current desc head */
+	int cur_len;			/* processed len in current desc */
+	int rem_len;			/* remaining length to be processed */
+	int size;			/* vring size */
+	int align;			/* vring alignment */
+	int id;				/* vring id */
+	int vdev_id;			/* TMFIFO_VDEV_xxx */
+	u32 pkt_len;			/* packet total length */
+	__virtio16 next_avail;		/* next avail desc id */
+	struct tmfifo *fifo;		/* pointer back to the tmfifo */
+};
+
+/* Interrupt types. */
+enum {
+	TM_RX_LWM_IRQ,			/* Rx low water mark irq */
+	TM_RX_HWM_IRQ,			/* Rx high water mark irq */
+	TM_TX_LWM_IRQ,			/* Tx low water mark irq */
+	TM_TX_HWM_IRQ,			/* Tx high water mark irq */
+	TM_IRQ_CNT
+};
+
+/* Ring types (Rx & Tx). */
+enum {
+	TMFIFO_VRING_RX,		/* Rx ring */
+	TMFIFO_VRING_TX,		/* Tx ring */
+	TMFIFO_VRING_NUM
+};
+
+struct tmfifo_vdev {
+	struct virtio_device vdev;	/* virtual device */
+	u8 status;
+	u64 features;
+	union {				/* virtio config space */
+		struct virtio_console_config cons;
+		struct virtio_net_config net;
+	} config;
+	struct tmfifo_vring vrings[TMFIFO_VRING_NUM];
+	u8 *tx_buf;			/* tx buffer */
+	u32 tx_head;			/* tx buffer head */
+	u32 tx_tail;			/* tx buffer tail */
+};
+
+#define TMFIFO_VDEV_TX_BUF_AVAIL(vdev) \
+	(((vdev)->tx_tail >= (vdev)->tx_head) ? \
+	(TMFIFO_CONS_TX_BUF_SIZE - 8 - ((vdev)->tx_tail - (vdev)->tx_head)) : \
+	((vdev)->tx_head - (vdev)->tx_tail - 8))
+
+#define TMFIFO_VDEV_TX_BUF_PUSH(vdev, len) do { \
+	(vdev)->tx_tail += (len); \
+	if ((vdev)->tx_tail >= TMFIFO_CONS_TX_BUF_SIZE) \
+		(vdev)->tx_tail -= TMFIFO_CONS_TX_BUF_SIZE; \
+} while (0)
+
+#define TMFIFO_VDEV_TX_BUF_POP(vdev, len) do { \
+	(vdev)->tx_head += (len); \
+	if ((vdev)->tx_head >= TMFIFO_CONS_TX_BUF_SIZE) \
+		(vdev)->tx_head -= TMFIFO_CONS_TX_BUF_SIZE; \
+} while (0)
+
+/* TMFIFO device structure */
+struct tmfifo {
+	struct tmfifo_vdev *vdev[TMFIFO_VDEV_MAX];	/* virtual devices */
+	struct platform_device *pdev;	/* platform device */
+	struct mutex lock;
+	void __iomem *rx_base;		/* mapped register base */
+	void __iomem *tx_base;		/* mapped register base */
+	int tx_fifo_size;		/* number of entries of the Tx FIFO */
+	int rx_fifo_size;		/* number of entries of the Rx FIFO */
+	unsigned long pend_events;	/* pending bits for deferred process */
+	int irq[TM_IRQ_CNT];		/* irq numbers */
+	struct work_struct work;	/* work struct for deferred process */
+	struct timer_list timer;	/* keepalive timer */
+	struct tmfifo_vring *vring[2];	/* current Tx/Rx ring */
+};
+
+union tmfifo_msg_hdr {
+	struct {
+		u8 type;		/* message type */
+		__be16 len;		/* payload length */
+		u8 unused[5];		/* reserved, set to 0 */
+	} __packed;
+	u64 data;
+};
+
+/*
+ * Default MAC.
+ * This MAC address will be read from EFI persistent variable if configured.
+ * It can also be reconfigured with standard Linux tools.
+ */
+static u8 tmfifo_net_default_mac[6] = {0x00, 0x1A, 0xCA, 0xFF, 0xFF, 0x01};
+
+/* MTU setting of the virtio-net interface. */
+#define TMFIFO_NET_MTU		1500
+
+/* Supported virtio-net features. */
+#define TMFIFO_NET_FEATURES	((1UL << VIRTIO_NET_F_MTU) | \
+				 (1UL << VIRTIO_NET_F_STATUS) | \
+				 (1UL << VIRTIO_NET_F_MAC))
+
+/* Forward declaration. */
+static void tmfifo_virtio_rxtx(struct virtqueue *vq, bool is_rx);
+static void tmfifo_release_pkt(struct virtio_device *vdev,
+			       struct tmfifo_vring *vring,
+			       struct vring_desc **desc);
+
+/* Allocate vrings for the fifo. */
+static int tmfifo_alloc_vrings(struct tmfifo *fifo,
+			       struct tmfifo_vdev *tm_vdev, int vdev_id)
+{
+	dma_addr_t dma;
+	void *va;
+	int i, size;
+	struct tmfifo_vring *vring;
+
+	for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+		vring = &tm_vdev->vrings[i];
+		vring->fifo = fifo;
+		vring->size = tmfifo_vring_size;
+		vring->align = SMP_CACHE_BYTES;
+		vring->id = i;
+		vring->vdev_id = vdev_id;
+
+		size = PAGE_ALIGN(vring_size(vring->size, vring->align));
+		va = dma_alloc_coherent(tm_vdev->vdev.dev.parent, size, &dma,
+					GFP_KERNEL);
+		if (!va) {
+			dev_err(tm_vdev->vdev.dev.parent,
+				"vring allocation failed\n");
+			return -EINVAL;
+		}
+
+		vring->va = va;
+		vring->dma = dma;
+	}
+
+	return 0;
+}
+
+/* Free vrings of the fifo device. */
+static void tmfifo_free_vrings(struct tmfifo *fifo, int vdev_id)
+{
+	int i, size;
+	struct tmfifo_vring *vring;
+	struct tmfifo_vdev *tm_vdev = fifo->vdev[vdev_id];
+
+	for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+		vring = &tm_vdev->vrings[i];
+
+		size = PAGE_ALIGN(vring_size(vring->size, vring->align));
+		if (vring->va) {
+			dma_free_coherent(tm_vdev->vdev.dev.parent, size,
+					  vring->va, vring->dma);
+			vring->va = NULL;
+			if (vring->vq) {
+				vring_del_virtqueue(vring->vq);
+				vring->vq = NULL;
+			}
+		}
+	}
+}
+
+/* Free interrupts of the fifo device. */
+static void tmfifo_free_irqs(struct tmfifo *fifo)
+{
+	int i, irq;
+
+	for (i = 0; i < TM_IRQ_CNT; i++) {
+		irq = fifo->irq[i];
+		if (irq) {
+			fifo->irq[i] = 0;
+			disable_irq(irq);
+			free_irq(irq, (u8 *)fifo + i);
+		}
+	}
+}
+
+/* Work handler for Rx, Tx or activity monitoring. */
+static void tmfifo_work_handler(struct work_struct *work)
+{
+	int i;
+	struct tmfifo_vdev *tm_vdev;
+	struct tmfifo *fifo = container_of(work, struct tmfifo, work);
+
+	if (!tmfifo_ready)
+		return;
+
+	mutex_lock(&fifo->lock);
+
+	/* Tx. */
+	if (test_and_clear_bit(TM_TX_LWM_IRQ, &fifo->pend_events) &&
+		       fifo->irq[TM_TX_LWM_IRQ]) {
+		for (i = 0; i < TMFIFO_VDEV_MAX; i++) {
+			tm_vdev = fifo->vdev[i];
+			if (tm_vdev != NULL) {
+				tmfifo_virtio_rxtx(
+					tm_vdev->vrings[TMFIFO_VRING_TX].vq,
+					false);
+			}
+		}
+	}
+
+	/* Rx. */
+	if (test_and_clear_bit(TM_RX_HWM_IRQ, &fifo->pend_events) &&
+		       fifo->irq[TM_RX_HWM_IRQ]) {
+		for (i = 0; i < TMFIFO_VDEV_MAX; i++) {
+			tm_vdev = fifo->vdev[i];
+			if (tm_vdev != NULL) {
+				tmfifo_virtio_rxtx(
+					tm_vdev->vrings[TMFIFO_VRING_RX].vq,
+					true);
+			}
+		}
+	}
+
+	mutex_unlock(&fifo->lock);
+}
+
+/* Interrupt handler. */
+static irqreturn_t tmfifo_irq_handler(int irq, void *dev_id)
+{
+	int i = (uintptr_t)dev_id % sizeof(void *);
+	struct tmfifo *fifo = dev_id - i;
+
+	if (i < TM_IRQ_CNT && !test_and_set_bit(i, &fifo->pend_events))
+		schedule_work(&fifo->work);
+
+	return IRQ_HANDLED;
+}
+
+/* Nothing to do for now. */
+static void tmfifo_virtio_dev_release(struct device *dev)
+{
+}
+
+/* Get the next packet descriptor from the vring. */
+static inline struct vring_desc *
+tmfifo_virtio_get_next_desc(struct virtqueue *vq)
+{
+	unsigned int idx, head;
+	struct vring *vr = (struct vring *)virtqueue_get_vring(vq);
+	struct tmfifo_vring *vring = (struct tmfifo_vring *)vq->priv;
+
+	if (!vr || vring->next_avail == vr->avail->idx)
+		return NULL;
+
+	idx = vring->next_avail % vr->num;
+	head = vr->avail->ring[idx];
+	BUG_ON(head >= vr->num);
+	vring->next_avail++;
+	return &vr->desc[head];
+}
+
+static inline void tmfifo_virtio_release_desc(struct virtio_device *vdev,
+					      struct vring *vr,
+					      struct vring_desc *desc, u32 len)
+{
+	unsigned int idx;
+
+	idx = vr->used->idx % vr->num;
+	vr->used->ring[idx].id = desc - vr->desc;
+	vr->used->ring[idx].len = cpu_to_virtio32(vdev, len);
+
+	/* Virtio could poll and check the 'idx' to decide
+	 * whether the desc is done or not. Add a memory
+	 * barrier here to make sure the update above completes
+	 * before updating the idx.
+	 */
+	mb();
+	vr->used->idx++;
+}
+
+/* Get the total length of a descriptor chain. */
+static inline u32 tmfifo_virtio_get_pkt_len(struct virtio_device *vdev,
+			struct vring_desc *desc, struct vring *vr)
+{
+	u32 len = 0, idx;
+
+	while (desc) {
+		len += virtio32_to_cpu(vdev, desc->len);
+		if (!(virtio16_to_cpu(vdev, desc->flags) & VRING_DESC_F_NEXT))
+			break;
+		idx = virtio16_to_cpu(vdev, desc->next);
+		desc = &vr->desc[idx];
+	}
+
+	return len;
+}
+
+static void tmfifo_release_pkt(struct virtio_device *vdev,
+			       struct tmfifo_vring *vring,
+			       struct vring_desc **desc)
+{
+	struct vring *vr = (struct vring *)virtqueue_get_vring(vring->vq);
+	struct vring_desc *desc_head;
+	uint32_t pkt_len = 0;
+
+	if (!vr)
+		return;
+
+	if (desc != NULL && *desc != NULL && vring->desc_head != NULL) {
+		desc_head = vring->desc_head;
+		pkt_len = vring->pkt_len;
+	} else {
+		desc_head = tmfifo_virtio_get_next_desc(vring->vq);
+		if (desc_head != NULL) {
+			pkt_len = tmfifo_virtio_get_pkt_len(vdev,
+							desc_head, vr);
+		}
+	}
+
+	if (desc_head != NULL)
+		tmfifo_virtio_release_desc(vdev, vr, desc_head, pkt_len);
+
+	if (desc != NULL)
+		*desc = NULL;
+	vring->pkt_len = 0;
+}
+
+/* House-keeping timer. */
+static void tmfifo_timer(struct timer_list *arg)
+{
+	struct tmfifo *fifo = container_of(arg, struct tmfifo, timer);
+
+	/*
+	 * Wake up the work handler to poll the Rx FIFO in case interrupt
+	 * missing or any leftover bytes stuck in the FIFO.
+	 */
+	test_and_set_bit(TM_RX_HWM_IRQ, &fifo->pend_events);
+
+	/*
+	 * Wake up Tx handler in case virtio has queued too many packets
+	 * and are waiting for buffer return.
+	 */
+	test_and_set_bit(TM_TX_LWM_IRQ, &fifo->pend_events);
+
+	schedule_work(&fifo->work);
+
+	mod_timer(&fifo->timer, jiffies + tmfifo_timer_interval);
+}
+
+/* Buffer the console output. */
+static void tmfifo_console_output(struct tmfifo_vdev *cons,
+				  struct virtqueue *vq)
+{
+	u32 len, pkt_len, idx;
+	struct vring_desc *head_desc, *desc = NULL;
+	struct vring *vr = (struct vring *)virtqueue_get_vring(vq);
+	struct virtio_device *vdev = &cons->vdev;
+	void *addr;
+	union tmfifo_msg_hdr *hdr;
+
+	for (;;) {
+		head_desc = tmfifo_virtio_get_next_desc(vq);
+		if (head_desc == NULL)
+			break;
+
+		/* Release the packet if no more space. */
+		pkt_len = tmfifo_virtio_get_pkt_len(vdev, head_desc, vr);
+		if (pkt_len + sizeof(*hdr) > TMFIFO_VDEV_TX_BUF_AVAIL(cons)) {
+			tmfifo_virtio_release_desc(vdev, vr, head_desc,
+						   pkt_len);
+			break;
+		}
+
+		hdr = (union tmfifo_msg_hdr *)&cons->tx_buf[cons->tx_tail];
+		hdr->data = 0;
+		hdr->type = VIRTIO_ID_CONSOLE;
+		hdr->len = htons(pkt_len);
+
+		TMFIFO_VDEV_TX_BUF_PUSH(cons, sizeof(*hdr));
+		desc = head_desc;
+
+		while (desc != NULL) {
+			addr = phys_to_virt(virtio64_to_cpu(vdev, desc->addr));
+			len = virtio32_to_cpu(vdev, desc->len);
+
+			if (len <= TMFIFO_CONS_TX_BUF_SIZE - cons->tx_tail) {
+				memcpy(cons->tx_buf + cons->tx_tail, addr, len);
+			} else {
+				u32 seg;
+
+				seg = TMFIFO_CONS_TX_BUF_SIZE - cons->tx_tail;
+				memcpy(cons->tx_buf + cons->tx_tail, addr, seg);
+				addr += seg;
+				memcpy(cons->tx_buf, addr, len - seg);
+			}
+			TMFIFO_VDEV_TX_BUF_PUSH(cons, len);
+
+			if (!(virtio16_to_cpu(vdev, desc->flags) &
+			    VRING_DESC_F_NEXT))
+				break;
+			idx = virtio16_to_cpu(vdev, desc->next);
+			desc = &vr->desc[idx];
+		}
+
+		/* Make each packet 8-byte aligned. */
+		TMFIFO_VDEV_TX_BUF_PUSH(cons, ((pkt_len + 7) & -8) - pkt_len);
+
+		tmfifo_virtio_release_desc(vdev, vr, head_desc, pkt_len);
+	}
+}
+
+/* Rx & Tx processing of a virtual queue. */
+static void tmfifo_virtio_rxtx(struct virtqueue *vq, bool is_rx)
+{
+	struct tmfifo_vring *vring;
+	struct tmfifo *fifo;
+	struct vring *vr;
+	struct virtio_device *vdev;
+	u64 sts, data;
+	int num_avail = 0, hdr_len, tx_reserve;
+	void *addr;
+	u32 len, idx;
+	struct vring_desc *desc;
+	unsigned long flags;
+	struct tmfifo_vdev *cons;
+
+	if (!vq)
+		return;
+
+	vring = (struct tmfifo_vring *)vq->priv;
+	fifo = vring->fifo;
+	vr = (struct vring *)virtqueue_get_vring(vq);
+
+	if (!fifo->vdev[vring->vdev_id])
+		return;
+	vdev = &fifo->vdev[vring->vdev_id]->vdev;
+	cons = fifo->vdev[VIRTIO_ID_CONSOLE];
+
+	/* Don't continue if another vring is running. */
+	if (fifo->vring[is_rx] != NULL && fifo->vring[is_rx] != vring)
+		return;
+
+	/* tx_reserve is used to reserved some room in FIFO for console. */
+	if (vring->vdev_id == VIRTIO_ID_NET) {
+		hdr_len = sizeof(struct virtio_net_hdr);
+		tx_reserve = fifo->tx_fifo_size / 16;
+	} else {
+		BUG_ON(vring->vdev_id != VIRTIO_ID_CONSOLE);
+		hdr_len = 0;
+		tx_reserve = 1;
+	}
+
+	desc = vring->desc;
+
+again:
+	while (1) {
+		/* Get available FIFO space. */
+		if (num_avail == 0) {
+			if (is_rx) {
+				/* Get the number of available words in FIFO. */
+				sts = readq(fifo->rx_base + TMFIFO_RX_STS);
+				num_avail = TMFIFO_RX_GET_STS_CNT(sts);
+
+				/* Don't continue if nothing in FIFO. */
+				if (num_avail <= 0)
+					break;
+			} else {
+				/* Get available space in FIFO. */
+				sts = readq(fifo->tx_base + TMFIFO_TX_STS);
+				num_avail = fifo->tx_fifo_size - tx_reserve -
+					TMFIFO_TX_GET_STS_CNT(sts);
+
+				if (num_avail <= 0)
+					break;
+			}
+		}
+
+		/* Console output always comes from the Tx buffer. */
+		if (!is_rx && vring->vdev_id == VIRTIO_ID_CONSOLE &&
+		    cons != NULL && cons->tx_buf != NULL) {
+			for (;;) {
+				spin_lock_irqsave(&tmfifo_spin_lock, flags);
+				if (cons->tx_head == cons->tx_tail) {
+					spin_unlock_irqrestore(
+						&tmfifo_spin_lock, flags);
+					return;
+				}
+				addr = cons->tx_buf + cons->tx_head;
+				writeq(cpu_to_le64(*(u64 *)addr),
+				       fifo->tx_base + TMFIFO_TX_DATA);
+				TMFIFO_VDEV_TX_BUF_POP(cons, sizeof(u64));
+				spin_unlock_irqrestore(&tmfifo_spin_lock,
+						       flags);
+				if (--num_avail <= 0)
+					goto again;
+			}
+		}
+
+		/* Get the desc of next packet. */
+		if (!desc) {
+			/* Save the head desc of the chain. */
+			vring->desc_head = tmfifo_virtio_get_next_desc(vq);
+			if (!vring->desc_head) {
+				vring->desc = NULL;
+				return;
+			}
+			desc = vring->desc_head;
+			vring->desc = desc;
+
+			if (is_rx && vring->vdev_id == VIRTIO_ID_NET) {
+				struct virtio_net_hdr *net_hdr;
+
+				/* Initialize the packet header. */
+				net_hdr = (struct virtio_net_hdr *)
+					phys_to_virt(virtio64_to_cpu(
+						vdev, desc->addr));
+				memset(net_hdr, 0, sizeof(*net_hdr));
+			}
+		}
+
+		/* Beginning of each packet. */
+		if (vring->pkt_len == 0) {
+			int vdev_id, vring_change = 0;
+			union tmfifo_msg_hdr hdr;
+
+			num_avail--;
+
+			/* Read/Write packet length. */
+			if (is_rx) {
+				hdr.data = readq(fifo->rx_base +
+						 TMFIFO_RX_DATA);
+				hdr.data = le64_to_cpu(hdr.data);
+
+				/* Skip the length 0 packet (keepalive). */
+				if (hdr.len == 0)
+					continue;
+
+				/* Check packet type. */
+				if (hdr.type == VIRTIO_ID_NET) {
+					vdev_id = VIRTIO_ID_NET;
+					hdr_len = sizeof(struct virtio_net_hdr);
+				} else if (hdr.type == VIRTIO_ID_CONSOLE) {
+					vdev_id = VIRTIO_ID_CONSOLE;
+					hdr_len = 0;
+				} else {
+					continue;
+				}
+
+				/*
+				 * Check whether the new packet still belongs
+				 * to this vring or not. If not, update the
+				 * pkt_len of the new vring and return.
+				 */
+				if (vdev_id != vring->vdev_id) {
+					struct tmfifo_vdev *dev2 =
+						fifo->vdev[vdev_id];
+
+					if (!dev2)
+						break;
+					vring->desc = desc;
+					vring = &dev2->vrings[TMFIFO_VRING_RX];
+					vring_change = 1;
+				}
+				vring->pkt_len = ntohs(hdr.len) + hdr_len;
+			} else {
+				vring->pkt_len = tmfifo_virtio_get_pkt_len(
+					vdev, desc, vr);
+
+				hdr.data = 0;
+				hdr.type = (vring->vdev_id == VIRTIO_ID_NET) ?
+					VIRTIO_ID_NET :
+					VIRTIO_ID_CONSOLE;
+				hdr.len = htons(vring->pkt_len - hdr_len);
+				writeq(cpu_to_le64(hdr.data),
+				       fifo->tx_base + TMFIFO_TX_DATA);
+			}
+
+			vring->cur_len = hdr_len;
+			vring->rem_len = vring->pkt_len;
+			fifo->vring[is_rx] = vring;
+
+			if (vring_change)
+				return;
+			continue;
+		}
+
+		/* Check available space in this desc. */
+		len = virtio32_to_cpu(vdev, desc->len);
+		if (len > vring->rem_len)
+			len = vring->rem_len;
+
+		/* Check if the current desc is already done. */
+		if (vring->cur_len == len)
+			goto check_done;
+
+		addr = phys_to_virt(virtio64_to_cpu(vdev, desc->addr));
+
+		/* Read a word from FIFO for Rx. */
+		if (is_rx) {
+			data = readq(fifo->rx_base + TMFIFO_RX_DATA);
+			data = le64_to_cpu(data);
+		}
+
+		if (vring->cur_len + sizeof(u64) <= len) {
+			/* The whole word. */
+			if (is_rx) {
+				memcpy(addr + vring->cur_len, &data,
+				       sizeof(u64));
+			} else {
+				memcpy(&data, addr + vring->cur_len,
+				       sizeof(u64));
+			}
+			vring->cur_len += sizeof(u64);
+		} else {
+			/* Leftover bytes. */
+			BUG_ON(vring->cur_len > len);
+			if (is_rx) {
+				memcpy(addr + vring->cur_len, &data,
+				       len - vring->cur_len);
+			} else {
+				memcpy(&data, addr + vring->cur_len,
+				       len - vring->cur_len);
+			}
+			vring->cur_len = len;
+		}
+
+		/* Write the word into FIFO for Tx. */
+		if (!is_rx) {
+			writeq(cpu_to_le64(data),
+			       fifo->tx_base + TMFIFO_TX_DATA);
+		}
+
+		num_avail--;
+
+check_done:
+		/* Check whether this desc is full or completed. */
+		if (vring->cur_len == len) {
+			vring->cur_len = 0;
+			vring->rem_len -= len;
+
+			/* Get the next desc on the chain. */
+			if (vring->rem_len > 0 &&
+			    (virtio16_to_cpu(vdev, desc->flags) &
+						VRING_DESC_F_NEXT)) {
+				idx = virtio16_to_cpu(vdev, desc->next);
+				desc = &vr->desc[idx];
+				continue;
+			}
+
+			/* Done and release the desc. */
+			tmfifo_release_pkt(vdev, vring, &desc);
+			fifo->vring[is_rx] = NULL;
+
+			/* Notify upper layer that packet is done. */
+			spin_lock_irqsave(&tmfifo_spin_lock, flags);
+			vring_interrupt(0, vq);
+			spin_unlock_irqrestore(&tmfifo_spin_lock, flags);
+			continue;
+		}
+	}
+
+	/* Save the current desc. */
+	vring->desc = desc;
+}
+
+/* The notify function is called when new buffers are posted. */
+static bool tmfifo_virtio_notify(struct virtqueue *vq)
+{
+	struct tmfifo_vring *vring = (struct tmfifo_vring *)vq->priv;
+	struct tmfifo *fifo = vring->fifo;
+	unsigned long flags;
+
+	/*
+	 * Virtio maintains vrings in pairs, even number ring for Rx
+	 * and odd number ring for Tx.
+	 */
+	if (!(vring->id & 1)) {
+		/* Set the RX HWM bit to start Rx. */
+		if (!test_and_set_bit(TM_RX_HWM_IRQ, &fifo->pend_events))
+			schedule_work(&fifo->work);
+	} else {
+		/*
+		 * Console could make blocking call with interrupts disabled.
+		 * In such case, the vring needs to be served right away. For
+		 * other cases, just set the TX LWM bit to start Tx in the
+		 * worker handler.
+		 */
+		if (vring->vdev_id == VIRTIO_ID_CONSOLE) {
+			spin_lock_irqsave(&tmfifo_spin_lock, flags);
+			tmfifo_console_output(fifo->vdev[VIRTIO_ID_CONSOLE],
+					      vq);
+			spin_unlock_irqrestore(&tmfifo_spin_lock, flags);
+			schedule_work(&fifo->work);
+		} else if (!test_and_set_bit(TM_TX_LWM_IRQ, &fifo->pend_events))
+			schedule_work(&fifo->work);
+	}
+
+	return true;
+}
+
+/* Get the array of feature bits for this device. */
+static u64 tmfifo_virtio_get_features(struct virtio_device *vdev)
+{
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	return tm_vdev->features;
+}
+
+/* Confirm device features to use. */
+static int tmfifo_virtio_finalize_features(struct virtio_device *vdev)
+{
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	tm_vdev->features = vdev->features;
+	return 0;
+}
+
+/* Free virtqueues found by find_vqs(). */
+static void tmfifo_virtio_del_vqs(struct virtio_device *vdev)
+{
+	int i;
+	struct tmfifo_vring *vring;
+	struct virtqueue *vq;
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	for (i = 0; i < ARRAY_SIZE(tm_vdev->vrings); i++) {
+		vring = &tm_vdev->vrings[i];
+
+		/* Release the pending packet. */
+		if (vring->desc != NULL)
+			tmfifo_release_pkt(&tm_vdev->vdev, vring, &vring->desc);
+
+		vq = vring->vq;
+		if (vq) {
+			vring->vq = NULL;
+			vring_del_virtqueue(vq);
+		}
+	}
+}
+
+/* Create and initialize the virtual queues. */
+static int tmfifo_virtio_find_vqs(struct virtio_device *vdev,
+				  unsigned int nvqs,
+				  struct virtqueue *vqs[],
+				  vq_callback_t *callbacks[],
+				  const char * const names[],
+				  const bool *ctx,
+				  struct irq_affinity *desc)
+{
+	int i, ret = -EINVAL, size;
+	struct tmfifo_vring *vring;
+	struct virtqueue *vq;
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	if (nvqs > ARRAY_SIZE(tm_vdev->vrings))
+		return -EINVAL;
+
+	for (i = 0; i < nvqs; ++i) {
+		if (!names[i])
+			goto error;
+		vring = &tm_vdev->vrings[i];
+
+		/* zero vring */
+		size = vring_size(vring->size, vring->align);
+		memset(vring->va, 0, size);
+		vq = vring_new_virtqueue(i, vring->size, vring->align, vdev,
+					 false, false, vring->va,
+					 tmfifo_virtio_notify,
+					 callbacks[i], names[i]);
+		if (!vq) {
+			dev_err(&vdev->dev, "vring_new_virtqueue failed\n");
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		vqs[i] = vq;
+		vring->vq = vq;
+		vq->priv = vring;
+	}
+
+	return 0;
+
+error:
+	tmfifo_virtio_del_vqs(vdev);
+	return ret;
+}
+
+/* Read the status byte. */
+static u8 tmfifo_virtio_get_status(struct virtio_device *vdev)
+{
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	return tm_vdev->status;
+}
+
+/* Write the status byte. */
+static void tmfifo_virtio_set_status(struct virtio_device *vdev, u8 status)
+{
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	tm_vdev->status = status;
+}
+
+/* Reset the device. Not much here for now. */
+static void tmfifo_virtio_reset(struct virtio_device *vdev)
+{
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	tm_vdev->status = 0;
+}
+
+/* Read the value of a configuration field. */
+static void tmfifo_virtio_get(struct virtio_device *vdev,
+			      unsigned int offset,
+			      void *buf,
+			      unsigned int len)
+{
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	if (offset + len > sizeof(tm_vdev->config) || offset + len < len) {
+		dev_err(vdev->dev.parent, "virtio_get access out of bounds\n");
+		return;
+	}
+
+	memcpy(buf, (u8 *)&tm_vdev->config + offset, len);
+}
+
+/* Write the value of a configuration field. */
+static void tmfifo_virtio_set(struct virtio_device *vdev,
+				 unsigned int offset,
+				 const void *buf,
+				 unsigned int len)
+{
+	struct tmfifo_vdev *tm_vdev = container_of(vdev, struct tmfifo_vdev,
+						   vdev);
+
+	if (offset + len > sizeof(tm_vdev->config) || offset + len < len) {
+		dev_err(vdev->dev.parent, "virtio_get access out of bounds\n");
+		return;
+	}
+
+	memcpy((u8 *)&tm_vdev->config + offset, buf, len);
+}
+
+/* Virtio config operations. */
+static const struct virtio_config_ops tmfifo_virtio_config_ops = {
+	.get_features = tmfifo_virtio_get_features,
+	.finalize_features = tmfifo_virtio_finalize_features,
+	.find_vqs = tmfifo_virtio_find_vqs,
+	.del_vqs = tmfifo_virtio_del_vqs,
+	.reset = tmfifo_virtio_reset,
+	.set_status = tmfifo_virtio_set_status,
+	.get_status = tmfifo_virtio_get_status,
+	.get = tmfifo_virtio_get,
+	.set = tmfifo_virtio_set,
+};
+
+/* Create vdev type in a tmfifo. */
+int tmfifo_create_vdev(struct tmfifo *fifo, int vdev_id, u64 features,
+		       void *config, u32 size)
+{
+	struct tmfifo_vdev *tm_vdev;
+	int ret = 0;
+
+	mutex_lock(&fifo->lock);
+
+	tm_vdev = fifo->vdev[vdev_id];
+	if (tm_vdev != NULL) {
+		pr_err("vdev %d already exists\n", vdev_id);
+		ret = -EEXIST;
+		goto already_exist;
+	}
+
+	tm_vdev = kzalloc(sizeof(*tm_vdev), GFP_KERNEL);
+	if (!tm_vdev) {
+		ret = -ENOMEM;
+		goto already_exist;
+	}
+
+	tm_vdev->vdev.id.device = vdev_id;
+	tm_vdev->vdev.config = &tmfifo_virtio_config_ops;
+	tm_vdev->vdev.dev.parent = &fifo->pdev->dev;
+	tm_vdev->vdev.dev.release = tmfifo_virtio_dev_release;
+	tm_vdev->features = features;
+	if (config)
+		memcpy(&tm_vdev->config, config, size);
+	if (tmfifo_alloc_vrings(fifo, tm_vdev, vdev_id)) {
+		pr_err("Unable to allocate vring\n");
+		ret = -ENOMEM;
+		goto alloc_vring_fail;
+	}
+	if (vdev_id == VIRTIO_ID_CONSOLE) {
+		tm_vdev->tx_buf = kmalloc(TMFIFO_CONS_TX_BUF_SIZE,
+					  GFP_KERNEL);
+	}
+	fifo->vdev[vdev_id] = tm_vdev;
+
+	/* Register the virtio device. */
+	ret = register_virtio_device(&tm_vdev->vdev);
+	if (ret) {
+		dev_err(&fifo->pdev->dev, "register_virtio_device() failed\n");
+		goto register_fail;
+	}
+
+	mutex_unlock(&fifo->lock);
+	return 0;
+
+register_fail:
+	tmfifo_free_vrings(fifo, vdev_id);
+	fifo->vdev[vdev_id] = NULL;
+alloc_vring_fail:
+	kfree(tm_vdev);
+already_exist:
+	mutex_unlock(&fifo->lock);
+	return ret;
+}
+
+/* Delete vdev type from a tmfifo. */
+int tmfifo_delete_vdev(struct tmfifo *fifo, int vdev_id)
+{
+	struct tmfifo_vdev *tm_vdev;
+
+	mutex_lock(&fifo->lock);
+
+	/* Unregister vdev. */
+	tm_vdev = fifo->vdev[vdev_id];
+	if (tm_vdev) {
+		unregister_virtio_device(&tm_vdev->vdev);
+		tmfifo_free_vrings(fifo, vdev_id);
+		kfree(tm_vdev->tx_buf);
+		kfree(tm_vdev);
+		fifo->vdev[vdev_id] = NULL;
+	}
+
+	mutex_unlock(&fifo->lock);
+
+	return 0;
+}
+
+/* Device remove function. */
+static int tmfifo_remove(struct platform_device *pdev)
+{
+	int i;
+	struct tmfifo *fifo = platform_get_drvdata(pdev);
+	struct resource *rx_res, *tx_res;
+
+	tmfifo_ready = false;
+
+	if (fifo) {
+		mutex_lock(&tmfifo_lock);
+
+		/* Stop the timer. */
+		del_timer_sync(&fifo->timer);
+
+		/* Release interrupts. */
+		tmfifo_free_irqs(fifo);
+
+		/* Cancel the pending work. */
+		cancel_work_sync(&fifo->work);
+
+		for (i = 0; i < TMFIFO_VDEV_MAX; i++)
+			tmfifo_delete_vdev(fifo, i);
+
+		/* Release IO resources. */
+		if (fifo->rx_base)
+			iounmap(fifo->rx_base);
+		if (fifo->tx_base)
+			iounmap(fifo->tx_base);
+
+		platform_set_drvdata(pdev, NULL);
+		kfree(fifo);
+
+		mutex_unlock(&tmfifo_lock);
+	}
+
+	rx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (rx_res)
+		release_mem_region(rx_res->start, resource_size(rx_res));
+	tx_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (tx_res)
+		release_mem_region(tx_res->start, resource_size(tx_res));
+
+	return 0;
+}
+
+/* Read the configured network MAC address from efi variable. */
+static void tmfifo_get_cfg_mac(u8 *mac)
+{
+	u8 buf[6];
+	efi_status_t status;
+	unsigned long size = sizeof(buf);
+	efi_char16_t name[] = { 'R', 's', 'h', 'i', 'm', 'M', 'a', 'c',
+				'A', 'd', 'd', 'r', 0 };
+	efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID;
+
+	status = efi.get_variable(name, &guid, NULL, &size, buf);
+	if (status == EFI_SUCCESS && size == sizeof(buf))
+		memcpy(mac, buf, sizeof(buf));
+}
+
+/* Probe the TMFIFO. */
+static int tmfifo_probe(struct platform_device *pdev)
+{
+	u64 ctl;
+	struct tmfifo *fifo;
+	struct resource *rx_res, *tx_res;
+	struct virtio_net_config net_config;
+	int i, ret;
+
+	/* Get the resource of the Rx & Tx FIFO. */
+	rx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tx_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!rx_res || !tx_res) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (request_mem_region(rx_res->start,
+			       resource_size(rx_res), "bf-tmfifo") == NULL) {
+		ret = -EBUSY;
+		goto early_err;
+	}
+
+	if (request_mem_region(tx_res->start,
+			       resource_size(tx_res), "bf-tmfifo") == NULL) {
+		release_mem_region(rx_res->start, resource_size(rx_res));
+		ret = -EBUSY;
+		goto early_err;
+	}
+
+	ret = -ENOMEM;
+	fifo = kzalloc(sizeof(struct tmfifo), GFP_KERNEL);
+	if (!fifo)
+		goto err;
+
+	fifo->pdev = pdev;
+	platform_set_drvdata(pdev, fifo);
+
+	INIT_WORK(&fifo->work, tmfifo_work_handler);
+
+	timer_setup(&fifo->timer, tmfifo_timer, 0);
+	fifo->timer.function = tmfifo_timer;
+
+	for (i = 0; i < TM_IRQ_CNT; i++) {
+		fifo->irq[i] = platform_get_irq(pdev, i);
+		ret = request_irq(fifo->irq[i], tmfifo_irq_handler, 0,
+				  "tmfifo", (u8 *)fifo + i);
+		if (ret) {
+			pr_err("Unable to request irq\n");
+			fifo->irq[i] = 0;
+			goto err;
+		}
+	}
+
+	fifo->rx_base = ioremap(rx_res->start, resource_size(rx_res));
+	if (!fifo->rx_base)
+		goto err;
+
+	fifo->tx_base = ioremap(tx_res->start, resource_size(tx_res));
+	if (!fifo->tx_base)
+		goto err;
+
+	/* Get Tx FIFO size and set the low/high watermark. */
+	ctl = readq(fifo->tx_base + TMFIFO_TX_CTL);
+	fifo->tx_fifo_size =
+		TMFIFO_GET_FIELD(ctl, TMFIFO_TX_CTL__MAX_ENTRIES);
+	ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_TX_CTL__LWM, fifo->tx_fifo_size / 2);
+	ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_TX_CTL__HWM, fifo->tx_fifo_size - 1);
+	writeq(ctl, fifo->tx_base + TMFIFO_TX_CTL);
+
+	/* Get Rx FIFO size and set the low/high watermark. */
+	ctl = readq(fifo->rx_base + TMFIFO_RX_CTL);
+	fifo->rx_fifo_size =
+		TMFIFO_GET_FIELD(ctl, TMFIFO_RX_CTL__MAX_ENTRIES);
+	ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_RX_CTL__LWM, 0);
+	ctl = TMFIFO_SET_FIELD(ctl, TMFIFO_RX_CTL__HWM, 1);
+	writeq(ctl, fifo->rx_base + TMFIFO_RX_CTL);
+
+	mutex_init(&fifo->lock);
+
+	/* Create the console vdev. */
+	ret = tmfifo_create_vdev(fifo, VIRTIO_ID_CONSOLE, 0, NULL, 0);
+	if (ret)
+		goto err;
+
+	/* Create the network vdev. */
+	memset(&net_config, 0, sizeof(net_config));
+	net_config.mtu = TMFIFO_NET_MTU;
+	net_config.status = VIRTIO_NET_S_LINK_UP;
+	memcpy(net_config.mac, tmfifo_net_default_mac, 6);
+	tmfifo_get_cfg_mac(net_config.mac);
+	ret = tmfifo_create_vdev(fifo, VIRTIO_ID_NET, TMFIFO_NET_FEATURES,
+				 &net_config, sizeof(net_config));
+	if (ret)
+		goto err;
+
+	mod_timer(&fifo->timer, jiffies + tmfifo_timer_interval);
+
+	tmfifo_ready = true;
+
+	return 0;
+
+err:
+	tmfifo_remove(pdev);
+early_err:
+	dev_err(&pdev->dev, "Probe Failed\n");
+	return ret;
+}
+
+static const struct of_device_id tmfifo_match[] = {
+	{ .compatible = "mellanox,bf-tmfifo" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tmfifo_match);
+
+static const struct acpi_device_id bf_tmfifo_acpi_match[] = {
+	{ "MLNXBF01", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, bf_tmfifo_acpi_match);
+
+static struct platform_driver tmfifo_driver = {
+	.probe = tmfifo_probe,
+	.remove = tmfifo_remove,
+	.driver = {
+		.name = "bf-tmfifo",
+		.of_match_table = tmfifo_match,
+		.acpi_match_table = ACPI_PTR(bf_tmfifo_acpi_match),
+	},
+};
+
+static int __init tmfifo_init(void)
+{
+	int ret;
+
+	mutex_init(&tmfifo_lock);
+
+	ret = platform_driver_register(&tmfifo_driver);
+	if (ret)
+		pr_err("Failed to register tmfifo driver.\n");
+
+	return ret;
+}
+
+static void __exit tmfifo_exit(void)
+{
+	platform_driver_unregister(&tmfifo_driver);
+}
+
+module_init(tmfifo_init);
+module_exit(tmfifo_exit);
+
+MODULE_DESCRIPTION("Mellanox BlueField SoC TMFIFO Driver");
+MODULE_AUTHOR("Mellanox Technologies, Ltd");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.7");
diff --git a/drivers/soc/mellanox/tmfifo_regs.h b/drivers/soc/mellanox/tmfifo_regs.h
new file mode 100644
index 0000000..b07f353
--- /dev/null
+++ b/drivers/soc/mellanox/tmfifo_regs.h
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (c) 2018, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __TMFIFO_REGS_H__
+#define __TMFIFO_REGS_H__
+
+#ifdef __ASSEMBLER__
+#define _64bit(x) x
+#else /* __ASSEMBLER__ */
+#ifdef __tile__
+#define _64bit(x) x ## UL
+#else /* __tile__ */
+#define _64bit(x) x ## ULL
+#endif /* __tile__ */
+#endif /* __ASSEMBLER */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
+#ifndef __DOXYGEN__
+
+#define TMFIFO_TX_DATA 0x0
+
+#define TMFIFO_TX_STS 0x8
+#define TMFIFO_TX_STS__LENGTH 0x0001
+#define TMFIFO_TX_STS__COUNT_SHIFT 0
+#define TMFIFO_TX_STS__COUNT_WIDTH 9
+#define TMFIFO_TX_STS__COUNT_RESET_VAL 0
+#define TMFIFO_TX_STS__COUNT_RMASK 0x1ff
+#define TMFIFO_TX_STS__COUNT_MASK  0x1ff
+
+#define TMFIFO_TX_CTL 0x10
+#define TMFIFO_TX_CTL__LENGTH 0x0001
+#define TMFIFO_TX_CTL__LWM_SHIFT 0
+#define TMFIFO_TX_CTL__LWM_WIDTH 8
+#define TMFIFO_TX_CTL__LWM_RESET_VAL 128
+#define TMFIFO_TX_CTL__LWM_RMASK 0xff
+#define TMFIFO_TX_CTL__LWM_MASK  0xff
+#define TMFIFO_TX_CTL__HWM_SHIFT 8
+#define TMFIFO_TX_CTL__HWM_WIDTH 8
+#define TMFIFO_TX_CTL__HWM_RESET_VAL 128
+#define TMFIFO_TX_CTL__HWM_RMASK 0xff
+#define TMFIFO_TX_CTL__HWM_MASK  0xff00
+#define TMFIFO_TX_CTL__MAX_ENTRIES_SHIFT 32
+#define TMFIFO_TX_CTL__MAX_ENTRIES_WIDTH 9
+#define TMFIFO_TX_CTL__MAX_ENTRIES_RESET_VAL 256
+#define TMFIFO_TX_CTL__MAX_ENTRIES_RMASK 0x1ff
+#define TMFIFO_TX_CTL__MAX_ENTRIES_MASK  _64bit(0x1ff00000000)
+
+#define TMFIFO_RX_DATA 0x0
+
+#define TMFIFO_RX_STS 0x8
+#define TMFIFO_RX_STS__LENGTH 0x0001
+#define TMFIFO_RX_STS__COUNT_SHIFT 0
+#define TMFIFO_RX_STS__COUNT_WIDTH 9
+#define TMFIFO_RX_STS__COUNT_RESET_VAL 0
+#define TMFIFO_RX_STS__COUNT_RMASK 0x1ff
+#define TMFIFO_RX_STS__COUNT_MASK  0x1ff
+
+#define TMFIFO_RX_CTL 0x10
+#define TMFIFO_RX_CTL__LENGTH 0x0001
+#define TMFIFO_RX_CTL__LWM_SHIFT 0
+#define TMFIFO_RX_CTL__LWM_WIDTH 8
+#define TMFIFO_RX_CTL__LWM_RESET_VAL 128
+#define TMFIFO_RX_CTL__LWM_RMASK 0xff
+#define TMFIFO_RX_CTL__LWM_MASK  0xff
+#define TMFIFO_RX_CTL__HWM_SHIFT 8
+#define TMFIFO_RX_CTL__HWM_WIDTH 8
+#define TMFIFO_RX_CTL__HWM_RESET_VAL 128
+#define TMFIFO_RX_CTL__HWM_RMASK 0xff
+#define TMFIFO_RX_CTL__HWM_MASK  0xff00
+#define TMFIFO_RX_CTL__MAX_ENTRIES_SHIFT 32
+#define TMFIFO_RX_CTL__MAX_ENTRIES_WIDTH 9
+#define TMFIFO_RX_CTL__MAX_ENTRIES_RESET_VAL 256
+#define TMFIFO_RX_CTL__MAX_ENTRIES_RMASK 0x1ff
+#define TMFIFO_RX_CTL__MAX_ENTRIES_MASK  _64bit(0x1ff00000000)
+
+#endif /* !defined(__DOXYGEN__) */
+#endif /* !defined(__TMFIFO_REGS_H__) */
-- 
1.8.3.1

^ permalink raw reply related

* [GIT PULL] arm64: fixes for -rc7
From: Will Deacon @ 2018-05-25 16:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Linus,

Here are a few arm64 fixes for -rc7. The two main fixes are for the asm
constraints in our LSE atomics and for our pmd/pud setters when changing
permissions for kernel mappings. Summary in the tag.

Please pull,

Will

--->8

The following changes since commit 771c577c23bac90597c685971d7297ea00f99d11:

  Linux 4.17-rc6 (2018-05-20 15:31:38 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-fixes

for you to fetch changes up to 82034c23fcbc2389c73d97737f61fa2dd6526413:

  arm64: Make sure permission updates happen for pmd/pud (2018-05-24 11:19:31 +0100)

----------------------------------------------------------------
More arm64 fixes:

- Fix application of read-only permissions to kernel section mappings

- Sanitise reported ESR values for signals delivered on a kernel address

- Ensure tishift GCC helpers are exported to modules

- Fix inline asm constraints for some LSE atomics

----------------------------------------------------------------
Jason A. Donenfeld (1):
      arm64: export tishift functions to modules

Laura Abbott (1):
      arm64: Make sure permission updates happen for pmd/pud

Peter Maydell (1):
      arm64: fault: Don't leak data in ESR context for user fault on kernel VA

Will Deacon (1):
      arm64: lse: Add early clobbers to some input/output asm operands

 arch/arm64/include/asm/atomic_lse.h | 24 ++++++++---------
 arch/arm64/kernel/arm64ksyms.c      |  8 ++++++
 arch/arm64/lib/tishift.S            | 15 ++---------
 arch/arm64/mm/fault.c               | 51 +++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/mmu.c                 | 16 +++++++-----
 5 files changed, 83 insertions(+), 31 deletions(-)

^ permalink raw reply

* [PATCH v3 08/15] ARM: spectre-v2: harden user aborts in kernel space
From: Tony Lindgren @ 2018-05-25 16:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525155207.GF17671@n2100.armlinux.org.uk>

* Russell King - ARM Linux <linux@armlinux.org.uk> [180525 15:54]:
> On Fri, May 25, 2018 at 08:47:42AM -0700, Tony Lindgren wrote:
> > We can now get this with the whole series applied:
> > 
> > CPU0: Spectre v2: firmware did not set auxiliary control register
> > IBE bit, system vulnerable
> > CPU: Spectre v2: using ICIALLU workaround
> > 
> > So maybe change the wording from "using %s workaround" to
> > "chosen workaround %s"?
> > 
> > Or I guess disabling the pr_info when not functional can
> > be done in the later patches based on some variable set
> > by check_spectre_auxcr() would be doable too.
> 
> You should not be getting both messages.  It looks like you're using
> an older series - I assumed you pulled my git tree rather than the
> patches?  The public git tree isn't up to date with these changes.

Yes I just fetched your git tree because it allows using
git mergetool because of the conflicts with next. I'll apply
manually and test again.

Thanks,

Tony

^ permalink raw reply

* [RFT v2 1/4] perf cs-etm: Generate sample for missed packets
From: Leo Yan @ 2018-05-25 15:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525152713.GD4091@kernel.org>

Hi Arnaldo, Rob,

On Fri, May 25, 2018 at 12:27:13PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Fri, May 25, 2018 at 03:03:47PM +0100, Robert Walker escreveu:
> > Hi Leo,
> > 
> > Following the discussions from your reply to this with a simplified patch,
> > this version of the patch works better as you also need to emit a branch
> > sample when handling a CS_ETM_TRACE_ON packet to indicate the end of a block
> > of trace.

I also will follow the suggestion as Rob mentioned in another email:
"The deadbeefdeadbeef addresses are a bit ugly - these are just dummy
values emitted in the decoder layer - maybe these should be changed
to 0."

> > This patch does not break the output from perf inject to generate
> > instruction samples for AutoFDO, so I am happy with that.

Thanks for confirmation.

> > Regards
> > 
> > Rob
> > 
> > Reviewed-by: Robert Walker <robert.walker@arm.com>
> 
> So, Leo, can you please resubmit, bumping the v2 to v3 (or the latest
> one, I haven't fully reread this thread) add this "Reviewed-by: Robert"
> tag and any other that people may have provided, so that I can merge it?

Sure!  I will respin the v3 patch series by following up Rob's
suggestion and add Rob's review tag.

BTW, I'd like to get ack from Mathieu as well.  Mathieu is working on
CPU wide tracing, so I talked with Mathieu he will review the patch
series if has conflict with CPU wide tracing.

[...]

Thanks,
Leo Yan

^ permalink raw reply

* [PATCH v2 1/3] input: touchscreen: edt-ft5x06: don't make device a wakeup source by default
From: Rob Herring @ 2018-05-25 15:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180524231732.GC177107@dtor-ws>

On Thu, May 24, 2018 at 6:17 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Wed, May 23, 2018 at 09:45:05AM -0500, Rob Herring wrote:
>> On Wed, May 23, 2018 at 3:27 AM, Daniel Mack <daniel@zonque.org> wrote:
>> > On Tuesday, May 22, 2018 07:54 PM, Rob Herring wrote:
>> >>
>> >> On Thu, May 17, 2018 at 11:05:50AM +0200, Daniel Mack wrote:
>> >>>
>> >>> Allow configuring the device as wakeup source through device properties,
>> >>> as
>> >>> not all platforms want to wake up on touch screen activity.
>> >>>
>> >>> The I2C core automatically reads the "wakeup-source" DT property to
>> >>> configure a device's wakeup capability, and board supports files can set
>> >>> I2C_CLIENT_WAKE in the flags.
>> >>
>> >>
>> >> This will break wake-up on working systems. Looks like mostly i.MX, but
>> >> there's one AM437x board. If that board doesn't care, then it is up to
>> >> Shawn.
>> >
>> >
>> > I added the property to the dts files, but as Dmitry pointed out, I missed
>> > some. Sorry for that.
>>
>> Just adding the property to dts files doesn't fix the compatibility
>> problem. If a user uses an existing dtb (before this change) with a
>> new kernel (after this change), then wakeup will stop working.
>
> Is this a practical problem though? Do we know of any products with
> this touch panel that use DTS not distributed with the kernel?

Distribution of dts with kernel is irrelevant. It is how the dtb's are
handled that matters. You still need to ask in tree users.

I can't have any way of knowing what DTs may exist as there is only
one upstream repository of dts files. There's not really a good
solution on this to avoid breaking users, so we'll just have to see if
anyone (besides the known users) complains.

Rob

^ permalink raw reply

* [PATCH v3 08/15] ARM: spectre-v2: harden user aborts in kernel space
From: Russell King - ARM Linux @ 2018-05-25 15:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180525154742.GA77025@atomide.com>

On Fri, May 25, 2018 at 08:47:42AM -0700, Tony Lindgren wrote:
> * Russell King <rmk+kernel@armlinux.org.uk> [180525 15:10]:
> > +static void cpu_v7_spectre_init(void)
> > +{
> > +	const char *spectre_v2_method = NULL;
> > +	int cpu = smp_processor_id();
> > +
> > +	if (per_cpu(harden_branch_predictor_fn, cpu))
> > +		return;
> > +
> > +	switch (read_cpuid_part()) {
> > +	case ARM_CPU_PART_CORTEX_A8:
> > +	case ARM_CPU_PART_CORTEX_A9:
> > +	case ARM_CPU_PART_CORTEX_A12:
> > +	case ARM_CPU_PART_CORTEX_A17:
> > +	case ARM_CPU_PART_CORTEX_A73:
> > +	case ARM_CPU_PART_CORTEX_A75:
> > +		per_cpu(harden_branch_predictor_fn, cpu) =
> > +			harden_branch_predictor_bpiall;
> > +		spectre_v2_method = "BPIALL";
> > +		break;
> > +
> > +	case ARM_CPU_PART_CORTEX_A15:
> > +	case ARM_CPU_PART_BRAHMA_B15:
> > +		per_cpu(harden_branch_predictor_fn, cpu) =
> > +			harden_branch_predictor_iciallu;
> > +		spectre_v2_method = "ICIALLU";
> > +		break;
> > +	}
> > +	if (spectre_v2_method)
> > +		pr_info("CPU%u: Spectre v2: using %s workaround\n",
> > +			smp_processor_id(), spectre_v2_method);
> > +}
> 
> We can now get this with the whole series applied:
> 
> CPU0: Spectre v2: firmware did not set auxiliary control register
> IBE bit, system vulnerable
> CPU: Spectre v2: using ICIALLU workaround
> 
> So maybe change the wording from "using %s workaround" to
> "chosen workaround %s"?
> 
> Or I guess disabling the pr_info when not functional can
> be done in the later patches based on some variable set
> by check_spectre_auxcr() would be doable too.

You should not be getting both messages.  It looks like you're using
an older series - I assumed you pulled my git tree rather than the
patches?  The public git tree isn't up to date with these changes.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox