Raffaele Recalcati <lamiapost...@gmail.com> writes:

> From: Davide Bonfanti <davide.bonfa...@bticino.it>

Missing changelog.  Stopped reading here.

Kevin

> Signed-off-by: Davide Bonfanti <davide.bonfa...@bticino.it>
> Signed-off-by: Raffaele Recalcati <raffaele.recalc...@bticino.it>
> ---
>  arch/arm/mach-davinci/clock.c              |  113 
> +++++++++++++++++++++++++++-
>  arch/arm/mach-davinci/clock.h              |   14 ++++
>  arch/arm/mach-davinci/dm365.c              |   23 +++++-
>  arch/arm/mach-davinci/include/mach/clock.h |    3 +
>  4 files changed, 146 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
> index 054c303..464c289 100644
> --- a/arch/arm/mach-davinci/clock.c
> +++ b/arch/arm/mach-davinci/clock.c
> @@ -144,6 +144,69 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
>  }
>  EXPORT_SYMBOL(clk_set_rate);
>  
> +int clkout2_set_rate(struct clk *clk, unsigned long rate)
> +{
> +     unsigned long flags;
> +     int ret = -EINVAL;
> +     int i, err, min_err, i_min_err;
> +     u32 regval;
> +     struct pll_data *pll;
> +     struct clk *parent = clk;
> +
> +     if (clk == NULL || IS_ERR(clk))
> +             return ret;
> +     if (!cpu_is_davinci_dm365())
> +             return -ENODEV;
> +
> +     while (parent->parent->parent)
> +             parent = parent->parent;
> +
> +     parent = clk->parent;
> +
> +     if (parent == clk)
> +             return -EPERM;
> +
> +     pll = parent->pll_data;
> +     regval = __raw_readl(IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE +
> +                     PERI_CLKCTL));
> +
> +     i_min_err = min_err = INT_MAX;
> +     for (i = 0x0F; i > 0; i--) {
> +             if (clk->set_rate) {
> +                     ret = clk_set_rate(clk, rate * i) ;
> +                     err = clk_get_rate(clk) - rate * i;
> +                     if (abs(min_err) > abs(err)) {
> +                             min_err = err;
> +                             i_min_err = i;
> +                     }
> +             }
> +     }
> +     i = i_min_err;
> +     ret = clk->set_rate(clk, rate * i) ;
> +
> +     regval &= ~(0x0F << 3);
> +     regval |= (i-1) << 3;
> +     regval |= 1 << CLOCKOUT2EN;
> +     __raw_writel(regval, IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE +
> +                     PERI_CLKCTL));
> +     rate *= i;
> +
> +     spin_lock_irqsave(&clockfw_lock, flags);
> +     if (ret == 0) {
> +             if (clk->recalc)
> +                     clk->rate = clk->recalc(clk);
> +             propagate_rate(clk);
> +             regval &= ~(1 << CLOCKOUT2EN);
> +             __raw_writel(regval, IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE +
> +                     PERI_CLKCTL));
> +     } else
> +             return -EINVAL;
> +     spin_unlock_irqrestore(&clockfw_lock, flags);
> +
> +     return ret;
> +}
> +EXPORT_SYMBOL(clkout2_set_rate);
> +
>  int clk_set_parent(struct clk *clk, struct clk *parent)
>  {
>       unsigned long flags;
> @@ -254,7 +317,15 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
>       u32 v, plldiv;
>       struct pll_data *pll;
>       unsigned long rate = clk->rate;
> +     struct clk *parent = clk;
> +
> +     if (clk == NULL || IS_ERR(clk))
> +             return -EINVAL;
> +     while (parent->parent->parent)
> +             parent = parent->parent;
>  
> +     if (parent == clk)
> +             return -EPERM;
>       /* If this is the PLL base clock, no more calculations needed */
>       if (clk->pll_data)
>               return rate;
> @@ -262,13 +333,13 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
>       if (WARN_ON(!clk->parent))
>               return rate;
>  
> -     rate = clk->parent->rate;
> +     rate = parent->rate;
> +
>  
>       /* Otherwise, the parent must be a PLL */
> -     if (WARN_ON(!clk->parent->pll_data))
> +     if (WARN_ON(!parent->pll_data))
>               return rate;
> -
> -     pll = clk->parent->pll_data;
> +     pll = parent->pll_data;
>  
>       /* If pre-PLL, source clock is before the multiplier and divider(s) */
>       if (clk->flags & PRE_PLL)
> @@ -286,6 +357,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
>  
>       return rate;
>  }
> +EXPORT_SYMBOL(clk_sysclk_recalc);
>  
>  static unsigned long clk_leafclk_recalc(struct clk *clk)
>  {
> @@ -433,6 +505,39 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned 
> int prediv,
>  }
>  EXPORT_SYMBOL(davinci_set_pllrate);
>  
> +int set_sysclk_rate(struct clk *clk, unsigned long rate)
> +{
> +     u32 clk_freq_min, clk_freq_max, plldiv;
> +     struct pll_data *pll;
> +     struct clk *parent = clk;
> +
> +     while (parent->parent->parent)
> +             parent = parent->parent;
> +     if (parent == clk)
> +             return -EPERM;
> +
> +     clk_freq_max = parent->rate;
> +     pll = parent->pll_data;
> +     if (clk->flags & PRE_PLL)
> +             clk_freq_max = pll->input_rate;
> +
> +     if (!clk->div_reg)
> +             return -EPERM;
> +
> +     clk_freq_min = clk_freq_max / 0x20;
> +     if ((rate < clk_freq_min) || (rate > clk_freq_max))
> +             return -EINVAL;
> +
> +     plldiv = clk_freq_max / rate ;
> +     if ((clk_freq_max % rate) < (rate >> 1))
> +             plldiv--;
> +     __raw_writel(plldiv & 0x1F, pll->base + clk->div_reg);
> +     __raw_writel(plldiv | 0x8000, pll->base + clk->div_reg);
> +     clk->rate = rate;
> +     return 0;
> +}
> +EXPORT_SYMBOL(set_sysclk_rate);
> +
>  int __init davinci_clk_init(struct clk_lookup *clocks)
>    {
>       struct clk_lookup *c;
> diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
> index 01e3648..74ba65f 100644
> --- a/arch/arm/mach-davinci/clock.h
> +++ b/arch/arm/mach-davinci/clock.h
> @@ -50,6 +50,11 @@
>  #define PLLDIV_EN       BIT(15)
>  #define PLLDIV_RATIO_MASK 0x1f
>  
> +#define PERI_CLKCTL  0x48
> +#define CLOCKOUT2EN  2
> +#define CLOCKOUT1EN  1
> +#define CLOCKOUT0EN  0
> +
>  /*
>   * OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN
>   * cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us
> @@ -95,6 +100,14 @@ struct clk {
>       struct list_head        childnode;      /* parent's child list node */
>       struct pll_data         *pll_data;
>       u32                     div_reg;
> +/*
> +     u32             sec_div_reg;
> +     u32             sec_div_reg_max;
> +     u32             sec_div_reg_shift;
> +     u32             out_enable_reg;
> +     u32             out_enable_bit;
> +*/
> +
>       unsigned long (*recalc) (struct clk *);
>       int (*set_rate) (struct clk *clk, unsigned long rate);
>       int (*round_rate) (struct clk *clk, unsigned long rate);
> @@ -121,6 +134,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned 
> int prediv,
>  
>  extern struct platform_device davinci_wdt_device;
>  extern void davinci_watchdog_reset(struct platform_device *);
> +int set_sysclk_rate(struct clk *clk, unsigned long rate);
>  
>  #endif
>  
> diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
> index e4ead0a..40aab63 100644
> --- a/arch/arm/mach-davinci/dm365.c
> +++ b/arch/arm/mach-davinci/dm365.c
> @@ -40,6 +40,15 @@
>  #include "mux.h"
>  
>  #define DM365_REF_FREQ               24000000        /* 24 MHz on the DM365 
> EVM */
> +#define PINMUX0              0x00
> +#define PINMUX1              0x04
> +#define PINMUX2              0x08
> +#define PINMUX3              0x0c
> +#define PINMUX4              0x10
> +#define INTMUX               0x18
> +#define EVTMUX               0x1c
> +
> +
>  
>  static struct pll_data pll1_data = {
>       .num            = 1,
> @@ -124,6 +133,7 @@ static struct clk pll1_sysclk6 = {
>       .parent         = &pll1_clk,
>       .flags          = CLK_PLL,
>       .div_reg        = PLLDIV6,
> +     .set_rate       = set_sysclk_rate,
>  };
>  
>  static struct clk pll1_sysclk7 = {
> @@ -147,6 +157,15 @@ static struct clk pll1_sysclk9 = {
>       .div_reg        = PLLDIV9,
>  };
>  
> +static struct clk clkout2_clk = {
> +     .name           = "clkout2",
> +     .parent         = &pll1_sysclk9,
> +     .flags          = CLK_PLL,
> +     .div_reg        = PLLDIV9,
> +     .set_rate       = set_sysclk_rate,
> +};
> +
> +
>  static struct clk pll2_clk = {
>       .name           = "pll2",
>       .parent         = &ref_clk,
> @@ -421,6 +440,7 @@ static struct clk_lookup dm365_clks[] = {
>       CLK(NULL, "pll1_sysclk7", &pll1_sysclk7),
>       CLK(NULL, "pll1_sysclk8", &pll1_sysclk8),
>       CLK(NULL, "pll1_sysclk9", &pll1_sysclk9),
> +     CLK(NULL, "clkout2", &clkout2_clk),
>       CLK(NULL, "pll2", &pll2_clk),
>       CLK(NULL, "pll2_aux", &pll2_aux_clk),
>       CLK(NULL, "clkout1", &clkout1_clk),
> @@ -467,9 +487,6 @@ static struct clk_lookup dm365_clks[] = {
>  
>  /*----------------------------------------------------------------------*/
>  
> -#define INTMUX               0x18
> -#define EVTMUX               0x1c
> -
>  
>  static const struct mux_config dm365_pins[] = {
>  #ifdef CONFIG_DAVINCI_MUX
> diff --git a/arch/arm/mach-davinci/include/mach/clock.h 
> b/arch/arm/mach-davinci/include/mach/clock.h
> index a3b0402..4296080 100644
> --- a/arch/arm/mach-davinci/include/mach/clock.h
> +++ b/arch/arm/mach-davinci/include/mach/clock.h
> @@ -18,4 +18,7 @@ struct clk;
>  extern int clk_register(struct clk *clk);
>  extern void clk_unregister(struct clk *clk);
>  
> +int clkout2_set_rate(struct clk *clk, unsigned long rate);
> +
> +
>  #endif
> -- 
> 1.7.0.4
>
> _______________________________________________
> Davinci-linux-open-source mailing list
> Davinci-linux-open-source@linux.davincidsp.com
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
_______________________________________________
Davinci-linux-open-source mailing list
Davinci-linux-open-source@linux.davincidsp.com
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to