summaryrefslogtreecommitdiff
path: root/include/linux/clk
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/clk')
-rw-r--r--include/linux/clk/gdsc.h22
-rw-r--r--include/linux/clk/msm-clk-provider.h270
-rw-r--r--include/linux/clk/msm-clk.h138
-rw-r--r--include/linux/clk/msm-clock-generic.h323
4 files changed, 753 insertions, 0 deletions
diff --git a/include/linux/clk/gdsc.h b/include/linux/clk/gdsc.h
new file mode 100644
index 000000000000..b012ed06d3f4
--- /dev/null
+++ b/include/linux/clk/gdsc.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __GDSC_H
+#define __GDSC_H
+
+#include <linux/regulator/consumer.h>
+
+/* Allow the clock memories to be turned off */
+void gdsc_allow_clear_retention(struct regulator *regulator);
+
+#endif
diff --git a/include/linux/clk/msm-clk-provider.h b/include/linux/clk/msm-clk-provider.h
new file mode 100644
index 000000000000..2fa8916ad356
--- /dev/null
+++ b/include/linux/clk/msm-clk-provider.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * 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
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MSM_CLK_PROVIDER_H
+#define __MSM_CLK_PROVIDER_H
+
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/seq_file.h>
+#include <linux/clk/msm-clk.h>
+
+#if defined(CONFIG_COMMON_CLK_MSM)
+/*
+ * Bit manipulation macros
+ */
+#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
+#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))
+
+/*
+ * Halt/Status Checking Mode Macros
+ */
+#define HALT 0 /* Bit pol: 1 = halted */
+#define NOCHECK 1 /* No bit to check, do nothing */
+#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */
+#define ENABLE 3 /* Bit pol: 1 = running */
+#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */
+#define DELAY 5 /* No bit to check, just delay */
+
+struct clk_register_data {
+ char *name;
+ u32 offset;
+};
+#ifdef CONFIG_DEBUG_FS
+void clk_debug_print_hw(struct clk *clk, struct seq_file *f);
+#else
+static inline void clk_debug_print_hw(struct clk *clk, struct seq_file *f) {}
+#endif
+
+#define CLK_WARN(clk, cond, fmt, ...) do { \
+ clk_debug_print_hw(clk, NULL); \
+ WARN(cond, "%s: " fmt, clk_name(clk), ##__VA_ARGS__); \
+} while (0)
+
+/**
+ * struct clk_vdd_class - Voltage scaling class
+ * @class_name: name of the class
+ * @regulator: array of regulators.
+ * @num_regulators: size of regulator array. Standard regulator APIs will be
+ used if this field > 0.
+ * @set_vdd: function to call when applying a new voltage setting.
+ * @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then
+ regulator.
+ * @vdd_ua: sorted 2D array of legal cureent settings. Indexed by level, then
+ regulator. Optional parameter.
+ * @level_votes: array of votes for each level.
+ * @num_levels: specifies the size of level_votes array.
+ * @skip_handoff: do not vote for the max possible voltage during init
+ * @use_max_uV: use INT_MAX for max_uV when calling regulator_set_voltage
+ * This is useful when different vdd_class share same regulator.
+ * @cur_level: the currently set voltage level
+ * @lock: lock to protect this struct
+ */
+struct clk_vdd_class {
+ const char *class_name;
+ struct regulator **regulator;
+ int num_regulators;
+ int (*set_vdd)(struct clk_vdd_class *v_class, int level);
+ int *vdd_uv;
+ int *vdd_ua;
+ int *level_votes;
+ int num_levels;
+ bool skip_handoff;
+ bool use_max_uV;
+ unsigned long cur_level;
+ struct mutex lock;
+};
+
+#define DEFINE_VDD_CLASS(_name, _set_vdd, _num_levels) \
+ struct clk_vdd_class _name = { \
+ .class_name = #_name, \
+ .set_vdd = _set_vdd, \
+ .level_votes = (int [_num_levels]) {}, \
+ .num_levels = _num_levels, \
+ .cur_level = _num_levels, \
+ .lock = __MUTEX_INITIALIZER(_name.lock) \
+ }
+
+#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv, \
+ _vdd_ua) \
+ struct clk_vdd_class _name = { \
+ .class_name = #_name, \
+ .vdd_uv = _vdd_uv, \
+ .vdd_ua = _vdd_ua, \
+ .regulator = (struct regulator * [_num_regulators]) {}, \
+ .num_regulators = _num_regulators, \
+ .level_votes = (int [_num_levels]) {}, \
+ .num_levels = _num_levels, \
+ .cur_level = _num_levels, \
+ .lock = __MUTEX_INITIALIZER(_name.lock) \
+ }
+
+#define DEFINE_VDD_REGS_INIT(_name, _num_regulators) \
+ struct clk_vdd_class _name = { \
+ .class_name = #_name, \
+ .regulator = (struct regulator * [_num_regulators]) {}, \
+ .num_regulators = _num_regulators, \
+ .lock = __MUTEX_INITIALIZER(_name.lock) \
+ }
+
+enum handoff {
+ HANDOFF_ENABLED_CLK,
+ HANDOFF_DISABLED_CLK,
+};
+
+struct clk_ops {
+ int (*prepare)(struct clk *clk);
+ int (*enable)(struct clk *clk);
+ void (*disable)(struct clk *clk);
+ void (*unprepare)(struct clk *clk);
+ void (*enable_hwcg)(struct clk *clk);
+ void (*disable_hwcg)(struct clk *clk);
+ int (*in_hwcg_mode)(struct clk *clk);
+ enum handoff (*handoff)(struct clk *clk);
+ int (*reset)(struct clk *clk, enum clk_reset_action action);
+ int (*pre_set_rate)(struct clk *clk, unsigned long new_rate);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+ 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);
+ unsigned long (*get_rate)(struct clk *clk);
+ long (*list_rate)(struct clk *clk, unsigned n);
+ int (*is_enabled)(struct clk *clk);
+ long (*round_rate)(struct clk *clk, unsigned long rate);
+ int (*set_parent)(struct clk *clk, struct clk *parent);
+ struct clk *(*get_parent)(struct clk *clk);
+ bool (*is_local)(struct clk *clk);
+ void __iomem *(*list_registers)(struct clk *clk, int n,
+ struct clk_register_data **regs, u32 *size);
+};
+
+/**
+ * struct clk
+ * @prepare_count: prepare refcount
+ * @prepare_lock: protects clk_prepare()/clk_unprepare() path and @prepare_count
+ * @count: enable refcount
+ * @lock: protects clk_enable()/clk_disable() path and @count
+ * @depends: non-direct parent of clock to enable when this clock is enabled
+ * @vdd_class: voltage scaling requirement class
+ * @fmax: maximum frequency in Hz supported at each voltage level
+ * @parent: the current source of this clock
+ * @opp_table_populated: tracks if the OPP table of this clock has been filled
+ */
+struct clk {
+ uint32_t flags;
+ struct clk_ops *ops;
+ const char *dbg_name;
+ struct clk *depends;
+ struct clk_vdd_class *vdd_class;
+ unsigned long *fmax;
+ int num_fmax;
+ unsigned long rate;
+ struct clk *parent;
+ struct clk_src *parents;
+ unsigned int num_parents;
+
+ struct list_head children;
+ struct list_head siblings;
+ struct list_head list;
+
+ unsigned count;
+ unsigned notifier_count;
+ spinlock_t lock;
+ unsigned prepare_count;
+ struct mutex prepare_lock;
+
+ unsigned long init_rate;
+ bool always_on;
+ bool opp_table_populated;
+
+ struct dentry *clk_dir;
+};
+
+#define CLK_INIT(name) \
+ .lock = __SPIN_LOCK_UNLOCKED((name).lock), \
+ .prepare_lock = __MUTEX_INITIALIZER((name).prepare_lock), \
+ .children = LIST_HEAD_INIT((name).children), \
+ .siblings = LIST_HEAD_INIT((name).siblings), \
+ .list = LIST_HEAD_INIT((name).list)
+
+bool is_rate_valid(struct clk *clk, unsigned long rate);
+int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
+int unvote_vdd_level(struct clk_vdd_class *vdd_class, int level);
+int __clk_pre_reparent(struct clk *c, struct clk *new, unsigned long *flags);
+void __clk_post_reparent(struct clk *c, struct clk *old, unsigned long *flags);
+
+/* Register clocks with the MSM clock driver */
+int msm_clock_register(struct clk_lookup *table, size_t size);
+int of_msm_clock_register(struct device_node *np, struct clk_lookup *table,
+ size_t size);
+
+int clock_rcgwr_init(struct platform_device *pdev);
+int clock_rcgwr_disable(struct platform_device *pdev);
+
+extern struct clk dummy_clk;
+extern struct clk_ops clk_ops_dummy;
+
+#define CLK_DUMMY(clk_name, clk_id, clk_dev, flags) { \
+ .con_id = clk_name, \
+ .dev_id = clk_dev, \
+ .clk = &dummy_clk, \
+ }
+
+#define DEFINE_CLK_DUMMY(name, _rate) \
+ static struct fixed_clk name = { \
+ .c = { \
+ .dbg_name = #name, \
+ .rate = _rate, \
+ .ops = &clk_ops_dummy, \
+ CLK_INIT(name.c), \
+ }, \
+ };
+
+#define CLK_LOOKUP(con, c, dev) { .con_id = con, .clk = &c, .dev_id = dev }
+#define CLK_LOOKUP_OF(con, _c, dev) { .con_id = con, .clk = &(&_c)->c, \
+ .dev_id = dev, .of_idx = clk_##_c }
+#define CLK_LIST(_c) { .clk = &(&_c)->c, .of_idx = clk_##_c }
+
+static inline bool is_better_rate(unsigned long req, unsigned long best,
+ unsigned long new)
+{
+ if (IS_ERR_VALUE(new))
+ return false;
+
+ return (req <= new && new < best) || (best < req && best < new);
+}
+
+extern int of_clk_add_provider(struct device_node *np,
+ struct clk *(*clk_src_get)(struct of_phandle_args *args,
+ void *data),
+ void *data);
+extern void of_clk_del_provider(struct device_node *np);
+
+static inline const char *clk_name(struct clk *c)
+{
+ if (IS_ERR_OR_NULL(c))
+ return "(null)";
+ return c->dbg_name;
+};
+#endif /* CONFIG_COMMON_CLK_MSM */
+#endif
diff --git a/include/linux/clk/msm-clk.h b/include/linux/clk/msm-clk.h
new file mode 100644
index 000000000000..8455fd776246
--- /dev/null
+++ b/include/linux/clk/msm-clk.h
@@ -0,0 +1,138 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MACH_CLK_H
+#define __MACH_CLK_H
+
+#include <linux/notifier.h>
+
+#if defined(CONFIG_COMMON_CLK_QCOM)
+enum branch_mem_flags {
+ CLKFLAG_RETAIN_PERIPH,
+ CLKFLAG_NORETAIN_PERIPH,
+ CLKFLAG_RETAIN_MEM,
+ CLKFLAG_NORETAIN_MEM,
+ CLKFLAG_PERIPH_OFF_SET,
+ CLKFLAG_PERIPH_OFF_CLEAR,
+};
+
+#include <linux/clk.h>
+
+#elif defined(CONFIG_COMMON_CLK_MSM)
+#define CLKFLAG_INVERT 0x00000001
+#define CLKFLAG_NOINVERT 0x00000002
+#define CLKFLAG_NONEST 0x00000004
+#define CLKFLAG_NORESET 0x00000008
+#define CLKFLAG_RETAIN_PERIPH 0x00000010
+#define CLKFLAG_NORETAIN_PERIPH 0x00000020
+#define CLKFLAG_RETAIN_MEM 0x00000040
+#define CLKFLAG_NORETAIN_MEM 0x00000080
+#define CLKFLAG_SKIP_HANDOFF 0x00000100
+#define CLKFLAG_MIN 0x00000400
+#define CLKFLAG_MAX 0x00000800
+#define CLKFLAG_INIT_DONE 0x00001000
+#define CLKFLAG_INIT_ERR 0x00002000
+#define CLKFLAG_NO_RATE_CACHE 0x00004000
+#define CLKFLAG_MEASURE 0x00008000
+#define CLKFLAG_EPROBE_DEFER 0x00010000
+#define CLKFLAG_PERIPH_OFF_SET 0x00020000
+#define CLKFLAG_PERIPH_OFF_CLEAR 0x00040000
+
+struct clk_lookup;
+struct clk;
+
+enum clk_reset_action {
+ CLK_RESET_DEASSERT = 0,
+ CLK_RESET_ASSERT = 1
+};
+
+struct clk_src {
+ struct clk *src;
+ int sel;
+};
+
+/* Rate is maximum clock rate in Hz */
+int clk_set_max_rate(struct clk *clk, unsigned long rate);
+
+/* Assert/Deassert reset to a hardware block associated with a clock */
+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);
+
+/* 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);
+
+/* returns the mux selection index associated with a particular parent */
+int clk_get_parent_sel(struct clk *c, struct clk *parent);
+
+/**
+ * DOC: clk notifier callback types
+ *
+ * PRE_RATE_CHANGE - called immediately before the clk rate is changed,
+ * to indicate that the rate change will proceed. Drivers must
+ * immediately terminate any operations that will be affected by the
+ * rate change. Callbacks may either return NOTIFY_DONE, NOTIFY_OK,
+ * NOTIFY_STOP or NOTIFY_BAD.
+ *
+ * ABORT_RATE_CHANGE: called if the rate change failed for some reason
+ * after PRE_RATE_CHANGE. In this case, all registered notifiers on
+ * the clk will be called with ABORT_RATE_CHANGE. Callbacks must
+ * always return NOTIFY_DONE or NOTIFY_OK.
+ *
+ * POST_RATE_CHANGE - called after the clk rate change has successfully
+ * completed. Callbacks must always return NOTIFY_DONE or NOTIFY_OK.
+ *
+ */
+#define PRE_RATE_CHANGE BIT(0)
+#define POST_RATE_CHANGE BIT(1)
+#define ABORT_RATE_CHANGE BIT(2)
+
+/**
+ * struct msm_clk_notifier - associate a clk with a notifier
+ * @clk: struct clk * to associate the notifier with
+ * @notifier_head: a blocking_notifier_head for this clk
+ * @node: linked list pointers
+ *
+ * A list of struct clk_notifier is maintained by the notifier code.
+ * An entry is created whenever code registers the first notifier on a
+ * particular @clk. Future notifiers on that @clk are added to the
+ * @notifier_head.
+ */
+struct msm_clk_notifier {
+ struct clk *clk;
+ struct srcu_notifier_head notifier_head;
+ struct list_head node;
+};
+
+/**
+ * struct msm_clk_notifier_data - rate data to pass to the notifier callback
+ * @clk: struct clk * being changed
+ * @old_rate: previous rate of this clk
+ * @new_rate: new rate of this clk
+ *
+ * For a pre-notifier, old_rate is the clk's rate before this rate
+ * change, and new_rate is what the rate will be in the future. For a
+ * post-notifier, old_rate and new_rate are both set to the clk's
+ * current rate (this was done to optimize the implementation).
+ */
+struct msm_clk_notifier_data {
+ struct clk *clk;
+ unsigned long old_rate;
+ unsigned long new_rate;
+};
+
+int msm_clk_notif_register(struct clk *clk, struct notifier_block *nb);
+
+int msm_clk_notif_unregister(struct clk *clk, struct notifier_block *nb);
+
+#endif /* CONFIG_COMMON_CLK_MSM */
+#endif
diff --git a/include/linux/clk/msm-clock-generic.h b/include/linux/clk/msm-clock-generic.h
new file mode 100644
index 000000000000..cb2d8787b84f
--- /dev/null
+++ b/include/linux/clk/msm-clock-generic.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2013-2018, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_CLOCK_GENERIC_H
+#define __MSM_CLOCK_GENERIC_H
+
+#include <linux/clk/msm-clk-provider.h>
+#include <linux/of.h>
+
+/**
+ * struct fixed_clk - fixed rate clock
+ * @c: clk
+ */
+struct fixed_clk {
+ struct clk c;
+};
+
+/* ==================== Mux clock ==================== */
+
+struct mux_clk;
+
+struct clk_mux_ops {
+ int (*set_mux_sel)(struct mux_clk *clk, int sel);
+ int (*get_mux_sel)(struct mux_clk *clk);
+
+ /* Optional */
+ bool (*is_enabled)(struct mux_clk *clk);
+ int (*enable)(struct mux_clk *clk);
+ void (*disable)(struct mux_clk *clk);
+ void __iomem *(*list_registers)(struct mux_clk *clk, int n,
+ struct clk_register_data **regs, u32 *size);
+};
+
+#define MUX_SRC_LIST(...) \
+ .parents = (struct clk_src[]){__VA_ARGS__}, \
+ .num_parents = ARRAY_SIZE(((struct clk_src[]){__VA_ARGS__}))
+
+#define MUX_REC_SRC_LIST(...) \
+ .rec_parents = (struct clk * []){__VA_ARGS__}, \
+ .num_rec_parents = ARRAY_SIZE(((struct clk * []){__VA_ARGS__}))
+
+struct mux_clk {
+ /* Parents in decreasing order of preference for obtaining rates. */
+ struct clk_src *parents;
+ int num_parents;
+ /* Recursively search for the requested parent in rec_parents. */
+ struct clk **rec_parents;
+ int num_rec_parents;
+ struct clk *safe_parent;
+ int safe_sel;
+ unsigned long safe_freq;
+ /*
+ * Before attempting a clk_round_rate on available sources, attempt a
+ * clk_get_rate on all those sources. If one of them is already at the
+ * necessary rate, that source will be used.
+ */
+ bool try_get_rate;
+ struct clk_mux_ops *ops;
+ /*
+ * Set if you need the mux to try a new parent before falling back to
+ * the current parent. If the safe_parent field above is set, then the
+ * safe_sel intermediate source will only be used if we fall back to
+ * to the current parent during mux_set_rate.
+ */
+ bool try_new_parent;
+
+ /* Fields not used by helper function. */
+ void *const __iomem *base;
+ u32 offset;
+ u32 en_offset;
+ u32 mask;
+ u32 shift;
+ u32 en_mask;
+ /*
+ * Set post divider for debug mux in order to divide the clock
+ * by post_div + 1.
+ */
+ u32 post_div;
+ int low_power_sel;
+ void *priv;
+
+ struct clk c;
+};
+
+static inline struct mux_clk *to_mux_clk(struct clk *c)
+{
+ return container_of(c, struct mux_clk, c);
+}
+
+extern struct clk_ops clk_ops_gen_mux;
+
+/* ==================== Divider clock ==================== */
+
+struct div_clk;
+
+struct clk_div_ops {
+ int (*set_div)(struct div_clk *clk, int div);
+ int (*get_div)(struct div_clk *clk);
+ bool (*is_enabled)(struct div_clk *clk);
+ int (*enable)(struct div_clk *clk);
+ void (*disable)(struct div_clk *clk);
+ void __iomem *(*list_registers)(struct div_clk *clk, int n,
+ struct clk_register_data **regs, u32 *size);
+};
+
+struct div_data {
+ unsigned int div;
+ unsigned int min_div;
+ unsigned int max_div;
+ unsigned long rate_margin;
+ /*
+ * Indicate whether this divider clock supports half-interger divider.
+ * If it is, all the min_div and max_div have been doubled. It means
+ * they are 2*N.
+ */
+ bool is_half_divider;
+ /*
+ * Skip odd dividers since the hardware may not support them.
+ */
+ bool skip_odd_div;
+ bool skip_even_div;
+ bool allow_div_one;
+ unsigned int cached_div;
+};
+
+struct div_clk {
+ struct div_data data;
+
+ /*
+ * Some implementations may require the divider to be set to a "safe"
+ * value that allows reprogramming of upstream clocks without violating
+ * voltage constraints.
+ */
+ unsigned long safe_freq;
+
+ /* Optional */
+ struct clk_div_ops *ops;
+
+ /* Fields not used by helper function. */
+ void *const __iomem *base;
+ u32 offset;
+ u32 mask;
+ u32 shift;
+ u32 en_mask;
+ void *priv;
+ struct clk c;
+};
+
+static inline struct div_clk *to_div_clk(struct clk *c)
+{
+ return container_of(c, struct div_clk, c);
+}
+
+extern struct clk_ops clk_ops_div;
+extern struct clk_ops clk_ops_slave_div;
+
+struct ext_clk {
+ struct clk c;
+ struct device *dev;
+ char *clk_id;
+};
+
+long parent_round_rate(struct clk *c, unsigned long rate);
+unsigned long parent_get_rate(struct clk *c);
+int parent_set_rate(struct clk *c, unsigned long rate);
+
+static inline struct ext_clk *to_ext_clk(struct clk *c)
+{
+ return container_of(c, struct ext_clk, c);
+}
+
+extern struct clk_ops clk_ops_ext;
+
+#define DEFINE_FIXED_DIV_CLK(clk_name, _div, _parent) \
+static struct div_clk clk_name = { \
+ .data = { \
+ .max_div = _div, \
+ .min_div = _div, \
+ .div = _div, \
+ }, \
+ .c = { \
+ .parent = _parent, \
+ .dbg_name = #clk_name, \
+ .ops = &clk_ops_div, \
+ CLK_INIT(clk_name.c), \
+ } \
+}
+
+#define DEFINE_FIXED_SLAVE_DIV_CLK(clk_name, _div, _parent) \
+static struct div_clk clk_name = { \
+ .data = { \
+ .max_div = _div, \
+ .min_div = _div, \
+ .div = _div, \
+ }, \
+ .c = { \
+ .parent = _parent, \
+ .dbg_name = #clk_name, \
+ .ops = &clk_ops_slave_div, \
+ CLK_INIT(clk_name.c), \
+ } \
+}
+
+#define DEFINE_EXT_CLK(clk_name, _parent) \
+static struct ext_clk clk_name = { \
+ .c = { \
+ .parent = _parent, \
+ .dbg_name = #clk_name, \
+ .ops = &clk_ops_ext, \
+ CLK_INIT(clk_name.c), \
+ } \
+}
+
+/* ==================== Mux Div clock ==================== */
+
+struct mux_div_clk;
+
+/*
+ * struct mux_div_ops
+ * the enable and disable ops are optional.
+ */
+
+struct mux_div_ops {
+ int (*set_src_div)(struct mux_div_clk *, u32 src_sel, u32 div);
+ void (*get_src_div)(struct mux_div_clk *, u32 *src_sel, u32 *div);
+ int (*enable)(struct mux_div_clk *);
+ void (*disable)(struct mux_div_clk *);
+ bool (*is_enabled)(struct mux_div_clk *);
+ void __iomem *(*list_registers)(struct mux_div_clk *md, int n,
+ struct clk_register_data **regs, u32 *size);
+};
+
+/*
+ * struct mux_div_clk - combined mux/divider clock
+ * @priv
+ parameters needed by ops
+ * @safe_freq
+ when switching rates from A to B, the mux div clock will
+ instead switch from A -> safe_freq -> B. This allows the
+ mux_div clock to change rates while enabled, even if this
+ behavior is not supported by the parent clocks.
+
+ If changing the rate of parent A also causes the rate of
+ parent B to change, then safe_freq must be defined.
+
+ safe_freq is expected to have a source clock which is always
+ on and runs at only one rate.
+ * @parents
+ list of parents and mux indicies
+ * @ops
+ function pointers for hw specific operations
+ * @src_sel
+ the mux index which will be used if the clock is enabled.
+ * @try_get_rate
+ Set if you need the mux to directly jump to a source
+ that is at the desired rate currently.
+ * @force_enable_md
+ Set if the mux-div needs to be force enabled/disabled during
+ clk_enable/disable.
+ */
+
+struct mux_div_clk {
+ /* Required parameters */
+ struct mux_div_ops *ops;
+ struct div_data data;
+ struct clk_src *parents;
+ u32 num_parents;
+
+ struct clk c;
+
+ /* Internal */
+ u32 src_sel;
+
+ /* Optional parameters */
+ void *priv;
+ void __iomem *base;
+ u32 div_mask;
+ u32 div_offset;
+ u32 div_shift;
+ u32 src_mask;
+ u32 src_offset;
+ u32 src_shift;
+ u32 en_mask;
+ u32 en_offset;
+
+ u32 safe_div;
+ struct clk *safe_parent;
+ unsigned long safe_freq;
+ bool try_get_rate;
+ bool force_enable_md;
+};
+
+static inline struct mux_div_clk *to_mux_div_clk(struct clk *clk)
+{
+ return container_of(clk, struct mux_div_clk, c);
+}
+
+extern struct clk_ops clk_ops_mux_div_clk;
+
+/* ==================== Virtual clock ==================== */
+struct virtclk_front {
+ int id;
+ struct clk c;
+ u32 flag;
+};
+
+extern struct clk_ops virtclk_front_ops;
+
+int msm_virtclk_front_probe(struct platform_device *pdev,
+ struct clk_lookup *table,
+ size_t size);
+
+#endif