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

Configure Feed

Select the types of activity you want to include in your feed.

phy: exynos5-usbdrd: convert core clocks to clk_bulk

Using the clk_bulk APIs, the clock handling for the core clocks becomes
much simpler. No need to check any flags whether or not certain clocks
exist or not. Further, we can drop the various handles to the
individual clocks in the driver data and instead simply treat them all
as one thing.

So far, this driver assumes that all platforms have a clock "ref". It
also assumes that the clocks "phy_pipe", "phy_utmi", and "itp" exist if
the platform data "has_common_clk_gate" is set to true. It then goes
and individually tries to acquire and enable and disable all the
individual clocks one by one. Rather than relying on these implicit
clocks and open-coding the clock handling, we can just explicitly spell
out the clock names in the different device data and use that
information to populate clk_bulk_data, allowing us to use the clk_bulk
APIs for managing the clocks.

As a side-effect, this change highlighted the fact that
exynos5_usbdrd_phy_power_on() forgot to check the result of the clock
enable calls. Using the clk_bulk APIs, the compiler now warns when
return values are not checked - therefore add the necessary check
instead of silently ignoring failures and continuing as if all is OK
when it isn't.

For consistency, also change a related dev_err() to dev_err_probe() in
exynos5_usbdrd_phy_clk_handle() to get consistent error message
formatting.

Finally, exynos5_usbdrd_phy_clk_handle() prints an error message in all
cases as necessary (except for -ENOMEM). There is no need to print
another message in its caller (the probe() function), and printing
errors during OOM conditions is usually discouraged. Drop the
duplicated message in exynos5_usbdrd_phy_probe().

Signed-off-by: André Draszik <andre.draszik@linaro.org>
Tested-by: Will McVicker <willmcvicker@google.com>
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Tested-by: Peter Griffin <peter.griffin@linaro.org>
Link: https://lore.kernel.org/r/20240617-usb-phy-gs101-v3-3-b66de9ae7424@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

André Draszik and committed by
Vinod Koul
54290bd9 bbb28a1d

+64 -71
+64 -71
drivers/phy/samsung/phy-exynos5-usbdrd.c
··· 185 185 struct exynos5_usbdrd_phy_drvdata { 186 186 const struct exynos5_usbdrd_phy_config *phy_cfg; 187 187 const struct phy_ops *phy_ops; 188 + const char * const *core_clk_names; 189 + int n_core_clks; 188 190 u32 pmu_offset_usbdrd0_phy; 189 191 u32 pmu_offset_usbdrd0_phy_ss; 190 192 u32 pmu_offset_usbdrd1_phy; 191 - bool has_common_clk_gate; 192 193 }; 193 194 194 195 /** ··· 197 196 * @dev: pointer to device instance of this platform device 198 197 * @reg_phy: usb phy controller register memory base 199 198 * @clk: phy clock for register access 200 - * @pipeclk: clock for pipe3 phy 201 - * @utmiclk: clock for utmi+ phy 202 - * @itpclk: clock for ITP generation 199 + * @core_clks: core clocks for phy (ref, pipe3, utmi+, ITP, etc. as required) 203 200 * @drv_data: pointer to SoC level driver data structure 204 201 * @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY 205 202 * instances each with its 'phy' and 'phy_cfg'. 206 203 * @extrefclk: frequency select settings when using 'separate 207 204 * reference clocks' for SS and HS operations 208 - * @ref_clk: reference clock to PHY block from which PHY's 209 - * operational clocks are derived 210 205 * @vbus: VBUS regulator for phy 211 206 * @vbus_boost: Boost regulator for VBUS present on few Exynos boards 212 207 */ ··· 210 213 struct device *dev; 211 214 void __iomem *reg_phy; 212 215 struct clk *clk; 213 - struct clk *pipeclk; 214 - struct clk *utmiclk; 215 - struct clk *itpclk; 216 + struct clk_bulk_data *core_clks; 216 217 const struct exynos5_usbdrd_phy_drvdata *drv_data; 217 218 struct phy_usb_instance { 218 219 struct phy *phy; ··· 220 225 const struct exynos5_usbdrd_phy_config *phy_cfg; 221 226 } phys[EXYNOS5_DRDPHYS_NUM]; 222 227 u32 extrefclk; 223 - struct clk *ref_clk; 224 228 struct regulator *vbus; 225 229 struct regulator *vbus_boost; 226 230 }; ··· 499 505 500 506 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n"); 501 507 502 - clk_prepare_enable(phy_drd->ref_clk); 503 - if (!phy_drd->drv_data->has_common_clk_gate) { 504 - clk_prepare_enable(phy_drd->pipeclk); 505 - clk_prepare_enable(phy_drd->utmiclk); 506 - clk_prepare_enable(phy_drd->itpclk); 507 - } 508 + ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_core_clks, 509 + phy_drd->core_clks); 510 + if (ret) 511 + return ret; 508 512 509 513 /* Enable VBUS supply */ 510 514 if (phy_drd->vbus_boost) { ··· 532 540 regulator_disable(phy_drd->vbus_boost); 533 541 534 542 fail_vbus: 535 - clk_disable_unprepare(phy_drd->ref_clk); 536 - if (!phy_drd->drv_data->has_common_clk_gate) { 537 - clk_disable_unprepare(phy_drd->itpclk); 538 - clk_disable_unprepare(phy_drd->utmiclk); 539 - clk_disable_unprepare(phy_drd->pipeclk); 540 - } 543 + clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks, 544 + phy_drd->core_clks); 541 545 542 546 return ret; 543 547 } ··· 554 566 if (phy_drd->vbus_boost) 555 567 regulator_disable(phy_drd->vbus_boost); 556 568 557 - clk_disable_unprepare(phy_drd->ref_clk); 558 - if (!phy_drd->drv_data->has_common_clk_gate) { 559 - clk_disable_unprepare(phy_drd->itpclk); 560 - clk_disable_unprepare(phy_drd->pipeclk); 561 - clk_disable_unprepare(phy_drd->utmiclk); 562 - } 569 + clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks, 570 + phy_drd->core_clks); 563 571 564 572 return 0; 565 573 } ··· 869 885 870 886 static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd) 871 887 { 872 - unsigned long ref_rate; 873 888 int ret; 889 + struct clk *ref_clk; 890 + unsigned long ref_rate; 874 891 875 892 phy_drd->clk = devm_clk_get(phy_drd->dev, "phy"); 876 893 if (IS_ERR(phy_drd->clk)) { ··· 879 894 return PTR_ERR(phy_drd->clk); 880 895 } 881 896 882 - phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref"); 883 - if (IS_ERR(phy_drd->ref_clk)) { 884 - dev_err(phy_drd->dev, "Failed to get phy reference clock\n"); 885 - return PTR_ERR(phy_drd->ref_clk); 886 - } 887 - ref_rate = clk_get_rate(phy_drd->ref_clk); 897 + phy_drd->core_clks = devm_kcalloc(phy_drd->dev, 898 + phy_drd->drv_data->n_core_clks, 899 + sizeof(*phy_drd->core_clks), 900 + GFP_KERNEL); 901 + if (!phy_drd->core_clks) 902 + return -ENOMEM; 888 903 904 + for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i) 905 + phy_drd->core_clks[i].id = phy_drd->drv_data->core_clk_names[i]; 906 + 907 + ret = devm_clk_bulk_get(phy_drd->dev, phy_drd->drv_data->n_core_clks, 908 + phy_drd->core_clks); 909 + if (ret) 910 + return dev_err_probe(phy_drd->dev, ret, 911 + "failed to get phy core clock(s)\n"); 912 + 913 + ref_clk = NULL; 914 + for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i) { 915 + if (!strcmp(phy_drd->core_clks[i].id, "ref")) { 916 + ref_clk = phy_drd->core_clks[i].clk; 917 + break; 918 + } 919 + } 920 + if (!ref_clk) 921 + return dev_err_probe(phy_drd->dev, -ENODEV, 922 + "failed to find phy reference clock\n"); 923 + 924 + ref_rate = clk_get_rate(ref_clk); 889 925 ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk); 890 - if (ret) { 891 - dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n", 892 - ref_rate); 893 - return ret; 894 - } 895 - 896 - if (!phy_drd->drv_data->has_common_clk_gate) { 897 - phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe"); 898 - if (IS_ERR(phy_drd->pipeclk)) { 899 - dev_info(phy_drd->dev, 900 - "PIPE3 phy operational clock not specified\n"); 901 - phy_drd->pipeclk = NULL; 902 - } 903 - 904 - phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi"); 905 - if (IS_ERR(phy_drd->utmiclk)) { 906 - dev_info(phy_drd->dev, 907 - "UTMI phy operational clock not specified\n"); 908 - phy_drd->utmiclk = NULL; 909 - } 910 - 911 - phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp"); 912 - if (IS_ERR(phy_drd->itpclk)) { 913 - dev_info(phy_drd->dev, 914 - "ITP clock from main OSC not specified\n"); 915 - phy_drd->itpclk = NULL; 916 - } 917 - } 926 + if (ret) 927 + return dev_err_probe(phy_drd->dev, ret, 928 + "clock rate (%ld) not supported\n", 929 + ref_rate); 918 930 919 931 return 0; 920 932 } ··· 939 957 }, 940 958 }; 941 959 960 + static const char * const exynos5_core_clk_names[] = { 961 + "ref", 962 + }; 963 + 964 + static const char * const exynos5433_core_clk_names[] = { 965 + "ref", "phy_pipe", "phy_utmi", "itp", 966 + }; 967 + 942 968 static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = { 943 969 .phy_cfg = phy_cfg_exynos5, 944 970 .phy_ops = &exynos5_usbdrd_phy_ops, 945 971 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 946 972 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, 947 - .has_common_clk_gate = true, 973 + .core_clk_names = exynos5_core_clk_names, 974 + .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names), 948 975 }; 949 976 950 977 static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { 951 978 .phy_cfg = phy_cfg_exynos5, 952 979 .phy_ops = &exynos5_usbdrd_phy_ops, 953 980 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 954 - .has_common_clk_gate = true, 981 + .core_clk_names = exynos5_core_clk_names, 982 + .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names), 955 983 }; 956 984 957 985 static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = { ··· 969 977 .phy_ops = &exynos5_usbdrd_phy_ops, 970 978 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 971 979 .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL, 972 - .has_common_clk_gate = false, 980 + .core_clk_names = exynos5433_core_clk_names, 981 + .n_core_clks = ARRAY_SIZE(exynos5433_core_clk_names), 973 982 }; 974 983 975 984 static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = { 976 985 .phy_cfg = phy_cfg_exynos5, 977 986 .phy_ops = &exynos5_usbdrd_phy_ops, 978 987 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 979 - .has_common_clk_gate = false, 988 + .core_clk_names = exynos5433_core_clk_names, 989 + .n_core_clks = ARRAY_SIZE(exynos5433_core_clk_names), 980 990 }; 981 991 982 992 static const struct exynos5_usbdrd_phy_drvdata exynos850_usbdrd_phy = { 983 993 .phy_cfg = phy_cfg_exynos850, 984 994 .phy_ops = &exynos850_usbdrd_phy_ops, 985 995 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 986 - .has_common_clk_gate = true, 996 + .core_clk_names = exynos5_core_clk_names, 997 + .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names), 987 998 }; 988 999 989 1000 static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { ··· 1040 1045 phy_drd->drv_data = drv_data; 1041 1046 1042 1047 ret = exynos5_usbdrd_phy_clk_handle(phy_drd); 1043 - if (ret) { 1044 - dev_err(dev, "Failed to initialize clocks\n"); 1048 + if (ret) 1045 1049 return ret; 1046 - } 1047 1050 1048 1051 reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, 1049 1052 "samsung,pmu-syscon");