Using the custom TI functions required not only replacing common memory access functions but also rewriting the routines used to set bypass and lock states. As for readl() and writel(), they also required the address of the register to be accessed, a parameter that is hidden by the TI clk module.
Signed-off-by: Dario Binacchi <dario...@libero.it> --- drivers/clk/ti/clk-am3-dpll.c | 86 +++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/drivers/clk/ti/clk-am3-dpll.c b/drivers/clk/ti/clk-am3-dpll.c index 90b4cc69ef..916d308034 100644 --- a/drivers/clk/ti/clk-am3-dpll.c +++ b/drivers/clk/ti/clk-am3-dpll.c @@ -17,15 +17,16 @@ #include <asm/arch/clock.h> #include <asm/arch/sys_proto.h> #include <asm/io.h> +#include "clk.h" struct clk_ti_am3_dpll_drv_data { ulong max_rate; }; struct clk_ti_am3_dpll_priv { - fdt_addr_t clkmode_reg; - fdt_addr_t idlest_reg; - fdt_addr_t clksel_reg; + struct clk_ti_reg clkmode_reg; + struct clk_ti_reg idlest_reg; + struct clk_ti_reg clksel_reg; struct clk clk_bypass; struct clk clk_ref; u16 last_rounded_mult; @@ -75,6 +76,37 @@ static ulong clk_ti_am3_dpll_round_rate(struct clk *clk, ulong rate) return ret; } +static void clk_ti_am3_dpll_clken(struct clk_ti_am3_dpll_priv *priv, + u8 clken_bits) +{ + u32 v; + + v = clk_ti_readl(&priv->clkmode_reg); + v &= ~CM_CLKMODE_DPLL_DPLL_EN_MASK; + v |= clken_bits << CM_CLKMODE_DPLL_EN_SHIFT; + clk_ti_writel(v, &priv->clkmode_reg); +} + +static int clk_ti_am3_dpll_state(struct clk *clk, u8 state) +{ + struct clk_ti_am3_dpll_priv *priv = dev_get_priv(clk->dev); + u32 i = 0, v; + + do { + v = clk_ti_readl(&priv->idlest_reg) & ST_DPLL_CLK_MASK; + if (v == state) { + dev_dbg(clk->dev, "transition to '%s' in %d loops\n", + state ? "locked" : "bypassed", i); + return 1; + } + + } while (++i < LDELAY); + + dev_err(clk->dev, "failed transition to '%s'\n", + state ? "locked" : "bypassed"); + return 0; +} + static ulong clk_ti_am3_dpll_set_rate(struct clk *clk, ulong rate) { struct clk_ti_am3_dpll_priv *priv = dev_get_priv(clk->dev); @@ -85,16 +117,13 @@ static ulong clk_ti_am3_dpll_set_rate(struct clk *clk, ulong rate) if (IS_ERR_VALUE(round_rate)) return round_rate; - v = readl(priv->clksel_reg); + v = clk_ti_readl(&priv->clksel_reg); /* enter bypass mode */ - clrsetbits_le32(priv->clkmode_reg, CM_CLKMODE_DPLL_DPLL_EN_MASK, - DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT); + clk_ti_am3_dpll_clken(priv, DPLL_EN_MN_BYPASS); /* wait for bypass mode */ - if (!wait_on_value(ST_DPLL_CLK_MASK, 0, - (void *)priv->idlest_reg, LDELAY)) - dev_err(clk->dev, "failed bypassing dpll\n"); + clk_ti_am3_dpll_state(clk, 0); /* set M & N */ v &= ~CM_CLKSEL_DPLL_M_MASK; @@ -105,18 +134,14 @@ static ulong clk_ti_am3_dpll_set_rate(struct clk *clk, ulong rate) v |= ((priv->last_rounded_div - 1) << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK; - writel(v, priv->clksel_reg); + clk_ti_writel(v, &priv->clksel_reg); /* lock dpll */ - clrsetbits_le32(priv->clkmode_reg, CM_CLKMODE_DPLL_DPLL_EN_MASK, - DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT); + clk_ti_am3_dpll_clken(priv, DPLL_EN_LOCK); /* wait till the dpll locks */ - if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK, - (void *)priv->idlest_reg, LDELAY)) { - dev_err(clk->dev, "failed locking dpll\n"); + if (!clk_ti_am3_dpll_state(clk, ST_DPLL_CLK_MASK)) hang(); - } return round_rate; } @@ -128,7 +153,7 @@ static ulong clk_ti_am3_dpll_get_rate(struct clk *clk) u32 m, n, v; /* Return bypass rate if DPLL is bypassed */ - v = readl(priv->clkmode_reg); + v = clk_ti_readl(&priv->clkmode_reg); v &= CM_CLKMODE_DPLL_EN_MASK; v >>= CM_CLKMODE_DPLL_EN_SHIFT; @@ -141,7 +166,7 @@ static ulong clk_ti_am3_dpll_get_rate(struct clk *clk) return rate; } - v = readl(priv->clksel_reg); + v = clk_ti_readl(&priv->clksel_reg); m = v & CM_CLKSEL_DPLL_M_MASK; m >>= CM_CLKSEL_DPLL_M_SHIFT; n = v & CM_CLKSEL_DPLL_N_MASK; @@ -204,33 +229,28 @@ static int clk_ti_am3_dpll_of_to_plat(struct udevice *dev) struct clk_ti_am3_dpll_priv *priv = dev_get_priv(dev); struct clk_ti_am3_dpll_drv_data *data = (struct clk_ti_am3_dpll_drv_data *)dev_get_driver_data(dev); + int err; priv->max_rate = data->max_rate; - priv->clkmode_reg = dev_read_addr_index(dev, 0); - if (priv->clkmode_reg == FDT_ADDR_T_NONE) { - dev_err(dev, "failed to get clkmode register\n"); - return -EINVAL; + err = clk_ti_get_reg_addr(dev, 0, &priv->clkmode_reg); + if (err) { + dev_err(dev, "failed to get clkmode register address\n"); + return err; } - dev_dbg(dev, "clkmode_reg=0x%08lx\n", priv->clkmode_reg); - - priv->idlest_reg = dev_read_addr_index(dev, 1); - if (priv->idlest_reg == FDT_ADDR_T_NONE) { + err = clk_ti_get_reg_addr(dev, 1, &priv->idlest_reg); + if (err) { dev_err(dev, "failed to get idlest register\n"); return -EINVAL; } - dev_dbg(dev, "idlest_reg=0x%08lx\n", priv->idlest_reg); - - priv->clksel_reg = dev_read_addr_index(dev, 2); - if (priv->clksel_reg == FDT_ADDR_T_NONE) { + err = clk_ti_get_reg_addr(dev, 2, &priv->clksel_reg); + if (err) { dev_err(dev, "failed to get clksel register\n"); - return -EINVAL; + return err; } - dev_dbg(dev, "clksel_reg=0x%08lx\n", priv->clksel_reg); - return 0; } -- 2.17.1