diff options
author | Dong Aisheng <b29396@freescale.com> | 2011-11-02 19:23:31 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-01-09 21:04:23 +0800 |
commit | 594f7f22dcfa72f068c1a999a077e637e14b8622 (patch) | |
tree | 65c85e3718ec2052cef6a12aaa92442c006d7252 /arch/arm/mach-mx6/clock.c | |
parent | d85f1321d467d25da4a1023a4e8351faf8f17630 (diff) |
ENGR00161256-2 mx6q arm2: add flexcan support
Add flexcan support.
Signed-off-by: Dong Aisheng <b29396@freescale.com>
Diffstat (limited to 'arch/arm/mach-mx6/clock.c')
-rw-r--r-- | arch/arm/mach-mx6/clock.c | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 58e6f3cd64f2..6a71747039a0 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -3032,11 +3032,70 @@ static struct clk ipu2_di_clk[] = { }, }; +static unsigned long _clk_can_root_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + u32 parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + /* Make sure rate is not greater than the maximum value for the clock. + * Also prevent a div of 0. + */ + if (div == 0) + div++; + + if (div > 64) + div = 64; + + return parent_rate / div; +} + +static int _clk_can_root_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + u32 parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (div == 0) + div++; + if (((parent_rate / div) != rate) || (div > 64)) + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CSCMR2) & MXC_CCM_CSCMR2_CAN_CLK_PODF_MASK; + reg |= ((div - 1) << MXC_CCM_CSCMR2_CAN_CLK_PODF_OFFSET); + + __raw_writel(reg, MXC_CCM_CSCMR2); + + return 0; +} + +static unsigned long _clk_can_root_get_rate(struct clk *clk) +{ + u32 reg, div; + unsigned long val; + + reg = __raw_readl(MXC_CCM_CSCMR2) & MXC_CCM_CSCMR2_CAN_CLK_PODF_MASK; + div = (reg >> MXC_CCM_CSCMR2_CAN_CLK_PODF_OFFSET) + 1; + val = clk_get_rate(clk->parent) / div; + + return val; +} + +static struct clk can_clk_root = { + __INIT_CLK_DEBUG(can_clk_root) + .parent = &pll3_60M, + .set_rate = _clk_can_root_set_rate, + .get_rate = _clk_can_root_get_rate, + .round_rate = _clk_can_root_round_rate, +}; + static struct clk can2_clk[] = { { __INIT_CLK_DEBUG(can2_module_clk) .id = 0, - .parent = &pll3_60M, + .parent = &can_clk_root, .enable_reg = MXC_CCM_CCGR0, .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET, .enable = _clk_enable, @@ -3047,7 +3106,7 @@ static struct clk can2_clk[] = { { __INIT_CLK_DEBUG(can2_serial_clk) .id = 1, - .parent = &pll3_60M, + .parent = &can_clk_root, .enable_reg = MXC_CCM_CCGR0, .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET, .enable = _clk_enable, @@ -3060,7 +3119,7 @@ static struct clk can1_clk[] = { { __INIT_CLK_DEBUG(can1_module_clk) .id = 0, - .parent = &pll3_60M, + .parent = &can_clk_root, .enable_reg = MXC_CCM_CCGR0, .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET, .enable = _clk_enable, @@ -3071,7 +3130,7 @@ static struct clk can1_clk[] = { { __INIT_CLK_DEBUG(can1_serial_clk) .id = 1, - .parent = &pll3_60M, + .parent = &can_clk_root, .enable_reg = MXC_CCM_CCGR0, .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET, .enable = _clk_enable, @@ -4630,8 +4689,9 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "ipu1_di1_clk", ipu1_di_clk[1]), _REGISTER_CLOCK(NULL, "ipu2_di0_clk", ipu2_di_clk[0]), _REGISTER_CLOCK(NULL, "ipu2_di1_clk", ipu2_di_clk[1]), - _REGISTER_CLOCK("FlexCAN.0", "can_clk", can1_clk[0]), - _REGISTER_CLOCK("FlexCAN.1", "can_clk", can2_clk[0]), + _REGISTER_CLOCK(NULL, "can_root_clk", can_clk_root), + _REGISTER_CLOCK("imx6q-flexcan.0", NULL, can1_clk[0]), + _REGISTER_CLOCK("imx6q-flexcan.1", NULL, can2_clk[0]), _REGISTER_CLOCK(NULL, "ldb_di0_clk", ldb_di0_clk), _REGISTER_CLOCK(NULL, "ldb_di1_clk", ldb_di1_clk), _REGISTER_CLOCK("mxc_spdif.0", NULL, spdif0_clk[0]), |