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