rt-thread/bsp/allwinner/libraries/sunxi-hal/hal/source/ccmu/sunxi/clk.c

831 lines
22 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
*
* Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
*the the People's Republic of China and other countries.
* All Allwinner Technology Co.,Ltd. trademarks are used with permission.
*
* DISCLAIMER
* THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
* IF YOU NEED TO INTEGRATE THIRD PARTYS TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
* IN ALLWINNERSSDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
* ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
* ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
* COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
* YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTYS TECHNOLOGY.
*
*
* THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
* PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
* THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
* OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* IN NO EVENT SHALL ALLWINNER 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 "sunxi_hal_common.h"
#include "clk.h"
#include "clk_periph.h"
#include "clk_factors.h"
#include <stdio.h>
#include <string.h>
extern clk_core_pt sunxi_clk_fixed_src_arry[];
extern clk_fixed_factor_pt sunxi_clk_fixed_factor_arry[];
extern clk_factor_pt sunxi_clk_factor_arry[];
extern clk_periph_pt sunxi_clk_periph_arry[];
extern clk_base_pt sunxi_periph_clk_init_arry[];
extern hal_clk_status_t (*sunxi_clk_factor_init[])(void);
static hal_clk_status_t sunxi_clk_set_parent(hal_clk_id_t clk, hal_clk_id_t parent_clk);
static hal_clk_status_t sunxi_clk_get_parent(hal_clk_id_t clk, hal_clk_id_t *parent_clk);
static hal_clk_status_t sunxi_clk_disable(hal_clk_id_t clk);
static hal_clk_status_t sunxi_clk_enabled(hal_clk_id_t clk);
static hal_clk_status_t sunxi_clk_is_enabled(hal_clk_id_t clk);
static hal_clk_status_t sunxi_clk_round_rate(hal_clk_id_t clk, u32 rate, u32 *prate);
static hal_clk_status_t sunxi_clk_recalc_rate(hal_clk_id_t clk, u32 *rate);
static hal_clk_status_t sunxi_clk_get_rate(hal_clk_id_t clk, u32 *rate);
static hal_clk_status_t sunxi_clk_set_rate(hal_clk_id_t clk, u32 rate);
static inline uint64_t read_cntpct(void)
{
u64 val;
asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r"(val));
return val;
}
static inline uint32_t read_cntfrq(void)
{
u32 frq;
asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(frq));
return frq;
}
void clk_udelay(u32 us)
{
u64 start, target;
start = read_cntpct();
target = read_cntfrq() / 1000000ULL * us;
while (read_cntpct() - start <= target) ;
}
clk_core_pt clk_get_core(hal_clk_id_t clk)
{
clk_core_pt pclk = NULL;
u32 i;
switch (HAL_CLK_GET_TYPE(clk))
{
/* */
case HAL_CLK_PERIPH:
for (i = 0; sunxi_clk_periph_arry[i] != NULL; i++)
{
pclk = (clk_core_pt)sunxi_clk_periph_arry[i];
if (pclk->clk == clk)
{
break;
}
}
break;
/* */
case HAL_CLK_FACTOR:
for (i = 0; sunxi_clk_factor_arry[i] != NULL; i++)
{
pclk = (clk_core_pt)sunxi_clk_factor_arry[i];
if (pclk->clk == clk)
{
break;
}
}
break;
/* */
case HAL_CLK_FIXED_SRC:
for (i = 0; sunxi_clk_fixed_src_arry[i] != NULL; i++)
{
pclk = (clk_core_pt)sunxi_clk_fixed_src_arry[i];
if (pclk->clk == clk)
{
break;
}
}
break;
/* */
case HAL_CLK_FIXED_FACTOR:
for (i = 0; sunxi_clk_fixed_factor_arry[i] != NULL; i++)
{
pclk = (clk_core_pt)sunxi_clk_fixed_factor_arry[i];
if (pclk->clk == clk)
{
break;
}
}
break;
/* */
default:
break;
}
return pclk;
}
hal_clk_status_t sunxi_clk_set_parent(hal_clk_id_t clk, hal_clk_id_t parent_clk)
{
u32 i = 0, cnt = 0, parent_rate = 0;
u8 index = 0;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return ret;
}
switch (pclk->clk_type)
{
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
if (periph_clk->clk_core.current_parent == parent_clk)
{
return HAL_CLK_STATUS_OK;
}
for (i = 0; i < periph_clk->parent_arry_size; i++)
{
if (periph_clk->parent_arry[i] != parent_clk)
{
continue;
}
ret = sunxi_clk_periph_set_parent(periph_clk, i);
break;
}
if (ret == HAL_CLK_STATUS_OK)
{
periph_clk->clk_core.current_parent = parent_clk;
periph_clk->clk_core.current_parent_type = HAL_CLK_GET_TYPE(parent_clk);
ret = sunxi_clk_recalc_rate(parent_clk, &parent_rate);
if (ret == HAL_CLK_STATUS_OK)
{
periph_clk->clk_core.parent_rate = parent_rate;
}
else
{
periph_clk->clk_core.parent_rate = 0;
}
}
break;
/* */
case HAL_CLK_FIXED_SRC:
case HAL_CLK_FIXED_FACTOR:
case HAL_CLK_FACTOR:
ret = HAL_CLK_STATUS_OK;
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROR_CLK_SET_RATE_REFUSED;
break;
}
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_clk_get_parent(hal_clk_id_t clk, hal_clk_id_t *parent_clk)
{
u32 i;
u8 index = 0;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
hal_clk_id_t parent;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return ret;
}
switch (pclk->clk_type)
{
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
ret = sunxi_clk_periph_get_parent(periph_clk, &index);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
if (index >= periph_clk->parent_arry_size)
{
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
break;
}
parent = periph_clk->parent_arry[index];
if (periph_clk->clk_core.current_parent == parent)
{
break;
}
periph_clk->clk_core.current_parent = parent;
periph_clk->clk_core.current_parent_type = HAL_CLK_GET_TYPE(parent);
(*parent_clk) = parent;
break;
/* */
case HAL_CLK_FIXED_SRC:
case HAL_CLK_FIXED_FACTOR:
case HAL_CLK_FACTOR:
pclk = clk_get_core(clk);
(*parent_clk) = pclk->current_parent;
ret = HAL_CLK_STATUS_OK;
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
break;
}
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_clk_disable(hal_clk_id_t clk)
{
u32 i;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
clk_factor_pt factor_clk = NULL;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return ret;
}
switch (pclk->clk_type)
{
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
ret = sunxi_clk_periph_disable(periph_clk);
if (ret == HAL_CLK_STATUS_DISABLED)
{
periph_clk->clk_core.clk_enbale = HAL_CLK_STATUS_DISABLED;
}
return HAL_CLK_STATUS_OK;
break;
/* */
case HAL_CLK_FACTOR:
factor_clk = (clk_factor_pt)pclk;
ret = sunxi_clk_fators_disable(factor_clk);
if (ret == HAL_CLK_STATUS_DISABLED)
{
factor_clk->clk_core.clk_enbale = HAL_CLK_STATUS_DISABLED;
}
return HAL_CLK_STATUS_OK;
break;
/* */
case HAL_CLK_FIXED_FACTOR:
ret = HAL_CLK_STATUS_ERROR_CLK_FACTOR_REFUSED;
break;
/* */
case HAL_CLK_FIXED_SRC:
ret = HAL_CLK_STATUS_ERROR_CLK_FACTOR_REFUSED;
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
break;
}
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_clk_enabled(hal_clk_id_t clk)
{
u32 i;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
clk_factor_pt factor_clk = NULL;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return ret;
}
switch (pclk->clk_type)
{
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
ret = sunxi_clk_periph_enable(periph_clk);
if (ret == HAL_CLK_STATUS_ENABLED)
{
periph_clk->clk_core.clk_enbale = HAL_CLK_STATUS_ENABLED;
}
break;
/* */
case HAL_CLK_FACTOR:
factor_clk = (clk_factor_pt)pclk;
ret = sunxi_clk_fators_enable(factor_clk);
if (ret == HAL_CLK_STATUS_ENABLED)
{
factor_clk->clk_core.clk_enbale = HAL_CLK_STATUS_ENABLED;
}
break;
/* */
case HAL_CLK_FIXED_SRC:
case HAL_CLK_FIXED_FACTOR:
return pclk->clk_enbale;
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
break;
}
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_clk_is_enabled(hal_clk_id_t clk)
{
u32 i;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
clk_factor_pt factor_clk = NULL;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return ret;
}
switch (pclk->clk_type)
{
case HAL_CLK_FIXED_SRC:
case HAL_CLK_FIXED_FACTOR:
return HAL_CLK_STATUS_ENABLED;
break;
/* */
case HAL_CLK_FACTOR:
factor_clk = (clk_factor_pt)pclk;
return sunxi_clk_fators_is_enabled(factor_clk);
break;
/* */
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
return sunxi_clk_periph_is_enabled(periph_clk);
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
break;
}
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_clk_round_rate(hal_clk_id_t clk, u32 rate, u32 *prate)
{
u32 i, parent_rate = 0, round_rate = 0;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
clk_factor_pt factor_clk = NULL;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return ret;
}
switch (pclk->clk_type)
{
/* */
case HAL_CLK_FIXED_SRC:
case HAL_CLK_FIXED_FACTOR:
(*prate) = pclk->clk_rate;
ret = HAL_CLK_STATUS_OK;
break;
/* */
case HAL_CLK_FACTOR:
factor_clk = (clk_factor_pt)pclk;
round_rate = sunxi_clk_factors_round_rate(factor_clk, rate);
if (round_rate == 0)
{
ret = HAL_CLK_STATUS_ERROR_CLK_ROUND_FAILED;
break;
}
*prate = round_rate;
ret = HAL_CLK_STATUS_OK;
break;
/* */
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
parent_rate = periph_clk->clk_core.parent_rate;
round_rate = sunxi_clk_periph_round_rate(periph_clk, rate, parent_rate);
if (round_rate == 0)
{
ret = HAL_CLK_STATUS_ERROR_CLK_ROUND_FAILED;
break;
}
*prate = round_rate;
ret = HAL_CLK_STATUS_OK;
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
return ret;
break;
}
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_clk_recalc_rate(hal_clk_id_t clk, u32 *rate)
{
u32 i, current_rate = 0;
u8 index = 0;
hal_clk_status_t ret = HAL_CLK_STATUS_OK;
hal_clk_id_t parent;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
clk_factor_pt factor_clk = NULL;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
}
switch (pclk->clk_type)
{
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
ret = sunxi_clk_periph_recalc_rate(periph_clk, &current_rate);
if (ret != HAL_CLK_STATUS_OK)
{
ret = HAL_CLK_STATUS_DISABLED;
break;
}
(*rate) = current_rate;
break;
case HAL_CLK_FACTOR:
factor_clk = (clk_factor_pt)pclk;
ret = sunxi_clk_factors_recalc_rate(factor_clk, &current_rate);
if (ret != HAL_CLK_STATUS_OK)
{
ret = HAL_CLK_STATUS_DISABLED;
break;
}
(*rate) = current_rate;
break;
/* */
case HAL_CLK_FIXED_SRC:
case HAL_CLK_FIXED_FACTOR:
(*rate) = pclk->clk_rate;
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
break;
}
return ret;
}
hal_clk_status_t sunxi_clk_get_rate(hal_clk_id_t clk, u32 *rate)
{
u32 i;
clk_core_pt pclk = NULL;
hal_clk_status_t ret = HAL_CLK_STATUS_OK;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
}
(*rate) = pclk->clk_rate;
return HAL_CLK_STATUS_OK;
}
hal_clk_status_t sunxi_clk_set_rate(hal_clk_id_t clk, u32 rate)
{
u32 i, parent_rate;
clk_core_pt pclk = NULL;
clk_periph_pt periph_clk = NULL;
clk_factor_pt factor_clk = NULL;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
CCMU_TRACE();
pclk = clk_get_core(clk);
if (pclk == NULL)
{
return ret;
}
switch (HAL_CLK_GET_TYPE(clk))
{
/* */
case HAL_CLK_PERIPH:
periph_clk = (clk_periph_pt)pclk;
if (periph_clk->clk_core.clk_enbale == HAL_CLK_STATUS_ENABLED)
{
return HAL_CLK_STATUS_ERROR_CLK_NEED_DISABLED;
}
if (periph_clk->clk_core.clk_rate == rate)
{
return HAL_CLK_STATUS_OK;
}
parent_rate = periph_clk->clk_core.parent_rate;
ret = sunxi_clk_periph_set_rate(periph_clk, rate);
if (ret == HAL_CLK_STATUS_OK)
{
periph_clk->clk_core.clk_rate = rate;
}
break;
/* */
case HAL_CLK_FACTOR:
factor_clk = (clk_factor_pt)pclk;
ret = sunxi_clk_factors_set_rate(factor_clk, rate);
if (ret == HAL_CLK_STATUS_OK)
{
factor_clk->clk_core.clk_rate = rate;
}
break;
/* */
case HAL_CLK_FIXED_SRC:
case HAL_CLK_FIXED_FACTOR:
ret = HAL_CLK_STATUS_ERROR_CLK_SET_RATE_REFUSED;
break;
/* */
default:
ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
break;
}
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_fixed_factor_clk_init(void)
{
u32 i = 0, parent_rate = 0;
clk_core_pt pclk = NULL;
clk_core_pt parent_clk_core = NULL;
clk_fixed_factor_pt fixed_factor = NULL;
hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
CCMU_TRACE();
for (i = 0; sunxi_clk_fixed_factor_arry[i] != NULL; i++)
{
fixed_factor = sunxi_clk_fixed_factor_arry[i];
parent_clk_core = clk_get_core(fixed_factor->clk_core.current_parent);
if (parent_clk_core == NULL)
{
return ret;
}
if (parent_clk_core->clk_enbale == HAL_CLK_STATUS_DISABLED)
{
return HAL_CLK_STATUS_ERROR_CLK_PARENT_DISABLED;
}
parent_rate = parent_clk_core->clk_rate;
fixed_factor->clk_core.clk_enbale = HAL_CLK_STATUS_ENABLED;
fixed_factor->clk_core.parent_rate = parent_rate;
fixed_factor->clk_core.clk_rate = (parent_rate * fixed_factor->clk_mult) / fixed_factor->clk_div;
}
ret = HAL_CLK_STATUS_OK;
CCMU_TRACE();
return ret;
}
hal_clk_status_t sunxi_periph_bus_clk_init(void)
{
hal_clk_status_t ret;
clk_base_pt clk_init;
clk_periph_pt pclk;
hal_clk_id_t parent_clk;
u32 i = 0, parent_rate = 0, round_rate = 0, check_rate = 0;
CCMU_TRACE();
for (i = 0; sunxi_periph_clk_init_arry[i] != NULL; i++)
{
parent_clk = HAL_CLK_UNINITIALIZED ;
clk_init = sunxi_periph_clk_init_arry[i];
pclk = (clk_periph_pt)clk_get_core(clk_init->clk);
if (pclk == NULL)
{
return HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
}
CCMU_DBG("Clk-id %d init start.................\n", clk_init->clk);
/* check and set clk parent select regs*/
ret = sunxi_clk_get_parent(clk_init->clk, &parent_clk);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
if (clk_init->parent != parent_clk)
{
CCMU_DBG("set Parent-id %d \n", parent_clk);
ret = sunxi_clk_set_parent(clk_init->clk, clk_init->parent);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
}
/* check and get round clk*/
ret = sunxi_clk_get_rate(clk_init->parent, &parent_rate);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
pclk->clk_core.current_parent = clk_init->parent;
pclk->clk_core.parent_rate = parent_rate;
ret = sunxi_clk_round_rate(clk_init->clk, clk_init->clk_rate, &round_rate);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
CCMU_DBG("get round rate %dHZ\n", round_rate);
/* check and disbale clk status*/
ret = sunxi_clk_is_enabled(clk_init->clk);
if (ret == HAL_CLK_STATUS_ENABLED)
{
ret = sunxi_clk_disable(clk_init->clk);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
}
CCMU_DBG("set new rate %dHZ\n", round_rate);
/* set clk rate*/
ret = sunxi_clk_set_rate(clk_init->clk, round_rate);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
/* enable clk status*/
ret = sunxi_clk_enabled(clk_init->clk);
if (ret != HAL_CLK_STATUS_ENABLED)
{
break;
}
ret = sunxi_clk_recalc_rate(clk_init->clk, &check_rate);
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
CCMU_DBG("Clk-id %d cached rate %dHZ recalc new rate %dHZ, parent-id %d parent rate %dHZ \n", clk_init->clk, pclk->clk_core.clk_rate, check_rate,
pclk->clk_core.current_parent, pclk->clk_core.parent_rate);
CCMU_DBG("Clk-id %d init final .................\n", clk_init->clk);
}
CCMU_DBG("ret %d \n", ret);
return ret;
}
hal_clk_status_t sunxi_factor_clk_init(void)
{
u32 i;
hal_clk_status_t ret = HAL_CLK_STATUS_OK;
hal_clk_status_t (*func)(void) = NULL;
for (i = 0; sunxi_clk_factor_init[i] != NULL; i++)
{
func = sunxi_clk_factor_init[i];
ret = func();
if (ret != HAL_CLK_STATUS_OK)
{
break;
}
}
return ret;
}
hal_clk_status_t clk_set_parent(hal_clk_id_t clk, hal_clk_id_t parent_clk)
{
return sunxi_clk_set_parent(clk, parent_clk);
}
hal_clk_id_t clk_get_parent(hal_clk_id_t clk)
{
hal_clk_id_t parent_clk = HAL_CLK_UNINITIALIZED ;
hal_clk_status_t ret;
ret = sunxi_clk_get_parent(clk, &parent_clk);
if (ret == HAL_CLK_STATUS_OK)
{
return parent_clk;
}
else
{
return HAL_CLK_UNINITIALIZED;
}
}
hal_clk_status_t clk_disable_unprepare(hal_clk_id_t clk)
{
return sunxi_clk_disable(clk);
}
hal_clk_status_t clk_prepare_enable(hal_clk_id_t clk)
{
return sunxi_clk_enabled(clk);
}
hal_clk_status_t clk_is_enabled(hal_clk_id_t clk)
{
return sunxi_clk_is_enabled(clk);
}
hal_clk_status_t clk_round_rate(hal_clk_id_t clk, u32 rate, u32 *prate)
{
return sunxi_clk_round_rate(clk, rate, prate);
}
hal_clk_status_t clk_recalc_rate(hal_clk_id_t clk, u32 *p_rate)
{
return sunxi_clk_recalc_rate(clk, p_rate);
}
hal_clk_status_t clk_set_rate(hal_clk_id_t clk, u32 rate)
{
return sunxi_clk_set_rate(clk, rate);
}
hal_clk_status_t clk_get_rate(hal_clk_id_t clk, u32 *rate)
{
return sunxi_clk_get_rate(clk, rate);
}
hal_clk_id_t clk_get(hal_clk_type_t type, hal_clk_id_t id)
{
return id;
}
hal_clk_status_t clk_put(hal_clk_id_t id)
{
return HAL_CLK_STATUS_OK;
}
hal_clk_status_t clk_init(void)
{
hal_clk_status_t ret;
ret = sunxi_factor_clk_init();
/*the parent clk of some fixed-factor clk maybe factor-pll clk,
so factor-pll clk init before fixed-factor clk*/
ret = sunxi_fixed_factor_clk_init();
ret = sunxi_periph_bus_clk_init();
return ret;
}