227 lines
5.3 KiB
C
227 lines
5.3 KiB
C
/* $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 <sys/cdefs.h>
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <arm/imx/imx23_clkctrlreg.h>
|
|
|
|
#include <lib/libsa/stand.h>
|
|
|
|
#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;
|
|
}
|