summaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorAvaneesh Kumar Dwivedi <akdwived@codeaurora.org>2016-12-30 08:54:01 -0500
committerBjorn Andersson <bjorn.andersson@linaro.org>2017-01-18 13:46:50 -0500
commit39b2410bdcdbc2f7a96cde9966d8eabe861e6d3c (patch)
tree70a7027a2dc692379ace63062df7470b8fb470fa /drivers/remoteproc
parent7a8ffe1fcaf89bb7d2588b98cba3163ee7d9db7a (diff)
remoteproc: qcom: Initialize and enable proxy and active clocks.
Certain clocks need voting by rproc on behalf of hexagon only during restart operation but certain clocks need to be voted till hexagon is up, these clocks are identified as proxy and active clocks respectively. This patch provide interface to initialize, enable and disable proxy and active clocks separately. Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> [bjorn: dropped disable of proxy clocks on stop] Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/qcom_q6v5_pil.c151
1 files changed, 109 insertions, 42 deletions
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index 1bebe88fdb62..991193596d9e 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -95,6 +95,8 @@
95 95
96struct rproc_hexagon_res { 96struct rproc_hexagon_res {
97 const char *hexagon_mba_image; 97 const char *hexagon_mba_image;
98 char **proxy_clk_names;
99 char **active_clk_names;
98}; 100};
99 101
100struct q6v5 { 102struct q6v5 {
@@ -114,11 +116,13 @@ struct q6v5 {
114 struct qcom_smem_state *state; 116 struct qcom_smem_state *state;
115 unsigned stop_bit; 117 unsigned stop_bit;
116 118
119 struct clk *active_clks[8];
120 struct clk *proxy_clks[4];
121 int active_clk_count;
122 int proxy_clk_count;
123
117 struct regulator_bulk_data supply[4]; 124 struct regulator_bulk_data supply[4];
118 125
119 struct clk *ahb_clk;
120 struct clk *axi_clk;
121 struct clk *rom_clk;
122 126
123 struct completion start_done; 127 struct completion start_done;
124 struct completion stop_done; 128 struct completion stop_done;
@@ -193,6 +197,37 @@ static void q6v5_regulator_disable(struct q6v5 *qproc)
193 regulator_set_voltage(mss, 0, 1150000); 197 regulator_set_voltage(mss, 0, 1150000);
194} 198}
195 199
200static int q6v5_clk_enable(struct device *dev,
201 struct clk **clks, int count)
202{
203 int rc;
204 int i;
205
206 for (i = 0; i < count; i++) {
207 rc = clk_prepare_enable(clks[i]);
208 if (rc) {
209 dev_err(dev, "Clock enable failed\n");
210 goto err;
211 }
212 }
213
214 return 0;
215err:
216 for (i--; i >= 0; i--)
217 clk_disable_unprepare(clks[i]);
218
219 return rc;
220}
221
222static void q6v5_clk_disable(struct device *dev,
223 struct clk **clks, int count)
224{
225 int i;
226
227 for (i = 0; i < count; i++)
228 clk_disable_unprepare(clks[i]);
229}
230
196static int q6v5_load(struct rproc *rproc, const struct firmware *fw) 231static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
197{ 232{
198 struct q6v5 *qproc = rproc->priv; 233 struct q6v5 *qproc = rproc->priv;
@@ -488,23 +523,24 @@ static int q6v5_start(struct rproc *rproc)
488 return ret; 523 return ret;
489 } 524 }
490 525
526 ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,
527 qproc->proxy_clk_count);
528 if (ret) {
529 dev_err(qproc->dev, "failed to enable proxy clocks\n");
530 goto disable_vdd;
531 }
491 ret = reset_control_deassert(qproc->mss_restart); 532 ret = reset_control_deassert(qproc->mss_restart);
492 if (ret) { 533 if (ret) {
493 dev_err(qproc->dev, "failed to deassert mss restart\n"); 534 dev_err(qproc->dev, "failed to deassert mss restart\n");
494 goto disable_vdd; 535 goto disable_proxy_clk;
495 } 536 }
496 537
497 ret = clk_prepare_enable(qproc->ahb_clk); 538 ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,
498 if (ret) 539 qproc->active_clk_count);
540 if (ret) {
541 dev_err(qproc->dev, "failed to enable clocks\n");
499 goto assert_reset; 542 goto assert_reset;
500 543 }
501 ret = clk_prepare_enable(qproc->axi_clk);
502 if (ret)
503 goto disable_ahb_clk;
504
505 ret = clk_prepare_enable(qproc->rom_clk);
506 if (ret)
507 goto disable_axi_clk;
508 544
509 writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG); 545 writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG);
510 546
@@ -539,7 +575,8 @@ static int q6v5_start(struct rproc *rproc)
539 575
540 qproc->running = true; 576 qproc->running = true;
541 577
542 /* TODO: All done, release the handover resources */ 578 q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
579 qproc->proxy_clk_count);
543 580
544 return 0; 581 return 0;
545 582
@@ -547,14 +584,13 @@ halt_axi_ports:
547 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6); 584 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
548 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); 585 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
549 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); 586 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
550 587 q6v5_clk_disable(qproc->dev, qproc->active_clks,
551 clk_disable_unprepare(qproc->rom_clk); 588 qproc->active_clk_count);
552disable_axi_clk:
553 clk_disable_unprepare(qproc->axi_clk);
554disable_ahb_clk:
555 clk_disable_unprepare(qproc->ahb_clk);
556assert_reset: 589assert_reset:
557 reset_control_assert(qproc->mss_restart); 590 reset_control_assert(qproc->mss_restart);
591disable_proxy_clk:
592 q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
593 qproc->proxy_clk_count);
558disable_vdd: 594disable_vdd:
559 q6v5_regulator_disable(qproc); 595 q6v5_regulator_disable(qproc);
560 596
@@ -583,9 +619,8 @@ static int q6v5_stop(struct rproc *rproc)
583 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); 619 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
584 620
585 reset_control_assert(qproc->mss_restart); 621 reset_control_assert(qproc->mss_restart);
586 clk_disable_unprepare(qproc->rom_clk); 622 q6v5_clk_disable(qproc->dev, qproc->active_clks,
587 clk_disable_unprepare(qproc->axi_clk); 623 qproc->active_clk_count);
588 clk_disable_unprepare(qproc->ahb_clk);
589 q6v5_regulator_disable(qproc); 624 q6v5_regulator_disable(qproc);
590 625
591 return 0; 626 return 0;
@@ -706,27 +741,27 @@ static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev)
706 return 0; 741 return 0;
707} 742}
708 743
709static int q6v5_init_clocks(struct q6v5 *qproc) 744static int q6v5_init_clocks(struct device *dev, struct clk **clks,
745 char **clk_names)
710{ 746{
711 qproc->ahb_clk = devm_clk_get(qproc->dev, "iface"); 747 int i;
712 if (IS_ERR(qproc->ahb_clk)) {
713 dev_err(qproc->dev, "failed to get iface clock\n");
714 return PTR_ERR(qproc->ahb_clk);
715 }
716 748
717 qproc->axi_clk = devm_clk_get(qproc->dev, "bus"); 749 if (!clk_names)
718 if (IS_ERR(qproc->axi_clk)) { 750 return 0;
719 dev_err(qproc->dev, "failed to get bus clock\n"); 751
720 return PTR_ERR(qproc->axi_clk); 752 for (i = 0; clk_names[i]; i++) {
721 } 753 clks[i] = devm_clk_get(dev, clk_names[i]);
754 if (IS_ERR(clks[i])) {
755 int rc = PTR_ERR(clks[i]);
722 756
723 qproc->rom_clk = devm_clk_get(qproc->dev, "mem"); 757 if (rc != -EPROBE_DEFER)
724 if (IS_ERR(qproc->rom_clk)) { 758 dev_err(dev, "Failed to get %s clock\n",
725 dev_err(qproc->dev, "failed to get mem clock\n"); 759 clk_names[i]);
726 return PTR_ERR(qproc->rom_clk); 760 return rc;
761 }
727 } 762 }
728 763
729 return 0; 764 return i;
730} 765}
731 766
732static int q6v5_init_reset(struct q6v5 *qproc) 767static int q6v5_init_reset(struct q6v5 *qproc)
@@ -843,9 +878,21 @@ static int q6v5_probe(struct platform_device *pdev)
843 if (ret) 878 if (ret)
844 goto free_rproc; 879 goto free_rproc;
845 880
846 ret = q6v5_init_clocks(qproc); 881 ret = q6v5_init_clocks(&pdev->dev, qproc->proxy_clks,
847 if (ret) 882 desc->proxy_clk_names);
883 if (ret < 0) {
884 dev_err(&pdev->dev, "Failed to get proxy clocks.\n");
848 goto free_rproc; 885 goto free_rproc;
886 }
887 qproc->proxy_clk_count = ret;
888
889 ret = q6v5_init_clocks(&pdev->dev, qproc->active_clks,
890 desc->active_clk_names);
891 if (ret < 0) {
892 dev_err(&pdev->dev, "Failed to get active clocks.\n");
893 goto free_rproc;
894 }
895 qproc->active_clk_count = ret;
849 896
850 ret = q6v5_regulator_init(qproc); 897 ret = q6v5_regulator_init(qproc);
851 if (ret) 898 if (ret)
@@ -901,10 +948,30 @@ static int q6v5_remove(struct platform_device *pdev)
901 948
902static const struct rproc_hexagon_res msm8916_mss = { 949static const struct rproc_hexagon_res msm8916_mss = {
903 .hexagon_mba_image = "mba.mbn", 950 .hexagon_mba_image = "mba.mbn",
951 .proxy_clk_names = (char*[]){
952 "xo",
953 NULL
954 },
955 .active_clk_names = (char*[]){
956 "iface",
957 "bus",
958 "mem",
959 NULL
960 },
904}; 961};
905 962
906static const struct rproc_hexagon_res msm8974_mss = { 963static const struct rproc_hexagon_res msm8974_mss = {
907 .hexagon_mba_image = "mba.b00", 964 .hexagon_mba_image = "mba.b00",
965 .proxy_clk_names = (char*[]){
966 "xo",
967 NULL
968 },
969 .active_clk_names = (char*[]){
970 "iface",
971 "bus",
972 "mem",
973 NULL
974 },
908}; 975};
909 976
910static const struct of_device_id q6v5_of_match[] = { 977static const struct of_device_id q6v5_of_match[] = {