xref: /linux/include/linux/clk/analogbits-wrpll-cln28hpc.h (revision 56fb34d86e875dbb0d3e6a81c5d3d035db373031)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2018-2019 SiFive, Inc.
4  * Wesley Terpstra
5  * Paul Walmsley
6  */
7 
8 #ifndef __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
9 #define __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
10 
11 #include <linux/types.h>
12 
13 /* DIVQ_VALUES: number of valid DIVQ values */
14 #define DIVQ_VALUES				6
15 
16 /*
17  * Bit definitions for struct wrpll_cfg.flags
18  *
19  * WRPLL_FLAGS_BYPASS_FLAG: if set, the PLL is either in bypass, or should be
20  *	programmed to enter bypass
21  * WRPLL_FLAGS_RESET_FLAG: if set, the PLL is in reset
22  * WRPLL_FLAGS_INT_FEEDBACK_FLAG: if set, the PLL is configured for internal
23  *	feedback mode
24  * WRPLL_FLAGS_EXT_FEEDBACK_FLAG: if set, the PLL is configured for external
25  *	feedback mode (not yet supported by this driver)
26  */
27 #define WRPLL_FLAGS_BYPASS_SHIFT		0
28 #define WRPLL_FLAGS_BYPASS_MASK		BIT(WRPLL_FLAGS_BYPASS_SHIFT)
29 #define WRPLL_FLAGS_RESET_SHIFT		1
30 #define WRPLL_FLAGS_RESET_MASK		BIT(WRPLL_FLAGS_RESET_SHIFT)
31 #define WRPLL_FLAGS_INT_FEEDBACK_SHIFT	2
32 #define WRPLL_FLAGS_INT_FEEDBACK_MASK	BIT(WRPLL_FLAGS_INT_FEEDBACK_SHIFT)
33 #define WRPLL_FLAGS_EXT_FEEDBACK_SHIFT	3
34 #define WRPLL_FLAGS_EXT_FEEDBACK_MASK	BIT(WRPLL_FLAGS_EXT_FEEDBACK_SHIFT)
35 
36 /**
37  * struct wrpll_cfg - WRPLL configuration values
38  * @divr: reference divider value (6 bits), as presented to the PLL signals
39  * @divf: feedback divider value (9 bits), as presented to the PLL signals
40  * @divq: output divider value (3 bits), as presented to the PLL signals
41  * @flags: PLL configuration flags.  See above for more information
42  * @range: PLL loop filter range.  See below for more information
43  * @output_rate_cache: cached output rates, swept across DIVQ
44  * @parent_rate: PLL refclk rate for which values are valid
45  * @max_r: maximum possible R divider value, given @parent_rate
46  * @init_r: initial R divider value to start the search from
47  *
48  * @divr, @divq, @divq, @range represent what the PLL expects to see
49  * on its input signals.  Thus @divr and @divf are the actual divisors
50  * minus one.  @divq is a power-of-two divider; for example, 1 =
51  * divide-by-2 and 6 = divide-by-64.  0 is an invalid @divq value.
52  *
53  * When initially passing a struct wrpll_cfg record, the
54  * record should be zero-initialized with the exception of the @flags
55  * field.  The only flag bits that need to be set are either
56  * WRPLL_FLAGS_INT_FEEDBACK or WRPLL_FLAGS_EXT_FEEDBACK.
57  */
58 struct wrpll_cfg {
59 	u8 divr;
60 	u8 divq;
61 	u8 range;
62 	u8 flags;
63 	u16 divf;
64 /* private: */
65 	u32 output_rate_cache[DIVQ_VALUES];
66 	unsigned long parent_rate;
67 	u8 max_r;
68 	u8 init_r;
69 };
70 
71 int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
72 			     unsigned long parent_rate);
73 
74 unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c);
75 
76 unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
77 				     unsigned long parent_rate);
78 
79 #endif /* __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H */
80