Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
0004  */
0005 
0006 #ifndef _CCU_MP_H_
0007 #define _CCU_MP_H_
0008 
0009 #include <linux/bitops.h>
0010 #include <linux/clk-provider.h>
0011 
0012 #include "ccu_common.h"
0013 #include "ccu_div.h"
0014 #include "ccu_mult.h"
0015 #include "ccu_mux.h"
0016 
0017 /*
0018  * struct ccu_mp - Definition of an M-P clock
0019  *
0020  * Clocks based on the formula parent >> P / M
0021  */
0022 struct ccu_mp {
0023     u32         enable;
0024 
0025     struct ccu_div_internal     m;
0026     struct ccu_div_internal     p;
0027     struct ccu_mux_internal mux;
0028 
0029     unsigned int        fixed_post_div;
0030 
0031     struct ccu_common   common;
0032 };
0033 
0034 #define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \
0035                        _mshift, _mwidth,        \
0036                        _pshift, _pwidth,        \
0037                        _muxshift, _muxwidth,    \
0038                        _gate, _postdiv, _flags) \
0039     struct ccu_mp _struct = {                   \
0040         .enable = _gate,                    \
0041         .m  = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0042         .p  = _SUNXI_CCU_DIV(_pshift, _pwidth),     \
0043         .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),     \
0044         .fixed_post_div = _postdiv,             \
0045         .common = {                     \
0046             .reg        = _reg,             \
0047             .features   = CCU_FEATURE_FIXED_POSTDIV,    \
0048             .hw.init    = CLK_HW_INIT_PARENTS(_name,    \
0049                                   _parents, \
0050                                   &ccu_mp_ops, \
0051                                   _flags),  \
0052         }                           \
0053     }
0054 
0055 #define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
0056                    _mshift, _mwidth,            \
0057                    _pshift, _pwidth,            \
0058                    _muxshift, _muxwidth,        \
0059                    _gate, _flags)           \
0060     struct ccu_mp _struct = {                   \
0061         .enable = _gate,                    \
0062         .m  = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0063         .p  = _SUNXI_CCU_DIV(_pshift, _pwidth),     \
0064         .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),     \
0065         .common = {                     \
0066             .reg        = _reg,             \
0067             .hw.init    = CLK_HW_INIT_PARENTS(_name,    \
0068                                   _parents, \
0069                                   &ccu_mp_ops, \
0070                                   _flags),  \
0071         }                           \
0072     }
0073 
0074 #define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,       \
0075                   _mshift, _mwidth,             \
0076                   _pshift, _pwidth,             \
0077                   _muxshift, _muxwidth,         \
0078                   _flags)                   \
0079     SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
0080                    _mshift, _mwidth,            \
0081                    _pshift, _pwidth,            \
0082                    _muxshift, _muxwidth,        \
0083                    0, _flags)
0084 
0085 #define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
0086                     _mshift, _mwidth,       \
0087                     _pshift, _pwidth,       \
0088                     _muxshift, _muxwidth,       \
0089                     _gate, _flags)          \
0090     struct ccu_mp _struct = {                   \
0091         .enable = _gate,                    \
0092         .m  = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0093         .p  = _SUNXI_CCU_DIV(_pshift, _pwidth),     \
0094         .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),     \
0095         .common = {                     \
0096             .reg        = _reg,             \
0097             .hw.init    = CLK_HW_INIT_PARENTS_DATA(_name, \
0098                                    _parents, \
0099                                    &ccu_mp_ops, \
0100                                    _flags), \
0101         }                           \
0102     }
0103 
0104 #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg,  \
0105                    _mshift, _mwidth,            \
0106                    _pshift, _pwidth,            \
0107                    _muxshift, _muxwidth,        \
0108                    _flags)              \
0109     SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
0110                     _mshift, _mwidth,       \
0111                     _pshift, _pwidth,       \
0112                     _muxshift, _muxwidth,       \
0113                     0, _flags)
0114 
0115 #define SUNXI_CCU_MP_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg,   \
0116                       _mshift, _mwidth,         \
0117                       _pshift, _pwidth,         \
0118                       _muxshift, _muxwidth,     \
0119                       _gate, _flags)            \
0120     struct ccu_mp _struct = {                   \
0121         .enable = _gate,                    \
0122         .m  = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
0123         .p  = _SUNXI_CCU_DIV(_pshift, _pwidth),     \
0124         .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),     \
0125         .common = {                     \
0126             .reg        = _reg,             \
0127             .hw.init    = CLK_HW_INIT_PARENTS_HW(_name, \
0128                                  _parents, \
0129                                  &ccu_mp_ops, \
0130                                  _flags), \
0131         }                           \
0132     }
0133 
0134 static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
0135 {
0136     struct ccu_common *common = hw_to_ccu_common(hw);
0137 
0138     return container_of(common, struct ccu_mp, common);
0139 }
0140 
0141 extern const struct clk_ops ccu_mp_ops;
0142 
0143 /*
0144  * Special class of M-P clock that supports MMC timing modes
0145  *
0146  * Since the MMC clock registers all follow the same layout, we can
0147  * simplify the macro for this particular case. In addition, as
0148  * switching modes also affects the output clock rate, we need to
0149  * have CLK_GET_RATE_NOCACHE for all these types of clocks.
0150  */
0151 
0152 #define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
0153                        _flags)              \
0154     struct ccu_mp _struct = {                   \
0155         .enable = BIT(31),                  \
0156         .m  = _SUNXI_CCU_DIV(0, 4),             \
0157         .p  = _SUNXI_CCU_DIV(16, 2),            \
0158         .mux    = _SUNXI_CCU_MUX(24, 2),            \
0159         .common = {                     \
0160             .reg        = _reg,             \
0161             .features   = CCU_FEATURE_MMC_TIMING_SWITCH, \
0162             .hw.init    = CLK_HW_INIT_PARENTS(_name,    \
0163                                   _parents, \
0164                                   &ccu_mp_mmc_ops, \
0165                                   CLK_GET_RATE_NOCACHE | \
0166                                   _flags),  \
0167         }                           \
0168     }
0169 
0170 extern const struct clk_ops ccu_mp_mmc_ops;
0171 
0172 #endif /* _CCU_MP_H_ */