summaryrefslogtreecommitdiff
path: root/drivers/clk/mmp/clk.h
diff options
context:
space:
mode:
authorChao Xie <chao.xie@marvell.com>2014-10-31 10:13:45 +0800
committerMichael Turquette <mturquette@linaro.org>2014-11-12 16:33:52 -0800
commitee81f4ee2a3632a2d7928f680c4af8243a18762f (patch)
tree7e0f473833adb5b523c033b32a31c10ee8cf5cf7 /drivers/clk/mmp/clk.h
parent3a2b2f84957d3c1e380640e23e438c40c730cfd1 (diff)
clk: mmp: add clock type mix
The clock type mix is a kind of clock combines "div" and "mux". This kind of clock can not allow to change div first then mux or change mux first or div. The reason is 1. Some clock has frequency change bit. Each time want to change the frequency, there are some operations based on this bit, and these operations are time-cost. Seperating div and mux change will make the process longer, and waste more time. 2. Seperting the div and mux may generate middle clock that the peripharals do not support. It may make the peripharals hang. There are three kinds of this type of clock in all SOCes. 1. The clock has bit to trigger the frequency change. 2. Same as #1, but the operations for the bit is different 3. Do not have frequency change bit. So this type of clock has implemented the callbacks ->determine_rate ->set_rate_and_parent These callbacks can help to change the div and mux together. Signed-off-by: Chao Xie <chao.xie@marvell.com> Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com> Signed-off-by: Michael Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/mmp/clk.h')
-rw-r--r--drivers/clk/mmp/clk.h66
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index d267639ece2b..26b24699ccd7 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -37,6 +37,72 @@ extern struct clk *mmp_clk_register_factor(const char *name,
struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
spinlock_t *lock);
+/* Clock type "mix" */
+#define MMP_CLK_BITS_MASK(width, shift) \
+ (((1 << (width)) - 1) << (shift))
+#define MMP_CLK_BITS_GET_VAL(data, width, shift) \
+ ((data & MMP_CLK_BITS_MASK(width, shift)) >> (shift))
+#define MMP_CLK_BITS_SET_VAL(val, width, shift) \
+ (((val) << (shift)) & MMP_CLK_BITS_MASK(width, shift))
+
+enum {
+ MMP_CLK_MIX_TYPE_V1,
+ MMP_CLK_MIX_TYPE_V2,
+ MMP_CLK_MIX_TYPE_V3,
+};
+
+/* The register layout */
+struct mmp_clk_mix_reg_info {
+ void __iomem *reg_clk_ctrl;
+ void __iomem *reg_clk_sel;
+ u8 width_div;
+ u8 shift_div;
+ u8 width_mux;
+ u8 shift_mux;
+ u8 bit_fc;
+};
+
+/* The suggested clock table from user. */
+struct mmp_clk_mix_clk_table {
+ unsigned long rate;
+ u8 parent_index;
+ unsigned int divisor;
+ unsigned int valid;
+};
+
+struct mmp_clk_mix_config {
+ struct mmp_clk_mix_reg_info reg_info;
+ struct mmp_clk_mix_clk_table *table;
+ unsigned int table_size;
+ u32 *mux_table;
+ struct clk_div_table *div_table;
+ u8 div_flags;
+ u8 mux_flags;
+};
+
+struct mmp_clk_mix {
+ struct clk_hw hw;
+ struct mmp_clk_mix_reg_info reg_info;
+ struct mmp_clk_mix_clk_table *table;
+ u32 *mux_table;
+ struct clk_div_table *div_table;
+ unsigned int table_size;
+ u8 div_flags;
+ u8 mux_flags;
+ unsigned int type;
+ spinlock_t *lock;
+};
+
+extern const struct clk_ops mmp_clk_mix_ops;
+extern struct clk *mmp_clk_register_mix(struct device *dev,
+ const char *name,
+ u8 num_parents,
+ const char **parent_names,
+ unsigned long flags,
+ struct mmp_clk_mix_config *config,
+ spinlock_t *lock);
+
+
extern struct clk *mmp_clk_register_pll2(const char *name,
const char *parent_name, unsigned long flags);
extern struct clk *mmp_clk_register_apbc(const char *name,