0001
0002 #ifndef _CCU_MUX_H_
0003 #define _CCU_MUX_H_
0004
0005 #include <linux/clk-provider.h>
0006
0007 #include "ccu_common.h"
0008
0009 struct ccu_mux_fixed_prediv {
0010 u8 index;
0011 u16 div;
0012 };
0013
0014 struct ccu_mux_var_prediv {
0015 u8 index;
0016 u8 shift;
0017 u8 width;
0018 };
0019
0020 struct ccu_mux_internal {
0021 u8 shift;
0022 u8 width;
0023 const u8 *table;
0024
0025 const struct ccu_mux_fixed_prediv *fixed_predivs;
0026 u8 n_predivs;
0027
0028 const struct ccu_mux_var_prediv *var_predivs;
0029 u8 n_var_predivs;
0030 };
0031
0032 #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table) \
0033 { \
0034 .shift = _shift, \
0035 .width = _width, \
0036 .table = _table, \
0037 }
0038
0039 #define _SUNXI_CCU_MUX(_shift, _width) \
0040 _SUNXI_CCU_MUX_TABLE(_shift, _width, NULL)
0041
0042 struct ccu_mux {
0043 u32 enable;
0044
0045 struct ccu_mux_internal mux;
0046 struct ccu_common common;
0047 };
0048
0049 #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \
0050 _reg, _shift, _width, _gate, \
0051 _flags) \
0052 struct ccu_mux _struct = { \
0053 .enable = _gate, \
0054 .mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
0055 .common = { \
0056 .reg = _reg, \
0057 .hw.init = CLK_HW_INIT_PARENTS(_name, \
0058 _parents, \
0059 &ccu_mux_ops, \
0060 _flags), \
0061 } \
0062 }
0063
0064 #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg, \
0065 _shift, _width, _gate, _flags) \
0066 SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \
0067 _reg, _shift, _width, _gate, \
0068 _flags)
0069
0070 #define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width, \
0071 _flags) \
0072 SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \
0073 _reg, _shift, _width, 0, _flags)
0074
0075 #define SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg, \
0076 _shift, _width, _gate, _flags) \
0077 struct ccu_mux _struct = { \
0078 .enable = _gate, \
0079 .mux = _SUNXI_CCU_MUX(_shift, _width), \
0080 .common = { \
0081 .reg = _reg, \
0082 .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
0083 _parents, \
0084 &ccu_mux_ops, \
0085 _flags), \
0086 } \
0087 }
0088
0089 #define SUNXI_CCU_MUX_DATA(_struct, _name, _parents, _reg, \
0090 _shift, _width, _flags) \
0091 SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg, \
0092 _shift, _width, 0, _flags)
0093
0094 #define SUNXI_CCU_MUX_HW_WITH_GATE(_struct, _name, _parents, _reg, \
0095 _shift, _width, _gate, _flags) \
0096 struct ccu_mux _struct = { \
0097 .enable = _gate, \
0098 .mux = _SUNXI_CCU_MUX(_shift, _width), \
0099 .common = { \
0100 .reg = _reg, \
0101 .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
0102 _parents, \
0103 &ccu_mux_ops, \
0104 _flags), \
0105 } \
0106 }
0107
0108 static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
0109 {
0110 struct ccu_common *common = hw_to_ccu_common(hw);
0111
0112 return container_of(common, struct ccu_mux, common);
0113 }
0114
0115 extern const struct clk_ops ccu_mux_ops;
0116
0117 unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
0118 struct ccu_mux_internal *cm,
0119 int parent_index,
0120 unsigned long parent_rate);
0121 int ccu_mux_helper_determine_rate(struct ccu_common *common,
0122 struct ccu_mux_internal *cm,
0123 struct clk_rate_request *req,
0124 unsigned long (*round)(struct ccu_mux_internal *,
0125 struct clk_hw *,
0126 unsigned long *,
0127 unsigned long,
0128 void *),
0129 void *data);
0130 u8 ccu_mux_helper_get_parent(struct ccu_common *common,
0131 struct ccu_mux_internal *cm);
0132 int ccu_mux_helper_set_parent(struct ccu_common *common,
0133 struct ccu_mux_internal *cm,
0134 u8 index);
0135
0136 struct ccu_mux_nb {
0137 struct notifier_block clk_nb;
0138 struct ccu_common *common;
0139 struct ccu_mux_internal *cm;
0140
0141 u32 delay_us;
0142 u8 bypass_index;
0143 u8 original_index;
0144 };
0145
0146 #define to_ccu_mux_nb(_nb) container_of(_nb, struct ccu_mux_nb, clk_nb)
0147
0148 int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb);
0149
0150 #endif