2 * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 /* Tegra SoC common clock control functions */
22 #include <asm/arch/clock.h>
23 #include <asm/arch/tegra.h>
24 #include <asm/arch-tegra/ap.h>
25 #include <asm/arch-tegra/clk_rst.h>
26 #include <asm/arch-tegra/pmc.h>
27 #include <asm/arch-tegra/timer.h>
32 * This is our record of the current clock rate of each clock. We don't
33 * fill all of these in since we are only really interested in clocks which
36 static unsigned pll_rate
[CLOCK_ID_COUNT
];
39 * The oscillator frequency is fixed to one of four set values. Based on this
40 * the other clocks are set up appropriately.
42 static unsigned osc_freq
[CLOCK_OSC_FREQ_COUNT
] = {
49 /* return 1 if a peripheral ID is in range */
50 #define clock_type_id_isvalid(id) ((id) >= 0 && \
51 (id) < CLOCK_TYPE_COUNT)
53 char pllp_valid
= 1; /* PLLP is set up correctly */
55 /* return 1 if a periphc_internal_id is in range */
56 #define periphc_internal_id_isvalid(id) ((id) >= 0 && \
59 /* number of clock outputs of a PLL */
60 static const u8 pll_num_clkouts
[] = {
69 int clock_get_osc_bypass(void)
71 struct clk_rst_ctlr
*clkrst
=
72 (struct clk_rst_ctlr
*)NV_PA_CLK_RST_BASE
;
75 reg
= readl(&clkrst
->crc_osc_ctrl
);
76 return (reg
& OSC_XOBP_MASK
) >> OSC_XOBP_SHIFT
;
79 /* Returns a pointer to the registers of the given pll */
80 static struct clk_pll
*get_pll(enum clock_id clkid
)
82 struct clk_rst_ctlr
*clkrst
=
83 (struct clk_rst_ctlr
*)NV_PA_CLK_RST_BASE
;
85 assert(clock_id_is_pll(clkid
));
86 if (clkid
>= (enum clock_id
)TEGRA_CLK_PLLS
) {
87 debug("%s: Invalid PLL %d\n", __func__
, clkid
);
90 return &clkrst
->crc_pll
[clkid
];
93 __weak
struct clk_pll_simple
*clock_get_simple_pll(enum clock_id clkid
)
98 int clock_ll_read_pll(enum clock_id clkid
, u32
*divm
, u32
*divn
,
99 u32
*divp
, u32
*cpcon
, u32
*lfcon
)
101 struct clk_pll
*pll
= get_pll(clkid
);
104 assert(clkid
!= CLOCK_ID_USB
);
106 /* Safety check, adds to code size but is small */
107 if (!clock_id_is_pll(clkid
) || clkid
== CLOCK_ID_USB
)
109 data
= readl(&pll
->pll_base
);
110 *divm
= (data
& PLL_DIVM_MASK
) >> PLL_DIVM_SHIFT
;
111 *divn
= (data
& PLL_DIVN_MASK
) >> PLL_DIVN_SHIFT
;
112 *divp
= (data
& PLL_DIVP_MASK
) >> PLL_DIVP_SHIFT
;
113 data
= readl(&pll
->pll_misc
);
114 *cpcon
= (data
& PLL_CPCON_MASK
) >> PLL_CPCON_SHIFT
;
115 *lfcon
= (data
& PLL_LFCON_MASK
) >> PLL_LFCON_SHIFT
;
120 unsigned long clock_start_pll(enum clock_id clkid
, u32 divm
, u32 divn
,
121 u32 divp
, u32 cpcon
, u32 lfcon
)
123 struct clk_pll
*pll
= NULL
;
126 if (clkid
< (enum clock_id
)TEGRA_CLK_PLLS
)
127 pll
= get_pll(clkid
);
130 * We cheat by treating all PLL (except PLLU) in the same fashion.
131 * This works only because:
132 * - same fields are always mapped at same offsets, except DCCON
133 * - DCCON is always 0, doesn't conflict
134 * - M,N, P of PLLP values are ignored for PLLP
136 misc_data
= (cpcon
<< PLL_CPCON_SHIFT
) | (lfcon
<< PLL_LFCON_SHIFT
);
138 data
= (divm
<< PLL_DIVM_SHIFT
) | (divn
<< PLL_DIVN_SHIFT
) |
139 (0 << PLL_BYPASS_SHIFT
) | (1 << PLL_ENABLE_SHIFT
);
141 if (clkid
== CLOCK_ID_USB
)
142 data
|= divp
<< PLLU_VCO_FREQ_SHIFT
;
144 data
|= divp
<< PLL_DIVP_SHIFT
;
146 writel(misc_data
, &pll
->pll_misc
);
147 writel(data
, &pll
->pll_base
);
149 struct clk_pll_simple
*pll
= clock_get_simple_pll(clkid
);
152 debug("%s: Uknown simple PLL %d\n", __func__
, clkid
);
155 writel(misc_data
, &pll
->pll_misc
);
156 writel(data
, &pll
->pll_base
);
159 /* calculate the stable time */
160 return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US
;
163 void clock_ll_set_source_divisor(enum periph_id periph_id
, unsigned source
,
166 u32
*reg
= get_periph_source_reg(periph_id
);
171 value
&= ~OUT_CLK_SOURCE_31_30_MASK
;
172 value
|= source
<< OUT_CLK_SOURCE_31_30_SHIFT
;
174 value
&= ~OUT_CLK_DIVISOR_MASK
;
175 value
|= divisor
<< OUT_CLK_DIVISOR_SHIFT
;
180 int clock_ll_set_source_bits(enum periph_id periph_id
, int mux_bits
,
183 u32
*reg
= get_periph_source_reg(periph_id
);
186 case MASK_BITS_31_30
:
187 clrsetbits_le32(reg
, OUT_CLK_SOURCE_31_30_MASK
,
188 source
<< OUT_CLK_SOURCE_31_30_SHIFT
);
191 case MASK_BITS_31_29
:
192 clrsetbits_le32(reg
, OUT_CLK_SOURCE_31_29_MASK
,
193 source
<< OUT_CLK_SOURCE_31_29_SHIFT
);
196 case MASK_BITS_31_28
:
197 clrsetbits_le32(reg
, OUT_CLK_SOURCE_31_28_MASK
,
198 source
<< OUT_CLK_SOURCE_31_28_SHIFT
);
208 void clock_ll_set_source(enum periph_id periph_id
, unsigned source
)
210 clock_ll_set_source_bits(periph_id
, MASK_BITS_31_30
, source
);
214 * Given the parent's rate and the required rate for the children, this works
215 * out the peripheral clock divider to use, in 7.1 binary format.
217 * @param divider_bits number of divider bits (8 or 16)
218 * @param parent_rate clock rate of parent clock in Hz
219 * @param rate required clock rate for this clock
220 * @return divider which should be used
222 static int clk_get_divider(unsigned divider_bits
, unsigned long parent_rate
,
225 u64 divider
= parent_rate
* 2;
226 unsigned max_divider
= 1 << divider_bits
;
229 do_div(divider
, rate
);
231 if ((s64
)divider
- 2 < 0)
234 if ((s64
)divider
- 2 >= max_divider
)
240 int clock_set_pllout(enum clock_id clkid
, enum pll_out_id pllout
, unsigned rate
)
242 struct clk_pll
*pll
= get_pll(clkid
);
243 int data
= 0, div
= 0, offset
= 0;
245 if (!clock_id_is_pll(clkid
))
248 if (pllout
+ 1 > pll_num_clkouts
[clkid
])
251 div
= clk_get_divider(8, pll_rate
[clkid
], rate
);
256 /* out2 and out4 are in the high part of the register */
257 if (pllout
== PLL_OUT2
|| pllout
== PLL_OUT4
)
260 data
= (div
<< PLL_OUT_RATIO_SHIFT
) |
261 PLL_OUT_OVRRIDE
| PLL_OUT_CLKEN
| PLL_OUT_RSTN
;
262 clrsetbits_le32(&pll
->pll_out
[pllout
>> 1],
263 PLL_OUT_RATIO_MASK
<< offset
, data
<< offset
);
269 * Given the parent's rate and the divider in 7.1 format, this works out the
270 * resulting peripheral clock rate.
272 * @param parent_rate clock rate of parent clock in Hz
273 * @param divider which should be used in 7.1 format
274 * @return effective clock rate of peripheral
276 static unsigned long get_rate_from_divider(unsigned long parent_rate
,
281 rate
= (u64
)parent_rate
* 2;
282 do_div(rate
, divider
+ 2);
286 unsigned long clock_get_periph_rate(enum periph_id periph_id
,
287 enum clock_id parent
)
289 u32
*reg
= get_periph_source_reg(periph_id
);
291 return get_rate_from_divider(pll_rate
[parent
],
292 (readl(reg
) & OUT_CLK_DIVISOR_MASK
) >> OUT_CLK_DIVISOR_SHIFT
);
296 * Find the best available 7.1 format divisor given a parent clock rate and
297 * required child clock rate. This function assumes that a second-stage
298 * divisor is available which can divide by powers of 2 from 1 to 256.
300 * @param divider_bits number of divider bits (8 or 16)
301 * @param parent_rate clock rate of parent clock in Hz
302 * @param rate required clock rate for this clock
303 * @param extra_div value for the second-stage divisor (not set if this
304 * function returns -1.
305 * @return divider which should be used, or -1 if nothing is valid
308 static int find_best_divider(unsigned divider_bits
, unsigned long parent_rate
,
309 unsigned long rate
, int *extra_div
)
312 int best_divider
= -1;
313 int best_error
= rate
;
315 /* try dividers from 1 to 256 and find closest match */
316 for (shift
= 0; shift
<= 8 && best_error
> 0; shift
++) {
317 unsigned divided_parent
= parent_rate
>> shift
;
318 int divider
= clk_get_divider(divider_bits
, divided_parent
,
320 unsigned effective_rate
= get_rate_from_divider(divided_parent
,
322 int error
= rate
- effective_rate
;
324 /* Given a valid divider, look for the lowest error */
325 if (divider
!= -1 && error
< best_error
) {
327 *extra_div
= 1 << shift
;
328 best_divider
= divider
;
332 /* return what we found - *extra_div will already be set */
337 * Adjust peripheral PLL to use the given divider and source.
339 * @param periph_id peripheral to adjust
340 * @param source Source number (0-3 or 0-7)
341 * @param mux_bits Number of mux bits (2 or 4)
342 * @param divider Required divider in 7.1 or 15.1 format
343 * @return 0 if ok, -1 on error (requesting a parent clock which is not valid
344 * for this peripheral)
346 static int adjust_periph_pll(enum periph_id periph_id
, int source
,
347 int mux_bits
, unsigned divider
)
349 u32
*reg
= get_periph_source_reg(periph_id
);
351 clrsetbits_le32(reg
, OUT_CLK_DIVISOR_MASK
,
352 divider
<< OUT_CLK_DIVISOR_SHIFT
);
355 /* work out the source clock and set it */
359 clock_ll_set_source_bits(periph_id
, mux_bits
, source
);
365 unsigned clock_adjust_periph_pll_div(enum periph_id periph_id
,
366 enum clock_id parent
, unsigned rate
, int *extra_div
)
368 unsigned effective_rate
;
369 int mux_bits
, divider_bits
, source
;
373 /* work out the source clock and set it */
374 source
= get_periph_clock_source(periph_id
, parent
, &mux_bits
,
377 divider
= find_best_divider(divider_bits
, pll_rate
[parent
],
382 assert(divider
>= 0);
383 if (adjust_periph_pll(periph_id
, source
, mux_bits
, divider
))
385 debug("periph %d, rate=%d, reg=%p = %x\n", periph_id
, rate
,
386 get_periph_source_reg(periph_id
),
387 readl(get_periph_source_reg(periph_id
)));
389 /* Check what we ended up with. This shouldn't matter though */
390 effective_rate
= clock_get_periph_rate(periph_id
, parent
);
392 effective_rate
/= *extra_div
;
393 if (rate
!= effective_rate
)
394 debug("Requested clock rate %u not honored (got %u)\n",
395 rate
, effective_rate
);
396 return effective_rate
;
399 unsigned clock_start_periph_pll(enum periph_id periph_id
,
400 enum clock_id parent
, unsigned rate
)
402 unsigned effective_rate
;
404 reset_set_enable(periph_id
, 1);
405 clock_enable(periph_id
);
407 effective_rate
= clock_adjust_periph_pll_div(periph_id
, parent
, rate
,
410 reset_set_enable(periph_id
, 0);
411 return effective_rate
;
414 void clock_enable(enum periph_id clkid
)
416 clock_set_enable(clkid
, 1);
419 void clock_disable(enum periph_id clkid
)
421 clock_set_enable(clkid
, 0);
424 void reset_periph(enum periph_id periph_id
, int us_delay
)
426 /* Put peripheral into reset */
427 reset_set_enable(periph_id
, 1);
431 reset_set_enable(periph_id
, 0);
436 void reset_cmplx_set_enable(int cpu
, int which
, int reset
)
438 struct clk_rst_ctlr
*clkrst
=
439 (struct clk_rst_ctlr
*)NV_PA_CLK_RST_BASE
;
442 /* Form the mask, which depends on the cpu chosen (2 or 4) */
443 assert(cpu
>= 0 && cpu
< MAX_NUM_CPU
);
446 /* either enable or disable those reset for that CPU */
448 writel(mask
, &clkrst
->crc_cpu_cmplx_set
);
450 writel(mask
, &clkrst
->crc_cpu_cmplx_clr
);
453 unsigned clock_get_rate(enum clock_id clkid
)
461 parent_rate
= osc_freq
[clock_get_osc_freq()];
462 if (clkid
== CLOCK_ID_OSC
)
465 pll
= get_pll(clkid
);
468 base
= readl(&pll
->pll_base
);
470 /* Oh for bf_unpack()... */
471 rate
= parent_rate
* ((base
& PLL_DIVN_MASK
) >> PLL_DIVN_SHIFT
);
472 divm
= (base
& PLL_DIVM_MASK
) >> PLL_DIVM_SHIFT
;
473 if (clkid
== CLOCK_ID_USB
)
474 divm
<<= (base
& PLLU_VCO_FREQ_MASK
) >> PLLU_VCO_FREQ_SHIFT
;
476 divm
<<= (base
& PLL_DIVP_MASK
) >> PLL_DIVP_SHIFT
;
482 * Set the output frequency you want for each PLL clock.
483 * PLL output frequencies are programmed by setting their N, M and P values.
484 * The governing equations are:
485 * VCO = (Fi / m) * n, Fo = VCO / (2^p)
486 * where Fo is the output frequency from the PLL.
487 * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
488 * 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
489 * Please see Tegra TRM section 5.3 to get the detail for PLL Programming
491 * @param n PLL feedback divider(DIVN)
492 * @param m PLL input divider(DIVN)
493 * @param p post divider(DIVP)
494 * @param cpcon base PLL charge pump(CPCON)
495 * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
496 * be overriden), 1 if PLL is already correct
498 int clock_set_rate(enum clock_id clkid
, u32 n
, u32 m
, u32 p
, u32 cpcon
)
504 pll
= get_pll(clkid
);
506 base_reg
= readl(&pll
->pll_base
);
508 /* Set BYPASS, m, n and p to PLL_BASE */
509 base_reg
&= ~PLL_DIVM_MASK
;
510 base_reg
|= m
<< PLL_DIVM_SHIFT
;
512 base_reg
&= ~PLL_DIVN_MASK
;
513 base_reg
|= n
<< PLL_DIVN_SHIFT
;
515 base_reg
&= ~PLL_DIVP_MASK
;
516 base_reg
|= p
<< PLL_DIVP_SHIFT
;
518 if (clkid
== CLOCK_ID_PERIPH
) {
520 * If the PLL is already set up, check that it is correct
521 * and record this info for clock_verify() to check.
523 if (base_reg
& PLL_BASE_OVRRIDE_MASK
) {
524 base_reg
|= PLL_ENABLE_MASK
;
525 if (base_reg
!= readl(&pll
->pll_base
))
527 return pllp_valid
? 1 : -1;
529 base_reg
|= PLL_BASE_OVRRIDE_MASK
;
532 base_reg
|= PLL_BYPASS_MASK
;
533 writel(base_reg
, &pll
->pll_base
);
535 /* Set cpcon to PLL_MISC */
536 misc_reg
= readl(&pll
->pll_misc
);
537 misc_reg
&= ~PLL_CPCON_MASK
;
538 misc_reg
|= cpcon
<< PLL_CPCON_SHIFT
;
539 writel(misc_reg
, &pll
->pll_misc
);
542 base_reg
|= PLL_ENABLE_MASK
;
543 writel(base_reg
, &pll
->pll_base
);
546 base_reg
&= ~PLL_BYPASS_MASK
;
547 writel(base_reg
, &pll
->pll_base
);
552 void clock_ll_start_uart(enum periph_id periph_id
)
554 /* Assert UART reset and enable clock */
555 reset_set_enable(periph_id
, 1);
556 clock_enable(periph_id
);
557 clock_ll_set_source(periph_id
, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
562 /* De-assert reset to UART */
563 reset_set_enable(periph_id
, 0);
566 #ifdef CONFIG_OF_CONTROL
567 int clock_decode_periph_id(const void *blob
, int node
)
573 err
= fdtdec_get_int_array(blob
, node
, "clocks", cell
,
577 id
= clk_id_to_periph_id(cell
[1]);
578 assert(clock_periph_id_isvalid(id
));
581 #endif /* CONFIG_OF_CONTROL */
583 int clock_verify(void)
585 struct clk_pll
*pll
= get_pll(CLOCK_ID_PERIPH
);
586 u32 reg
= readl(&pll
->pll_base
);
589 printf("Warning: PLLP %x is not correct\n", reg
);
592 debug("PLLP %x is correct\n", reg
);
596 void clock_init(void)
598 pll_rate
[CLOCK_ID_MEMORY
] = clock_get_rate(CLOCK_ID_MEMORY
);
599 pll_rate
[CLOCK_ID_PERIPH
] = clock_get_rate(CLOCK_ID_PERIPH
);
600 pll_rate
[CLOCK_ID_CGENERAL
] = clock_get_rate(CLOCK_ID_CGENERAL
);
601 pll_rate
[CLOCK_ID_DISPLAY
] = clock_get_rate(CLOCK_ID_DISPLAY
);
602 pll_rate
[CLOCK_ID_OSC
] = clock_get_rate(CLOCK_ID_OSC
);
603 pll_rate
[CLOCK_ID_SFROM32KHZ
] = 32768;
604 pll_rate
[CLOCK_ID_XCPU
] = clock_get_rate(CLOCK_ID_XCPU
);
605 debug("Osc = %d\n", pll_rate
[CLOCK_ID_OSC
]);
606 debug("PLLM = %d\n", pll_rate
[CLOCK_ID_MEMORY
]);
607 debug("PLLP = %d\n", pll_rate
[CLOCK_ID_PERIPH
]);
608 debug("PLLC = %d\n", pll_rate
[CLOCK_ID_CGENERAL
]);
609 debug("PLLD = %d\n", pll_rate
[CLOCK_ID_DISPLAY
]);
610 debug("PLLX = %d\n", pll_rate
[CLOCK_ID_XCPU
]);
613 static void set_avp_clock_source(u32 src
)
615 struct clk_rst_ctlr
*clkrst
=
616 (struct clk_rst_ctlr
*)NV_PA_CLK_RST_BASE
;
619 val
= (src
<< SCLK_SWAKEUP_FIQ_SOURCE_SHIFT
) |
620 (src
<< SCLK_SWAKEUP_IRQ_SOURCE_SHIFT
) |
621 (src
<< SCLK_SWAKEUP_RUN_SOURCE_SHIFT
) |
622 (src
<< SCLK_SWAKEUP_IDLE_SOURCE_SHIFT
) |
623 (SCLK_SYS_STATE_RUN
<< SCLK_SYS_STATE_SHIFT
);
624 writel(val
, &clkrst
->crc_sclk_brst_pol
);
629 * This function is useful on Tegra30, and any later SoCs that have compatible
630 * PLLP configuration registers.
632 void tegra30_set_up_pllp(void)
634 struct clk_rst_ctlr
*clkrst
= (struct clk_rst_ctlr
*)NV_PA_CLK_RST_BASE
;
638 * Based on the Tegra TRM, the system clock (which is the AVP clock) can
639 * run up to 275MHz. On power on, the default sytem clock source is set
640 * to PLLP_OUT0. This function sets PLLP's (hence PLLP_OUT0's) rate to
641 * 408MHz which is beyond system clock's upper limit.
643 * The fix is to set the system clock to CLK_M before initializing PLLP,
644 * and then switch back to PLLP_OUT4, which has an appropriate divider
645 * configured, after PLLP has been configured
647 set_avp_clock_source(SCLK_SOURCE_CLKM
);
650 * PLLP output frequency set to 408Mhz
651 * PLLC output frequency set to 228Mhz
653 switch (clock_get_osc_freq()) {
654 case CLOCK_OSC_FREQ_12_0
: /* OSC is 12Mhz */
655 clock_set_rate(CLOCK_ID_PERIPH
, 408, 12, 0, 8);
656 clock_set_rate(CLOCK_ID_CGENERAL
, 456, 12, 1, 8);
659 case CLOCK_OSC_FREQ_26_0
: /* OSC is 26Mhz */
660 clock_set_rate(CLOCK_ID_PERIPH
, 408, 26, 0, 8);
661 clock_set_rate(CLOCK_ID_CGENERAL
, 600, 26, 0, 8);
664 case CLOCK_OSC_FREQ_13_0
: /* OSC is 13Mhz */
665 clock_set_rate(CLOCK_ID_PERIPH
, 408, 13, 0, 8);
666 clock_set_rate(CLOCK_ID_CGENERAL
, 600, 13, 0, 8);
668 case CLOCK_OSC_FREQ_19_2
:
671 * These are not supported. It is too early to print a
672 * message and the UART likely won't work anyway due to the
673 * oscillator being wrong.
678 /* Set PLLP_OUT1, 2, 3 & 4 freqs to 9.6, 48, 102 & 204MHz */
681 /* Assert RSTN before enable */
682 reg
= PLLP_OUT2_RSTN_EN
| PLLP_OUT1_RSTN_EN
;
683 writel(reg
, &clkrst
->crc_pll
[CLOCK_ID_PERIPH
].pll_out
[0]);
684 /* Set divisor and reenable */
685 reg
= (IN_408_OUT_48_DIVISOR
<< PLLP_OUT2_RATIO
)
686 | PLLP_OUT2_OVR
| PLLP_OUT2_CLKEN
| PLLP_OUT2_RSTN_DIS
687 | (IN_408_OUT_9_6_DIVISOR
<< PLLP_OUT1_RATIO
)
688 | PLLP_OUT1_OVR
| PLLP_OUT1_CLKEN
| PLLP_OUT1_RSTN_DIS
;
689 writel(reg
, &clkrst
->crc_pll
[CLOCK_ID_PERIPH
].pll_out
[0]);
692 /* Assert RSTN before enable */
693 reg
= PLLP_OUT4_RSTN_EN
| PLLP_OUT3_RSTN_EN
;
694 writel(reg
, &clkrst
->crc_pll
[CLOCK_ID_PERIPH
].pll_out
[1]);
695 /* Set divisor and reenable */
696 reg
= (IN_408_OUT_204_DIVISOR
<< PLLP_OUT4_RATIO
)
697 | PLLP_OUT4_OVR
| PLLP_OUT4_CLKEN
| PLLP_OUT4_RSTN_DIS
698 | (IN_408_OUT_102_DIVISOR
<< PLLP_OUT3_RATIO
)
699 | PLLP_OUT3_OVR
| PLLP_OUT3_CLKEN
| PLLP_OUT3_RSTN_DIS
;
700 writel(reg
, &clkrst
->crc_pll
[CLOCK_ID_PERIPH
].pll_out
[1]);
702 set_avp_clock_source(SCLK_SOURCE_PLLP_OUT4
);
705 int clock_external_output(int clk_id
)
707 struct pmc_ctlr
*pmc
= (struct pmc_ctlr
*)NV_PA_PMC_BASE
;
709 if (clk_id
>= 1 && clk_id
<= 3) {
710 setbits_le32(&pmc
->pmc_clk_out_cntrl
,
711 1 << (2 + (clk_id
- 1) * 8));
713 printf("%s: Unknown output clock id %d\n", __func__
, clk_id
);