forked from xuos/xiuos
1251 lines
35 KiB
C
1251 lines
35 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause */
|
|
/*
|
|
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
|
|
*/
|
|
|
|
#include "hal_base.h"
|
|
#include "hal_def.h"
|
|
#include "hal_cru.h"
|
|
|
|
/** @addtogroup RK_HAL_Driver
|
|
* @{
|
|
*/
|
|
|
|
/** @addtogroup CRU
|
|
* @{
|
|
*/
|
|
|
|
/** @defgroup CRU_How_To_Use How To Use
|
|
* @{
|
|
|
|
The CRU driver can be used as follows:
|
|
|
|
- Invoke cru functions to set clk rate, enable or disable clk, reset clk in each device.
|
|
- The gate and soft reset id is include register offset and shift information:
|
|
|
|
con_offset: id /16
|
|
shift: id %16
|
|
|
|
- The mux and div id is include register offset, shift, mask information:
|
|
|
|
[15:0]: con
|
|
[23:16]: shift
|
|
[31:24]: width
|
|
|
|
- CRU driver is just responsible for passing simple command data, And
|
|
the usecount is the user's responsibility. Protection the usecount at the driver layer.
|
|
- More details refer to APIs' descriptions as below.
|
|
|
|
@} */
|
|
|
|
/** @defgroup CRU_Private_Definition Private Definition
|
|
* @{
|
|
*/
|
|
/********************* Private MACRO Definition ******************************/
|
|
|
|
#define PWRDOWN_SHIFT 13
|
|
#define PWRDOWN_MASK 1 << PWRDOWN_SHIFT
|
|
#define PLL_POSTDIV1_SHIFT 12
|
|
#define PLL_POSTDIV1_MASK 0x7 << PLL_POSTDIV1_SHIFT
|
|
#define PLL_FBDIV_SHIFT 0
|
|
#define PLL_FBDIV_MASK 0xfff << PLL_FBDIV_SHIFT
|
|
#define PLL_POSTDIV2_SHIFT 6
|
|
#define PLL_POSTDIV2_MASK 0x7 << PLL_POSTDIV2_SHIFT
|
|
#define PLL_REFDIV_SHIFT 0
|
|
#define PLL_REFDIV_MASK 0x3f << PLL_REFDIV_SHIFT
|
|
#define PLL_DSMPD_SHIFT 12
|
|
#define PLL_DSMPD_MASK 1 << PLL_DSMPD_SHIFT
|
|
#define PLL_FRAC_SHIFT 0
|
|
#define PLL_FRAC_MASK 0xffffff << PLL_FRAC_SHIFT
|
|
|
|
|
|
#define MIN_FOUTVCO_FREQ (800 * MHZ)
|
|
#define MAX_FOUTVCO_FREQ (2000 * MHZ)
|
|
#define MIN_FOUT_FREQ (24 * MHZ)
|
|
#define MAX_FOUT_FREQ (1600 * MHZ)
|
|
|
|
#define EXPONENT_OF_FRAC_PLL 24
|
|
#define RK_PLL_MODE_SLOW 0
|
|
#define RK_PLL_MODE_NORMAL 1
|
|
#define RK_PLL_MODE_DEEP 2
|
|
#define PLL_GET_PLLMODE(val, shift, mask) (((uint32_t)(val) & mask) >> shift)
|
|
|
|
#define PLL_GET_FBDIV(x) (((uint32_t)(x) & (PLL_FBDIV_MASK)) >> PLL_FBDIV_SHIFT)
|
|
#define PLL_GET_REFDIV(x) \
|
|
(((uint32_t)(x) & (PLL_REFDIV_MASK)) >> PLL_REFDIV_SHIFT)
|
|
#define PLL_GET_POSTDIV1(x) \
|
|
(((uint32_t)(x) & (PLL_POSTDIV1_MASK)) >> PLL_POSTDIV1_SHIFT)
|
|
#define PLL_GET_POSTDIV2(x) \
|
|
(((uint32_t)(x) & (PLL_POSTDIV2_MASK)) >> PLL_POSTDIV2_SHIFT)
|
|
#define PLL_GET_DSMPD(x) (((uint32_t)(x) & (PLL_DSMPD_MASK)) >> PLL_DSMPD_SHIFT)
|
|
#define PLL_GET_FRAC(x) (((uint32_t)(x) & (PLL_FRAC_MASK)) >> PLL_FRAC_SHIFT)
|
|
|
|
#define CRU_PLL_ROUND_UP_TO_KHZ(x) (HAL_DIV_ROUND_UP((x), KHZ) * KHZ)
|
|
|
|
#define CRU_READ(r) (*(volatile uint32_t *)(r))
|
|
#define CRU_WRITE(r, b, w, v) (*(volatile uint32_t *)(r) = ((w) << (16) | (v) << (b)))
|
|
|
|
/********************* Private Structure Definition **************************/
|
|
static struct PLL_CONFIG g_rockchipAutoTable;
|
|
__attribute__((weak)) const struct HAL_CRU_DEV g_cruDev;
|
|
|
|
/********************* Private Variable Definition ***************************/
|
|
/********************* Private Function Definition ***************************/
|
|
|
|
/** Calculate the greatest common divisor */
|
|
static uint32_t CRU_Gcd(uint32_t m, uint32_t n)
|
|
{
|
|
int t;
|
|
|
|
while (m > 0) {
|
|
if (n > m) {
|
|
t = m;
|
|
m = n;
|
|
n = t;
|
|
}
|
|
m -= n;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static int isBetterFreq(uint32_t now, uint32_t new, uint32_t best)
|
|
{
|
|
return (new <= now && new > best);
|
|
}
|
|
|
|
int HAL_CRU_FreqGetMux4(uint32_t freq, uint32_t freq0, uint32_t freq1,
|
|
uint32_t freq2, uint32_t freq3)
|
|
{
|
|
uint32_t best = 0;
|
|
|
|
if (isBetterFreq(freq, freq0, best)) {
|
|
best = freq0;
|
|
}
|
|
|
|
if (isBetterFreq(freq, freq1, best)) {
|
|
best = freq1;
|
|
}
|
|
|
|
if (isBetterFreq(freq, freq2, best)) {
|
|
best = freq2;
|
|
}
|
|
|
|
if (isBetterFreq(freq, freq3, best)) {
|
|
best = freq3;
|
|
}
|
|
|
|
if (best == freq0) {
|
|
return 0;
|
|
} else if (best == freq1) {
|
|
return 1;
|
|
} else if (best == freq2) {
|
|
return 2;
|
|
} else if (best == freq3) {
|
|
return 3;
|
|
}
|
|
|
|
return HAL_INVAL;
|
|
}
|
|
|
|
int HAL_CRU_FreqGetMux3(uint32_t freq, uint32_t freq0, uint32_t freq1, uint32_t freq2)
|
|
{
|
|
return HAL_CRU_FreqGetMux4(freq, freq0, freq1, freq2, freq2);
|
|
}
|
|
|
|
int HAL_CRU_FreqGetMux2(uint32_t freq, uint32_t freq0, uint32_t freq1)
|
|
{
|
|
return HAL_CRU_FreqGetMux4(freq, freq0, freq1, freq1, freq1);
|
|
}
|
|
|
|
uint32_t HAL_CRU_MuxGetFreq4(uint32_t muxName, uint32_t freq0, uint32_t freq1,
|
|
uint32_t freq2, uint32_t freq3)
|
|
{
|
|
switch (HAL_CRU_ClkGetMux(muxName)) {
|
|
case 0:
|
|
|
|
return freq0;
|
|
case 1:
|
|
|
|
return freq1;
|
|
case 2:
|
|
|
|
return freq2;
|
|
case 3:
|
|
|
|
return freq3;
|
|
}
|
|
|
|
return HAL_INVAL;
|
|
}
|
|
|
|
uint32_t HAL_CRU_MuxGetFreq3(uint32_t muxName, uint32_t freq0,
|
|
uint32_t freq1, uint32_t freq2)
|
|
{
|
|
return HAL_CRU_MuxGetFreq4(muxName, freq0, freq1, freq2, freq2);
|
|
}
|
|
|
|
uint32_t HAL_CRU_MuxGetFreq2(uint32_t muxName, uint32_t freq0, uint32_t freq1)
|
|
{
|
|
return HAL_CRU_MuxGetFreq4(muxName, freq0, freq1, freq1, freq1);
|
|
}
|
|
|
|
int HAL_CRU_RoundFreqGetMux4(uint32_t freq, uint32_t pFreq0,
|
|
uint32_t pFreq1, uint32_t pFreq2,
|
|
uint32_t pFreq3, uint32_t *pFreqOut)
|
|
{
|
|
uint32_t mux;
|
|
|
|
if (pFreq3 && (pFreq3 % freq == 0)) {
|
|
*pFreqOut = pFreq3;
|
|
mux = 3;
|
|
} else if (pFreq2 && (pFreq2 % freq == 0)) {
|
|
*pFreqOut = pFreq2;
|
|
mux = 2;
|
|
} else if (pFreq1 % freq == 0) {
|
|
*pFreqOut = pFreq1;
|
|
mux = 1;
|
|
} else {
|
|
*pFreqOut = pFreq0;
|
|
mux = 0;
|
|
}
|
|
|
|
return mux;
|
|
}
|
|
|
|
int HAL_CRU_RoundFreqGetMux3(uint32_t freq, uint32_t pFreq0,
|
|
uint32_t pFreq1, uint32_t pFreq2, uint32_t *pFreqOut)
|
|
{
|
|
return HAL_CRU_RoundFreqGetMux4(freq, pFreq0, pFreq1, pFreq2, 0, pFreqOut);
|
|
}
|
|
|
|
int HAL_CRU_RoundFreqGetMux2(uint32_t freq, uint32_t pFreq0, uint32_t pFreq1, uint32_t *pFreqOut)
|
|
{
|
|
return HAL_CRU_RoundFreqGetMux4(freq, pFreq0, pFreq1, 0, 0, pFreqOut);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @brief Rockchip pll clk set postdiv.
|
|
* @param foutHz: output freq
|
|
* @param *postDiv1: pll postDiv1
|
|
* @param *postDiv2: pll postDiv2
|
|
* @param *foutVco: pll vco
|
|
* @return HAL_Status.
|
|
* How to calculate the PLL:
|
|
* Formulas also embedded within the fractional PLL Verilog model:
|
|
* If DSMPD = 1 (DSM is disabled, "integer mode")
|
|
* FOUTVCO = FREF / REFDIV * FBDIV
|
|
* FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
|
|
* Where:
|
|
* FOUTVCO = fractional PLL non-divided output frequency
|
|
* FOUTPOSTDIV = fractional PLL divided output frequency
|
|
* (output of second post divider)
|
|
*/
|
|
static HAL_Status CRU_PllSetPostDiv(uint32_t foutHz, uint32_t *postDiv1,
|
|
uint32_t *postDiv2, uint32_t *foutVco)
|
|
{
|
|
uint32_t freq;
|
|
|
|
if (foutHz < MIN_FOUTVCO_FREQ) {
|
|
for (*postDiv1 = 1; *postDiv1 <= 7; (*postDiv1)++) {
|
|
for (*postDiv2 = 1; *postDiv2 <= 7; (*postDiv2)++) {
|
|
freq = foutHz * (*postDiv1) * (*postDiv2);
|
|
if (freq >= MIN_FOUTVCO_FREQ && freq <= MAX_FOUTVCO_FREQ) {
|
|
*foutVco = freq;
|
|
|
|
return HAL_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return HAL_ERROR;
|
|
} else {
|
|
*postDiv1 = 1;
|
|
*postDiv2 = 1;
|
|
|
|
return HAL_OK;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get pll parameter by auto.
|
|
* @param finHz: pll intput freq
|
|
* @param foutHz: pll output freq
|
|
* @return struct PLL_CONFIG.
|
|
* How to calculate the PLL:
|
|
* Formulas also embedded within the fractional PLL Verilog model:
|
|
* If DSMPD = 1 (DSM is disabled, "integer mode")
|
|
* FOUTVCO = FREF / REFDIV * FBDIV
|
|
* FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
|
|
* Where:
|
|
* FOUTVCO = fractional PLL non-divided output frequency
|
|
* FOUTPOSTDIV = fractional PLL divided output frequency
|
|
* (output of second post divider)
|
|
* FREF = fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
|
|
* REFDIV = fractional PLL input reference clock divider
|
|
* FBDIV = Integer value programmed into feedback divide
|
|
*/
|
|
static const struct PLL_CONFIG *CRU_PllSetByAuto(uint32_t finHz,
|
|
uint32_t foutHz)
|
|
{
|
|
struct PLL_CONFIG *rateTable = &g_rockchipAutoTable;
|
|
uint32_t foutVco = foutHz;
|
|
uint64_t fin64, frac64;
|
|
uint32_t postDiv1, postDiv2;
|
|
uint32_t clkGcd = 0;
|
|
HAL_Status error;
|
|
|
|
if (finHz == 0 || foutHz == 0 || foutHz == finHz) {
|
|
return NULL;
|
|
}
|
|
|
|
error = CRU_PllSetPostDiv(foutHz, &postDiv1, &postDiv2, &foutVco);
|
|
if (error) {
|
|
return NULL;
|
|
}
|
|
rateTable->postDiv1 = postDiv1;
|
|
rateTable->postDiv2 = postDiv2;
|
|
rateTable->dsmpd = 1;
|
|
|
|
if (finHz / MHZ * MHZ == finHz && foutHz / MHZ * MHZ == foutHz) {
|
|
finHz /= MHZ;
|
|
foutVco /= MHZ;
|
|
clkGcd = CRU_Gcd(finHz, foutVco);
|
|
rateTable->refDiv = finHz / clkGcd;
|
|
rateTable->fbDiv = foutVco / clkGcd;
|
|
|
|
rateTable->frac = 0;
|
|
} else if (finHz / MHZ * MHZ != finHz) {
|
|
clkGcd = foutHz / finHz;
|
|
rateTable->fbDiv = clkGcd;
|
|
rateTable->refDiv = 1;
|
|
rateTable->postDiv1 = 1;
|
|
rateTable->postDiv2 = 1;
|
|
|
|
fin64 = foutHz * rateTable->refDiv;
|
|
fin64 = HAL_DivU64(fin64 << EXPONENT_OF_FRAC_PLL, finHz);
|
|
frac64 = rateTable->fbDiv;
|
|
frac64 = rateTable->fbDiv << EXPONENT_OF_FRAC_PLL;
|
|
frac64 = fin64 - frac64;
|
|
rateTable->frac = frac64;
|
|
if (rateTable->frac > 0) {
|
|
rateTable->dsmpd = 0;
|
|
}
|
|
} else {
|
|
clkGcd = CRU_Gcd(finHz / MHZ, foutVco / MHZ);
|
|
rateTable->refDiv = finHz / MHZ / clkGcd;
|
|
rateTable->fbDiv = foutVco / MHZ / clkGcd;
|
|
rateTable->frac = 0;
|
|
|
|
frac64 = (foutVco % MHZ);
|
|
fin64 = finHz;
|
|
frac64 = frac64 * rateTable->refDiv;
|
|
frac64 = HAL_DivU64(frac64 << EXPONENT_OF_FRAC_PLL, fin64);
|
|
rateTable->frac = frac64;
|
|
if (rateTable->frac > 0) {
|
|
rateTable->dsmpd = 0;
|
|
}
|
|
}
|
|
|
|
return rateTable;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Get pll parameter by rateTable.
|
|
* @param *pSetup: struct PLL_SETUP struct, Contains PLL register parameters
|
|
* @param rate: pll target rate.
|
|
* @return struct PLL_CONFIG.
|
|
* How to calculate the PLL:
|
|
* Look up the rateTable to get the PLL config parameter
|
|
*/
|
|
static const struct PLL_CONFIG *CRU_PllGetSettings(struct PLL_SETUP *pSetup,
|
|
uint32_t rate)
|
|
{
|
|
const struct PLL_CONFIG *rateTable = pSetup->rateTable;
|
|
|
|
if (rateTable == NULL) {
|
|
return CRU_PllSetByAuto(PLL_INPUT_OSC_RATE, rate);
|
|
}
|
|
|
|
while (rateTable->rate) {
|
|
if (rateTable->rate == rate) {
|
|
break;
|
|
}
|
|
rateTable++;
|
|
}
|
|
if (rateTable->rate != rate) {
|
|
return CRU_PllSetByAuto(PLL_INPUT_OSC_RATE, rate);
|
|
} else {
|
|
return rateTable;
|
|
}
|
|
}
|
|
/** @} */
|
|
/********************* Public Function Definition ****************************/
|
|
|
|
/** @defgroup CRU_Exported_Functions_Group5 Other Functions
|
|
* @attention these APIs allow direct use in the HAL layer.
|
|
* @{
|
|
*/
|
|
|
|
|
|
/*
|
|
* Formulas also embedded within the fractional PLL Verilog model:
|
|
* If DSMPD = 1 (DSM is disabled, "integer mode")
|
|
* FOUTVCO = FREF / REFDIV * FBDIV
|
|
* FOUT = FOUTVCO / POSTDIV1 / POSTDIV2
|
|
* If DSMPD = 0 (DSM is enabled, "fractional mode")
|
|
* FOUTVCO = (FREF / REFDIV) * (FBDIV + FRAC / (2^24))
|
|
* FOUTPOSTDIV = FOUTVCO / (POSTDIV1*POSTDIV2)
|
|
* FOUT = FOUTVCO / POSTDIV1 / POSTDIV2
|
|
*/
|
|
uint32_t HAL_CRU_GetPllFreq(struct PLL_SETUP *pSetup)
|
|
{
|
|
uint32_t refDiv, fbDiv, postdDv1, postDiv2, frac, dsmpd;
|
|
uint32_t mode = 0, rate = PLL_INPUT_OSC_RATE;
|
|
|
|
mode = PLL_GET_PLLMODE(READ_REG(*(pSetup->modeOffset)), pSetup->modeShift,
|
|
pSetup->modeMask);
|
|
|
|
switch (mode) {
|
|
case RK_PLL_MODE_SLOW:
|
|
rate = PLL_INPUT_OSC_RATE;
|
|
break;
|
|
case RK_PLL_MODE_NORMAL:
|
|
postdDv1 = PLL_GET_POSTDIV1(READ_REG(*(pSetup->conOffset0)));
|
|
fbDiv = PLL_GET_FBDIV(READ_REG(*(pSetup->conOffset0)));
|
|
postDiv2 = PLL_GET_POSTDIV2(READ_REG(*(pSetup->conOffset1)));
|
|
refDiv = PLL_GET_REFDIV(READ_REG(*(pSetup->conOffset1)));
|
|
dsmpd = PLL_GET_DSMPD(READ_REG(*(pSetup->conOffset1)));
|
|
frac = PLL_GET_FRAC(READ_REG(*(pSetup->conOffset2)));
|
|
rate = (rate / refDiv) * fbDiv;
|
|
if (dsmpd == 0) {
|
|
uint64_t fracRate = PLL_INPUT_OSC_RATE;
|
|
|
|
fracRate *= frac;
|
|
fracRate = fracRate >> EXPONENT_OF_FRAC_PLL;
|
|
fracRate = fracRate / refDiv;
|
|
rate += fracRate;
|
|
}
|
|
rate = rate / (postdDv1 * postDiv2);
|
|
rate = CRU_PLL_ROUND_UP_TO_KHZ(rate);
|
|
break;
|
|
case RK_PLL_MODE_DEEP:
|
|
default:
|
|
rate = 32768;
|
|
break;
|
|
}
|
|
|
|
return rate;
|
|
}
|
|
|
|
/*
|
|
* Force PLL into slow mode
|
|
* Pll Power down
|
|
* Pll Config fbDiv, refDiv, postdDv1, postDiv2, dsmpd, frac
|
|
* Pll Power up
|
|
* Waiting for pll lock
|
|
* Force PLL into normal mode
|
|
*/
|
|
HAL_Status HAL_CRU_SetPllFreq(struct PLL_SETUP *pSetup, uint32_t rate)
|
|
{
|
|
const struct PLL_CONFIG *pConfig;
|
|
int delay = 2400;
|
|
|
|
if (rate == HAL_CRU_GetPllFreq(pSetup)) {
|
|
return HAL_OK;
|
|
} else if (rate < MIN_FOUT_FREQ) {
|
|
return HAL_INVAL;
|
|
} else if (rate > MAX_FOUT_FREQ) {
|
|
return HAL_INVAL;
|
|
}
|
|
|
|
pConfig = CRU_PllGetSettings(pSetup, rate);
|
|
if (!pConfig) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
/* Force PLL into slow mode to ensure output stable clock */
|
|
WRITE_REG_MASK_WE(*(pSetup->modeOffset), pSetup->modeMask, RK_PLL_MODE_SLOW << pSetup->modeShift);
|
|
|
|
/* Pll Power down */
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset1), PWRDOWN_MASK, 1 << PWRDOWN_SHIFT);
|
|
|
|
/* Pll Config */
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset1), PLL_POSTDIV2_MASK, pConfig->postDiv2 << PLL_POSTDIV2_SHIFT);
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset1), PLL_REFDIV_MASK, pConfig->refDiv << PLL_REFDIV_SHIFT);
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset0), PLL_POSTDIV1_MASK, pConfig->postDiv1 << PLL_POSTDIV1_SHIFT);
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset0), PLL_FBDIV_MASK, pConfig->fbDiv << PLL_FBDIV_SHIFT);
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset1), PLL_DSMPD_MASK, pConfig->dsmpd << PLL_DSMPD_SHIFT);
|
|
|
|
if (pConfig->frac) {
|
|
WRITE_REG(*(pSetup->conOffset2), (READ_REG(*(pSetup->conOffset2)) & 0xff000000) | pConfig->frac);
|
|
}
|
|
|
|
/* Pll Power up */
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset1), PWRDOWN_MASK, 0 << PWRDOWN_SHIFT);
|
|
|
|
/* Waiting for pll lock */
|
|
while (delay > 0) {
|
|
if (pSetup->stat0) {
|
|
if (READ_REG(*(pSetup->stat0)) & (1 << pSetup->lockShift)) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (READ_REG(*(pSetup->conOffset1)) & (1 << pSetup->lockShift)) {
|
|
break;
|
|
}
|
|
}
|
|
HAL_CPUDelayUs(1000);
|
|
delay--;
|
|
}
|
|
if (delay == 0) {
|
|
return HAL_TIMEOUT;
|
|
}
|
|
|
|
/* Force PLL into normal mode */
|
|
WRITE_REG_MASK_WE(*(pSetup->modeOffset), pSetup->modeMask, RK_PLL_MODE_NORMAL << pSetup->modeShift);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_SetPllPowerUp(struct PLL_SETUP *pSetup)
|
|
{
|
|
int delay = 2400;
|
|
|
|
/* Pll Power up */
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset1), PWRDOWN_MASK, 0 << PWRDOWN_SHIFT);
|
|
|
|
/* Waiting for pll lock */
|
|
while (delay > 0) {
|
|
if (pSetup->stat0) {
|
|
if (READ_REG(*(pSetup->stat0)) & (1 << pSetup->lockShift)) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (READ_REG(*(pSetup->conOffset1)) & (1 << pSetup->lockShift)) {
|
|
break;
|
|
}
|
|
}
|
|
HAL_CPUDelayUs(1000);
|
|
delay--;
|
|
}
|
|
if (delay == 0) {
|
|
return HAL_TIMEOUT;
|
|
}
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_SetPllPowerDown(struct PLL_SETUP *pSetup)
|
|
{
|
|
/* Pll Power down */
|
|
WRITE_REG_MASK_WE(*(pSetup->conOffset1), PWRDOWN_MASK, 1 << PWRDOWN_SHIFT);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
|
|
#ifdef CRU_CLK_USE_CON_BANK
|
|
static const struct HAL_CRU_DEV *CRU_GetInfo(void)
|
|
{
|
|
return &g_cruDev;
|
|
}
|
|
|
|
HAL_Check HAL_CRU_ClkIsEnabled(uint32_t clk)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
|
uint32_t reg;
|
|
HAL_Check ret;
|
|
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
|
ret = (HAL_Check)(!((CRU_READ(reg) & (1 << shift)) >> shift));
|
|
|
|
return ret;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkEnable(uint32_t clk)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
|
uint32_t reg;
|
|
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
|
CRU_WRITE(reg, shift, 1U << shift, 0U);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkDisable(uint32_t clk)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
|
uint32_t reg;
|
|
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
|
CRU_WRITE(reg, shift, 1U << shift, 1U);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkDisableUnused(uint32_t bank, uint32_t index, uint32_t val)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t reg;
|
|
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].gateOffset + index * 4;
|
|
CRU_WRITE(reg, 0, 0, val);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Check HAL_CRU_ClkIsReset(uint32_t clk)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
|
uint32_t reg;
|
|
HAL_Check ret;
|
|
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
|
ret = (HAL_Check)((CRU_READ(reg) & (1 << shift)) >> shift);
|
|
|
|
return ret;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetAssert(uint32_t clk)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_RESET_GET_BITS_SHIFT(clk);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
|
uint32_t reg;
|
|
|
|
HAL_ASSERT(shift < 16);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
|
CRU_WRITE(reg, shift, 1U << shift, 1U);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetDeassert(uint32_t clk)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_RESET_GET_BITS_SHIFT(clk);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clk);
|
|
uint32_t reg;
|
|
|
|
HAL_ASSERT(shift < 16);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
|
CRU_WRITE(reg, shift, 1U << shift, 0U);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetSyncAssert(int numClks, uint32_t *clks)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clks[0]);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clks[0]);
|
|
uint32_t val = 0;
|
|
uint32_t reg;
|
|
int i;
|
|
|
|
for (i = 0; i < numClks; i++) {
|
|
val |= HAL_BIT(CLK_RESET_GET_BITS_SHIFT(clks[i]));
|
|
if (index != CLK_RESET_GET_REG_OFFSET(clks[i])) {
|
|
return HAL_ERROR;
|
|
}
|
|
}
|
|
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
|
CRU_WRITE(reg, 0, val, val);
|
|
HAL_DBG("%s: index: 0x%lx, val: 0x%lx\n", __func__, index, val);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetSyncDeassert(int numClks, uint32_t *clks)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clks[0]);
|
|
uint32_t bank = CLK_GATE_GET_REG_BANK(clks[0]);
|
|
uint32_t val = 0;
|
|
uint32_t reg;
|
|
int i;
|
|
|
|
for (i = 0; i < numClks; i++) {
|
|
val |= HAL_BIT(CLK_RESET_GET_BITS_SHIFT(clks[i]));
|
|
if (index != CLK_RESET_GET_REG_OFFSET(clks[i])) {
|
|
return HAL_ERROR;
|
|
}
|
|
}
|
|
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].softOffset + index * 4;
|
|
CRU_WRITE(reg, 0, val, 0);
|
|
HAL_DBG("%s: index: 0x%lx, val: 0x%lx\n", __func__, index, val);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkSetDiv(uint32_t divName, uint32_t divValue)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t shift, mask, index;
|
|
uint32_t reg, bank;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(divName);
|
|
shift = CLK_DIV_GET_BITS_SHIFT(divName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_DIV_GET_MASK(divName);
|
|
if (divValue > mask) {
|
|
divValue = mask;
|
|
}
|
|
|
|
bank = CLK_DIV_GET_BANK(divName);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
|
CRU_WRITE(reg, shift, mask, (divValue - 1U));
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
uint32_t HAL_CRU_ClkGetDiv(uint32_t divName)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t shift, mask, index, divValue;
|
|
uint32_t reg, bank;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(divName);
|
|
shift = CLK_DIV_GET_BITS_SHIFT(divName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_DIV_GET_MASK(divName);
|
|
bank = CLK_DIV_GET_BANK(divName);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
|
divValue = ((CRU_READ(reg) & mask) >> shift) + 1;
|
|
|
|
return divValue;
|
|
}
|
|
|
|
HAL_SECTION_SRAM_CODE
|
|
HAL_Status HAL_CRU_ClkSetMux(uint32_t muxName, uint32_t muxValue)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t shift, mask, index;
|
|
uint32_t reg, bank;
|
|
|
|
index = CLK_MUX_GET_REG_OFFSET(muxName);
|
|
shift = CLK_MUX_GET_BITS_SHIFT(muxName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_MUX_GET_MASK(muxName);
|
|
bank = CLK_MUX_GET_BANK(muxName);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
|
CRU_WRITE(reg, shift, mask, muxValue);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_SECTION_SRAM_CODE
|
|
uint32_t HAL_CRU_ClkGetMux(uint32_t muxName)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t shift, mask, index, muxValue;
|
|
uint32_t reg, bank;
|
|
|
|
index = CLK_MUX_GET_REG_OFFSET(muxName);
|
|
shift = CLK_MUX_GET_BITS_SHIFT(muxName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_MUX_GET_MASK(muxName);
|
|
bank = CLK_MUX_GET_BANK(muxName);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
|
muxValue = ((CRU_READ(reg) & mask) >> shift);
|
|
|
|
return muxValue;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkSetFracDiv(uint32_t fracDivName,
|
|
uint32_t numerator,
|
|
uint32_t denominator)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t reg, bank;
|
|
uint32_t index;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(fracDivName);
|
|
bank = CLK_DIV_GET_BANK(fracDivName);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
|
CRU_WRITE(reg, 0, 0, ((numerator << 16) | denominator));
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkGetFracDiv(uint32_t fracDivName,
|
|
uint32_t *numerator,
|
|
uint32_t *denominator)
|
|
{
|
|
const struct HAL_CRU_DEV *ctrl = CRU_GetInfo();
|
|
uint32_t reg, bank;
|
|
uint32_t index;
|
|
uint32_t val;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(fracDivName);
|
|
bank = CLK_DIV_GET_BANK(fracDivName);
|
|
reg = ctrl->banks[bank].cruBase + ctrl->banks[bank].selOffset + index * 4;
|
|
val = CRU_READ(reg);
|
|
|
|
*numerator = (val & 0xffff0000) >> 16;
|
|
*denominator = (val & 0x0000ffff);
|
|
|
|
return HAL_OK;
|
|
}
|
|
#else /* CRU_CLK_USE_CON_BANK */
|
|
|
|
HAL_Check HAL_CRU_ClkIsEnabled(uint32_t clk)
|
|
{
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
HAL_Check ret;
|
|
|
|
#ifdef CRU_GATE_CON_CNT
|
|
if (index < CRU_GATE_CON_CNT) {
|
|
ret = (HAL_Check)(!((CRU->CRU_CLKGATE_CON[index] & (1 << shift)) >> shift));
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
ret = (HAL_Check)(!((PMUCRU->CRU_CLKGATE_CON[index - CRU_GATE_CON_CNT] & (1 << shift)) >> shift));
|
|
#else
|
|
ret = (HAL_Check)(!((CRU->PMU_CLKGATE_CON[index - CRU_GATE_CON_CNT] & (1 << shift)) >> shift));
|
|
#endif
|
|
}
|
|
#else
|
|
ret = (HAL_Check)(!((CRU->CRU_CLKGATE_CON[index] & (1 << shift)) >> shift));
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkEnable(uint32_t clk)
|
|
{
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
|
|
#ifdef CRU_GATE_CON_CNT
|
|
if (index < CRU_GATE_CON_CNT) {
|
|
CRU->CRU_CLKGATE_CON[index] = VAL_MASK_WE(1U << shift, 0U << shift);
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
PMUCRU->CRU_CLKGATE_CON[index - CRU_GATE_CON_CNT] = VAL_MASK_WE(1U << shift, 0U << shift);
|
|
#else
|
|
CRU->PMU_CLKGATE_CON[index - CRU_GATE_CON_CNT] = VAL_MASK_WE(1U << shift, 0U << shift);
|
|
#endif
|
|
}
|
|
#else
|
|
CRU->CRU_CLKGATE_CON[index] = VAL_MASK_WE(1U << shift, 0U << shift);
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkDisable(uint32_t clk)
|
|
{
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
|
|
#ifdef CRU_GATE_CON_CNT
|
|
if (index < CRU_GATE_CON_CNT) {
|
|
CRU->CRU_CLKGATE_CON[index] = VAL_MASK_WE(1U << shift, 1U << shift);
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
PMUCRU->CRU_CLKGATE_CON[index - CRU_GATE_CON_CNT] = VAL_MASK_WE(1U << shift, 1U << shift);
|
|
#else
|
|
CRU->PMU_CLKGATE_CON[index - CRU_GATE_CON_CNT] = VAL_MASK_WE(1U << shift, 1U << shift);
|
|
#endif
|
|
}
|
|
#else
|
|
CRU->CRU_CLKGATE_CON[index] = VAL_MASK_WE(1U << shift, 1U << shift);
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkDisableUnused(uint32_t bank, uint32_t index, uint32_t val)
|
|
{
|
|
#ifdef CRU_GATE_CON_CNT
|
|
if (index < CRU_GATE_CON_CNT) {
|
|
CRU->CRU_CLKGATE_CON[index] = val;
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
PMUCRU->CRU_CLKGATE_CON[index - CRU_GATE_CON_CNT] = val;
|
|
#else
|
|
CRU->PMU_CLKGATE_CON[index - CRU_GATE_CON_CNT] = val;
|
|
#endif
|
|
}
|
|
#else
|
|
CRU->CRU_CLKGATE_CON[index] = val;
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Check HAL_CRU_ClkIsReset(uint32_t clk)
|
|
{
|
|
uint32_t index = CLK_GATE_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_GATE_GET_BITS_SHIFT(clk);
|
|
HAL_Check ret;
|
|
|
|
#ifdef CRU_SRST_CON_CNT
|
|
if (index < CRU_SRST_CON_CNT) {
|
|
ret = (HAL_Check)((CRU->CRU_CLKGATE_CON[index] & (1 << shift)) >> shift);
|
|
} else {
|
|
ret = (HAL_Check)((PMUCRU->CRU_CLKGATE_CON[index - CRU_SRST_CON_CNT] & (1 << shift)) >> shift);
|
|
}
|
|
#else
|
|
ret = (HAL_Check)((CRU->CRU_CLKGATE_CON[index] & (1 << shift)) >> shift);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetAssert(uint32_t clk)
|
|
{
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_RESET_GET_BITS_SHIFT(clk);
|
|
|
|
HAL_ASSERT(shift < 16);
|
|
#ifdef CRU_SRST_CON_CNT
|
|
if (index < CRU_SRST_CON_CNT) {
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(1U << shift, 1U << shift);
|
|
} else {
|
|
PMUCRU->CRU_SOFTRST_CON[index - CRU_SRST_CON_CNT] = VAL_MASK_WE(1U << shift, 1U << shift);
|
|
}
|
|
#else
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(1U << shift, 1U << shift);
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetDeassert(uint32_t clk)
|
|
{
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clk);
|
|
uint32_t shift = CLK_RESET_GET_BITS_SHIFT(clk);
|
|
|
|
HAL_ASSERT(shift < 16);
|
|
#ifdef CRU_SRST_CON_CNT
|
|
if (index < CRU_SRST_CON_CNT) {
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(1U << shift, 0U << shift);
|
|
} else {
|
|
PMUCRU->CRU_SOFTRST_CON[index - CRU_SRST_CON_CNT] = VAL_MASK_WE(1U << shift, 0U << shift);
|
|
}
|
|
#else
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(1U << shift, 0U << shift);
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetSyncAssert(int numClks, uint32_t *clks)
|
|
{
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clks[0]);
|
|
uint32_t val = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < numClks; i++) {
|
|
val |= HAL_BIT(CLK_RESET_GET_BITS_SHIFT(clks[i]));
|
|
if (index != CLK_RESET_GET_REG_OFFSET(clks[i])) {
|
|
return HAL_ERROR;
|
|
}
|
|
}
|
|
|
|
#ifdef CRU_SRST_CON_CNT
|
|
if (index < CRU_SRST_CON_CNT) {
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(val, val);
|
|
} else {
|
|
PMUCRU->CRU_SOFTRST_CON[index - CRU_SRST_CON_CNT] = VAL_MASK_WE(val, val);
|
|
}
|
|
#else
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(val, val);
|
|
#endif
|
|
HAL_DBG("%s: index: 0x%lx, val: 0x%lx\n", __func__, index, val);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkResetSyncDeassert(int numClks, uint32_t *clks)
|
|
{
|
|
uint32_t index = CLK_RESET_GET_REG_OFFSET(clks[0]);
|
|
uint32_t val = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < numClks; i++) {
|
|
val |= HAL_BIT(CLK_RESET_GET_BITS_SHIFT(clks[i]));
|
|
if (index != CLK_RESET_GET_REG_OFFSET(clks[i])) {
|
|
return HAL_ERROR;
|
|
}
|
|
}
|
|
|
|
#ifdef CRU_SRST_CON_CNT
|
|
if (index < CRU_SRST_CON_CNT) {
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(val, 0);
|
|
} else {
|
|
PMUCRU->CRU_SOFTRST_CON[index - CRU_SRST_CON_CNT] = VAL_MASK_WE(val, 0);
|
|
}
|
|
#else
|
|
CRU->CRU_SOFTRST_CON[index] = VAL_MASK_WE(val, 0);
|
|
#endif
|
|
HAL_DBG("%s: index: 0x%lx, val: 0x%lx\n", __func__, index, val);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkSetDiv(uint32_t divName, uint32_t divValue)
|
|
{
|
|
uint32_t shift, mask, index;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(divName);
|
|
shift = CLK_DIV_GET_BITS_SHIFT(divName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_DIV_GET_MASK(divName);
|
|
if (divValue > mask) {
|
|
divValue = mask;
|
|
}
|
|
|
|
#ifdef CRU_CLK_DIV_CON_CNT
|
|
if (index < CRU_CLK_DIV_CON_CNT) {
|
|
CRU->CRU_CLKSEL_CON[index] = VAL_MASK_WE(mask, (divValue - 1U) << shift);
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
PMUCRU->CRU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT] = VAL_MASK_WE(mask, (divValue - 1U) << shift);
|
|
#else
|
|
CRU->PMU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT] = VAL_MASK_WE(mask, (divValue - 1U) << shift);
|
|
#endif
|
|
}
|
|
#else
|
|
CRU->CRU_CLKSEL_CON[index] = VAL_MASK_WE(mask, (divValue - 1U) << shift);
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
uint32_t HAL_CRU_ClkGetDiv(uint32_t divName)
|
|
{
|
|
uint32_t shift, mask, index, divValue;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(divName);
|
|
shift = CLK_DIV_GET_BITS_SHIFT(divName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_DIV_GET_MASK(divName);
|
|
|
|
#ifdef CRU_CLK_DIV_CON_CNT
|
|
if (index < CRU_CLK_DIV_CON_CNT) {
|
|
divValue = ((((CRU->CRU_CLKSEL_CON[index]) & mask) >> shift) + 1);
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
divValue = ((((PMUCRU->CRU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT]) & mask) >> shift) + 1);
|
|
#else
|
|
divValue = ((((CRU->PMU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT]) & mask) >> shift) + 1);
|
|
#endif
|
|
}
|
|
#else
|
|
divValue = ((((CRU->CRU_CLKSEL_CON[index]) & mask) >> shift) + 1);
|
|
#endif
|
|
|
|
return divValue;
|
|
}
|
|
|
|
HAL_SECTION_SRAM_CODE
|
|
HAL_Status HAL_CRU_ClkSetMux(uint32_t muxName, uint32_t muxValue)
|
|
{
|
|
uint32_t shift, mask, index;
|
|
|
|
index = CLK_MUX_GET_REG_OFFSET(muxName);
|
|
shift = CLK_MUX_GET_BITS_SHIFT(muxName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_MUX_GET_MASK(muxName);
|
|
|
|
#ifdef CRU_CLK_SEL_CON_CNT
|
|
if (index < CRU_CLK_DIV_CON_CNT) {
|
|
CRU->CRU_CLKSEL_CON[index] = VAL_MASK_WE(mask, muxValue << shift);
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
PMUCRU->CRU_CLKSEL_CON[index - CRU_CLK_SEL_CON_CNT] = VAL_MASK_WE(mask, muxValue << shift);
|
|
#else
|
|
CRU->PMU_CLKSEL_CON[index - CRU_CLK_SEL_CON_CNT] = VAL_MASK_WE(mask, muxValue << shift);
|
|
#endif
|
|
}
|
|
#else
|
|
CRU->CRU_CLKSEL_CON[index] = VAL_MASK_WE(mask, muxValue << shift);
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_SECTION_SRAM_CODE
|
|
uint32_t HAL_CRU_ClkGetMux(uint32_t muxName)
|
|
{
|
|
uint32_t shift, mask, index, muxValue;
|
|
|
|
index = CLK_MUX_GET_REG_OFFSET(muxName);
|
|
shift = CLK_MUX_GET_BITS_SHIFT(muxName);
|
|
HAL_ASSERT(shift < 16);
|
|
mask = CLK_MUX_GET_MASK(muxName);
|
|
|
|
#ifdef CRU_CLK_SEL_CON_CNT
|
|
if (index < CRU_CLK_SEL_CON_CNT) {
|
|
muxValue = ((CRU->CRU_CLKSEL_CON[index] & mask) >> shift);
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
muxValue = ((PMUCRU->CRU_CLKSEL_CON[index - CRU_CLK_SEL_CON_CNT] & mask) >> shift);
|
|
#else
|
|
muxValue = ((CRU->PMU_CLKSEL_CON[index - CRU_CLK_SEL_CON_CNT] & mask) >> shift);
|
|
#endif
|
|
}
|
|
#else
|
|
muxValue = ((CRU->CRU_CLKSEL_CON[index] & mask) >> shift);
|
|
#endif
|
|
|
|
return muxValue;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkSetFracDiv(uint32_t fracDivName,
|
|
uint32_t numerator,
|
|
uint32_t denominator)
|
|
{
|
|
uint32_t index;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(fracDivName);
|
|
#ifdef CRU_CLK_DIV_CON_CNT
|
|
if (index < CRU_CLK_DIV_CON_CNT) {
|
|
CRU->CRU_CLKSEL_CON[index] = (numerator << 16) | denominator;
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
PMUCRU->CRU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT] = (numerator << 16) | denominator;
|
|
#else
|
|
CRU->PMU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT] = (numerator << 16) | denominator;
|
|
#endif
|
|
}
|
|
#else
|
|
CRU->CRU_CLKSEL_CON[index] = (numerator << 16) | denominator;
|
|
#endif
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkGetFracDiv(uint32_t fracDivName,
|
|
uint32_t *numerator,
|
|
uint32_t *denominator)
|
|
{
|
|
uint32_t index;
|
|
uint32_t val;
|
|
|
|
index = CLK_DIV_GET_REG_OFFSET(fracDivName);
|
|
#ifdef CRU_CLK_DIV_CON_CNT
|
|
if (index < CRU_CLK_DIV_CON_CNT) {
|
|
val = CRU->CRU_CLKSEL_CON[index];
|
|
} else {
|
|
#ifdef PMUCRU_BASE
|
|
val = PMUCRU->CRU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT];
|
|
#else
|
|
val = CRU->CRU_CLKSEL_CON[index - CRU_CLK_DIV_CON_CNT];
|
|
#endif
|
|
}
|
|
#else
|
|
val = CRU->CRU_CLKSEL_CON[index];
|
|
#endif
|
|
|
|
*numerator = (val & 0xffff0000) >> 16;
|
|
*denominator = (val & 0x0000ffff);
|
|
|
|
return HAL_OK;
|
|
}
|
|
#endif /* CRU_CLK_USE_CON_BANK */
|
|
|
|
HAL_Status HAL_CRU_FracdivGetConfig(uint32_t rateOut, uint32_t rate,
|
|
uint32_t *numerator,
|
|
uint32_t *denominator)
|
|
{
|
|
uint32_t gcdVal;
|
|
|
|
gcdVal = CRU_Gcd(rate, rateOut);
|
|
if (!gcdVal) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
*numerator = rateOut / gcdVal;
|
|
*denominator = rate / gcdVal;
|
|
|
|
if (*numerator < 4) {
|
|
*numerator *= 4;
|
|
*denominator *= 4;
|
|
}
|
|
if (*numerator > 0xffff || *denominator > 0xffff) {
|
|
return HAL_INVAL;
|
|
}
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_ClkNp5BestDiv(eCLOCK_Name clockName, uint32_t rate, uint32_t pRate, uint32_t *bestdiv)
|
|
{
|
|
uint32_t div = CLK_GET_DIV(clockName);
|
|
uint32_t maxDiv = CLK_DIV_GET_MASK(div);
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < maxDiv; i++) {
|
|
if (((pRate * 2) == (rate * (i * 2 + 3)))) {
|
|
*bestdiv = i;
|
|
|
|
return HAL_OK;
|
|
}
|
|
}
|
|
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
__attribute__((weak)) HAL_Status HAL_CRU_VopDclkEnable(uint32_t gateId)
|
|
{
|
|
HAL_CRU_ClkEnable(gateId);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
__attribute__((weak)) HAL_Status HAL_CRU_VopDclkDisable(uint32_t gateId)
|
|
{
|
|
HAL_CRU_ClkDisable(gateId);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
HAL_Status HAL_CRU_SetGlbSrst(eCRU_GlbSrstType type)
|
|
{
|
|
#ifdef CRU_GLB_SRST_FST_VALUE_OFFSET
|
|
if (type == GLB_SRST_FST) {
|
|
CRU->GLB_SRST_FST_VALUE = GLB_SRST_FST;
|
|
}
|
|
#endif
|
|
#ifdef CRU_GLB_SRST_SND_VALUE_OFFSET
|
|
if (type == GLB_SRST_SND) {
|
|
CRU->GLB_SRST_SND_VALUE = GLB_SRST_SND;
|
|
}
|
|
#endif
|
|
|
|
return HAL_INVAL;
|
|
}
|
|
|
|
/** @} */
|
|
|
|
/** @} */
|
|
|
|
/** @} */
|
|
|
|
|