-142736, Sync spacc driver code. -2303c6, add suspend to ram featrue. -d3bff8, support pdm mic using AEC. -203610, support new spinand flash:HYF1GQ4UDACAE. Change-Id: Iec21bccaee43c4a71213b42b88f41a45527fd8a5
2849 lines
70 KiB
C
2849 lines
70 KiB
C
/*
|
|
* Copyright (c) 2021 CVITEK
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*/
|
|
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/clkdev.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/mfd/syscon.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/syscore_ops.h>
|
|
|
|
#include <dt-bindings/clock/cv181x-clock.h>
|
|
|
|
#define CV181X_CLK_FLAGS_ALL (CLK_GET_RATE_NOCACHE)
|
|
// #define CV181X_CLK_FLAGS_ALL (CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL)
|
|
// #define CV181X_CLK_FLAGS_ALL (CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED)
|
|
#define CV181X_CLK_FLAGS_MUX (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT)
|
|
|
|
/* top_pll_g2 */
|
|
#define REG_PLL_G2_CTRL 0x800
|
|
#define REG_PLL_G2_STATUS 0x804
|
|
#define REG_MIPIMPLL_CSR 0x808
|
|
#define REG_APLL0_CSR 0x80C
|
|
#define REG_DISPPLL_CSR 0x810
|
|
#define REG_CAM0PLL_CSR 0x814
|
|
#define REG_CAM1PLL_CSR 0x818
|
|
#define REG_PLL_G2_SSC_SYN_CTRL 0x840
|
|
#define REG_APLL_SSC_SYN_CTRL 0x850
|
|
#define REG_APLL_SSC_SYN_SET 0x854
|
|
#define REG_APLL_SSC_SYN_SPAN 0x858
|
|
#define REG_APLL_SSC_SYN_STEP 0x85C
|
|
#define REG_DISPPLL_SSC_SYN_CTRL 0x860
|
|
#define REG_DISPPLL_SSC_SYN_SET 0x864
|
|
#define REG_DISPPLL_SSC_SYN_SPAN 0x868
|
|
#define REG_DISPPLL_SSC_SYN_STEP 0x86C
|
|
#define REG_CAM0PLL_SSC_SYN_CTRL 0x870
|
|
#define REG_CAM0PLL_SSC_SYN_SET 0x874
|
|
#define REG_CAM0PLL_SSC_SYN_SPAN 0x878
|
|
#define REG_CAM0PLL_SSC_SYN_STEP 0x87C
|
|
#define REG_CAM1PLL_SSC_SYN_CTRL 0x880
|
|
#define REG_CAM1PLL_SSC_SYN_SET 0x884
|
|
#define REG_CAM1PLL_SSC_SYN_SPAN 0x888
|
|
#define REG_CAM1PLL_SSC_SYN_STEP 0x88C
|
|
#define REG_APLL_FRAC_DIV_CTRL 0x890
|
|
#define REG_APLL_FRAC_DIV_M 0x894
|
|
#define REG_APLL_FRAC_DIV_N 0x898
|
|
#define REG_MIPIMPLL_CLK_CSR 0x8A0
|
|
#define REG_A0PLL_CLK_CSR 0x8A4
|
|
#define REG_DISPPLL_CLK_CSR 0x8A8
|
|
#define REG_CAM0PLL_CLK_CSR 0x8AC
|
|
#define REG_CAM1PLL_CLK_CSR 0x8B0
|
|
#define REG_CLK_CAM0_SRC_DIV 0x8C0
|
|
#define REG_CLK_CAM1_SRC_DIV 0x8C4
|
|
|
|
/* top_pll_g6 */
|
|
#define REG_PLL_G6_CTRL 0x900
|
|
#define REG_PLL_G6_STATUS 0x904
|
|
#define REG_MPLL_CSR 0x908
|
|
#define REG_TPLL_CSR 0x90C
|
|
#define REG_FPLL_CSR 0x910
|
|
#define REG_PLL_G6_SSC_SYN_CTRL 0x940
|
|
#define REG_DPLL_SSC_SYN_CTRL 0x950
|
|
#define REG_DPLL_SSC_SYN_SET 0x954
|
|
#define REG_DPLL_SSC_SYN_SPAN 0x958
|
|
#define REG_DPLL_SSC_SYN_STEP 0x95C
|
|
#define REG_MPLL_SSC_SYN_CTRL 0x960
|
|
#define REG_MPLL_SSC_SYN_SET 0x964
|
|
#define REG_MPLL_SSC_SYN_SPAN 0x968
|
|
#define REG_MPLL_SSC_SYN_STEP 0x96C
|
|
#define REG_TPLL_SSC_SYN_CTRL 0x970
|
|
#define REG_TPLL_SSC_SYN_SET 0x974
|
|
#define REG_TPLL_SSC_SYN_SPAN 0x978
|
|
#define REG_TPLL_SSC_SYN_STEP 0x97C
|
|
|
|
/* clkgen */
|
|
#define REG_CLK_EN_0 0x000
|
|
#define REG_CLK_EN_1 0x004
|
|
#define REG_CLK_EN_2 0x008
|
|
#define REG_CLK_EN_3 0x00C
|
|
#define REG_CLK_EN_4 0x010
|
|
#define REG_CLK_SEL_0 0x020
|
|
#define REG_CLK_BYP_0 0x030
|
|
#define REG_CLK_BYP_1 0x034
|
|
|
|
#define REG_DIV_CLK_A53_0 0x040
|
|
#define REG_DIV_CLK_A53_1 0x044
|
|
#define REG_DIV_CLK_CPU_AXI0 0x048
|
|
#define REG_DIV_CLK_CPU_GIC 0x050
|
|
#define REG_DIV_CLK_TPU 0x054
|
|
#define REG_DIV_CLK_EMMC 0x064
|
|
#define REG_DIV_CLK_100K_EMMC 0x06C
|
|
#define REG_DIV_CLK_SD0 0x070
|
|
#define REG_DIV_CLK_100K_SD0 0x078
|
|
#define REG_DIV_CLK_SD1 0x07C
|
|
#define REG_DIV_CLK_100K_SD1 0x084
|
|
#define REG_DIV_CLK_SPI_NAND 0x088
|
|
#define REG_DIV_CLK_500M_ETH0 0x08C
|
|
#define REG_DIV_CLK_500M_ETH1 0x090
|
|
#define REG_DIV_CLK_GPIO_DB 0x094
|
|
#define REG_DIV_CLK_SDMA_AUD0 0x098
|
|
#define REG_DIV_CLK_SDMA_AUD1 0x09C
|
|
#define REG_DIV_CLK_SDMA_AUD2 0x0A0
|
|
#define REG_DIV_CLK_SDMA_AUD3 0x0A4
|
|
#define REG_DIV_CLK_CAM0_200 0x0A8
|
|
#define REG_DIV_CLK_AXI4 0x0B8
|
|
#define REG_DIV_CLK_AXI6 0x0BC
|
|
#define REG_DIV_CLK_DSI_ESC 0x0C4
|
|
#define REG_DIV_CLK_AXI_VIP 0x0C8
|
|
#define REG_DIV_CLK_SRC_VIP_SYS_0 0x0D0
|
|
#define REG_DIV_CLK_SRC_VIP_SYS_1 0x0D8
|
|
#define REG_DIV_CLK_DISP_SRC_VIP 0x0E0
|
|
#define REG_DIV_CLK_AXI_VIDEO_CODEC 0x0E4
|
|
#define REG_DIV_CLK_VC_SRC0 0x0EC
|
|
#define REG_DIV_CLK_1M 0x0FC
|
|
#define REG_DIV_CLK_SPI 0x100
|
|
#define REG_DIV_CLK_I2C 0x104
|
|
#define REG_DIV_CLK_SRC_VIP_SYS_2 0x110
|
|
#define REG_DIV_CLK_AUDSRC 0x118
|
|
#define REG_DIV_CLK_PWM_SRC_0 0x120
|
|
#define REG_DIV_CLK_AP_DEBUG 0x128
|
|
#define REG_DIV_CLK_RTCSYS_SRC_0 0x12C
|
|
#define REG_DIV_CLK_C906_0_0 0x130
|
|
#define REG_DIV_CLK_C906_0_1 0x134
|
|
#define REG_DIV_CLK_C906_1_0 0x138
|
|
#define REG_DIV_CLK_C906_1_1 0x13C
|
|
#define REG_DIV_CLK_SRC_VIP_SYS_3 0x140
|
|
#define REG_DIV_CLK_SRC_VIP_SYS_4 0x144
|
|
|
|
#define REG_PLL_G2_CSR_NUM (REG_CAM1PLL_CSR / 4 - REG_MIPIMPLL_CSR / 4 + 1)
|
|
#define REG_PLL_G2_CSR_START REG_MIPIMPLL_CSR
|
|
|
|
#define REG_PLL_G6_CSR_NUM (REG_FPLL_CSR / 4 - REG_MPLL_CSR / 4 + 1)
|
|
#define REG_PLL_G6_CSR_START REG_MPLL_CSR
|
|
|
|
#define REG_CLK_EN_NUM (REG_CLK_EN_4 / 4 - REG_CLK_EN_0 / 4 + 1)
|
|
#define REG_CLK_EN_START REG_CLK_EN_0
|
|
|
|
#define REG_CLK_SEL_NUM (REG_CLK_SEL_0 / 4 - REG_CLK_SEL_0 / 4 + 1)
|
|
#define REG_CLK_SEL_START REG_CLK_SEL_0
|
|
|
|
#define REG_CLK_BYP_NUM (REG_CLK_BYP_1 / 4 - REG_CLK_BYP_0 / 4 + 1)
|
|
#define REG_CLK_BYP_START REG_CLK_BYP_0
|
|
|
|
#define REG_CLK_DIV_NUM (REG_DIV_CLK_SRC_VIP_SYS_4 / 4 - REG_DIV_CLK_A53_0 / 4 + 1)
|
|
#define REG_CLK_DIV_START REG_DIV_CLK_A53_0
|
|
|
|
#define REG_CLK_G2_DIV_NUM (REG_CLK_CAM1_SRC_DIV / 4 - REG_CLK_CAM0_SRC_DIV / 4 + 1)
|
|
#define REG_CLK_G2_DIV_START REG_CLK_CAM0_SRC_DIV
|
|
|
|
#define CV181X_PLL_LOCK_TIMEOUT_MS 200
|
|
|
|
/* PLL status register offset */
|
|
#define PLL_STATUS_MASK 0xFF
|
|
#define PLL_STATUS_OFFSET 0x04
|
|
|
|
/* G2 Synthesizer register offset */
|
|
#define G2_SSC_CTRL_MASK 0xFF
|
|
#define G2_SSC_CTRL_OFFSET 0x40
|
|
#define SSC_SYN_SET_MASK 0x0F
|
|
#define SSC_SYN_SET_OFFSET 0x04
|
|
|
|
#define to_cv181x_pll_clk(_hw) container_of(_hw, struct cv181x_pll_hw_clock, hw)
|
|
#define to_cv181x_clk(_hw) container_of(_hw, struct cv181x_hw_clock, hw)
|
|
|
|
#define div_mask(width) ((1 << (width)) - 1)
|
|
|
|
static DEFINE_SPINLOCK(cv181x_clk_lock);
|
|
|
|
struct cv181x_clock_data {
|
|
void __iomem *base;
|
|
spinlock_t *lock;
|
|
struct clk_hw_onecell_data hw_data;
|
|
#ifdef CONFIG_PM_SLEEP
|
|
uint32_t clken_saved_regs[REG_CLK_EN_NUM];
|
|
uint32_t clksel_saved_regs[REG_CLK_SEL_NUM];
|
|
uint32_t clkbyp_saved_regs[REG_CLK_BYP_NUM];
|
|
uint32_t clkdiv_saved_regs[REG_CLK_DIV_NUM];
|
|
uint32_t g2_clkdiv_saved_regs[REG_CLK_G2_DIV_NUM];
|
|
uint32_t pll_g2_csr_saved_regs[REG_PLL_G2_CSR_NUM];
|
|
uint32_t a0pll_ssc_syn_set_saved_reg;
|
|
uint32_t disppll_ssc_syn_set_saved_reg;
|
|
uint32_t cam0pll_ssc_syn_set_saved_reg;
|
|
uint32_t cam1pll_ssc_syn_set_saved_reg;
|
|
uint32_t pll_g6_csr_saved_regs[REG_PLL_G6_CSR_NUM];
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
};
|
|
|
|
struct cv181x_gate {
|
|
u32 reg;
|
|
s8 shift;
|
|
unsigned long flags;
|
|
};
|
|
|
|
struct cv181x_div {
|
|
u32 reg;
|
|
s8 shift;
|
|
s8 width;
|
|
s16 initval;
|
|
unsigned long flags;
|
|
};
|
|
|
|
struct cv181x_mux {
|
|
u32 reg;
|
|
s8 shift;
|
|
s8 width;
|
|
unsigned long flags;
|
|
};
|
|
|
|
struct cv181x_hw_clock {
|
|
unsigned int id;
|
|
const char *name;
|
|
struct clk_hw hw;
|
|
void __iomem *base;
|
|
spinlock_t *lock;
|
|
|
|
struct cv181x_gate gate;
|
|
struct cv181x_div div[2]; /* 0: DIV_IN0, 1: DIV_IN1 */
|
|
struct cv181x_mux mux[3]; /* 0: bypass, 1: CLK_SEL, 2: CLK_SRC(DIV_IN0_SRC_MUX) */
|
|
};
|
|
|
|
struct cv181x_pll_clock {
|
|
unsigned int id;
|
|
const char *name;
|
|
u32 reg_csr;
|
|
u32 reg_ssc;
|
|
s16 post_div_sel; /* -1: postdiv*/
|
|
unsigned long flags;
|
|
};
|
|
|
|
struct cv181x_pll_hw_clock {
|
|
struct cv181x_pll_clock pll;
|
|
void __iomem *base;
|
|
spinlock_t *lock;
|
|
struct clk_hw hw;
|
|
};
|
|
|
|
static const struct clk_ops cv181x_g6_pll_ops;
|
|
static const struct clk_ops cv181x_g2_pll_ops;
|
|
static const struct clk_ops cv181x_g2d_pll_ops;
|
|
static const struct clk_ops cv181x_clk_ops;
|
|
|
|
static struct cv181x_clock_data *clk_data;
|
|
|
|
static unsigned long cvi_clk_flags;
|
|
|
|
#define CV181X_CLK(_id, _name, _parents, _gate_reg, _gate_shift, \
|
|
_div_0_reg, _div_0_shift, \
|
|
_div_0_width, _div_0_initval, \
|
|
_div_1_reg, _div_1_shift, \
|
|
_div_1_width, _div_1_initval, \
|
|
_mux_0_reg, _mux_0_shift, \
|
|
_mux_1_reg, _mux_1_shift, \
|
|
_mux_2_reg, _mux_2_shift, _flags) { \
|
|
.id = _id, \
|
|
.name = _name, \
|
|
.gate.reg = _gate_reg, \
|
|
.gate.shift = _gate_shift, \
|
|
.div[0].reg = _div_0_reg, \
|
|
.div[0].shift = _div_0_shift, \
|
|
.div[0].width = _div_0_width, \
|
|
.div[0].initval = _div_0_initval, \
|
|
.div[1].reg = _div_1_reg, \
|
|
.div[1].shift = _div_1_shift, \
|
|
.div[1].width = _div_1_width, \
|
|
.div[1].initval = _div_1_initval, \
|
|
.mux[0].reg = _mux_0_reg, \
|
|
.mux[0].shift = _mux_0_shift, \
|
|
.mux[0].width = 1, \
|
|
.mux[1].reg = _mux_1_reg, \
|
|
.mux[1].shift = _mux_1_shift, \
|
|
.mux[1].width = 1, \
|
|
.mux[2].reg = _mux_2_reg, \
|
|
.mux[2].shift = _mux_2_shift, \
|
|
.mux[2].width = 2, \
|
|
.hw.init = CLK_HW_INIT_PARENTS( \
|
|
_name, _parents, \
|
|
&cv181x_clk_ops, \
|
|
_flags | CV181X_CLK_FLAGS_ALL), \
|
|
}
|
|
|
|
|
|
#define CLK_G6_PLL(_id, _name, _parent, _reg_csr, _flags) { \
|
|
.pll.id = _id, \
|
|
.pll.name = _name, \
|
|
.pll.reg_csr = _reg_csr, \
|
|
.pll.reg_ssc = 0, \
|
|
.pll.post_div_sel = -1, \
|
|
.hw.init = CLK_HW_INIT_PARENTS(_name, _parent, \
|
|
&cv181x_g6_pll_ops, \
|
|
_flags | \
|
|
CV181X_CLK_FLAGS_ALL), \
|
|
}
|
|
|
|
#define CLK_G2_PLL(_id, _name, _parent, _reg_csr, _reg_ssc, _flags) { \
|
|
.pll.id = _id, \
|
|
.pll.name = _name, \
|
|
.pll.reg_csr = _reg_csr, \
|
|
.pll.reg_ssc = _reg_ssc, \
|
|
.pll.post_div_sel = -1, \
|
|
.hw.init = CLK_HW_INIT_PARENTS(_name, _parent, \
|
|
&cv181x_g2_pll_ops, \
|
|
_flags | \
|
|
CV181X_CLK_FLAGS_ALL), \
|
|
}
|
|
|
|
#define CLK_G2D_PLL(_id, _name, _parent, _reg_csr, _reg_ssc, \
|
|
_post_div_sel, _flags) { \
|
|
.pll.id = _id, \
|
|
.pll.name = _name, \
|
|
.pll.reg_csr = _reg_csr, \
|
|
.pll.reg_ssc = _reg_ssc, \
|
|
.pll.post_div_sel = _post_div_sel, \
|
|
.hw.init = CLK_HW_INIT_PARENTS(_name, _parent, \
|
|
&cv181x_g2d_pll_ops, \
|
|
_flags | \
|
|
CV181X_CLK_FLAGS_ALL), \
|
|
}
|
|
|
|
const char *const cv181x_pll_parent[] = {"osc"};
|
|
const char *const cv181x_frac_pll_parent[] = {"clk_mipimpll"};
|
|
|
|
/*
|
|
* All PLL clocks are marked as CRITICAL, hence they are very crucial
|
|
* for the functioning of the SoC
|
|
*/
|
|
static struct cv181x_pll_hw_clock cv181x_pll_clks[] = {
|
|
CLK_G6_PLL(CV181X_CLK_MPLL, "clk_mpll", cv181x_pll_parent, REG_MPLL_CSR, 0),
|
|
CLK_G6_PLL(CV181X_CLK_TPLL, "clk_tpll", cv181x_pll_parent, REG_TPLL_CSR, 0),
|
|
CLK_G6_PLL(CV181X_CLK_FPLL, "clk_fpll", cv181x_pll_parent, REG_FPLL_CSR, 0),
|
|
CLK_G2_PLL(CV181X_CLK_MIPIMPLL, "clk_mipimpll", cv181x_pll_parent, REG_MIPIMPLL_CSR, 0, 0),
|
|
CLK_G2_PLL(CV181X_CLK_A0PLL, "clk_a0pll", cv181x_frac_pll_parent, REG_APLL0_CSR, REG_APLL_SSC_SYN_CTRL, 0),
|
|
CLK_G2_PLL(CV181X_CLK_DISPPLL, "clk_disppll", cv181x_frac_pll_parent, REG_DISPPLL_CSR,
|
|
REG_DISPPLL_SSC_SYN_CTRL, 0),
|
|
CLK_G2_PLL(CV181X_CLK_CAM0PLL, "clk_cam0pll", cv181x_frac_pll_parent, REG_CAM0PLL_CSR, REG_CAM0PLL_SSC_SYN_CTRL,
|
|
CLK_IGNORE_UNUSED),
|
|
CLK_G2_PLL(CV181X_CLK_CAM1PLL, "clk_cam1pll", cv181x_frac_pll_parent, REG_CAM1PLL_CSR,
|
|
REG_CAM1PLL_SSC_SYN_CTRL, 0),
|
|
CLK_G2D_PLL(CV181X_CLK_MIPIMPLL_D3, "clk_mipimpll_d3", cv181x_pll_parent, REG_MIPIMPLL_CSR,
|
|
0, 3, CLK_IGNORE_UNUSED),
|
|
CLK_G2D_PLL(CV181X_CLK_CAM0PLL_D2, "clk_cam0pll_d2", cv181x_frac_pll_parent, REG_CAM0PLL_CSR,
|
|
REG_CAM0PLL_SSC_SYN_CTRL, 2, CLK_IGNORE_UNUSED),
|
|
CLK_G2D_PLL(CV181X_CLK_CAM0PLL_D3, "clk_cam0pll_d3", cv181x_frac_pll_parent, REG_CAM0PLL_CSR,
|
|
REG_CAM0PLL_SSC_SYN_CTRL, 3, CLK_IGNORE_UNUSED),
|
|
};
|
|
|
|
/*
|
|
* Clocks marked as CRITICAL are needed for the proper functioning
|
|
* of the SoC.
|
|
*/
|
|
static struct cv181x_hw_clock cv181x_clks[] = {
|
|
CV181X_CLK(CV181X_CLK_A53, "clk_a53",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_tpll", "clk_a0pll", "clk_mipimpll", "clk_mpll"}),
|
|
REG_CLK_EN_0, 0,
|
|
REG_DIV_CLK_A53_0, 16, 4, 1,
|
|
REG_DIV_CLK_A53_1, 16, 4, 2,
|
|
REG_CLK_BYP_0, 0,
|
|
REG_CLK_SEL_0, 0,
|
|
REG_DIV_CLK_A53_0, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CPU_AXI0, "clk_cpu_axi0",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_disppll"}),
|
|
REG_CLK_EN_0, 1,
|
|
REG_DIV_CLK_CPU_AXI0, 16, 4, 3,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 1,
|
|
0, -1,
|
|
REG_DIV_CLK_CPU_AXI0, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CPU_GIC, "clk_cpu_gic",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_0, 2,
|
|
REG_DIV_CLK_CPU_GIC, 16, 4, 5,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 2,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_XTAL_A53, "clk_xtal_a53",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 3,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TPU, "clk_tpu",
|
|
((const char *[]) {"osc", "clk_tpll", "clk_a0pll", "clk_mipimpll", "clk_fpll"}),
|
|
REG_CLK_EN_0, 4,
|
|
REG_DIV_CLK_TPU, 16, 4, 3,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 3,
|
|
0, -1,
|
|
REG_DIV_CLK_TPU, 8,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_TPU_FAB, "clk_tpu_fab",
|
|
((const char *[]) {"osc", "clk_mipimpll"}),
|
|
REG_CLK_EN_0, 5,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 4,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_AHB_ROM, "clk_ahb_rom",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_0, 6,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_DDR_AXI_REG, "clk_ddr_axi_reg",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_0, 7,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_RTC_25M, "clk_rtc_25m",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 8,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TEMPSEN, "clk_tempsen",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 9,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_SARADC, "clk_saradc",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 10,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_EFUSE, "clk_efuse",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 11,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_APB_EFUSE, "clk_apb_efuse",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 12,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_DEBUG, "clk_debug",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 13,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_XTAL_MISC, "clk_xtal_misc",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_0, 14,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI4_EMMC, "clk_axi4_emmc",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_0, 15,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_EMMC, "clk_emmc",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_disppll"}),
|
|
REG_CLK_EN_0, 16,
|
|
REG_DIV_CLK_EMMC, 16, 5, 15,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 5,
|
|
0, -1,
|
|
REG_DIV_CLK_EMMC, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_100K_EMMC, "clk_100k_emmc",
|
|
((const char *[]) {"clk_1m"}),
|
|
REG_CLK_EN_0, 17,
|
|
REG_DIV_CLK_100K_EMMC, 16, 8, 10,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI4_SD0, "clk_axi4_sd0",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_0, 18,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SD0, "clk_sd0",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_disppll"}),
|
|
REG_CLK_EN_0, 19,
|
|
REG_DIV_CLK_SD0, 16, 5, 15,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 6,
|
|
0, -1,
|
|
REG_DIV_CLK_SD0, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_100K_SD0, "clk_100k_sd0",
|
|
((const char *[]) {"clk_1m"}),
|
|
REG_CLK_EN_0, 20,
|
|
REG_DIV_CLK_100K_SD0, 16, 8, 10,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI4_SD1, "clk_axi4_sd1",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_0, 21,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SD1, "clk_sd1",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_disppll"}),
|
|
REG_CLK_EN_0, 22,
|
|
REG_DIV_CLK_SD1, 16, 5, 15,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 7,
|
|
0, -1,
|
|
REG_DIV_CLK_SD1, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_100K_SD1, "clk_100k_sd1",
|
|
((const char *[]) {"clk_1m"}),
|
|
REG_CLK_EN_0, 23,
|
|
REG_DIV_CLK_100K_SD1, 16, 8, 10,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SPI_NAND, "clk_spi_nand",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_disppll"}),
|
|
REG_CLK_EN_0, 24,
|
|
REG_DIV_CLK_SPI_NAND, 16, 5, 8,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 8,
|
|
0, -1,
|
|
REG_DIV_CLK_SPI_NAND, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_500M_ETH0, "clk_500m_eth0",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_0, 25,
|
|
REG_DIV_CLK_500M_ETH0, 16, 4, 3,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 9,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI4_ETH0, "clk_axi4_eth0",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_0, 26,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_500M_ETH1, "clk_500m_eth1",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_0, 27,
|
|
REG_DIV_CLK_500M_ETH1, 16, 4, 3,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 10,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI4_ETH1, "clk_axi4_eth1",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_0, 28,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_GPIO, "clk_apb_gpio",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_0, 29,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_GPIO_INTR, "clk_apb_gpio_intr",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_0, 30,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_GPIO_DB, "clk_gpio_db",
|
|
((const char *[]) {"clk_1m"}),
|
|
REG_CLK_EN_0, 31,
|
|
REG_DIV_CLK_GPIO_DB, 16, 16, 10,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AHB_SF, "clk_ahb_sf",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 0,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SDMA_AXI, "clk_sdma_axi",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 1,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_SDMA_AUD0, "clk_sdma_aud0",
|
|
((const char *[]) {"osc", "clk_a0pll", "a24k_clk"}),
|
|
REG_CLK_EN_1, 2,
|
|
REG_DIV_CLK_SDMA_AUD0, 16, 8, 18,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 11,
|
|
0, -1,
|
|
REG_DIV_CLK_SDMA_AUD0, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SDMA_AUD1, "clk_sdma_aud1",
|
|
((const char *[]) {"osc", "clk_a0pll", "a24k_clk"}),
|
|
REG_CLK_EN_1, 3,
|
|
REG_DIV_CLK_SDMA_AUD1, 16, 8, 18,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 12,
|
|
0, -1,
|
|
REG_DIV_CLK_SDMA_AUD1, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SDMA_AUD2, "clk_sdma_aud2",
|
|
((const char *[]) {"osc", "clk_a0pll", "a24k_clk"}),
|
|
REG_CLK_EN_1, 4,
|
|
REG_DIV_CLK_SDMA_AUD2, 16, 8, 18,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 13,
|
|
0, -1,
|
|
REG_DIV_CLK_SDMA_AUD2, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SDMA_AUD3, "clk_sdma_aud3",
|
|
((const char *[]) {"osc", "clk_a0pll", "a24k_clk"}),
|
|
REG_CLK_EN_1, 5,
|
|
REG_DIV_CLK_SDMA_AUD3, 16, 8, 18,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 14,
|
|
0, -1,
|
|
REG_DIV_CLK_SDMA_AUD3, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2C, "clk_apb_i2c",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 6,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_WDT, "clk_apb_wdt",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_1, 7,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_PWM, "clk_pwm",
|
|
((const char *[]) {"clk_pwm_src"}),
|
|
REG_CLK_EN_1, 8,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_SPI0, "clk_apb_spi0",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 9,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_SPI1, "clk_apb_spi1",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 10,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_SPI2, "clk_apb_spi2",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 11,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_SPI3, "clk_apb_spi3",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 12,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CAM0_200, "clk_cam0_200",
|
|
((const char *[]) {"osc", "osc", "clk_disppll"}),
|
|
REG_CLK_EN_1, 13,
|
|
REG_DIV_CLK_CAM0_200, 16, 4, 1,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 16,
|
|
0, -1,
|
|
REG_DIV_CLK_CAM0_200, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_UART0, "clk_uart0",
|
|
((const char *[]) {"clk_cam0_200"}),
|
|
REG_CLK_EN_1, 14,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_UART0, "clk_apb_uart0",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 15,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_UART1, "clk_uart1",
|
|
((const char *[]) {"clk_cam0_200"}),
|
|
REG_CLK_EN_1, 16,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_UART1, "clk_apb_uart1",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 17,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_UART2, "clk_uart2",
|
|
((const char *[]) {"clk_cam0_200"}),
|
|
REG_CLK_EN_1, 18,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_UART2, "clk_apb_uart2",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 19,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_UART3, "clk_uart3",
|
|
((const char *[]) {"clk_cam0_200"}),
|
|
REG_CLK_EN_1, 20,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_UART3, "clk_apb_uart3",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 21,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_UART4, "clk_uart4",
|
|
((const char *[]) {"clk_cam0_200"}),
|
|
REG_CLK_EN_1, 22,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_UART4, "clk_apb_uart4",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 23,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2S0, "clk_apb_i2s0",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 24,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2S1, "clk_apb_i2s1",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 25,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2S2, "clk_apb_i2s2",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 26,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2S3, "clk_apb_i2s3",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 27,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI4_USB, "clk_axi4_usb",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 28,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_APB_USB, "clk_apb_usb",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_1, 29,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_125M_USB, "clk_125m_usb",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_1, 30,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 17,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_33K_USB, "clk_33k_usb",
|
|
((const char *[]) {"clk_1m"}),
|
|
REG_CLK_EN_1, 31,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_12M_USB, "clk_12m_usb",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_2, 0,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 18,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_AXI4, "clk_axi4",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_disppll"}),
|
|
REG_CLK_EN_2, 1,
|
|
REG_DIV_CLK_AXI4, 16, 4, 5,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 19,
|
|
0, -1,
|
|
REG_DIV_CLK_AXI4, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI6, "clk_axi6",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_2, 2,
|
|
REG_DIV_CLK_AXI6, 16, 4, 15,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 20,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_DSI_ESC, "clk_dsi_esc",
|
|
((const char *[]) {"osc", "clk_axi6"}),
|
|
REG_CLK_EN_2, 3,
|
|
REG_DIV_CLK_DSI_ESC, 16, 4, 5,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 21,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_AXI_VIP, "clk_axi_vip",
|
|
((const char *[]) {"osc", "clk_mipimpll", "clk_cam0pll", "clk_disppll", "clk_fpll"}),
|
|
REG_CLK_EN_2, 4,
|
|
REG_DIV_CLK_AXI_VIP, 16, 4, 3,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 22,
|
|
0, -1,
|
|
REG_DIV_CLK_AXI_VIP, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_SRC_VIP_SYS_0, "clk_src_vip_sys_0",
|
|
((const char *[]) {"osc", "clk_mipimpll", "clk_cam0pll", "clk_disppll", "clk_fpll"}),
|
|
REG_CLK_EN_2, 5,
|
|
REG_DIV_CLK_SRC_VIP_SYS_0, 16, 4, 6,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 23,
|
|
0, -1,
|
|
REG_DIV_CLK_SRC_VIP_SYS_0, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_SRC_VIP_SYS_1, "clk_src_vip_sys_1",
|
|
((const char *[]) {"osc", "clk_mipimpll", "clk_cam0pll", "clk_disppll", "clk_fpll"}),
|
|
REG_CLK_EN_2, 6,
|
|
REG_DIV_CLK_SRC_VIP_SYS_1, 16, 4, 5,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 24,
|
|
0, -1,
|
|
REG_DIV_CLK_SRC_VIP_SYS_1, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_DISP_SRC_VIP, "clk_disp_src_vip",
|
|
((const char *[]) {"osc", "clk_disppll"}),
|
|
REG_CLK_EN_2, 7,
|
|
REG_DIV_CLK_DISP_SRC_VIP, 16, 4, 8,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 25,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_AXI_VIDEO_CODEC, "clk_axi_video_codec",
|
|
((const char *[]) {"osc", "clk_a0pll", "clk_mipimpll", "clk_cam1pll", "clk_fpll"}),
|
|
REG_CLK_EN_2, 8,
|
|
REG_DIV_CLK_AXI_VIDEO_CODEC, 16, 4, 2,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 26,
|
|
0, -1,
|
|
REG_DIV_CLK_AXI_VIDEO_CODEC, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_VC_SRC0, "clk_vc_src0",
|
|
((const char *[]) {"osc", "clk_disppll", "clk_mipimpll", "clk_cam1pll", "clk_fpll"}),
|
|
REG_CLK_EN_2, 9,
|
|
REG_DIV_CLK_VC_SRC0, 16, 4, 2,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 27,
|
|
0, -1,
|
|
REG_DIV_CLK_VC_SRC0, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_H264C, "clk_h264c",
|
|
((const char *[]) {"clk_axi_video_codec"}),
|
|
REG_CLK_EN_2, 10,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_H265C, "clk_h265c",
|
|
((const char *[]) {"clk_axi_video_codec"}),
|
|
REG_CLK_EN_2, 11,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_JPEG, "clk_jpeg",
|
|
((const char *[]) {"clk_axi_video_codec"}),
|
|
REG_CLK_EN_2, 12,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_APB_JPEG, "clk_apb_jpeg",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_2, 13,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_APB_H264C, "clk_apb_h264c",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_2, 14,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_APB_H265C, "clk_apb_h265c",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_2, 15,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_CAM0, "clk_cam0",
|
|
((const char *[]) {"clk_cam0pll", "clk_cam0pll_d2", "clk_cam0pll_d3", "clk_mipimpll_d3"}),
|
|
REG_CLK_EN_2, 16,
|
|
REG_CLK_CAM0_SRC_DIV, 16, 6, -1,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
REG_CLK_CAM0_SRC_DIV, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_CAM1, "clk_cam1",
|
|
((const char *[]) {"clk_cam0pll", "clk_cam0pll_d2", "clk_cam0pll_d3", "clk_mipimpll_d3"}),
|
|
REG_CLK_EN_2, 17,
|
|
REG_CLK_CAM1_SRC_DIV, 16, 6, -1,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
REG_CLK_CAM1_SRC_DIV, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_CSI_MAC0_VIP, "clk_csi_mac0_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 18,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_CSI_MAC1_VIP, "clk_csi_mac1_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 19,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_ISP_TOP_VIP, "clk_isp_top_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 20,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_IMG_D_VIP, "clk_img_d_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 21,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_IMG_V_VIP, "clk_img_v_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 22,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_SC_TOP_VIP, "clk_sc_top_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 23,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_SC_D_VIP, "clk_sc_d_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 24,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_SC_V1_VIP, "clk_sc_v1_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 25,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_SC_V2_VIP, "clk_sc_v2_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 26,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_SC_V3_VIP, "clk_sc_v3_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 27,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_DWA_VIP, "clk_dwa_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 28,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_BT_VIP, "clk_bt_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 29,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_DISP_VIP, "clk_disp_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 30,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_DSI_MAC_VIP, "clk_dsi_mac_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_2, 31,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_LVDS0_VIP, "clk_lvds0_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_3, 0,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_LVDS1_VIP, "clk_lvds1_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_3, 1,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CSI0_RX_VIP, "clk_csi0_rx_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_3, 2,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CSI1_RX_VIP, "clk_csi1_rx_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_3, 3,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_PAD_VI_VIP, "clk_pad_vi_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_3, 4,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_1M, "clk_1m",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_3, 5,
|
|
REG_DIV_CLK_1M, 16, 6, 25,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SPI, "clk_spi",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_3, 6,
|
|
REG_DIV_CLK_SPI, 16, 6, 8,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 30,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_I2C, "clk_i2c",
|
|
((const char *[]) {"osc", "clk_axi6"}),
|
|
REG_CLK_EN_3, 7,
|
|
REG_DIV_CLK_I2C, 16, 4, 1,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 31,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_PM, "clk_pm",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_3, 8,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER0, "clk_timer0",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 9,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER1, "clk_timer1",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 10,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER2, "clk_timer2",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 11,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER3, "clk_timer3",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 12,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER4, "clk_timer4",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 13,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER5, "clk_timer5",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 14,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER6, "clk_timer6",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 15,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_TIMER7, "clk_timer7",
|
|
((const char *[]) {"clk_xtal_misc"}),
|
|
REG_CLK_EN_3, 16,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2C0, "clk_apb_i2c0",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_3, 17,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2C1, "clk_apb_i2c1",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_3, 18,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2C2, "clk_apb_i2c2",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_3, 19,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2C3, "clk_apb_i2c3",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_3, 20,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_I2C4, "clk_apb_i2c4",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_3, 21,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_WGN, "clk_wgn",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_3, 22,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_WGN0, "clk_wgn0",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_3, 23,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_WGN1, "clk_wgn1",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_3, 24,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_WGN2, "clk_wgn2",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_3, 25,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_KEYSCAN, "clk_keyscan",
|
|
((const char *[]) {"osc"}),
|
|
REG_CLK_EN_3, 26,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_AHB_SF1, "clk_ahb_sf1",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_3, 27,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_VC_SRC1, "clk_vc_src1",
|
|
((const char *[]) {"osc", "clk_cam1pll"}),
|
|
REG_CLK_EN_3, 28,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_SRC_VIP_SYS_2, "clk_src_vip_sys_2",
|
|
((const char *[]) {"osc", "clk_mipimpll", "clk_cam0pll", "clk_disppll", "clk_fpll"}),
|
|
REG_CLK_EN_3, 29,
|
|
REG_DIV_CLK_SRC_VIP_SYS_2, 16, 4, 2,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 1,
|
|
0, -1,
|
|
REG_DIV_CLK_SRC_VIP_SYS_2, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_PAD_VI1_VIP, "clk_pad_vi1_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_3, 30,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CFG_REG_VIP, "clk_cfg_reg_vip",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_3, 31,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CFG_REG_VC, "clk_cfg_reg_vc",
|
|
((const char *[]) {"clk_axi6"}),
|
|
REG_CLK_EN_4, 0,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_AUDSRC, "clk_audsrc",
|
|
((const char *[]) {"osc", "clk_a0pll", "a24k_clk"}),
|
|
REG_CLK_EN_4, 1,
|
|
REG_DIV_CLK_AUDSRC, 16, 8, 18,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 2,
|
|
0, -1,
|
|
REG_DIV_CLK_AUDSRC, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_APB_AUDSRC, "clk_apb_audsrc",
|
|
((const char *[]) {"clk_axi4"}),
|
|
REG_CLK_EN_4, 2,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_VC_SRC2, "clk_vc_src2",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_4, 3,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 3,
|
|
0, -1,
|
|
0, -1,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_PWM_SRC, "clk_pwm_src",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_disppll"}),
|
|
REG_CLK_EN_4, 4,
|
|
REG_DIV_CLK_PWM_SRC_0, 16, 6, 10,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_0, 15,
|
|
0, -1,
|
|
REG_DIV_CLK_PWM_SRC_0, 8,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_AP_DEBUG, "clk_ap_debug",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_4, 5,
|
|
REG_DIV_CLK_AP_DEBUG, 16, 4, 5,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 4,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SRC_RTC_SYS_0, "clk_src_rtc_sys_0",
|
|
((const char *[]) {"osc", "clk_fpll"}),
|
|
REG_CLK_EN_4, 6,
|
|
REG_DIV_CLK_RTCSYS_SRC_0, 16, 4, 5,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 5,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_PAD_VI2_VIP, "clk_pad_vi2_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 7,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CSI_BE_VIP, "clk_csi_be_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 8,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_VIP_IP0, "clk_vip_ip0",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 9,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_VIP_IP1, "clk_vip_ip1",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 10,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_VIP_IP2, "clk_vip_ip2",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 11,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_VIP_IP3, "clk_vip_ip3",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 12,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_C906_0, "clk_c906_0",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_tpll", "clk_a0pll", "clk_mipimpll", "clk_mpll"}),
|
|
REG_CLK_EN_4, 13,
|
|
REG_DIV_CLK_C906_0_0, 16, 4, 1,
|
|
REG_DIV_CLK_C906_0_1, 16, 4, 2,
|
|
REG_CLK_BYP_1, 6,
|
|
REG_CLK_SEL_0, 23,
|
|
REG_DIV_CLK_C906_0_0, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_C906_1, "clk_c906_1",
|
|
((const char *[]) {"osc", "clk_fpll", "clk_tpll", "clk_a0pll", "clk_disppll", "clk_mpll"}),
|
|
REG_CLK_EN_4, 14,
|
|
REG_DIV_CLK_C906_1_0, 16, 4, 2,
|
|
REG_DIV_CLK_C906_1_1, 16, 4, 2,
|
|
REG_CLK_BYP_1, 7,
|
|
REG_CLK_SEL_0, 24,
|
|
REG_DIV_CLK_C906_1_0, 8,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_SRC_VIP_SYS_3, "clk_src_vip_sys_3",
|
|
((const char *[]) {"osc", "clk_mipimpll", "clk_cam0pll", "clk_disppll", "clk_fpll"}),
|
|
REG_CLK_EN_4, 15,
|
|
REG_DIV_CLK_SRC_VIP_SYS_3, 16, 4, 2,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 8,
|
|
0, -1,
|
|
REG_DIV_CLK_SRC_VIP_SYS_3, 8,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_SRC_VIP_SYS_4, "clk_src_vip_sys_4",
|
|
((const char *[]) {"osc", "clk_mipimpll", "clk_cam0pll", "clk_disppll", "clk_fpll"}),
|
|
REG_CLK_EN_4, 16,
|
|
REG_DIV_CLK_SRC_VIP_SYS_4, 16, 4, 3,
|
|
0, -1, 0, 0,
|
|
REG_CLK_BYP_1, 9,
|
|
0, -1,
|
|
REG_DIV_CLK_SRC_VIP_SYS_4, 8,
|
|
0),
|
|
CV181X_CLK(CV181X_CLK_IVE_VIP, "clk_ive_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 17,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_RAW_VIP, "clk_raw_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 18,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_OSDC_VIP, "clk_osdc_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 19,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
CV181X_CLK(CV181X_CLK_CSI_MAC2_VIP, "clk_csi_mac2_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 20,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IGNORE_UNUSED),
|
|
CV181X_CLK(CV181X_CLK_CAM0_VIP, "clk_cam0_vip",
|
|
((const char *[]) {"clk_axi_vip"}),
|
|
REG_CLK_EN_4, 21,
|
|
0, -1, 0, 0,
|
|
0, -1, 0, 0,
|
|
0, -1,
|
|
0, -1,
|
|
0, -1,
|
|
CLK_IS_CRITICAL),
|
|
};
|
|
|
|
static int __init cvi_clk_flags_setup(char *arg)
|
|
{
|
|
int ret;
|
|
unsigned long flags;
|
|
|
|
ret = kstrtol(arg, 0, &flags);
|
|
if (ret)
|
|
return ret;
|
|
|
|
cvi_clk_flags = flags;
|
|
pr_info("cvi_clk_flags = 0x%lX\n", cvi_clk_flags);
|
|
|
|
return 1;
|
|
}
|
|
__setup("cvi_clk_flags=", cvi_clk_flags_setup);
|
|
|
|
static unsigned long cv181x_pll_rate_calc(u32 regval, s16 post_div_sel, unsigned long parent_rate)
|
|
{
|
|
u64 numerator;
|
|
u32 predivsel, postdivsel, divsel;
|
|
u32 denominator;
|
|
|
|
predivsel = regval & 0x7f;
|
|
postdivsel = post_div_sel < 0 ? (regval >> 8) & 0x7f : (u32)post_div_sel;
|
|
divsel = (regval >> 17) & 0x7f;
|
|
|
|
numerator = parent_rate * divsel;
|
|
denominator = predivsel * postdivsel;
|
|
do_div(numerator, denominator);
|
|
|
|
return (unsigned long)numerator;
|
|
}
|
|
|
|
static unsigned long cv181x_g6_pll_recalc_rate(struct clk_hw *hw,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct cv181x_pll_hw_clock *pll_hw = to_cv181x_pll_clk(hw);
|
|
unsigned long rate;
|
|
u32 regval;
|
|
|
|
regval = readl(pll_hw->base + pll_hw->pll.reg_csr);
|
|
rate = cv181x_pll_rate_calc(regval, pll_hw->pll.post_div_sel, parent_rate);
|
|
|
|
return rate;
|
|
}
|
|
|
|
static long cv181x_g6_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long *prate)
|
|
{
|
|
return rate;
|
|
}
|
|
|
|
static int cv181x_g6_pll_calc_csr(unsigned long parent_rate, unsigned long rate, u32 *csr)
|
|
{
|
|
u64 numerator;
|
|
u32 denominator;
|
|
u32 divsel; /* [23:17] DIV_SEL */
|
|
u32 postdivsel = 1; /* [14:8] POST_DIV_SEL */
|
|
u32 ictrl = 7; /* [26:24] ICTRL */
|
|
u32 selmode = 1; /* [16:15] SEL_MODE */
|
|
u32 predivsel = 1; /* [6:0] PRE_DIV_SEL */
|
|
u32 vco_clks[] = {900, 1000, 1100, 1200, 1300, 1400, 1500, 1600};
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(vco_clks); i++) {
|
|
if ((vco_clks[i] * 1000000) % rate == 0) {
|
|
postdivsel = vco_clks[i] * 1000000 / rate;
|
|
rate = vco_clks[i] * 1000000;
|
|
pr_debug("rate=%ld, postdivsel=%d\n", rate, postdivsel);
|
|
break;
|
|
}
|
|
}
|
|
|
|
numerator = rate;
|
|
denominator = parent_rate;
|
|
|
|
do_div(numerator, denominator);
|
|
|
|
divsel = (u32)numerator & 0x7f;
|
|
*csr = (divsel << 17) | (postdivsel << 8) | (ictrl << 24) | (selmode << 15) | predivsel;
|
|
|
|
pr_debug("csr=0x%08x\n", *csr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cv181x_g6_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct cv181x_pll_hw_clock *pll_hw = to_cv181x_pll_clk(hw);
|
|
unsigned long flags = 0;
|
|
int ret;
|
|
u32 reg_g6_pll_status;
|
|
u32 regval_csr;
|
|
u32 regval_g6_pll_status;
|
|
u32 g6_pll_update_status = 0;
|
|
ktime_t timeout;
|
|
|
|
reg_g6_pll_status = (pll_hw->pll.reg_csr & ~PLL_STATUS_MASK) + PLL_STATUS_OFFSET;
|
|
|
|
if (pll_hw->lock)
|
|
spin_lock_irqsave(pll_hw->lock, flags);
|
|
else
|
|
__acquire(pll_hw->lock);
|
|
|
|
/* calculate csr register */
|
|
ret = cv181x_g6_pll_calc_csr(parent_rate, rate, ®val_csr);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
/* csr register */
|
|
writel(regval_csr, pll_hw->base + pll_hw->pll.reg_csr);
|
|
|
|
if (pll_hw->pll.reg_csr == REG_MPLL_CSR)
|
|
g6_pll_update_status = BIT(0);
|
|
else if (pll_hw->pll.reg_csr == REG_TPLL_CSR)
|
|
g6_pll_update_status = BIT(1);
|
|
else if (pll_hw->pll.reg_csr == REG_FPLL_CSR)
|
|
g6_pll_update_status = BIT(2);
|
|
|
|
/* wait for pll setting updated */
|
|
timeout = ktime_add_ms(ktime_get(), CV181X_PLL_LOCK_TIMEOUT_MS);
|
|
while (1) {
|
|
regval_g6_pll_status = readl(pll_hw->base + reg_g6_pll_status);
|
|
if ((regval_g6_pll_status & g6_pll_update_status) == 0)
|
|
break;
|
|
|
|
if (ktime_after(ktime_get(), timeout)) {
|
|
pr_err("timeout waiting for pll update, g6_pll_status = 0x%08x\n",
|
|
regval_g6_pll_status);
|
|
break;
|
|
}
|
|
cpu_relax();
|
|
}
|
|
|
|
if (pll_hw->lock)
|
|
spin_unlock_irqrestore(pll_hw->lock, flags);
|
|
else
|
|
__release(pll_hw->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct clk_ops cv181x_g6_pll_ops = {
|
|
.recalc_rate = cv181x_g6_pll_recalc_rate,
|
|
.round_rate = cv181x_g6_pll_round_rate,
|
|
.set_rate = cv181x_g6_pll_set_rate,
|
|
};
|
|
|
|
static unsigned long cv181x_g2_pll_recalc_rate(struct clk_hw *hw,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct cv181x_pll_hw_clock *pll_hw = to_cv181x_pll_clk(hw);
|
|
u32 reg_ssc_set;
|
|
u32 reg_g2_ssc_ctrl;
|
|
u32 regval_csr;
|
|
u32 regval_ssc_set;
|
|
u32 regval_g2_ssc_ctrl;
|
|
u64 numerator;
|
|
u32 denominator;
|
|
unsigned long clk_ref;
|
|
unsigned long rate;
|
|
|
|
regval_csr = readl(pll_hw->base + pll_hw->pll.reg_csr);
|
|
|
|
/* pll without synthesizer */
|
|
if (pll_hw->pll.reg_ssc == 0) {
|
|
clk_ref = parent_rate;
|
|
goto rate_calc;
|
|
}
|
|
|
|
/* calculate synthesizer freq */
|
|
reg_ssc_set = (pll_hw->pll.reg_ssc & ~SSC_SYN_SET_MASK) + SSC_SYN_SET_OFFSET;
|
|
reg_g2_ssc_ctrl = (pll_hw->pll.reg_ssc & ~G2_SSC_CTRL_MASK) + G2_SSC_CTRL_OFFSET;
|
|
|
|
regval_ssc_set = readl(pll_hw->base + reg_ssc_set);
|
|
regval_g2_ssc_ctrl = readl(pll_hw->base + reg_g2_ssc_ctrl);
|
|
|
|
/* bit0 sel_syn_clk */
|
|
numerator = (regval_g2_ssc_ctrl & 0x1) ? parent_rate : (parent_rate >> 1);
|
|
|
|
numerator <<= 26;
|
|
denominator = regval_ssc_set;
|
|
if (denominator)
|
|
do_div(numerator, denominator);
|
|
else
|
|
pr_err("pll ssc_set is zero\n");
|
|
|
|
clk_ref = numerator;
|
|
|
|
rate_calc:
|
|
rate = cv181x_pll_rate_calc(regval_csr, pll_hw->pll.post_div_sel, clk_ref);
|
|
|
|
return rate;
|
|
}
|
|
|
|
static const struct {
|
|
unsigned long rate;
|
|
u32 csr;
|
|
u32 ssc_set;
|
|
} g2_pll_rate_lut[] = {
|
|
// {.rate = 48000000, .csr = 0x00129201, .ssc_set = 629145600},
|
|
// {.rate = 406425600, .csr = 0x010E9201, .ssc_set = 594430839},
|
|
// {.rate = 417792000, .csr = 0x01109201, .ssc_set = 642509804},
|
|
// {.rate = 768000000, .csr = 0x00108101, .ssc_set = 419430400},
|
|
// {.rate = 832000000, .csr = 0x00108101, .ssc_set = 387166523},
|
|
// {.rate = 1032000000, .csr = 0x00148101, .ssc_set = 390167814},
|
|
// {.rate = 1050000000, .csr = 0x00168101, .ssc_set = 421827145},
|
|
// {.rate = 1056000000, .csr = 0x00208100, .ssc_set = 412977625},
|
|
// {.rate = 1125000000, .csr = 0x00168101, .ssc_set = 393705325},
|
|
// {.rate = 1188000000, .csr = 0x00188101, .ssc_set = 610080582}, //postdiv=1
|
|
{.rate = 1188000000, .csr = 0x00308201, .ssc_set = 610080582}, //postdiv=2
|
|
};
|
|
|
|
static int cv181x_g2_pll_get_setting_from_lut(unsigned long rate, u32 *csr,
|
|
u32 *ssc_set)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(g2_pll_rate_lut); i++) {
|
|
if (rate == g2_pll_rate_lut[i].rate) {
|
|
*csr = g2_pll_rate_lut[i].csr;
|
|
*ssc_set = g2_pll_rate_lut[i].ssc_set;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
*csr = 0;
|
|
*ssc_set = 0;
|
|
return -ENOENT;
|
|
}
|
|
|
|
static long cv181x_g2_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long *prate)
|
|
{
|
|
return rate;
|
|
}
|
|
|
|
static int cv181x_g2_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct cv181x_pll_hw_clock *pll_hw = to_cv181x_pll_clk(hw);
|
|
unsigned long flags = 0;
|
|
int ret;
|
|
u32 reg_ssc_set;
|
|
u32 reg_ssc_ctrl;
|
|
u32 reg_g2_pll_status;
|
|
u32 regval_csr;
|
|
u32 regval_ssc_set;
|
|
u32 regval_ssc_ctrl;
|
|
u32 regval_g2_pll_status;
|
|
u32 g2_pll_update_status = 0;
|
|
ktime_t timeout;
|
|
|
|
/* pll without synthesizer */
|
|
if (pll_hw->pll.reg_ssc == 0)
|
|
return -ENOENT;
|
|
|
|
ret = cv181x_g2_pll_get_setting_from_lut(rate, ®val_csr,
|
|
®val_ssc_set);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
reg_ssc_set = (pll_hw->pll.reg_ssc & ~SSC_SYN_SET_MASK) + SSC_SYN_SET_OFFSET;
|
|
reg_ssc_ctrl = pll_hw->pll.reg_ssc;
|
|
reg_g2_pll_status = (pll_hw->pll.reg_csr & ~PLL_STATUS_MASK) + PLL_STATUS_OFFSET;
|
|
|
|
if (pll_hw->lock)
|
|
spin_lock_irqsave(pll_hw->lock, flags);
|
|
else
|
|
__acquire(pll_hw->lock);
|
|
|
|
/* set synthersizer */
|
|
writel(regval_ssc_set, pll_hw->base + reg_ssc_set);
|
|
|
|
/* bit 0 toggle */
|
|
regval_ssc_ctrl = readl(pll_hw->base + reg_ssc_ctrl);
|
|
regval_ssc_ctrl ^= 0x00000001;
|
|
writel(regval_ssc_ctrl, pll_hw->base + reg_ssc_ctrl);
|
|
|
|
/* csr register */
|
|
writel(regval_csr, pll_hw->base + pll_hw->pll.reg_csr);
|
|
|
|
if (pll_hw->pll.reg_csr == REG_MIPIMPLL_CSR)
|
|
g2_pll_update_status = BIT(0);
|
|
else if (pll_hw->pll.reg_csr == REG_APLL0_CSR)
|
|
g2_pll_update_status = BIT(1);
|
|
else if (pll_hw->pll.reg_csr == REG_DISPPLL_CSR)
|
|
g2_pll_update_status = BIT(2);
|
|
else if (pll_hw->pll.reg_csr == REG_CAM0PLL_CSR)
|
|
g2_pll_update_status = BIT(3);
|
|
else if (pll_hw->pll.reg_csr == REG_CAM1PLL_CSR)
|
|
g2_pll_update_status = BIT(4);
|
|
|
|
/* wait for pll setting updated */
|
|
timeout = ktime_add_ms(ktime_get(), CV181X_PLL_LOCK_TIMEOUT_MS);
|
|
while (1) {
|
|
regval_g2_pll_status = readl(pll_hw->base + reg_g2_pll_status);
|
|
if ((regval_g2_pll_status & g2_pll_update_status) == 0)
|
|
break;
|
|
|
|
if (ktime_after(ktime_get(), timeout)) {
|
|
pr_err("timeout waiting for pll update, g2_pll_status = 0x%08x\n",
|
|
regval_g2_pll_status);
|
|
break;
|
|
}
|
|
cpu_relax();
|
|
}
|
|
|
|
if (pll_hw->lock)
|
|
spin_unlock_irqrestore(pll_hw->lock, flags);
|
|
else
|
|
__release(pll_hw->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct clk_ops cv181x_g2_pll_ops = {
|
|
.recalc_rate = cv181x_g2_pll_recalc_rate,
|
|
.round_rate = cv181x_g2_pll_round_rate,
|
|
.set_rate = cv181x_g2_pll_set_rate,
|
|
};
|
|
|
|
static const struct clk_ops cv181x_g2d_pll_ops = {
|
|
.recalc_rate = cv181x_g2_pll_recalc_rate,
|
|
};
|
|
|
|
static struct clk_hw *cv181x_clk_register_pll(struct cv181x_pll_hw_clock *pll_clk,
|
|
void __iomem *sys_base)
|
|
{
|
|
struct clk_hw *hw;
|
|
struct clk_init_data init;
|
|
int err;
|
|
|
|
pll_clk->lock = &cv181x_clk_lock;
|
|
pll_clk->base = sys_base;
|
|
|
|
if (cvi_clk_flags) {
|
|
/* copy clk_init_data for modification */
|
|
memcpy(&init, pll_clk->hw.init, sizeof(init));
|
|
|
|
init.flags |= cvi_clk_flags;
|
|
pll_clk->hw.init = &init;
|
|
}
|
|
|
|
hw = &pll_clk->hw;
|
|
|
|
err = clk_hw_register(NULL, hw);
|
|
if (err)
|
|
return ERR_PTR(err);
|
|
|
|
return hw;
|
|
}
|
|
|
|
static void cv181x_clk_unregister_pll(struct clk_hw *hw)
|
|
{
|
|
struct cv181x_pll_hw_clock *pll_hw = to_cv181x_pll_clk(hw);
|
|
|
|
clk_hw_unregister(hw);
|
|
kfree(pll_hw);
|
|
}
|
|
|
|
static int cv181x_clk_register_plls(struct cv181x_pll_hw_clock *clks,
|
|
int num_clks,
|
|
struct cv181x_clock_data *data)
|
|
{
|
|
struct clk_hw *hw;
|
|
void __iomem *pll_base = data->base;
|
|
int i;
|
|
|
|
for (i = 0; i < num_clks; i++) {
|
|
struct cv181x_pll_hw_clock *cv181x_clk = &clks[i];
|
|
|
|
hw = cv181x_clk_register_pll(cv181x_clk, pll_base);
|
|
if (IS_ERR(hw)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, cv181x_clk->pll.name);
|
|
goto err_clk;
|
|
}
|
|
|
|
data->hw_data.hws[clks[i].pll.id] = hw;
|
|
|
|
clk_hw_register_clkdev(hw, cv181x_clk->pll.name, NULL);
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_clk:
|
|
while (i--)
|
|
cv181x_clk_unregister_pll(data->hw_data.hws[clks[i].pll.id]);
|
|
|
|
return PTR_ERR(hw);
|
|
}
|
|
|
|
static int cv181x_clk_is_bypassed(struct cv181x_hw_clock *clk_hw)
|
|
{
|
|
u32 val;
|
|
void __iomem *reg_addr = clk_hw->base + clk_hw->mux[0].reg;
|
|
|
|
if (clk_hw->mux[0].shift >= 0) {
|
|
val = readl(reg_addr) >> clk_hw->mux[0].shift;
|
|
val &= 0x1; //width
|
|
} else {
|
|
val = 0;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
static int cv181x_clk_get_clk_sel(struct cv181x_hw_clock *clk_hw)
|
|
{
|
|
u32 val;
|
|
void __iomem *reg_addr = clk_hw->base + clk_hw->mux[1].reg;
|
|
|
|
if (clk_hw->mux[1].shift >= 0) {
|
|
val = readl(reg_addr) >> clk_hw->mux[1].shift;
|
|
val &= 0x1; //width
|
|
val ^= 0x1; //invert value
|
|
} else {
|
|
val = 0;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
static int cv181x_clk_get_src_sel(struct cv181x_hw_clock *clk_hw)
|
|
{
|
|
u32 val;
|
|
void __iomem *reg_addr = clk_hw->base + clk_hw->mux[2].reg;
|
|
|
|
if (clk_hw->mux[2].shift >= 0) {
|
|
val = readl(reg_addr) >> clk_hw->mux[2].shift;
|
|
val &= 0x3; //width
|
|
} else {
|
|
val = 0;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
static unsigned long cv181x_clk_div_recalc_rate(struct clk_hw *hw,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
unsigned int clk_sel = cv181x_clk_get_clk_sel(clk_hw);
|
|
void __iomem *reg_addr = clk_hw->base + clk_hw->div[clk_sel].reg;
|
|
unsigned int val;
|
|
unsigned long rate;
|
|
|
|
if ((clk_hw->mux[0].shift >= 0) && cv181x_clk_is_bypassed(clk_hw))
|
|
return parent_rate;
|
|
|
|
if ((clk_hw->div[clk_sel].initval > 0) && !(readl(reg_addr) & BIT(3))) {
|
|
val = clk_hw->div[clk_sel].initval;
|
|
} else {
|
|
val = readl(reg_addr) >> clk_hw->div[clk_sel].shift;
|
|
val &= div_mask(clk_hw->div[clk_sel].width);
|
|
}
|
|
rate = divider_recalc_rate(hw, parent_rate, val, NULL,
|
|
clk_hw->div[clk_sel].flags,
|
|
clk_hw->div[clk_sel].width);
|
|
|
|
return rate;
|
|
}
|
|
|
|
static long cv181x_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long *prate)
|
|
{
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
unsigned int clk_sel = cv181x_clk_get_clk_sel(clk_hw);
|
|
|
|
if ((clk_hw->mux[0].shift >= 0) && cv181x_clk_is_bypassed(clk_hw))
|
|
return DIV_ROUND_UP_ULL((u64)*prate, 1);
|
|
|
|
return divider_round_rate(hw, rate, prate, NULL,
|
|
clk_hw->div[clk_sel].width, clk_hw->div[clk_sel].flags);
|
|
}
|
|
|
|
static long cv181x_clk_div_calc_round_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long *prate)
|
|
{
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
|
|
if (clk_hw->div[0].shift > 0)
|
|
return divider_round_rate(hw, rate, prate, NULL,
|
|
clk_hw->div[0].width, clk_hw->div[0].flags);
|
|
else
|
|
return DIV_ROUND_UP_ULL((u64)*prate, 1);
|
|
}
|
|
|
|
static int cv181x_clk_div_determine_rate(struct clk_hw *hw,
|
|
struct clk_rate_request *req)
|
|
{
|
|
struct clk_hw *current_parent;
|
|
unsigned long parent_rate;
|
|
unsigned long best_delta;
|
|
unsigned long best_rate;
|
|
u32 parent_count;
|
|
long rate;
|
|
u32 which;
|
|
|
|
pr_debug("%s()_%d: req->rate=%ld\n", __func__, __LINE__, req->rate);
|
|
|
|
parent_count = clk_hw_get_num_parents(hw);
|
|
pr_debug("%s()_%d: parent_count=%d\n", __func__, __LINE__, parent_count);
|
|
|
|
if ((parent_count < 2) || (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT)) {
|
|
rate = cv181x_clk_div_round_rate(hw, req->rate, &req->best_parent_rate);
|
|
if (rate < 0)
|
|
return rate;
|
|
|
|
req->rate = rate;
|
|
return 0;
|
|
}
|
|
|
|
/* Unless we can do better, stick with current parent */
|
|
current_parent = clk_hw_get_parent(hw);
|
|
parent_rate = clk_hw_get_rate(current_parent);
|
|
best_rate = cv181x_clk_div_calc_round_rate(hw, req->rate, &parent_rate);
|
|
best_delta = abs(best_rate - req->rate);
|
|
|
|
pr_debug("%s()_%d: parent_rate=%ld, best_rate=%ld, best_delta=%ld\n",
|
|
__func__, __LINE__, parent_rate, best_rate, best_delta);
|
|
|
|
/* Check whether any other parent clock can produce a better result */
|
|
for (which = 0; which < parent_count; which++) {
|
|
struct clk_hw *parent = clk_hw_get_parent_by_index(hw, which);
|
|
unsigned long delta;
|
|
unsigned long other_rate;
|
|
|
|
pr_debug("%s()_%d: idx=%d, parent_rate=%ld, best_rate=%ld, best_delta=%ld\n",
|
|
__func__, __LINE__, which, parent_rate, best_rate, best_delta);
|
|
|
|
if (!parent)
|
|
continue;
|
|
|
|
if (parent == current_parent)
|
|
continue;
|
|
|
|
/* Not support CLK_SET_RATE_PARENT */
|
|
parent_rate = clk_hw_get_rate(parent);
|
|
other_rate = cv181x_clk_div_calc_round_rate(hw, req->rate, &parent_rate);
|
|
delta = abs(other_rate - req->rate);
|
|
pr_debug("%s()_%d: parent_rate=%ld, other_rate=%ld, delta=%ld\n",
|
|
__func__, __LINE__, parent_rate, other_rate, delta);
|
|
if (delta < best_delta) {
|
|
best_delta = delta;
|
|
best_rate = other_rate;
|
|
req->best_parent_hw = parent;
|
|
req->best_parent_rate = parent_rate;
|
|
pr_debug("%s()_%d: parent_rate=%ld, best_rate=%ld, best_delta=%ld\n",
|
|
__func__, __LINE__, parent_rate, best_rate, best_delta);
|
|
}
|
|
}
|
|
|
|
req->rate = best_rate;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cv181x_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
unsigned int clk_sel = cv181x_clk_get_clk_sel(clk_hw);
|
|
void __iomem *reg_addr = clk_hw->base + clk_hw->div[clk_sel].reg;
|
|
unsigned long flags = 0;
|
|
int value;
|
|
u32 val;
|
|
|
|
pr_debug("%s()_%d:%s, rate=%ld, parent_rate=%ld\n", __func__, __LINE__, clk_hw->name, rate, parent_rate);
|
|
|
|
if (clk_hw->div[clk_sel].shift < 0)
|
|
pr_err("Error: %s: div[%d].shift = %d\n", __func__, clk_sel, clk_hw->div[clk_sel].shift);
|
|
|
|
value = divider_get_val(rate, parent_rate, NULL,
|
|
clk_hw->div[clk_sel].width,
|
|
clk_hw->div[clk_sel].flags);
|
|
if (value < 0)
|
|
return value;
|
|
|
|
if (clk_hw->lock)
|
|
spin_lock_irqsave(clk_hw->lock, flags);
|
|
else
|
|
__acquire(clk_hw->lock);
|
|
|
|
val = readl(reg_addr);
|
|
val &= ~(div_mask(clk_hw->div[clk_sel].width) << clk_hw->div[clk_sel].shift);
|
|
val |= (u32)value << clk_hw->div[clk_sel].shift;
|
|
if (!(clk_hw->div[clk_sel].initval < 0))
|
|
val |= BIT(3);
|
|
writel(val, reg_addr);
|
|
|
|
if (clk_hw->lock)
|
|
spin_unlock_irqrestore(clk_hw->lock, flags);
|
|
else
|
|
__release(clk_hw->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cv181x_clk_gate_endisable(struct clk_hw *hw, int enable)
|
|
{
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
void __iomem *reg_addr = clk_hw->base + clk_hw->gate.reg;
|
|
unsigned long flags = 0;
|
|
u32 reg;
|
|
|
|
if (clk_hw->gate.shift < 0)
|
|
pr_err("Error: %s: gate.shift = %d\n", __func__, clk_hw->gate.shift);
|
|
|
|
if (clk_hw->lock)
|
|
spin_lock_irqsave(clk_hw->lock, flags);
|
|
else
|
|
__acquire(clk_hw->lock);
|
|
|
|
reg = readl(reg_addr);
|
|
|
|
if (enable)
|
|
reg |= BIT(clk_hw->gate.shift);
|
|
else
|
|
reg &= ~BIT(clk_hw->gate.shift);
|
|
|
|
writel(reg, reg_addr);
|
|
|
|
if (clk_hw->lock)
|
|
spin_unlock_irqrestore(clk_hw->lock, flags);
|
|
else
|
|
__release(clk_hw->lock);
|
|
}
|
|
|
|
static int cv181x_clk_gate_enable(struct clk_hw *hw)
|
|
{
|
|
cv181x_clk_gate_endisable(hw, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cv181x_clk_gate_disable(struct clk_hw *hw)
|
|
{
|
|
cv181x_clk_gate_endisable(hw, 0);
|
|
}
|
|
|
|
static int cv181x_clk_gate_is_enabled(struct clk_hw *hw)
|
|
{
|
|
u32 reg;
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
void __iomem *reg_addr = clk_hw->base + clk_hw->gate.reg;
|
|
|
|
if (clk_hw->gate.shift < 0)
|
|
pr_err("Error: %s: gate.shift = %d\n", __func__, clk_hw->gate.shift);
|
|
|
|
reg = readl(reg_addr);
|
|
|
|
reg &= BIT(clk_hw->gate.shift);
|
|
|
|
if (clk_hw_get_flags(hw) & CLK_IGNORE_UNUSED)
|
|
return __clk_get_enable_count(hw->clk) ? (reg ? 1 : 0) : 0;
|
|
else
|
|
return reg ? 1 : 0;
|
|
}
|
|
|
|
static u8 cv181x_clk_mux_get_parent(struct clk_hw *hw)
|
|
{
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
u8 clk_sel = cv181x_clk_get_clk_sel(clk_hw);
|
|
u8 src_sel = cv181x_clk_get_src_sel(clk_hw);
|
|
u8 parent_idx = 0;
|
|
|
|
/*
|
|
* | 0 | 1 | 2 | 3 | 4 | 5 |
|
|
* +-------+-------+-------+-------+-------+-------+
|
|
* | XTAL | DIV_1 | src_0 | src_1 | src_2 | src_3 |
|
|
* | XTAL | src_0 | src_1 | src_2 | src_3 | |
|
|
* | DIV_1 | src_0 | src_1 | src_2 | src_3 | |
|
|
* | src_0 | src_1 | src_2 | src_3 | | |
|
|
* +-------+-------+-------+-------+-------+-------+
|
|
*/
|
|
|
|
if (clk_hw->mux[0].shift >= 0) {
|
|
// clk with bypass reg
|
|
if (cv181x_clk_is_bypassed(clk_hw)) {
|
|
parent_idx = 0;
|
|
} else {
|
|
if (clk_hw->mux[1].shift >= 0) {
|
|
// clk with clk_sel reg
|
|
if (clk_sel) {
|
|
parent_idx = 1;
|
|
} else {
|
|
parent_idx = src_sel + 2;
|
|
}
|
|
} else {
|
|
// clk without clk_sel reg
|
|
parent_idx = src_sel + 1;
|
|
}
|
|
}
|
|
} else {
|
|
// clk without bypass reg
|
|
if (clk_hw->mux[1].shift >= 0) {
|
|
// clk with clk_sel reg
|
|
if (clk_sel) {
|
|
parent_idx = 0;
|
|
} else {
|
|
parent_idx = src_sel + 1;
|
|
}
|
|
} else {
|
|
//clk without clk_sel reg
|
|
parent_idx = src_sel;
|
|
}
|
|
}
|
|
|
|
return parent_idx;
|
|
}
|
|
|
|
static int cv181x_clk_mux_set_parent(struct clk_hw *hw, u8 index)
|
|
{
|
|
struct cv181x_hw_clock *clk_hw = to_cv181x_clk(hw);
|
|
unsigned long flags = 0;
|
|
void __iomem *reg_addr;
|
|
unsigned int reg;
|
|
|
|
if (clk_hw->lock)
|
|
spin_lock_irqsave(clk_hw->lock, flags);
|
|
else
|
|
__acquire(clk_hw->lock);
|
|
|
|
/*
|
|
* | 0 | 1 | 2 | 3 | 4 | 5 |
|
|
* +-------+-------+-------+-------+-------+-------+
|
|
* | XTAL | DIV_1 | src_0 | src_1 | src_2 | src_3 |
|
|
* | XTAL | src_0 | src_1 | src_2 | src_3 | |
|
|
* | DIV_1 | src_0 | src_1 | src_2 | src_3 | |
|
|
* | src_0 | src_1 | src_2 | src_3 | | |
|
|
* +-------+-------+-------+-------+-------+-------+
|
|
*/
|
|
|
|
if (index == 0) {
|
|
if (clk_hw->mux[0].shift >= 0) {
|
|
// set bypass
|
|
reg_addr = clk_hw->base + clk_hw->mux[0].reg;
|
|
reg = readl(reg_addr);
|
|
reg |= 1 << clk_hw->mux[0].shift;
|
|
writel(reg, reg_addr);
|
|
goto unlock_release;
|
|
} else if (clk_hw->mux[1].shift >= 0) {
|
|
// set clk_sel to DIV_1
|
|
reg_addr = clk_hw->base + clk_hw->mux[1].reg;
|
|
reg = readl(reg_addr);
|
|
reg &= ~(1 << clk_hw->mux[1].shift);
|
|
writel(reg, reg_addr);
|
|
goto unlock_release;
|
|
}
|
|
} else if (index == 1) {
|
|
if (clk_hw->mux[0].shift >= 0) {
|
|
// clear bypass
|
|
reg_addr = clk_hw->base + clk_hw->mux[0].reg;
|
|
reg = readl(reg_addr);
|
|
reg &= ~(0x1 << clk_hw->mux[0].shift);
|
|
writel(reg, reg_addr);
|
|
|
|
if (clk_hw->mux[1].shift >= 0) {
|
|
// set clk_sel to DIV_1
|
|
reg_addr = clk_hw->base + clk_hw->mux[1].reg;
|
|
reg = readl(reg_addr);
|
|
reg &= ~(1 << clk_hw->mux[1].shift);
|
|
writel(reg, reg_addr);
|
|
goto unlock_release;
|
|
} else {
|
|
index--;
|
|
}
|
|
} else if (clk_hw->mux[1].shift >= 0) {
|
|
// set clk_sel to DIV_0
|
|
reg_addr = clk_hw->base + clk_hw->mux[1].reg;
|
|
reg = readl(reg_addr);
|
|
reg |= 1 << clk_hw->mux[1].shift;
|
|
writel(reg, reg_addr);
|
|
index--;
|
|
}
|
|
} else {
|
|
if (clk_hw->mux[0].shift >= 0) {
|
|
// clear bypass
|
|
reg_addr = clk_hw->base + clk_hw->mux[0].reg;
|
|
reg = readl(reg_addr);
|
|
reg &= ~(0x1 << clk_hw->mux[0].shift);
|
|
writel(reg, reg_addr);
|
|
index--;
|
|
}
|
|
|
|
if (clk_hw->mux[1].shift >= 0) {
|
|
// set clk_sel to DIV_0
|
|
reg_addr = clk_hw->base + clk_hw->mux[1].reg;
|
|
reg = readl(reg_addr);
|
|
reg |= 1 << clk_hw->mux[1].shift;
|
|
writel(reg, reg_addr);
|
|
index--;
|
|
}
|
|
}
|
|
|
|
if (index < 0) {
|
|
pr_err("index is negative(%d)\n", index);
|
|
goto unlock_release;
|
|
}
|
|
|
|
// set src_sel reg
|
|
reg_addr = clk_hw->base + clk_hw->mux[2].reg;
|
|
reg = readl(reg_addr);
|
|
reg &= ~(0x3 << clk_hw->mux[2].shift); // clear bits
|
|
reg |= (index & 0x3) << clk_hw->mux[2].shift; //set bits
|
|
writel(reg, reg_addr);
|
|
|
|
unlock_release:
|
|
if (clk_hw->lock)
|
|
spin_unlock_irqrestore(clk_hw->lock, flags);
|
|
else
|
|
__release(clk_hw->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct clk_ops cv181x_clk_ops = {
|
|
// gate
|
|
.enable = cv181x_clk_gate_enable,
|
|
.disable = cv181x_clk_gate_disable,
|
|
.is_enabled = cv181x_clk_gate_is_enabled,
|
|
|
|
// div
|
|
.recalc_rate = cv181x_clk_div_recalc_rate,
|
|
.round_rate = cv181x_clk_div_round_rate,
|
|
.determine_rate = cv181x_clk_div_determine_rate,
|
|
.set_rate = cv181x_clk_div_set_rate,
|
|
|
|
//mux
|
|
.get_parent = cv181x_clk_mux_get_parent,
|
|
.set_parent = cv181x_clk_mux_set_parent,
|
|
};
|
|
|
|
static struct clk_hw *cv181x_register_clk(struct cv181x_hw_clock *cv181x_clk,
|
|
void __iomem *sys_base)
|
|
{
|
|
struct clk_hw *hw;
|
|
struct clk_init_data init;
|
|
int err;
|
|
|
|
cv181x_clk->gate.flags = 0;
|
|
cv181x_clk->div[0].flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
|
|
CLK_DIVIDER_ROUND_CLOSEST;
|
|
cv181x_clk->div[1].flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
|
|
CLK_DIVIDER_ROUND_CLOSEST;
|
|
cv181x_clk->mux[0].flags = 0; /* clk byp */
|
|
cv181x_clk->mux[1].flags = 0; /* clk sel */
|
|
cv181x_clk->mux[2].flags = 0; /* div_0 src_sel */
|
|
cv181x_clk->base = sys_base;
|
|
cv181x_clk->lock = &cv181x_clk_lock;
|
|
|
|
if (cvi_clk_flags) {
|
|
/* copy clk_init_data for modification */
|
|
memcpy(&init, cv181x_clk->hw.init, sizeof(init));
|
|
|
|
init.flags |= cvi_clk_flags;
|
|
cv181x_clk->hw.init = &init;
|
|
}
|
|
|
|
hw = &cv181x_clk->hw;
|
|
err = clk_hw_register(NULL, hw);
|
|
if (err) {
|
|
return ERR_PTR(err);
|
|
}
|
|
|
|
return hw;
|
|
}
|
|
|
|
static void cv181x_unregister_clk(struct clk_hw *hw)
|
|
{
|
|
struct cv181x_hw_clock *cv181x_clk = to_cv181x_clk(hw);
|
|
|
|
clk_hw_unregister(hw);
|
|
kfree(cv181x_clk);
|
|
}
|
|
static int cv181x_register_clks(struct cv181x_hw_clock *clks,
|
|
int num_clks,
|
|
struct cv181x_clock_data *data)
|
|
{
|
|
struct clk_hw *hw;
|
|
void __iomem *sys_base = data->base;
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < num_clks; i++) {
|
|
struct cv181x_hw_clock *cv181x_clk = &clks[i];
|
|
|
|
hw = cv181x_register_clk(cv181x_clk, sys_base);
|
|
|
|
if (IS_ERR(hw)) {
|
|
pr_err("%s: failed to register clock %s\n",
|
|
__func__, cv181x_clk->name);
|
|
goto err_clk;
|
|
}
|
|
data->hw_data.hws[clks[i].id] = hw;
|
|
clk_hw_register_clkdev(hw, cv181x_clk->name, NULL);
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_clk:
|
|
while (i--)
|
|
cv181x_unregister_clk(data->hw_data.hws[clks[i].id]);
|
|
|
|
return PTR_ERR(hw);
|
|
}
|
|
|
|
static const struct of_device_id cvi_clk_match_ids_tables[] = {
|
|
{
|
|
.compatible = "cvitek,cv181x-clk",
|
|
},
|
|
{}
|
|
};
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
static int cv181x_clk_suspend(void)
|
|
{
|
|
memcpy_fromio(clk_data->clken_saved_regs,
|
|
clk_data->base + REG_CLK_EN_START,
|
|
REG_CLK_EN_NUM * 4);
|
|
|
|
memcpy_fromio(clk_data->clksel_saved_regs,
|
|
clk_data->base + REG_CLK_SEL_START,
|
|
REG_CLK_SEL_NUM * 4);
|
|
|
|
memcpy_fromio(clk_data->clkbyp_saved_regs,
|
|
clk_data->base + REG_CLK_BYP_START,
|
|
REG_CLK_BYP_NUM * 4);
|
|
|
|
memcpy_fromio(clk_data->clkdiv_saved_regs,
|
|
clk_data->base + REG_CLK_DIV_START,
|
|
REG_CLK_DIV_NUM * 4);
|
|
|
|
memcpy_fromio(clk_data->g2_clkdiv_saved_regs,
|
|
clk_data->base + REG_CLK_G2_DIV_START,
|
|
REG_CLK_G2_DIV_NUM * 4);
|
|
|
|
memcpy_fromio(clk_data->pll_g2_csr_saved_regs,
|
|
clk_data->base + REG_PLL_G2_CSR_START,
|
|
REG_PLL_G2_CSR_NUM * 4);
|
|
|
|
memcpy_fromio(clk_data->pll_g6_csr_saved_regs,
|
|
clk_data->base + REG_PLL_G6_CSR_START,
|
|
REG_PLL_G6_CSR_NUM * 4);
|
|
|
|
clk_data->a0pll_ssc_syn_set_saved_reg =
|
|
readl(clk_data->base + REG_APLL_SSC_SYN_SET);
|
|
|
|
clk_data->disppll_ssc_syn_set_saved_reg =
|
|
readl(clk_data->base + REG_DISPPLL_SSC_SYN_SET);
|
|
|
|
clk_data->cam0pll_ssc_syn_set_saved_reg =
|
|
readl(clk_data->base + REG_CAM0PLL_SSC_SYN_SET);
|
|
|
|
clk_data->cam1pll_ssc_syn_set_saved_reg =
|
|
readl(clk_data->base + REG_CAM1PLL_SSC_SYN_SET);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cv181x_clk_resume(void)
|
|
{
|
|
uint32_t regval;
|
|
|
|
/* switch clock to xtal */
|
|
writel(0xffffffff, clk_data->base + REG_CLK_BYP_0);
|
|
writel(0xffffffff, clk_data->base + REG_CLK_BYP_1);
|
|
|
|
memcpy_toio(clk_data->base + REG_CLK_EN_START,
|
|
clk_data->clken_saved_regs,
|
|
REG_CLK_EN_NUM * 4);
|
|
|
|
memcpy_toio(clk_data->base + REG_CLK_SEL_START,
|
|
clk_data->clksel_saved_regs,
|
|
REG_CLK_SEL_NUM * 4);
|
|
|
|
memcpy_toio(clk_data->base + REG_CLK_DIV_START,
|
|
clk_data->clkdiv_saved_regs,
|
|
REG_CLK_DIV_NUM * 4);
|
|
|
|
memcpy_toio(clk_data->base + REG_CLK_G2_DIV_START,
|
|
clk_data->g2_clkdiv_saved_regs,
|
|
REG_CLK_G2_DIV_NUM * 4);
|
|
|
|
// memcpy_toio(clk_data->base + REG_PLL_G6_CSR_START,
|
|
// clk_data->pll_g6_csr_saved_regs,
|
|
// REG_PLL_G6_CSR_NUM * 4);
|
|
|
|
/* wait for pll setting updated */
|
|
while (readl(clk_data->base + REG_PLL_G6_STATUS) & 0x7) {
|
|
}
|
|
|
|
/* A0PLL */
|
|
if (clk_data->a0pll_ssc_syn_set_saved_reg !=
|
|
readl(clk_data->base + REG_APLL_SSC_SYN_SET)) {
|
|
pr_debug("%s: update A0PLL\n", __func__);
|
|
writel(clk_data->a0pll_ssc_syn_set_saved_reg,
|
|
clk_data->base + REG_APLL_SSC_SYN_SET);
|
|
|
|
/* toggle software update */
|
|
regval = readl(clk_data->base + REG_APLL_SSC_SYN_CTRL);
|
|
regval ^= 1;
|
|
writel(regval, clk_data->base + REG_APLL_SSC_SYN_CTRL);
|
|
}
|
|
|
|
/* DISPPLL */
|
|
if (clk_data->disppll_ssc_syn_set_saved_reg !=
|
|
readl(clk_data->base + REG_DISPPLL_SSC_SYN_SET)) {
|
|
pr_debug("%s: update DISPPLL\n", __func__);
|
|
writel(clk_data->disppll_ssc_syn_set_saved_reg,
|
|
clk_data->base + REG_DISPPLL_SSC_SYN_SET);
|
|
|
|
/* toggle software update */
|
|
regval = readl(clk_data->base + REG_DISPPLL_SSC_SYN_CTRL);
|
|
regval ^= 1;
|
|
writel(regval, clk_data->base + REG_DISPPLL_SSC_SYN_CTRL);
|
|
}
|
|
|
|
/* CAM0PLL */
|
|
if (clk_data->cam0pll_ssc_syn_set_saved_reg !=
|
|
readl(clk_data->base + REG_CAM0PLL_SSC_SYN_SET)) {
|
|
pr_debug("%s: update CAM0PLL\n", __func__);
|
|
writel(clk_data->cam0pll_ssc_syn_set_saved_reg,
|
|
clk_data->base + REG_CAM0PLL_SSC_SYN_SET);
|
|
|
|
/* toggle software update */
|
|
regval = readl(clk_data->base + REG_CAM0PLL_SSC_SYN_CTRL);
|
|
regval ^= 1;
|
|
writel(regval, clk_data->base + REG_CAM0PLL_SSC_SYN_CTRL);
|
|
}
|
|
|
|
/* CAM1PLL */
|
|
if (clk_data->cam1pll_ssc_syn_set_saved_reg !=
|
|
readl(clk_data->base + REG_CAM1PLL_SSC_SYN_SET)) {
|
|
pr_debug("%s: update CAM1PLL\n", __func__);
|
|
writel(clk_data->cam1pll_ssc_syn_set_saved_reg,
|
|
clk_data->base + REG_CAM1PLL_SSC_SYN_SET);
|
|
|
|
/* toggle software update */
|
|
regval = readl(clk_data->base + REG_CAM1PLL_SSC_SYN_CTRL);
|
|
regval ^= 1;
|
|
writel(regval, clk_data->base + REG_CAM1PLL_SSC_SYN_CTRL);
|
|
}
|
|
|
|
memcpy_toio(clk_data->base + REG_PLL_G2_CSR_START,
|
|
clk_data->pll_g2_csr_saved_regs,
|
|
REG_PLL_G2_CSR_NUM * 4);
|
|
|
|
/* wait for pll setting updated */
|
|
while (readl(clk_data->base + REG_PLL_G2_STATUS) & 0x1F) {
|
|
}
|
|
|
|
memcpy_toio(clk_data->base + REG_CLK_BYP_START,
|
|
clk_data->clkbyp_saved_regs,
|
|
REG_CLK_BYP_NUM * 4);
|
|
}
|
|
|
|
static struct syscore_ops cv181x_clk_syscore_ops = {
|
|
.suspend = cv181x_clk_suspend,
|
|
.resume = cv181x_clk_resume,
|
|
};
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
|
|
static void __init cvi_clk_init(struct device_node *node)
|
|
{
|
|
int num_clks;
|
|
int i;
|
|
int ret = 0;
|
|
int of_num_clks;
|
|
struct clk *clk;
|
|
|
|
of_num_clks = of_clk_get_parent_count(node);
|
|
for (i = 0; i < of_num_clks; i++) {
|
|
clk = of_clk_get(node, i);
|
|
clk_register_clkdev(clk, __clk_get_name(clk), NULL);
|
|
clk_put(clk);
|
|
}
|
|
|
|
num_clks = ARRAY_SIZE(cv181x_pll_clks) +
|
|
ARRAY_SIZE(cv181x_clks);
|
|
|
|
clk_data = kzalloc(sizeof(struct cv181x_clock_data) +
|
|
sizeof(struct clk_hw) * num_clks,
|
|
GFP_KERNEL);
|
|
if (!clk_data) {
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
for (i = 0; i < num_clks; i++)
|
|
clk_data->hw_data.hws[i] = ERR_PTR(-ENOENT);
|
|
|
|
clk_data->hw_data.num = num_clks;
|
|
|
|
clk_data->lock = &cv181x_clk_lock;
|
|
|
|
clk_data->base = of_iomap(node, 0);
|
|
if (!clk_data->base) {
|
|
pr_err("Failed to map address range for cvitek,cv181x-clk node\n");
|
|
return;
|
|
}
|
|
|
|
cv181x_clk_register_plls(cv181x_pll_clks,
|
|
ARRAY_SIZE(cv181x_pll_clks),
|
|
clk_data);
|
|
|
|
cv181x_register_clks(cv181x_clks,
|
|
ARRAY_SIZE(cv181x_clks),
|
|
clk_data);
|
|
|
|
|
|
/* register clk-provider */
|
|
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, &clk_data->hw_data);
|
|
if (ret)
|
|
pr_err("Unable to add hw clk provider\n");
|
|
|
|
/* force enable clocks */
|
|
// clk_prepare_enable(clk_data->hw_data.hws[CV181X_CLK_DSI_MAC_VIP]->clk);
|
|
// clk_prepare_enable(clk_data->hw_data.hws[CV181X_CLK_DISP_VIP]->clk);
|
|
// clk_prepare_enable(clk_data->hw_data.hws[CV181X_CLK_BT_VIP]->clk);
|
|
// clk_prepare_enable(clk_data->hw_data.hws[CV181X_CLK_SC_TOP_VIP]->clk);
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
register_syscore_ops(&cv181x_clk_syscore_ops);
|
|
#endif
|
|
|
|
if (!ret)
|
|
return;
|
|
|
|
out:
|
|
pr_err("%s failed error number %d\n", __func__, ret);
|
|
}
|
|
CLK_OF_DECLARE(cvi_clk, "cvitek,cv181x-clk", cvi_clk_init);
|