diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-01-17 22:29:11 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-01-17 22:29:11 -0500 |
| commit | 12ba8571ab6b232f5facef6b1dd28c5ebc2b530a (patch) | |
| tree | 8df2d122d62bf93916558dc4b59e342276a8b5d4 | |
| parent | 901b2082b51d4f1c6deac5d5264a744b793ed46f (diff) | |
| parent | c7662fc59ca38517e0ec04ceaa123ed8209ab6bf (diff) | |
Merge tag 'clk-fixes-for-linus' of git://git.linaro.org/people/mike.turquette/linux
Pull clock driver fixes from Mike Turquette:
"Small number of fixes for clock drivers and a single null pointer
dereference fix in the framework core code.
The driver fixes vary from fixing section mismatch warnings to
preventing machines from hanging (and preventing developers from
crying)"
* tag 'clk-fixes-for-linus' of git://git.linaro.org/people/mike.turquette/linux:
clk: fix possible null pointer dereference
Revert "clk: ppc-corenet: Fix Section mismatch warning"
clk: rockchip: fix deadlock possibility in cpuclk
clk: berlin: bg2q: remove non-exist "smemc" gate clock
clk: at91: keep slow clk enabled to prevent system hang
clk: rockchip: fix rk3288 cpuclk core dividers
clk: rockchip: fix rk3066 pll lock bit location
clk: rockchip: Fix clock gate for rk3188 hclk_emem_peri
clk: rockchip: add CLK_IGNORE_UNUSED flag to fix rk3066/rk3188 USB Host
| -rw-r--r-- | drivers/clk/at91/clk-slow.c | 27 | ||||
| -rw-r--r-- | drivers/clk/berlin/bg2q.c | 1 | ||||
| -rw-r--r-- | drivers/clk/clk-ppc-corenet.c | 2 | ||||
| -rw-r--r-- | drivers/clk/clk.c | 2 | ||||
| -rw-r--r-- | drivers/clk/rockchip/clk-cpu.c | 10 | ||||
| -rw-r--r-- | drivers/clk/rockchip/clk-rk3188.c | 27 | ||||
| -rw-r--r-- | drivers/clk/rockchip/clk-rk3288.c | 28 |
7 files changed, 69 insertions, 28 deletions
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c index 32f7c1b36204..2f13bd5246b5 100644 --- a/drivers/clk/at91/clk-slow.c +++ b/drivers/clk/at91/clk-slow.c | |||
| @@ -70,6 +70,7 @@ struct clk_sam9x5_slow { | |||
| 70 | 70 | ||
| 71 | #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) | 71 | #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) |
| 72 | 72 | ||
| 73 | static struct clk *slow_clk; | ||
| 73 | 74 | ||
| 74 | static int clk_slow_osc_prepare(struct clk_hw *hw) | 75 | static int clk_slow_osc_prepare(struct clk_hw *hw) |
| 75 | { | 76 | { |
| @@ -357,6 +358,8 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr, | |||
| 357 | clk = clk_register(NULL, &slowck->hw); | 358 | clk = clk_register(NULL, &slowck->hw); |
| 358 | if (IS_ERR(clk)) | 359 | if (IS_ERR(clk)) |
| 359 | kfree(slowck); | 360 | kfree(slowck); |
| 361 | else | ||
| 362 | slow_clk = clk; | ||
| 360 | 363 | ||
| 361 | return clk; | 364 | return clk; |
| 362 | } | 365 | } |
| @@ -433,6 +436,8 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, | |||
| 433 | clk = clk_register(NULL, &slowck->hw); | 436 | clk = clk_register(NULL, &slowck->hw); |
| 434 | if (IS_ERR(clk)) | 437 | if (IS_ERR(clk)) |
| 435 | kfree(slowck); | 438 | kfree(slowck); |
| 439 | else | ||
| 440 | slow_clk = clk; | ||
| 436 | 441 | ||
| 437 | return clk; | 442 | return clk; |
| 438 | } | 443 | } |
| @@ -465,3 +470,25 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np, | |||
| 465 | 470 | ||
| 466 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | 471 | of_clk_add_provider(np, of_clk_src_simple_get, clk); |
| 467 | } | 472 | } |
| 473 | |||
| 474 | /* | ||
| 475 | * FIXME: All slow clk users are not properly claiming it (get + prepare + | ||
| 476 | * enable) before using it. | ||
| 477 | * If all users properly claiming this clock decide that they don't need it | ||
| 478 | * anymore (or are removed), it is disabled while faulty users are still | ||
| 479 | * requiring it, and the system hangs. | ||
| 480 | * Prevent this clock from being disabled until all users are properly | ||
| 481 | * requesting it. | ||
| 482 | * Once this is done we should remove this function and the slow_clk variable. | ||
| 483 | */ | ||
| 484 | static int __init of_at91_clk_slow_retain(void) | ||
| 485 | { | ||
| 486 | if (!slow_clk) | ||
| 487 | return 0; | ||
| 488 | |||
| 489 | __clk_get(slow_clk); | ||
| 490 | clk_prepare_enable(slow_clk); | ||
| 491 | |||
| 492 | return 0; | ||
| 493 | } | ||
| 494 | arch_initcall(of_at91_clk_slow_retain); | ||
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c index 21784e4eb3f0..440ef81ab15c 100644 --- a/drivers/clk/berlin/bg2q.c +++ b/drivers/clk/berlin/bg2q.c | |||
| @@ -285,7 +285,6 @@ static const struct berlin2_gate_data bg2q_gates[] __initconst = { | |||
| 285 | { "pbridge", "perif", 15, CLK_IGNORE_UNUSED }, | 285 | { "pbridge", "perif", 15, CLK_IGNORE_UNUSED }, |
| 286 | { "sdio", "perif", 16, CLK_IGNORE_UNUSED }, | 286 | { "sdio", "perif", 16, CLK_IGNORE_UNUSED }, |
| 287 | { "nfc", "perif", 18 }, | 287 | { "nfc", "perif", 18 }, |
| 288 | { "smemc", "perif", 19 }, | ||
| 289 | { "pcie", "perif", 22 }, | 288 | { "pcie", "perif", 22 }, |
| 290 | }; | 289 | }; |
| 291 | 290 | ||
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-ppc-corenet.c index b6e6c85507a5..0a47d6f49cd6 100644 --- a/drivers/clk/clk-ppc-corenet.c +++ b/drivers/clk/clk-ppc-corenet.c | |||
| @@ -291,7 +291,7 @@ static const struct of_device_id ppc_clk_ids[] __initconst = { | |||
| 291 | {} | 291 | {} |
| 292 | }; | 292 | }; |
| 293 | 293 | ||
| 294 | static struct platform_driver ppc_corenet_clk_driver __initdata = { | 294 | static struct platform_driver ppc_corenet_clk_driver = { |
| 295 | .driver = { | 295 | .driver = { |
| 296 | .name = "ppc_corenet_clock", | 296 | .name = "ppc_corenet_clock", |
| 297 | .of_match_table = ppc_clk_ids, | 297 | .of_match_table = ppc_clk_ids, |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f4963b7d4e17..d48ac71c6c8b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
| @@ -1366,7 +1366,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) | |||
| 1366 | new_rate = clk->ops->determine_rate(clk->hw, rate, | 1366 | new_rate = clk->ops->determine_rate(clk->hw, rate, |
| 1367 | &best_parent_rate, | 1367 | &best_parent_rate, |
| 1368 | &parent_hw); | 1368 | &parent_hw); |
| 1369 | parent = parent_hw->clk; | 1369 | parent = parent_hw ? parent_hw->clk : NULL; |
| 1370 | } else if (clk->ops->round_rate) { | 1370 | } else if (clk->ops->round_rate) { |
| 1371 | new_rate = clk->ops->round_rate(clk->hw, rate, | 1371 | new_rate = clk->ops->round_rate(clk->hw, rate, |
| 1372 | &best_parent_rate); | 1372 | &best_parent_rate); |
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 75c8c45ef728..8539c4fd34cc 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c | |||
| @@ -124,10 +124,11 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, | |||
| 124 | { | 124 | { |
| 125 | const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; | 125 | const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; |
| 126 | unsigned long alt_prate, alt_div; | 126 | unsigned long alt_prate, alt_div; |
| 127 | unsigned long flags; | ||
| 127 | 128 | ||
| 128 | alt_prate = clk_get_rate(cpuclk->alt_parent); | 129 | alt_prate = clk_get_rate(cpuclk->alt_parent); |
| 129 | 130 | ||
| 130 | spin_lock(cpuclk->lock); | 131 | spin_lock_irqsave(cpuclk->lock, flags); |
| 131 | 132 | ||
| 132 | /* | 133 | /* |
| 133 | * If the old parent clock speed is less than the clock speed | 134 | * If the old parent clock speed is less than the clock speed |
| @@ -164,7 +165,7 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, | |||
| 164 | cpuclk->reg_base + reg_data->core_reg); | 165 | cpuclk->reg_base + reg_data->core_reg); |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | spin_unlock(cpuclk->lock); | 168 | spin_unlock_irqrestore(cpuclk->lock, flags); |
| 168 | return 0; | 169 | return 0; |
| 169 | } | 170 | } |
| 170 | 171 | ||
| @@ -173,6 +174,7 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, | |||
| 173 | { | 174 | { |
| 174 | const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; | 175 | const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; |
| 175 | const struct rockchip_cpuclk_rate_table *rate; | 176 | const struct rockchip_cpuclk_rate_table *rate; |
| 177 | unsigned long flags; | ||
| 176 | 178 | ||
| 177 | rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate); | 179 | rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate); |
| 178 | if (!rate) { | 180 | if (!rate) { |
| @@ -181,7 +183,7 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, | |||
| 181 | return -EINVAL; | 183 | return -EINVAL; |
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | spin_lock(cpuclk->lock); | 186 | spin_lock_irqsave(cpuclk->lock, flags); |
| 185 | 187 | ||
| 186 | if (ndata->old_rate < ndata->new_rate) | 188 | if (ndata->old_rate < ndata->new_rate) |
| 187 | rockchip_cpuclk_set_dividers(cpuclk, rate); | 189 | rockchip_cpuclk_set_dividers(cpuclk, rate); |
| @@ -201,7 +203,7 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, | |||
| 201 | if (ndata->old_rate > ndata->new_rate) | 203 | if (ndata->old_rate > ndata->new_rate) |
| 202 | rockchip_cpuclk_set_dividers(cpuclk, rate); | 204 | rockchip_cpuclk_set_dividers(cpuclk, rate); |
| 203 | 205 | ||
| 204 | spin_unlock(cpuclk->lock); | 206 | spin_unlock_irqrestore(cpuclk->lock, flags); |
| 205 | return 0; | 207 | return 0; |
| 206 | } | 208 | } |
| 207 | 209 | ||
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index c54078960847..7eb684c50d42 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c | |||
| @@ -210,6 +210,17 @@ PNAME(mux_sclk_hsadc_p) = { "hsadc_src", "hsadc_frac", "ext_hsadc" }; | |||
| 210 | PNAME(mux_mac_p) = { "gpll", "dpll" }; | 210 | PNAME(mux_mac_p) = { "gpll", "dpll" }; |
| 211 | PNAME(mux_sclk_macref_p) = { "mac_src", "ext_rmii" }; | 211 | PNAME(mux_sclk_macref_p) = { "mac_src", "ext_rmii" }; |
| 212 | 212 | ||
| 213 | static struct rockchip_pll_clock rk3066_pll_clks[] __initdata = { | ||
| 214 | [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), | ||
| 215 | RK2928_MODE_CON, 0, 5, 0, rk3188_pll_rates), | ||
| 216 | [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4), | ||
| 217 | RK2928_MODE_CON, 4, 4, 0, NULL), | ||
| 218 | [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8), | ||
| 219 | |||
