1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __CLK_STARFIVE_JH71X0_H
3 #define __CLK_STARFIVE_JH71X0_H
4 
5 #include <linux/bits.h>
6 #include <linux/clk-provider.h>
7 #include <linux/device.h>
8 #include <linux/spinlock.h>
9 
10 /* register fields */
11 #define JH71X0_CLK_ENABLE	BIT(31)
12 #define JH71X0_CLK_INVERT	BIT(30)
13 #define JH71X0_CLK_MUX_MASK	GENMASK(27, 24)
14 #define JH71X0_CLK_MUX_SHIFT	24
15 #define JH71X0_CLK_DIV_MASK	GENMASK(23, 0)
16 #define JH71X0_CLK_FRAC_MASK	GENMASK(15, 8)
17 #define JH71X0_CLK_FRAC_SHIFT	8
18 #define JH71X0_CLK_INT_MASK	GENMASK(7, 0)
19 
20 /* fractional divider min/max */
21 #define JH71X0_CLK_FRAC_MIN	100UL
22 #define JH71X0_CLK_FRAC_MAX	25599UL
23 
24 /* clock data */
25 struct jh71x0_clk_data {
26 	const char *name;
27 	unsigned long flags;
28 	u32 max;
29 	u8 parents[4];
30 };
31 
32 #define JH71X0_GATE(_idx, _name, _flags, _parent)				\
33 [_idx] = {									\
34 	.name = _name,								\
35 	.flags = CLK_SET_RATE_PARENT | (_flags),				\
36 	.max = JH71X0_CLK_ENABLE,						\
37 	.parents = { [0] = _parent },						\
38 }
39 
40 #define JH71X0__DIV(_idx, _name, _max, _parent)					\
41 [_idx] = {									\
42 	.name = _name,								\
43 	.flags = 0,								\
44 	.max = _max,								\
45 	.parents = { [0] = _parent },						\
46 }
47 
48 #define JH71X0_GDIV(_idx, _name, _flags, _max, _parent)				\
49 [_idx] = {									\
50 	.name = _name,								\
51 	.flags = _flags,							\
52 	.max = JH71X0_CLK_ENABLE | (_max),					\
53 	.parents = { [0] = _parent },						\
54 }
55 
56 #define JH71X0_FDIV(_idx, _name, _parent)					\
57 [_idx] = {									\
58 	.name = _name,								\
59 	.flags = 0,								\
60 	.max = JH71X0_CLK_FRAC_MAX,						\
61 	.parents = { [0] = _parent },						\
62 }
63 
64 #define JH71X0__MUX(_idx, _name, _nparents, ...)				\
65 [_idx] = {									\
66 	.name = _name,								\
67 	.flags = 0,								\
68 	.max = ((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT,			\
69 	.parents = { __VA_ARGS__ },						\
70 }
71 
72 #define JH71X0_GMUX(_idx, _name, _flags, _nparents, ...)			\
73 [_idx] = {									\
74 	.name = _name,								\
75 	.flags = _flags,							\
76 	.max = JH71X0_CLK_ENABLE |						\
77 		(((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT),			\
78 	.parents = { __VA_ARGS__ },						\
79 }
80 
81 #define JH71X0_MDIV(_idx, _name, _max, _nparents, ...)				\
82 [_idx] = {									\
83 	.name = _name,								\
84 	.flags = 0,								\
85 	.max = (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max),		\
86 	.parents = { __VA_ARGS__ },						\
87 }
88 
89 #define JH71X0__GMD(_idx, _name, _flags, _max, _nparents, ...)			\
90 [_idx] = {									\
91 	.name = _name,								\
92 	.flags = _flags,							\
93 	.max = JH71X0_CLK_ENABLE |						\
94 		(((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max),		\
95 	.parents = { __VA_ARGS__ },						\
96 }
97 
98 #define JH71X0__INV(_idx, _name, _parent)					\
99 [_idx] = {									\
100 	.name = _name,								\
101 	.flags = CLK_SET_RATE_PARENT,						\
102 	.max = JH71X0_CLK_INVERT,						\
103 	.parents = { [0] = _parent },						\
104 }
105 
106 struct jh71x0_clk {
107 	struct clk_hw hw;
108 	unsigned int idx;
109 	unsigned int max_div;
110 };
111 
112 struct jh71x0_clk_priv {
113 	/* protect clk enable and set rate/parent from happening at the same time */
114 	spinlock_t rmw_lock;
115 	struct device *dev;
116 	void __iomem *base;
117 	struct clk_hw *pll[3];
118 	struct jh71x0_clk reg[];
119 };
120 
121 const struct clk_ops *starfive_jh71x0_clk_ops(u32 max);
122 
123 #endif
124