1*07d538d2SMario Six /* SPDX-License-Identifier: GPL-2.0+ */
2*07d538d2SMario Six /*
3*07d538d2SMario Six * (C) Copyright 2018
4*07d538d2SMario Six * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5*07d538d2SMario Six */
6*07d538d2SMario Six
7*07d538d2SMario Six /**
8*07d538d2SMario Six * enum ratio - Description of a core clock ratio
9*07d538d2SMario Six * @RAT_UNK: Unknown ratio
10*07d538d2SMario Six * @RAT_BYP: Bypass
11*07d538d2SMario Six * @RAT_1_TO_8: Ratio 1:8
12*07d538d2SMario Six * @RAT_1_TO_4: Ratio 1:4
13*07d538d2SMario Six * @RAT_1_TO_2: Ratio 1:2
14*07d538d2SMario Six * @RAT_1_TO_1: Ratio 1:1
15*07d538d2SMario Six * @RAT_1_5_TO_1: Ratio 1.5:1
16*07d538d2SMario Six * @RAT_2_TO_1: Ratio 2:1
17*07d538d2SMario Six * @RAT_2_5_TO_1: Ratio 2.5:1
18*07d538d2SMario Six * @RAT_3_TO_1: Ratio 3:1
19*07d538d2SMario Six */
20*07d538d2SMario Six enum ratio {
21*07d538d2SMario Six RAT_UNK,
22*07d538d2SMario Six RAT_BYP,
23*07d538d2SMario Six RAT_1_TO_8,
24*07d538d2SMario Six RAT_1_TO_4,
25*07d538d2SMario Six RAT_1_TO_2,
26*07d538d2SMario Six RAT_1_TO_1,
27*07d538d2SMario Six RAT_1_5_TO_1,
28*07d538d2SMario Six RAT_2_TO_1,
29*07d538d2SMario Six RAT_2_5_TO_1,
30*07d538d2SMario Six RAT_3_TO_1
31*07d538d2SMario Six };
32*07d538d2SMario Six
33*07d538d2SMario Six /**
34*07d538d2SMario Six * struct corecnf - Description for a core clock configuration
35*07d538d2SMario Six * @core_csb_ratio: Core clock frequency to CSB clock frequency ratio
36*07d538d2SMario Six * @vco_divider: VCO divider (Core VCO frequency = Core frequency * VCO divider)
37*07d538d2SMario Six */
38*07d538d2SMario Six struct corecnf {
39*07d538d2SMario Six int core_csb_ratio;
40*07d538d2SMario Six int vco_divider;
41*07d538d2SMario Six };
42*07d538d2SMario Six
43*07d538d2SMario Six /*
44*07d538d2SMario Six * Table with all valid Core CSB frequency ratio / VCO divider combinations as
45*07d538d2SMario Six * indexed by the COREPLL field of the SPMR
46*07d538d2SMario Six */
47*07d538d2SMario Six static const struct corecnf corecnf_tab[] = {
48*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x00 */
49*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x01 */
50*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x02 */
51*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x03 */
52*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x04 */
53*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x05 */
54*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x06 */
55*07d538d2SMario Six {RAT_BYP, RAT_BYP}, /* 0x07 */
56*07d538d2SMario Six {RAT_1_TO_1, RAT_1_TO_2}, /* 0x08 */
57*07d538d2SMario Six {RAT_1_TO_1, RAT_1_TO_4}, /* 0x09 */
58*07d538d2SMario Six {RAT_1_TO_1, RAT_1_TO_8}, /* 0x0A */
59*07d538d2SMario Six {RAT_1_TO_1, RAT_1_TO_8}, /* 0x0B */
60*07d538d2SMario Six {RAT_1_5_TO_1, RAT_1_TO_2}, /* 0x0C */
61*07d538d2SMario Six {RAT_1_5_TO_1, RAT_1_TO_4}, /* 0x0D */
62*07d538d2SMario Six {RAT_1_5_TO_1, RAT_1_TO_8}, /* 0x0E */
63*07d538d2SMario Six {RAT_1_5_TO_1, RAT_1_TO_8}, /* 0x0F */
64*07d538d2SMario Six {RAT_2_TO_1, RAT_1_TO_2}, /* 0x10 */
65*07d538d2SMario Six {RAT_2_TO_1, RAT_1_TO_4}, /* 0x11 */
66*07d538d2SMario Six {RAT_2_TO_1, RAT_1_TO_8}, /* 0x12 */
67*07d538d2SMario Six {RAT_2_TO_1, RAT_1_TO_8}, /* 0x13 */
68*07d538d2SMario Six {RAT_2_5_TO_1, RAT_1_TO_2}, /* 0x14 */
69*07d538d2SMario Six {RAT_2_5_TO_1, RAT_1_TO_4}, /* 0x15 */
70*07d538d2SMario Six {RAT_2_5_TO_1, RAT_1_TO_8}, /* 0x16 */
71*07d538d2SMario Six {RAT_2_5_TO_1, RAT_1_TO_8}, /* 0x17 */
72*07d538d2SMario Six {RAT_3_TO_1, RAT_1_TO_2}, /* 0x18 */
73*07d538d2SMario Six {RAT_3_TO_1, RAT_1_TO_4}, /* 0x19 */
74*07d538d2SMario Six {RAT_3_TO_1, RAT_1_TO_8}, /* 0x1A */
75*07d538d2SMario Six {RAT_3_TO_1, RAT_1_TO_8}, /* 0x1B */
76*07d538d2SMario Six };
77*07d538d2SMario Six
78*07d538d2SMario Six /**
79*07d538d2SMario Six * enum reg_type - Register to read a field from
80*07d538d2SMario Six * @REG_SCCR: Use the SCCR register
81*07d538d2SMario Six * @REG_SPMR: Use the SPMR register
82*07d538d2SMario Six */
83*07d538d2SMario Six enum reg_type {
84*07d538d2SMario Six REG_SCCR,
85*07d538d2SMario Six REG_SPMR,
86*07d538d2SMario Six };
87*07d538d2SMario Six
88*07d538d2SMario Six /**
89*07d538d2SMario Six * enum mode_type - Description of how to read a specific frequency value
90*07d538d2SMario Six * @TYPE_INVALID: Unknown type, will provoke error
91*07d538d2SMario Six * @TYPE_SCCR_STANDARD: Read a field from the SCCR register, and use it
92*07d538d2SMario Six * as a divider for the CSB clock to compute the
93*07d538d2SMario Six * frequency
94*07d538d2SMario Six * @TYPE_SCCR_ONOFF: The field describes a bit flag that can turn the
95*07d538d2SMario Six * clock on or off
96*07d538d2SMario Six * @TYPE_SPMR_DIRECT_MULTIPLY: Read a field from the SPMR register, and use it
97*07d538d2SMario Six * as a multiplier for the CSB clock to compute the
98*07d538d2SMario Six * frequency
99*07d538d2SMario Six * @TYPE_SPECIAL: The frequency is calculated in a non-standard way
100*07d538d2SMario Six */
101*07d538d2SMario Six enum mode_type {
102*07d538d2SMario Six TYPE_INVALID = 0,
103*07d538d2SMario Six TYPE_SCCR_STANDARD,
104*07d538d2SMario Six TYPE_SCCR_ONOFF,
105*07d538d2SMario Six TYPE_SPMR_DIRECT_MULTIPLY,
106*07d538d2SMario Six TYPE_SPECIAL,
107*07d538d2SMario Six };
108*07d538d2SMario Six
109*07d538d2SMario Six /* Map of each clock index to its human-readable name */
110*07d538d2SMario Six static const char * const names[] = {
111*07d538d2SMario Six [MPC83XX_CLK_CORE] = "Core",
112*07d538d2SMario Six [MPC83XX_CLK_CSB] = "Coherent System Bus",
113*07d538d2SMario Six [MPC83XX_CLK_QE] = "QE",
114*07d538d2SMario Six [MPC83XX_CLK_BRG] = "BRG",
115*07d538d2SMario Six [MPC83XX_CLK_LBIU] = "Local Bus Controller",
116*07d538d2SMario Six [MPC83XX_CLK_LCLK] = "Local Bus",
117*07d538d2SMario Six [MPC83XX_CLK_MEM] = "DDR",
118*07d538d2SMario Six [MPC83XX_CLK_MEM_SEC] = "DDR Secondary",
119*07d538d2SMario Six [MPC83XX_CLK_ENC] = "SEC",
120*07d538d2SMario Six [MPC83XX_CLK_I2C1] = "I2C1",
121*07d538d2SMario Six [MPC83XX_CLK_I2C2] = "I2C2",
122*07d538d2SMario Six [MPC83XX_CLK_TDM] = "TDM",
123*07d538d2SMario Six [MPC83XX_CLK_SDHC] = "SDHC",
124*07d538d2SMario Six [MPC83XX_CLK_TSEC1] = "TSEC1",
125*07d538d2SMario Six [MPC83XX_CLK_TSEC2] = "TSEC2",
126*07d538d2SMario Six [MPC83XX_CLK_USBDR] = "USB DR",
127*07d538d2SMario Six [MPC83XX_CLK_USBMPH] = "USB MPH",
128*07d538d2SMario Six [MPC83XX_CLK_PCIEXP1] = "PCIEXP1",
129*07d538d2SMario Six [MPC83XX_CLK_PCIEXP2] = "PCIEXP2",
130*07d538d2SMario Six [MPC83XX_CLK_SATA] = "SATA",
131*07d538d2SMario Six [MPC83XX_CLK_DMAC] = "DMAC",
132*07d538d2SMario Six [MPC83XX_CLK_PCI] = "PCI",
133*07d538d2SMario Six };
134*07d538d2SMario Six
135*07d538d2SMario Six /**
136*07d538d2SMario Six * struct clk_mode - Structure for clock mode descriiptions
137*07d538d2SMario Six * @low: The low bit of the data field to read for this mode (may not apply to
138*07d538d2SMario Six * some modes)
139*07d538d2SMario Six * @high: The high bit of the data field to read for this mode (may not apply to
140*07d538d2SMario Six * some modes)
141*07d538d2SMario Six * @type: The type of the mode description (one of enum mode_type)
142*07d538d2SMario Six */
143*07d538d2SMario Six struct clk_mode {
144*07d538d2SMario Six u8 low;
145*07d538d2SMario Six u8 high;
146*07d538d2SMario Six int type;
147*07d538d2SMario Six };
148*07d538d2SMario Six
149*07d538d2SMario Six /**
150*07d538d2SMario Six * set_mode() - Build a clock mode description from data
151*07d538d2SMario Six * @mode: The clock mode description to be filled out
152*07d538d2SMario Six * @low: The low bit of the data field to read for this mode (may not apply to
153*07d538d2SMario Six * some modes)
154*07d538d2SMario Six * @high: The high bit of the data field to read for this mode (may not apply to
155*07d538d2SMario Six * some modes)
156*07d538d2SMario Six * @type: The type of the mode description (one of enum mode_type)
157*07d538d2SMario Six *
158*07d538d2SMario Six * Clock mode descriptions are a succinct description of how to read a specific
159*07d538d2SMario Six * clock's rate from the hardware; usually by reading a specific field of a
160*07d538d2SMario Six * register, such a s the SCCR register, but some types use different methods
161*07d538d2SMario Six * for obtaining the clock rate.
162*07d538d2SMario Six */
set_mode(struct clk_mode * mode,u8 low,u8 high,int type)163*07d538d2SMario Six static void set_mode(struct clk_mode *mode, u8 low, u8 high, int type)
164*07d538d2SMario Six {
165*07d538d2SMario Six mode->low = low;
166*07d538d2SMario Six mode->high = high;
167*07d538d2SMario Six mode->type = type;
168*07d538d2SMario Six }
169*07d538d2SMario Six
170*07d538d2SMario Six /**
171*07d538d2SMario Six * retrieve_mode() - Get the clock mode description for a specific clock
172*07d538d2SMario Six * @clk: The identifier of the clock for which the clock description should
173*07d538d2SMario Six * be retrieved
174*07d538d2SMario Six * @soc_type: The type of MPC83xx SoC for which the clock description should be
175*07d538d2SMario Six * retrieved
176*07d538d2SMario Six * @mode: Pointer to a clk_mode structure to be filled with data for the
177*07d538d2SMario Six * clock
178*07d538d2SMario Six *
179*07d538d2SMario Six * Since some clock rate are stored in different places on different MPC83xx
180*07d538d2SMario Six * SoCs, the SoC type has to be supplied along with the clock's identifier.
181*07d538d2SMario Six *
182*07d538d2SMario Six * Return: 0 if OK, -ve on error
183*07d538d2SMario Six */
retrieve_mode(int clk,int soc_type,struct clk_mode * mode)184*07d538d2SMario Six static int retrieve_mode(int clk, int soc_type, struct clk_mode *mode)
185*07d538d2SMario Six {
186*07d538d2SMario Six switch (clk) {
187*07d538d2SMario Six case MPC83XX_CLK_CORE:
188*07d538d2SMario Six case MPC83XX_CLK_CSB:
189*07d538d2SMario Six case MPC83XX_CLK_QE:
190*07d538d2SMario Six case MPC83XX_CLK_BRG:
191*07d538d2SMario Six case MPC83XX_CLK_LCLK:
192*07d538d2SMario Six case MPC83XX_CLK_I2C2:
193*07d538d2SMario Six set_mode(mode, 0, 0, TYPE_SPECIAL);
194*07d538d2SMario Six break;
195*07d538d2SMario Six case MPC83XX_CLK_MEM:
196*07d538d2SMario Six set_mode(mode, 1, 1, TYPE_SPMR_DIRECT_MULTIPLY);
197*07d538d2SMario Six break;
198*07d538d2SMario Six case MPC83XX_CLK_LBIU:
199*07d538d2SMario Six case MPC83XX_CLK_MEM_SEC:
200*07d538d2SMario Six set_mode(mode, 0, 0, TYPE_SPMR_DIRECT_MULTIPLY);
201*07d538d2SMario Six break;
202*07d538d2SMario Six case MPC83XX_CLK_TSEC1:
203*07d538d2SMario Six set_mode(mode, 0, 1, TYPE_SCCR_STANDARD);
204*07d538d2SMario Six break;
205*07d538d2SMario Six case MPC83XX_CLK_TSEC2:
206*07d538d2SMario Six if (soc_type == SOC_MPC8313) /* I2C and TSEC2 are the same register */
207*07d538d2SMario Six set_mode(mode, 2, 3, TYPE_SCCR_STANDARD);
208*07d538d2SMario Six else /* FIXME(mario.six@gdsys.cc): This has separate enable/disable bit! */
209*07d538d2SMario Six set_mode(mode, 0, 1, TYPE_SCCR_STANDARD);
210*07d538d2SMario Six break;
211*07d538d2SMario Six case MPC83XX_CLK_SDHC:
212*07d538d2SMario Six set_mode(mode, 4, 5, TYPE_SCCR_STANDARD);
213*07d538d2SMario Six break;
214*07d538d2SMario Six case MPC83XX_CLK_ENC:
215*07d538d2SMario Six set_mode(mode, 6, 7, TYPE_SCCR_STANDARD);
216*07d538d2SMario Six break;
217*07d538d2SMario Six case MPC83XX_CLK_I2C1:
218*07d538d2SMario Six if (soc_type == SOC_MPC8349)
219*07d538d2SMario Six set_mode(mode, 2, 3, TYPE_SCCR_STANDARD);
220*07d538d2SMario Six else /* I2C and ENC are the same register */
221*07d538d2SMario Six set_mode(mode, 6, 7, TYPE_SCCR_STANDARD);
222*07d538d2SMario Six break;
223*07d538d2SMario Six case MPC83XX_CLK_PCIEXP1:
224*07d538d2SMario Six set_mode(mode, 10, 11, TYPE_SCCR_STANDARD);
225*07d538d2SMario Six break;
226*07d538d2SMario Six case MPC83XX_CLK_PCIEXP2:
227*07d538d2SMario Six set_mode(mode, 12, 13, TYPE_SCCR_STANDARD);
228*07d538d2SMario Six break;
229*07d538d2SMario Six case MPC83XX_CLK_USBDR:
230*07d538d2SMario Six if (soc_type == SOC_MPC8313 || soc_type == SOC_MPC8349)
231*07d538d2SMario Six set_mode(mode, 10, 11, TYPE_SCCR_STANDARD);
232*07d538d2SMario Six else
233*07d538d2SMario Six set_mode(mode, 8, 9, TYPE_SCCR_STANDARD);
234*07d538d2SMario Six break;
235*07d538d2SMario Six case MPC83XX_CLK_USBMPH:
236*07d538d2SMario Six set_mode(mode, 8, 9, TYPE_SCCR_STANDARD);
237*07d538d2SMario Six break;
238*07d538d2SMario Six case MPC83XX_CLK_PCI:
239*07d538d2SMario Six set_mode(mode, 15, 15, TYPE_SCCR_ONOFF);
240*07d538d2SMario Six break;
241*07d538d2SMario Six case MPC83XX_CLK_DMAC:
242*07d538d2SMario Six set_mode(mode, 26, 27, TYPE_SCCR_STANDARD);
243*07d538d2SMario Six break;
244*07d538d2SMario Six case MPC83XX_CLK_SATA:
245*07d538d2SMario Six /* FIXME(mario.six@gdsys.cc): All SATA controllers must have the same clock ratio */
246*07d538d2SMario Six if (soc_type == SOC_MPC8379) {
247*07d538d2SMario Six set_mode(mode, 24, 25, TYPE_SCCR_STANDARD);
248*07d538d2SMario Six set_mode(mode, 26, 27, TYPE_SCCR_STANDARD);
249*07d538d2SMario Six set_mode(mode, 28, 29, TYPE_SCCR_STANDARD);
250*07d538d2SMario Six set_mode(mode, 30, 31, TYPE_SCCR_STANDARD);
251*07d538d2SMario Six } else {
252*07d538d2SMario Six set_mode(mode, 18, 19, TYPE_SCCR_STANDARD);
253*07d538d2SMario Six set_mode(mode, 20, 21, TYPE_SCCR_STANDARD);
254*07d538d2SMario Six }
255*07d538d2SMario Six break;
256*07d538d2SMario Six case MPC83XX_CLK_TDM:
257*07d538d2SMario Six set_mode(mode, 26, 27, TYPE_SCCR_STANDARD);
258*07d538d2SMario Six break;
259*07d538d2SMario Six default:
260*07d538d2SMario Six debug("%s: Unknown clock type %d on soc type %d\n",
261*07d538d2SMario Six __func__, clk, soc_type);
262*07d538d2SMario Six set_mode(mode, 0, 0, TYPE_INVALID);
263*07d538d2SMario Six return -EINVAL;
264*07d538d2SMario Six }
265*07d538d2SMario Six
266*07d538d2SMario Six return 0;
267*07d538d2SMario Six }
268*07d538d2SMario Six
269*07d538d2SMario Six /**
270*07d538d2SMario Six * get_spmr() - Read the SPMR (System PLL Mode Register)
271*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
272*07d538d2SMario Six *
273*07d538d2SMario Six * Return: The SPMR value as a 32-bit number.
274*07d538d2SMario Six */
get_spmr(immap_t * im)275*07d538d2SMario Six static inline u32 get_spmr(immap_t *im)
276*07d538d2SMario Six {
277*07d538d2SMario Six u32 res = in_be32(&im->clk.spmr);
278*07d538d2SMario Six
279*07d538d2SMario Six return res;
280*07d538d2SMario Six }
281*07d538d2SMario Six
282*07d538d2SMario Six /**
283*07d538d2SMario Six * get_sccr() - Read the SCCR (System Clock Control Register)
284*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
285*07d538d2SMario Six *
286*07d538d2SMario Six * Return: The SCCR value as a 32-bit number.
287*07d538d2SMario Six */
get_sccr(immap_t * im)288*07d538d2SMario Six static inline u32 get_sccr(immap_t *im)
289*07d538d2SMario Six {
290*07d538d2SMario Six u32 res = in_be32(&im->clk.sccr);
291*07d538d2SMario Six
292*07d538d2SMario Six return res;
293*07d538d2SMario Six }
294*07d538d2SMario Six
295*07d538d2SMario Six /**
296*07d538d2SMario Six * get_lcrr() - Read the LCRR (Clock Ratio Register)
297*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
298*07d538d2SMario Six *
299*07d538d2SMario Six * Return: The LCRR value as a 32-bit number.
300*07d538d2SMario Six */
get_lcrr(immap_t * im)301*07d538d2SMario Six static inline u32 get_lcrr(immap_t *im)
302*07d538d2SMario Six {
303*07d538d2SMario Six u32 res = in_be32(&im->im_lbc.lcrr);
304*07d538d2SMario Six
305*07d538d2SMario Six return res;
306*07d538d2SMario Six }
307*07d538d2SMario Six
308*07d538d2SMario Six /**
309*07d538d2SMario Six * get_pci_sync_in() - Read the PCI synchronization clock speed
310*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
311*07d538d2SMario Six *
312*07d538d2SMario Six * Return: The PCI synchronization clock speed value as a 32-bit number.
313*07d538d2SMario Six */
get_pci_sync_in(immap_t * im)314*07d538d2SMario Six static inline u32 get_pci_sync_in(immap_t *im)
315*07d538d2SMario Six {
316*07d538d2SMario Six u8 clkin_div;
317*07d538d2SMario Six
318*07d538d2SMario Six clkin_div = (get_spmr(im) & SPMR_CKID) >> SPMR_CKID_SHIFT;
319*07d538d2SMario Six return CONFIG_SYS_CLK_FREQ / (1 + clkin_div);
320*07d538d2SMario Six }
321*07d538d2SMario Six
322*07d538d2SMario Six /**
323*07d538d2SMario Six * get_csb_clk() - Read the CSB (Coheren System Bus) clock speed
324*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
325*07d538d2SMario Six *
326*07d538d2SMario Six * Return: The CSB clock speed value as a 32-bit number.
327*07d538d2SMario Six */
get_csb_clk(immap_t * im)328*07d538d2SMario Six static inline u32 get_csb_clk(immap_t *im)
329*07d538d2SMario Six {
330*07d538d2SMario Six u8 spmf;
331*07d538d2SMario Six
332*07d538d2SMario Six spmf = (get_spmr(im) & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
333*07d538d2SMario Six return CONFIG_SYS_CLK_FREQ * spmf;
334*07d538d2SMario Six }
335*07d538d2SMario Six
336*07d538d2SMario Six /**
337*07d538d2SMario Six * spmr_field() - Read a specific SPMR field
338*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
339*07d538d2SMario Six * @mask: A bitmask that describes the bitfield to be read
340*07d538d2SMario Six *
341*07d538d2SMario Six * Return: The value of the bit field as a 32-bit number.
342*07d538d2SMario Six */
spmr_field(immap_t * im,u32 mask)343*07d538d2SMario Six static inline uint spmr_field(immap_t *im, u32 mask)
344*07d538d2SMario Six {
345*07d538d2SMario Six /* Extract shift from bitmask */
346*07d538d2SMario Six uint shift = mask ? ffs(mask) - 1 : 0;
347*07d538d2SMario Six
348*07d538d2SMario Six return (get_spmr(im) & mask) >> shift;
349*07d538d2SMario Six }
350*07d538d2SMario Six
351*07d538d2SMario Six /**
352*07d538d2SMario Six * sccr_field() - Read a specific SCCR field
353*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
354*07d538d2SMario Six * @mask: A bitmask that describes the bitfield to be read
355*07d538d2SMario Six *
356*07d538d2SMario Six * Return: The value of the bit field as a 32-bit number.
357*07d538d2SMario Six */
sccr_field(immap_t * im,u32 mask)358*07d538d2SMario Six static inline uint sccr_field(immap_t *im, u32 mask)
359*07d538d2SMario Six {
360*07d538d2SMario Six /* Extract shift from bitmask */
361*07d538d2SMario Six uint shift = mask ? ffs(mask) - 1 : 0;
362*07d538d2SMario Six
363*07d538d2SMario Six return (get_sccr(im) & mask) >> shift;
364*07d538d2SMario Six }
365*07d538d2SMario Six
366*07d538d2SMario Six /**
367*07d538d2SMario Six * lcrr_field() - Read a specific LCRR field
368*07d538d2SMario Six * @im: Pointer to the MPC83xx main register map in question
369*07d538d2SMario Six * @mask: A bitmask that describes the bitfield to be read
370*07d538d2SMario Six *
371*07d538d2SMario Six * Return: The value of the bit field as a 32-bit number.
372*07d538d2SMario Six */
lcrr_field(immap_t * im,u32 mask)373*07d538d2SMario Six static inline uint lcrr_field(immap_t *im, u32 mask)
374*07d538d2SMario Six {
375*07d538d2SMario Six /* Extract shift from bitmask */
376*07d538d2SMario Six uint shift = mask ? ffs(mask) - 1 : 0;
377*07d538d2SMario Six
378*07d538d2SMario Six return (get_lcrr(im) & mask) >> shift;
379*07d538d2SMario Six }
380