diff options
Diffstat (limited to 'arch/arm/mach-mx6/clock.c')
-rw-r--r-- | arch/arm/mach-mx6/clock.c | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 6b1fad161b4..e709b347c6a 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -4655,6 +4655,100 @@ static unsigned long _clk_clko_round_rate(struct clk *clk, return parent_rate / div; } +static int _clk_clko2_set_parent(struct clk *clk, struct clk *parent) +{ + u32 sel, reg; + + if (parent == &mmdc_ch0_axi_clk[0]) + sel = 0; + else if (parent == &mmdc_ch1_axi_clk[0]) + sel = 1; + else if (parent == &usdhc4_clk) + sel = 2; + else if (parent == &usdhc1_clk) + sel = 3; + else if (parent == &gpu2d_axi_clk) + sel = 4; + else if (parent == &ecspi_clk[0]) + sel = 6; + else if (parent == &gpu3d_axi_clk) + sel = 7; + else if (parent == &usdhc3_clk) + sel = 8; + else if (parent == &pcie_clk[0]) + sel = 9; + else if (parent == &ipu1_clk) + sel = 11; + else if (parent == &ipu2_clk) + sel = 12; + else if (parent == &vdo_axi_clk) + sel = 13; + else if (parent == &osc_clk) + sel = 14; + else if (parent == &gpu2d_core_clk[0]) + sel = 15; + else if (parent == &gpu3d_core_clk[0]) + sel = 16; + else if (parent == &usdhc2_clk) + sel = 17; + else if (parent == &ssi1_clk) + sel = 18; + else if (parent == &ssi2_clk) + sel = 19; + else if (parent == &ssi3_clk) + sel = 20; + else if (parent == &gpu3d_shader_clk) + sel = 21; + else if (parent == &can_clk_root) + sel = 23; + else if (parent == &ldb_di0_clk) + sel = 24; + else if (parent == &ldb_di1_clk) + sel = 25; + else if (parent == &esai_clk) + sel = 26; + else if (parent == &uart_clk[0]) + sel = 28; + else if (parent == &spdif0_clk[0]) + sel = 29; + else if (parent == &hsi_tx_clk[0]) + sel = 31; + else + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CCOSR); + reg &= ~MXC_CCM_CCOSR_CKO2_SEL_MASK; + reg |= sel << MXC_CCM_CCOSR_CKO2_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CCOSR); + return 0; +} + +static unsigned long _clk_clko2_get_rate(struct clk *clk) +{ + u32 reg = __raw_readl(MXC_CCM_CCOSR); + u32 div = ((reg & MXC_CCM_CCOSR_CKO2_DIV_MASK) >> + MXC_CCM_CCOSR_CKO2_DIV_OFFSET) + 1; + return clk_get_rate(clk->parent) / div; +} + +static int _clk_clko2_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 parent_rate = clk_get_rate(clk->parent); + u32 div = parent_rate / rate; + + if (div == 0) + div++; + if (((parent_rate / div) != rate) || (div > 8)) + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CCOSR); + reg &= ~MXC_CCM_CCOSR_CKO2_DIV_MASK; + reg |= (div - 1) << MXC_CCM_CCOSR_CKO2_DIV_OFFSET; + __raw_writel(reg, MXC_CCM_CCOSR); + return 0; +} + static struct clk clko_clk = { __INIT_CLK_DEBUG(clko_clk) .parent = &pll2_528_bus_main_clk, @@ -4668,6 +4762,19 @@ static struct clk clko_clk = { .round_rate = _clk_clko_round_rate, }; +static struct clk clko2_clk = { + __INIT_CLK_DEBUG(clko2_clk) + .parent = &usdhc4_clk, + .enable = _clk_enable1, + .enable_reg = MXC_CCM_CCOSR, + .enable_shift = MXC_CCM_CCOSR_CKO2_EN_OFFSET, + .disable = _clk_disable1, + .set_parent = _clk_clko2_set_parent, + .set_rate = _clk_clko2_set_rate, + .get_rate = _clk_clko2_get_rate, + .round_rate = _clk_clko_round_rate, +}; + static struct clk perfmon0_clk = { __INIT_CLK_DEBUG(perfmon0_clk) .parent = &mmdc_ch0_axi_clk[0], @@ -4820,6 +4927,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, NULL, aips_tz2_clk), _REGISTER_CLOCK(NULL, NULL, aips_tz1_clk), _REGISTER_CLOCK(NULL, "clko_clk", clko_clk), + _REGISTER_CLOCK(NULL, "clko2_clk", clko2_clk), _REGISTER_CLOCK("mxs-perfmon.0", "perfmon", perfmon0_clk), _REGISTER_CLOCK("mxs-perfmon.1", "perfmon", perfmon1_clk), _REGISTER_CLOCK("mxs-perfmon.2", "perfmon", perfmon2_clk), @@ -4909,6 +5017,10 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_set_parent(&gpu3d_core_clk[0], &mmdc_ch0_axi_clk[0]); clk_set_rate(&gpu3d_core_clk[0], 528000000); + /* PCLK camera - J5 */ + clk_set_parent(&clko2_clk, &osc_clk); + clk_set_rate(&clko2_clk, 2400000); + /* * FIXME: asrc needs to use asrc_serial(spdif1) clock to do sample * rate convertion and this clock frequency can not be too high, set |