[U-Boot] [PATCH 0/4] Exynos5: Add cpu freq and tmu throttling

This patch set adds cpu frequency scaling and tmu throttling for exynos5.
Akshay Saraswat (4): pmic: max77686: add pmic_set_voltage api for max77686 Exynos5: cpufreq: Implement frequency scaling for exynos5 smdk5250: enable support for tmu throttling Exynos5: config: enable cpu freq
arch/arm/include/asm/arch-exynos/cpufreq.h | 54 ++++++ board/samsung/smdk5250/smdk5250.c | 19 ++ drivers/power/Makefile | 1 + drivers/power/exynos-cpufreq.c | 282 +++++++++++++++++++++++++++++ drivers/power/pmic/pmic_max77686.c | 61 +++++++ include/configs/exynos5250-dt.h | 3 + include/power/max77686_pmic.h | 12 ++ include/power/pmic.h | 1 + 8 files changed, 433 insertions(+) create mode 100644 arch/arm/include/asm/arch-exynos/cpufreq.h create mode 100644 drivers/power/exynos-cpufreq.c

This patch adds pmic_set_voltage api in max77686. As the name suggests, this api is required for switching voltage from one level to another.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com --- drivers/power/pmic/pmic_max77686.c | 61 ++++++++++++++++++++++++++++++++++++++ include/power/max77686_pmic.h | 12 ++++++++ include/power/pmic.h | 1 + 3 files changed, 74 insertions(+)
diff --git a/drivers/power/pmic/pmic_max77686.c b/drivers/power/pmic/pmic_max77686.c index 7fcb4c0..d8782f8 100644 --- a/drivers/power/pmic/pmic_max77686.c +++ b/drivers/power/pmic/pmic_max77686.c @@ -77,3 +77,64 @@ int pmic_init(unsigned char bus)
return 0; } + +int pmic_set_voltage(u32 new_voltage) +{ + struct pmic *p; + u32 read_data, volt_level, ret; + + p = pmic_get("MAX77686_PMIC"); + if (!p) + return -ENODEV; + + /* Read BUCK2 DVS1 value */ + ret = pmic_reg_read(p, MAX77686_REG_PMIC_BUCK2DVS1, &read_data); + if (ret != 0) { + debug("CPUFREQ: max77686 BUCK2 DVS1 register read failed.\n"); + return -1; + } + + /* Calculate voltage level */ + volt_level = new_voltage - MAX77686_BUCK2_VOL_MIN * 1000; + + if (volt_level < 0) { + debug("CPUFREQ: Not a valid voltage level to set\n"); + return -1; + } + + volt_level /= MAX77686_BUCK2_VOL_DIV; + + /* Update voltage level in BUCK2 DVS1 register value */ + clrsetbits_8(&read_data, + MAX77686_BUCK2_VOL_BITMASK << MAX77686_BUCK2_VOL_BITPOS, + volt_level << MAX77686_BUCK2_VOL_BITPOS); + + /* Write new value in BUCK2 DVS1 */ + ret = pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1, read_data); + if (ret != 0) { + debug("CPUFREQ: max77686 BUCK2 DVS1 register write failed.\n"); + return -1; + } + + /* Set ENABLE BUCK2 register bits */ + read_data = 0; + ret = pmic_reg_read(p, MAX77686_BUCK2_VOL_ENADDR, &read_data); + if (ret != 0) { + debug("CPUFREQ: max77686 BUCK2 enable address read failed.\n"); + return -1; + } + + clrsetbits_8(&read_data, + (MAX77686_BUCK2_VOL_ENBITMASK + << MAX77686_BUCK2_VOL_ENBITPOS), + (MAX77686_BUCK2_VOL_ENBITON + << MAX77686_BUCK2_VOL_ENBITPOS)); + + ret = pmic_reg_write(p, MAX77686_BUCK2_VOL_ENADDR, read_data); + if (ret != 0) { + debug("CPUFREQ: max77686 BUCK2 enable address write failed.\n"); + return -1; + } + + return 0; +} diff --git a/include/power/max77686_pmic.h b/include/power/max77686_pmic.h index fdc7ca9..2780f17 100644 --- a/include/power/max77686_pmic.h +++ b/include/power/max77686_pmic.h @@ -175,6 +175,18 @@ enum { #define MAX77686_LD05CTRL1_1_8V 0x14 /* LDO10 1.8 volt value */ #define MAX77686_LD10CTRL1_1_8V 0x14 + +/* BUCK2 voltage parameter values */ +#define MAX77686_BUCK2_VOL_BITPOS 0x0 +#define MAX77686_BUCK2_VOL_BITMASK 0xff +#define MAX77686_BUCK2_VOL_ENBITPOS 0x4 +#define MAX77686_BUCK2_VOL_ENBITMASK 0x3 +#define MAX77686_BUCK2_VOL_ENADDR 0x12 +#define MAX77686_BUCK2_VOL_ENBITON 0x1 +#define MAX77686_BUCK2_VOL_ENBITOFF 0x0 +#define MAX77686_BUCK2_VOL_MIN 925 +#define MAX77686_BUCK2_VOL_DIV 12500 + /* * MAX77686_REG_PMIC_32KHZ set to 32KH CP * output is activated diff --git a/include/power/pmic.h b/include/power/pmic.h index 1ecfc05..02f6f11 100644 --- a/include/power/pmic.h +++ b/include/power/pmic.h @@ -99,6 +99,7 @@ int pmic_probe(struct pmic *p); int pmic_reg_read(struct pmic *p, u32 reg, u32 *val); int pmic_reg_write(struct pmic *p, u32 reg, u32 val); int pmic_set_output(struct pmic *p, u32 reg, int ldo, int on); +int pmic_set_voltage(u32 new_voltage);
#define pmic_i2c_addr (p->hw.i2c.addr) #define pmic_i2c_tx_num (p->hw.i2c.tx_num)

Hi Akshay,
On Wed, Apr 3, 2013 at 12:27 AM, Akshay Saraswat akshay.s@samsung.com wrote:
This patch adds pmic_set_voltage api in max77686. As the name suggests, this api is required for switching voltage from one level to another.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com
drivers/power/pmic/pmic_max77686.c | 61 ++++++++++++++++++++++++++++++++++++++ include/power/max77686_pmic.h | 12 ++++++++ include/power/pmic.h | 1 + 3 files changed, 74 insertions(+)
diff --git a/drivers/power/pmic/pmic_max77686.c b/drivers/power/pmic/pmic_max77686.c index 7fcb4c0..d8782f8 100644 --- a/drivers/power/pmic/pmic_max77686.c +++ b/drivers/power/pmic/pmic_max77686.c @@ -77,3 +77,64 @@ int pmic_init(unsigned char bus)
return 0;
}
+int pmic_set_voltage(u32 new_voltage) +{
struct pmic *p;
u32 read_data, volt_level, ret;
p = pmic_get("MAX77686_PMIC");
if (!p)
return -ENODEV;
/* Read BUCK2 DVS1 value */
ret = pmic_reg_read(p, MAX77686_REG_PMIC_BUCK2DVS1, &read_data);
if (ret != 0) {
debug("CPUFREQ: max77686 BUCK2 DVS1 register read failed.\n");
return -1;
}
/* Calculate voltage level */
volt_level = new_voltage - MAX77686_BUCK2_VOL_MIN * 1000;
if (volt_level < 0) {
debug("CPUFREQ: Not a valid voltage level to set\n");
return -1;
}
volt_level /= MAX77686_BUCK2_VOL_DIV;
/* Update voltage level in BUCK2 DVS1 register value */
clrsetbits_8(&read_data,
MAX77686_BUCK2_VOL_BITMASK << MAX77686_BUCK2_VOL_BITPOS,
volt_level << MAX77686_BUCK2_VOL_BITPOS);
/* Write new value in BUCK2 DVS1 */
ret = pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1, read_data);
if (ret != 0) {
debug("CPUFREQ: max77686 BUCK2 DVS1 register write failed.\n");
return -1;
}
/* Set ENABLE BUCK2 register bits */
read_data = 0;
ret = pmic_reg_read(p, MAX77686_BUCK2_VOL_ENADDR, &read_data);
if (ret != 0) {
debug("CPUFREQ: max77686 BUCK2 enable address read failed.\n");
return -1;
}
clrsetbits_8(&read_data,
(MAX77686_BUCK2_VOL_ENBITMASK
<< MAX77686_BUCK2_VOL_ENBITPOS),
(MAX77686_BUCK2_VOL_ENBITON
<< MAX77686_BUCK2_VOL_ENBITPOS));
ret = pmic_reg_write(p, MAX77686_BUCK2_VOL_ENADDR, read_data);
if (ret != 0) {
debug("CPUFREQ: max77686 BUCK2 enable address write failed.\n");
return -1;
}
return 0;
+} diff --git a/include/power/max77686_pmic.h b/include/power/max77686_pmic.h index fdc7ca9..2780f17 100644 --- a/include/power/max77686_pmic.h +++ b/include/power/max77686_pmic.h @@ -175,6 +175,18 @@ enum { #define MAX77686_LD05CTRL1_1_8V 0x14 /* LDO10 1.8 volt value */ #define MAX77686_LD10CTRL1_1_8V 0x14
+/* BUCK2 voltage parameter values */ +#define MAX77686_BUCK2_VOL_BITPOS 0x0 +#define MAX77686_BUCK2_VOL_BITMASK 0xff +#define MAX77686_BUCK2_VOL_ENBITPOS 0x4 +#define MAX77686_BUCK2_VOL_ENBITMASK 0x3 +#define MAX77686_BUCK2_VOL_ENADDR 0x12 +#define MAX77686_BUCK2_VOL_ENBITON 0x1 +#define MAX77686_BUCK2_VOL_ENBITOFF 0x0 +#define MAX77686_BUCK2_VOL_MIN 925 +#define MAX77686_BUCK2_VOL_DIV 12500
/*
- MAX77686_REG_PMIC_32KHZ set to 32KH CP
- output is activated
diff --git a/include/power/pmic.h b/include/power/pmic.h index 1ecfc05..02f6f11 100644 --- a/include/power/pmic.h +++ b/include/power/pmic.h @@ -99,6 +99,7 @@ int pmic_probe(struct pmic *p); int pmic_reg_read(struct pmic *p, u32 reg, u32 *val); int pmic_reg_write(struct pmic *p, u32 reg, u32 val); int pmic_set_output(struct pmic *p, u32 reg, int ldo, int on); +int pmic_set_voltage(u32 new_voltage);
Please can you document what 'new_voltage' means in a function comment? Is it microvolts, or something else?
Regards, Simon
#define pmic_i2c_addr (p->hw.i2c.addr)
#define pmic_i2c_tx_num (p->hw.i2c.tx_num)
1.8.0

Exynos5 currently runs at full speed i.e. 1.7 GHz everytime. Scaling down the clock speed in certain situations, may help in reducing the ARM temperature and power consumption.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com --- arch/arm/include/asm/arch-exynos/cpufreq.h | 54 ++++++ drivers/power/Makefile | 1 + drivers/power/exynos-cpufreq.c | 282 +++++++++++++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 arch/arm/include/asm/arch-exynos/cpufreq.h create mode 100644 drivers/power/exynos-cpufreq.c
diff --git a/arch/arm/include/asm/arch-exynos/cpufreq.h b/arch/arm/include/asm/arch-exynos/cpufreq.h new file mode 100644 index 0000000..173e804 --- /dev/null +++ b/arch/arm/include/asm/arch-exynos/cpufreq.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS - CPU frequency scaling support + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Define various levels of ARM frequency */ +enum cpufreq_level { + CPU_FREQ_L200, /* 200 MHz */ + CPU_FREQ_L300, /* 300 MHz */ + CPU_FREQ_L400, /* 400 MHz */ + CPU_FREQ_L500, /* 500 MHz */ + CPU_FREQ_L600, /* 600 MHz */ + CPU_FREQ_L700, /* 700 MHz */ + CPU_FREQ_L800, /* 800 MHz */ + CPU_FREQ_L900, /* 900 MHz */ + CPU_FREQ_L1000, /* 1000 MHz */ + CPU_FREQ_L1100, /* 1100 MHz */ + CPU_FREQ_L1200, /* 1200 MHz */ + CPU_FREQ_L1300, /* 1300 MHz */ + CPU_FREQ_L1400, /* 1400 MHz */ + CPU_FREQ_L1500, /* 1500 MHz */ + CPU_FREQ_L1600, /* 1600 MHz */ + CPU_FREQ_L1700, /* 1700 MHz */ + CPU_FREQ_LCOUNT, +}; + +/* + * Initialize ARM frequency scaling + * + * @param blob FDT blob + * @return int value, 0 for success + */ +int exynos_cpufreq_init(void); + +/* + * Switch ARM frequency to new level + * + * @param new_freq_level enum cpufreq_level, states new frequency + * @return int value, 0 for success + */ +int exynos_set_frequency(enum cpufreq_level new_freq_level); diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 1dac16a..4589d9b 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_TPS6586X_POWER) += tps6586x.o COBJS-$(CONFIG_TWL4030_POWER) += twl4030.o COBJS-$(CONFIG_TWL6030_POWER) += twl6030.o COBJS-$(CONFIG_TWL6035_POWER) += twl6035.o +COBJS-$(CONFIG_EXYNOS_CPUFREQ) += exynos-cpufreq.o
COBJS-$(CONFIG_POWER) += power_core.o COBJS-$(CONFIG_DIALOG_POWER) += power_dialog.o diff --git a/drivers/power/exynos-cpufreq.c b/drivers/power/exynos-cpufreq.c new file mode 100644 index 0000000..f473167 --- /dev/null +++ b/drivers/power/exynos-cpufreq.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS - CPU frequency scaling support + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <power/pmic.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include <asm/arch/cpufreq.h> + +/* APLL CON0 */ +#define CON0_LOCK_BIT_MASK (0x1 << 29) +#define MDIV_MASK(x) (x << 16) +#define PDIV_MASK(x) (x << 8) +#define SDIV_MASK(x) (x << 0) +#define APLL_PMS_MASK ~(MDIV_MASK(0x3ff) \ + | PDIV_MASK(0x3f) | SDIV_MASK(0x7)) + +/* MUX_STAT CPU select */ +#define MUX_CPU_NONE (0x7 << 16) +#define MUX_CPU_MOUT_APLL (0x1 << 16) + +/* CLK_DIV_CPU0_VAL */ +#define DIV_CPU0_RSVD ~((0x7 << 28) \ + | (0x7 << 24) \ + | (0x7 << 20) \ + | (0x7 << 16) \ + | (0x7 << 12) \ + | (0x7 << 8) \ + | (0x7 << 4) \ + | (0x7)) + +/* CLK_DIV_CPU1 */ +#define DIV_CPU1_RSVD ~((0x7 << 4) | (0x7)) + +struct cpufreq_clkdiv { + uint8_t cpu0; + uint8_t cpu1; +}; + +struct cpufreq_data { + uint8_t arm; + uint8_t cpud; + uint8_t acp; + uint8_t periph; + uint8_t atb; + uint8_t pclk_dbg; + uint8_t apll; + uint8_t arm2; + uint8_t copy; + uint8_t hpm; + uint32_t apll_mdiv; + uint32_t apll_pdiv; + uint32_t apll_sdiv; + uint32_t volt; +}; + +static enum cpufreq_level old_freq_level; +static struct cpufreq_clkdiv exynos5250_clkdiv; + +/* + * Clock divider, PMS and ASV group voltage values corresponding + * to frequencies. + */ +static struct cpufreq_data exynos5250_data_table[CPU_FREQ_LCOUNT] = { + /* + * { ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2, COPY, HPM, + * APLL_MDIV, APLL_PDIV, APLL_SDIV, VOLTAGE } + */ + { 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 100, 3, 2, 925000 }, /* 200 MHz */ + { 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 200, 4, 2, 937500 }, /* 300 MHz */ + { 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 100, 3, 1, 950000 }, /* 400 MHz */ + { 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 125, 3, 1, 975000 }, /* 500 MHz */ + { 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 200, 4, 1, 1000000 }, /* 600 MHz */ + { 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 175, 3, 1, 1012500 }, /* 700 MHz */ + { 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 100, 3, 0, 1025000 }, /* 800 MHz */ + { 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 150, 4, 0, 1050000 }, /* 900 MHz */ + { 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 125, 3, 0, 1075000 }, /* 1000 MHz */ + { 0, 3, 7, 7, 5, 1, 3, 0, 0, 2, 275, 6, 0, 1100000 }, /* 1100 MHz */ + { 0, 2, 7, 7, 5, 1, 3, 0, 0, 2, 200, 4, 0, 1125000 }, /* 1200 MHz */ + { 0, 2, 7, 7, 6, 1, 3, 0, 0, 2, 325, 6, 0, 1150000 }, /* 1300 MHz */ + { 0, 2, 7, 7, 6, 1, 4, 0, 0, 2, 175, 3, 0, 1200000 }, /* 1400 MHz */ + { 0, 2, 7, 7, 7, 1, 4, 0, 0, 2, 250, 4, 0, 1225000 }, /* 1500 MHz */ + { 0, 3, 7, 7, 7, 1, 4, 0, 0, 2, 200, 3, 0, 1250000 }, /* 1600 MHz */ + { 0, 3, 7, 7, 7, 2, 5, 0, 0, 2, 425, 6, 0, 1300000 }, /* 1700 MHz */ +}; + +/* + * Set clock divider values to alter exynos5 frequency + * + * @param new_freq_level enum cpufreq_level, states new frequency + * @param clk struct exynos5_clock *, + * provides clock reg addresses + */ +static void exynos5_set_clkdiv(enum cpufreq_level new_freq_level, + struct exynos5_clock *clk) +{ + unsigned int val; + + /* Change Divider - CPU0 */ + val = exynos5250_clkdiv.cpu0; + + val |= (exynos5250_data_table[new_freq_level].arm << 0) | + (exynos5250_data_table[new_freq_level].cpud << 4) | + (exynos5250_data_table[new_freq_level].acp << 8) | + (exynos5250_data_table[new_freq_level].periph << 12) | + (exynos5250_data_table[new_freq_level].atb << 16) | + (exynos5250_data_table[new_freq_level].pclk_dbg << 20) | + (exynos5250_data_table[new_freq_level].apll << 24) | + (exynos5250_data_table[new_freq_level].arm2 << 28); + + writel(val, &clk->div_cpu0); + + /* Wait for CPU0 divider to be stable */ + while (readl(&clk->div_stat_cpu0) & 0x11111111) + ; + + /* Change Divider - CPU1 */ + val = exynos5250_clkdiv.cpu1; + + val |= (exynos5250_data_table[new_freq_level].copy << 0) | + (exynos5250_data_table[new_freq_level].hpm << 4); + + writel(val, &clk->div_cpu1); + + /* Wait for CPU1 divider to be stable */ + while (readl(&clk->div_stat_cpu1) & 0x11) + ; +} + +/* + * Set APLL values to alter exynos5 frequency + * + * @param new_freq_level enum cpufreq_level, states new frequency + * @param clk struct exynos5_clock *, + * provides clock reg addresses + */ +static void exynos5_set_apll(enum cpufreq_level new_freq_level, + struct exynos5_clock *clk) +{ + unsigned int val, pdiv; + + /* Set APLL Lock time */ + pdiv = exynos5250_data_table[new_freq_level].apll_pdiv; + writel((pdiv * 250), &clk->apll_lock); + + /* Change PLL PMS values */ + val = readl(&clk->apll_con0); + val &= APLL_PMS_MASK; + val |= MDIV_MASK(exynos5250_data_table[new_freq_level].apll_mdiv) | + PDIV_MASK(exynos5250_data_table[new_freq_level].apll_pdiv) | + SDIV_MASK(exynos5250_data_table[new_freq_level].apll_sdiv); + writel(val, &clk->apll_con0); + + /* Wait for APLL lock time to complete */ + while (!(readl(&clk->apll_con0) & CON0_LOCK_BIT_MASK)) + ; +} + +/* + * Switch ARM power corresponding to new frequency level + * + * @param new_volt_index enum cpufreq_level, provides new voltage + * corresponing to new frequency level + * @return int value, 0 for success + */ +static int exynos5_set_voltage(enum cpufreq_level new_volt_index) +{ + u32 new_volt; + + new_volt = exynos5250_data_table[new_volt_index].volt; + + return pmic_set_voltage(new_volt); +} + +/* + * Switch exybos5 frequency to new level + * + * @param new_freq_level enum cpufreq_level, provides new frequency + * @return int value, 0 for success + */ +static int exynos5_set_frequency(enum cpufreq_level new_freq_level) +{ + int error = 0; + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + if (old_freq_level < new_freq_level) { + /* Alter voltage corresponding to new frequency */ + error = exynos5_set_voltage(new_freq_level); + + /* Change the system clock divider values */ + exynos5_set_clkdiv(new_freq_level, clk); + + /* Change the apll m,p,s value */ + exynos5_set_apll(new_freq_level, clk); + } else if (old_freq_level > new_freq_level) { + /* Change the apll m,p,s value */ + exynos5_set_apll(new_freq_level, clk); + + /* Change the system clock divider values */ + exynos5_set_clkdiv(new_freq_level, clk); + + /* Alter voltage corresponding to new frequency */ + error = exynos5_set_voltage(new_freq_level); + } + + old_freq_level = new_freq_level; + debug("ARM Frequency changed\n"); + + return error; +} + +/* + * Switch ARM frequency to new level + * + * @param new_freq_level enum cpufreq_level, states new frequency + * @return int value, 0 for success + */ +int exynos_set_frequency(enum cpufreq_level new_freq_level) +{ + if (cpu_is_exynos5()) { + return exynos5_set_frequency(new_freq_level); + } else { + debug("CPUFREQ: Frequency scaling not allowed for this CPU\n"); + return -1; + } +} + +/* + * Initialize frequency scaling for exynos5 + */ +static void exynos5_cpufreq_init(void) +{ + unsigned int val; + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + /* Save default divider ratios for CPU0 */ + val = readl(&clk->div_cpu0); + val &= DIV_CPU0_RSVD; + exynos5250_clkdiv.cpu0 = val; + + /* Save default divider ratios for CPU1 */ + val = readl(&clk->div_cpu1); + val &= DIV_CPU1_RSVD; + exynos5250_clkdiv.cpu1 = val; + + /* Calculate default ARM frequence level */ + old_freq_level = (get_pll_clk(APLL) / 100000000) - 2; + debug("Current ARM frequency is %u\n", val); +} + +/* + * Initialize ARM frequency scaling + * + * @return int value, 0 for success + */ +int exynos_cpufreq_init(void) +{ + if (cpu_is_exynos5()) { + exynos5_cpufreq_init(); + return 0; + } else { + debug("CPUFREQ: Could not init for this CPU\n"); + return -1; + } +}

Hi Akshay,
On Wed, Apr 3, 2013 at 12:27 AM, Akshay Saraswat akshay.s@samsung.com wrote:
Exynos5 currently runs at full speed i.e. 1.7 GHz everytime. Scaling down the clock speed in certain situations, may help in reducing the ARM temperature and power consumption.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com
arch/arm/include/asm/arch-exynos/cpufreq.h | 54 ++++++ drivers/power/Makefile | 1 + drivers/power/exynos-cpufreq.c | 282 +++++++++++++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 arch/arm/include/asm/arch-exynos/cpufreq.h create mode 100644 drivers/power/exynos-cpufreq.c
There may be a couple of style nits here I think (do you use patman or checkpatch?) but otherwise:
Acked-by: Simon Glass sjg@chromium.org

Hi Simon,
Hi Akshay,
On Wed, Apr 3, 2013 at 12:27 AM, Akshay Saraswat akshay.s@samsung.com wrote:
Exynos5 currently runs at full speed i.e. 1.7 GHz everytime. Scaling down the clock speed in certain situations, may help in reducing the ARM temperature and power consumption.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com
arch/arm/include/asm/arch-exynos/cpufreq.h | 54 ++++++ drivers/power/Makefile | 1 + drivers/power/exynos-cpufreq.c | 282 +++++++++++++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 arch/arm/include/asm/arch-exynos/cpufreq.h create mode 100644 drivers/power/exynos-cpufreq.c
There may be a couple of style nits here I think (do you use patman or checkpatch?) but otherwise:
Acked-by: Simon Glass sjg@chromium.org
Yes, I did use tools/checkpach from u-boot-samsung to verify style errors in these patches, I didn't get any. It shows 0 errors and 0 warnings for all 4 patches. No wonder, there could be few things which checkpatch might not have caught. Please let me know the errors, I'll rectify them. And also, I am pushing one more revision for PMIC set-voltage patch with function comment. Please review it.
Regards, Akshay Saraswat

Hi Akshay,
On Sun, May 12, 2013 at 11:15 PM, Akshay Saraswat akshay.s@samsung.com wrote:
Hi Simon,
Hi Akshay,
On Wed, Apr 3, 2013 at 12:27 AM, Akshay Saraswat akshay.s@samsung.com wrote:
Exynos5 currently runs at full speed i.e. 1.7 GHz everytime. Scaling down the clock speed in certain situations, may help in reducing the ARM temperature and power consumption.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com
arch/arm/include/asm/arch-exynos/cpufreq.h | 54 ++++++ drivers/power/Makefile | 1 + drivers/power/exynos-cpufreq.c | 282 +++++++++++++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 arch/arm/include/asm/arch-exynos/cpufreq.h create mode 100644 drivers/power/exynos-cpufreq.c
There may be a couple of style nits here I think (do you use patman or checkpatch?) but otherwise:
Acked-by: Simon Glass sjg@chromium.org
Yes, I did use tools/checkpach from u-boot-samsung to verify style errors in these patches, I didn't get any. It shows 0 errors and 0 warnings for all 4 patches. No wonder, there could be few things which checkpatch might not have caught. Please let me know the errors, I'll rectify them.
Sorry I can't see what I noticed last time, it looks good!
And also, I am pushing one more revision for PMIC set-voltage patch with function comment. Please review it.
OK, will do.
I am hoping to collect up all the outstanding patches and put them somewhere for testing.
Regards, Simon

Adding tmu throttling support to smdk5250.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com --- board/samsung/smdk5250/smdk5250.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/board/samsung/smdk5250/smdk5250.c b/board/samsung/smdk5250/smdk5250.c index 8b09e1d..301dcf8 100644 --- a/board/samsung/smdk5250/smdk5250.c +++ b/board/samsung/smdk5250/smdk5250.c @@ -38,6 +38,8 @@ #include <power/pmic.h> #include <power/max77686_pmic.h> #include <tmu.h> +#include <asm/arch/cpufreq.h> +#include <asm/arch/clk.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -58,6 +60,15 @@ static void boot_temp_check(void) break; case TMU_STATUS_WARNING: puts("EXYNOS_TMU: WARNING! Temperature very high\n"); +#ifdef CONFIG_EXYNOS_CPUFREQ + exynos_set_frequency(CPU_FREQ_L400); +#endif + break; + case TMU_STATUS_NORMAL: +#ifdef CONFIG_EXYNOS_CPUFREQ + if (get_pll_clk(APLL) != 1700000000) + exynos_set_frequency(CPU_FREQ_L1700); +#endif break; /* * TMU_STATUS_INIT means something is wrong with temperature sensing @@ -110,6 +121,13 @@ int board_init(void) boot_temp_check(); #endif
+#if defined CONFIG_EXYNOS_CPUFREQ + if (exynos_cpufreq_init()) { + debug("%s: Failed to init CPU frequency scaling\n", __func__); + return -1; + } +#endif + #ifdef CONFIG_EXYNOS_SPI spi_init(); #endif @@ -119,6 +137,7 @@ int board_init(void) #ifdef CONFIG_SOUND_MAX98095 board_enable_audio_codec(); #endif + return 0; }

On Wed, Apr 3, 2013 at 12:27 AM, Akshay Saraswat akshay.s@samsung.com wrote:
Adding tmu throttling support to smdk5250.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com
Acked-by: Simon Glass sjg@chromium.org
board/samsung/smdk5250/smdk5250.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)

This patch enables cpu freq support for exynos5 by adding config for it.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com --- include/configs/exynos5250-dt.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 496a194..18d3e04 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -128,6 +128,9 @@ #define CONFIG_CMD_DTT #define CONFIG_TMU_CMD_DTT
+/* CPU Frequency Scaling */ +#define CONFIG_EXYNOS_CPUFREQ + /* USB */ #define CONFIG_CMD_USB #define CONFIG_USB_EHCI

On Wed, Apr 3, 2013 at 12:27 AM, Akshay Saraswat akshay.s@samsung.com wrote:
This patch enables cpu freq support for exynos5 by adding config for it.
Signed-off-by: Akshay Saraswat akshay.s@samsung.com
Acked-by: Simon Glass sjg@chromium.org
include/configs/exynos5250-dt.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 496a194..18d3e04 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -128,6 +128,9 @@ #define CONFIG_CMD_DTT #define CONFIG_TMU_CMD_DTT
+/* CPU Frequency Scaling */ +#define CONFIG_EXYNOS_CPUFREQ
/* USB */ #define CONFIG_CMD_USB
#define CONFIG_USB_EHCI
1.8.0
participants (2)
-
Akshay Saraswat
-
Simon Glass