diff options
-rw-r--r-- | drivers/clk/rockchip/clk-cpu.c | 1 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-pll.c | 321 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-px30.c | 2 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3308.c | 2 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.c | 5 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.h | 35 |
6 files changed, 253 insertions, 113 deletions
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 7b623ddb3086..0e986bb4f28e 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -286,6 +286,7 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, goto free_cpuclk; } cpuclk->pll_hw = __clk_get_hw(pll_clk); + rockchip_boost_init(cpuclk->pll_hw); } cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]); diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index addcdb07553a..2426582ad23a 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -26,6 +26,7 @@ #include <linux/regmap.h> #include <linux/clk.h> #include <linux/gcd.h> +#include <linux/mfd/syscon.h> #include "clk.h" #define PLL_MODE_MASK 0x3 @@ -52,9 +53,13 @@ struct rockchip_clk_pll { int sel; unsigned long scaling; spinlock_t *lock; - bool boost_enabled; struct rockchip_clk_provider *ctx; + + bool boost_enabled; + unsigned long boost_low_rate; + unsigned long boost_high_rate; + struct regmap *boost; #ifdef CONFIG_DEBUG_FS struct hlist_node debug_node; #endif @@ -69,6 +74,7 @@ static void rockchip_rk3366_pll_get_params(struct rockchip_clk_pll *pll, struct rockchip_pll_rate_table *rate); static int rockchip_rk3366_pll_set_params(struct rockchip_clk_pll *pll, const struct rockchip_pll_rate_table *rate); +static void rockchip_boost_disable_low(struct rockchip_clk_pll *pll); #define MHZ (1000UL * 1000UL) #define KHZ (1000UL) @@ -387,65 +393,6 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) return -ETIMEDOUT; } -void rockchip_boost_enable_recovery_sw_low(struct clk_hw *hw) -{ - struct rockchip_clk_pll *pll; - struct regmap *boost; - unsigned int val; - - if (!hw) - return; - pll = to_rockchip_clk_pll(hw); - if (!pll->boost_enabled || IS_ERR(pll->ctx->boost)) - return; - - boost = pll->ctx->boost; - regmap_write(boost, BOOST_BOOST_CON, - HIWORD_UPDATE(1, BOOST_RECOVERY_MASK, - BOOST_RECOVERY_SHIFT)); - do { - regmap_read(boost, BOOST_FSM_STATUS, &val); - } while (!(val & BOOST_BUSY_STATE)); - - regmap_write(boost, BOOST_BOOST_CON, - HIWORD_UPDATE(1, BOOST_SW_CTRL_MASK, - BOOST_SW_CTRL_SHIFT) | - HIWORD_UPDATE(1, BOOST_LOW_FREQ_EN_MASK, - BOOST_LOW_FREQ_EN_SHIFT)); -} - -void rockchip_boost_disable_low(struct rockchip_clk_pll *pll) -{ - struct regmap *boost = pll->ctx->boost; - - if (!pll->boost_enabled || IS_ERR(boost)) - return; - - regmap_write(boost, BOOST_BOOST_CON, - HIWORD_UPDATE(0, BOOST_LOW_FREQ_EN_MASK, - BOOST_LOW_FREQ_EN_SHIFT)); -} - -void rockchip_boost_disable_recovery_sw(struct clk_hw *hw) -{ - struct rockchip_clk_pll *pll; - struct regmap *boost; - - if (!hw) - return; - pll = to_rockchip_clk_pll(hw); - if (!pll->boost_enabled || IS_ERR(pll->ctx->boost)) - return; - - boost = pll->ctx->boost; - regmap_write(boost, BOOST_BOOST_CON, - HIWORD_UPDATE(0, BOOST_RECOVERY_MASK, - BOOST_RECOVERY_SHIFT)); - regmap_write(boost, BOOST_BOOST_CON, - HIWORD_UPDATE(0, BOOST_SW_CTRL_MASK, - BOOST_SW_CTRL_SHIFT)); -} - /** * PLL used in RK3036 */ @@ -466,6 +413,30 @@ void rockchip_boost_disable_recovery_sw(struct clk_hw *hw) #define RK3036_PLLCON1_PWRDOWN (1 << 13) +static unsigned long +rockchip_rk3036_pll_con_to_rate(struct rockchip_clk_pll *pll, + u32 con0, u32 con1) +{ + unsigned int fbdiv, postdiv1, refdiv, postdiv2; + u64 rate64 = 24000000; + + fbdiv = ((con0 >> RK3036_PLLCON0_FBDIV_SHIFT) & + RK3036_PLLCON0_FBDIV_MASK); + postdiv1 = ((con0 >> RK3036_PLLCON0_POSTDIV1_SHIFT) & + RK3036_PLLCON0_POSTDIV1_MASK); + refdiv = ((con1 >> RK3036_PLLCON1_REFDIV_SHIFT) & + RK3036_PLLCON1_REFDIV_MASK); + postdiv2 = ((con1 >> RK3036_PLLCON1_POSTDIV2_SHIFT) & + RK3036_PLLCON1_POSTDIV2_MASK); + + rate64 *= fbdiv; + do_div(rate64, refdiv); + do_div(rate64, postdiv1); + do_div(rate64, postdiv2); + + return (unsigned long)rate64; +} + static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, struct rockchip_pll_rate_table *rate) { @@ -1398,8 +1369,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, u8 num_parents, int con_offset, int grf_lock_offset, int lock_shift, int mode_offset, int mode_shift, struct rockchip_pll_rate_table *rate_table, - unsigned long flags, u8 clk_pll_flags, - bool boost_enabled) + unsigned long flags, u8 clk_pll_flags) { const char *pll_parents[3]; struct clk_init_data init; @@ -1524,7 +1494,6 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, pll->flags = clk_pll_flags; pll->lock = &ctx->lock; pll->ctx = ctx; - pll->boost_enabled = boost_enabled; pll_clk = clk_register(NULL, &pll->hw); if (IS_ERR(pll_clk)) { @@ -1533,14 +1502,6 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, goto err_pll; } -#ifdef CONFIG_DEBUG_FS - if (boost_enabled && !IS_ERR(ctx->boost)) { - mutex_lock(&clk_boost_lock); - hlist_add_head(&pll->debug_node, &clk_boost_list); - mutex_unlock(&clk_boost_lock); - } -#endif - return mux_clk; err_pll: @@ -1551,36 +1512,198 @@ err_mux: return mux_clk; } +static unsigned long rockchip_pll_con_to_rate(struct rockchip_clk_pll *pll, + u32 con0, u32 con1) +{ + switch (pll->type) { + case pll_rk3036: + case pll_rk3328: + return rockchip_rk3036_pll_con_to_rate(pll, con0, con1); + case pll_rk3066: + break; + case pll_rk3366: + break; + case pll_rk3399: + break; + default: + pr_warn("%s: Unknown pll type\n", __func__); + } + + return 0; +} + +void rockchip_boost_init(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll; + struct device_node *np; + u32 value, con0, con1; + + if (!hw) + return; + pll = to_rockchip_clk_pll(hw); + np = of_parse_phandle(pll->ctx->cru_node, "rockchip,boost", 0); + if (!np) { + pr_debug("%s: failed to get boost np\n", __func__); + return; + } + pll->boost = syscon_node_to_regmap(np); + if (IS_ERR(pll->boost)) { + pr_debug("%s: failed to get boost regmap\n", __func__); + return; + } + + if (!of_property_read_u32(np, "rockchip,boost-low-con0", &con0) && + !of_property_read_u32(np, "rockchip,boost-low-con1", &con1)) { + pr_debug("boost-low-con=0x%x 0x%x\n", con0, con1); + regmap_write(pll->boost, BOOST_PLL_L_CON(0), + HIWORD_UPDATE(con0, BOOST_PLL_CON_MASK, 0)); + regmap_write(pll->boost, BOOST_PLL_L_CON(1), + HIWORD_UPDATE(con1, BOOST_PLL_CON_MASK, 0)); + pll->boost_low_rate = rockchip_pll_con_to_rate(pll, con0, + con1); + pr_debug("boost-low-rate=%lu\n", pll->boost_low_rate); + } + if (!of_property_read_u32(np, "rockchip,boost-high-con0", &con0) && + !of_property_read_u32(np, "rockchip,boost-high-con1", &con1)) { + pr_debug("boost-high-con=0x%x 0x%x\n", con0, con1); + regmap_write(pll->boost, BOOST_PLL_H_CON(0), + HIWORD_UPDATE(con0, BOOST_PLL_CON_MASK, 0)); + regmap_write(pll->boost, BOOST_PLL_H_CON(1), + HIWORD_UPDATE(con1, BOOST_PLL_CON_MASK, 0)); + pll->boost_high_rate = rockchip_pll_con_to_rate(pll, con0, + con1); + pr_debug("boost-high-rate=%lu\n", pll->boost_high_rate); + } + if (!of_property_read_u32(np, "rockchip,boost-backup-pll", &value)) { + pr_debug("boost-backup-pll=0x%x\n", value); + regmap_write(pll->boost, BOOST_CLK_CON, + HIWORD_UPDATE(value, BOOST_BACKUP_PLL_MASK, + BOOST_BACKUP_PLL_SHIFT)); + } + if (!of_property_read_u32(np, "rockchip,boost-backup-pll-usage", + &value)) { + pr_debug("boost-backup-pll-usage=0x%x\n", value); + regmap_write(pll->boost, BOOST_CLK_CON, + HIWORD_UPDATE(value, BOOST_BACKUP_PLL_USAGE_MASK, + BOOST_BACKUP_PLL_USAGE_SHIFT)); + } + if (!of_property_read_u32(np, "rockchip,boost-switch-threshold", + &value)) { + pr_debug("boost-switch-threshold=0x%x\n", value); + regmap_write(pll->boost, BOOST_SWITCH_THRESHOLD, value); + } + if (!of_property_read_u32(np, "rockchip,boost-statis-threshold", + &value)) { + pr_debug("boost-statis-threshold=0x%x\n", value); + regmap_write(pll->boost, BOOST_STATIS_THRESHOLD, value); + } + if (!of_property_read_u32(np, "rockchip,boost-statis-enable", + &value)) { + pr_debug("boost-statis-enable=0x%x\n", value); + regmap_write(pll->boost, BOOST_BOOST_CON, + HIWORD_UPDATE(value, BOOST_STATIS_ENABLE_MASK, + BOOST_STATIS_ENABLE_SHIFT)); + } + if (!of_property_read_u32(np, "rockchip,boost-enable", &value)) { + pr_debug("boost-enable=0x%x\n", value); + regmap_write(pll->boost, BOOST_BOOST_CON, + HIWORD_UPDATE(value, BOOST_ENABLE_MASK, + BOOST_ENABLE_SHIFT)); + if (value) + pll->boost_enabled = true; + } +#ifdef CONFIG_DEBUG_FS + if (pll->boost_enabled) { + mutex_lock(&clk_boost_lock); + hlist_add_head(&pll->debug_node, &clk_boost_list); + mutex_unlock(&clk_boost_lock); + } +#endif +} + +void rockchip_boost_enable_recovery_sw_low(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll; + unsigned int val; + + if (!hw) + return; + pll = to_rockchip_clk_pll(hw); + if (!pll->boost_enabled) + return; + + regmap_write(pll->boost, BOOST_BOOST_CON, + HIWORD_UPDATE(1, BOOST_RECOVERY_MASK, + BOOST_RECOVERY_SHIFT)); + do { + regmap_read(pll->boost, BOOST_FSM_STATUS, &val); + } while (!(val & BOOST_BUSY_STATE)); + + regmap_write(pll->boost, BOOST_BOOST_CON, + HIWORD_UPDATE(1, BOOST_SW_CTRL_MASK, + BOOST_SW_CTRL_SHIFT) | + HIWORD_UPDATE(1, BOOST_LOW_FREQ_EN_MASK, + BOOST_LOW_FREQ_EN_SHIFT)); +} + +static void rockchip_boost_disable_low(struct rockchip_clk_pll *pll) +{ + if (!pll->boost_enabled) + return; + + regmap_write(pll->boost, BOOST_BOOST_CON, + HIWORD_UPDATE(0, BOOST_LOW_FREQ_EN_MASK, + BOOST_LOW_FREQ_EN_SHIFT)); +} + +void rockchip_boost_disable_recovery_sw(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll; + + if (!hw) + return; + pll = to_rockchip_clk_pll(hw); + if (!pll->boost_enabled) + return; + + regmap_write(pll->boost, BOOST_BOOST_CON, + HIWORD_UPDATE(0, BOOST_RECOVERY_MASK, + BOOST_RECOVERY_SHIFT)); + regmap_write(pll->boost, BOOST_BOOST_CON, + HIWORD_UPDATE(0, BOOST_SW_CTRL_MASK, + BOOST_SW_CTRL_SHIFT)); +} + #ifdef CONFIG_DEBUG_FS #include <linux/debugfs.h> static int boost_summary_show(struct seq_file *s, void *data) { struct rockchip_clk_pll *pll = (struct rockchip_clk_pll *)s->private; - struct regmap *boost = pll->ctx->boost; u32 boost_count = 0; u32 freq_cnt0 = 0, freq_cnt1 = 0; - u64 high_freq_time = 0; + u64 freq_cnt = 0, high_freq_time = 0; u32 short_count = 0, short_threshold = 0; u32 interval_time = 0; - seq_puts(s, " device boost_count high_freq_time(us) short_count short_threshold interval_time\n"); - seq_puts(s, "------------------------------------------------------------------------------------------\n"); + seq_puts(s, " device boost_count high_freq_count high_freq_time short_count short_threshold interval_count\n"); + seq_puts(s, "------------------------------------------------------------------------------------------------------\n"); seq_printf(s, " %s\n", clk_hw_get_name(&pll->hw)); - regmap_read(boost, BOOST_SWITCH_CNT, &boost_count); + regmap_read(pll->boost, BOOST_SWITCH_CNT, &boost_count); - regmap_read(boost, BOOST_HIGH_PERF_CNT0, &freq_cnt0); - regmap_read(boost, BOOST_HIGH_PERF_CNT1, &freq_cnt1); - high_freq_time = ((u64)freq_cnt1 << 32) + (u64)freq_cnt0; + regmap_read(pll->boost, BOOST_HIGH_PERF_CNT0, &freq_cnt0); + regmap_read(pll->boost, BOOST_HIGH_PERF_CNT1, &freq_cnt1); + freq_cnt = ((u64)freq_cnt1 << 32) + (u64)freq_cnt0; + high_freq_time = freq_cnt; do_div(high_freq_time, 24); - regmap_read(boost, BOOST_SHORT_SWITCH_CNT, &short_count); - regmap_read(boost, BOOST_STATIS_THRESHOLD, &short_threshold); - regmap_read(boost, BOOST_SWITCH_THRESHOLD, &interval_time); + regmap_read(pll->boost, BOOST_SHORT_SWITCH_CNT, &short_count); + regmap_read(pll->boost, BOOST_STATIS_THRESHOLD, &short_threshold); + regmap_read(pll->boost, BOOST_SWITCH_THRESHOLD, &interval_time); - seq_printf(s, "%21u %20llu %13u %17u %15u\n", - boost_count, high_freq_time, short_count, + seq_printf(s, "%22u %17llu %15llu %12u %16u %15u\n", + boost_count, freq_cnt, high_freq_time, short_count, short_threshold, interval_time); return 0; @@ -1598,6 +1721,29 @@ static const struct file_operations boost_summary_fops = { .release = single_release, }; +static int boost_config_show(struct seq_file *s, void *data) +{ + struct rockchip_clk_pll *pll = (struct rockchip_clk_pll *)s->private; + + seq_printf(s, "boost_enabled: %d\n", pll->boost_enabled); + seq_printf(s, "boost_low_rate: %lu\n", pll->boost_low_rate); + seq_printf(s, "boost_high_rate: %lu\n", pll->boost_high_rate); + + return 0; +} + +static int boost_config_open(struct inode *inode, struct file *file) +{ + return single_open(file, boost_config_show, inode->i_private); +} + +static const struct file_operations boost_config_fops = { + .open = boost_config_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int boost_debug_create_one(struct rockchip_clk_pll *pll, struct dentry *rootdir) { @@ -1617,6 +1763,13 @@ static int boost_debug_create_one(struct rockchip_clk_pll *pll, return -ENOMEM; } + d = debugfs_create_file("boost_config", 0444, pdentry, + pll, &boost_config_fops); + if (!d) { + pr_err("%s: failed to create boost config file\n", __func__); + return -ENOMEM; + } + return 0; } diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c index 9b340f5926cd..52a75e12f433 100644 --- a/drivers/clk/rockchip/clk-px30.c +++ b/drivers/clk/rockchip/clk-px30.c @@ -191,7 +191,7 @@ PNAME(mux_usbphy_ref_p) = { "xin24m", "clk_ref24m_pmu" }; PNAME(mux_mipidsiphy_ref_p) = { "xin24m", "clk_ref24m_pmu" }; static struct rockchip_pll_clock px30_pll_clks[] __initdata = { - [apll] = PLL_BOOST(pll_rk3328, PLL_APLL, "apll", mux_pll_p, + [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p, 0, PX30_PLL_CON(0), PX30_MODE_CON, 0, 0, 0, px30_pll_rates), [dpll] = PLL(pll_rk3328, PLL_DPLL, "dpll", mux_pll_p, diff --git a/drivers/clk/rockchip/clk-rk3308.c b/drivers/clk/rockchip/clk-rk3308.c index 79f6f98c49ac..0cd2928ee94f 100644 --- a/drivers/clk/rockchip/clk-rk3308.c +++ b/drivers/clk/rockchip/clk-rk3308.c @@ -190,7 +190,7 @@ PNAME(mux_spdif_rx_src_p) = { "clk_spdif_rx_div", "clk_spdif_rx_div50" }; PNAME(mux_spdif_rx_p) = { "clk_spdif_rx_src", "clk_spdif_rx_frac" }; static struct rockchip_pll_clock rk3308_pll_clks[] __initdata = { - [apll] = PLL_BOOST(pll_rk3328, PLL_APLL, "apll", mux_pll_p, + [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p, 0, RK3308_PLL_CON(0), RK3308_MODE_CON, 0, 0, 0, rk3308_pll_rates), [dpll] = PLL(pll_rk3328, PLL_DPLL, "dpll", mux_pll_p, diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index b187fae83991..b90f21731d5e 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -410,8 +410,6 @@ struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, spin_lock_init(&ctx->lock); ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, "rockchip,grf"); - ctx->boost = syscon_regmap_lookup_by_phandle(ctx->cru_node, - "rockchip,boost"); return ctx; @@ -455,8 +453,7 @@ void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, list->con_offset, grf_lock_offset, list->lock_shift, list->mode_offset, list->mode_shift, list->rate_table, - list->flags, list->pll_flags, - list->boost_enabled); + list->flags, list->pll_flags); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 7ef87aad40d2..6db1e7a66f19 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -45,12 +45,21 @@ struct clk; #define BOOST_SWITCH_THRESHOLD 0x0024 #define BOOST_FSM_STATUS 0x0028 #define BOOST_PLL_L_CON(x) ((x) * 0x4 + 0x2c) +#define BOOST_PLL_CON_MASK 0xffff +#define BOOST_BACKUP_PLL_MASK 0x3 +#define BOOST_BACKUP_PLL_SHIFT 8 +#define BOOST_BACKUP_PLL_USAGE_MASK 0x1 +#define BOOST_BACKUP_PLL_USAGE_SHIFT 12 +#define BOOST_ENABLE_MASK 0x1 +#define BOOST_ENABLE_SHIFT 0 #define BOOST_RECOVERY_MASK 0x1 #define BOOST_RECOVERY_SHIFT 1 #define BOOST_SW_CTRL_MASK 0x1 #define BOOST_SW_CTRL_SHIFT 2 #define BOOST_LOW_FREQ_EN_MASK 0x1 #define BOOST_LOW_FREQ_EN_SHIFT 3 +#define BOOST_STATIS_ENABLE_MASK 0x1 +#define BOOST_STATIS_ENABLE_SHIFT 4 #define BOOST_BUSY_STATE BIT(8) #define PX30_PLL_CON(x) ((x) * 0x4) @@ -261,7 +270,6 @@ struct rockchip_clk_provider { struct clk_onecell_data clk_data; struct device_node *cru_node; struct regmap *grf; - struct regmap *boost; spinlock_t lock; }; @@ -294,7 +302,6 @@ struct rockchip_pll_rate_table { * @type: Type of PLL to be registered. * @pll_flags: hardware-specific flags * @rate_table: Table of usable pll rates - * @boost_enabled: whether pll supports boost * * Flags: * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the @@ -313,7 +320,6 @@ struct rockchip_pll_clock { enum rockchip_pll_type type; u8 pll_flags; struct rockchip_pll_rate_table *rate_table; - bool boost_enabled; }; #define ROCKCHIP_PLL_SYNC_RATE BIT(0) @@ -335,32 +341,15 @@ struct rockchip_pll_clock { .rate_table = _rtable, \ } -#define PLL_BOOST(_type, _id, _name, _pnames, _flags, _con, _mode, \ - _mshift, _lshift, _pflags, _rtable) \ - { \ - .id = _id, \ - .type = _type, \ - .name = _name, \ - .parent_names = _pnames, \ - .num_parents = ARRAY_SIZE(_pnames), \ - .flags = CLK_GET_RATE_NOCACHE | _flags, \ - .con_offset = _con, \ - .mode_offset = _mode, \ - .mode_shift = _mshift, \ - .lock_shift = _lshift, \ - .pll_flags = _pflags, \ - .rate_table = _rtable, \ - .boost_enabled = true, \ - } - struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, enum rockchip_pll_type pll_type, const char *name, const char *const *parent_names, u8 num_parents, int con_offset, int grf_lock_offset, int lock_shift, int mode_offset, int mode_shift, struct rockchip_pll_rate_table *rate_table, - unsigned long flags, u8 clk_pll_flags, - bool boost_enabled); + unsigned long flags, u8 clk_pll_flags); + +void rockchip_boost_init(struct clk_hw *hw); void rockchip_boost_enable_recovery_sw_low(struct clk_hw *hw); |