/* $Id: clock_prep.c,v 1.3 2013/10/07 17:36:40 matt Exp $ */ /* * Copyright (c) 2012 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Petri Laakso. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "common.h" #define CLKCTRL_HBUS (HW_CLKCTRL_BASE + HW_CLKCTRL_HBUS) #define CLKCTRL_PLL0 (HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0) #define CLKCTRL_PLL0_S (HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0_SET) #define CLKCTRL_PLL0_C (HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0_CLR) #define CLKCTRL_PLL1 (HW_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL1) #define CLKCTRL_FRAC (HW_CLKCTRL_BASE + HW_CLKCTRL_FRAC) #define CLKCTRL_FRAC_S (HW_CLKCTRL_BASE + HW_CLKCTRL_FRAC_SET) #define CLKCTRL_FRAC_C (HW_CLKCTRL_BASE + HW_CLKCTRL_FRAC_CLR) #define CLKCTRL_SEQ (HW_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ) #define CLKCTRL_SEQ_S (HW_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ_SET) #define CLKCTRL_SEQ_C (HW_CLKCTRL_BASE + HW_CLKCTRL_CLKSEQ_CLR) #define CLKCTRL_EMI (HW_CLKCTRL_BASE + HW_CLKCTRL_EMI) #define CLKCTRL_SSP (HW_CLKCTRL_BASE + HW_CLKCTRL_SSP) void en_pll(void); void set_hbus_div(unsigned int); void set_cpu_frac(unsigned int); void bypass_cpu(void); void set_emi_div(unsigned int); void set_emi_frac(unsigned int); void bypass_emi(void); /* * Power on 480 MHz PLL. */ void en_pll(void) { REG_WR(CLKCTRL_PLL0_S, HW_CLKCTRL_PLLCTRL0_POWER); while(!(REG_RD(CLKCTRL_PLL1) & HW_CLKCTRL_PLLCTRL1)) ; return; } void bypass_cpu(void) { REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_CPU); return; } void bypass_emi(void) { REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_EMI); return; } void bypass_ssp(void) { REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_SSP); return; } void bypass_saif(void) { REG_WR(CLKCTRL_SEQ_C, HW_CLKCTRL_CLKSEQ_BYPASS_SAIF); return; } /* * Set HBUS divider value. */ void set_hbus_div(unsigned int div) { uint32_t tmp_r; while (REG_RD(CLKCTRL_HBUS) & HW_CLKCTRL_HBUS_BUSY) ; tmp_r = REG_RD(CLKCTRL_HBUS); tmp_r &= ~HW_CLKCTRL_HBUS_DIV; tmp_r |= __SHIFTIN(div, HW_CLKCTRL_HBUS_DIV); REG_WR(CLKCTRL_HBUS, tmp_r); while (REG_RD(CLKCTRL_HBUS) & HW_CLKCTRL_HBUS_BUSY) ; return; } /* * Set CPU frac. */ void set_cpu_frac(unsigned int frac) { uint8_t tmp_r; tmp_r = REG_RD_BYTE(CLKCTRL_FRAC); tmp_r &= ~(HW_CLKCTRL_FRAC_CLKGATECPU | HW_CLKCTRL_FRAC_CPUFRAC); tmp_r |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_CPUFRAC); REG_WR_BYTE(CLKCTRL_FRAC, tmp_r); return; } /* * Set EMI frac. */ void set_emi_frac(unsigned int frac) { uint8_t *emi_frac; uint16_t tmp_r; emi_frac = (uint8_t *)(CLKCTRL_FRAC); emi_frac++; tmp_r = *emi_frac<<8; tmp_r &= ~(HW_CLKCTRL_FRAC_CLKGATEEMI | HW_CLKCTRL_FRAC_EMIFRAC); tmp_r |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_EMIFRAC); *emi_frac = tmp_r>>8; return; } /* * Set EMU divider value. */ void set_emi_div(unsigned int div) { uint32_t tmp_r; while (REG_RD(CLKCTRL_EMI) & (HW_CLKCTRL_EMI_BUSY_REF_XTAL | HW_CLKCTRL_EMI_BUSY_REF_EMI)) ; tmp_r = REG_RD(CLKCTRL_EMI); tmp_r &= ~(HW_CLKCTRL_EMI_CLKGATE | HW_CLKCTRL_EMI_DIV_EMI); tmp_r |= __SHIFTIN(div, HW_CLKCTRL_EMI_DIV_EMI); REG_WR(CLKCTRL_EMI, tmp_r); return; } /* * Set SSP divider value. */ void set_ssp_div(unsigned int div) { uint32_t tmp_r; tmp_r = REG_RD(CLKCTRL_SSP); tmp_r &= ~HW_CLKCTRL_SSP_CLKGATE; REG_WR(CLKCTRL_SSP, tmp_r); while (REG_RD(CLKCTRL_SSP) & HW_CLKCTRL_SSP_BUSY) ; tmp_r = REG_RD(CLKCTRL_SSP); tmp_r &= ~HW_CLKCTRL_SSP_DIV; tmp_r |= __SHIFTIN(div, HW_CLKCTRL_SSP_DIV); REG_WR(CLKCTRL_SSP, tmp_r); while (REG_RD(CLKCTRL_SSP) & HW_CLKCTRL_SSP_BUSY) ; return; } /* * Set IO frac. */ void set_io_frac(unsigned int frac) { uint8_t *io_frac; uint32_t tmp_r; io_frac = (uint8_t *)(CLKCTRL_FRAC); io_frac++; /* emi */ io_frac++; /* pix */ io_frac++; /* io */ tmp_r = (*io_frac)<<24; tmp_r &= ~(HW_CLKCTRL_FRAC_CLKGATEIO | HW_CLKCTRL_FRAC_IOFRAC); tmp_r |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_IOFRAC); *io_frac = (uint8_t)(tmp_r>>24); return; }