xref: /netbsd-src/sys/arch/evbarm/stand/bootimx23/clock_prep.c (revision 94de07308fa702688d56949a9efc73b223f72255)
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