1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (c) 2015 Endless Mobile, Inc.
4  * Author: Carlo Caione <carlo@endlessm.com>
5  */
6 
7 #ifndef __CLKC_H
8 #define __CLKC_H
9 
10 #include <linux/clk-provider.h>
11 #include "clk-regmap.h"
12 
13 #define PMASK(width)			GENMASK(width - 1, 0)
14 #define SETPMASK(width, shift)		GENMASK(shift + width - 1, shift)
15 #define CLRPMASK(width, shift)		(~SETPMASK(width, shift))
16 
17 #define PARM_GET(width, shift, reg)					\
18 	(((reg) & SETPMASK(width, shift)) >> (shift))
19 #define PARM_SET(width, shift, reg, val)				\
20 	(((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
21 
22 #define MESON_PARM_APPLICABLE(p)		(!!((p)->width))
23 
24 struct parm {
25 	u16	reg_off;
26 	u8	shift;
27 	u8	width;
28 };
29 
meson_parm_read(struct regmap * map,struct parm * p)30 static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
31 {
32 	unsigned int val;
33 
34 	regmap_read(map, p->reg_off, &val);
35 	return PARM_GET(p->width, p->shift, val);
36 }
37 
meson_parm_write(struct regmap * map,struct parm * p,unsigned int val)38 static inline void meson_parm_write(struct regmap *map, struct parm *p,
39 				    unsigned int val)
40 {
41 	regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
42 			   val << p->shift);
43 }
44 
45 
46 struct pll_rate_table {
47 	unsigned long	rate;
48 	u16		m;
49 	u16		n;
50 	u16		od;
51 	u16		od2;
52 	u16		od3;
53 };
54 
55 #define PLL_RATE(_r, _m, _n, _od)					\
56 	{								\
57 		.rate		= (_r),					\
58 		.m		= (_m),					\
59 		.n		= (_n),					\
60 		.od		= (_od),				\
61 	}
62 
63 #define CLK_MESON_PLL_ROUND_CLOSEST	BIT(0)
64 
65 struct meson_clk_pll_data {
66 	struct parm m;
67 	struct parm n;
68 	struct parm frac;
69 	struct parm od;
70 	struct parm od2;
71 	struct parm od3;
72 	struct parm l;
73 	struct parm rst;
74 	const struct reg_sequence *init_regs;
75 	unsigned int init_count;
76 	const struct pll_rate_table *table;
77 	u8 flags;
78 };
79 
80 #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
81 
82 struct meson_clk_mpll_data {
83 	struct parm sdm;
84 	struct parm sdm_en;
85 	struct parm n2;
86 	struct parm ssen;
87 	struct parm misc;
88 	spinlock_t *lock;
89 	u8 flags;
90 };
91 
92 #define CLK_MESON_MPLL_ROUND_CLOSEST	BIT(0)
93 
94 struct meson_clk_phase_data {
95 	struct parm ph;
96 };
97 
98 int meson_clk_degrees_from_val(unsigned int val, unsigned int width);
99 unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width);
100 
101 #define MESON_GATE(_name, _reg, _bit)					\
102 struct clk_regmap _name = {						\
103 	.data = &(struct clk_regmap_gate_data){				\
104 		.offset = (_reg),					\
105 		.bit_idx = (_bit),					\
106 	},								\
107 	.hw.init = &(struct clk_init_data) {				\
108 		.name = #_name,						\
109 		.ops = &clk_regmap_gate_ops,				\
110 		.parent_names = (const char *[]){ "clk81" },		\
111 		.num_parents = 1,					\
112 		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),	\
113 	},								\
114 };
115 
116 /* clk_ops */
117 extern const struct clk_ops meson_clk_pll_ro_ops;
118 extern const struct clk_ops meson_clk_pll_ops;
119 extern const struct clk_ops meson_clk_cpu_ops;
120 extern const struct clk_ops meson_clk_mpll_ro_ops;
121 extern const struct clk_ops meson_clk_mpll_ops;
122 extern const struct clk_ops meson_clk_phase_ops;
123 
124 #endif /* __CLKC_H */
125