xref: /openbmc/linux/drivers/clk/sprd/div.h (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
17a12f838SNishad Kamdar /* SPDX-License-Identifier: GPL-2.0 */
2e3f05d3bSChunyan Zhang //
3e3f05d3bSChunyan Zhang // Spreadtrum divider clock driver
4e3f05d3bSChunyan Zhang //
5e3f05d3bSChunyan Zhang // Copyright (C) 2017 Spreadtrum, Inc.
6e3f05d3bSChunyan Zhang // Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
7e3f05d3bSChunyan Zhang 
8e3f05d3bSChunyan Zhang #ifndef _SPRD_DIV_H_
9e3f05d3bSChunyan Zhang #define _SPRD_DIV_H_
10e3f05d3bSChunyan Zhang 
11e3f05d3bSChunyan Zhang #include "common.h"
12e3f05d3bSChunyan Zhang 
13e3f05d3bSChunyan Zhang /**
14e3f05d3bSChunyan Zhang  * struct sprd_div_internal - Internal divider description
15e3f05d3bSChunyan Zhang  * @shift: Bit offset of the divider in its register
16e3f05d3bSChunyan Zhang  * @width: Width of the divider field in its register
17e3f05d3bSChunyan Zhang  *
18e3f05d3bSChunyan Zhang  * That structure represents a single divider, and is meant to be
19e3f05d3bSChunyan Zhang  * embedded in other structures representing the various clock
20e3f05d3bSChunyan Zhang  * classes.
21e3f05d3bSChunyan Zhang  */
22e3f05d3bSChunyan Zhang struct sprd_div_internal {
23e3f05d3bSChunyan Zhang 	u8	shift;
24e3f05d3bSChunyan Zhang 	u8	width;
25e3f05d3bSChunyan Zhang };
26e3f05d3bSChunyan Zhang 
27e3f05d3bSChunyan Zhang #define _SPRD_DIV_CLK(_shift, _width)	\
28e3f05d3bSChunyan Zhang 	{				\
29e3f05d3bSChunyan Zhang 		.shift	= _shift,	\
30e3f05d3bSChunyan Zhang 		.width	= _width,	\
31e3f05d3bSChunyan Zhang 	}
32e3f05d3bSChunyan Zhang 
33e3f05d3bSChunyan Zhang struct sprd_div {
34e3f05d3bSChunyan Zhang 	struct sprd_div_internal	div;
35e3f05d3bSChunyan Zhang 	struct sprd_clk_common	common;
36e3f05d3bSChunyan Zhang };
37e3f05d3bSChunyan Zhang 
38*ea8ca310SChunyan Zhang #define SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg,		\
39*ea8ca310SChunyan Zhang 				_shift, _width, _flags, _fn)		\
40e3f05d3bSChunyan Zhang 	struct sprd_div _struct = {					\
41e3f05d3bSChunyan Zhang 		.div	= _SPRD_DIV_CLK(_shift, _width),		\
42e3f05d3bSChunyan Zhang 		.common	= {						\
43e3f05d3bSChunyan Zhang 			.regmap		= NULL,				\
44e3f05d3bSChunyan Zhang 			.reg		= _reg,				\
45*ea8ca310SChunyan Zhang 			.hw.init	= _fn(_name, _parent,		\
46*ea8ca310SChunyan Zhang 					      &sprd_div_ops, _flags),	\
47e3f05d3bSChunyan Zhang 		}							\
48e3f05d3bSChunyan Zhang 	}
49e3f05d3bSChunyan Zhang 
50*ea8ca310SChunyan Zhang #define SPRD_DIV_CLK(_struct, _name, _parent, _reg,			\
51*ea8ca310SChunyan Zhang 		     _shift, _width, _flags)				\
52*ea8ca310SChunyan Zhang 	SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg,		\
53*ea8ca310SChunyan Zhang 				_shift, _width, _flags, CLK_HW_INIT)
54*ea8ca310SChunyan Zhang 
55*ea8ca310SChunyan Zhang #define SPRD_DIV_CLK_HW(_struct, _name, _parent, _reg,			\
56*ea8ca310SChunyan Zhang 			_shift, _width, _flags)				\
57*ea8ca310SChunyan Zhang 	SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg,		\
58*ea8ca310SChunyan Zhang 				_shift, _width, _flags, CLK_HW_INIT_HW)
59*ea8ca310SChunyan Zhang 
hw_to_sprd_div(const struct clk_hw * hw)60e3f05d3bSChunyan Zhang static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw)
61e3f05d3bSChunyan Zhang {
62e3f05d3bSChunyan Zhang 	struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
63e3f05d3bSChunyan Zhang 
64e3f05d3bSChunyan Zhang 	return container_of(common, struct sprd_div, common);
65e3f05d3bSChunyan Zhang }
66e3f05d3bSChunyan Zhang 
67e3f05d3bSChunyan Zhang unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
68e3f05d3bSChunyan Zhang 					  const struct sprd_div_internal *div,
69e3f05d3bSChunyan Zhang 					  unsigned long parent_rate);
70e3f05d3bSChunyan Zhang 
71e3f05d3bSChunyan Zhang int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
72e3f05d3bSChunyan Zhang 			     const struct sprd_div_internal *div,
73e3f05d3bSChunyan Zhang 			     unsigned long rate,
74e3f05d3bSChunyan Zhang 			     unsigned long parent_rate);
75e3f05d3bSChunyan Zhang 
76e3f05d3bSChunyan Zhang extern const struct clk_ops sprd_div_ops;
77e3f05d3bSChunyan Zhang 
78e3f05d3bSChunyan Zhang #endif /* _SPRD_DIV_H_ */
79