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