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