xref: /OK3568_Linux_fs/kernel/drivers/clk/bcm/clk-iproc.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2014 Broadcom Corporation
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or
5*4882a593Smuzhiyun  * modify it under the terms of the GNU General Public License as
6*4882a593Smuzhiyun  * published by the Free Software Foundation version 2.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9*4882a593Smuzhiyun  * kind, whether express or implied; without even the implied warranty
10*4882a593Smuzhiyun  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11*4882a593Smuzhiyun  * GNU General Public License for more details.
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #ifndef _CLK_IPROC_H
15*4882a593Smuzhiyun #define _CLK_IPROC_H
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <linux/kernel.h>
18*4882a593Smuzhiyun #include <linux/list.h>
19*4882a593Smuzhiyun #include <linux/spinlock.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/device.h>
22*4882a593Smuzhiyun #include <linux/of.h>
23*4882a593Smuzhiyun #include <linux/clk-provider.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define IPROC_CLK_NAME_LEN 25
26*4882a593Smuzhiyun #define IPROC_CLK_INVALID_OFFSET 0xffffffff
27*4882a593Smuzhiyun #define bit_mask(width) ((1 << (width)) - 1)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* clocks that should not be disabled at runtime */
30*4882a593Smuzhiyun #define IPROC_CLK_AON BIT(0)
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun /* PLL that requires gating through ASIU */
33*4882a593Smuzhiyun #define IPROC_CLK_PLL_ASIU BIT(1)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun /* PLL that has fractional part of the NDIV */
36*4882a593Smuzhiyun #define IPROC_CLK_PLL_HAS_NDIV_FRAC BIT(2)
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /*
39*4882a593Smuzhiyun  * Some of the iProc PLL/clocks may have an ASIC bug that requires read back
40*4882a593Smuzhiyun  * of the same register following the write to flush the write transaction into
41*4882a593Smuzhiyun  * the intended register
42*4882a593Smuzhiyun  */
43*4882a593Smuzhiyun #define IPROC_CLK_NEEDS_READ_BACK BIT(3)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun  * Some PLLs require the PLL SW override bit to be set before changes can be
47*4882a593Smuzhiyun  * applied to the PLL
48*4882a593Smuzhiyun  */
49*4882a593Smuzhiyun #define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /*
52*4882a593Smuzhiyun  * Some PLLs use a different way to control clock power, via the PWRDWN bit in
53*4882a593Smuzhiyun  * the PLL control register
54*4882a593Smuzhiyun  */
55*4882a593Smuzhiyun #define IPROC_CLK_EMBED_PWRCTRL BIT(5)
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /*
58*4882a593Smuzhiyun  * Some PLLs have separate registers for Status and Control.  Identify this to
59*4882a593Smuzhiyun  * let the driver know if additional registers need to be used
60*4882a593Smuzhiyun  */
61*4882a593Smuzhiyun #define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /*
64*4882a593Smuzhiyun  * Some PLLs have an additional divide by 2 in master clock calculation;
65*4882a593Smuzhiyun  * MCLK = VCO_freq / (Mdiv * 2). Identify this to let the driver know
66*4882a593Smuzhiyun  * of modified calculations
67*4882a593Smuzhiyun  */
68*4882a593Smuzhiyun #define IPROC_CLK_MCLK_DIV_BY_2 BIT(7)
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun /*
71*4882a593Smuzhiyun  * Some PLLs provide a look up table for the leaf clock frequencies and
72*4882a593Smuzhiyun  * auto calculates VCO frequency parameters based on the provided leaf
73*4882a593Smuzhiyun  * clock frequencies. They have a user mode that allows the divider
74*4882a593Smuzhiyun  * controls to be determined by the user
75*4882a593Smuzhiyun  */
76*4882a593Smuzhiyun #define IPROC_CLK_PLL_USER_MODE_ON BIT(8)
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun  * Some PLLs have an active low reset
80*4882a593Smuzhiyun  */
81*4882a593Smuzhiyun #define IPROC_CLK_PLL_RESET_ACTIVE_LOW BIT(9)
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /*
84*4882a593Smuzhiyun  * Calculate the PLL parameters are runtime, instead of using table
85*4882a593Smuzhiyun  */
86*4882a593Smuzhiyun #define IPROC_CLK_PLL_CALC_PARAM BIT(10)
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /*
89*4882a593Smuzhiyun  * Parameters for VCO frequency configuration
90*4882a593Smuzhiyun  *
91*4882a593Smuzhiyun  * VCO frequency =
92*4882a593Smuzhiyun  * ((ndiv_int + ndiv_frac / 2^20) * (ref freqeuncy  / pdiv)
93*4882a593Smuzhiyun  */
94*4882a593Smuzhiyun struct iproc_pll_vco_param {
95*4882a593Smuzhiyun 	unsigned long rate;
96*4882a593Smuzhiyun 	unsigned int ndiv_int;
97*4882a593Smuzhiyun 	unsigned int ndiv_frac;
98*4882a593Smuzhiyun 	unsigned int pdiv;
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun struct iproc_clk_reg_op {
102*4882a593Smuzhiyun 	unsigned int offset;
103*4882a593Smuzhiyun 	unsigned int shift;
104*4882a593Smuzhiyun 	unsigned int width;
105*4882a593Smuzhiyun };
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun /*
108*4882a593Smuzhiyun  * Clock gating control at the top ASIU level
109*4882a593Smuzhiyun  */
110*4882a593Smuzhiyun struct iproc_asiu_gate {
111*4882a593Smuzhiyun 	unsigned int offset;
112*4882a593Smuzhiyun 	unsigned int en_shift;
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun /*
116*4882a593Smuzhiyun  * Control of powering on/off of a PLL
117*4882a593Smuzhiyun  *
118*4882a593Smuzhiyun  * Before powering off a PLL, input isolation (ISO) needs to be enabled
119*4882a593Smuzhiyun  */
120*4882a593Smuzhiyun struct iproc_pll_aon_pwr_ctrl {
121*4882a593Smuzhiyun 	unsigned int offset;
122*4882a593Smuzhiyun 	unsigned int pwr_width;
123*4882a593Smuzhiyun 	unsigned int pwr_shift;
124*4882a593Smuzhiyun 	unsigned int iso_shift;
125*4882a593Smuzhiyun };
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun /*
128*4882a593Smuzhiyun  * Control of the PLL reset
129*4882a593Smuzhiyun  */
130*4882a593Smuzhiyun struct iproc_pll_reset_ctrl {
131*4882a593Smuzhiyun 	unsigned int offset;
132*4882a593Smuzhiyun 	unsigned int reset_shift;
133*4882a593Smuzhiyun 	unsigned int p_reset_shift;
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun  * Control of the Ki, Kp, and Ka parameters
138*4882a593Smuzhiyun  */
139*4882a593Smuzhiyun struct iproc_pll_dig_filter_ctrl {
140*4882a593Smuzhiyun 	unsigned int offset;
141*4882a593Smuzhiyun 	unsigned int ki_shift;
142*4882a593Smuzhiyun 	unsigned int ki_width;
143*4882a593Smuzhiyun 	unsigned int kp_shift;
144*4882a593Smuzhiyun 	unsigned int kp_width;
145*4882a593Smuzhiyun 	unsigned int ka_shift;
146*4882a593Smuzhiyun 	unsigned int ka_width;
147*4882a593Smuzhiyun };
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun /*
150*4882a593Smuzhiyun  * To enable SW control of the PLL
151*4882a593Smuzhiyun  */
152*4882a593Smuzhiyun struct iproc_pll_sw_ctrl {
153*4882a593Smuzhiyun 	unsigned int offset;
154*4882a593Smuzhiyun 	unsigned int shift;
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun struct iproc_pll_vco_ctrl {
158*4882a593Smuzhiyun 	unsigned int u_offset;
159*4882a593Smuzhiyun 	unsigned int l_offset;
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun /*
163*4882a593Smuzhiyun  * Main PLL control parameters
164*4882a593Smuzhiyun  */
165*4882a593Smuzhiyun struct iproc_pll_ctrl {
166*4882a593Smuzhiyun 	unsigned long flags;
167*4882a593Smuzhiyun 	struct iproc_pll_aon_pwr_ctrl aon;
168*4882a593Smuzhiyun 	struct iproc_asiu_gate asiu;
169*4882a593Smuzhiyun 	struct iproc_pll_reset_ctrl reset;
170*4882a593Smuzhiyun 	struct iproc_pll_dig_filter_ctrl dig_filter;
171*4882a593Smuzhiyun 	struct iproc_pll_sw_ctrl sw_ctrl;
172*4882a593Smuzhiyun 	struct iproc_clk_reg_op ndiv_int;
173*4882a593Smuzhiyun 	struct iproc_clk_reg_op ndiv_frac;
174*4882a593Smuzhiyun 	struct iproc_clk_reg_op pdiv;
175*4882a593Smuzhiyun 	struct iproc_pll_vco_ctrl vco_ctrl;
176*4882a593Smuzhiyun 	struct iproc_clk_reg_op status;
177*4882a593Smuzhiyun 	struct iproc_clk_reg_op macro_mode;
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun /*
181*4882a593Smuzhiyun  * Controls enabling/disabling a PLL derived clock
182*4882a593Smuzhiyun  */
183*4882a593Smuzhiyun struct iproc_clk_enable_ctrl {
184*4882a593Smuzhiyun 	unsigned int offset;
185*4882a593Smuzhiyun 	unsigned int enable_shift;
186*4882a593Smuzhiyun 	unsigned int hold_shift;
187*4882a593Smuzhiyun 	unsigned int bypass_shift;
188*4882a593Smuzhiyun };
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun /*
191*4882a593Smuzhiyun  * Main clock control parameters for clocks derived from the PLLs
192*4882a593Smuzhiyun  */
193*4882a593Smuzhiyun struct iproc_clk_ctrl {
194*4882a593Smuzhiyun 	unsigned int channel;
195*4882a593Smuzhiyun 	unsigned long flags;
196*4882a593Smuzhiyun 	struct iproc_clk_enable_ctrl enable;
197*4882a593Smuzhiyun 	struct iproc_clk_reg_op mdiv;
198*4882a593Smuzhiyun };
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun /*
201*4882a593Smuzhiyun  * Divisor of the ASIU clocks
202*4882a593Smuzhiyun  */
203*4882a593Smuzhiyun struct iproc_asiu_div {
204*4882a593Smuzhiyun 	unsigned int offset;
205*4882a593Smuzhiyun 	unsigned int en_shift;
206*4882a593Smuzhiyun 	unsigned int high_shift;
207*4882a593Smuzhiyun 	unsigned int high_width;
208*4882a593Smuzhiyun 	unsigned int low_shift;
209*4882a593Smuzhiyun 	unsigned int low_width;
210*4882a593Smuzhiyun };
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun void iproc_armpll_setup(struct device_node *node);
213*4882a593Smuzhiyun void iproc_pll_clk_setup(struct device_node *node,
214*4882a593Smuzhiyun 			 const struct iproc_pll_ctrl *pll_ctrl,
215*4882a593Smuzhiyun 			 const struct iproc_pll_vco_param *vco,
216*4882a593Smuzhiyun 			 unsigned int num_vco_entries,
217*4882a593Smuzhiyun 			 const struct iproc_clk_ctrl *clk_ctrl,
218*4882a593Smuzhiyun 			 unsigned int num_clks);
219*4882a593Smuzhiyun void iproc_asiu_setup(struct device_node *node,
220*4882a593Smuzhiyun 		      const struct iproc_asiu_div *div,
221*4882a593Smuzhiyun 		      const struct iproc_asiu_gate *gate,
222*4882a593Smuzhiyun 		      unsigned int num_clks);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun #endif /* _CLK_IPROC_H */
225