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