Message ID | 1246886001-2285-2-git-send-email-nsekhar@ti.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Hello. Sekhar Nori wrote: > add basic cpufreq support for DA850/OMAP-L138 > Currently, frequency scaling only on PLL0 is supported. No scaling of PLL1 > or voltage levels as yet. > This patch also moves Async3 clock source to PLL1 so that frequency scaling > on PLL0 does not affect those peripherals. Without this the console on UART2 > goes for a toss the moment CPUFreq kicks in. > The OPP defintions assume clock input of 24MHz to the SoC. This is inline > with hardcoding of input frequency in the <soc>.c files. At some point > this will need to move into board dependent code as boards appear with > different input clock. > Tested with ondemand governer and a shell script to vary processor load. > Signed-off-by: Sekhar Nori <nsekhar@ti.com> > diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c > index 274f004..7a3a376 100644 > --- a/arch/arm/mach-davinci/da850.c > +++ b/arch/arm/mach-davinci/da850.c > @@ -15,6 +15,7 @@ > #include <linux/init.h> > #include <linux/clk.h> > #include <linux/platform_device.h> > +#include <linux/cpufreq.h> > > #include <asm/mach/map.h> > > @@ -32,14 +33,20 @@ > > #define DA850_PSC0_BASE 0x01c10000 > #define DA850_PLL0_BASE 0x01c11000 > -#define DA850_JTAG_ID_REG 0x01c14018 > #define DA850_TIMER64P0_BASE 0x01c20000 > #define DA850_TIMER64P1_BASE 0x01c21000 > #define DA850_GPIO_BASE 0x01e26000 > #define DA850_PSC1_BASE 0x01e27000 > #define DA850_PLL1_BASE 0x01e1a000 Please don't duplicate these #define's which are not specific to DA850 and are the same for DA830. Could you move them into soime header file instead -- probably <mach/hardware.h>? > +#define DA850_SYSCFG_BASE 0x01c14000 > +#define DA850_CFGCHIP0_REG (DA850_SYSCFG_BASE + 0x17c) > +#define DA850_CFGCHIP3_REG (DA850_SYSCFG_BASE + 0x188) > +#define DA850_JTAG_ID_REG (DA850_SYSCFG_BASE + 0x18) These registers are the same b/w DA830 and DA850. Place them into some header file instead. Note that I'll also need CHIPCFG2 #define for the USB platfrom code. WBR, Sergei
Hello, I wrote: >> add basic cpufreq support for DA850/OMAP-L138 >> Currently, frequency scaling only on PLL0 is supported. No scaling of >> PLL1 >> or voltage levels as yet. >> This patch also moves Async3 clock source to PLL1 so that frequency >> scaling >> on PLL0 does not affect those peripherals. Without this the console on >> UART2 >> goes for a toss the moment CPUFreq kicks in. >> The OPP defintions assume clock input of 24MHz to the SoC. This is inline >> with hardcoding of input frequency in the <soc>.c files. At some point >> this will need to move into board dependent code as boards appear with >> different input clock. >> Tested with ondemand governer and a shell script to vary processor load. >> Signed-off-by: Sekhar Nori <nsekhar@ti.com> >> diff --git a/arch/arm/mach-davinci/da850.c >> b/arch/arm/mach-davinci/da850.c >> index 274f004..7a3a376 100644 >> --- a/arch/arm/mach-davinci/da850.c >> +++ b/arch/arm/mach-davinci/da850.c >> @@ -15,6 +15,7 @@ >> #include <linux/init.h> >> #include <linux/clk.h> >> #include <linux/platform_device.h> >> +#include <linux/cpufreq.h> >> #include <asm/mach/map.h> >> @@ -32,14 +33,20 @@ >> #define DA850_PSC0_BASE 0x01c10000 >> #define DA850_PLL0_BASE 0x01c11000 >> -#define DA850_JTAG_ID_REG 0x01c14018 >> #define DA850_TIMER64P0_BASE 0x01c20000 >> #define DA850_TIMER64P1_BASE 0x01c21000 >> #define DA850_GPIO_BASE 0x01e26000 >> #define DA850_PSC1_BASE 0x01e27000 >> #define DA850_PLL1_BASE 0x01e1a000 > Please don't duplicate these #define's which are not specific to > DA850 and are the same for DA830. Could you move them into soime header > file instead -- probably <mach/hardware.h>? No, actually there's <mach/da8xx.h> for exactly that purpose. >> +#define DA850_SYSCFG_BASE 0x01c14000 >> +#define DA850_CFGCHIP0_REG (DA850_SYSCFG_BASE + 0x17c) >> +#define DA850_CFGCHIP3_REG (DA850_SYSCFG_BASE + 0x188) >> +#define DA850_JTAG_ID_REG (DA850_SYSCFG_BASE + 0x18) > These registers are the same b/w DA830 and DA850. Place them into > some header file instead. > Note that I'll also need CHIPCFG2 #define for the USB platfrom code. WBR, Sergei
On Mon, Jul 06, 2009 at 21:23:47, Sergei Shtylyov wrote: > Hello. > > Sekhar Nori wrote: > > > add basic cpufreq support for DA850/OMAP-L138 > > > Currently, frequency scaling only on PLL0 is supported. No scaling of PLL1 > > or voltage levels as yet. > > > This patch also moves Async3 clock source to PLL1 so that frequency scaling > > on PLL0 does not affect those peripherals. Without this the console on UART2 > > goes for a toss the moment CPUFreq kicks in. > > > The OPP defintions assume clock input of 24MHz to the SoC. This is inline > > with hardcoding of input frequency in the <soc>.c files. At some point > > this will need to move into board dependent code as boards appear with > > different input clock. > > > Tested with ondemand governer and a shell script to vary processor load. > > > Signed-off-by: Sekhar Nori <nsekhar@ti.com> > > > diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c > > index 274f004..7a3a376 100644 > > --- a/arch/arm/mach-davinci/da850.c > > +++ b/arch/arm/mach-davinci/da850.c > > @@ -15,6 +15,7 @@ > > #include <linux/init.h> > > #include <linux/clk.h> > > #include <linux/platform_device.h> > > +#include <linux/cpufreq.h> > > > > #include <asm/mach/map.h> > > > > @@ -32,14 +33,20 @@ > > > > #define DA850_PSC0_BASE 0x01c10000 > > #define DA850_PLL0_BASE 0x01c11000 > > -#define DA850_JTAG_ID_REG 0x01c14018 > > #define DA850_TIMER64P0_BASE 0x01c20000 > > #define DA850_TIMER64P1_BASE 0x01c21000 > > #define DA850_GPIO_BASE 0x01e26000 > > #define DA850_PSC1_BASE 0x01e27000 > > #define DA850_PLL1_BASE 0x01e1a000 > > Please don't duplicate these #define's which are not specific to DA850 > and are the same for DA830. Could you move them into soime header file > instead -- probably <mach/hardware.h>? > Sergei, The above lines were added by my DA850/OMAP-L138 SoC and EVM patches. I'll move them to mach/da8xx.h file when I submit my next version of the patches. Kevin, Do you have any objections to moving these #defines to mach/da8xx.h file as they'll be common across DA830/OMAP-L137 and DA850/OMAP-L138? Regards, Sudhakar
"Rajashekhara, Sudhakar" <sudhakar.raj@ti.com> writes: > On Mon, Jul 06, 2009 at 21:23:47, Sergei Shtylyov wrote: >> Hello. >> >> Sekhar Nori wrote: >> >> > add basic cpufreq support for DA850/OMAP-L138 >> >> > Currently, frequency scaling only on PLL0 is supported. No scaling of PLL1 >> > or voltage levels as yet. >> >> > This patch also moves Async3 clock source to PLL1 so that frequency scaling >> > on PLL0 does not affect those peripherals. Without this the console on UART2 >> > goes for a toss the moment CPUFreq kicks in. >> >> > The OPP defintions assume clock input of 24MHz to the SoC. This is inline >> > with hardcoding of input frequency in the <soc>.c files. At some point >> > this will need to move into board dependent code as boards appear with >> > different input clock. >> >> > Tested with ondemand governer and a shell script to vary processor load. >> >> > Signed-off-by: Sekhar Nori <nsekhar@ti.com> >> >> > diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c >> > index 274f004..7a3a376 100644 >> > --- a/arch/arm/mach-davinci/da850.c >> > +++ b/arch/arm/mach-davinci/da850.c >> > @@ -15,6 +15,7 @@ >> > #include <linux/init.h> >> > #include <linux/clk.h> >> > #include <linux/platform_device.h> >> > +#include <linux/cpufreq.h> >> > >> > #include <asm/mach/map.h> >> > >> > @@ -32,14 +33,20 @@ >> > >> > #define DA850_PSC0_BASE 0x01c10000 >> > #define DA850_PLL0_BASE 0x01c11000 >> > -#define DA850_JTAG_ID_REG 0x01c14018 >> > #define DA850_TIMER64P0_BASE 0x01c20000 >> > #define DA850_TIMER64P1_BASE 0x01c21000 >> > #define DA850_GPIO_BASE 0x01e26000 >> > #define DA850_PSC1_BASE 0x01e27000 >> > #define DA850_PLL1_BASE 0x01e1a000 >> >> Please don't duplicate these #define's which are not specific to DA850 >> and are the same for DA830. Could you move them into soime header file >> instead -- probably <mach/hardware.h>? >> > > Sergei, > The above lines were added by my DA850/OMAP-L138 SoC and EVM patches. > I'll move them to mach/da8xx.h file when I submit my next version of > the patches. > > Kevin, > Do you have any objections to moving these #defines to mach/da8xx.h file > as they'll be common across DA830/OMAP-L137 and DA850/OMAP-L138? I think that is a good idea. Thanks, Kevin
different input clock. Tested with ondemand governer and a shell script to vary processor load. Signed-off-by: Sekhar Nori <nsekhar@ti.com> --- arch/arm/mach-davinci/da850.c | 152 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 149 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 274f004..7a3a376 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/cpufreq.h> #include <asm/mach/map.h> @@ -32,14 +33,20 @@ #define DA850_PSC0_BASE 0x01c10000 #define DA850_PLL0_BASE 0x01c11000 -#define DA850_JTAG_ID_REG 0x01c14018 #define DA850_TIMER64P0_BASE 0x01c20000 #define DA850_TIMER64P1_BASE 0x01c21000 #define DA850_GPIO_BASE 0x01e26000 #define DA850_PSC1_BASE 0x01e27000 #define DA850_PLL1_BASE 0x01e1a000 +#define DA850_SYSCFG_BASE 0x01c14000 +#define DA850_CFGCHIP0_REG (DA850_SYSCFG_BASE + 0x17c) +#define DA850_CFGCHIP3_REG (DA850_SYSCFG_BASE + 0x188) +#define DA850_JTAG_ID_REG (DA850_SYSCFG_BASE + 0x18) + #define DA850_REF_FREQ 24000000 +static int da850_set_armrate(struct clk *clk, unsigned long rate); +static int da850_round_armrate(struct clk *clk, unsigned long rate); static struct pll_data pll0_data = { .num = 1, @@ -235,14 +242,14 @@ static struct clk uart0_clk = { static struct clk uart1_clk = { .name = "uart1", - .parent = &pll0_sysclk2, + .parent = &pll1_sysclk2, .lpsc = DA8XX_LPSC1_UART1, .psc_ctlr = 1, }; static struct clk uart2_clk = { .name = "uart2", - .parent = &pll0_sysclk2, + .parent = &pll1_sysclk2, .lpsc = DA8XX_LPSC1_UART2, .psc_ctlr = 1, }; @@ -281,6 +288,8 @@ static struct clk arm_clk = { .parent = &pll0_sysclk6, .lpsc = DA8XX_LPSC0_ARM, .flags = ALWAYS_ENABLED, + .set_rate = da850_set_armrate, + .round_rate = da850_round_armrate, }; static struct clk rmii_clk = { @@ -600,6 +609,65 @@ static struct davinci_timer_info da850_timer_info = { .clocksource_id = T0_TOP, }; +#define MAX_NUM_OPP 3 + +/* + * Notes: + * According to the TRM, minimum PLLM results in max power savings. + * The OPP definitions below should keep the PLLM as low as possible. + * + * The output of the PLLM must be between 400 to 600 MHz. + * This rules out prediv of anything but divide-by-one for 24Mhz OSC input. + */ +struct da850_opp { + unsigned int freq; /* in KHz */ + unsigned int prediv; + unsigned int mult; + unsigned int postdiv; +}; + +static const struct da850_opp da850_opp_300 = { + .freq = 300000, + .prediv = 1, + .mult = 25, + .postdiv = 2, +}; + +static const struct da850_opp da850_opp_200 = { + .freq = 200000, + .prediv = 1, + .mult = 25, + .postdiv = 3, +}; + +static const struct da850_opp da850_opp_96 = { + .freq = 96000, + .prediv = 1, + .mult = 20, + .postdiv = 5, +}; + +#define OPP(freq) \ + { \ + .index = (unsigned int) &da850_opp_##freq, \ + .frequency = freq * 1000, \ + } + +static struct cpufreq_frequency_table da850_freq_table[MAX_NUM_OPP+1] = { + OPP(300), + OPP(200), + OPP(96), + { + .index = 0, + .frequency = CPUFREQ_TABLE_END, + }, +}; + +void da850_init_cpufreq_table(struct cpufreq_frequency_table **table) +{ + *table = &da850_freq_table[0]; +} + static struct davinci_soc_info davinci_soc_info_da850 = { .io_desc = da850_io_desc, .io_desc_num = ARRAY_SIZE(da850_io_desc), @@ -622,9 +690,87 @@ static struct davinci_soc_info davinci_soc_info_da850 = { .gpio_irq = IRQ_DA8XX_GPIO0, .serial_dev = &da8xx_serial_device, .emac_pdata = &da8xx_emac_pdata, + .init_cpufreq_table = da850_init_cpufreq_table, }; +static int da850_round_armrate(struct clk *clk, unsigned long rate) +{ + int i, ret = 0, diff; + unsigned int best = (unsigned int) -1; + + rate /= 1000; /* convert to kHz */ + + for (i = 0; da850_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + diff = da850_freq_table[i].frequency - rate; + if (diff < 0) + diff = -diff; + + if (diff < best) { + best = diff; + ret = da850_freq_table[i].frequency; + } + } + + return ret * 1000; +} + +static int da850_set_armrate(struct clk *clk, unsigned long rate) +{ + int i, ret; + unsigned int prediv, mult, postdiv; + struct da850_opp *opp; + struct clk *pllclk = &pll0_clk; + struct pll_data *pll = pllclk->pll_data; + + /* convert to KHz */ + rate /= 1000; + + for (i = 0; da850_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + if (rate == da850_freq_table[i].frequency) + break; + } + + if (da850_freq_table[i].frequency == CPUFREQ_TABLE_END) { + printk(KERN_WARNING "%s: Unsupported ARM clock rate %ld\n", + __func__, rate); + return -EINVAL; + } + + opp = (struct da850_opp *) da850_freq_table[i].index; + prediv = opp->prediv; + mult = opp->mult; + postdiv = opp->postdiv; + + /* Unlock writing to PLL registers */ + __raw_writel(__raw_readl(IO_ADDRESS(DA850_CFGCHIP0_REG)) & ~BIT(4), + IO_ADDRESS(DA850_CFGCHIP0_REG)); + + ret = davinci_set_pllrate(pll, prediv, mult, postdiv); + if (ret) + return ret; + + /* Propogate new rate */ + pllclk->rate = pllclk->parent->rate; + pllclk->rate /= prediv; + pllclk->rate *= mult; + pllclk->rate /= postdiv; + + /* FIXME: unnecessarily re-calculates rates for PLL1 as well */ + davinci_clk_recalc_rates(da850_clks); + + return 0; +} + void __init da850_init(void) { davinci_common_init(&davinci_soc_info_da850); + + /* + * set Async3 clock source to come from PLL1 so PLL0 frequency changes + * dont affect as many peripherals as possible. + * Note: This changes the clock source for UART1/2. So, low level debug + * will garble beyond this point if the source rate changes. + */ + __raw_writel(__raw_readl(IO_ADDRESS(DA850_CFGCHIP3_REG)) | BIT(4), + IO_ADDRESS(DA850_CFGCHIP3_REG)); }