Home | History | Annotate | Line # | Download | only in bootimx23
      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
     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
     78 bypass_cpu(void)
     79 {
     80 
     81 	REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_CPU);
     82 
     83 	return;
     84 }
     85 void
     86 bypass_emi(void)
     87 {
     88 	REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_EMI);
     89 
     90 	return;
     91 }
     92 void
     93 bypass_ssp(void)
     94 {
     95 	REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_SSP);
     96 
     97 	return;
     98 }
     99 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
    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
    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
    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
    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
    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
    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