[][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");