Home | History | Annotate | Line # | Download | only in bootimx23
clock_prep.c revision 1.2.2.2
      1 /* $Id: clock_prep.c,v 1.2.2.2 2013/01/16 05:32:56 yamt 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/param.h>
     33 #include <sys/cdefs.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 void enable_pll(void);
     43 void enable_ref_cpu(int);
     44 void enable_ref_emi(int);
     45 void enable_ref_io(int);
     46 void use_ref_cpu(void);
     47 void use_ref_emi(void);
     48 void use_ref_io(void);
     49 void set_hbus_div(int);
     50 void set_emi_div(int);
     51 void set_ssp_div(int);
     52 
     53 /* Clock frequences after clock_prep() */
     54 #define CPU_FRAC 0x13		/* CPUCLK @ 454.74 MHz */
     55 #define HBUS_DIV 0x3		/* AHBCLK @ 151.58 MHz */
     56 #define EMI_FRAC 0x21		/* EMICLK @ 130.91 MHz */
     57 #define EMI_DIV 0x2
     58 #define IO_FRAC 0x12		/* IOCLK  @ 480.00 MHz */
     59 #define SSP_DIV 0x5		/* SSPCLK @  96.00 MHz */
     60 
     61 /* Offset to frac register for byte store instructions. (strb) */
     62 #define HW_CLKCTRL_FRAC_CPU (HW_CLKCTRL_FRAC+0)
     63 #define HW_CLKCTRL_FRAC_EMI (HW_CLKCTRL_FRAC+1)
     64 #define HW_CLKCTRL_FRAC_IO (HW_CLKCTRL_FRAC+3)
     65 
     66 #define CLKCTRL_RD(reg) *(volatile uint32_t *)((HW_CLKCTRL_BASE) + (reg))
     67 #define CLKCTRL_WR(reg, val)						\
     68 do {									\
     69 	*(volatile uint32_t *)((HW_CLKCTRL_BASE) + (reg)) = val;	\
     70 } while (0)
     71 #define CLKCTRL_WR_BYTE(reg, val)					\
     72 do {									\
     73 	*(volatile uint8_t *)((HW_CLKCTRL_BASE) + (reg)) = val;	\
     74 } while (0)
     75 
     76 /*
     77  * Initializes fast PLL based clocks for CPU, HBUS and DRAM.
     78  */
     79 int
     80 clock_prep(void)
     81 {
     82 
     83 	enable_pll();
     84 	enable_ref_cpu(CPU_FRAC);
     85 	enable_ref_emi(EMI_FRAC);
     86 	enable_ref_io(IO_FRAC);
     87 	set_emi_div(EMI_DIV);
     88 	set_hbus_div(HBUS_DIV);
     89 	delay_us(1000);
     90 	use_ref_cpu();
     91 	//delay_us(1000);
     92 	use_ref_emi();
     93 	use_ref_io();
     94 	set_ssp_div(SSP_DIV);
     95 
     96 	return 0;
     97 }
     98 
     99 /*
    100  * Turn PLL on and wait until it's locked to 480 MHz.
    101  */
    102 void
    103 enable_pll(void)
    104 {
    105 
    106 	CLKCTRL_WR(HW_CLKCTRL_PLLCTRL0_SET, HW_CLKCTRL_PLLCTRL0_POWER);
    107 	while (!(CLKCTRL_RD(HW_CLKCTRL_PLLCTRL1) & HW_CLKCTRL_PLLCTRL1_LOCK));
    108 
    109 	return;
    110 }
    111 
    112 /*
    113  * Enable fractional divider clock ref_cpu with divide value "frac".
    114  */
    115 void
    116 enable_ref_cpu(int frac)
    117 {
    118 	uint32_t reg;
    119 
    120 	reg = CLKCTRL_RD(HW_CLKCTRL_FRAC);
    121 	reg &= ~(HW_CLKCTRL_FRAC_CLKGATECPU | HW_CLKCTRL_FRAC_CPUFRAC);
    122 	reg |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_CPUFRAC);
    123 	CLKCTRL_WR_BYTE(HW_CLKCTRL_FRAC_CPU, reg);
    124 
    125 	return;
    126 }
    127 
    128 /*
    129  * Enable fractional divider clock ref_emi with divide value "frac".
    130  */
    131 void
    132 enable_ref_emi(int frac)
    133 {
    134 	uint32_t reg;
    135 
    136 	reg = CLKCTRL_RD(HW_CLKCTRL_FRAC);
    137 	reg &= ~(HW_CLKCTRL_FRAC_CLKGATEEMI | HW_CLKCTRL_FRAC_EMIFRAC);
    138 	reg |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_EMIFRAC);
    139 	CLKCTRL_WR_BYTE(HW_CLKCTRL_FRAC_EMI, (reg >> 8));
    140 
    141 	return;
    142 }
    143 
    144 /*
    145  * Enable fractional divider clock ref_io with divide value "frac".
    146  */
    147 void
    148 enable_ref_io(int frac)
    149 {
    150 	uint32_t reg;
    151 
    152 	reg = CLKCTRL_RD(HW_CLKCTRL_FRAC);
    153 	reg &= ~(HW_CLKCTRL_FRAC_CLKGATEIO | HW_CLKCTRL_FRAC_IOFRAC);
    154 	reg |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_IOFRAC);
    155 	CLKCTRL_WR_BYTE(HW_CLKCTRL_FRAC_IO, (reg >> 24));
    156 
    157 	return;
    158 }
    159 
    160 /*
    161  * Divide CLK_P by "div" to get CLK_H frequency.
    162  */
    163 void
    164 set_hbus_div(int div)
    165 {
    166 	uint32_t reg;
    167 
    168 	reg = CLKCTRL_RD(HW_CLKCTRL_HBUS);
    169 	reg &= ~(HW_CLKCTRL_HBUS_DIV);
    170 	reg |= __SHIFTIN(div, HW_CLKCTRL_HBUS_DIV);
    171 	while (CLKCTRL_RD(HW_CLKCTRL_HBUS) & HW_CLKCTRL_HBUS_BUSY);
    172 	CLKCTRL_WR(HW_CLKCTRL_HBUS, reg);
    173 
    174 	return;
    175 }
    176 
    177 /*
    178  * ref_emi is divied "div" to get CLK_EMI.
    179  */
    180 void
    181 set_emi_div(int div)
    182 {
    183 	uint32_t reg;
    184 
    185 	reg = CLKCTRL_RD(HW_CLKCTRL_EMI);
    186 	reg &= ~(HW_CLKCTRL_EMI_DIV_EMI);
    187 	reg |= __SHIFTIN(div, HW_CLKCTRL_EMI_DIV_EMI);
    188 	CLKCTRL_WR(HW_CLKCTRL_EMI, reg);
    189 
    190 	return;
    191 }
    192 
    193 /*
    194  * ref_io is divied "div" to get CLK_SSP.
    195  */
    196 void
    197 set_ssp_div(int div)
    198 {
    199 	uint32_t reg;
    200 
    201 	reg = CLKCTRL_RD(HW_CLKCTRL_SSP);
    202 	reg &= ~(HW_CLKCTRL_SSP_DIV);
    203 	reg |= __SHIFTIN(div, HW_CLKCTRL_SSP_DIV);
    204 	CLKCTRL_WR(HW_CLKCTRL_SSP, reg);
    205 
    206 	return;
    207 }
    208 
    209 /*
    210  * Transition from ref_xtal to use ref_cpu.
    211  */
    212 void
    213 use_ref_cpu(void)
    214 {
    215 	CLKCTRL_WR(HW_CLKCTRL_CLKSEQ_CLR, HW_CLKCTRL_CLKSEQ_BYPASS_CPU);
    216 	return;
    217 }
    218 
    219 /*
    220  * Transition from ref_xtal to use ref_emi and source CLK_EMI from ref_emi.
    221  */
    222 void
    223 use_ref_emi(void)
    224 {
    225 	uint32_t reg;
    226 
    227 	/* Enable ref_emi. */
    228 	CLKCTRL_WR(HW_CLKCTRL_CLKSEQ_CLR, HW_CLKCTRL_CLKSEQ_BYPASS_EMI);
    229 
    230 	/* CLK_EMI sourced by the ref_emi. */
    231 	reg = CLKCTRL_RD(HW_CLKCTRL_EMI);
    232 	reg &= ~(HW_CLKCTRL_EMI_CLKGATE);
    233 	CLKCTRL_WR(HW_CLKCTRL_EMI, reg);
    234 
    235 	return;
    236 }
    237 
    238 /*
    239  * Transition from ref_xtal to use ref_io and source CLK_SSP from ref_io.
    240  */
    241 void
    242 use_ref_io(void)
    243 {
    244 	uint32_t reg;
    245 
    246 	/* Enable ref_io for SSP. */
    247 	CLKCTRL_WR(HW_CLKCTRL_CLKSEQ_CLR, HW_CLKCTRL_CLKSEQ_BYPASS_SSP);
    248 
    249 	/* CLK_SSP sourced by the ref_io. */
    250 	reg = CLKCTRL_RD(HW_CLKCTRL_SSP);
    251 	reg &= ~(HW_CLKCTRL_SSP_CLKGATE);
    252 	CLKCTRL_WR(HW_CLKCTRL_SSP, reg);
    253 
    254 	return;
    255 }
    256