173 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright (c) 2016 Maxime Ripard. All rights reserved.4 */5 6#ifndef _CCU_MP_H_7#define _CCU_MP_H_8 9#include <linux/bitops.h>10#include <linux/clk-provider.h>11 12#include "ccu_common.h"13#include "ccu_div.h"14#include "ccu_mult.h"15#include "ccu_mux.h"16 17/*18 * struct ccu_mp - Definition of an M-P clock19 *20 * Clocks based on the formula parent >> P / M21 */22struct ccu_mp {23 u32 enable;24 25 struct ccu_div_internal m;26 struct ccu_div_internal p;27 struct ccu_mux_internal mux;28 29 unsigned int fixed_post_div;30 31 struct ccu_common common;32};33 34#define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \35 _mshift, _mwidth, \36 _pshift, _pwidth, \37 _muxshift, _muxwidth, \38 _gate, _postdiv, _flags) \39 struct ccu_mp _struct = { \40 .enable = _gate, \41 .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \42 .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \43 .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \44 .fixed_post_div = _postdiv, \45 .common = { \46 .reg = _reg, \47 .features = CCU_FEATURE_FIXED_POSTDIV, \48 .hw.init = CLK_HW_INIT_PARENTS(_name, \49 _parents, \50 &ccu_mp_ops, \51 _flags), \52 } \53 }54 55#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \56 _mshift, _mwidth, \57 _pshift, _pwidth, \58 _muxshift, _muxwidth, \59 _gate, _flags) \60 struct ccu_mp _struct = { \61 .enable = _gate, \62 .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \63 .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \64 .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \65 .common = { \66 .reg = _reg, \67 .hw.init = CLK_HW_INIT_PARENTS(_name, \68 _parents, \69 &ccu_mp_ops, \70 _flags), \71 } \72 }73 74#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg, \75 _mshift, _mwidth, \76 _pshift, _pwidth, \77 _muxshift, _muxwidth, \78 _flags) \79 SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \80 _mshift, _mwidth, \81 _pshift, _pwidth, \82 _muxshift, _muxwidth, \83 0, _flags)84 85#define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \86 _mshift, _mwidth, \87 _pshift, _pwidth, \88 _muxshift, _muxwidth, \89 _gate, _flags) \90 struct ccu_mp _struct = { \91 .enable = _gate, \92 .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \93 .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \94 .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \95 .common = { \96 .reg = _reg, \97 .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \98 _parents, \99 &ccu_mp_ops, \100 _flags), \101 } \102 }103 104#define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \105 _mshift, _mwidth, \106 _pshift, _pwidth, \107 _muxshift, _muxwidth, \108 _flags) \109 SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \110 _mshift, _mwidth, \111 _pshift, _pwidth, \112 _muxshift, _muxwidth, \113 0, _flags)114 115#define SUNXI_CCU_MP_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg, \116 _mshift, _mwidth, \117 _pshift, _pwidth, \118 _muxshift, _muxwidth, \119 _gate, _flags) \120 struct ccu_mp _struct = { \121 .enable = _gate, \122 .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \123 .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \124 .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \125 .common = { \126 .reg = _reg, \127 .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \128 _parents, \129 &ccu_mp_ops, \130 _flags), \131 } \132 }133 134static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)135{136 struct ccu_common *common = hw_to_ccu_common(hw);137 138 return container_of(common, struct ccu_mp, common);139}140 141extern const struct clk_ops ccu_mp_ops;142 143/*144 * Special class of M-P clock that supports MMC timing modes145 *146 * Since the MMC clock registers all follow the same layout, we can147 * simplify the macro for this particular case. In addition, as148 * switching modes also affects the output clock rate, we need to149 * have CLK_GET_RATE_NOCACHE for all these types of clocks.150 */151 152#define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg, \153 _flags) \154 struct ccu_mp _struct = { \155 .enable = BIT(31), \156 .m = _SUNXI_CCU_DIV(0, 4), \157 .p = _SUNXI_CCU_DIV(16, 2), \158 .mux = _SUNXI_CCU_MUX(24, 2), \159 .common = { \160 .reg = _reg, \161 .features = CCU_FEATURE_MMC_TIMING_SWITCH, \162 .hw.init = CLK_HW_INIT_PARENTS(_name, \163 _parents, \164 &ccu_mp_mmc_ops, \165 CLK_GET_RATE_NOCACHE | \166 _flags), \167 } \168 }169 170extern const struct clk_ops ccu_mp_mmc_ops;171 172#endif /* _CCU_MP_H_ */173