| .. | .. |
|---|
| 24 | 24 | #include <linux/rational.h> |
|---|
| 25 | 25 | #include "clk.h" |
|---|
| 26 | 26 | |
|---|
| 27 | +#ifdef MODULE |
|---|
| 28 | +static HLIST_HEAD(clk_ctx_list); |
|---|
| 29 | +#endif |
|---|
| 30 | + |
|---|
| 27 | 31 | /** |
|---|
| 28 | 32 | * Register a clock branch. |
|---|
| 29 | 33 | * Most clock branches have a form like |
|---|
| .. | .. |
|---|
| 185 | 189 | struct clk_hw *p_parent; |
|---|
| 186 | 190 | unsigned long scale; |
|---|
| 187 | 191 | |
|---|
| 192 | + if (rate == 0) { |
|---|
| 193 | + pr_warn("%s p_rate(%ld), rate(%ld), maybe invalid frequency setting!\n", |
|---|
| 194 | + clk_hw_get_name(hw), *parent_rate, rate); |
|---|
| 195 | + *m = 0; |
|---|
| 196 | + *n = 1; |
|---|
| 197 | + return; |
|---|
| 198 | + } |
|---|
| 199 | + |
|---|
| 188 | 200 | p_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); |
|---|
| 189 | 201 | if ((rate * 20 > p_rate) && (p_rate % rate != 0)) { |
|---|
| 190 | 202 | p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); |
|---|
| .. | .. |
|---|
| 221 | 233 | * for m and n. In the result it will be the nearest rate left shifted |
|---|
| 222 | 234 | * by (scale - fd->nwidth) bits. |
|---|
| 223 | 235 | */ |
|---|
| 236 | + if (*parent_rate == 0) { |
|---|
| 237 | + pr_warn("%s p_rate(%ld), rate(%ld), maybe invalid frequency setting!\n", |
|---|
| 238 | + clk_hw_get_name(hw), *parent_rate, rate); |
|---|
| 239 | + *m = 0; |
|---|
| 240 | + *n = 1; |
|---|
| 241 | + return; |
|---|
| 242 | + } |
|---|
| 224 | 243 | scale = fls_long(*parent_rate / rate - 1); |
|---|
| 225 | 244 | if (scale > fd->nwidth) |
|---|
| 226 | 245 | rate <<= scale - fd->nwidth; |
|---|
| .. | .. |
|---|
| 417 | 436 | "rockchip,grf"); |
|---|
| 418 | 437 | ctx->pmugrf = syscon_regmap_lookup_by_phandle(ctx->cru_node, |
|---|
| 419 | 438 | "rockchip,pmugrf"); |
|---|
| 439 | + |
|---|
| 440 | +#ifdef MODULE |
|---|
| 441 | + hlist_add_head(&ctx->list_node, &clk_ctx_list); |
|---|
| 442 | +#endif |
|---|
| 420 | 443 | |
|---|
| 421 | 444 | return ctx; |
|---|
| 422 | 445 | |
|---|
| .. | .. |
|---|
| 783 | 806 | |
|---|
| 784 | 807 | } |
|---|
| 785 | 808 | EXPORT_SYMBOL_GPL(rockchip_clk_unprotect); |
|---|
| 809 | + |
|---|
| 810 | +void rockchip_clk_disable_unused(void) |
|---|
| 811 | +{ |
|---|
| 812 | + struct rockchip_clk_provider *ctx; |
|---|
| 813 | + struct clk *clk; |
|---|
| 814 | + struct clk_hw *hw; |
|---|
| 815 | + int i = 0, flag = 0; |
|---|
| 816 | + |
|---|
| 817 | + hlist_for_each_entry(ctx, &clk_ctx_list, list_node) { |
|---|
| 818 | + for (i = 0; i < ctx->clk_data.clk_num; i++) { |
|---|
| 819 | + clk = ctx->clk_data.clks[i]; |
|---|
| 820 | + if (clk && !IS_ERR(clk)) { |
|---|
| 821 | + hw = __clk_get_hw(clk); |
|---|
| 822 | + if (hw) |
|---|
| 823 | + flag = clk_hw_get_flags(hw); |
|---|
| 824 | + if (flag & CLK_IGNORE_UNUSED) |
|---|
| 825 | + continue; |
|---|
| 826 | + if (flag & CLK_IS_CRITICAL) |
|---|
| 827 | + continue; |
|---|
| 828 | + clk_prepare_enable(clk); |
|---|
| 829 | + clk_disable_unprepare(clk); |
|---|
| 830 | + } |
|---|
| 831 | + } |
|---|
| 832 | + } |
|---|
| 833 | +} |
|---|
| 834 | +EXPORT_SYMBOL_GPL(rockchip_clk_disable_unused); |
|---|
| 786 | 835 | #endif /* MODULE */ |
|---|