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_DIV_H_
78c2ecf20Sopenharmony_ci#define _CCU_DIV_H_
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "ccu_common.h"
128c2ecf20Sopenharmony_ci#include "ccu_mux.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci/**
158c2ecf20Sopenharmony_ci * struct ccu_div_internal - Internal divider description
168c2ecf20Sopenharmony_ci * @shift: Bit offset of the divider in its register
178c2ecf20Sopenharmony_ci * @width: Width of the divider field in its register
188c2ecf20Sopenharmony_ci * @max: Maximum value allowed for that divider. This is the
198c2ecf20Sopenharmony_ci *       arithmetic value, not the maximum value to be set in the
208c2ecf20Sopenharmony_ci *       register.
218c2ecf20Sopenharmony_ci * @flags: clk_divider flags to apply on this divider
228c2ecf20Sopenharmony_ci * @table: Divider table pointer (if applicable)
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * That structure represents a single divider, and is meant to be
258c2ecf20Sopenharmony_ci * embedded in other structures representing the various clock
268c2ecf20Sopenharmony_ci * classes.
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci * It is basically a wrapper around the clk_divider functions
298c2ecf20Sopenharmony_ci * arguments.
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_cistruct ccu_div_internal {
328c2ecf20Sopenharmony_ci	u8			shift;
338c2ecf20Sopenharmony_ci	u8			width;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	u32			max;
368c2ecf20Sopenharmony_ci	u32			offset;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	u32			flags;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	struct clk_div_table	*table;
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags)	\
448c2ecf20Sopenharmony_ci	{								\
458c2ecf20Sopenharmony_ci		.shift	= _shift,					\
468c2ecf20Sopenharmony_ci		.width	= _width,					\
478c2ecf20Sopenharmony_ci		.flags	= _flags,					\
488c2ecf20Sopenharmony_ci		.table	= _table,					\
498c2ecf20Sopenharmony_ci	}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table)			\
528c2ecf20Sopenharmony_ci	_SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
558c2ecf20Sopenharmony_ci	{								\
568c2ecf20Sopenharmony_ci		.shift	= _shift,					\
578c2ecf20Sopenharmony_ci		.width	= _width,					\
588c2ecf20Sopenharmony_ci		.flags	= _flags,					\
598c2ecf20Sopenharmony_ci		.max	= _max,						\
608c2ecf20Sopenharmony_ci		.offset	= _off,						\
618c2ecf20Sopenharmony_ci	}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags)		\
648c2ecf20Sopenharmony_ci	_SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags)			\
678c2ecf20Sopenharmony_ci	_SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV_MAX(_shift, _width, _max)			\
708c2ecf20Sopenharmony_ci	_SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset)			\
738c2ecf20Sopenharmony_ci	_SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define _SUNXI_CCU_DIV(_shift, _width)					\
768c2ecf20Sopenharmony_ci	_SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistruct ccu_div {
798c2ecf20Sopenharmony_ci	u32			enable;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	struct ccu_div_internal	div;
828c2ecf20Sopenharmony_ci	struct ccu_mux_internal	mux;
838c2ecf20Sopenharmony_ci	struct ccu_common	common;
848c2ecf20Sopenharmony_ci	unsigned int		fixed_post_div;
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,	\
888c2ecf20Sopenharmony_ci				      _shift, _width,			\
898c2ecf20Sopenharmony_ci				      _table, _gate, _flags)		\
908c2ecf20Sopenharmony_ci	struct ccu_div _struct = {					\
918c2ecf20Sopenharmony_ci		.div		= _SUNXI_CCU_DIV_TABLE(_shift, _width,	\
928c2ecf20Sopenharmony_ci						       _table),		\
938c2ecf20Sopenharmony_ci		.enable		= _gate,				\
948c2ecf20Sopenharmony_ci		.common	= {						\
958c2ecf20Sopenharmony_ci			.reg		= _reg,				\
968c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT(_name,		\
978c2ecf20Sopenharmony_ci						      _parent,		\
988c2ecf20Sopenharmony_ci						      &ccu_div_ops,	\
998c2ecf20Sopenharmony_ci						      _flags),		\
1008c2ecf20Sopenharmony_ci		}							\
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci#define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,		\
1058c2ecf20Sopenharmony_ci			    _shift, _width,				\
1068c2ecf20Sopenharmony_ci			    _table, _flags)				\
1078c2ecf20Sopenharmony_ci	SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,	\
1088c2ecf20Sopenharmony_ci				      _shift, _width, _table, 0,	\
1098c2ecf20Sopenharmony_ci				      _flags)
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci#define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,			\
1128c2ecf20Sopenharmony_ci					_parents, _table,		\
1138c2ecf20Sopenharmony_ci					_reg,				\
1148c2ecf20Sopenharmony_ci					_mshift, _mwidth,		\
1158c2ecf20Sopenharmony_ci					_muxshift, _muxwidth,		\
1168c2ecf20Sopenharmony_ci					_gate, _flags)			\
1178c2ecf20Sopenharmony_ci	struct ccu_div _struct = {					\
1188c2ecf20Sopenharmony_ci		.enable	= _gate,					\
1198c2ecf20Sopenharmony_ci		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
1208c2ecf20Sopenharmony_ci		.mux	= _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
1218c2ecf20Sopenharmony_ci		.common	= {						\
1228c2ecf20Sopenharmony_ci			.reg		= _reg,				\
1238c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
1248c2ecf20Sopenharmony_ci							      _parents, \
1258c2ecf20Sopenharmony_ci							      &ccu_div_ops, \
1268c2ecf20Sopenharmony_ci							      _flags),	\
1278c2ecf20Sopenharmony_ci		},							\
1288c2ecf20Sopenharmony_ci	}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci#define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
1318c2ecf20Sopenharmony_ci				  _mshift, _mwidth, _muxshift, _muxwidth, \
1328c2ecf20Sopenharmony_ci				  _gate, _flags)			\
1338c2ecf20Sopenharmony_ci	SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,			\
1348c2ecf20Sopenharmony_ci					_parents, NULL,			\
1358c2ecf20Sopenharmony_ci					_reg, _mshift, _mwidth,		\
1368c2ecf20Sopenharmony_ci					_muxshift, _muxwidth,		\
1378c2ecf20Sopenharmony_ci					_gate, _flags)
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci#define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,		\
1408c2ecf20Sopenharmony_ci			     _mshift, _mwidth, _muxshift, _muxwidth,	\
1418c2ecf20Sopenharmony_ci			     _flags)					\
1428c2ecf20Sopenharmony_ci	SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,			\
1438c2ecf20Sopenharmony_ci					_parents, NULL,			\
1448c2ecf20Sopenharmony_ci					_reg, _mshift, _mwidth,		\
1458c2ecf20Sopenharmony_ci					_muxshift, _muxwidth,		\
1468c2ecf20Sopenharmony_ci					0, _flags)
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci#define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,		\
1508c2ecf20Sopenharmony_ci			      _mshift, _mwidth,	_gate,			\
1518c2ecf20Sopenharmony_ci			      _flags)					\
1528c2ecf20Sopenharmony_ci	struct ccu_div _struct = {					\
1538c2ecf20Sopenharmony_ci		.enable	= _gate,					\
1548c2ecf20Sopenharmony_ci		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
1558c2ecf20Sopenharmony_ci		.common	= {						\
1568c2ecf20Sopenharmony_ci			.reg		= _reg,				\
1578c2ecf20Sopenharmony_ci			.hw.init	= CLK_HW_INIT(_name,		\
1588c2ecf20Sopenharmony_ci						      _parent,		\
1598c2ecf20Sopenharmony_ci						      &ccu_div_ops,	\
1608c2ecf20Sopenharmony_ci						      _flags),		\
1618c2ecf20Sopenharmony_ci		},							\
1628c2ecf20Sopenharmony_ci	}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci#define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,	\
1658c2ecf20Sopenharmony_ci		    _flags)						\
1668c2ecf20Sopenharmony_ci	SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,		\
1678c2ecf20Sopenharmony_ci			      _mshift, _mwidth, 0, _flags)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct ccu_common *common = hw_to_ccu_common(hw);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	return container_of(common, struct ccu_div, common);
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciextern const struct clk_ops ccu_div_ops;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci#endif /* _CCU_DIV_H_ */
179