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 *original_clk; 118 struct notifier_block pll_clk_nb; 119 struct clk_hw *pll[3]; 120 struct jh71x0_clk reg[]; 121 }; 122 123 const struct clk_ops *starfive_jh71x0_clk_ops(u32 max); 124 125 #endif 126