diff options
-rw-r--r-- | Documentation/devicetree/bindings/firmware/qcom,scm.txt | 2 | ||||
-rw-r--r-- | drivers/firmware/qcom_scm.c | 49 |
2 files changed, 39 insertions, 12 deletions
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt index 3b4436e56865..20f26fbce875 100644 --- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt | |||
@@ -10,8 +10,10 @@ Required properties: | |||
10 | * "qcom,scm-apq8064" for APQ8064 platforms | 10 | * "qcom,scm-apq8064" for APQ8064 platforms |
11 | * "qcom,scm-msm8660" for MSM8660 platforms | 11 | * "qcom,scm-msm8660" for MSM8660 platforms |
12 | * "qcom,scm-msm8690" for MSM8690 platforms | 12 | * "qcom,scm-msm8690" for MSM8690 platforms |
13 | * "qcom,scm-msm8996" for MSM8996 platforms | ||
13 | * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc) | 14 | * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc) |
14 | - clocks: One to three clocks may be required based on compatible. | 15 | - clocks: One to three clocks may be required based on compatible. |
16 | * No clock required for "qcom,scm-msm8996" | ||
15 | * Only core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660", and "qcom,scm-msm8960" | 17 | * Only core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660", and "qcom,scm-msm8960" |
16 | * Core, iface, and bus clocks required for "qcom,scm" | 18 | * Core, iface, and bus clocks required for "qcom,scm" |
17 | - clock-names: Must contain "core" for the core clock, "iface" for the interface | 19 | - clock-names: Must contain "core" for the core clock, "iface" for the interface |
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 9bf66aefdbd0..893f953eaccf 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c | |||
@@ -28,6 +28,10 @@ | |||
28 | 28 | ||
29 | #include "qcom_scm.h" | 29 | #include "qcom_scm.h" |
30 | 30 | ||
31 | #define SCM_HAS_CORE_CLK BIT(0) | ||
32 | #define SCM_HAS_IFACE_CLK BIT(1) | ||
33 | #define SCM_HAS_BUS_CLK BIT(2) | ||
34 | |||
31 | struct qcom_scm { | 35 | struct qcom_scm { |
32 | struct device *dev; | 36 | struct device *dev; |
33 | struct clk *core_clk; | 37 | struct clk *core_clk; |
@@ -323,32 +327,40 @@ EXPORT_SYMBOL(qcom_scm_is_available); | |||
323 | static int qcom_scm_probe(struct platform_device *pdev) | 327 | static int qcom_scm_probe(struct platform_device *pdev) |
324 | { | 328 | { |
325 | struct qcom_scm *scm; | 329 | struct qcom_scm *scm; |
330 | unsigned long clks; | ||
326 | int ret; | 331 | int ret; |
327 | 332 | ||
328 | scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL); | 333 | scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL); |
329 | if (!scm) | 334 | if (!scm) |
330 | return -ENOMEM; | 335 | return -ENOMEM; |
331 | 336 | ||
332 | scm->core_clk = devm_clk_get(&pdev->dev, "core"); | 337 | clks = (unsigned long)of_device_get_match_data(&pdev->dev); |
333 | if (IS_ERR(scm->core_clk)) { | 338 | if (clks & SCM_HAS_CORE_CLK) { |
334 | if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER) | 339 | scm->core_clk = devm_clk_get(&pdev->dev, "core"); |
340 | if (IS_ERR(scm->core_clk)) { | ||
341 | if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER) | ||
342 | dev_err(&pdev->dev, | ||
343 | "failed to acquire core clk\n"); | ||
335 | return PTR_ERR(scm->core_clk); | 344 | return PTR_ERR(scm->core_clk); |
336 | 345 | } | |
337 | scm->core_clk = NULL; | ||
338 | } | 346 | } |
339 | 347 | ||
340 | if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) { | 348 | if (clks & SCM_HAS_IFACE_CLK) { |
341 | scm->iface_clk = devm_clk_get(&pdev->dev, "iface"); | 349 | scm->iface_clk = devm_clk_get(&pdev->dev, "iface"); |
342 | if (IS_ERR(scm->iface_clk)) { | 350 | if (IS_ERR(scm->iface_clk)) { |
343 | if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER) | 351 | if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER) |
344 | dev_err(&pdev->dev, "failed to acquire iface clk\n"); | 352 | dev_err(&pdev->dev, |
353 | "failed to acquire iface clk\n"); | ||
345 | return PTR_ERR(scm->iface_clk); | 354 | return PTR_ERR(scm->iface_clk); |
346 | } | 355 | } |
356 | } | ||
347 | 357 | ||
358 | if (clks & SCM_HAS_BUS_CLK) { | ||
348 | scm->bus_clk = devm_clk_get(&pdev->dev, "bus"); | 359 | scm->bus_clk = devm_clk_get(&pdev->dev, "bus"); |
349 | if (IS_ERR(scm->bus_clk)) { | 360 | if (IS_ERR(scm->bus_clk)) { |
350 | if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER) | 361 | if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER) |
351 | dev_err(&pdev->dev, "failed to acquire bus clk\n"); | 362 | dev_err(&pdev->dev, |
363 | "failed to acquire bus clk\n"); | ||
352 | return PTR_ERR(scm->bus_clk); | 364 | return PTR_ERR(scm->bus_clk); |
353 | } | 365 | } |
354 | } | 366 | } |
@@ -374,10 +386,23 @@ static int qcom_scm_probe(struct platform_device *pdev) | |||
374 | } | 386 | } |
375 | 387 | ||
376 | static const struct of_device_id qcom_scm_dt_match[] = { | 388 | static const struct of_device_id qcom_scm_dt_match[] = { |
377 | { .compatible = "qcom,scm-apq8064",}, | 389 | { .compatible = "qcom,scm-apq8064", |
378 | { .compatible = "qcom,scm-msm8660",}, | 390 | .data = (void *) SCM_HAS_CORE_CLK, |
379 | { .compatible = "qcom,scm-msm8960",}, | 391 | }, |
380 | { .compatible = "qcom,scm",}, | 392 | { .compatible = "qcom,scm-msm8660", |
393 | .data = (void *) SCM_HAS_CORE_CLK, | ||
394 | }, | ||
395 | { .compatible = "qcom,scm-msm8960", | ||
396 | .data = (void *) SCM_HAS_CORE_CLK, | ||
397 | }, | ||
398 | { .compatible = "qcom,scm-msm8996", | ||
399 | .data = NULL, /* no clocks */ | ||
400 | }, | ||
401 | { .compatible = "qcom,scm", | ||
402 | .data = (void *)(SCM_HAS_CORE_CLK | ||
403 | | SCM_HAS_IFACE_CLK | ||
404 | | SCM_HAS_BUS_CLK), | ||
405 | }, | ||
381 | {} | 406 | {} |
382 | }; | 407 | }; |
383 | 408 | ||