mirror of
https://github.com/hanwckf/immortalwrt-mt798x.git
synced 2025-01-10 03:09:08 +08:00
126 lines
3.7 KiB
Diff
126 lines
3.7 KiB
Diff
--- 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");
|