summaryrefslogtreecommitdiffstats
path: root/drivers/clk/socfpga/clk-periph.c
diff options
context:
space:
mode:
authorDinh Nguyen <dinguyen@altera.com>2014-05-12 12:27:22 -0500
committerDinh Nguyen <dinguyen@altera.com>2014-05-12 12:27:22 -0500
commit0691bb1b5a1865b3bbc9b7ce6e26eff546abb1cf (patch)
tree1011296d0c0a3ec703f73880c96667be0f569eee /drivers/clk/socfpga/clk-periph.c
parentd1db0eea852497762cab43b905b879dfcd3b8987 (diff)
downloadlinux-0691bb1b5a1865b3bbc9b7ce6e26eff546abb1cf.tar.bz2
clk: socfpga: add divider registers to the main pll outputs
The C0(mpu_clk), C1(main_clk), and C2(dbg_base_clk) outputs from the main PLL go through a pre-divider before coming into the system. These registers were hidden for the CycloneV platform, but are now used for the ArriaV platform. This patch updates the clock driver to read the div-reg property for the socfpga-periph-clk clocks. Also moves the div_mask define to clk.h for re-use. Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
Diffstat (limited to 'drivers/clk/socfpga/clk-periph.c')
-rw-r--r--drivers/clk/socfpga/clk-periph.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c
index 81623a3736f9..46531c34ec9b 100644
--- a/drivers/clk/socfpga/clk-periph.c
+++ b/drivers/clk/socfpga/clk-periph.c
@@ -29,12 +29,18 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
unsigned long parent_rate)
{
struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
- u32 div;
+ u32 div, val;
- if (socfpgaclk->fixed_div)
+ if (socfpgaclk->fixed_div) {
div = socfpgaclk->fixed_div;
- else
+ } else {
+ if (socfpgaclk->div_reg) {
+ val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+ val &= div_mask(socfpgaclk->width);
+ parent_rate /= (val + 1);
+ }
div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
+ }
return parent_rate / div;
}
@@ -54,6 +60,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
struct clk_init_data init;
int rc;
u32 fixed_div;
+ u32 div_reg[3];
of_property_read_u32(node, "reg", &reg);
@@ -63,6 +70,15 @@ static __init void __socfpga_periph_init(struct device_node *node,
periph_clk->hw.reg = clk_mgr_base_addr + reg;
+ rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+ if (!rc) {
+ periph_clk->div_reg = clk_mgr_base_addr + div_reg[0];
+ periph_clk->shift = div_reg[1];
+ periph_clk->width = div_reg[2];
+ } else {
+ periph_clk->div_reg = 0;
+ }
+
rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
if (rc)
periph_clk->fixed_div = 0;