summaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-09-13 14:56:06 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-09-13 14:56:06 +0200
commit074a8fdc929a9cdb13b2ed7e637055d0acc05de2 (patch)
tree2e6182c70403ad1db43e3128903e3c79531ce1dd /drivers/clk
parent0e1892b2e9348a94f58d1a4518e931c8ba46843e (diff)
parent994fa02f5d7d815265b625f6114d19f156547b69 (diff)
downloadbarebox-074a8fdc929a9cdb13b2ed7e637055d0acc05de2.tar.gz
barebox-074a8fdc929a9cdb13b2ed7e637055d0acc05de2.tar.xz
Merge branch 'for-next/socfpga'
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/socfpga.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/clk/socfpga.c b/drivers/clk/socfpga.c
index 37ed038be8..6af0632caf 100644
--- a/drivers/clk/socfpga.c
+++ b/drivers/clk/socfpga.c
@@ -116,18 +116,27 @@ struct clk_periph {
const char *parent;
unsigned regofs;
unsigned int fixed_div;
+ void __iomem *div_reg;
+ unsigned int width;
+ unsigned int shift;
};
static unsigned long clk_periph_recalc_rate(struct clk *clk,
unsigned long parent_rate)
{
struct clk_periph *periph = container_of(clk, struct clk_periph, clk);
- u32 div;
+ u32 div, val;
- if (periph->fixed_div)
+ if (periph->fixed_div) {
div = periph->fixed_div;
- else
+ } else {
+ if (periph->div_reg) {
+ val = readl(periph->div_reg) >> periph->shift;
+ val &= div_mask(periph->width);
+ parent_rate /= (val + 1);
+ }
div = ((readl(clk_mgr_base_addr + periph->regofs) & 0x1ff) + 1);
+ }
return parent_rate / div;
}
@@ -140,6 +149,7 @@ static struct clk *socfpga_periph_clk(struct device_node *node)
{
struct clk_periph *periph;
int ret;
+ u32 div_reg[3];
periph = xzalloc(sizeof(*periph));
@@ -152,6 +162,15 @@ static struct clk *socfpga_periph_clk(struct device_node *node)
periph->clk.name = xstrdup(node->name);
periph->clk.ops = &clk_periph_ops;
+ ret = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+ if (!ret) {
+ periph->div_reg = clk_mgr_base_addr + div_reg[0];
+ periph->shift = div_reg[1];
+ periph->width = div_reg[2];
+ } else {
+ periph->div_reg = 0;
+ }
+
of_property_read_u32(node, "reg", &periph->regofs);
of_property_read_u32(node, "fixed-divider", &periph->fixed_div);