Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
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;   /* How many us to wait after reparenting */
0142     u8  bypass_index;   /* Which parent to temporarily use */
0143     u8  original_index; /* This is set by the notifier callback */
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 /* _CCU_MUX_H_ */