A set of clk driver fixes that resolve issues for various SoCs. Most of
these are incorrect clk data, like bad parent descriptions. When the clk tree is improperly described things don't work, like USB and UFS controllers, because clk frequencies are wonky. Here are the extra details: - Fix the parent of UFS reference clks on Qualcomm SC8280XP so that UFS works properly. - Fix the clk ID for USB on AT91 RM9200 so the USB driver continues to probe. - Stop using of_device_get_match_data() on the wrong device for a Samsung Exynos driver so it gets the proper clk data. - Fix ExynosAutov9 binding. - Fix the parent of the div4 clk on Exynos7885. - Stop calling runtime PM APIs from the Qualcomm GDSC driver directly as it leads to a lockdep splat and is just plain wrong because it violates runtime PM semantics by calling runtime PM APIs when the device has been runtime PM disabled. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAmOH34YRHHNib3lkQGtl cm5lbC5vcmcACgkQrQKIl8bklSWa1w/7BNQeGBZaSZR4AM44xvIHqOn0DJnsKDws 4cPf2tUMSSlfjaSceuF84dM78JSJlxN2QtMKqxooI5H/AwcKA7ZhmKgqHmytPGb8 yHALXy0nL3+ojuzXB46wn+EN6B7odeAK99dcEsUEytDHDgxUck0WvHmFjUJFwu/r 2BbQVqGw8EYWz7fngbbovoCGmddLgoHam0dLq5lkiSe7b9NXx+zWilcoEbbXHGah HNOkjoeKV1Mub7XlWM86DYp3XH7hn9/gb+ztETVG2OZnPl3vLTI9+CaTyGfVx/29 0ZwaPOxdzBaOLw+We64BY7ikgqNN274TBt1U6EtL+SBKVlqPd173EcxcNtb93pac 2OAopef2/DximX6gLQYX8XeAaRJ4HQM1JKH6qdUV2vzlruT+S13/FT8tPsORzFRY xGxX98vhVHg6r6BWg0IdLl5F/9QAz2NyPkfxK24wDcnTNVcInmBRYBC2IsaNuXq8 agOjfxST+V+Lxc8w5lT1zGZIEnvrXcIsW4YT1piacZQsZeUYGPn+7imkBZR+4/mC 0ggLmTd27u0mzN8ecjLR8mu1D+acoXm+8qAk4CPIRjq3uns03nAgB0yt0aFZV5Z1 zE+vuNnjlFlTxH+h5vDhmM7QWCLhs9CMRHL41aEDV60ADRC6rkbJodIczpPqlxg4 c1HkSKuZLaA= =EmWU -----END PGP SIGNATURE----- Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux Pull clk fixes from Stephen Boyd: "A set of clk driver fixes that resolve issues for various SoCs. Most of these are incorrect clk data, like bad parent descriptions. When the clk tree is improperly described things don't work, like USB and UFS controllers, because clk frequencies are wonky. Here are the extra details: - Fix the parent of UFS reference clks on Qualcomm SC8280XP so that UFS works properly - Fix the clk ID for USB on AT91 RM9200 so the USB driver continues to probe - Stop using of_device_get_match_data() on the wrong device for a Samsung Exynos driver so it gets the proper clk data - Fix ExynosAutov9 binding - Fix the parent of the div4 clk on Exynos7885 - Stop calling runtime PM APIs from the Qualcomm GDSC driver directly as it leads to a lockdep splat and is just plain wrong because it violates runtime PM semantics by calling runtime PM APIs when the device has been runtime PM disabled" * tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: clk: qcom: gcc-sc8280xp: add cxo as parent for three ufs ref clks ARM: at91: rm9200: fix usb device clock id clk: samsung: Revert "clk: samsung: exynos-clkout: Use of_device_get_match_data()" dt-bindings: clock: exynosautov9: fix reference to CMU_FSYS1 clk: qcom: gdsc: Remove direct runtime PM calls clk: samsung: exynos7885: Correct "div4" clock parents
This commit is contained in:
Коммит
063c0e773a
|
@ -148,7 +148,7 @@ allOf:
|
|||
items:
|
||||
- const: oscclk
|
||||
- const: dout_clkcmu_fsys1_bus
|
||||
- const: dout_clkcmu_fsys1_mmc_card
|
||||
- const: gout_clkcmu_fsys1_mmc_card
|
||||
- const: dout_clkcmu_fsys1_usbdrd
|
||||
|
||||
- if:
|
||||
|
|
|
@ -666,7 +666,7 @@
|
|||
compatible = "atmel,at91rm9200-udc";
|
||||
reg = <0xfffb0000 0x4000>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_HIGH 2>;
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 11>, <&pmc PMC_TYPE_SYSTEM 2>;
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 11>, <&pmc PMC_TYPE_SYSTEM 1>;
|
||||
clock-names = "pclk", "hclk";
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@ static const struct clk_pll_characteristics rm9200_pll_characteristics = {
|
|||
};
|
||||
|
||||
static const struct sck at91rm9200_systemck[] = {
|
||||
{ .n = "udpck", .p = "usbck", .id = 2 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 1 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 4 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
|
|
|
@ -5364,6 +5364,8 @@ static struct clk_branch gcc_ufs_1_card_clkref_clk = {
|
|||
.enable_mask = BIT(0),
|
||||
.hw.init = &(const struct clk_init_data) {
|
||||
.name = "gcc_ufs_1_card_clkref_clk",
|
||||
.parent_data = &gcc_parent_data_tcxo,
|
||||
.num_parents = 1,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -5432,6 +5434,8 @@ static struct clk_branch gcc_ufs_card_clkref_clk = {
|
|||
.enable_mask = BIT(0),
|
||||
.hw.init = &(const struct clk_init_data) {
|
||||
.name = "gcc_ufs_card_clkref_clk",
|
||||
.parent_data = &gcc_parent_data_tcxo,
|
||||
.num_parents = 1,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
@ -5848,6 +5852,8 @@ static struct clk_branch gcc_ufs_ref_clkref_clk = {
|
|||
.enable_mask = BIT(0),
|
||||
.hw.init = &(const struct clk_init_data) {
|
||||
.name = "gcc_ufs_ref_clkref_clk",
|
||||
.parent_data = &gcc_parent_data_tcxo,
|
||||
.num_parents = 1,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
@ -56,22 +55,6 @@ enum gdsc_status {
|
|||
GDSC_ON
|
||||
};
|
||||
|
||||
static int gdsc_pm_runtime_get(struct gdsc *sc)
|
||||
{
|
||||
if (!sc->dev)
|
||||
return 0;
|
||||
|
||||
return pm_runtime_resume_and_get(sc->dev);
|
||||
}
|
||||
|
||||
static int gdsc_pm_runtime_put(struct gdsc *sc)
|
||||
{
|
||||
if (!sc->dev)
|
||||
return 0;
|
||||
|
||||
return pm_runtime_put_sync(sc->dev);
|
||||
}
|
||||
|
||||
/* Returns 1 if GDSC status is status, 0 if not, and < 0 on error */
|
||||
static int gdsc_check_status(struct gdsc *sc, enum gdsc_status status)
|
||||
{
|
||||
|
@ -271,8 +254,9 @@ static void gdsc_retain_ff_on(struct gdsc *sc)
|
|||
regmap_update_bits(sc->regmap, sc->gdscr, mask, mask);
|
||||
}
|
||||
|
||||
static int _gdsc_enable(struct gdsc *sc)
|
||||
static int gdsc_enable(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct gdsc *sc = domain_to_gdsc(domain);
|
||||
int ret;
|
||||
|
||||
if (sc->pwrsts == PWRSTS_ON)
|
||||
|
@ -328,22 +312,11 @@ static int _gdsc_enable(struct gdsc *sc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gdsc_enable(struct generic_pm_domain *domain)
|
||||
static int gdsc_disable(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct gdsc *sc = domain_to_gdsc(domain);
|
||||
int ret;
|
||||
|
||||
ret = gdsc_pm_runtime_get(sc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return _gdsc_enable(sc);
|
||||
}
|
||||
|
||||
static int _gdsc_disable(struct gdsc *sc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (sc->pwrsts == PWRSTS_ON)
|
||||
return gdsc_assert_reset(sc);
|
||||
|
||||
|
@ -388,18 +361,6 @@ static int _gdsc_disable(struct gdsc *sc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gdsc_disable(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct gdsc *sc = domain_to_gdsc(domain);
|
||||
int ret;
|
||||
|
||||
ret = _gdsc_disable(sc);
|
||||
|
||||
gdsc_pm_runtime_put(sc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gdsc_init(struct gdsc *sc)
|
||||
{
|
||||
u32 mask, val;
|
||||
|
@ -447,11 +408,6 @@ static int gdsc_init(struct gdsc *sc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* ...and the power-domain */
|
||||
ret = gdsc_pm_runtime_get(sc);
|
||||
if (ret)
|
||||
goto err_disable_supply;
|
||||
|
||||
/*
|
||||
* Votable GDSCs can be ON due to Vote from other masters.
|
||||
* If a Votable GDSC is ON, make sure we have a Vote.
|
||||
|
@ -459,14 +415,14 @@ static int gdsc_init(struct gdsc *sc)
|
|||
if (sc->flags & VOTABLE) {
|
||||
ret = gdsc_update_collapse_bit(sc, false);
|
||||
if (ret)
|
||||
goto err_put_rpm;
|
||||
goto err_disable_supply;
|
||||
}
|
||||
|
||||
/* Turn on HW trigger mode if supported */
|
||||
if (sc->flags & HW_CTRL) {
|
||||
ret = gdsc_hwctrl(sc, true);
|
||||
if (ret < 0)
|
||||
goto err_put_rpm;
|
||||
goto err_disable_supply;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -496,13 +452,10 @@ static int gdsc_init(struct gdsc *sc)
|
|||
|
||||
ret = pm_genpd_init(&sc->pd, NULL, !on);
|
||||
if (ret)
|
||||
goto err_put_rpm;
|
||||
goto err_disable_supply;
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_rpm:
|
||||
if (on)
|
||||
gdsc_pm_runtime_put(sc);
|
||||
err_disable_supply:
|
||||
if (on && sc->rsupply)
|
||||
regulator_disable(sc->rsupply);
|
||||
|
@ -541,8 +494,6 @@ int gdsc_register(struct gdsc_desc *desc,
|
|||
for (i = 0; i < num; i++) {
|
||||
if (!scs[i])
|
||||
continue;
|
||||
if (pm_runtime_enabled(dev))
|
||||
scs[i]->dev = dev;
|
||||
scs[i]->regmap = regmap;
|
||||
scs[i]->rcdev = rcdev;
|
||||
ret = gdsc_init(scs[i]);
|
||||
|
|
|
@ -30,7 +30,6 @@ struct reset_controller_dev;
|
|||
* @resets: ids of resets associated with this gdsc
|
||||
* @reset_count: number of @resets
|
||||
* @rcdev: reset controller
|
||||
* @dev: the device holding the GDSC, used for pm_runtime calls
|
||||
*/
|
||||
struct gdsc {
|
||||
struct generic_pm_domain pd;
|
||||
|
@ -74,7 +73,6 @@ struct gdsc {
|
|||
|
||||
const char *supply;
|
||||
struct regulator *rsupply;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
struct gdsc_desc {
|
||||
|
|
|
@ -81,17 +81,19 @@ MODULE_DEVICE_TABLE(of, exynos_clkout_ids);
|
|||
static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask)
|
||||
{
|
||||
const struct exynos_clkout_variant *variant;
|
||||
const struct of_device_id *match;
|
||||
|
||||
if (!dev->parent) {
|
||||
dev_err(dev, "not instantiated from MFD\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
variant = of_device_get_match_data(dev->parent);
|
||||
if (!variant) {
|
||||
match = of_match_device(exynos_clkout_ids, dev->parent);
|
||||
if (!match) {
|
||||
dev_err(dev, "cannot match parent device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
variant = match->data;
|
||||
|
||||
*mux_mask = variant->mux_mask;
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ static const struct samsung_div_clock top_div_clks[] __initconst = {
|
|||
CLK_CON_DIV_PLL_SHARED0_DIV2, 0, 1),
|
||||
DIV(CLK_DOUT_SHARED0_DIV3, "dout_shared0_div3", "fout_shared0_pll",
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV3, 0, 2),
|
||||
DIV(CLK_DOUT_SHARED0_DIV4, "dout_shared0_div4", "fout_shared0_pll",
|
||||
DIV(CLK_DOUT_SHARED0_DIV4, "dout_shared0_div4", "dout_shared0_div2",
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV4, 0, 1),
|
||||
DIV(CLK_DOUT_SHARED0_DIV5, "dout_shared0_div5", "fout_shared0_pll",
|
||||
CLK_CON_DIV_PLL_SHARED0_DIV5, 0, 3),
|
||||
|
@ -239,7 +239,7 @@ static const struct samsung_div_clock top_div_clks[] __initconst = {
|
|||
CLK_CON_DIV_PLL_SHARED1_DIV2, 0, 1),
|
||||
DIV(CLK_DOUT_SHARED1_DIV3, "dout_shared1_div3", "fout_shared1_pll",
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV3, 0, 2),
|
||||
DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "fout_shared1_pll",
|
||||
DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "dout_shared1_div2",
|
||||
CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1),
|
||||
|
||||
/* CORE */
|
||||
|
|
Загрузка…
Ссылка в новой задаче