xref: /netbsd-src/sys/arch/evbarm/stand/bootimx23/clock_prep.c (revision 94de07308fa702688d56949a9efc73b223f72255)
1*94de0730Smatt /* $Id: clock_prep.c,v 1.3 2013/10/07 17:36:40 matt Exp $ */
2da8587eaSjkunz 
3da8587eaSjkunz /*
4da8587eaSjkunz  * Copyright (c) 2012 The NetBSD Foundation, Inc.
5da8587eaSjkunz  * All rights reserved.
6da8587eaSjkunz  *
7da8587eaSjkunz  * This code is derived from software contributed to The NetBSD Foundation
8da8587eaSjkunz  * by Petri Laakso.
9da8587eaSjkunz  *
10da8587eaSjkunz  * Redistribution and use in source and binary forms, with or without
11da8587eaSjkunz  * modification, are permitted provided that the following conditions
12da8587eaSjkunz  * are met:
13da8587eaSjkunz  * 1. Redistributions of source code must retain the above copyright
14da8587eaSjkunz  *    notice, this list of conditions and the following disclaimer.
15da8587eaSjkunz  * 2. Redistributions in binary form must reproduce the above copyright
16da8587eaSjkunz  *    notice, this list of conditions and the following disclaimer in the
17da8587eaSjkunz  *    documentation and/or other materials provided with the distribution.
18da8587eaSjkunz  *
19da8587eaSjkunz  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20da8587eaSjkunz  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21da8587eaSjkunz  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22da8587eaSjkunz  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23da8587eaSjkunz  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24da8587eaSjkunz  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25da8587eaSjkunz  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26da8587eaSjkunz  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27da8587eaSjkunz  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28da8587eaSjkunz  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29da8587eaSjkunz  * POSSIBILITY OF SUCH DAMAGE.
30da8587eaSjkunz  */
31da8587eaSjkunz 
32da8587eaSjkunz #include <sys/cdefs.h>
33*94de0730Smatt #include <sys/param.h>
34da8587eaSjkunz #include <sys/types.h>
35da8587eaSjkunz 
36da8587eaSjkunz #include <arm/imx/imx23_clkctrlreg.h>
37da8587eaSjkunz 
38da8587eaSjkunz #include <lib/libsa/stand.h>
39da8587eaSjkunz 
40da8587eaSjkunz #include "common.h"
41da8587eaSjkunz 
42*94de0730Smatt #define CLKCTRL_HBUS	(HW_CLKCTRL_BASE + HW_CLKCTRL_HBUS)
43*94de0730Smatt #define CLKCTRL_PLL0	(HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0)
44*94de0730Smatt #define CLKCTRL_PLL0_S	(HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0_SET)
45*94de0730Smatt #define CLKCTRL_PLL0_C	(HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0_CLR)
46*94de0730Smatt #define CLKCTRL_PLL1	(HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL1)
47*94de0730Smatt #define CLKCTRL_FRAC	(HW_CLKCTRL_BASE + HW_CLKCTRL_FRAC)
48*94de0730Smatt #define CLKCTRL_FRAC_S	(HW_CLKCTRL_BASE + HW_CLKCTRL_FRAC_SET)
49*94de0730Smatt #define CLKCTRL_FRAC_C	(HW_CLKCTRL_BASE + HW_CLKCTRL_FRAC_CLR)
50*94de0730Smatt #define CLKCTRL_SEQ	(HW_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ)
51*94de0730Smatt #define CLKCTRL_SEQ_S	(HW_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ_SET)
52*94de0730Smatt #define CLKCTRL_SEQ_C	(HW_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ_CLR)
53*94de0730Smatt #define CLKCTRL_EMI	(HW_CLKCTRL_BASE + HW_CLKCTRL_EMI)
54*94de0730Smatt #define CLKCTRL_SSP	(HW_CLKCTRL_BASE + HW_CLKCTRL_SSP)
55*94de0730Smatt 
56*94de0730Smatt void en_pll(void);
57*94de0730Smatt void set_hbus_div(unsigned int);
58*94de0730Smatt void set_cpu_frac(unsigned int);
59*94de0730Smatt void bypass_cpu(void);
60*94de0730Smatt void set_emi_div(unsigned int);
61*94de0730Smatt void set_emi_frac(unsigned int);
62*94de0730Smatt void bypass_emi(void);
63da8587eaSjkunz 
645379dc38Sjkunz /*
65*94de0730Smatt  * Power on 480 MHz PLL.
665379dc38Sjkunz  */
67*94de0730Smatt void
en_pll(void)68*94de0730Smatt en_pll(void)
69da8587eaSjkunz {
70da8587eaSjkunz 
71*94de0730Smatt 	REG_WR(CLKCTRL_PLL0_S, HW_CLKCTRL_PLLCTRL0_POWER);
72*94de0730Smatt 	while(!(REG_RD(CLKCTRL_PLL1) & HW_CLKCTRL_PLLCTRL1))
73*94de0730Smatt 		;
74da8587eaSjkunz 
75da8587eaSjkunz 	return;
76da8587eaSjkunz }
77*94de0730Smatt void
bypass_cpu(void)78*94de0730Smatt bypass_cpu(void)
79da8587eaSjkunz {
80da8587eaSjkunz 
81*94de0730Smatt 	REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_CPU);
82da8587eaSjkunz 
83da8587eaSjkunz 	return;
84da8587eaSjkunz }
85*94de0730Smatt void
bypass_emi(void)86*94de0730Smatt bypass_emi(void)
87da8587eaSjkunz {
88*94de0730Smatt 	REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_EMI);
89da8587eaSjkunz 
90da8587eaSjkunz 	return;
91da8587eaSjkunz }
92*94de0730Smatt void
bypass_ssp(void)93*94de0730Smatt bypass_ssp(void)
94da8587eaSjkunz {
95*94de0730Smatt 	REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_SSP);
96da8587eaSjkunz 
97da8587eaSjkunz 	return;
98da8587eaSjkunz }
99*94de0730Smatt void
bypass_saif(void)100*94de0730Smatt bypass_saif(void)
101da8587eaSjkunz {
102*94de0730Smatt 	REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_SAIF);
103da8587eaSjkunz 
104da8587eaSjkunz 	return;
105da8587eaSjkunz }
106da8587eaSjkunz /*
107*94de0730Smatt  * Set HBUS divider value.
108da8587eaSjkunz  */
109*94de0730Smatt void
set_hbus_div(unsigned int div)110*94de0730Smatt set_hbus_div(unsigned int div)
111da8587eaSjkunz {
112*94de0730Smatt 	uint32_t tmp_r;
113da8587eaSjkunz 
114*94de0730Smatt 	while (REG_RD(CLKCTRL_HBUS) & HW_CLKCTRL_HBUS_BUSY)
115*94de0730Smatt 		;
116*94de0730Smatt 
117*94de0730Smatt 	tmp_r = REG_RD(CLKCTRL_HBUS);
118*94de0730Smatt 	tmp_r &= ~HW_CLKCTRL_HBUS_DIV;
119*94de0730Smatt 	tmp_r |= __SHIFTIN(div, HW_CLKCTRL_HBUS_DIV);
120*94de0730Smatt 	REG_WR(CLKCTRL_HBUS, tmp_r);
121*94de0730Smatt 
122*94de0730Smatt 	while (REG_RD(CLKCTRL_HBUS) & HW_CLKCTRL_HBUS_BUSY)
123*94de0730Smatt 		;
124da8587eaSjkunz 
125da8587eaSjkunz 	return;
126da8587eaSjkunz }
127da8587eaSjkunz /*
128*94de0730Smatt  * Set CPU frac.
129da8587eaSjkunz  */
130*94de0730Smatt void
set_cpu_frac(unsigned int frac)131*94de0730Smatt set_cpu_frac(unsigned int frac)
132da8587eaSjkunz {
133*94de0730Smatt 	uint8_t tmp_r;
134da8587eaSjkunz 
135*94de0730Smatt 	tmp_r = REG_RD_BYTE(CLKCTRL_FRAC);
136*94de0730Smatt 	tmp_r &= ~(HW_CLKCTRL_FRAC_CLKGATECPU | HW_CLKCTRL_FRAC_CPUFRAC);
137*94de0730Smatt 	tmp_r |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_CPUFRAC);
138*94de0730Smatt 	REG_WR_BYTE(CLKCTRL_FRAC, tmp_r);
139da8587eaSjkunz 
140da8587eaSjkunz 	return;
141da8587eaSjkunz }
142da8587eaSjkunz /*
143*94de0730Smatt  * Set EMI frac.
144da8587eaSjkunz  */
145*94de0730Smatt void
set_emi_frac(unsigned int frac)146*94de0730Smatt set_emi_frac(unsigned int frac)
147da8587eaSjkunz {
148*94de0730Smatt 	uint8_t *emi_frac;
149*94de0730Smatt 	uint16_t tmp_r;
150da8587eaSjkunz 
151*94de0730Smatt 	emi_frac = (uint8_t *)(CLKCTRL_FRAC);
152*94de0730Smatt 	emi_frac++;
153da8587eaSjkunz 
154*94de0730Smatt 	tmp_r = *emi_frac<<8;
155*94de0730Smatt 	tmp_r &= ~(HW_CLKCTRL_FRAC_CLKGATEEMI | HW_CLKCTRL_FRAC_EMIFRAC);
156*94de0730Smatt 	tmp_r |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_EMIFRAC);
157da8587eaSjkunz 
158*94de0730Smatt 	*emi_frac = tmp_r>>8;
159da8587eaSjkunz 
160da8587eaSjkunz 	return;
161da8587eaSjkunz }
162da8587eaSjkunz /*
163*94de0730Smatt  * Set EMU divider value.
164da8587eaSjkunz  */
165*94de0730Smatt void
set_emi_div(unsigned int div)166*94de0730Smatt set_emi_div(unsigned int div)
167da8587eaSjkunz {
168*94de0730Smatt 	uint32_t tmp_r;
169da8587eaSjkunz 
170*94de0730Smatt 	while (REG_RD(CLKCTRL_EMI) &
171*94de0730Smatt 		(HW_CLKCTRL_EMI_BUSY_REF_XTAL | HW_CLKCTRL_EMI_BUSY_REF_EMI))
172*94de0730Smatt 		;
173da8587eaSjkunz 
174*94de0730Smatt 	tmp_r = REG_RD(CLKCTRL_EMI);
175*94de0730Smatt 	tmp_r &= ~(HW_CLKCTRL_EMI_CLKGATE | HW_CLKCTRL_EMI_DIV_EMI);
176*94de0730Smatt 	tmp_r |= __SHIFTIN(div, HW_CLKCTRL_EMI_DIV_EMI);
177*94de0730Smatt 	REG_WR(CLKCTRL_EMI, tmp_r);
178*94de0730Smatt 
179*94de0730Smatt 	return;
180*94de0730Smatt }
181*94de0730Smatt /*
182*94de0730Smatt  * Set SSP divider value.
183*94de0730Smatt  */
184*94de0730Smatt void
set_ssp_div(unsigned int div)185*94de0730Smatt set_ssp_div(unsigned int div)
186*94de0730Smatt {
187*94de0730Smatt 	uint32_t tmp_r;
188*94de0730Smatt 
189*94de0730Smatt 	tmp_r = REG_RD(CLKCTRL_SSP);
190*94de0730Smatt 	tmp_r &= ~HW_CLKCTRL_SSP_CLKGATE;
191*94de0730Smatt 	REG_WR(CLKCTRL_SSP, tmp_r);
192*94de0730Smatt 
193*94de0730Smatt 	while (REG_RD(CLKCTRL_SSP) & HW_CLKCTRL_SSP_BUSY)
194*94de0730Smatt 		;
195*94de0730Smatt 
196*94de0730Smatt 	tmp_r = REG_RD(CLKCTRL_SSP);
197*94de0730Smatt 	tmp_r &= ~HW_CLKCTRL_SSP_DIV;
198*94de0730Smatt 	tmp_r |= __SHIFTIN(div, HW_CLKCTRL_SSP_DIV);
199*94de0730Smatt 	REG_WR(CLKCTRL_SSP, tmp_r);
200*94de0730Smatt 
201*94de0730Smatt 	while (REG_RD(CLKCTRL_SSP) & HW_CLKCTRL_SSP_BUSY)
202*94de0730Smatt 		;
203*94de0730Smatt 
204*94de0730Smatt 	return;
205*94de0730Smatt }
206*94de0730Smatt /*
207*94de0730Smatt  * Set IO frac.
208*94de0730Smatt  */
209*94de0730Smatt void
set_io_frac(unsigned int frac)210*94de0730Smatt set_io_frac(unsigned int frac)
211*94de0730Smatt {
212*94de0730Smatt 	uint8_t *io_frac;
213*94de0730Smatt 	uint32_t tmp_r;
214*94de0730Smatt 
215*94de0730Smatt 	io_frac = (uint8_t *)(CLKCTRL_FRAC);
216*94de0730Smatt 	io_frac++; /* emi */
217*94de0730Smatt 	io_frac++; /* pix */
218*94de0730Smatt 	io_frac++; /* io */
219*94de0730Smatt 	tmp_r = (*io_frac)<<24;
220*94de0730Smatt 	tmp_r &= ~(HW_CLKCTRL_FRAC_CLKGATEIO | HW_CLKCTRL_FRAC_IOFRAC);
221*94de0730Smatt 	tmp_r |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_IOFRAC);
222*94de0730Smatt 
223*94de0730Smatt 	*io_frac = (uint8_t)(tmp_r>>24);
224da8587eaSjkunz 
225da8587eaSjkunz 	return;
226da8587eaSjkunz }
227