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_NM_H_
78c2ecf20Sopenharmony_ci#define _CCU_NM_H_
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "ccu_common.h"
128c2ecf20Sopenharmony_ci#include "ccu_div.h"
138c2ecf20Sopenharmony_ci#include "ccu_frac.h"
148c2ecf20Sopenharmony_ci#include "ccu_mult.h"
158c2ecf20Sopenharmony_ci#include "ccu_sdm.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * struct ccu_nm - Definition of an N-M clock
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * Clocks based on the formula parent * N / M
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_cistruct ccu_nm {
238c2ecf20Sopenharmony_ci	u32			enable;
248c2ecf20Sopenharmony_ci	u32			lock;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	struct ccu_mult_internal	n;
278c2ecf20Sopenharmony_ci	struct ccu_div_internal		m;
288c2ecf20Sopenharmony_ci	struct ccu_frac_internal	frac;
298c2ecf20Sopenharmony_ci	struct ccu_sdm_internal		sdm;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	unsigned int		fixed_post_div;
328c2ecf20Sopenharmony_ci	unsigned int		min_rate;
338c2ecf20Sopenharmony_ci	unsigned int		max_rate;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	struct ccu_common	common;
368c2ecf20Sopenharmony_ci};
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(_struct, _name, _parent, _reg,	\
398c2ecf20Sopenharmony_ci					_nshift, _nwidth,		\
408c2ecf20Sopenharmony_ci					_mshift, _mwidth,		\
418c2ecf20Sopenharmony_ci					_sdm_table, _sdm_en,		\
428c2ecf20Sopenharmony_ci					_sdm_reg, _sdm_reg_en,		\
438c2ecf20Sopenharmony_ci					_gate, _lock, _flags)		\
448c2ecf20Sopenharmony_ci	struct ccu_nm _struct = {					\
458c2ecf20Sopenharmony_ci		.enable		= _gate,				\
468c2ecf20Sopenharmony_ci		.lock		= _lock,				\
478c2ecf20Sopenharmony_ci		.n		= _SUNXI_CCU_MULT(_nshift, _nwidth),	\
488c2ecf20Sopenharmony_ci		.m		= _SUNXI_CCU_DIV(_mshift, _mwidth),	\
498c2ecf20Sopenharmony_ci		.sdm		= _SUNXI_CCU_SDM(_sdm_table, _sdm_en,	\
508c2ecf20Sopenharmony_ci						 _sdm_reg, _sdm_reg_en),\
518c2ecf20Sopenharmony_ci		.common		= {					\
528c2ecf20Sopenharmony_ci			.reg		= _reg,				\
538c2ecf20Sopenharmony_ci			.features	= CCU_FEATURE_SIGMA_DELTA_MOD,	\
548c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT(_name,		\
558c2ecf20Sopenharmony_ci						      _parent,		\
568c2ecf20Sopenharmony_ci						      &ccu_nm_ops,	\
578c2ecf20Sopenharmony_ci						      _flags),		\
588c2ecf20Sopenharmony_ci		},							\
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(_struct, _name, _parent, _reg,	\
628c2ecf20Sopenharmony_ci					 _nshift, _nwidth,		\
638c2ecf20Sopenharmony_ci					 _mshift, _mwidth,		\
648c2ecf20Sopenharmony_ci					 _frac_en, _frac_sel,		\
658c2ecf20Sopenharmony_ci					 _frac_rate_0, _frac_rate_1,	\
668c2ecf20Sopenharmony_ci					 _gate, _lock, _flags)		\
678c2ecf20Sopenharmony_ci	struct ccu_nm _struct = {					\
688c2ecf20Sopenharmony_ci		.enable		= _gate,				\
698c2ecf20Sopenharmony_ci		.lock		= _lock,				\
708c2ecf20Sopenharmony_ci		.n		= _SUNXI_CCU_MULT(_nshift, _nwidth),	\
718c2ecf20Sopenharmony_ci		.m		= _SUNXI_CCU_DIV(_mshift, _mwidth),	\
728c2ecf20Sopenharmony_ci		.frac		= _SUNXI_CCU_FRAC(_frac_en, _frac_sel,	\
738c2ecf20Sopenharmony_ci						  _frac_rate_0,		\
748c2ecf20Sopenharmony_ci						  _frac_rate_1),	\
758c2ecf20Sopenharmony_ci		.common		= {					\
768c2ecf20Sopenharmony_ci			.reg		= _reg,				\
778c2ecf20Sopenharmony_ci			.features	= CCU_FEATURE_FRACTIONAL,	\
788c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT(_name,		\
798c2ecf20Sopenharmony_ci						      _parent,		\
808c2ecf20Sopenharmony_ci						      &ccu_nm_ops,	\
818c2ecf20Sopenharmony_ci						      _flags),		\
828c2ecf20Sopenharmony_ci		},							\
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(_struct, _name, _parent,	\
868c2ecf20Sopenharmony_ci					     _reg, _min_rate,		\
878c2ecf20Sopenharmony_ci					     _nshift, _nwidth,		\
888c2ecf20Sopenharmony_ci					     _mshift, _mwidth,		\
898c2ecf20Sopenharmony_ci					     _frac_en, _frac_sel,	\
908c2ecf20Sopenharmony_ci					     _frac_rate_0, _frac_rate_1,\
918c2ecf20Sopenharmony_ci					     _gate, _lock, _flags)	\
928c2ecf20Sopenharmony_ci	struct ccu_nm _struct = {					\
938c2ecf20Sopenharmony_ci		.enable		= _gate,				\
948c2ecf20Sopenharmony_ci		.lock		= _lock,				\
958c2ecf20Sopenharmony_ci		.n		= _SUNXI_CCU_MULT(_nshift, _nwidth),	\
968c2ecf20Sopenharmony_ci		.m		= _SUNXI_CCU_DIV(_mshift, _mwidth),	\
978c2ecf20Sopenharmony_ci		.frac		= _SUNXI_CCU_FRAC(_frac_en, _frac_sel,	\
988c2ecf20Sopenharmony_ci						  _frac_rate_0,		\
998c2ecf20Sopenharmony_ci						  _frac_rate_1),	\
1008c2ecf20Sopenharmony_ci		.min_rate	= _min_rate,				\
1018c2ecf20Sopenharmony_ci		.common		= {					\
1028c2ecf20Sopenharmony_ci			.reg		= _reg,				\
1038c2ecf20Sopenharmony_ci			.features	= CCU_FEATURE_FRACTIONAL,	\
1048c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT(_name,		\
1058c2ecf20Sopenharmony_ci						      _parent,		\
1068c2ecf20Sopenharmony_ci						      &ccu_nm_ops,	\
1078c2ecf20Sopenharmony_ci						      _flags),		\
1088c2ecf20Sopenharmony_ci		},							\
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name,	\
1128c2ecf20Sopenharmony_ci						 _parent, _reg,		\
1138c2ecf20Sopenharmony_ci						 _min_rate, _max_rate,	\
1148c2ecf20Sopenharmony_ci						 _nshift, _nwidth,	\
1158c2ecf20Sopenharmony_ci						 _mshift, _mwidth,	\
1168c2ecf20Sopenharmony_ci						 _frac_en, _frac_sel,	\
1178c2ecf20Sopenharmony_ci						 _frac_rate_0,		\
1188c2ecf20Sopenharmony_ci						 _frac_rate_1,		\
1198c2ecf20Sopenharmony_ci						 _gate, _lock, _flags)	\
1208c2ecf20Sopenharmony_ci	struct ccu_nm _struct = {					\
1218c2ecf20Sopenharmony_ci		.enable		= _gate,				\
1228c2ecf20Sopenharmony_ci		.lock		= _lock,				\
1238c2ecf20Sopenharmony_ci		.n		= _SUNXI_CCU_MULT(_nshift, _nwidth),	\
1248c2ecf20Sopenharmony_ci		.m		= _SUNXI_CCU_DIV(_mshift, _mwidth),	\
1258c2ecf20Sopenharmony_ci		.frac		= _SUNXI_CCU_FRAC(_frac_en, _frac_sel,	\
1268c2ecf20Sopenharmony_ci						  _frac_rate_0,		\
1278c2ecf20Sopenharmony_ci						  _frac_rate_1),	\
1288c2ecf20Sopenharmony_ci		.min_rate	= _min_rate,				\
1298c2ecf20Sopenharmony_ci		.max_rate	= _max_rate,				\
1308c2ecf20Sopenharmony_ci		.common		= {					\
1318c2ecf20Sopenharmony_ci			.reg		= _reg,				\
1328c2ecf20Sopenharmony_ci			.features	= CCU_FEATURE_FRACTIONAL,	\
1338c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT(_name,		\
1348c2ecf20Sopenharmony_ci						      _parent,		\
1358c2ecf20Sopenharmony_ci						      &ccu_nm_ops,	\
1368c2ecf20Sopenharmony_ci						      _flags),		\
1378c2ecf20Sopenharmony_ci		},							\
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci#define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg,	\
1418c2ecf20Sopenharmony_ci				    _nshift, _nwidth,			\
1428c2ecf20Sopenharmony_ci				    _mshift, _mwidth,			\
1438c2ecf20Sopenharmony_ci				    _gate, _lock, _flags)		\
1448c2ecf20Sopenharmony_ci	struct ccu_nm _struct = {					\
1458c2ecf20Sopenharmony_ci		.enable		= _gate,				\
1468c2ecf20Sopenharmony_ci		.lock		= _lock,				\
1478c2ecf20Sopenharmony_ci		.n		= _SUNXI_CCU_MULT(_nshift, _nwidth),	\
1488c2ecf20Sopenharmony_ci		.m		= _SUNXI_CCU_DIV(_mshift, _mwidth),	\
1498c2ecf20Sopenharmony_ci		.common		= {					\
1508c2ecf20Sopenharmony_ci			.reg		= _reg,				\
1518c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT(_name,		\
1528c2ecf20Sopenharmony_ci						      _parent,		\
1538c2ecf20Sopenharmony_ci						      &ccu_nm_ops,	\
1548c2ecf20Sopenharmony_ci						      _flags),		\
1558c2ecf20Sopenharmony_ci		},							\
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic inline struct ccu_nm *hw_to_ccu_nm(struct clk_hw *hw)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	struct ccu_common *common = hw_to_ccu_common(hw);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	return container_of(common, struct ccu_nm, common);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ciextern const struct clk_ops ccu_nm_ops;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#endif /* _CCU_NM_H_ */
168