diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/at91/clk-generated.c | 6 | ||||
-rw-r--r-- | drivers/clk/clk-versaclock5.c | 42 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-pll.c | 2 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3036.c | 5 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3308.c | 1 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-dfll.c | 2 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra-periph.c | 6 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/fuse-tegra.c | 60 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/fuse-tegra20.c | 11 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/fuse-tegra30.c | 16 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/fuse.h | 2 | ||||
-rw-r--r-- | drivers/soc/tegra/pmc.c | 14 | ||||
-rw-r--r-- | drivers/soc/tegra/powergate-bpmp.c | 1 |
13 files changed, 139 insertions, 29 deletions
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index b4fc8d71daf2..b656d25a9767 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c @@ -128,6 +128,12 @@ static int clk_generated_determine_rate(struct clk_hw *hw, int i; u32 div; + /* do not look for a rate that is outside of our range */ + if (gck->range.max && req->rate > gck->range.max) + req->rate = gck->range.max; + if (gck->range.min && req->rate < gck->range.min) + req->rate = gck->range.min; + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { if (gck->chg_pid == i) continue; diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 3c737742c2a9..c6d3b1ab3d55 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -907,6 +907,7 @@ static const struct of_device_id clk_vc5_of_match[]; static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) { + unsigned int oe, sd, src_mask = 0, src_val = 0; struct vc5_driver_data *vc5; struct clk_init_data init; const char *parent_names[2]; @@ -930,11 +931,33 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) return -EPROBE_DEFER; vc5->regmap = devm_regmap_init_i2c(client, &vc5_regmap_config); - if (IS_ERR(vc5->regmap)) { - dev_err(&client->dev, "failed to allocate register map\n"); - return PTR_ERR(vc5->regmap); + if (IS_ERR(vc5->regmap)) + return dev_err_probe(&client->dev, PTR_ERR(vc5->regmap), + "failed to allocate register map\n"); + + ret = of_property_read_u32(client->dev.of_node, "idt,shutdown", &sd); + if (!ret) { + src_mask |= VC5_PRIM_SRC_SHDN_EN_GBL_SHDN; + if (sd) + src_val |= VC5_PRIM_SRC_SHDN_EN_GBL_SHDN; + } else if (ret != -EINVAL) { + return dev_err_probe(&client->dev, ret, + "could not read idt,shutdown\n"); } + ret = of_property_read_u32(client->dev.of_node, + "idt,output-enable-active", &oe); + if (!ret) { + src_mask |= VC5_PRIM_SRC_SHDN_SP; + if (oe) + src_val |= VC5_PRIM_SRC_SHDN_SP; + } else if (ret != -EINVAL) { + return dev_err_probe(&client->dev, ret, + "could not read idt,output-enable-active\n"); + } + + regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, src_mask, src_val); + /* Register clock input mux */ memset(&init, 0, sizeof(init)); @@ -957,10 +980,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) __clk_get_name(vc5->pin_clkin); } - if (!init.num_parents) { - dev_err(&client->dev, "no input clock specified!\n"); - return -EINVAL; - } + if (!init.num_parents) + return dev_err_probe(&client->dev, -EINVAL, + "no input clock specified!\n"); /* Configure Optional Loading Capacitance for external XTAL */ if (!(vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)) { @@ -1099,14 +1121,16 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5); if (ret) { - dev_err(&client->dev, "unable to add clk provider\n"); + dev_err_probe(&client->dev, ret, + "unable to add clk provider\n"); goto err_clk; } return 0; err_clk_register: - dev_err(&client->dev, "unable to register %s\n", init.name); + dev_err_probe(&client->dev, ret, + "unable to register %s\n", init.name); kfree(init.name); /* clock framework made a copy of the name */ err_clk: if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index fe937bcdb487..f7827b3b7fc1 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -940,7 +940,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, switch (pll_type) { case pll_rk3036: case pll_rk3328: - if (!pll->rate_table || IS_ERR(ctx->grf)) + if (!pll->rate_table) init.ops = &rockchip_rk3036_pll_clk_norate_ops; else init.ops = &rockchip_rk3036_pll_clk_ops; diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 614845cc5b4a..d644bc155ec6 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -121,6 +121,7 @@ PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" }; PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" }; +PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" }; PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; @@ -340,7 +341,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS, RK2928_CLKGATE_CON(10), 4, GFLAGS), - COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, + COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_dmyapll_dpll_gpll_xin24_p, 0, RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, RK2928_CLKGATE_CON(10), 5, GFLAGS), @@ -403,7 +404,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS), GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS), GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), - GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), + GATE(HCLK_SFC, "hclk_sfc", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS), GATE(HCLK_MAC, "hclk_mac", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), /* pclk_peri gates */ diff --git a/drivers/clk/rockchip/clk-rk3308.c b/drivers/clk/rockchip/clk-rk3308.c index 2c3bd0c749f2..db3396c3e6e9 100644 --- a/drivers/clk/rockchip/clk-rk3308.c +++ b/drivers/clk/rockchip/clk-rk3308.c @@ -911,6 +911,7 @@ static const char *const rk3308_critical_clocks[] __initconst = { "hclk_audio", "pclk_audio", "sclk_ddrc", + "clk_ddrphy4x", }; static void __init rk3308_clk_init(struct device_node *np) diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index a5f526bb0483..6144447f86c6 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -1377,7 +1377,7 @@ static void dfll_debug_init(struct tegra_dfll *td) } #else -static void inline dfll_debug_init(struct tegra_dfll *td) { } +static inline void dfll_debug_init(struct tegra_dfll *td) { } #endif /* CONFIG_DEBUG_FS */ /* diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 292d6269daf1..4dcf7f7cb8a0 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -777,11 +777,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("ahbdma", "hclk", 33, 0, tegra_clk_ahbdma, 0), GATE("apbdma", "pclk", 34, 0, tegra_clk_apbdma, 0), GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), - /* - * Critical for RAM re-repair operation, which must occur on resume - * from LP1 system suspend and as part of CCPLEX cluster switching. - */ - GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, CLK_IS_CRITICAL), + GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0), GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0), GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0), diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 3d9da3d359da..f2151815db58 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -13,6 +13,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/sys_soc.h> @@ -210,6 +211,8 @@ static int tegra_fuse_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fuse); fuse->dev = &pdev->dev; + pm_runtime_enable(&pdev->dev); + if (fuse->soc->probe) { err = fuse->soc->probe(fuse); if (err < 0) @@ -246,14 +249,71 @@ static int tegra_fuse_probe(struct platform_device *pdev) return 0; restore: + fuse->clk = NULL; fuse->base = base; + pm_runtime_disable(&pdev->dev); return err; } +static int __maybe_unused tegra_fuse_runtime_resume(struct device *dev) +{ + int err; + + err = clk_prepare_enable(fuse->clk); + if (err < 0) { + dev_err(dev, "failed to enable FUSE clock: %d\n", err); + return err; + } + + return 0; +} + +static int __maybe_unused tegra_fuse_runtime_suspend(struct device *dev) +{ + clk_disable_unprepare(fuse->clk); + + return 0; +} + +static int __maybe_unused tegra_fuse_suspend(struct device *dev) +{ + int ret; + + /* + * Critical for RAM re-repair operation, which must occur on resume + * from LP1 system suspend and as part of CCPLEX cluster switching. + */ + if (fuse->soc->clk_suspend_on) + ret = pm_runtime_resume_and_get(dev); + else + ret = pm_runtime_force_suspend(dev); + + return ret; +} + +static int __maybe_unused tegra_fuse_resume(struct device *dev) +{ + int ret = 0; + + if (fuse->soc->clk_suspend_on) + pm_runtime_put(dev); + else + ret = pm_runtime_force_resume(dev); + + return ret; +} + +static const struct dev_pm_ops tegra_fuse_pm = { + SET_RUNTIME_PM_OPS(tegra_fuse_runtime_suspend, tegra_fuse_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra_fuse_suspend, tegra_fuse_resume) +}; + static struct platform_driver tegra_fuse_driver = { .driver = { .name = "tegra-fuse", .of_match_table = tegra_fuse_match, + .pm = &tegra_fuse_pm, .suppress_bind_attrs = true, }, .probe = tegra_fuse_probe, diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c index 16aaa28573ac..8ec9fc5e5e4b 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra20.c +++ b/drivers/soc/tegra/fuse/fuse-tegra20.c @@ -16,6 +16,7 @@ #include <linux/kobject.h> #include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/random.h> #include <soc/tegra/fuse.h> @@ -46,6 +47,10 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) u32 value = 0; int err; + err = pm_runtime_resume_and_get(fuse->dev); + if (err) + return err; + mutex_lock(&fuse->apbdma.lock); fuse->apbdma.config.src_addr = fuse->phys + FUSE_BEGIN + offset; @@ -66,8 +71,6 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) reinit_completion(&fuse->apbdma.wait); - clk_prepare_enable(fuse->clk); - dmaengine_submit(dma_desc); dma_async_issue_pending(fuse->apbdma.chan); time_left = wait_for_completion_timeout(&fuse->apbdma.wait, @@ -78,10 +81,9 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) else value = *fuse->apbdma.virt; - clk_disable_unprepare(fuse->clk); - out: mutex_unlock(&fuse->apbdma.lock); + pm_runtime_put(fuse->dev); return value; } @@ -165,4 +167,5 @@ const struct tegra_fuse_soc tegra20_fuse_soc = { .probe = tegra20_fuse_probe, .info = &tegra20_fuse_info, .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index c1aa7815bd6e..b071d433d74f 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -12,6 +12,7 @@ #include <linux/of_device.h> #include <linux/of_address.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/random.h> #include <soc/tegra/fuse.h> @@ -52,15 +53,13 @@ static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset) u32 value; int err; - err = clk_prepare_enable(fuse->clk); - if (err < 0) { - dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err); + err = pm_runtime_resume_and_get(fuse->dev); + if (err) return 0; - } value = readl_relaxed(fuse->base + FUSE_BEGIN + offset); - clk_disable_unprepare(fuse->clk); + pm_runtime_put(fuse->dev); return value; } @@ -113,6 +112,7 @@ const struct tegra_fuse_soc tegra30_fuse_soc = { .speedo_init = tegra30_init_speedo_data, .info = &tegra30_fuse_info, .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -128,6 +128,7 @@ const struct tegra_fuse_soc tegra114_fuse_soc = { .speedo_init = tegra114_init_speedo_data, .info = &tegra114_fuse_info, .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -209,6 +210,7 @@ const struct tegra_fuse_soc tegra124_fuse_soc = { .lookups = tegra124_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra124_fuse_lookups), .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = true, }; #endif @@ -295,6 +297,7 @@ const struct tegra_fuse_soc tegra210_fuse_soc = { .lookups = tegra210_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra210_fuse_lookups), .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -325,6 +328,7 @@ const struct tegra_fuse_soc tegra186_fuse_soc = { .lookups = tegra186_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra186_fuse_lookups), .soc_attr_group = &tegra_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -355,6 +359,7 @@ const struct tegra_fuse_soc tegra194_fuse_soc = { .lookups = tegra194_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra194_fuse_lookups), .soc_attr_group = &tegra194_soc_attr_group, + .clk_suspend_on = false, }; #endif @@ -385,5 +390,6 @@ const struct tegra_fuse_soc tegra234_fuse_soc = { .lookups = tegra234_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra234_fuse_lookups), .soc_attr_group = &tegra194_soc_attr_group, + .clk_suspend_on = false, }; #endif diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h index e057a58e2060..de58feba0435 100644 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@ -34,6 +34,8 @@ struct tegra_fuse_soc { unsigned int num_lookups; const struct attribute_group *soc_attr_group; + + bool clk_suspend_on; }; struct tegra_fuse { diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index ea62f84d1c8b..50091c4ec948 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -436,7 +436,7 @@ struct tegra_pmc { static struct tegra_pmc *pmc = &(struct tegra_pmc) { .base = NULL, - .suspend_mode = TEGRA_SUSPEND_NONE, + .suspend_mode = TEGRA_SUSPEND_NOT_READY, }; static inline struct tegra_powergate * @@ -1812,6 +1812,7 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np) u32 value, values[2]; if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) { + pmc->suspend_mode = TEGRA_SUSPEND_NONE; } else { switch (value) { case 0: @@ -2785,6 +2786,11 @@ static int tegra_pmc_regmap_init(struct tegra_pmc *pmc) return 0; } +static void tegra_pmc_reset_suspend_mode(void *data) +{ + pmc->suspend_mode = TEGRA_SUSPEND_NOT_READY; +} + static int tegra_pmc_probe(struct platform_device *pdev) { void __iomem *base; @@ -2803,6 +2809,11 @@ static int tegra_pmc_probe(struct platform_device *pdev) if (err < 0) return err; + err = devm_add_action_or_reset(&pdev->dev, tegra_pmc_reset_suspend_mode, + NULL); + if (err) + return err; + /* take over the memory region from the early initialization */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); @@ -2909,6 +2920,7 @@ static int tegra_pmc_probe(struct platform_device *pdev) tegra_pmc_clock_register(pmc, pdev->dev.of_node); platform_set_drvdata(pdev, pmc); + tegra_pm_init_suspend(); return 0; diff --git a/drivers/soc/tegra/powergate-bpmp.c b/drivers/soc/tegra/powergate-bpmp.c index 06c792bafca5..8eaf50d0b6af 100644 --- a/drivers/soc/tegra/powergate-bpmp.c +++ b/drivers/soc/tegra/powergate-bpmp.c @@ -7,7 +7,6 @@ #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/slab.h> -#include <linux/version.h> #include <soc/tegra/bpmp.h> #include <soc/tegra/bpmp-abi.h> |