Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'clk-pm-runtime' into clk-next

* clk-pm-runtime:
clk: samsung: exynos-audss: Add support for runtime PM
clk: samsung: exynos-audss: Use local variable for controller's device
clk: samsung: exynos5433: Add support for runtime PM
clk: samsung: Add support for runtime PM
clk: Add support for runtime PM

+519 -135
+6
Documentation/devicetree/bindings/clock/clk-exynos-audss.txt
··· 33 33 - clock-names: Aliases for the above clocks. They should be "pll_ref", 34 34 "pll_in", "cdclk", "sclk_audio", and "sclk_pcm_in" respectively. 35 35 36 + Optional Properties: 37 + 38 + - power-domains: a phandle to respective power domain node as described by 39 + generic PM domain bindings (see power/power_domain.txt for more 40 + information). 41 + 36 42 The following is the list of clocks generated by the controller. Each clock is 37 43 assigned an identifier and client nodes use this identifier to specify the 38 44 clock which they consume. Some of the clocks are available only on a particular
+16
Documentation/devicetree/bindings/clock/exynos5433-clock.txt
··· 168 168 - aclk_cam1_400 169 169 - aclk_cam1_552 170 170 171 + Optional properties: 172 + - power-domains: a phandle to respective power domain node as described by 173 + generic PM domain bindings (see power/power_domain.txt for more 174 + information). 175 + 171 176 Each clock is assigned an identifier and client nodes can use this identifier 172 177 to specify the clock which they consume. 173 178 ··· 275 270 clocks = <&xxti>, 276 271 <&cmu_top CLK_ACLK_G2D_266>, 277 272 <&cmu_top CLK_ACLK_G2D_400>; 273 + power-domains = <&pd_g2d>; 278 274 }; 279 275 280 276 cmu_disp: clock-controller@13b90000 { ··· 301 295 <&cmu_mif CLK_SCLK_DECON_ECLK_DISP>, 302 296 <&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>, 303 297 <&cmu_mif CLK_ACLK_DISP_333>; 298 + power-domains = <&pd_disp>; 304 299 }; 305 300 306 301 cmu_aud: clock-controller@114c0000 { ··· 311 304 312 305 clock-names = "oscclk", "fout_aud_pll"; 313 306 clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>; 307 + power-domains = <&pd_aud>; 314 308 }; 315 309 316 310 cmu_bus0: clock-controller@13600000 { ··· 348 340 349 341 clock-names = "oscclk", "aclk_g3d_400"; 350 342 clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>; 343 + power-domains = <&pd_g3d>; 351 344 }; 352 345 353 346 cmu_gscl: clock-controller@13cf0000 { ··· 362 353 clocks = <&xxti>, 363 354 <&cmu_top CLK_ACLK_GSCL_111>, 364 355 <&cmu_top CLK_ACLK_GSCL_333>; 356 + power-domains = <&pd_gscl>; 365 357 }; 366 358 367 359 cmu_apollo: clock-controller@11900000 { ··· 394 384 clocks = <&xxti>, 395 385 <&cmu_top CLK_SCLK_JPEG_MSCL>, 396 386 <&cmu_top CLK_ACLK_MSCL_400>; 387 + power-domains = <&pd_mscl>; 397 388 }; 398 389 399 390 cmu_mfc: clock-controller@15280000 { ··· 404 393 405 394 clock-names = "oscclk", "aclk_mfc_400"; 406 395 clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>; 396 + power-domains = <&pd_mfc>; 407 397 }; 408 398 409 399 cmu_hevc: clock-controller@14f80000 { ··· 414 402 415 403 clock-names = "oscclk", "aclk_hevc_400"; 416 404 clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>; 405 + power-domains = <&pd_hevc>; 417 406 }; 418 407 419 408 cmu_isp: clock-controller@146d0000 { ··· 428 415 clocks = <&xxti>, 429 416 <&cmu_top CLK_ACLK_ISP_DIS_400>, 430 417 <&cmu_top CLK_ACLK_ISP_400>; 418 + power-domains = <&pd_isp>; 431 419 }; 432 420 433 421 cmu_cam0: clock-controller@120d0000 { ··· 444 430 <&cmu_top CLK_ACLK_CAM0_333>, 445 431 <&cmu_top CLK_ACLK_CAM0_400>, 446 432 <&cmu_top CLK_ACLK_CAM0_552>; 433 + power-domains = <&pd_cam0>; 447 434 }; 448 435 449 436 cmu_cam1: clock-controller@145d0000 { ··· 466 451 <&cmu_top CLK_ACLK_CAM1_333>, 467 452 <&cmu_top CLK_ACLK_CAM1_400>, 468 453 <&cmu_top CLK_ACLK_CAM1_552>; 454 + power-domains = <&pd_cam1>; 469 455 }; 470 456 471 457 Example 3: UART controller node that consumes the clock generated by the clock
+112 -14
drivers/clk/clk.c
··· 21 21 #include <linux/of.h> 22 22 #include <linux/device.h> 23 23 #include <linux/init.h> 24 + #include <linux/pm_runtime.h> 24 25 #include <linux/sched.h> 25 26 #include <linux/clkdev.h> 26 27 ··· 47 46 const struct clk_ops *ops; 48 47 struct clk_hw *hw; 49 48 struct module *owner; 49 + struct device *dev; 50 50 struct clk_core *parent; 51 51 const char **parent_names; 52 52 struct clk_core **parents; ··· 88 86 unsigned long max_rate; 89 87 struct hlist_node clks_node; 90 88 }; 89 + 90 + /*** runtime pm ***/ 91 + static int clk_pm_runtime_get(struct clk_core *core) 92 + { 93 + int ret = 0; 94 + 95 + if (!core->dev) 96 + return 0; 97 + 98 + ret = pm_runtime_get_sync(core->dev); 99 + return ret < 0 ? ret : 0; 100 + } 101 + 102 + static void clk_pm_runtime_put(struct clk_core *core) 103 + { 104 + if (!core->dev) 105 + return; 106 + 107 + pm_runtime_put_sync(core->dev); 108 + } 91 109 92 110 /*** locking ***/ 93 111 static void clk_prepare_lock(void) ··· 172 150 173 151 static bool clk_core_is_prepared(struct clk_core *core) 174 152 { 153 + bool ret = false; 154 + 175 155 /* 176 156 * .is_prepared is optional for clocks that can prepare 177 157 * fall back to software usage counter if it is missing ··· 181 157 if (!core->ops->is_prepared) 182 158 return core->prepare_count; 183 159 184 - return core->ops->is_prepared(core->hw); 160 + if (!clk_pm_runtime_get(core)) { 161 + ret = core->ops->is_prepared(core->hw); 162 + clk_pm_runtime_put(core); 163 + } 164 + 165 + return ret; 185 166 } 186 167 187 168 static bool clk_core_is_enabled(struct clk_core *core) 188 169 { 170 + bool ret = false; 171 + 189 172 /* 190 173 * .is_enabled is only mandatory for clocks that gate 191 174 * fall back to software usage counter if .is_enabled is missing ··· 200 169 if (!core->ops->is_enabled) 201 170 return core->enable_count; 202 171 203 - return core->ops->is_enabled(core->hw); 172 + /* 173 + * Check if clock controller's device is runtime active before 174 + * calling .is_enabled callback. If not, assume that clock is 175 + * disabled, because we might be called from atomic context, from 176 + * which pm_runtime_get() is not allowed. 177 + * This function is called mainly from clk_disable_unused_subtree, 178 + * which ensures proper runtime pm activation of controller before 179 + * taking enable spinlock, but the below check is needed if one tries 180 + * to call it from other places. 181 + */ 182 + if (core->dev) { 183 + pm_runtime_get_noresume(core->dev); 184 + if (!pm_runtime_active(core->dev)) { 185 + ret = false; 186 + goto done; 187 + } 188 + } 189 + 190 + ret = core->ops->is_enabled(core->hw); 191 + done: 192 + clk_pm_runtime_put(core); 193 + 194 + return ret; 204 195 } 205 196 206 197 /*** helper functions ***/ ··· 542 489 if (core->ops->unprepare) 543 490 core->ops->unprepare(core->hw); 544 491 492 + clk_pm_runtime_put(core); 493 + 545 494 trace_clk_unprepare_complete(core); 546 495 clk_core_unprepare(core->parent); 547 496 } ··· 585 530 return 0; 586 531 587 532 if (core->prepare_count == 0) { 588 - ret = clk_core_prepare(core->parent); 533 + ret = clk_pm_runtime_get(core); 589 534 if (ret) 590 535 return ret; 536 + 537 + ret = clk_core_prepare(core->parent); 538 + if (ret) 539 + goto runtime_put; 591 540 592 541 trace_clk_prepare(core); 593 542 ··· 600 541 601 542 trace_clk_prepare_complete(core); 602 543 603 - if (ret) { 604 - clk_core_unprepare(core->parent); 605 - return ret; 606 - } 544 + if (ret) 545 + goto unprepare; 607 546 } 608 547 609 548 core->prepare_count++; 610 549 611 550 return 0; 551 + unprepare: 552 + clk_core_unprepare(core->parent); 553 + runtime_put: 554 + clk_pm_runtime_put(core); 555 + return ret; 612 556 } 613 557 614 558 static int clk_core_prepare_lock(struct clk_core *core) ··· 807 745 if (core->flags & CLK_IGNORE_UNUSED) 808 746 return; 809 747 748 + if (clk_pm_runtime_get(core)) 749 + return; 750 + 810 751 if (clk_core_is_prepared(core)) { 811 752 trace_clk_unprepare(core); 812 753 if (core->ops->unprepare_unused) ··· 818 753 core->ops->unprepare(core->hw); 819 754 trace_clk_unprepare_complete(core); 820 755 } 756 + 757 + clk_pm_runtime_put(core); 821 758 } 822 759 823 760 static void clk_disable_unused_subtree(struct clk_core *core) ··· 834 767 835 768 if (core->flags & CLK_OPS_PARENT_ENABLE) 836 769 clk_core_prepare_enable(core->parent); 770 + 771 + if (clk_pm_runtime_get(core)) 772 + goto unprepare_out; 837 773 838 774 flags = clk_enable_lock(); 839 775 ··· 862 792 863 793 unlock_out: 864 794 clk_enable_unlock(flags); 795 + clk_pm_runtime_put(core); 796 + unprepare_out: 865 797 if (core->flags & CLK_OPS_PARENT_ENABLE) 866 798 clk_core_disable_unprepare(core->parent); 867 799 } ··· 1110 1038 static unsigned long clk_recalc(struct clk_core *core, 1111 1039 unsigned long parent_rate) 1112 1040 { 1113 - if (core->ops->recalc_rate) 1114 - return core->ops->recalc_rate(core->hw, parent_rate); 1115 - return parent_rate; 1041 + unsigned long rate = parent_rate; 1042 + 1043 + if (core->ops->recalc_rate && !clk_pm_runtime_get(core)) { 1044 + rate = core->ops->recalc_rate(core->hw, parent_rate); 1045 + clk_pm_runtime_put(core); 1046 + } 1047 + return rate; 1116 1048 } 1117 1049 1118 1050 /** ··· 1641 1565 { 1642 1566 struct clk_core *top, *fail_clk; 1643 1567 unsigned long rate = req_rate; 1568 + int ret = 0; 1644 1569 1645 1570 if (!core) 1646 1571 return 0; ··· 1658 1581 if (!top) 1659 1582 return -EINVAL; 1660 1583 1584 + ret = clk_pm_runtime_get(core); 1585 + if (ret) 1586 + return ret; 1587 + 1661 1588 /* notify that we are about to change rates */ 1662 1589 fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE); 1663 1590 if (fail_clk) { 1664 1591 pr_debug("%s: failed to set %s rate\n", __func__, 1665 1592 fail_clk->name); 1666 1593 clk_propagate_rate_change(top, ABORT_RATE_CHANGE); 1667 - return -EBUSY; 1594 + ret = -EBUSY; 1595 + goto err; 1668 1596 } 1669 1597 1670 1598 /* change the rates */ 1671 1599 clk_change_rate(top); 1672 1600 1673 1601 core->req_rate = req_rate; 1602 + err: 1603 + clk_pm_runtime_put(core); 1674 1604 1675 - return 0; 1605 + return ret; 1676 1606 } 1677 1607 1678 1608 /** ··· 1910 1826 p_rate = parent->rate; 1911 1827 } 1912 1828 1829 + ret = clk_pm_runtime_get(core); 1830 + if (ret) 1831 + goto out; 1832 + 1913 1833 /* propagate PRE_RATE_CHANGE notifications */ 1914 1834 ret = __clk_speculate_rates(core, p_rate); 1915 1835 1916 1836 /* abort if a driver objects */ 1917 1837 if (ret & NOTIFY_STOP_MASK) 1918 - goto out; 1838 + goto runtime_put; 1919 1839 1920 1840 /* do the re-parent */ 1921 1841 ret = __clk_set_parent(core, parent, p_index); ··· 1932 1844 __clk_recalc_accuracies(core); 1933 1845 } 1934 1846 1847 + runtime_put: 1848 + clk_pm_runtime_put(core); 1935 1849 out: 1936 1850 clk_prepare_unlock(); 1937 1851 ··· 2440 2350 */ 2441 2351 static int __clk_core_init(struct clk_core *core) 2442 2352 { 2443 - int i, ret = 0; 2353 + int i, ret; 2444 2354 struct clk_core *orphan; 2445 2355 struct hlist_node *tmp2; 2446 2356 unsigned long rate; ··· 2449 2359 return -EINVAL; 2450 2360 2451 2361 clk_prepare_lock(); 2362 + 2363 + ret = clk_pm_runtime_get(core); 2364 + if (ret) 2365 + goto unlock; 2452 2366 2453 2367 /* check to see if a clock with this name is already registered */ 2454 2368 if (clk_core_lookup(core->name)) { ··· 2606 2512 2607 2513 kref_init(&core->ref); 2608 2514 out: 2515 + clk_pm_runtime_put(core); 2516 + unlock: 2609 2517 clk_prepare_unlock(); 2610 2518 2611 2519 if (!ret) ··· 2679 2583 goto fail_name; 2680 2584 } 2681 2585 core->ops = hw->init->ops; 2586 + if (dev && pm_runtime_enabled(dev)) 2587 + core->dev = dev; 2682 2588 if (dev && dev->driver) 2683 2589 core->owner = dev->driver->owner; 2684 2590 core->hw = hw;
+47 -29
drivers/clk/samsung/clk-exynos-audss.c
··· 18 18 #include <linux/syscore_ops.h> 19 19 #include <linux/module.h> 20 20 #include <linux/platform_device.h> 21 + #include <linux/pm_runtime.h> 21 22 22 23 #include <dt-bindings/clock/exynos-audss-clk.h> 23 24 ··· 37 36 #define ASS_CLK_DIV 0x4 38 37 #define ASS_CLK_GATE 0x8 39 38 40 - #ifdef CONFIG_PM_SLEEP 41 39 static unsigned long reg_save[][2] = { 42 40 { ASS_CLK_SRC, 0 }, 43 41 { ASS_CLK_DIV, 0 }, 44 42 { ASS_CLK_GATE, 0 }, 45 43 }; 46 44 47 - static int exynos_audss_clk_suspend(struct device *dev) 45 + static int __maybe_unused exynos_audss_clk_suspend(struct device *dev) 48 46 { 49 47 int i; 50 48 ··· 53 53 return 0; 54 54 } 55 55 56 - static int exynos_audss_clk_resume(struct device *dev) 56 + static int __maybe_unused exynos_audss_clk_resume(struct device *dev) 57 57 { 58 58 int i; 59 59 ··· 62 62 63 63 return 0; 64 64 } 65 - #endif /* CONFIG_PM_SLEEP */ 66 65 67 66 struct exynos_audss_clk_drvdata { 68 67 unsigned int has_adma_clk:1; ··· 134 135 const struct exynos_audss_clk_drvdata *variant; 135 136 struct clk_hw **clk_table; 136 137 struct resource *res; 138 + struct device *dev = &pdev->dev; 137 139 int i, ret = 0; 138 140 139 141 variant = of_device_get_match_data(&pdev->dev); ··· 142 142 return -EINVAL; 143 143 144 144 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 145 - reg_base = devm_ioremap_resource(&pdev->dev, res); 145 + reg_base = devm_ioremap_resource(dev, res); 146 146 if (IS_ERR(reg_base)) { 147 - dev_err(&pdev->dev, "failed to map audss registers\n"); 147 + dev_err(dev, "failed to map audss registers\n"); 148 148 return PTR_ERR(reg_base); 149 149 } 150 150 151 151 epll = ERR_PTR(-ENODEV); 152 152 153 - clk_data = devm_kzalloc(&pdev->dev, 153 + clk_data = devm_kzalloc(dev, 154 154 sizeof(*clk_data) + 155 155 sizeof(*clk_data->hws) * EXYNOS_AUDSS_MAX_CLKS, 156 156 GFP_KERNEL); ··· 160 160 clk_data->num = variant->num_clks; 161 161 clk_table = clk_data->hws; 162 162 163 - pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); 164 - pll_in = devm_clk_get(&pdev->dev, "pll_in"); 163 + pll_ref = devm_clk_get(dev, "pll_ref"); 164 + pll_in = devm_clk_get(dev, "pll_in"); 165 165 if (!IS_ERR(pll_ref)) 166 166 mout_audss_p[0] = __clk_get_name(pll_ref); 167 167 if (!IS_ERR(pll_in)) { ··· 172 172 173 173 ret = clk_prepare_enable(epll); 174 174 if (ret) { 175 - dev_err(&pdev->dev, 175 + dev_err(dev, 176 176 "failed to prepare the epll clock\n"); 177 177 return ret; 178 178 } 179 179 } 180 180 } 181 - clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss", 181 + 182 + /* 183 + * Enable runtime PM here to allow the clock core using runtime PM 184 + * for the registered clocks. Additionally, we increase the runtime 185 + * PM usage count before registering the clocks, to prevent the 186 + * clock core from runtime suspending the device. 187 + */ 188 + pm_runtime_get_noresume(dev); 189 + pm_runtime_set_active(dev); 190 + pm_runtime_enable(dev); 191 + 192 + clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(dev, "mout_audss", 182 193 mout_audss_p, ARRAY_SIZE(mout_audss_p), 183 194 CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, 184 195 reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); 185 196 186 - cdclk = devm_clk_get(&pdev->dev, "cdclk"); 187 - sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio"); 197 + cdclk = devm_clk_get(dev, "cdclk"); 198 + sclk_audio = devm_clk_get(dev, "sclk_audio"); 188 199 if (!IS_ERR(cdclk)) 189 200 mout_i2s_p[1] = __clk_get_name(cdclk); 190 201 if (!IS_ERR(sclk_audio)) 191 202 mout_i2s_p[2] = __clk_get_name(sclk_audio); 192 - clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(NULL, "mout_i2s", 203 + clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(dev, "mout_i2s", 193 204 mout_i2s_p, ARRAY_SIZE(mout_i2s_p), 194 205 CLK_SET_RATE_NO_REPARENT, 195 206 reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); 196 207 197 - clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp", 208 + clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(dev, "dout_srp", 198 209 "mout_audss", CLK_SET_RATE_PARENT, 199 210 reg_base + ASS_CLK_DIV, 0, 4, 0, &lock); 200 211 201 - clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL, 212 + clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(dev, 202 213 "dout_aud_bus", "dout_srp", CLK_SET_RATE_PARENT, 203 214 reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); 204 215 205 - clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s", 216 + clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(dev, "dout_i2s", 206 217 "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0, 207 218 &lock); 208 219 209 - clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(NULL, "srp_clk", 220 + clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(dev, "srp_clk", 210 221 "dout_srp", CLK_SET_RATE_PARENT, 211 222 reg_base + ASS_CLK_GATE, 0, 0, &lock); 212 223 213 - clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(NULL, "i2s_bus", 224 + clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(dev, "i2s_bus", 214 225 "dout_aud_bus", CLK_SET_RATE_PARENT, 215 226 reg_base + ASS_CLK_GATE, 2, 0, &lock); 216 227 217 - clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(NULL, "sclk_i2s", 228 + clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(dev, "sclk_i2s", 218 229 "dout_i2s", CLK_SET_RATE_PARENT, 219 230 reg_base + ASS_CLK_GATE, 3, 0, &lock); 220 231 221 - clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(NULL, "pcm_bus", 232 + clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(dev, "pcm_bus", 222 233 "sclk_pcm", CLK_SET_RATE_PARENT, 223 234 reg_base + ASS_CLK_GATE, 4, 0, &lock); 224 235 225 - sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in"); 236 + sclk_pcm_in = devm_clk_get(dev, "sclk_pcm_in"); 226 237 if (!IS_ERR(sclk_pcm_in)) 227 238 sclk_pcm_p = __clk_get_name(sclk_pcm_in); 228 - clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm", 239 + clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(dev, "sclk_pcm", 229 240 sclk_pcm_p, CLK_SET_RATE_PARENT, 230 241 reg_base + ASS_CLK_GATE, 5, 0, &lock); 231 242 232 243 if (variant->has_adma_clk) { 233 - clk_table[EXYNOS_ADMA] = clk_hw_register_gate(NULL, "adma", 244 + clk_table[EXYNOS_ADMA] = clk_hw_register_gate(dev, "adma", 234 245 "dout_srp", CLK_SET_RATE_PARENT, 235 246 reg_base + ASS_CLK_GATE, 9, 0, &lock); 236 247 } 237 248 238 249 for (i = 0; i < clk_data->num; i++) { 239 250 if (IS_ERR(clk_table[i])) { 240 - dev_err(&pdev->dev, "failed to register clock %d\n", i); 251 + dev_err(dev, "failed to register clock %d\n", i); 241 252 ret = PTR_ERR(clk_table[i]); 242 253 goto unregister; 243 254 } 244 255 } 245 256 246 - ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get, 257 + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, 247 258 clk_data); 248 259 if (ret) { 249 - dev_err(&pdev->dev, "failed to add clock provider\n"); 260 + dev_err(dev, "failed to add clock provider\n"); 250 261 goto unregister; 251 262 } 263 + 264 + pm_runtime_put_sync(dev); 252 265 253 266 return 0; 254 267 255 268 unregister: 256 269 exynos_audss_clk_teardown(); 270 + pm_runtime_put_sync(dev); 271 + pm_runtime_disable(dev); 257 272 258 273 if (!IS_ERR(epll)) 259 274 clk_disable_unprepare(epll); ··· 281 266 of_clk_del_provider(pdev->dev.of_node); 282 267 283 268 exynos_audss_clk_teardown(); 269 + pm_runtime_disable(&pdev->dev); 284 270 285 271 if (!IS_ERR(epll)) 286 272 clk_disable_unprepare(epll); ··· 290 274 } 291 275 292 276 static const struct dev_pm_ops exynos_audss_clk_pm_ops = { 293 - SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_audss_clk_suspend, 294 - exynos_audss_clk_resume) 277 + SET_RUNTIME_PM_OPS(exynos_audss_clk_suspend, exynos_audss_clk_resume, 278 + NULL) 279 + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 280 + pm_runtime_force_resume) 295 281 }; 296 282 297 283 static struct platform_driver exynos_audss_clk_driver = {
+324 -85
drivers/clk/samsung/clk-exynos5433.c
··· 9 9 * Common Clock Framework support for Exynos5433 SoC. 10 10 */ 11 11 12 + #include <linux/clk.h> 12 13 #include <linux/clk-provider.h> 13 14 #include <linux/of.h> 14 15 #include <linux/of_address.h> 16 + #include <linux/of_device.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/pm_runtime.h> 15 19 16 20 #include <dt-bindings/clock/exynos5433.h> 17 21 ··· 1995 1991 ENABLE_IP_FSYS1, 1996 1992 }; 1997 1993 1994 + static const struct samsung_clk_reg_dump fsys_suspend_regs[] = { 1995 + { MUX_SEL_FSYS0, 0 }, 1996 + { MUX_SEL_FSYS1, 0 }, 1997 + { MUX_SEL_FSYS2, 0 }, 1998 + { MUX_SEL_FSYS3, 0 }, 1999 + { MUX_SEL_FSYS4, 0 }, 2000 + }; 2001 + 1998 2002 static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = { 1999 2003 /* PHY clocks from USBDRD30_PHY */ 2000 2004 FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY, ··· 2308 2296 .nr_clk_ids = FSYS_NR_CLK, 2309 2297 .clk_regs = fsys_clk_regs, 2310 2298 .nr_clk_regs = ARRAY_SIZE(fsys_clk_regs), 2299 + .suspend_regs = fsys_suspend_regs, 2300 + .nr_suspend_regs = ARRAY_SIZE(fsys_suspend_regs), 2301 + .clk_name = "aclk_fsys_200", 2311 2302 }; 2312 - 2313 - static void __init exynos5433_cmu_fsys_init(struct device_node *np) 2314 - { 2315 - samsung_cmu_register_one(np, &fsys_cmu_info); 2316 - } 2317 - 2318 - CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys", 2319 - exynos5433_cmu_fsys_init); 2320 2303 2321 2304 /* 2322 2305 * Register offset definitions for CMU_G2D ··· 2340 2333 DIV_ENABLE_IP_G2D0, 2341 2334 DIV_ENABLE_IP_G2D1, 2342 2335 DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D, 2336 + }; 2337 + 2338 + static const struct samsung_clk_reg_dump g2d_suspend_regs[] = { 2339 + { MUX_SEL_G2D0, 0 }, 2343 2340 }; 2344 2341 2345 2342 /* list of all parent clock list */ ··· 2431 2420 .nr_clk_ids = G2D_NR_CLK, 2432 2421 .clk_regs = g2d_clk_regs, 2433 2422 .nr_clk_regs = ARRAY_SIZE(g2d_clk_regs), 2423 + .suspend_regs = g2d_suspend_regs, 2424 + .nr_suspend_regs = ARRAY_SIZE(g2d_suspend_regs), 2425 + .clk_name = "aclk_g2d_400", 2434 2426 }; 2435 - 2436 - static void __init exynos5433_cmu_g2d_init(struct device_node *np) 2437 - { 2438 - samsung_cmu_register_one(np, &g2d_cmu_info); 2439 - } 2440 - 2441 - CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d", 2442 - exynos5433_cmu_g2d_init); 2443 2427 2444 2428 /* 2445 2429 * Register offset definitions for CMU_DISP ··· 2498 2492 ENABLE_IP_DISP1, 2499 2493 CLKOUT_CMU_DISP, 2500 2494 CLKOUT_CMU_DISP_DIV_STAT, 2495 + }; 2496 + 2497 + static const struct samsung_clk_reg_dump disp_suspend_regs[] = { 2498 + /* PLL has to be enabled for suspend */ 2499 + { DISP_PLL_CON0, 0x85f40502 }, 2500 + /* ignore status of external PHY muxes during suspend to avoid hangs */ 2501 + { MUX_IGNORE_DISP2, 0x00111111 }, 2502 + { MUX_SEL_DISP0, 0 }, 2503 + { MUX_SEL_DISP1, 0 }, 2504 + { MUX_SEL_DISP2, 0 }, 2505 + { MUX_SEL_DISP3, 0 }, 2506 + { MUX_SEL_DISP4, 0 }, 2501 2507 }; 2502 2508 2503 2509 /* list of all parent clock list */ ··· 2859 2841 .nr_clk_ids = DISP_NR_CLK, 2860 2842 .clk_regs = disp_clk_regs, 2861 2843 .nr_clk_regs = ARRAY_SIZE(disp_clk_regs), 2844 + .suspend_regs = disp_suspend_regs, 2845 + .nr_suspend_regs = ARRAY_SIZE(disp_suspend_regs), 2846 + .clk_name = "aclk_disp_333", 2862 2847 }; 2863 - 2864 - static void __init exynos5433_cmu_disp_init(struct device_node *np) 2865 - { 2866 - samsung_cmu_register_one(np, &disp_cmu_info); 2867 - } 2868 - 2869 - CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp", 2870 - exynos5433_cmu_disp_init); 2871 2848 2872 2849 /* 2873 2850 * Register offset definitions for CMU_AUD ··· 2896 2883 ENABLE_SCLK_AUD1, 2897 2884 ENABLE_IP_AUD0, 2898 2885 ENABLE_IP_AUD1, 2886 + }; 2887 + 2888 + static const struct samsung_clk_reg_dump aud_suspend_regs[] = { 2889 + { MUX_SEL_AUD0, 0 }, 2890 + { MUX_SEL_AUD1, 0 }, 2899 2891 }; 2900 2892 2901 2893 /* list of all parent clock list */ ··· 3029 3011 .nr_clk_ids = AUD_NR_CLK, 3030 3012 .clk_regs = aud_clk_regs, 3031 3013 .nr_clk_regs = ARRAY_SIZE(aud_clk_regs), 3014 + .suspend_regs = aud_suspend_regs, 3015 + .nr_suspend_regs = ARRAY_SIZE(aud_suspend_regs), 3016 + .clk_name = "fout_aud_pll", 3032 3017 }; 3033 - 3034 - static void __init exynos5433_cmu_aud_init(struct device_node *np) 3035 - { 3036 - samsung_cmu_register_one(np, &aud_cmu_info); 3037 - } 3038 - CLK_OF_DECLARE(exynos5433_cmu_aud, "samsung,exynos5433-cmu-aud", 3039 - exynos5433_cmu_aud_init); 3040 - 3041 3018 3042 3019 /* 3043 3020 * Register offset definitions for CMU_BUS{0|1|2} ··· 3235 3222 CLK_STOPCTRL, 3236 3223 }; 3237 3224 3225 + static const struct samsung_clk_reg_dump g3d_suspend_regs[] = { 3226 + { MUX_SEL_G3D, 0 }, 3227 + }; 3228 + 3238 3229 /* list of all parent clock list */ 3239 3230 PNAME(mout_aclk_g3d_400_p) = { "mout_g3d_pll", "aclk_g3d_400", }; 3240 3231 PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll", }; ··· 3312 3295 .nr_clk_ids = G3D_NR_CLK, 3313 3296 .clk_regs = g3d_clk_regs, 3314 3297 .nr_clk_regs = ARRAY_SIZE(g3d_clk_regs), 3298 + .suspend_regs = g3d_suspend_regs, 3299 + .nr_suspend_regs = ARRAY_SIZE(g3d_suspend_regs), 3300 + .clk_name = "aclk_g3d_400", 3315 3301 }; 3316 - 3317 - static void __init exynos5433_cmu_g3d_init(struct device_node *np) 3318 - { 3319 - samsung_cmu_register_one(np, &g3d_cmu_info); 3320 - } 3321 - CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d", 3322 - exynos5433_cmu_g3d_init); 3323 3302 3324 3303 /* 3325 3304 * Register offset definitions for CMU_GSCL ··· 3353 3340 ENABLE_IP_GSCL_SECURE_SMMU_GSCL0, 3354 3341 ENABLE_IP_GSCL_SECURE_SMMU_GSCL1, 3355 3342 ENABLE_IP_GSCL_SECURE_SMMU_GSCL2, 3343 + }; 3344 + 3345 + static const struct samsung_clk_reg_dump gscl_suspend_regs[] = { 3346 + { MUX_SEL_GSCL, 0 }, 3347 + { ENABLE_ACLK_GSCL, 0xfff }, 3348 + { ENABLE_PCLK_GSCL, 0xff }, 3356 3349 }; 3357 3350 3358 3351 /* list of all parent clock list */ ··· 3455 3436 .nr_clk_ids = GSCL_NR_CLK, 3456 3437 .clk_regs = gscl_clk_regs, 3457 3438 .nr_clk_regs = ARRAY_SIZE(gscl_clk_regs), 3439 + .suspend_regs = gscl_suspend_regs, 3440 + .nr_suspend_regs = ARRAY_SIZE(gscl_suspend_regs), 3441 + .clk_name = "aclk_gscl_111", 3458 3442 }; 3459 - 3460 - static void __init exynos5433_cmu_gscl_init(struct device_node *np) 3461 - { 3462 - samsung_cmu_register_one(np, &gscl_cmu_info); 3463 - } 3464 - CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl", 3465 - exynos5433_cmu_gscl_init); 3466 3443 3467 3444 /* 3468 3445 * Register offset definitions for CMU_APOLLO ··· 3985 3970 ENABLE_IP_MSCL_SECURE_SMMU_JPEG, 3986 3971 }; 3987 3972 3973 + static const struct samsung_clk_reg_dump mscl_suspend_regs[] = { 3974 + { MUX_SEL_MSCL0, 0 }, 3975 + { MUX_SEL_MSCL1, 0 }, 3976 + }; 3977 + 3988 3978 /* list of all parent clock list */ 3989 3979 PNAME(mout_sclk_jpeg_user_p) = { "oscclk", "sclk_jpeg_mscl", }; 3990 3980 PNAME(mout_aclk_mscl_400_user_p) = { "oscclk", "aclk_mscl_400", }; ··· 4102 4082 .nr_clk_ids = MSCL_NR_CLK, 4103 4083 .clk_regs = mscl_clk_regs, 4104 4084 .nr_clk_regs = ARRAY_SIZE(mscl_clk_regs), 4085 + .suspend_regs = mscl_suspend_regs, 4086 + .nr_suspend_regs = ARRAY_SIZE(mscl_suspend_regs), 4087 + .clk_name = "aclk_mscl_400", 4105 4088 }; 4106 - 4107 - static void __init exynos5433_cmu_mscl_init(struct device_node *np) 4108 - { 4109 - samsung_cmu_register_one(np, &mscl_cmu_info); 4110 - } 4111 - CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl", 4112 - exynos5433_cmu_mscl_init); 4113 4089 4114 4090 /* 4115 4091 * Register offset definitions for CMU_MFC ··· 4134 4118 ENABLE_IP_MFC0, 4135 4119 ENABLE_IP_MFC1, 4136 4120 ENABLE_IP_MFC_SECURE_SMMU_MFC, 4121 + }; 4122 + 4123 + static const struct samsung_clk_reg_dump mfc_suspend_regs[] = { 4124 + { MUX_SEL_MFC, 0 }, 4137 4125 }; 4138 4126 4139 4127 PNAME(mout_aclk_mfc_400_user_p) = { "oscclk", "aclk_mfc_400", }; ··· 4210 4190 .nr_clk_ids = MFC_NR_CLK, 4211 4191 .clk_regs = mfc_clk_regs, 4212 4192 .nr_clk_regs = ARRAY_SIZE(mfc_clk_regs), 4193 + .suspend_regs = mfc_suspend_regs, 4194 + .nr_suspend_regs = ARRAY_SIZE(mfc_suspend_regs), 4195 + .clk_name = "aclk_mfc_400", 4213 4196 }; 4214 - 4215 - static void __init exynos5433_cmu_mfc_init(struct device_node *np) 4216 - { 4217 - samsung_cmu_register_one(np, &mfc_cmu_info); 4218 - } 4219 - CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc", 4220 - exynos5433_cmu_mfc_init); 4221 4197 4222 4198 /* 4223 4199 * Register offset definitions for CMU_HEVC ··· 4242 4226 ENABLE_IP_HEVC0, 4243 4227 ENABLE_IP_HEVC1, 4244 4228 ENABLE_IP_HEVC_SECURE_SMMU_HEVC, 4229 + }; 4230 + 4231 + static const struct samsung_clk_reg_dump hevc_suspend_regs[] = { 4232 + { MUX_SEL_HEVC, 0 }, 4245 4233 }; 4246 4234 4247 4235 PNAME(mout_aclk_hevc_400_user_p) = { "oscclk", "aclk_hevc_400", }; ··· 4320 4300 .nr_clk_ids = HEVC_NR_CLK, 4321 4301 .clk_regs = hevc_clk_regs, 4322 4302 .nr_clk_regs = ARRAY_SIZE(hevc_clk_regs), 4303 + .suspend_regs = hevc_suspend_regs, 4304 + .nr_suspend_regs = ARRAY_SIZE(hevc_suspend_regs), 4305 + .clk_name = "aclk_hevc_400", 4323 4306 }; 4324 - 4325 - static void __init exynos5433_cmu_hevc_init(struct device_node *np) 4326 - { 4327 - samsung_cmu_register_one(np, &hevc_cmu_info); 4328 - } 4329 - CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc", 4330 - exynos5433_cmu_hevc_init); 4331 4307 4332 4308 /* 4333 4309 * Register offset definitions for CMU_ISP ··· 4356 4340 ENABLE_IP_ISP1, 4357 4341 ENABLE_IP_ISP2, 4358 4342 ENABLE_IP_ISP3, 4343 + }; 4344 + 4345 + static const struct samsung_clk_reg_dump isp_suspend_regs[] = { 4346 + { MUX_SEL_ISP, 0 }, 4359 4347 }; 4360 4348 4361 4349 PNAME(mout_aclk_isp_dis_400_user_p) = { "oscclk", "aclk_isp_dis_400", }; ··· 4573 4553 .nr_clk_ids = ISP_NR_CLK, 4574 4554 .clk_regs = isp_clk_regs, 4575 4555 .nr_clk_regs = ARRAY_SIZE(isp_clk_regs), 4556 + .suspend_regs = isp_suspend_regs, 4557 + .nr_suspend_regs = ARRAY_SIZE(isp_suspend_regs), 4558 + .clk_name = "aclk_isp_400", 4576 4559 }; 4577 - 4578 - static void __init exynos5433_cmu_isp_init(struct device_node *np) 4579 - { 4580 - samsung_cmu_register_one(np, &isp_cmu_info); 4581 - } 4582 - CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp", 4583 - exynos5433_cmu_isp_init); 4584 4560 4585 4561 /* 4586 4562 * Register offset definitions for CMU_CAM0 ··· 4641 4625 ENABLE_IP_CAM02, 4642 4626 ENABLE_IP_CAM03, 4643 4627 }; 4628 + 4629 + static const struct samsung_clk_reg_dump cam0_suspend_regs[] = { 4630 + { MUX_SEL_CAM00, 0 }, 4631 + { MUX_SEL_CAM01, 0 }, 4632 + { MUX_SEL_CAM02, 0 }, 4633 + { MUX_SEL_CAM03, 0 }, 4634 + { MUX_SEL_CAM04, 0 }, 4635 + }; 4636 + 4644 4637 PNAME(mout_aclk_cam0_333_user_p) = { "oscclk", "aclk_cam0_333", }; 4645 4638 PNAME(mout_aclk_cam0_400_user_p) = { "oscclk", "aclk_cam0_400", }; 4646 4639 PNAME(mout_aclk_cam0_552_user_p) = { "oscclk", "aclk_cam0_552", }; ··· 5055 5030 .nr_clk_ids = CAM0_NR_CLK, 5056 5031 .clk_regs = cam0_clk_regs, 5057 5032 .nr_clk_regs = ARRAY_SIZE(cam0_clk_regs), 5033 + .suspend_regs = cam0_suspend_regs, 5034 + .nr_suspend_regs = ARRAY_SIZE(cam0_suspend_regs), 5035 + .clk_name = "aclk_cam0_400", 5058 5036 }; 5059 - 5060 - static void __init exynos5433_cmu_cam0_init(struct device_node *np) 5061 - { 5062 - samsung_cmu_register_one(np, &cam0_cmu_info); 5063 - } 5064 - CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0", 5065 - exynos5433_cmu_cam0_init); 5066 5037 5067 5038 /* 5068 5039 * Register offset definitions for CMU_CAM1 ··· 5104 5083 ENABLE_IP_CAM10, 5105 5084 ENABLE_IP_CAM11, 5106 5085 ENABLE_IP_CAM12, 5086 + }; 5087 + 5088 + static const struct samsung_clk_reg_dump cam1_suspend_regs[] = { 5089 + { MUX_SEL_CAM10, 0 }, 5090 + { MUX_SEL_CAM11, 0 }, 5091 + { MUX_SEL_CAM12, 0 }, 5107 5092 }; 5108 5093 5109 5094 PNAME(mout_sclk_isp_uart_user_p) = { "oscclk", "sclk_isp_uart_cam1", }; ··· 5430 5403 .nr_clk_ids = CAM1_NR_CLK, 5431 5404 .clk_regs = cam1_clk_regs, 5432 5405 .nr_clk_regs = ARRAY_SIZE(cam1_clk_regs), 5406 + .suspend_regs = cam1_suspend_regs, 5407 + .nr_suspend_regs = ARRAY_SIZE(cam1_suspend_regs), 5408 + .clk_name = "aclk_cam1_400", 5433 5409 }; 5434 5410 5435 - static void __init exynos5433_cmu_cam1_init(struct device_node *np) 5411 + 5412 + struct exynos5433_cmu_data { 5413 + struct samsung_clk_reg_dump *clk_save; 5414 + unsigned int nr_clk_save; 5415 + const struct samsung_clk_reg_dump *clk_suspend; 5416 + unsigned int nr_clk_suspend; 5417 + 5418 + struct clk *clk; 5419 + struct clk **pclks; 5420 + int nr_pclks; 5421 + 5422 + /* must be the last entry */ 5423 + struct samsung_clk_provider ctx; 5424 + }; 5425 + 5426 + static int exynos5433_cmu_suspend(struct device *dev) 5436 5427 { 5437 - samsung_cmu_register_one(np, &cam1_cmu_info); 5428 + struct exynos5433_cmu_data *data = dev_get_drvdata(dev); 5429 + int i; 5430 + 5431 + samsung_clk_save(data->ctx.reg_base, data->clk_save, 5432 + data->nr_clk_save); 5433 + 5434 + for (i = 0; i < data->nr_pclks; i++) 5435 + clk_prepare_enable(data->pclks[i]); 5436 + 5437 + /* for suspend some registers have to be set to certain values */ 5438 + samsung_clk_restore(data->ctx.reg_base, data->clk_suspend, 5439 + data->nr_clk_suspend); 5440 + 5441 + for (i = 0; i < data->nr_pclks; i++) 5442 + clk_disable_unprepare(data->pclks[i]); 5443 + 5444 + clk_disable_unprepare(data->clk); 5445 + 5446 + return 0; 5438 5447 } 5439 - CLK_OF_DECLARE(exynos5433_cmu_cam1, "samsung,exynos5433-cmu-cam1", 5440 - exynos5433_cmu_cam1_init); 5448 + 5449 + static int exynos5433_cmu_resume(struct device *dev) 5450 + { 5451 + struct exynos5433_cmu_data *data = dev_get_drvdata(dev); 5452 + int i; 5453 + 5454 + clk_prepare_enable(data->clk); 5455 + 5456 + for (i = 0; i < data->nr_pclks; i++) 5457 + clk_prepare_enable(data->pclks[i]); 5458 + 5459 + samsung_clk_restore(data->ctx.reg_base, data->clk_save, 5460 + data->nr_clk_save); 5461 + 5462 + for (i = 0; i < data->nr_pclks; i++) 5463 + clk_disable_unprepare(data->pclks[i]); 5464 + 5465 + return 0; 5466 + } 5467 + 5468 + static int __init exynos5433_cmu_probe(struct platform_device *pdev) 5469 + { 5470 + const struct samsung_cmu_info *info; 5471 + struct exynos5433_cmu_data *data; 5472 + struct samsung_clk_provider *ctx; 5473 + struct device *dev = &pdev->dev; 5474 + struct resource *res; 5475 + void __iomem *reg_base; 5476 + int i; 5477 + 5478 + info = of_device_get_match_data(dev); 5479 + 5480 + data = devm_kzalloc(dev, sizeof(*data) + 5481 + sizeof(*data->ctx.clk_data.hws) * info->nr_clk_ids, 5482 + GFP_KERNEL); 5483 + if (!data) 5484 + return -ENOMEM; 5485 + ctx = &data->ctx; 5486 + 5487 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 5488 + reg_base = devm_ioremap_resource(dev, res); 5489 + if (IS_ERR(reg_base)) { 5490 + dev_err(dev, "failed to map registers\n"); 5491 + return PTR_ERR(reg_base); 5492 + } 5493 + 5494 + for (i = 0; i < info->nr_clk_ids; ++i) 5495 + ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); 5496 + 5497 + ctx->clk_data.num = info->nr_clk_ids; 5498 + ctx->reg_base = reg_base; 5499 + ctx->dev = dev; 5500 + spin_lock_init(&ctx->lock); 5501 + 5502 + data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs, 5503 + info->nr_clk_regs); 5504 + data->nr_clk_save = info->nr_clk_regs; 5505 + data->clk_suspend = info->suspend_regs; 5506 + data->nr_clk_suspend = info->nr_suspend_regs; 5507 + data->nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks", 5508 + "#clock-cells"); 5509 + if (data->nr_pclks > 0) { 5510 + data->pclks = devm_kcalloc(dev, sizeof(struct clk *), 5511 + data->nr_pclks, GFP_KERNEL); 5512 + 5513 + for (i = 0; i < data->nr_pclks; i++) { 5514 + struct clk *clk = of_clk_get(dev->of_node, i); 5515 + 5516 + if (IS_ERR(clk)) 5517 + return PTR_ERR(clk); 5518 + data->pclks[i] = clk; 5519 + } 5520 + } 5521 + 5522 + if (info->clk_name) 5523 + data->clk = clk_get(dev, info->clk_name); 5524 + clk_prepare_enable(data->clk); 5525 + 5526 + platform_set_drvdata(pdev, data); 5527 + 5528 + /* 5529 + * Enable runtime PM here to allow the clock core using runtime PM 5530 + * for the registered clocks. Additionally, we increase the runtime 5531 + * PM usage count before registering the clocks, to prevent the 5532 + * clock core from runtime suspending the device. 5533 + */ 5534 + pm_runtime_get_noresume(dev); 5535 + pm_runtime_set_active(dev); 5536 + pm_runtime_enable(dev); 5537 + 5538 + if (info->pll_clks) 5539 + samsung_clk_register_pll(ctx, info->pll_clks, info->nr_pll_clks, 5540 + reg_base); 5541 + if (info->mux_clks) 5542 + samsung_clk_register_mux(ctx, info->mux_clks, 5543 + info->nr_mux_clks); 5544 + if (info->div_clks) 5545 + samsung_clk_register_div(ctx, info->div_clks, 5546 + info->nr_div_clks); 5547 + if (info->gate_clks) 5548 + samsung_clk_register_gate(ctx, info->gate_clks, 5549 + info->nr_gate_clks); 5550 + if (info->fixed_clks) 5551 + samsung_clk_register_fixed_rate(ctx, info->fixed_clks, 5552 + info->nr_fixed_clks); 5553 + if (info->fixed_factor_clks) 5554 + samsung_clk_register_fixed_factor(ctx, info->fixed_factor_clks, 5555 + info->nr_fixed_factor_clks); 5556 + 5557 + samsung_clk_of_add_provider(dev->of_node, ctx); 5558 + pm_runtime_put_sync(dev); 5559 + 5560 + return 0; 5561 + } 5562 + 5563 + static const struct of_device_id exynos5433_cmu_of_match[] = { 5564 + { 5565 + .compatible = "samsung,exynos5433-cmu-aud", 5566 + .data = &aud_cmu_info, 5567 + }, { 5568 + .compatible = "samsung,exynos5433-cmu-cam0", 5569 + .data = &cam0_cmu_info, 5570 + }, { 5571 + .compatible = "samsung,exynos5433-cmu-cam1", 5572 + .data = &cam1_cmu_info, 5573 + }, { 5574 + .compatible = "samsung,exynos5433-cmu-disp", 5575 + .data = &disp_cmu_info, 5576 + }, { 5577 + .compatible = "samsung,exynos5433-cmu-g2d", 5578 + .data = &g2d_cmu_info, 5579 + }, { 5580 + .compatible = "samsung,exynos5433-cmu-g3d", 5581 + .data = &g3d_cmu_info, 5582 + }, { 5583 + .compatible = "samsung,exynos5433-cmu-fsys", 5584 + .data = &fsys_cmu_info, 5585 + }, { 5586 + .compatible = "samsung,exynos5433-cmu-gscl", 5587 + .data = &gscl_cmu_info, 5588 + }, { 5589 + .compatible = "samsung,exynos5433-cmu-mfc", 5590 + .data = &mfc_cmu_info, 5591 + }, { 5592 + .compatible = "samsung,exynos5433-cmu-hevc", 5593 + .data = &hevc_cmu_info, 5594 + }, { 5595 + .compatible = "samsung,exynos5433-cmu-isp", 5596 + .data = &isp_cmu_info, 5597 + }, { 5598 + .compatible = "samsung,exynos5433-cmu-mscl", 5599 + .data = &mscl_cmu_info, 5600 + }, { 5601 + }, 5602 + }; 5603 + 5604 + static const struct dev_pm_ops exynos5433_cmu_pm_ops = { 5605 + SET_RUNTIME_PM_OPS(exynos5433_cmu_suspend, exynos5433_cmu_resume, 5606 + NULL) 5607 + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 5608 + pm_runtime_force_resume) 5609 + }; 5610 + 5611 + static struct platform_driver exynos5433_cmu_driver __refdata = { 5612 + .driver = { 5613 + .name = "exynos5433-cmu", 5614 + .of_match_table = exynos5433_cmu_of_match, 5615 + .suppress_bind_attrs = true, 5616 + .pm = &exynos5433_cmu_pm_ops, 5617 + }, 5618 + .probe = exynos5433_cmu_probe, 5619 + }; 5620 + 5621 + static int __init exynos5433_cmu_init(void) 5622 + { 5623 + return platform_driver_register(&exynos5433_cmu_driver); 5624 + } 5625 + core_initcall(exynos5433_cmu_init);
+1 -1
drivers/clk/samsung/clk-pll.c
··· 1388 1388 pll->lock_reg = base + pll_clk->lock_offset; 1389 1389 pll->con_reg = base + pll_clk->con_offset; 1390 1390 1391 - ret = clk_hw_register(NULL, &pll->hw); 1391 + ret = clk_hw_register(ctx->dev, &pll->hw); 1392 1392 if (ret) { 1393 1393 pr_err("%s: failed to register pll clock %s : %d\n", 1394 1394 __func__, pll_clk->name, ret);
+6 -6
drivers/clk/samsung/clk.c
··· 134 134 unsigned int idx, ret; 135 135 136 136 for (idx = 0; idx < nr_clk; idx++, list++) { 137 - clk_hw = clk_hw_register_fixed_rate(NULL, list->name, 137 + clk_hw = clk_hw_register_fixed_rate(ctx->dev, list->name, 138 138 list->parent_name, list->flags, list->fixed_rate); 139 139 if (IS_ERR(clk_hw)) { 140 140 pr_err("%s: failed to register clock %s\n", __func__, ··· 163 163 unsigned int idx; 164 164 165 165 for (idx = 0; idx < nr_clk; idx++, list++) { 166 - clk_hw = clk_hw_register_fixed_factor(NULL, list->name, 166 + clk_hw = clk_hw_register_fixed_factor(ctx->dev, list->name, 167 167 list->parent_name, list->flags, list->mult, list->div); 168 168 if (IS_ERR(clk_hw)) { 169 169 pr_err("%s: failed to register clock %s\n", __func__, ··· 184 184 unsigned int idx, ret; 185 185 186 186 for (idx = 0; idx < nr_clk; idx++, list++) { 187 - clk_hw = clk_hw_register_mux(NULL, list->name, 187 + clk_hw = clk_hw_register_mux(ctx->dev, list->name, 188 188 list->parent_names, list->num_parents, list->flags, 189 189 ctx->reg_base + list->offset, 190 190 list->shift, list->width, list->mux_flags, &ctx->lock); ··· 217 217 218 218 for (idx = 0; idx < nr_clk; idx++, list++) { 219 219 if (list->table) 220 - clk_hw = clk_hw_register_divider_table(NULL, 220 + clk_hw = clk_hw_register_divider_table(ctx->dev, 221 221 list->name, list->parent_name, list->flags, 222 222 ctx->reg_base + list->offset, 223 223 list->shift, list->width, list->div_flags, 224 224 list->table, &ctx->lock); 225 225 else 226 - clk_hw = clk_hw_register_divider(NULL, list->name, 226 + clk_hw = clk_hw_register_divider(ctx->dev, list->name, 227 227 list->parent_name, list->flags, 228 228 ctx->reg_base + list->offset, list->shift, 229 229 list->width, list->div_flags, &ctx->lock); ··· 255 255 unsigned int idx, ret; 256 256 257 257 for (idx = 0; idx < nr_clk; idx++, list++) { 258 - clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name, 258 + clk_hw = clk_hw_register_gate(ctx->dev, list->name, list->parent_name, 259 259 list->flags, ctx->reg_base + list->offset, 260 260 list->bit_idx, list->gate_flags, &ctx->lock); 261 261 if (IS_ERR(clk_hw)) {
+7
drivers/clk/samsung/clk.h
··· 24 24 */ 25 25 struct samsung_clk_provider { 26 26 void __iomem *reg_base; 27 + struct device *dev; 27 28 spinlock_t lock; 28 29 /* clk_data must be the last entry due to variable lenght 'hws' array */ 29 30 struct clk_hw_onecell_data clk_data; ··· 353 352 /* list and number of clocks registers */ 354 353 const unsigned long *clk_regs; 355 354 unsigned int nr_clk_regs; 355 + 356 + /* list and number of clocks registers to set before suspend */ 357 + const struct samsung_clk_reg_dump *suspend_regs; 358 + unsigned int nr_suspend_regs; 359 + /* name of the parent clock needed for CMU register access */ 360 + const char *clk_name; 356 361 }; 357 362 358 363 extern struct samsung_clk_provider *__init samsung_clk_init(