Loading drivers/clk/msm/clock-local2.c +43 −0 Original line number Diff line number Diff line Loading @@ -346,6 +346,48 @@ static void disable_unprepare_rcg_srcs(struct clk *c, struct clk *curr, clk_unprepare(curr); } static int rcg_clk_set_duty_cycle(struct clk *c, u32 numerator, u32 denominator) { struct rcg_clk *rcg = to_rcg_clk(c); u32 notn_m_val, n_val, m_val, d_val, not2d_val; u32 max_n_value; if (!numerator || numerator == denominator) return -EINVAL; if (!rcg->mnd_reg_width) rcg->mnd_reg_width = 8; max_n_value = 1 << (rcg->mnd_reg_width - 1); notn_m_val = readl_relaxed(N_REG(rcg)); m_val = readl_relaxed(M_REG(rcg)); n_val = ((~notn_m_val) + m_val) & BM((rcg->mnd_reg_width - 1), 0); if (n_val > max_n_value) { pr_warn("%s duty-cycle cannot be set for required frequency %ld\n", c->dbg_name, clk_get_rate(c)); return -EINVAL; } /* Calculate the 2d value */ d_val = DIV_ROUND_CLOSEST((numerator * n_val * 2), denominator); /* Check BIT WIDTHS OF 2d. If D is too big reduce Duty cycle. */ if (d_val > (BIT(rcg->mnd_reg_width) - 1)) { d_val = (BIT(rcg->mnd_reg_width) - 1) / 2; d_val *= 2; } not2d_val = (~d_val) & BM((rcg->mnd_reg_width - 1), 0); writel_relaxed(not2d_val, D_REG(rcg)); rcg_update_config(rcg); return 0; } static int rcg_clk_set_rate(struct clk *c, unsigned long rate) { struct clk_freq_tbl *cf, *nf; Loading Loading @@ -2119,6 +2161,7 @@ struct clk_ops clk_ops_rcg_mnd = { .enable = rcg_clk_enable, .disable = rcg_clk_disable, .set_rate = rcg_clk_set_rate, .set_duty_cycle = rcg_clk_set_duty_cycle, .list_rate = rcg_clk_list_rate, .round_rate = rcg_clk_round_rate, .handoff = rcg_mnd_clk_handoff, Loading drivers/clk/msm/clock.c +22 −0 Original line number Diff line number Diff line Loading @@ -825,6 +825,28 @@ int clk_set_flags(struct clk *clk, unsigned long flags) } EXPORT_SYMBOL(clk_set_flags); int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator) { if (IS_ERR_OR_NULL(clk)) return -EINVAL; if (numerator > denominator) { pr_err("Numerator cannot be > denominator\n"); return -EINVAL; } if (!denominator) { pr_err("Denominator can not be Zero\n"); return -EINVAL; } if (!clk->ops->set_duty_cycle) return -ENOSYS; return clk->ops->set_duty_cycle(clk, numerator, denominator); } EXPORT_SYMBOL(clk_set_duty_cycle); static LIST_HEAD(initdata_list); static void init_sibling_lists(struct clk_lookup *clock_tbl, size_t num_clocks) Loading include/linux/clk/msm-clk-provider.h +2 −1 Original line number Diff line number Diff line /* * Copyright (C) 2007 Google, Inc. * Copyright (c) 2007-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -146,6 +146,7 @@ struct clk_ops { void (*post_set_rate)(struct clk *clk, unsigned long old_rate); int (*set_max_rate)(struct clk *clk, unsigned long rate); int (*set_flags)(struct clk *clk, unsigned flags); int (*set_duty_cycle)(struct clk *clk, u32 numerator, u32 denominator); unsigned long (*get_rate)(struct clk *clk); long (*list_rate)(struct clk *clk, unsigned n); int (*is_enabled)(struct clk *clk); Loading include/linux/clk/msm-clk.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2009, 2012-2015 The Linux Foundation. All rights reserved. /* Copyright (c) 2009, 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -55,6 +55,11 @@ int clk_reset(struct clk *clk, enum clk_reset_action action); /* Set clock-specific configuration parameters */ int clk_set_flags(struct clk *clk, unsigned long flags); /* Set clock duty-cycle as a ratio of numerator/denominator for the desired * duty cycle */ int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator); /* returns the mux selection index associated with a particular parent */ int parent_to_src_sel(struct clk_src *parents, int num_parents, struct clk *p); Loading include/soc/qcom/clock-local2.h +2 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ struct clk_freq_tbl { /** * struct rcg_clk - root clock generator * @cmd_rcgr_reg: command register * @mnd_reg_width: Width of MND register * @set_rate: function to set frequency * @freq_tbl: frequency table for this RCG * @current_freq: current RCG frequency Loading @@ -66,6 +67,7 @@ struct clk_freq_tbl { */ struct rcg_clk { u32 cmd_rcgr_reg; u32 mnd_reg_width; void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *); Loading Loading
drivers/clk/msm/clock-local2.c +43 −0 Original line number Diff line number Diff line Loading @@ -346,6 +346,48 @@ static void disable_unprepare_rcg_srcs(struct clk *c, struct clk *curr, clk_unprepare(curr); } static int rcg_clk_set_duty_cycle(struct clk *c, u32 numerator, u32 denominator) { struct rcg_clk *rcg = to_rcg_clk(c); u32 notn_m_val, n_val, m_val, d_val, not2d_val; u32 max_n_value; if (!numerator || numerator == denominator) return -EINVAL; if (!rcg->mnd_reg_width) rcg->mnd_reg_width = 8; max_n_value = 1 << (rcg->mnd_reg_width - 1); notn_m_val = readl_relaxed(N_REG(rcg)); m_val = readl_relaxed(M_REG(rcg)); n_val = ((~notn_m_val) + m_val) & BM((rcg->mnd_reg_width - 1), 0); if (n_val > max_n_value) { pr_warn("%s duty-cycle cannot be set for required frequency %ld\n", c->dbg_name, clk_get_rate(c)); return -EINVAL; } /* Calculate the 2d value */ d_val = DIV_ROUND_CLOSEST((numerator * n_val * 2), denominator); /* Check BIT WIDTHS OF 2d. If D is too big reduce Duty cycle. */ if (d_val > (BIT(rcg->mnd_reg_width) - 1)) { d_val = (BIT(rcg->mnd_reg_width) - 1) / 2; d_val *= 2; } not2d_val = (~d_val) & BM((rcg->mnd_reg_width - 1), 0); writel_relaxed(not2d_val, D_REG(rcg)); rcg_update_config(rcg); return 0; } static int rcg_clk_set_rate(struct clk *c, unsigned long rate) { struct clk_freq_tbl *cf, *nf; Loading Loading @@ -2119,6 +2161,7 @@ struct clk_ops clk_ops_rcg_mnd = { .enable = rcg_clk_enable, .disable = rcg_clk_disable, .set_rate = rcg_clk_set_rate, .set_duty_cycle = rcg_clk_set_duty_cycle, .list_rate = rcg_clk_list_rate, .round_rate = rcg_clk_round_rate, .handoff = rcg_mnd_clk_handoff, Loading
drivers/clk/msm/clock.c +22 −0 Original line number Diff line number Diff line Loading @@ -825,6 +825,28 @@ int clk_set_flags(struct clk *clk, unsigned long flags) } EXPORT_SYMBOL(clk_set_flags); int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator) { if (IS_ERR_OR_NULL(clk)) return -EINVAL; if (numerator > denominator) { pr_err("Numerator cannot be > denominator\n"); return -EINVAL; } if (!denominator) { pr_err("Denominator can not be Zero\n"); return -EINVAL; } if (!clk->ops->set_duty_cycle) return -ENOSYS; return clk->ops->set_duty_cycle(clk, numerator, denominator); } EXPORT_SYMBOL(clk_set_duty_cycle); static LIST_HEAD(initdata_list); static void init_sibling_lists(struct clk_lookup *clock_tbl, size_t num_clocks) Loading
include/linux/clk/msm-clk-provider.h +2 −1 Original line number Diff line number Diff line /* * Copyright (C) 2007 Google, Inc. * Copyright (c) 2007-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -146,6 +146,7 @@ struct clk_ops { void (*post_set_rate)(struct clk *clk, unsigned long old_rate); int (*set_max_rate)(struct clk *clk, unsigned long rate); int (*set_flags)(struct clk *clk, unsigned flags); int (*set_duty_cycle)(struct clk *clk, u32 numerator, u32 denominator); unsigned long (*get_rate)(struct clk *clk); long (*list_rate)(struct clk *clk, unsigned n); int (*is_enabled)(struct clk *clk); Loading
include/linux/clk/msm-clk.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2009, 2012-2015 The Linux Foundation. All rights reserved. /* Copyright (c) 2009, 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -55,6 +55,11 @@ int clk_reset(struct clk *clk, enum clk_reset_action action); /* Set clock-specific configuration parameters */ int clk_set_flags(struct clk *clk, unsigned long flags); /* Set clock duty-cycle as a ratio of numerator/denominator for the desired * duty cycle */ int clk_set_duty_cycle(struct clk *clk, u32 numerator, u32 denominator); /* returns the mux selection index associated with a particular parent */ int parent_to_src_sel(struct clk_src *parents, int num_parents, struct clk *p); Loading
include/soc/qcom/clock-local2.h +2 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ struct clk_freq_tbl { /** * struct rcg_clk - root clock generator * @cmd_rcgr_reg: command register * @mnd_reg_width: Width of MND register * @set_rate: function to set frequency * @freq_tbl: frequency table for this RCG * @current_freq: current RCG frequency Loading @@ -66,6 +67,7 @@ struct clk_freq_tbl { */ struct rcg_clk { u32 cmd_rcgr_reg; u32 mnd_reg_width; void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *); Loading