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 56void en_pll(void); 57void set_hbus_div(unsigned int); 58void set_cpu_frac(unsigned int); 59void bypass_cpu(void); 60void set_emi_div(unsigned int); 61void set_emi_frac(unsigned int); 62void bypass_emi(void); 63 64/* 65 * Power on 480 MHz PLL. 66 */ 67void 68en_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} 77void 78bypass_cpu(void) 79{ 80 81 REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_CPU); 82 83 return; 84} 85void 86bypass_emi(void) 87{ 88 REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_EMI); 89 90 return; 91} 92void 93bypass_ssp(void) 94{ 95 REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_SSP); 96 97 return; 98} 99void 100bypass_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 */ 109void 110set_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 */ 130void 131set_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 */ 145void 146set_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 */ 165void 166set_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 */ 184void 185set_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 */ 209void 210set_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