18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2016 Maxime Ripard. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef _CCU_MP_H_ 78c2ecf20Sopenharmony_ci#define _CCU_MP_H_ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/bitops.h> 108c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "ccu_common.h" 138c2ecf20Sopenharmony_ci#include "ccu_div.h" 148c2ecf20Sopenharmony_ci#include "ccu_mult.h" 158c2ecf20Sopenharmony_ci#include "ccu_mux.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * struct ccu_mp - Definition of an M-P clock 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Clocks based on the formula parent >> P / M 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_cistruct ccu_mp { 238c2ecf20Sopenharmony_ci u32 enable; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci struct ccu_div_internal m; 268c2ecf20Sopenharmony_ci struct ccu_div_internal p; 278c2ecf20Sopenharmony_ci struct ccu_mux_internal mux; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci unsigned int fixed_post_div; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci struct ccu_common common; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \ 358c2ecf20Sopenharmony_ci _mshift, _mwidth, \ 368c2ecf20Sopenharmony_ci _pshift, _pwidth, \ 378c2ecf20Sopenharmony_ci _muxshift, _muxwidth, \ 388c2ecf20Sopenharmony_ci _gate, _postdiv, _flags) \ 398c2ecf20Sopenharmony_ci struct ccu_mp _struct = { \ 408c2ecf20Sopenharmony_ci .enable = _gate, \ 418c2ecf20Sopenharmony_ci .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ 428c2ecf20Sopenharmony_ci .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \ 438c2ecf20Sopenharmony_ci .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \ 448c2ecf20Sopenharmony_ci .fixed_post_div = _postdiv, \ 458c2ecf20Sopenharmony_ci .common = { \ 468c2ecf20Sopenharmony_ci .reg = _reg, \ 478c2ecf20Sopenharmony_ci .features = CCU_FEATURE_FIXED_POSTDIV, \ 488c2ecf20Sopenharmony_ci .hw.init = CLK_HW_INIT_PARENTS(_name, \ 498c2ecf20Sopenharmony_ci _parents, \ 508c2ecf20Sopenharmony_ci &ccu_mp_ops, \ 518c2ecf20Sopenharmony_ci _flags), \ 528c2ecf20Sopenharmony_ci } \ 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ 568c2ecf20Sopenharmony_ci _mshift, _mwidth, \ 578c2ecf20Sopenharmony_ci _pshift, _pwidth, \ 588c2ecf20Sopenharmony_ci _muxshift, _muxwidth, \ 598c2ecf20Sopenharmony_ci _gate, _flags) \ 608c2ecf20Sopenharmony_ci struct ccu_mp _struct = { \ 618c2ecf20Sopenharmony_ci .enable = _gate, \ 628c2ecf20Sopenharmony_ci .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ 638c2ecf20Sopenharmony_ci .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \ 648c2ecf20Sopenharmony_ci .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \ 658c2ecf20Sopenharmony_ci .common = { \ 668c2ecf20Sopenharmony_ci .reg = _reg, \ 678c2ecf20Sopenharmony_ci .hw.init = CLK_HW_INIT_PARENTS(_name, \ 688c2ecf20Sopenharmony_ci _parents, \ 698c2ecf20Sopenharmony_ci &ccu_mp_ops, \ 708c2ecf20Sopenharmony_ci _flags), \ 718c2ecf20Sopenharmony_ci } \ 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg, \ 758c2ecf20Sopenharmony_ci _mshift, _mwidth, \ 768c2ecf20Sopenharmony_ci _pshift, _pwidth, \ 778c2ecf20Sopenharmony_ci _muxshift, _muxwidth, \ 788c2ecf20Sopenharmony_ci _flags) \ 798c2ecf20Sopenharmony_ci SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ 808c2ecf20Sopenharmony_ci _mshift, _mwidth, \ 818c2ecf20Sopenharmony_ci _pshift, _pwidth, \ 828c2ecf20Sopenharmony_ci _muxshift, _muxwidth, \ 838c2ecf20Sopenharmony_ci 0, _flags) 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct ccu_common *common = hw_to_ccu_common(hw); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci return container_of(common, struct ccu_mp, common); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciextern const struct clk_ops ccu_mp_ops; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* 958c2ecf20Sopenharmony_ci * Special class of M-P clock that supports MMC timing modes 968c2ecf20Sopenharmony_ci * 978c2ecf20Sopenharmony_ci * Since the MMC clock registers all follow the same layout, we can 988c2ecf20Sopenharmony_ci * simplify the macro for this particular case. In addition, as 998c2ecf20Sopenharmony_ci * switching modes also affects the output clock rate, we need to 1008c2ecf20Sopenharmony_ci * have CLK_GET_RATE_NOCACHE for all these types of clocks. 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ 1048c2ecf20Sopenharmony_ci _flags) \ 1058c2ecf20Sopenharmony_ci struct ccu_mp _struct = { \ 1068c2ecf20Sopenharmony_ci .enable = BIT(31), \ 1078c2ecf20Sopenharmony_ci .m = _SUNXI_CCU_DIV(0, 4), \ 1088c2ecf20Sopenharmony_ci .p = _SUNXI_CCU_DIV(16, 2), \ 1098c2ecf20Sopenharmony_ci .mux = _SUNXI_CCU_MUX(24, 2), \ 1108c2ecf20Sopenharmony_ci .common = { \ 1118c2ecf20Sopenharmony_ci .reg = _reg, \ 1128c2ecf20Sopenharmony_ci .features = CCU_FEATURE_MMC_TIMING_SWITCH, \ 1138c2ecf20Sopenharmony_ci .hw.init = CLK_HW_INIT_PARENTS(_name, \ 1148c2ecf20Sopenharmony_ci _parents, \ 1158c2ecf20Sopenharmony_ci &ccu_mp_mmc_ops, \ 1168c2ecf20Sopenharmony_ci CLK_GET_RATE_NOCACHE | \ 1178c2ecf20Sopenharmony_ci _flags), \ 1188c2ecf20Sopenharmony_ci } \ 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciextern const struct clk_ops ccu_mp_mmc_ops; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#endif /* _CCU_MP_H_ */ 124