623 lines
20 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
*
* Author: Joseph Chen <chenjh@rock-chips.com>
*/
#include "cru_core.h"
#include "cru_rkx110.h"
/*
* [RKX110 CHIP]: RX
*
* ================= SECTION: Input clock from devices =========================
*
* ### 300M ###
* clk_8x_pma2pcs0
* clk_8x_pma2pcs1
*
*
* ### 200M ###
* sclk_i2s_link2pcs --|-- sclk_i2s_link2pcs_inter1
* |-- sclk_i2s_link2pcs_inter2
*
*
* ### 200M ###
* clk_link_pcs0 --|-- clk_pma2pcs0 |-- clk_pma2link2pcs_link
* | |
* |-- clk_pma2link2pcs_cm (MUX) --|-- clk_pma2link2pcs_psc0
* clk_link_pcs1 --| |
* |-- clk_pma2pcs1 |-- clk_pma2link2pcs_psc1
*
* clk_rxbytehs_csihost0
* clk_rxbytehs_csihost1
* iclk_dsi0
* iclk_dsi1
* iclk_vicap
*
*
* ### 150M ###
* dclk_lvds0 -- clk_d_lvds0_rklink_tx_cm --|-- clk_d_lvds0_pattern_gen_en
* |-- clk_d_lvds0_rklink_tx
*
* dclk_lvds1 -- clk_d_lvds1_rklink_tx_cm --|-- clk_d_lvds1_pattern_gen_en
* |-- clk_d_lvds1_rklink_tx
*
* clk_d_rgb_rklink_tx
* pclkin_vicap_dvp_rx
* rxpclk_lvds_align
* rxpclk_vicap_lvds
*/
#define RKX110_SSCG_RXPLL_EN 0
#define RKX110_SSCG_CPLL_EN 0
#define RKX110_TESTOUT_MUX -1 /* valid options: RKX110_TEST_CLKOUT_IOUT_SEL_? */
#define RKX110_GRF_GPIO0B_IOMUX_H 0x0001000c
#define GPIO0B7_TEST_CLKOUT 0x01c00080
#define I2S_122888_BEST_PRATE 393216000
#define I2S_112896_BEST_PRATE 756403200
static struct PLL_CONFIG PLL_TABLE[] = {
/* _mhz, _refDiv, _fbDiv, _postdDv1, _postDiv2, _dsmpd, _frac */
RK_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
RK_PLL_RATE(600000000, 1, 25, 1, 1, 1, 0),
/* display */
RK_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
/* audio: 12.288M */
RK_PLL_RATE(688128000, 1, 86, 3, 1, 0, 268435), /* div=56, vco=2064.384M */
RK_PLL_RATE(393216000, 2, 131, 4, 1, 0, 1207959), /* div=32, vco=1572.864M */
RK_PLL_RATE(344064000, 1, 43, 3, 1, 0, 134217), /* div=28, vco=1032.192M */
/* audio: 11.2896M */
RK_PLL_RATE(474163200, 1, 79, 4, 1, 0, 456340), /* div=42, vco=1896.6528M */
RK_PLL_RATE(756403200, 1, 63, 2, 1, 0, 563714), /* div=67, vco=1512.8064M */
RK_PLL_RATE(564480000, 1, 47, 2, 1, 0, 671088), /* div=50, vco=1128.96M */
{ /* sentinel */ },
};
static struct PLL_SETUP RXPLL_SETUP = {
.id = PLL_RXPLL,
.conOffset0 = 0x00000020,
.conOffset1 = 0x00000024,
.conOffset2 = 0x00000028,
.conOffset3 = 0x0000002c,
.modeOffset = 0x00000600,
.modeShift = 0, /* 0: slow-mode, 1: normal-mode */
.lockShift = 10,
.modeMask = 0x1,
.rateTable = PLL_TABLE,
.minRefdiv = 1,
.maxRefdiv = 2,
.minVco = _MHZ(375),
.maxVco = _MHZ(2400),
.minFout = _MHZ(24),
.maxFout = _MHZ(1200),
.sscgEn = RKX110_SSCG_RXPLL_EN,
};
static struct PLL_SETUP CPLL_SETUP = {
.id = PLL_CPLL,
.conOffset0 = 0x00000000,
.conOffset1 = 0x00000004,
.conOffset2 = 0x00000008,
.conOffset3 = 0x0000000c,
.modeOffset = 0x00000600,
.modeShift = 2,
.lockShift = 10,
.modeMask = 0x1 << 2,
.rateTable = PLL_TABLE,
.minRefdiv = 1,
.maxRefdiv = 2,
.minVco = _MHZ(375),
.maxVco = _MHZ(2400),
.minFout = _MHZ(24),
.maxFout = _MHZ(1200),
.sscgEn = RKX110_SSCG_CPLL_EN,
};
static uint32_t RKX11x_HAL_CRU_ClkGetFreq(struct hwclk *hw, uint32_t clockName)
{
uint32_t pRate = 0, freq = 0;
uint32_t clkMux, clkDiv;
if (clockName == RKX110_CLK_D_DSI_0_PATTERN_GEN ||
clockName == RKX110_CLK_D_DSI_1_PATTERN_GEN) {
clockName = RKX110_CPS_DCLK_RX_PRE;
}
clkMux = CLK_GET_MUX(clockName);
clkDiv = CLK_GET_DIV(clockName);
switch (clockName) {
case RKX110_CPS_PLL_RXPLL:
hw->pllRate[RKX110_RXPLL] = HAL_CRU_GetPllFreq(hw, &RXPLL_SETUP);
return hw->pllRate[RKX110_RXPLL];
case RKX110_CPS_PLL_CPLL:
hw->pllRate[RKX110_CPLL] = HAL_CRU_GetPllFreq(hw, &CPLL_SETUP);
return hw->pllRate[RKX110_CPLL];
/*
* 400MHZ => down to 200M
* === RX_DCLK_RX_PRE gate children ===
*
* dclk_dsi0
* dclk_dsi1
* dclk_vicap_csi
*
* clk_c_dvp_rklink_tx
* clk_c_csi_rklink_tx
*
* clk_d_dsi_0_rklink_tx
* clk_d_dsi_1_rklink_tx
* clk_d_dsi_0_pattern_gen
* clk_d_dsi_1_pattern_gen
* clk_c_lvds_rklink_tx
*
* NOTE: `clk_d_rgb_rklink_tx` is an input clock.
*
*/
case RKX110_CPS_DCLK_RX_PRE:
/* camera: 150M */
case RKX110_CPS_CLK_CAM0_OUT2IO:
case RKX110_CPS_CLK_CAM1_OUT2IO:
case RKX110_CPS_CLK_CIF_OUT2IO:
/* dsi: 200M */
case RKX110_CPS_DCLK_D_DSI_0_REC_RKLINK_TX:
case RKX110_CPS_DCLK_D_DSI_1_REC_RKLINK_TX:
/* lvds: 300M */
case RKX110_CPS_CLK_2X_LVDS_RKLINK_TX:
/* i2s: 600M => down to 300M */
case RKX110_CPS_CLK_I2S_SRC_RKLINK_TX:
freq = HAL_CRU_MuxGetFreq3(hw, clkMux, hw->pllRate[RKX110_RXPLL],
hw->pllRate[RKX110_CPLL], OSC_24M);
break;
/* mipi: ref_1000M, cfg_100M */
case RKX110_CPS_CKREF_MIPIRXPHY0:
case RKX110_CPS_CKREF_MIPIRXPHY1:
case RKX110_CPS_CFGCLK_MIPIRXPHY0:
case RKX110_CPS_CFGCLK_MIPIRXPHY1:
/* pre-bus: 100M */
case RKX110_CPS_BUSCLK_RX_PRE0:
freq = HAL_CRU_MuxGetFreq2(hw, clkMux, hw->pllRate[RKX110_RXPLL],
hw->pllRate[RKX110_CPLL]);
break;
/*
* bus: 100MHZ => down to 24M
*
* === RX_BUSCLK_RX_PRE gate children ===
*
* pclk_rx_cru
* pclk_rx_grf
* pclk_rx_gpio0/1
* pclk_rx_efuse
* pclk_mipi_grf_rx0/1
* pclk_rx_i2c2apb
* pclk_rx_i2c2apb_debug
* pclk_csihost0/1
* pclk_rklink_tx
* pclk_dsi_{0,1}_pattern_gen
* pclk_lvds_{0,1}_pattern_gen
* pclk_pcs0/1
* pclk_pcs{0,1}_ada
* pclk_mipirxphy0/1
* pclk_dft2apb
*
* hclk_vicap
* hclk_dsi0/1
*/
case RKX110_CPS_BUSCLK_RX_PRE:
pRate = RKX11x_HAL_CRU_ClkGetFreq(hw, RKX110_CPS_BUSCLK_RX_PRE0);
freq = HAL_CRU_MuxGetFreq2(hw, clkMux, OSC_24M, pRate);
break;
case RKX110_CPS_CLK_PMA2LINK2PCS_CM:
return _MHZ(200);
/* gpio: 24M */
case RKX110_CPS_DCLK_RX_GPIO0:
case RKX110_CPS_DCLK_RX_GPIO1:
/* efuse: 24M */
case RKX110_CPS_RX_EFUSE:
/* pcs_ada: 24M */
case RKX110_CPS_PCS0_ADA:
case RKX110_CPS_PCS1_ADA:
return OSC_24M;
default:
CRU_ERR("%s: %s: Unknown clk 0x%08x\n", __func__, hw->name, clockName);
return HAL_INVAL;
}
if (!clkMux && !clkDiv) {
return 0;
}
if (clkDiv) {
freq /= (HAL_CRU_ClkGetDiv(hw, clkDiv));
}
return freq;
}
static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName, uint32_t rate)
{
uint32_t clkMux, clkDiv;
uint32_t mux = 0, div = 1;
uint32_t pRate = 0;
uint32_t maxDiv;
uint32_t pll;
uint8_t overMax = 0;
HAL_Status ret = HAL_OK;
int i;
if (clockName == RKX110_CLK_D_DSI_0_PATTERN_GEN ||
clockName == RKX110_CLK_D_DSI_1_PATTERN_GEN) {
clockName = RKX110_CPS_DCLK_RX_PRE;
}
clkMux = CLK_GET_MUX(clockName);
clkDiv = CLK_GET_DIV(clockName);
switch (clockName) {
case RKX110_CPS_PLL_RXPLL:
ret = HAL_CRU_SetPllFreq(hw, &RXPLL_SETUP, rate);
if (ret != HAL_OK) {
CRU_ERR("%s: RXPLL set rate: %d failed\n", hw->name, rate);
} else {
hw->pllRate[RKX110_RXPLL] = rate;
CRU_MSG("%s: RXPLL set rate: %d\n", hw->name, rate);
}
return ret;
case RKX110_CPS_PLL_CPLL:
ret = HAL_CRU_SetPllFreq(hw, &CPLL_SETUP, rate);
if (ret != HAL_OK) {
CRU_ERR("%s: CPLL set rate: %d failed\n", hw->name, rate);
} else {
hw->pllRate[RKX110_CPLL] = rate;
CRU_MSG("%s: CPLL set rate: %d\n", hw->name, rate);
}
return ret;
/* link(dclk): Allowed to change PLL rate if need ! */
case RKX110_CPS_DCLK_D_DSI_0_REC_RKLINK_TX:
case RKX110_CPS_DCLK_D_DSI_1_REC_RKLINK_TX:
case RKX110_CPS_CLK_2X_LVDS_RKLINK_TX:
/* i2s */
case RKX110_CPS_CLK_I2S_SRC_RKLINK_TX:
maxDiv = CLK_DIV_GET_MAXDIV(clkDiv);
if (DIV_NO_REM(hw->pllRate[RKX110_RXPLL], rate, maxDiv)) {
mux = 0;
pRate = hw->pllRate[RKX110_RXPLL];
} else if (DIV_NO_REM(hw->pllRate[RKX110_CPLL], rate, maxDiv)) {
mux = 1;
pRate = hw->pllRate[RKX110_CPLL];
} else if (DIV_NO_REM(OSC_24M, rate, maxDiv)) {
mux = 2;
pRate = OSC_24M;
} else {
if (clockName == RKX110_CPS_CLK_I2S_SRC_RKLINK_TX) {
pll = RKX110_CPS_PLL_CPLL;
if (DIV_NO_REM(I2S_122888_BEST_PRATE, rate, maxDiv)) {
pRate = I2S_122888_BEST_PRATE;
} else if (DIV_NO_REM(I2S_112896_BEST_PRATE, rate, maxDiv)) {
pRate = I2S_112896_BEST_PRATE;
}
} else {
pll = RKX110_CPS_PLL_RXPLL;
}
/* PLL change closest new rate <= 1200M if need */
if (!pRate) {
if (!rate || rate > _MHZ(1200))
return HAL_ERROR;
for (i = _MHZ(1200) / rate; i > _MHZ(24) / rate; i--) {
pRate = i * rate;
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret == HAL_OK)
break;
}
if (ret != HAL_OK)
return ret;
} else {
ret = RKX11x_HAL_CRU_ClkSetFreq(hw, pll, pRate);
if (ret != HAL_OK) {
return ret;
}
}
/* if success, continue to set divider */
}
break;
/* bus */
case RKX110_CPS_DCLK_RX_PRE:
/* camera */
case RKX110_CPS_CLK_CAM0_OUT2IO:
case RKX110_CPS_CLK_CAM1_OUT2IO:
case RKX110_CPS_CLK_CIF_OUT2IO:
mux = HAL_CRU_RoundFreqGetMux3(hw, rate, hw->pllRate[RKX110_RXPLL],
hw->pllRate[RKX110_CPLL], OSC_24M, &pRate);
break;
/* mipi */
case RKX110_CPS_CKREF_MIPIRXPHY0:
case RKX110_CPS_CKREF_MIPIRXPHY1:
case RKX110_CPS_CFGCLK_MIPIRXPHY0:
case RKX110_CPS_CFGCLK_MIPIRXPHY1:
/* pre-bus */
case RKX110_CPS_BUSCLK_RX_PRE0:
mux = HAL_CRU_RoundFreqGetMux2(hw, rate, hw->pllRate[RKX110_RXPLL],
hw->pllRate[RKX110_CPLL], &pRate);
break;
/* bus */
case RKX110_CPS_BUSCLK_RX_PRE:
if (rate == OSC_24M) {
return HAL_CRU_ClkSetMux(hw, clkMux, 0);
} else {
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_BUSCLK_RX_PRE0, rate);
return HAL_CRU_ClkSetMux(hw, clkMux, 1);
}
break;
/* gpio */
case RKX110_CPS_DCLK_RX_GPIO0:
case RKX110_CPS_DCLK_RX_GPIO1:
/* efuse */
case RKX110_CPS_RX_EFUSE:
/* pcs_ada */
case RKX110_CPS_PCS0_ADA:
case RKX110_CPS_PCS1_ADA:
return rate == OSC_24M ? 0 : HAL_INVAL;
case RKX110_CPS_CLK_PMA2LINK2PCS_CM:
if (rate != _MHZ(200)) {
return HAL_INVAL;
}
HAL_CRU_ClkSetMux(hw, clkMux, 0);
return HAL_OK;
default:
CRU_ERR("%s: %s: Unknown clk 0x%08x\n", __func__, hw->name, clockName);
return HAL_INVAL;
}
if (!clkMux && !clkDiv) {
return HAL_INVAL;
}
if (pRate) {
div = HAL_DIV_ROUND_UP(pRate, rate);
}
if (clkDiv) {
overMax = div > CLK_DIV_GET_MAXDIV(clkDiv);
if (overMax) {
CRU_MSG("%s: %s: Clk '0x%08x' req div(%d) over max(%d)!\n",
__func__, hw->name, clockName, div, CLK_DIV_GET_MAXDIV(clkDiv));
div = CLK_DIV_GET_MAXDIV(clkDiv);
}
HAL_CRU_ClkSetDiv(hw, clkDiv, div);
}
if (clkMux) {
HAL_CRU_ClkSetMux(hw, clkMux, mux);
}
return HAL_OK;
}
#if RKX110_SSCG_CPLL_EN || RKX110_SSCG_RXPLL_EN
static void RKX11x_HAL_CRU_Init_SSCG(struct hwclk *hw)
{
uint8_t down_spread = 1; /* 0: center spread */
uint8_t amplitude = 8; /* range: 0x00 - 0x1f */
#if RKX110_SSCG_CPLL_EN
/* down-spread, 0.8%, 37.5khz */
HAL_CRU_Write(hw, hw->cru_base + 0x0c, 0x1f000000 | ((amplitude & 0x1f) << 8));
HAL_CRU_Write(hw, hw->cru_base + 0x0c, 0x00f00050);
HAL_CRU_Write(hw, hw->cru_base + 0x0c, 0x00080000 | ((down_spread & 0x1) << 3));
HAL_CRU_Write(hw, hw->cru_base + 0x04, 0x10000000);
HAL_CRU_Write(hw, hw->cru_base + 0x0c, 0x00070000);
CRU_MSG("%s: CPLL enable SSCG\n", hw->name);
#endif
#if RKX110_SSCG_RXPLL_EN
/* down-spread, 0.8%, 37.5khz */
HAL_CRU_Write(hw, hw->cru_base + 0x2c, 0x1f000000 | ((amplitude & 0x1f) << 8));
HAL_CRU_Write(hw, hw->cru_base + 0x2c, 0x00f00050);
HAL_CRU_Write(hw, hw->cru_base + 0x2c, 0x00080000 | ((down_spread & 0x1) << 3));
HAL_CRU_Write(hw, hw->cru_base + 0x24, 0x10000000);
HAL_CRU_Write(hw, hw->cru_base + 0x2c, 0x00070000);
CRU_MSG("%s: RXPLL enable SSCG\n", hw->name);
#endif
}
#endif
static HAL_Status RKX11x_HAL_CRU_InitTestout(struct hwclk *hw, uint32_t clockName,
uint32_t muxValue, uint32_t divValue)
{
uint32_t clkMux = CLK_GET_MUX(clockName);
uint32_t clkDiv = CLK_GET_DIV(clockName);
/* gpio0_b7: iomux to clk_testout */
HAL_CRU_Write(hw, RKX110_GRF_GPIO0B_IOMUX_H, GPIO0B7_TEST_CLKOUT);
/* Enable clock */
HAL_CRU_ClkEnable(hw, RKX110_CLK_TESTOUT_TOP_GATE);
/* Mux, div */
HAL_CRU_ClkSetDiv(hw, clkDiv, divValue);
HAL_CRU_ClkSetMux(hw, clkMux, muxValue);
CRU_MSG("%s: Testout div=%d, mux=%d\n", hw->name, divValue, muxValue);
return HAL_OK;
}
static HAL_Status RKX11x_HAL_CRU_Init(struct hwclk *hw, struct xferclk *xfer)
{
hw->cru_base = 0x0;
hw->sel_con0 = hw->cru_base + 0x100;
hw->gate_con0 = hw->cru_base + 0x300;
hw->softrst_con0 = hw->cru_base + 0x400;
hw->gbl_srst_fst = 0x0614;
hw->flags = 0;
hw->num_gate = 16 * 12;
hw->gate = HAL_KCALLOC(hw->num_gate, sizeof(struct clkGate));
if (!hw->gate) {
return HAL_NOMEM;
}
strcat(hw->name, "<CRU.110@");
strcat(hw->name, xfer->name);
strcat(hw->name, ">");
/* Don't change order */
#if RKX110_SSCG_CPLL_EN || RKX110_SSCG_RXPLL_EN
RKX11x_HAL_CRU_Init_SSCG(hw);
#endif
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_PLL_CPLL, _MHZ(1200));
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_PLL_RXPLL, _MHZ(1188));
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_BUSCLK_RX_PRE, _MHZ(24));
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_CLK_PMA2LINK2PCS_CM, _MHZ(200));
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_DCLK_RX_PRE, _MHZ(200));
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_CLK_I2S_SRC_RKLINK_TX, _MHZ(300));
RKX11x_HAL_CRU_ClkSetFreq(hw, RKX110_CPS_CFGCLK_MIPIRXPHY0, _MHZ(100));
HAL_CRU_ClkEnable(hw, RKX110_CLK_TESTOUT_TOP_GATE);
#if RKX110_TESTOUT_MUX >= 0
/* clk_testout support max 150M output, so set div=10 by default if not 24M */
RKX11x_HAL_CRU_InitTestout(hw, RKX110_CPS_TEST_CLKOUT, RKX110_TESTOUT_MUX,
RKX110_TESTOUT_MUX == 0 ? 1 : 10);
#endif
return HAL_OK;
}
PNAME(mux_24m_p) = { "xin24m" };
PNAME(mux_rxpll_cpll_p) = { "rxpll", "cpll" };
PNAME(mux_rxpll_cpll_24m_p) = { "rxpll", "cpll", "xin24m" };
PNAME(mux_rxpre0_24m_p) = { "xin24m", "busclk_rx_pre0" };
#define CAL_FREQ_REG 0xf00
static uint32_t RKX11x_HAL_CRU_ClkGetExtFreq(struct hwclk *hw, uint32_t clk)
{
uint32_t clkMux = CLK_GET_MUX(RKX110_CPS_TEST_CLKOUT);
uint32_t clkDiv = CLK_GET_DIV(RKX110_CPS_TEST_CLKOUT);
uint32_t freq, mhz;
uint8_t div = 10;
HAL_CRU_ClkSetDiv(hw, clkDiv, div);
HAL_CRU_ClkSetMux(hw, clkMux, 0);
HAL_SleepMs(2);
HAL_CRU_ClkSetMux(hw, clkMux, clk);
HAL_SleepMs(2);
freq = HAL_CRU_Read(hw, CAL_FREQ_REG);
/* Fix accuracy */
if ((freq % 10) == 0x9) {
freq++;
}
freq *= (1000 * div);
/* If no external input, freq is close to 24M */
mhz = freq / 1000000;
if ((clk != 0) && (mhz == 23 || mhz == 24)) {
freq = 0;
}
return freq;
}
static struct clkTable rkx11x_clkTable[] = {
/* internal */
CLK_DECLARE_INT("rxpll", RKX110_CPS_PLL_RXPLL, mux_24m_p),
CLK_DECLARE_INT("cpll", RKX110_CPS_PLL_CPLL, mux_24m_p),
CLK_DECLARE_INT("dclk_rx_pre", RKX110_CPS_DCLK_RX_PRE, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("clk_d_dsi_0_pattern", RKX110_CPS_DCLK_RX_PRE, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("clk_d_dsi_1_pattern", RKX110_CPS_DCLK_RX_PRE, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("clk_cam0_out2io", RKX110_CPS_CLK_CAM0_OUT2IO, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("clk_cam1_out2io", RKX110_CPS_CLK_CAM1_OUT2IO, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("clk_cif_out2io", RKX110_CPS_CLK_CIF_OUT2IO, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("dclk_d_dsi_0_rec_rklink_tx", RKX110_CPS_DCLK_D_DSI_0_REC_RKLINK_TX, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("dclk_d_dsi_1_rec_rklink_tx", RKX110_CPS_DCLK_D_DSI_1_REC_RKLINK_TX, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("clk_2x_lvds_rklink_tx", RKX110_CPS_CLK_2X_LVDS_RKLINK_TX, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("clk_i2s_src_rklink_tx", RKX110_CPS_CLK_I2S_SRC_RKLINK_TX, mux_rxpll_cpll_24m_p),
CLK_DECLARE_INT("ckref_mipirxphy0", RKX110_CPS_CKREF_MIPIRXPHY0, mux_rxpll_cpll_p),
CLK_DECLARE_INT("ckref_mipirxphy1", RKX110_CPS_CKREF_MIPIRXPHY1, mux_rxpll_cpll_p),
CLK_DECLARE_INT("cfgclk_mipirxphy0", RKX110_CPS_CFGCLK_MIPIRXPHY0, mux_rxpll_cpll_p),
CLK_DECLARE_INT("cfgclk_mipirxphy1", RKX110_CPS_CFGCLK_MIPIRXPHY1, mux_rxpll_cpll_p),
CLK_DECLARE_INT("busclk_rx_pre0", RKX110_CPS_BUSCLK_RX_PRE0, mux_rxpll_cpll_p),
CLK_DECLARE_INT("busclk_rx_pre", RKX110_CPS_BUSCLK_RX_PRE, mux_rxpre0_24m_p),
CLK_DECLARE_INT("dclk_rx_gpio0", RKX110_CPS_DCLK_RX_GPIO0, mux_24m_p),
CLK_DECLARE_INT("dclk_rx_gpio1", RKX110_CPS_DCLK_RX_GPIO1, mux_24m_p),
CLK_DECLARE_INT("rx_efuse", RKX110_CPS_RX_EFUSE, mux_24m_p),
CLK_DECLARE_INT("pcs0_ada", RKX110_CPS_PCS0_ADA, mux_24m_p),
CLK_DECLARE_INT("pcs1_ada", RKX110_CPS_PCS1_ADA, mux_24m_p),
/* external */
CLK_DECLARE_EXT("xin24m", 0, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("rxpclk_vicap_lvds", 3, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("clk_rxbytehs_csihost0", 4, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("clk_rxbytehs_csihost1", 5, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("clk_d_rgb_rklink_tx", 6, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("dclk_lvds0", 7, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("dclk_lvds1", 8, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("clk_link_pcs0", 9, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("clk_link_pcs1", 10, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("pclkin_vicap_dvp_rx", 21, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("iclk_dsi0", 22, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("iclk_dsi1", 23, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("rxpclk_lvds_align", 24, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("clk_8x_pma2pcs0", 25, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT("clk_8x_pma2pcs1", 26, RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_d_lvds0_rklink_tx_cm", 7, "dclk_lvds0", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_d_lvds0_rklink_tx", 7, "clk_d_lvds0_rklink_tx_cm", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_d_lvds0_pattern_gen_en", 7, "clk_d_lvds0_rklink_tx_cm", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_d_lvds1_rklink_tx_cm", 8, "dclk_lvds1", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_d_lvds1_rklink_tx", 8, "clk_d_lvds1_rklink_tx_cm", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_d_lvds1_pattern_gen_en", 8, "clk_d_lvds1_rklink_tx_cm", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_pma2pcs0", 9, "clk_link_pcs0", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_pma2link2pcs_cm", 9, "clk_link_pcs0", RKX11x_HAL_CRU_ClkGetExtFreq),
CLK_DECLARE_EXT_PARENT("clk_pma2pcs1", 9, "clk_link_pcs1", RKX11x_HAL_CRU_ClkGetExtFreq),
{ /* sentinel */ },
};
struct clkOps rkx110_clk_ops =
{
.clkTable = rkx11x_clkTable,
.clkInit = RKX11x_HAL_CRU_Init,
.clkGetFreq = RKX11x_HAL_CRU_ClkGetFreq,
.clkSetFreq = RKX11x_HAL_CRU_ClkSetFreq,
.clkInitTestout = RKX11x_HAL_CRU_InitTestout,
};