Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
[linux-2.6-microblaze.git] / drivers / remoteproc / qcom_q6v5_adsp.c
index 1f3ef9e..e953886 100644 (file)
 #define LPASS_PWR_ON_REG               0x10
 #define LPASS_HALTREQ_REG              0x0
 
-/* list of clocks required by ADSP PIL */
-static const char * const adsp_clk_id[] = {
-       "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
-       "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core",
-};
+#define QDSP6SS_XO_CBCR                0x38
+#define QDSP6SS_CORE_CBCR      0x20
+#define QDSP6SS_SLEEP_CBCR     0x3c
 
 struct adsp_pil_data {
        int crash_reason_smem;
@@ -59,6 +57,9 @@ struct adsp_pil_data {
        const char *ssr_name;
        const char *sysmon_name;
        int ssctl_id;
+
+       const char **clk_ids;
+       int num_clks;
 };
 
 struct qcom_adsp {
@@ -75,7 +76,7 @@ struct qcom_adsp {
        void __iomem *qdsp6ss_base;
 
        struct reset_control *pdc_sync_reset;
-       struct reset_control *cc_lpass_restart;
+       struct reset_control *restart;
 
        struct regmap *halt_map;
        unsigned int halt_lpass;
@@ -143,7 +144,7 @@ reset:
        /* Assert the LPASS PDC Reset */
        reset_control_assert(adsp->pdc_sync_reset);
        /* Place the LPASS processor into reset */
-       reset_control_assert(adsp->cc_lpass_restart);
+       reset_control_assert(adsp->restart);
        /* wait after asserting subsystem restart from AOSS */
        usleep_range(200, 300);
 
@@ -153,7 +154,7 @@ reset:
        /* De-assert the LPASS PDC Reset */
        reset_control_deassert(adsp->pdc_sync_reset);
        /* Remove the LPASS reset */
-       reset_control_deassert(adsp->cc_lpass_restart);
+       reset_control_deassert(adsp->restart);
        /* wait after de-asserting subsystem restart from AOSS */
        usleep_range(200, 300);
 
@@ -192,6 +193,15 @@ static int adsp_start(struct rproc *rproc)
                goto disable_power_domain;
        }
 
+       /* Enable the XO clock */
+       writel(1, adsp->qdsp6ss_base + QDSP6SS_XO_CBCR);
+
+       /* Enable the QDSP6SS sleep clock */
+       writel(1, adsp->qdsp6ss_base + QDSP6SS_SLEEP_CBCR);
+
+       /* Enable the QDSP6 core clock */
+       writel(1, adsp->qdsp6ss_base + QDSP6SS_CORE_CBCR);
+
        /* Program boot address */
        writel(adsp->mem_phys >> 4, adsp->qdsp6ss_base + RST_EVB_REG);
 
@@ -280,8 +290,9 @@ static const struct rproc_ops adsp_ops = {
        .load = adsp_load,
 };
 
-static int adsp_init_clock(struct qcom_adsp *adsp)
+static int adsp_init_clock(struct qcom_adsp *adsp, const char **clk_ids)
 {
+       int num_clks = 0;
        int i, ret;
 
        adsp->xo = devm_clk_get(adsp->dev, "xo");
@@ -292,32 +303,39 @@ static int adsp_init_clock(struct qcom_adsp *adsp)
                return ret;
        }
 
-       adsp->num_clks = ARRAY_SIZE(adsp_clk_id);
+       for (i = 0; clk_ids[i]; i++)
+               num_clks++;
+
+       adsp->num_clks = num_clks;
        adsp->clks = devm_kcalloc(adsp->dev, adsp->num_clks,
                                sizeof(*adsp->clks), GFP_KERNEL);
        if (!adsp->clks)
                return -ENOMEM;
 
        for (i = 0; i < adsp->num_clks; i++)
-               adsp->clks[i].id = adsp_clk_id[i];
+               adsp->clks[i].id = clk_ids[i];
 
        return devm_clk_bulk_get(adsp->dev, adsp->num_clks, adsp->clks);
 }
 
 static int adsp_init_reset(struct qcom_adsp *adsp)
 {
-       adsp->pdc_sync_reset = devm_reset_control_get_exclusive(adsp->dev,
+       adsp->pdc_sync_reset = devm_reset_control_get_optional_exclusive(adsp->dev,
                        "pdc_sync");
        if (IS_ERR(adsp->pdc_sync_reset)) {
                dev_err(adsp->dev, "failed to acquire pdc_sync reset\n");
                return PTR_ERR(adsp->pdc_sync_reset);
        }
 
-       adsp->cc_lpass_restart = devm_reset_control_get_exclusive(adsp->dev,
-                       "cc_lpass");
-       if (IS_ERR(adsp->cc_lpass_restart)) {
-               dev_err(adsp->dev, "failed to acquire cc_lpass restart\n");
-               return PTR_ERR(adsp->cc_lpass_restart);
+       adsp->restart = devm_reset_control_get_optional_exclusive(adsp->dev, "restart");
+
+       /* Fall back to the  old "cc_lpass" if "restart" is absent */
+       if (!adsp->restart)
+               adsp->restart = devm_reset_control_get_exclusive(adsp->dev, "cc_lpass");
+
+       if (IS_ERR(adsp->restart)) {
+               dev_err(adsp->dev, "failed to acquire restart\n");
+               return PTR_ERR(adsp->restart);
        }
 
        return 0;
@@ -415,7 +433,7 @@ static int adsp_probe(struct platform_device *pdev)
        if (ret)
                goto free_rproc;
 
-       ret = adsp_init_clock(adsp);
+       ret = adsp_init_clock(adsp, desc->clk_ids);
        if (ret)
                goto free_rproc;
 
@@ -479,9 +497,28 @@ static const struct adsp_pil_data adsp_resource_init = {
        .ssr_name = "lpass",
        .sysmon_name = "adsp",
        .ssctl_id = 0x14,
+       .clk_ids = (const char*[]) {
+               "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
+               "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", NULL
+       },
+       .num_clks = 7,
+};
+
+static const struct adsp_pil_data cdsp_resource_init = {
+       .crash_reason_smem = 601,
+       .firmware_name = "cdsp.mdt",
+       .ssr_name = "cdsp",
+       .sysmon_name = "cdsp",
+       .ssctl_id = 0x17,
+       .clk_ids = (const char*[]) {
+               "sway", "tbu", "bimc", "ahb_aon", "q6ss_slave", "q6ss_master",
+               "q6_axim", NULL
+       },
+       .num_clks = 7,
 };
 
 static const struct of_device_id adsp_of_match[] = {
+       { .compatible = "qcom,qcs404-cdsp-pil", .data = &cdsp_resource_init },
        { .compatible = "qcom,sdm845-adsp-pil", .data = &adsp_resource_init },
        { },
 };