[][arm64: dts: mt7986: Add mmc subsys clock control]

[Description]
Add support for the additional subsys clocks to allow it to be
configured appropriately.

[Release-log]
N/A

Change-Id: I7a2c965f88e705c29483f4c722134780d91a53bd
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5950105
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-clkitg.dtsi b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-clkitg.dtsi
index b148f6d..feef6a2 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-clkitg.dtsi
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986-clkitg.dtsi
@@ -99,10 +99,10 @@
 			<&clk40m>,
 			<&clk40m>,
 			<&infracfg_ao CK_INFRA_FRTC_CK>,
-			<&infracfg_ao CK_INFRA_MSDC_CK>,
-			<&infracfg_ao CK_INFRA_MSDC_HCK_CK>,
-			<&infracfg_ao CK_INFRA_MSDC_133M_CK>,
-			<&infracfg_ao CK_INFRA_MSDC_66M_CK>,
+			<&clk40m>,
+			<&clk40m>,
+			<&clk40m>,
+			<&clk40m>,
 			<&clk40m>,
 			<&clk40m>,
 			<&infracfg_ao CK_INFRA_FBIST2FPC_CK>,
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
index 2b72991..9f86879 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -538,9 +538,11 @@
 			<0 0x11c20000 0 0x1000>;
 		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&topckgen CK_TOP_EMMC_416M>,
-			<&topckgen CK_TOP_EMMC_250M>,
-			<&infracfg_ao CK_INFRA_MSDC_CK>;
-		clock-names = "source", "hclk", "source_cg";
+			<&infracfg_ao CK_INFRA_MSDC_HCK_CK>,
+			<&infracfg_ao CK_INFRA_MSDC_CK>,
+			<&infracfg_ao CK_INFRA_MSDC_66M_CK>,
+			<&infracfg_ao CK_INFRA_MSDC_133M_CK>;
+		clock-names = "source", "hclk", "source_cg", "sys_cg", "axi_cg";
 		assigned-clocks = <&topckgen CK_TOP_EMMC_416M_SEL>,
 				  <&topckgen CK_TOP_EMMC_250M_SEL>;
 		assigned-clock-parents = <&topckgen CK_TOP_CB_M_416M>,
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
index 14e3640..523d585 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
@@ -504,9 +504,11 @@
 			<0 0x11c20000 0 0x1000>;
 		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&topckgen CK_TOP_EMMC_416M>,
-			<&topckgen CK_TOP_EMMC_250M>,
-			<&infracfg_ao CK_INFRA_MSDC_CK>;
-		clock-names = "source", "hclk", "source_cg";
+			<&infracfg_ao CK_INFRA_MSDC_HCK_CK>,
+			<&infracfg_ao CK_INFRA_MSDC_CK>,
+			<&infracfg_ao CK_INFRA_MSDC_66M_CK>,
+			<&infracfg_ao CK_INFRA_MSDC_133M_CK>;
+		clock-names = "source", "hclk", "source_cg", "sys_cg", "axi_cg";
 		assigned-clocks = <&topckgen CK_TOP_EMMC_416M_SEL>,
 				  <&topckgen CK_TOP_EMMC_250M_SEL>;
 		assigned-clock-parents = <&topckgen CK_TOP_CB_M_416M>,
diff --git a/target/linux/mediatek/patches-5.4/0802-mtk-sd-Add-subsys-clock-control.patch b/target/linux/mediatek/patches-5.4/0802-mtk-sd-Add-subsys-clock-control.patch
new file mode 100644
index 0000000..8732cef
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/0802-mtk-sd-Add-subsys-clock-control.patch
@@ -0,0 +1,125 @@
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -33,6 +33,7 @@
+ #include <linux/mmc/slot-gpio.h>
+ 
+ #define MAX_BD_NUM          1024
++#define MSDC_NR_CLOCKS	    3
+ 
+ /*--------------------------------------------------------------------------*/
+ /* Common Definition                                                        */
+@@ -419,6 +420,8 @@ struct msdc_host {
+ 	struct clk *h_clk;      /* msdc h_clk */
+ 	struct clk *bus_clk;	/* bus clock which used to access register */
+ 	struct clk *src_clk_cg; /* msdc source clock control gate */
++	struct clk *sys_clk_cg; /* msdc subsys clock control gate */
++	struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS];
+ 	u32 mclk;		/* mmc subsystem clock frequency */
+ 	u32 src_clk_freq;	/* source clock frequency */
+ 	unsigned char timing;
+@@ -745,6 +748,7 @@ static void msdc_set_timeout(struct msdc
+ 
+ static void msdc_gate_clock(struct msdc_host *host)
+ {
++	clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks);
+ 	clk_disable_unprepare(host->src_clk_cg);
+ 	clk_disable_unprepare(host->src_clk);
+ 	clk_disable_unprepare(host->bus_clk);
+@@ -753,10 +757,18 @@ static void msdc_gate_clock(struct msdc_
+ 
+ static void msdc_ungate_clock(struct msdc_host *host)
+ {
++	int ret;
++
+ 	clk_prepare_enable(host->h_clk);
+ 	clk_prepare_enable(host->bus_clk);
+ 	clk_prepare_enable(host->src_clk);
+ 	clk_prepare_enable(host->src_clk_cg);
++	ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks);
++	if (ret) {
++		dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n");
++		return;
++	}
++
+ 	while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
+ 		cpu_relax();
+ }
+@@ -2195,6 +2207,50 @@ static void msdc_of_property_parse(struc
+ 		host->hs400_cmd_resp_sel_rising = false;
+ }
+ 
++static int msdc_of_clock_parse(struct platform_device *pdev,
++			       struct msdc_host *host)
++{
++	int ret;
++
++	host->src_clk = devm_clk_get(&pdev->dev, "source");
++	if (IS_ERR(host->src_clk))
++		return PTR_ERR(host->src_clk);
++
++	host->h_clk = devm_clk_get(&pdev->dev, "hclk");
++	if (IS_ERR(host->h_clk))
++		return PTR_ERR(host->h_clk);
++
++	host->bus_clk = devm_clk_get_optional(&pdev->dev, "bus_clk");
++	if (IS_ERR(host->bus_clk))
++		host->bus_clk = NULL;
++
++
++	/*source clock control gate is optional clock*/
++	host->src_clk_cg = devm_clk_get_optional(&pdev->dev, "source_cg");
++	if (IS_ERR(host->src_clk_cg))
++		host->src_clk_cg = NULL;
++
++	host->sys_clk_cg = devm_clk_get_optional(&pdev->dev, "sys_cg");
++	if (IS_ERR(host->sys_clk_cg))
++		host->sys_clk_cg = NULL;
++
++	/* If present, always enable for this clock gate */
++	clk_prepare_enable(host->sys_clk_cg);
++
++	host->bulk_clks[0].id = "pclk_cg";
++	host->bulk_clks[1].id = "axi_cg";
++	host->bulk_clks[2].id = "ahb_cg";
++
++	ret = devm_clk_bulk_get_optional(&pdev->dev, MSDC_NR_CLOCKS,
++					 host->bulk_clks);
++	if (ret) {
++		dev_err(&pdev->dev, "Cannot get pclk/axi/ahb clock gates\n");
++		return ret;
++	}
++
++	return 0;
++}
++
+ static int msdc_drv_probe(struct platform_device *pdev)
+ {
+ 	struct mmc_host *mmc;
+@@ -2235,25 +2291,9 @@ static int msdc_drv_probe(struct platfor
+ 	if (ret)
+ 		goto host_free;
+ 
+-	host->src_clk = devm_clk_get(&pdev->dev, "source");
+-	if (IS_ERR(host->src_clk)) {
+-		ret = PTR_ERR(host->src_clk);
+-		goto host_free;
+-	}
+-
+-	host->h_clk = devm_clk_get(&pdev->dev, "hclk");
+-	if (IS_ERR(host->h_clk)) {
+-		ret = PTR_ERR(host->h_clk);
++	ret = msdc_of_clock_parse(pdev, host);
++	if (ret)
+ 		goto host_free;
+-	}
+-
+-	host->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
+-	if (IS_ERR(host->bus_clk))
+-		host->bus_clk = NULL;
+-	/*source clock control gate is optional clock*/
+-	host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg");
+-	if (IS_ERR(host->src_clk_cg))
+-		host->src_clk_cg = NULL;
+ 
+ 	host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
+ 								"hrst");