1
0
mirror of https://git.yoctoproject.org/meta-ti synced 2026-05-29 23:12:45 +00:00

linux 3.0: initial recipe that will track 3.0rc till 3.0 final

Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
This commit is contained in:
Koen Kooi
2011-07-20 14:41:45 +02:00
parent 7018fe0a81
commit e125e989fa
30 changed files with 79751 additions and 0 deletions
@@ -0,0 +1,196 @@
From 033514238d4b2b59b1507f39372dbabe7365c102 Mon Sep 17 00:00:00 2001
From: Fernandes, Joel A <joelagnel@ti.com>
Date: Tue, 7 Jun 2011 15:54:45 -0500
Subject: [PATCH] OMAP3: beagle: add support for beagleboard xM revision C
OMAP3: beagle: add support for beagleboard xM revision C
The USB enable GPIO has been in beagleboard xM revision C.
The USER button has been moved since beagleboard xM.
Also, board specific initialization has been moved to beagle_config struct
and initialized in omap3_beagle_init_rev. Default values in struct are for xMC.
Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/board-omap3beagle.c | 78 ++++++++++++++++++++-----------
1 files changed, 51 insertions(+), 27 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7f21d24..4b113b2 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -61,7 +61,8 @@
* AXBX = GPIO173, GPIO172, GPIO171: 1 1 1
* C1_3 = GPIO173, GPIO172, GPIO171: 1 1 0
* C4 = GPIO173, GPIO172, GPIO171: 1 0 1
- * XM = GPIO173, GPIO172, GPIO171: 0 0 0
+ * XMA/XMB = GPIO173, GPIO172, GPIO171: 0 0 0
+ * XMC = GPIO173, GPIO172, GPIO171: 0 1 0
*/
enum {
OMAP3BEAGLE_BOARD_UNKN = 0,
@@ -69,14 +70,26 @@ enum {
OMAP3BEAGLE_BOARD_C1_3,
OMAP3BEAGLE_BOARD_C4,
OMAP3BEAGLE_BOARD_XM,
+ OMAP3BEAGLE_BOARD_XMC,
};
static u8 omap3_beagle_version;
-static u8 omap3_beagle_get_rev(void)
-{
- return omap3_beagle_version;
-}
+/*
+ * Board-specific configuration
+ * Defaults to BeagleBoard-xMC
+ */
+static struct {
+ int mmc1_gpio_wp;
+ int usb_pwr_level;
+ int reset_gpio;
+ int usr_button_gpio;
+} beagle_config = {
+ .mmc1_gpio_wp = -EINVAL,
+ .usb_pwr_level = GPIOF_OUT_INIT_LOW,
+ .reset_gpio = 129,
+ .usr_button_gpio = 4,
+};
static struct gpio omap3_beagle_rev_gpios[] __initdata = {
{ 171, GPIOF_IN, "rev_id_0" },
@@ -111,18 +124,32 @@ static void __init omap3_beagle_init_rev(void)
case 7:
printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+ beagle_config.mmc1_gpio_wp = 29;
+ beagle_config.reset_gpio = 170;
+ beagle_config.usr_button_gpio = 7;
break;
case 6:
printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+ beagle_config.mmc1_gpio_wp = 23;
+ beagle_config.reset_gpio = 170;
+ beagle_config.usr_button_gpio = 7;
break;
case 5:
printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+ beagle_config.mmc1_gpio_wp = 23;
+ beagle_config.reset_gpio = 170;
+ beagle_config.usr_button_gpio = 7;
break;
case 0:
- printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM Ax/Bx\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+ beagle_config.usb_pwr_level = GPIOF_OUT_INIT_HIGH;
+ break;
+ case 2:
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
break;
default:
printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
@@ -234,7 +261,7 @@ static struct omap2_hsmmc_info mmc[] = {
{
.mmc = 1,
.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
- .gpio_wp = 29,
+ .gpio_wp = -EINVAL,
},
{} /* Terminator */
};
@@ -252,17 +279,11 @@ static struct gpio_led gpio_leds[];
static int beagle_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
- int r, usb_pwr_level;
-
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
- mmc[0].gpio_wp = -EINVAL;
- } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
- (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
- omap_mux_init_gpio(23, OMAP_PIN_INPUT);
- mmc[0].gpio_wp = 23;
- } else {
- omap_mux_init_gpio(29, OMAP_PIN_INPUT);
- }
+ int r;
+
+ if (beagle_config.mmc1_gpio_wp != -EINVAL)
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+ mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
@@ -276,9 +297,8 @@ static int beagle_twl_gpio_setup(struct device *dev,
* high / others active low)
* DVI reset GPIO is different between beagle revisions
*/
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
- usb_pwr_level = GPIOF_OUT_INIT_HIGH;
- beagle_dvi_device.reset_gpio = 129;
+ /* Valid for all -xM revisions */
+ if (cpu_is_omap3630()) {
/*
* gpio + 1 on Xm controls the TFP410's enable line (active low)
* gpio + 2 control varies depending on the board rev as below:
@@ -296,8 +316,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
pr_err("%s: unable to configure DVI_LDO_EN\n",
__func__);
} else {
- usb_pwr_level = GPIOF_OUT_INIT_LOW;
- beagle_dvi_device.reset_gpio = 170;
/*
* REVISIT: need ehci-omap hooks for external VBUS
* power switch and overcurrent detect
@@ -305,8 +323,10 @@ static int beagle_twl_gpio_setup(struct device *dev,
if (gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC"))
pr_err("%s: unable to configure EHCI_nOC\n", __func__);
}
+ beagle_dvi_device.reset_gpio = beagle_config.reset_gpio;
- gpio_request_one(gpio + TWL4030_GPIO_MAX, usb_pwr_level, "nEN_USB_PWR");
+ gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level,
+ "nEN_USB_PWR");
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -458,7 +478,8 @@ static struct platform_device leds_gpio = {
static struct gpio_keys_button gpio_buttons[] = {
{
.code = BTN_EXTRA,
- .gpio = 7,
+ /* Dynamically assigned depending on board */
+ .gpio = -EINVAL,
.desc = "user",
.wakeup = 1,
},
@@ -525,8 +546,8 @@ static void __init beagle_opp_init(void)
return;
}
- /* Custom OPP enabled for XM */
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+ /* Custom OPP enabled for all xM versions */
+ if (cpu_is_omap3630()) {
struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
struct omap_hwmod *dh = omap_hwmod_lookup("iva");
struct device *dev;
@@ -566,6 +587,9 @@ static void __init omap3_beagle_init(void)
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap3_beagle_init_rev();
omap3_beagle_i2c_init();
+
+ gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
+
platform_add_devices(omap3_beagle_devices,
ARRAY_SIZE(omap3_beagle_devices));
omap_display_init(&beagle_dss_data);
--
1.6.6.1
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,36 @@
From 0c06ec8074efa965a12ce79122ab64cebbb27dc9 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Mon, 14 Feb 2011 12:41:10 +0530
Subject: [PATCH 1/7] OMAP3+: SR: disable interrupt by default
We will enable and disable interrupt on a need basis in the class
driver. We need to keep the IRQ disabled by default else the
forceupdate or vcbypass events could trigger events that we don't
need/expect to handle.
This is a preparation for SmartReflex AVS class drivers such as
class 2 and class 1.5 which would need to use interrupts. Existing
SmartReflex AVS class 3 driver does not require to use interrupts
and is not impacted by this change.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index fb7dc52..998b57f 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -270,6 +270,7 @@ static int sr_late_init(struct omap_sr *sr_info)
0, name, (void *)sr_info);
if (ret)
goto error;
+ disable_irq(sr_info->irq);
}
if (pdata && pdata->enable_on_init)
--
1.6.6.1
@@ -0,0 +1,40 @@
From 2c555d8ee3544326033cb3b0ead6c0eb48cb4919 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Mon, 14 Feb 2011 21:14:17 +0530
Subject: [PATCH 2/7] OMAP3+: SR: enable/disable SR only on need
Since we already know the state of the autocomp enablement, we can
see if the requested state is different from the current state and
enable/disable SR only on the need basis.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 998b57f..a4b4319 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -809,10 +809,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)
return -EINVAL;
}
- if (!val)
- sr_stop_vddautocomp(sr_info);
- else
- sr_start_vddautocomp(sr_info);
+ /* control enable/disable only if there is a delta in value */
+ if (sr_info->autocomp_active != val) {
+ if (!val)
+ sr_stop_vddautocomp(sr_info);
+ else
+ sr_start_vddautocomp(sr_info);
+ }
return 0;
}
--
1.6.6.1
@@ -0,0 +1,48 @@
From 60b31f5fad1dda709f3e38ad88dcc8d1496db52d Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Mon, 14 Feb 2011 12:33:13 +0530
Subject: [PATCH 3/7] OMAP3+: SR: fix cosmetic indentation
Error label case seems to have a 2 tab indentation when just 1 is
necessary.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index a4b4319..931879d 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -279,16 +279,16 @@ static int sr_late_init(struct omap_sr *sr_info)
return ret;
error:
- iounmap(sr_info->base);
- mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
- list_del(&sr_info->node);
- dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
- "interrupt handler. Smartreflex will"
- "not function as desired\n", __func__);
- kfree(name);
- kfree(sr_info);
- return ret;
+ iounmap(sr_info->base);
+ mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+ list_del(&sr_info->node);
+ dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
+ "interrupt handler. Smartreflex will"
+ "not function as desired\n", __func__);
+ kfree(name);
+ kfree(sr_info);
+ return ret;
}
static void sr_v1_disable(struct omap_sr *sr)
--
1.6.6.1
@@ -0,0 +1,79 @@
From e38ec7b32ebb15b1e703743ea14ca7a29675a3ba Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@ti.com>
Date: Thu, 26 May 2011 14:48:19 -0700
Subject: [PATCH 4/7] OMAP3: PM debug: remove sleep_while_idle feature
Remove the OMAP-specific PM debug 'sleep_while_idle' feature which is
currently available as an OMAP-specific debugfs entry.
This duplicates existing ARM-generic functionality available as a
boot-time option using the boot cmdline option 'hohlt'.
If runtime configuration of this is needed, then adding a debugfs
entry for the ARM-generic hlt/nohlt interface should be added.
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/pm-debug.c | 3 ---
arch/arm/mach-omap2/pm.h | 2 --
arch/arm/mach-omap2/pm34xx.c | 2 --
3 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index e01da45..d9f0821 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -40,7 +40,6 @@
int omap2_pm_debug;
u32 enable_off_mode;
-u32 sleep_while_idle;
u32 wakeup_timer_seconds;
u32 wakeup_timer_milliseconds;
@@ -639,8 +638,6 @@ static int pm_dbg_init(void)
(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
&enable_off_mode, &pm_dbg_option_fops);
- (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUSR, d,
- &sleep_while_idle, &pm_dbg_option_fops);
(void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d,
&wakeup_timer_seconds, &pm_dbg_option_fops);
(void) debugfs_create_file("wakeup_timer_milliseconds",
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 45bcfce..674eedc 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -69,13 +69,11 @@ extern void omap2_pm_dump(int mode, int resume, unsigned int us);
extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
extern int omap2_pm_debug;
extern u32 enable_off_mode;
-extern u32 sleep_while_idle;
#else
#define omap2_pm_dump(mode, resume, us) do {} while (0);
#define omap2_pm_wakeup_on_timer(seconds, milliseconds) do {} while (0);
#define omap2_pm_debug 0
#define enable_off_mode 0
-#define sleep_while_idle 0
#endif
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c155c9d..cb34244 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -497,8 +497,6 @@ console_still_active:
int omap3_can_sleep(void)
{
- if (!sleep_while_idle)
- return 0;
if (!omap_uart_can_sleep())
return 0;
return 1;
--
1.6.6.1
@@ -0,0 +1,215 @@
From 51ea2570669b64adfaee2c4a757122f0376255dd Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@ti.com>
Date: Thu, 26 May 2011 14:07:41 -0700
Subject: [PATCH 5/7] OMAP2: PM debug: remove register dumping
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/pm-debug.c | 119 ----------------------------------------
arch/arm/mach-omap2/pm.h | 4 -
arch/arm/mach-omap2/pm24xx.c | 6 +-
3 files changed, 2 insertions(+), 127 deletions(-)
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index d9f0821..a8425d6 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -38,129 +38,10 @@
#include "prm2xxx_3xxx.h"
#include "pm.h"
-int omap2_pm_debug;
u32 enable_off_mode;
u32 wakeup_timer_seconds;
u32 wakeup_timer_milliseconds;
-#define DUMP_PRM_MOD_REG(mod, reg) \
- regs[reg_count].name = #mod "." #reg; \
- regs[reg_count++].val = omap2_prm_read_mod_reg(mod, reg)
-#define DUMP_CM_MOD_REG(mod, reg) \
- regs[reg_count].name = #mod "." #reg; \
- regs[reg_count++].val = omap2_cm_read_mod_reg(mod, reg)
-#define DUMP_PRM_REG(reg) \
- regs[reg_count].name = #reg; \
- regs[reg_count++].val = __raw_readl(reg)
-#define DUMP_CM_REG(reg) \
- regs[reg_count].name = #reg; \
- regs[reg_count++].val = __raw_readl(reg)
-#define DUMP_INTC_REG(reg, off) \
- regs[reg_count].name = #reg; \
- regs[reg_count++].val = \
- __raw_readl(OMAP2_L4_IO_ADDRESS(0x480fe000 + (off)))
-
-void omap2_pm_dump(int mode, int resume, unsigned int us)
-{
- struct reg {
- const char *name;
- u32 val;
- } regs[32];
- int reg_count = 0, i;
- const char *s1 = NULL, *s2 = NULL;
-
- if (!resume) {
-#if 0
- /* MPU */
- DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
- DUMP_CM_MOD_REG(MPU_MOD, OMAP2_CM_CLKSTCTRL);
- DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTCTRL);
- DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTST);
- DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
-#endif
-#if 0
- /* INTC */
- DUMP_INTC_REG(INTC_MIR0, 0x0084);
- DUMP_INTC_REG(INTC_MIR1, 0x00a4);
- DUMP_INTC_REG(INTC_MIR2, 0x00c4);
-#endif
-#if 0
- DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
- if (cpu_is_omap24xx()) {
- DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
- DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
- OMAP2_PRCM_CLKEMUL_CTRL_OFFSET);
- DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
- OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
- }
- DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
- DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
- DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
- DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
- DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
- DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
- DUMP_PRM_MOD_REG(CORE_MOD, OMAP2_PM_PWSTST);
-#endif
-#if 0
- /* DSP */
- if (cpu_is_omap24xx()) {
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
- DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_CM_CLKSTCTRL);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTCTRL);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTST);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTCTRL);
- DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTST);
- }
-#endif
- } else {
- DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
- if (cpu_is_omap24xx())
- DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
- DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
- DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
-#if 1
- DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
- DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
- DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
-#endif
- }
-
- switch (mode) {
- case 0:
- s1 = "full";
- s2 = "retention";
- break;
- case 1:
- s1 = "MPU";
- s2 = "retention";
- break;
- case 2:
- s1 = "MPU";
- s2 = "idle";
- break;
- }
-
- if (!resume)
-#ifdef CONFIG_NO_HZ
- printk(KERN_INFO
- "--- Going to %s %s (next timer after %u ms)\n", s1, s2,
- jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
- jiffies));
-#else
- printk(KERN_INFO "--- Going to %s %s\n", s1, s2);
-#endif
- else
- printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n",
- us / 1000, us % 1000);
-
- for (i = 0; i < reg_count; i++)
- printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
-}
-
void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
{
u32 tick_rate, cycles;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 674eedc..acac275 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -65,14 +65,10 @@ extern u32 wakeup_timer_milliseconds;
extern struct omap_dm_timer *gptimer_wakeup;
#ifdef CONFIG_PM_DEBUG
-extern void omap2_pm_dump(int mode, int resume, unsigned int us);
extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
-extern int omap2_pm_debug;
extern u32 enable_off_mode;
#else
-#define omap2_pm_dump(mode, resume, us) do {} while (0);
#define omap2_pm_wakeup_on_timer(seconds, milliseconds) do {} while (0);
-#define omap2_pm_debug 0
#define enable_off_mode 0
#endif
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index df3ded6..bf089e7 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -53,6 +53,8 @@
#include "powerdomain.h"
#include "clockdomain.h"
+static int omap2_pm_debug;
+
#ifdef CONFIG_SUSPEND
static suspend_state_t suspend_state = PM_SUSPEND_ON;
static inline bool is_suspending(void)
@@ -123,7 +125,6 @@ static void omap2_enter_full_retention(void)
omap2_gpio_prepare_for_idle(0);
if (omap2_pm_debug) {
- omap2_pm_dump(0, 0, 0);
getnstimeofday(&ts_preidle);
}
@@ -160,7 +161,6 @@ no_sleep:
getnstimeofday(&ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
- omap2_pm_dump(0, 1, tmp);
}
omap2_gpio_resume_after_idle();
@@ -247,7 +247,6 @@ static void omap2_enter_mpu_retention(void)
}
if (omap2_pm_debug) {
- omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
getnstimeofday(&ts_preidle);
}
@@ -259,7 +258,6 @@ static void omap2_enter_mpu_retention(void)
getnstimeofday(&ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
- omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
}
}
--
1.6.6.1
@@ -0,0 +1,313 @@
From 2cb229bc89ac3f0b369ffcfb375bb1469f77d98b Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@ti.com>
Date: Thu, 26 May 2011 15:34:39 -0700
Subject: [PATCH 6/7] OMAP3: PM debug: remove register dumping
Remove OMAP3-specific register dumping feature from PM debug layer.
This is removed because:
- it's ugly
- it's OMAP3-specific, and will obviously not scale to OMAP4+
- userspace /dev/mem-based tools (like omapconf) can do this much better
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/pm-debug.c | 221 ----------------------------------------
arch/arm/mach-omap2/pm.h | 4 -
2 files changed, 0 insertions(+), 225 deletions(-)
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index a8425d6..3d1cce2 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -63,10 +63,6 @@ void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-static void pm_dbg_regset_store(u32 *ptr);
-
-static struct dentry *pm_dbg_dir;
-
static int pm_dbg_init_done;
static int pm_dbg_init(void);
@@ -76,160 +72,6 @@ enum {
DEBUG_FILE_TIMERS,
};
-struct pm_module_def {
- char name[8]; /* Name of the module */
- short type; /* CM or PRM */
- unsigned short offset;
- int low; /* First register address on this module */
- int high; /* Last register address on this module */
-};
-
-#define MOD_CM 0
-#define MOD_PRM 1
-
-static const struct pm_module_def *pm_dbg_reg_modules;
-static const struct pm_module_def omap3_pm_reg_modules[] = {
- { "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c },
- { "OCP", MOD_CM, OCP_MOD, 0, 0x10 },
- { "MPU", MOD_CM, MPU_MOD, 4, 0x4c },
- { "CORE", MOD_CM, CORE_MOD, 0, 0x4c },
- { "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c },
- { "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 },
- { "CCR", MOD_CM, PLL_MOD, 0, 0x70 },
- { "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c },
- { "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c },
- { "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c },
- { "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 },
- { "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 },
- { "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c },
-
- { "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc },
- { "OCP", MOD_PRM, OCP_MOD, 4, 0x1c },
- { "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 },
- { "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 },
- { "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 },
- { "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 },
- { "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 },
- { "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 },
- { "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 },
- { "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 },
- { "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 },
- { "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 },
- { "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 },
- { "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 },
- { "", 0, 0, 0, 0 },
-};
-
-#define PM_DBG_MAX_REG_SETS 4
-
-static void *pm_dbg_reg_set[PM_DBG_MAX_REG_SETS];
-
-static int pm_dbg_get_regset_size(void)
-{
- static int regset_size;
-
- if (regset_size == 0) {
- int i = 0;
-
- while (pm_dbg_reg_modules[i].name[0] != 0) {
- regset_size += pm_dbg_reg_modules[i].high +
- 4 - pm_dbg_reg_modules[i].low;
- i++;
- }
- }
- return regset_size;
-}
-
-static int pm_dbg_show_regs(struct seq_file *s, void *unused)
-{
- int i, j;
- unsigned long val;
- int reg_set = (int)s->private;
- u32 *ptr;
- void *store = NULL;
- int regs;
- int linefeed;
-
- if (reg_set == 0) {
- store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
- ptr = store;
- pm_dbg_regset_store(ptr);
- } else {
- ptr = pm_dbg_reg_set[reg_set - 1];
- }
-
- i = 0;
-
- while (pm_dbg_reg_modules[i].name[0] != 0) {
- regs = 0;
- linefeed = 0;
- if (pm_dbg_reg_modules[i].type == MOD_CM)
- seq_printf(s, "MOD: CM_%s (%08x)\n",
- pm_dbg_reg_modules[i].name,
- (u32)(OMAP3430_CM_BASE +
- pm_dbg_reg_modules[i].offset));
- else
- seq_printf(s, "MOD: PRM_%s (%08x)\n",
- pm_dbg_reg_modules[i].name,
- (u32)(OMAP3430_PRM_BASE +
- pm_dbg_reg_modules[i].offset));
-
- for (j = pm_dbg_reg_modules[i].low;
- j <= pm_dbg_reg_modules[i].high; j += 4) {
- val = *(ptr++);
- if (val != 0) {
- regs++;
- if (linefeed) {
- seq_printf(s, "\n");
- linefeed = 0;
- }
- seq_printf(s, " %02x => %08lx", j, val);
- if (regs % 4 == 0)
- linefeed = 1;
- }
- }
- seq_printf(s, "\n");
- i++;
- }
-
- if (store != NULL)
- kfree(store);
-
- return 0;
-}
-
-static void pm_dbg_regset_store(u32 *ptr)
-{
- int i, j;
- u32 val;
-
- i = 0;
-
- while (pm_dbg_reg_modules[i].name[0] != 0) {
- for (j = pm_dbg_reg_modules[i].low;
- j <= pm_dbg_reg_modules[i].high; j += 4) {
- if (pm_dbg_reg_modules[i].type == MOD_CM)
- val = omap2_cm_read_mod_reg(
- pm_dbg_reg_modules[i].offset, j);
- else
- val = omap2_prm_read_mod_reg(
- pm_dbg_reg_modules[i].offset, j);
- *(ptr++) = val;
- }
- i++;
- }
-}
-
-int pm_dbg_regset_save(int reg_set)
-{
- if (pm_dbg_reg_set[reg_set-1] == NULL)
- return -EINVAL;
-
- pm_dbg_regset_store(pm_dbg_reg_set[reg_set-1]);
-
- return 0;
-}
-
static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
"OFF",
"RET",
@@ -349,11 +191,6 @@ static int pm_dbg_open(struct inode *inode, struct file *file)
};
}
-static int pm_dbg_reg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pm_dbg_show_regs, inode->i_private);
-}
-
static const struct file_operations debug_fops = {
.open = pm_dbg_open,
.read = seq_read,
@@ -361,40 +198,6 @@ static const struct file_operations debug_fops = {
.release = single_release,
};
-static const struct file_operations debug_reg_fops = {
- .open = pm_dbg_reg_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-int pm_dbg_regset_init(int reg_set)
-{
- char name[2];
-
- if (!pm_dbg_init_done)
- pm_dbg_init();
-
- if (reg_set < 1 || reg_set > PM_DBG_MAX_REG_SETS ||
- pm_dbg_reg_set[reg_set-1] != NULL)
- return -EINVAL;
-
- pm_dbg_reg_set[reg_set-1] =
- kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
-
- if (pm_dbg_reg_set[reg_set-1] == NULL)
- return -ENOMEM;
-
- if (pm_dbg_dir != NULL) {
- sprintf(name, "%d", reg_set);
-
- (void) debugfs_create_file(name, S_IRUGO,
- pm_dbg_dir, (void *)reg_set, &debug_reg_fops);
- }
-
- return 0;
-}
-
static int pwrdm_suspend_get(void *data, u64 *val)
{
int ret = -EINVAL;
@@ -477,20 +280,11 @@ DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
static int pm_dbg_init(void)
{
- int i;
struct dentry *d;
- char name[2];
if (pm_dbg_init_done)
return 0;
- if (cpu_is_omap34xx())
- pm_dbg_reg_modules = omap3_pm_reg_modules;
- else {
- printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
- return -ENODEV;
- }
-
d = debugfs_create_dir("pm_debug", NULL);
if (IS_ERR(d))
return PTR_ERR(d);
@@ -502,21 +296,6 @@ static int pm_dbg_init(void)
pwrdm_for_each(pwrdms_setup, (void *)d);
- pm_dbg_dir = debugfs_create_dir("registers", d);
- if (IS_ERR(pm_dbg_dir))
- return PTR_ERR(pm_dbg_dir);
-
- (void) debugfs_create_file("current", S_IRUGO,
- pm_dbg_dir, (void *)0, &debug_reg_fops);
-
- for (i = 0; i < PM_DBG_MAX_REG_SETS; i++)
- if (pm_dbg_reg_set[i] != NULL) {
- sprintf(name, "%d", i+1);
- (void) debugfs_create_file(name, S_IRUGO,
- pm_dbg_dir, (void *)(i+1), &debug_reg_fops);
-
- }
-
(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
&enable_off_mode, &pm_dbg_option_fops);
(void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d,
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index acac275..ea58f5d 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -74,12 +74,8 @@ extern u32 enable_off_mode;
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
-extern int pm_dbg_regset_save(int reg_set);
-extern int pm_dbg_regset_init(int reg_set);
#else
#define pm_dbg_update_time(pwrdm, prev) do {} while (0);
-#define pm_dbg_regset_save(reg_set) do {} while (0);
-#define pm_dbg_regset_init(reg_set) do {} while (0);
#endif /* CONFIG_PM_DEBUG */
extern void omap24xx_idle_loop_suspend(void);
--
1.6.6.1
@@ -0,0 +1,37 @@
From 7472bb7b89bfdc6beef83bb6008219158e072975 Mon Sep 17 00:00:00 2001
From: Sanjeev Premi <premi@ti.com>
Date: Fri, 17 Jun 2011 02:01:00 +0530
Subject: [PATCH 7/7] OMAP2+: PM: fix section mismatch in pm_dbg_init()
Fix the section mismatch warning:
WARNING: vmlinux.o(.text+0x21118): Section mismatch
in reference from the function pm_dbg_init() to the
function .init.text:pwrdms_setup()
The function pm_dbg_init() references
the function __init pwrdms_setup().
This is often because pm_dbg_init lacks a __init
annotation or the annotation of pwrdms_setup is wrong.
Signed-off-by: Sanjeev Premi <premi@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/pm-debug.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 3d1cce2..3feb475 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -278,7 +278,7 @@ static int option_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
-static int pm_dbg_init(void)
+static int __init pm_dbg_init(void)
{
struct dentry *d;
--
1.6.6.1
@@ -0,0 +1,84 @@
From e029940bc6c0ff4ad3c8e2b4f31d0a3de78eff32 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Wed, 25 May 2011 00:43:26 -0700
Subject: [PATCH 01/19] PM: OPP: introduce function to free cpufreq table
cpufreq table allocated by opp_init_cpufreq_table is better
freed by OPP layer itself. This allows future modifications to
the table handling to be transparent to the users.
Signed-off-by: Nishanth Menon <nm@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
---
Documentation/power/opp.txt | 2 ++
drivers/base/power/opp.c | 17 +++++++++++++++++
include/linux/opp.h | 8 ++++++++
3 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
index 5ae70a1..3035d00 100644
--- a/Documentation/power/opp.txt
+++ b/Documentation/power/opp.txt
@@ -321,6 +321,8 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
addition to CONFIG_PM as power management feature is required to
dynamically scale voltage and frequency in a system.
+opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table
+
7. Data Structures
==================
Typically an SoC contains multiple voltage domains which are variable. Each
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 56a6899..5cc1232 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -625,4 +625,21 @@ int opp_init_cpufreq_table(struct device *dev,
return 0;
}
+
+/**
+ * opp_free_cpufreq_table() - free the cpufreq table
+ * @dev: device for which we do this operation
+ * @table: table to free
+ *
+ * Free up the table allocated by opp_init_cpufreq_table
+ */
+void opp_free_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+ if (!table)
+ return;
+
+ kfree(*table);
+ *table = NULL;
+}
#endif /* CONFIG_CPU_FREQ */
diff --git a/include/linux/opp.h b/include/linux/opp.h
index 5449945..7020e97 100644
--- a/include/linux/opp.h
+++ b/include/linux/opp.h
@@ -94,12 +94,20 @@ static inline int opp_disable(struct device *dev, unsigned long freq)
#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
int opp_init_cpufreq_table(struct device *dev,
struct cpufreq_frequency_table **table);
+void opp_free_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table);
#else
static inline int opp_init_cpufreq_table(struct device *dev,
struct cpufreq_frequency_table **table)
{
return -EINVAL;
}
+
+static inline
+void opp_free_cpufreq_table(struct device *dev,
+ struct cpufreq_frequency_table **table)
+{
+}
#endif /* CONFIG_CPU_FREQ */
#endif /* __LINUX_OPP_H__ */
--
1.6.6.1
@@ -0,0 +1,28 @@
From 895fc8961297666b46b4cd3f8c01010051d2164e Mon Sep 17 00:00:00 2001
From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Date: Wed, 11 Aug 2010 17:02:43 -0700
Subject: [PATCH 02/19] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/plat-omap/cpu-omap.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index da4f68d..cd09d4b 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -160,7 +160,7 @@ static int __init omap_cpufreq_init(void)
return cpufreq_register_driver(&omap_driver);
}
-arch_initcall(omap_cpufreq_init);
+late_initcall(omap_cpufreq_init);
/*
* if ever we want to remove this, upon cleanup call:
--
1.6.6.1
@@ -0,0 +1,32 @@
From 62bd1b0f18ee6c6bad1573c2f06e74b0abc418a3 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@deeprootsystems.com>
Date: Wed, 11 Aug 2010 17:05:38 -0700
Subject: [PATCH 03/19] OMAP: CPUfreq: ensure policy is fully initialized
Ensure policy min/max/cur values are initialized when OMAP
CPUfreq driver starts.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/plat-omap/cpu-omap.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index cd09d4b..1b36664 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -126,6 +126,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
VERY_HI_RATE) / 1000;
}
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = omap_getspeed(0);
+
/* FIXME: what's the actual transition time? */
policy->cpuinfo.transition_latency = 300 * 1000;
--
1.6.6.1
@@ -0,0 +1,264 @@
From afa9b062a33a9d9d2d9077cc519e1375b8338e39 Mon Sep 17 00:00:00 2001
From: Rajendra Nayak <rnayak@ti.com>
Date: Mon, 10 Nov 2008 17:00:25 +0530
Subject: [PATCH 04/19] OMAP3 PM: CPUFreq driver for OMAP3
CPUFreq driver for OMAP3
With additional fixes and cleanups from Tero Kristo:
- Fix rate calculation bug in omap3_select_table_rate
- Refreshed DVFS VDD1 control against latest clock fw
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
OMAP3: PM: CPUFreq: Fix omap_getspeed.
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Make sure omap cpufreq driver initializes after cpufreq framework and governors
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
merge: CPUFreq: remove obsolete funcs
OMAP3 clock: Update cpufreq driver
This patch removes all refrences to virtual clock
nodes in CPUFreq driver.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Jean Pihet <jpihet@mvista.com>
PM: Prevent direct cpufreq scaling during initialization
It is seen that the OMAP specific cpufreq initialization code tries to
scale the MPU frequency to the highest possible without taking care of
the voltage level. On power on reset the power IC does not provide the
necessary voltage for the highest available MPU frequency (that would
satisfy all Si families). This potentially is an window of opportunity
for things to go wrong.
Signed-off-by: Romit Dasgupta <romit@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
OMAP3: PM: enable 600MHz (overdrive) OPP
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
omap3: introduce cpufreq
OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only.
With this patch, omap opp layer now has its compilation flags
bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c.
A new file has been created to contain cpu freq code related to
OMAP3: cpufreq34xx.c
OMAP34xx and OMAP36xx family OPPs are made available
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Romit Dasgupta <romit@ti.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
omap3: cpufreq: allow default opp table init
For board files which choose to override the defaults, the existing
mechanism will work, for boards that would like to work with defaults,
allow init_common_hw to call init_opp_table to initialize if not
already initialized. this will allow all omap boards which have opp
tables predefined for a silicon to use the same.
Originally reported for overo:
http://marc.info/?t=127265269400004&r=1&w=2
Signed-off-by: Nishanth Menon <nm@ti.com>
Reported-by: Peter Tseng <tsenpet09@gmail.com>
Cc: Cliff Brake <cliff.brake@gmail.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
OMAP2: update OPP data to be device based
Cc: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
OMAP3: CPUfreq: update to device-based OPP API
Update usage of OPP API to use new device-based API. This requires
getting the 'struct device' for the MPU and using that with the OPP
API.
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
omap3: opp: make independent of cpufreq
Make opp3xx data which is registered with the opp layer
dependent purely on CONFIG_PM as opp layer and pm.c users
are CONFIG_PM dependent not cpufreq dependent.
so we rename the data definition to opp3xxx_data.c (inline with what
we have for omap2), also move the build definition to be under
the existing CONFIG_PM build instead of CPUFREQ.
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/clock.h | 14 +++++++++++++-
arch/arm/mach-omap2/clock34xx.c | 2 ++
arch/arm/plat-omap/cpu-omap.c | 34 +++++++++++++++++++++++++++++++---
3 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index e10ff2b..0a07e50 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -141,7 +141,9 @@ extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[];
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
+#ifdef CONFIG_CPU_FREQ
+
+#ifdef CONFIG_ARCH_OMAP2
extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
#else
@@ -149,6 +151,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
#define omap2_clk_exit_cpufreq_table 0
#endif
+#ifdef CONFIG_ARCH_OMAP3
+extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
+extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
+#else
+#define omap3_clk_init_cpufreq_table 0
+#define omap3_clk_exit_cpufreq_table 0
+#endif
+
+#endif /* CONFIG_CPU_FREQ */
+
extern const struct clkops clkops_omap2_iclk_dflt_wait;
extern const struct clkops clkops_omap2_iclk_dflt;
extern const struct clkops clkops_omap2_iclk_idle_only;
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 1fc96b9..119e135 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -20,6 +20,8 @@
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/cpufreq.h>
#include <plat/clock.h>
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 1b36664..f0f9430 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -8,6 +8,10 @@
*
* Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
*
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Updated to support OMAP3
+ * Rajendra Nayak <rnayak@ti.com>
+ *
* 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.
@@ -26,12 +30,19 @@
#include <plat/clock.h>
#include <asm/system.h>
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+#include <plat/omap-pm.h>
+#include <plat/opp.h>
+#endif
+
#define VERY_HI_RATE 900000000
static struct cpufreq_frequency_table *freq_table;
#ifdef CONFIG_ARCH_OMAP1
#define MPU_CLK "mpu"
+#elif CONFIG_ARCH_OMAP3
+#define MPU_CLK "arm_fck"
#else
#define MPU_CLK "virt_prcm_set"
#endif
@@ -73,7 +84,13 @@ static int omap_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
+#ifdef CONFIG_ARCH_OMAP1
struct cpufreq_freqs freqs;
+#endif
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+ unsigned long freq;
+ struct device *mpu_dev = omap2_get_mpuss_device();
+#endif
int ret = 0;
/* Ensure desired rate is within allowed range. Some govenors
@@ -83,13 +100,13 @@ static int omap_target(struct cpufreq_policy *policy,
if (target_freq > policy->max)
target_freq = policy->max;
+#ifdef CONFIG_ARCH_OMAP1
freqs.old = omap_getspeed(0);
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
freqs.cpu = 0;
if (freqs.old == freqs.new)
return ret;
-
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
#ifdef CONFIG_CPU_FREQ_DEBUG
printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
@@ -97,7 +114,11 @@ static int omap_target(struct cpufreq_policy *policy,
#endif
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
+#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
+ freq = target_freq * 1000;
+ if (opp_find_freq_ceil(mpu_dev, &freq))
+ omap_pm_cpu_set_freq(freq);
+#endif
return ret;
}
@@ -114,7 +135,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
policy->cur = policy->min = policy->max = omap_getspeed(0);
- clk_init_cpufreq_table(&freq_table);
+ if (!cpu_is_omap34xx()) {
+ clk_init_cpufreq_table(&freq_table);
+ } else {
+ struct device *mpu_dev = omap2_get_mpuss_device();
+
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
+ }
+
if (freq_table) {
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
if (!result)
--
1.6.6.1
@@ -0,0 +1,33 @@
From c93327d36f0dc4ea6693fcae54c561eb8bafdd1e Mon Sep 17 00:00:00 2001
From: Silesh C V <silesh@ti.com>
Date: Wed, 29 Sep 2010 14:52:54 +0530
Subject: [PATCH 05/19] OMAP: PM: CPUFREQ: Fix conditional compilation
Fix conditional compilation. A conditional expresiion
should follow "#elif", in this case #elif clause should
check whether CONFIG_ARCH_OMAP3 is defined or not
(ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for
the value of the macro.
Signed-off-by: Silesh C V <silesh@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/plat-omap/cpu-omap.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index f0f9430..c3ac065 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -41,7 +41,7 @@ static struct cpufreq_frequency_table *freq_table;
#ifdef CONFIG_ARCH_OMAP1
#define MPU_CLK "mpu"
-#elif CONFIG_ARCH_OMAP3
+#elif defined(CONFIG_ARCH_OMAP3)
#define MPU_CLK "arm_fck"
#else
#define MPU_CLK "virt_prcm_set"
--
1.6.6.1
@@ -0,0 +1,34 @@
From b8246b5d5edc98155628ba88510bc7e67baf7acf Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@deeprootsystems.com>
Date: Tue, 16 Nov 2010 11:48:41 -0800
Subject: [PATCH 06/19] cpufreq: fixup after new OPP layer merged
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/plat-omap/cpu-omap.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index c3ac065..9cd2709 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -25,6 +25,7 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/opp.h>
#include <mach/hardware.h>
#include <plat/clock.h>
@@ -32,7 +33,7 @@
#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
#include <plat/omap-pm.h>
-#include <plat/opp.h>
+#include <plat/common.h>
#endif
#define VERY_HI_RATE 900000000
--
1.6.6.1
@@ -0,0 +1,673 @@
From 9f9061d3e98aa6db7d5c3feabd5a2d93eb3cb737 Mon Sep 17 00:00:00 2001
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
Date: Mon, 14 Mar 2011 17:08:48 +0530
Subject: [PATCH 07/19] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers.
This patch is an attempt to cleanup the #ifdeferry in the
omap CPUfreq drivers.
The split betwenn OMAP1 and OMAP2PLUS is logical because
- OMAP1 doesn't support opp layer.
- OMAP1 build is seperate from omap2plus.
Includes minor header/copyright updates reported by Todd Poynor.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Vishwanath BS <vishwanath.bs@ti.com>
Cc: Todd Poynor <toddpoynor@google.com>
Cc: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap1/Makefile | 3 +
arch/arm/mach-omap1/omap1-cpufreq.c | 175 ++++++++++++++++++++++++++
arch/arm/mach-omap2/Makefile | 3 +
arch/arm/mach-omap2/omap2plus-cpufreq.c | 201 ++++++++++++++++++++++++++++++
arch/arm/plat-omap/Makefile | 1 -
arch/arm/plat-omap/cpu-omap.c | 204 -------------------------------
6 files changed, 382 insertions(+), 205 deletions(-)
create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c
create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c
delete mode 100644 arch/arm/plat-omap/cpu-omap.c
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 5b114d1..9600410 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+# CPUFREQ driver
+obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o
+
# Power Management
obj-$(CONFIG_PM) += pm.o sleep.o
diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c
new file mode 100644
index 0000000..7c5216e
--- /dev/null
+++ b/arch/arm/mach-omap1/omap1-cpufreq.c
@@ -0,0 +1,175 @@
+/*
+ * OMAP1 cpufreq driver
+ *
+ * CPU frequency scaling for OMAP
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * 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.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/opp.h>
+
+#include <asm/system.h>
+
+#include <plat/clock.h>
+#include <plat/omap-pm.h>
+
+#include <mach/hardware.h>
+
+#define VERY_HI_RATE 900000000
+
+static struct cpufreq_frequency_table *freq_table;
+static struct clk *mpu_clk;
+
+static int omap_verify_speed(struct cpufreq_policy *policy)
+{
+ if (freq_table)
+ return cpufreq_frequency_table_verify(policy, freq_table);
+
+ if (policy->cpu)
+ return -EINVAL;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
+ policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+ return 0;
+}
+
+static unsigned int omap_getspeed(unsigned int cpu)
+{
+ unsigned long rate;
+
+ if (cpu)
+ return 0;
+
+ rate = clk_get_rate(mpu_clk) / 1000;
+ return rate;
+}
+
+static int omap_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ int ret = 0;
+
+ /* Ensure desired rate is within allowed range. Some govenors
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
+ if (target_freq < policy->min)
+ target_freq = policy->min;
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+
+ freqs.old = omap_getspeed(0);
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
+ freqs.cpu = 0;
+
+ if (freqs.old == freqs.new)
+ return ret;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
+#endif
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return ret;
+}
+
+static int __init omap_cpu_init(struct cpufreq_policy *policy)
+{
+ int result = 0;
+
+ mpu_clk = clk_get(NULL, "mpu");
+ if (IS_ERR(mpu_clk))
+ return PTR_ERR(mpu_clk);
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ policy->cur = policy->min = policy->max = omap_getspeed(0);
+
+ clk_init_cpufreq_table(&freq_table);
+
+ if (freq_table) {
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (!result)
+ cpufreq_frequency_table_get_attr(freq_table,
+ policy->cpu);
+ } else {
+ policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
+ policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
+ VERY_HI_RATE) / 1000;
+ }
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = omap_getspeed(0);
+
+ /* FIXME: what's the actual transition time? */
+ policy->cpuinfo.transition_latency = 300 * 1000;
+
+ return 0;
+}
+
+static int omap_cpu_exit(struct cpufreq_policy *policy)
+{
+ clk_exit_cpufreq_table(&freq_table);
+ clk_put(mpu_clk);
+ return 0;
+}
+
+static struct freq_attr *omap_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver omap_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = omap_verify_speed,
+ .target = omap_target,
+ .get = omap_getspeed,
+ .init = omap_cpu_init,
+ .exit = omap_cpu_exit,
+ .name = "omap1",
+ .attr = omap_cpufreq_attr,
+};
+
+static int __init omap_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&omap_driver);
+}
+
+static void __exit omap_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&omap_driver);
+}
+
+MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs");
+MODULE_LICENSE("GPL");
+module_init(omap_cpufreq_init);
+module_exit(omap_cpufreq_exit);
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b148077..5024064 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o
endif
+# CPUFREQ driver
+obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o
+
# Power Management
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
new file mode 100644
index 0000000..27f641b
--- /dev/null
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -0,0 +1,201 @@
+/*
+ * OMAP2PLUS cpufreq driver
+ *
+ * CPU frequency scaling for OMAP
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
+ *
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
+ * Updated to support OMAP3
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * 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.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/opp.h>
+
+#include <asm/system.h>
+#include <asm/smp_plat.h>
+
+#include <plat/clock.h>
+#include <plat/omap-pm.h>
+#include <plat/common.h>
+
+#include <mach/hardware.h>
+
+#define VERY_HI_RATE 900000000
+
+static struct cpufreq_frequency_table *freq_table;
+static struct clk *mpu_clk;
+
+static int omap_verify_speed(struct cpufreq_policy *policy)
+{
+ if (freq_table)
+ return cpufreq_frequency_table_verify(policy, freq_table);
+
+ if (policy->cpu)
+ return -EINVAL;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
+ policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+ return 0;
+}
+
+static unsigned int omap_getspeed(unsigned int cpu)
+{
+ unsigned long rate;
+
+ if (cpu)
+ return 0;
+
+ rate = clk_get_rate(mpu_clk) / 1000;
+ return rate;
+}
+
+static int omap_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ int ret = 0;
+ struct cpufreq_freqs freqs;
+
+ /* Ensure desired rate is within allowed range. Some govenors
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
+ if (target_freq < policy->min)
+ target_freq = policy->min;
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+
+ freqs.old = omap_getspeed(0);
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
+ freqs.cpu = 0;
+
+ if (freqs.old == freqs.new)
+ return ret;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
+#endif
+
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+
+ /*
+ * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies
+ * won't get updated when UP machine cpufreq build with
+ * CONFIG_SMP enabled. Below code is added only to manage that
+ * scenario
+ */
+ if (!is_smp())
+ loops_per_jiffy =
+ cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return ret;
+}
+
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+{
+ int result = 0;
+ struct device *mpu_dev;
+
+ if (cpu_is_omap24xx())
+ mpu_clk = clk_get(NULL, "virt_prcm_set");
+ else if (cpu_is_omap34xx())
+ mpu_clk = clk_get(NULL, "dpll1_ck");
+ else if (cpu_is_omap34xx())
+ mpu_clk = clk_get(NULL, "dpll_mpu_ck");
+
+ if (IS_ERR(mpu_clk))
+ return PTR_ERR(mpu_clk);
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ policy->cur = policy->min = policy->max = omap_getspeed(0);
+
+ mpu_dev = omap2_get_mpuss_device();
+ if (!mpu_dev) {
+ pr_warning("%s: unable to get the mpu device\n", __func__);
+ return -EINVAL;
+ }
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
+
+ if (freq_table) {
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (!result)
+ cpufreq_frequency_table_get_attr(freq_table,
+ policy->cpu);
+ } else {
+ policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
+ policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
+ VERY_HI_RATE) / 1000;
+ }
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = omap_getspeed(0);
+
+ /* FIXME: what's the actual transition time? */
+ policy->cpuinfo.transition_latency = 300 * 1000;
+
+ return 0;
+}
+
+static int omap_cpu_exit(struct cpufreq_policy *policy)
+{
+ clk_exit_cpufreq_table(&freq_table);
+ clk_put(mpu_clk);
+ return 0;
+}
+
+static struct freq_attr *omap_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver omap_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = omap_verify_speed,
+ .target = omap_target,
+ .get = omap_getspeed,
+ .init = omap_cpu_init,
+ .exit = omap_cpu_exit,
+ .name = "omap2plus",
+ .attr = omap_cpufreq_attr,
+};
+
+static int __init omap_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&omap_driver);
+}
+
+static void __exit omap_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&omap_driver);
+}
+
+MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs");
+MODULE_LICENSE("GPL");
+module_init(omap_cpufreq_init);
+module_exit(omap_cpufreq_exit);
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index f0233e6..4ef7493 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
-obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
deleted file mode 100644
index 9cd2709..0000000
--- a/arch/arm/plat-omap/cpu-omap.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/cpu-omap.c
- *
- * CPU frequency scaling for OMAP
- *
- * Copyright (C) 2005 Nokia Corporation
- * Written by Tony Lindgren <tony@atomide.com>
- *
- * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Updated to support OMAP3
- * Rajendra Nayak <rnayak@ti.com>
- *
- * 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.
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/cpufreq.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/opp.h>
-
-#include <mach/hardware.h>
-#include <plat/clock.h>
-#include <asm/system.h>
-
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
-#include <plat/omap-pm.h>
-#include <plat/common.h>
-#endif
-
-#define VERY_HI_RATE 900000000
-
-static struct cpufreq_frequency_table *freq_table;
-
-#ifdef CONFIG_ARCH_OMAP1
-#define MPU_CLK "mpu"
-#elif defined(CONFIG_ARCH_OMAP3)
-#define MPU_CLK "arm_fck"
-#else
-#define MPU_CLK "virt_prcm_set"
-#endif
-
-static struct clk *mpu_clk;
-
-/* TODO: Add support for SDRAM timing changes */
-
-static int omap_verify_speed(struct cpufreq_policy *policy)
-{
- if (freq_table)
- return cpufreq_frequency_table_verify(policy, freq_table);
-
- if (policy->cpu)
- return -EINVAL;
-
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
-
- policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
- policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
- return 0;
-}
-
-static unsigned int omap_getspeed(unsigned int cpu)
-{
- unsigned long rate;
-
- if (cpu)
- return 0;
-
- rate = clk_get_rate(mpu_clk) / 1000;
- return rate;
-}
-
-static int omap_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
-#ifdef CONFIG_ARCH_OMAP1
- struct cpufreq_freqs freqs;
-#endif
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
- unsigned long freq;
- struct device *mpu_dev = omap2_get_mpuss_device();
-#endif
- int ret = 0;
-
- /* Ensure desired rate is within allowed range. Some govenors
- * (ondemand) will just pass target_freq=0 to get the minimum. */
- if (target_freq < policy->min)
- target_freq = policy->min;
- if (target_freq > policy->max)
- target_freq = policy->max;
-
-#ifdef CONFIG_ARCH_OMAP1
- freqs.old = omap_getspeed(0);
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
- freqs.cpu = 0;
-
- if (freqs.old == freqs.new)
- return ret;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-#ifdef CONFIG_CPU_FREQ_DEBUG
- printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
- freqs.old, freqs.new);
-#endif
- ret = clk_set_rate(mpu_clk, freqs.new * 1000);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
- freq = target_freq * 1000;
- if (opp_find_freq_ceil(mpu_dev, &freq))
- omap_pm_cpu_set_freq(freq);
-#endif
- return ret;
-}
-
-static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
-{
- int result = 0;
-
- mpu_clk = clk_get(NULL, MPU_CLK);
- if (IS_ERR(mpu_clk))
- return PTR_ERR(mpu_clk);
-
- if (policy->cpu != 0)
- return -EINVAL;
-
- policy->cur = policy->min = policy->max = omap_getspeed(0);
-
- if (!cpu_is_omap34xx()) {
- clk_init_cpufreq_table(&freq_table);
- } else {
- struct device *mpu_dev = omap2_get_mpuss_device();
-
- opp_init_cpufreq_table(mpu_dev, &freq_table);
- }
-
- if (freq_table) {
- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
- if (!result)
- cpufreq_frequency_table_get_attr(freq_table,
- policy->cpu);
- } else {
- policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
- policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
- VERY_HI_RATE) / 1000;
- }
-
- policy->min = policy->cpuinfo.min_freq;
- policy->max = policy->cpuinfo.max_freq;
- policy->cur = omap_getspeed(0);
-
- /* FIXME: what's the actual transition time? */
- policy->cpuinfo.transition_latency = 300 * 1000;
-
- return 0;
-}
-
-static int omap_cpu_exit(struct cpufreq_policy *policy)
-{
- clk_exit_cpufreq_table(&freq_table);
- clk_put(mpu_clk);
- return 0;
-}
-
-static struct freq_attr *omap_cpufreq_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static struct cpufreq_driver omap_driver = {
- .flags = CPUFREQ_STICKY,
- .verify = omap_verify_speed,
- .target = omap_target,
- .get = omap_getspeed,
- .init = omap_cpu_init,
- .exit = omap_cpu_exit,
- .name = "omap",
- .attr = omap_cpufreq_attr,
-};
-
-static int __init omap_cpufreq_init(void)
-{
- return cpufreq_register_driver(&omap_driver);
-}
-
-late_initcall(omap_cpufreq_init);
-
-/*
- * if ever we want to remove this, upon cleanup call:
- *
- * cpufreq_unregister_driver()
- * cpufreq_frequency_table_put_attr()
- */
-
--
1.6.6.1
@@ -0,0 +1,171 @@
From f5dc16c8178d0c0bcad795f8ebc71934c4028472 Mon Sep 17 00:00:00 2001
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
Date: Mon, 14 Mar 2011 17:08:49 +0530
Subject: [PATCH 08/19] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430
On OMAP SMP configuartion, both processors share the voltage
and clock. So both CPUs needs to be scaled together and hence
needs software co-ordination.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
cc: Vishwanath BS <vishwanath.bs@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 73 ++++++++++++++++++++++++++-----
1 files changed, 62 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index 27f641b..3730f96 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -26,9 +26,11 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/opp.h>
+#include <linux/cpu.h>
#include <asm/system.h>
#include <asm/smp_plat.h>
+#include <asm/cpu.h>
#include <plat/clock.h>
#include <plat/omap-pm.h>
@@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu)
{
unsigned long rate;
- if (cpu)
+ if (cpu >= NR_CPUS)
return 0;
rate = clk_get_rate(mpu_clk) / 1000;
@@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- int ret = 0;
+ int i, ret = 0;
struct cpufreq_freqs freqs;
+ /* Changes not allowed until all CPUs are online */
+ if (is_smp() && (num_online_cpus() < NR_CPUS))
+ return ret;
+
/* Ensure desired rate is within allowed range. Some govenors
* (ondemand) will just pass target_freq=0 to get the minimum. */
if (target_freq < policy->min)
@@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy,
if (target_freq > policy->max)
target_freq = policy->max;
- freqs.old = omap_getspeed(0);
+ freqs.old = omap_getspeed(policy->cpu);
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
- freqs.cpu = 0;
+ freqs.cpu = policy->cpu;
if (freqs.old == freqs.new)
return ret;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ if (!is_smp()) {
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ goto set_freq;
+ }
+
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ }
+set_freq:
#ifdef CONFIG_CPU_FREQ_DEBUG
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
#endif
@@ -105,12 +121,33 @@ static int omap_target(struct cpufreq_policy *policy,
* CONFIG_SMP enabled. Below code is added only to manage that
* scenario
*/
- if (!is_smp())
+ freqs.new = omap_getspeed(policy->cpu);
+ if (!is_smp()) {
loops_per_jiffy =
cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ goto skip_lpj;
+ }
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+#ifdef CONFIG_SMP
+ /*
+ * Note that loops_per_jiffy is not updated on SMP systems in
+ * cpufreq driver. So, update the per-CPU loops_per_jiffy value
+ * on frequency transition. We need to update all dependent CPUs.
+ */
+ for_each_cpu(i, policy->cpus)
+ per_cpu(cpu_data, i).loops_per_jiffy =
+ cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy,
+ freqs.old, freqs.new);
+#endif
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+
+skip_lpj:
return ret;
}
@@ -118,6 +155,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
{
int result = 0;
struct device *mpu_dev;
+ static cpumask_var_t cpumask;
if (cpu_is_omap24xx())
mpu_clk = clk_get(NULL, "virt_prcm_set");
@@ -129,12 +167,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
if (IS_ERR(mpu_clk))
return PTR_ERR(mpu_clk);
- if (policy->cpu != 0)
+ if (policy->cpu >= NR_CPUS)
return -EINVAL;
- policy->cur = policy->min = policy->max = omap_getspeed(0);
-
+ policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
mpu_dev = omap2_get_mpuss_device();
+
if (!mpu_dev) {
pr_warning("%s: unable to get the mpu device\n", __func__);
return -EINVAL;
@@ -154,7 +192,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
- policy->cur = omap_getspeed(0);
+ policy->cur = omap_getspeed(policy->cpu);
+
+ /*
+ * On OMAP SMP configuartion, both processors share the voltage
+ * and clock. So both CPUs needs to be scaled together and hence
+ * needs software co-ordination. Use cpufreq affected_cpus
+ * interface to handle this scenario. Additional is_smp() check
+ * is to keep SMP_ON_UP build working.
+ */
+ if (is_smp()) {
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+ cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
+ cpumask_copy(policy->cpus, cpumask);
+ }
/* FIXME: what's the actual transition time? */
policy->cpuinfo.transition_latency = 300 * 1000;
--
1.6.6.1
@@ -0,0 +1,30 @@
From 07367b4c3afd8e881c4cf50ef35d081c4ac252b8 Mon Sep 17 00:00:00 2001
From: Jarkko Nikula <jhnikula@gmail.com>
Date: Thu, 14 Apr 2011 16:21:58 +0300
Subject: [PATCH 09/19] OMAP2PLUS: cpufreq: Fix typo when attempting to set mpu_clk for OMAP4
Fix this typo as there is no dpll_mpu_ck for OMAP3 and code flow is clearly
trying to set mpu_clk for OMAP4 for which this dpll_mpu_ck is available.
Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index 3730f96..a725d90 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -161,7 +161,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
mpu_clk = clk_get(NULL, "virt_prcm_set");
else if (cpu_is_omap34xx())
mpu_clk = clk_get(NULL, "dpll1_ck");
- else if (cpu_is_omap34xx())
+ else if (cpu_is_omap44xx())
mpu_clk = clk_get(NULL, "dpll_mpu_ck");
if (IS_ERR(mpu_clk))
--
1.6.6.1
@@ -0,0 +1,64 @@
From 4d3e024c2f7f0334874bbb2a168b62e91cb2517a Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Wed, 25 May 2011 16:38:46 -0700
Subject: [PATCH 10/19] OMAP2+: cpufreq: move clk name decision to init
Clk name does'nt need to dynamically detected during clk init.
move them off to driver initialization, if we dont have a clk name,
there is no point in registering the driver anyways. The actual clk
get and put is left at cpu_init and exit functions.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index a725d90..c46d0cd 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -42,6 +42,7 @@
static struct cpufreq_frequency_table *freq_table;
static struct clk *mpu_clk;
+static char *mpu_clk_name;
static int omap_verify_speed(struct cpufreq_policy *policy)
{
@@ -157,13 +158,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
struct device *mpu_dev;
static cpumask_var_t cpumask;
- if (cpu_is_omap24xx())
- mpu_clk = clk_get(NULL, "virt_prcm_set");
- else if (cpu_is_omap34xx())
- mpu_clk = clk_get(NULL, "dpll1_ck");
- else if (cpu_is_omap44xx())
- mpu_clk = clk_get(NULL, "dpll_mpu_ck");
-
+ mpu_clk = clk_get(NULL, mpu_clk_name);
if (IS_ERR(mpu_clk))
return PTR_ERR(mpu_clk);
@@ -238,6 +233,17 @@ static struct cpufreq_driver omap_driver = {
static int __init omap_cpufreq_init(void)
{
+ if (cpu_is_omap24xx())
+ mpu_clk_name = "virt_prcm_set";
+ else if (cpu_is_omap34xx())
+ mpu_clk_name = "dpll1_ck";
+ else if (cpu_is_omap44xx())
+ mpu_clk_name = "dpll_mpu_ck";
+
+ if (!mpu_clk_name) {
+ pr_err("%s: unsupported Silicon?\n", __func__);
+ return -EINVAL;
+ }
return cpufreq_register_driver(&omap_driver);
}
--
1.6.6.1
@@ -0,0 +1,64 @@
From 85afa12ad2a6e7a23ddf4b25e78e0ce5b9f18a64 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Wed, 25 May 2011 16:38:47 -0700
Subject: [PATCH 11/19] OMAP2+: cpufreq: deny initialization if no mpudev
if we do not have mpu_dev we normally fail in cpu_init. It is better
to fail driver registration if the devices are not available.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 15 ++++++++-------
1 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index c46d0cd..33a91ec 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -43,6 +43,7 @@
static struct cpufreq_frequency_table *freq_table;
static struct clk *mpu_clk;
static char *mpu_clk_name;
+static struct device *mpu_dev;
static int omap_verify_speed(struct cpufreq_policy *policy)
{
@@ -155,7 +156,6 @@ skip_lpj:
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
{
int result = 0;
- struct device *mpu_dev;
static cpumask_var_t cpumask;
mpu_clk = clk_get(NULL, mpu_clk_name);
@@ -166,12 +166,6 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
return -EINVAL;
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
- mpu_dev = omap2_get_mpuss_device();
-
- if (!mpu_dev) {
- pr_warning("%s: unable to get the mpu device\n", __func__);
- return -EINVAL;
- }
opp_init_cpufreq_table(mpu_dev, &freq_table);
if (freq_table) {
@@ -244,6 +238,13 @@ static int __init omap_cpufreq_init(void)
pr_err("%s: unsupported Silicon?\n", __func__);
return -EINVAL;
}
+
+ mpu_dev = omap2_get_mpuss_device();
+ if (!mpu_dev) {
+ pr_warning("%s: unable to get the mpu device\n", __func__);
+ return -EINVAL;
+ }
+
return cpufreq_register_driver(&omap_driver);
}
--
1.6.6.1
@@ -0,0 +1,129 @@
From 345f93655f425c87ba01e949dc038e04542d8cd4 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Thu, 26 May 2011 19:39:17 -0700
Subject: [PATCH 12/19] OMAP2+: cpufreq: dont support !freq_table
OMAP2+ all have frequency tables, hence the hacks we had for older
silicon do not need to be carried forward. As part of this change,
use cpufreq_frequency_table_target to find the best match for
frequency requested.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 67 +++++++++++++++----------------
1 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index 33a91ec..acf18e8 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -38,8 +38,6 @@
#include <mach/hardware.h>
-#define VERY_HI_RATE 900000000
-
static struct cpufreq_frequency_table *freq_table;
static struct clk *mpu_clk;
static char *mpu_clk_name;
@@ -47,20 +45,9 @@ static struct device *mpu_dev;
static int omap_verify_speed(struct cpufreq_policy *policy)
{
- if (freq_table)
- return cpufreq_frequency_table_verify(policy, freq_table);
-
- if (policy->cpu)
+ if (!freq_table)
return -EINVAL;
-
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
-
- policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
- policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
- return 0;
+ return cpufreq_frequency_table_verify(policy, freq_table);
}
static unsigned int omap_getspeed(unsigned int cpu)
@@ -78,22 +65,35 @@ static int omap_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- int i, ret = 0;
+ unsigned int i;
+ int ret = 0;
struct cpufreq_freqs freqs;
/* Changes not allowed until all CPUs are online */
if (is_smp() && (num_online_cpus() < NR_CPUS))
return ret;
- /* Ensure desired rate is within allowed range. Some govenors
- * (ondemand) will just pass target_freq=0 to get the minimum. */
- if (target_freq < policy->min)
- target_freq = policy->min;
- if (target_freq > policy->max)
- target_freq = policy->max;
+ if (!freq_table) {
+ dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
+ policy->cpu);
+ return -EINVAL;
+ }
+
+ ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
+ relation, &i);
+ if (ret) {
+ dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n",
+ __func__, policy->cpu, target_freq, ret);
+ return ret;
+ }
+ freqs.new = freq_table[i].frequency;
+ if (!freqs.new) {
+ dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__,
+ policy->cpu, target_freq);
+ return -EINVAL;
+ }
freqs.old = omap_getspeed(policy->cpu);
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
freqs.cpu = policy->cpu;
if (freqs.old == freqs.new)
@@ -166,19 +166,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
return -EINVAL;
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
- opp_init_cpufreq_table(mpu_dev, &freq_table);
-
- if (freq_table) {
- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
- if (!result)
- cpufreq_frequency_table_get_attr(freq_table,
- policy->cpu);
- } else {
- policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
- policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
- VERY_HI_RATE) / 1000;
+ result = opp_init_cpufreq_table(mpu_dev, &freq_table);
+
+ if (result) {
+ dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
+ __func__, policy->cpu, result);
+ return result;
}
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (!result)
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
policy->cur = omap_getspeed(policy->cpu);
--
1.6.6.1
@@ -0,0 +1,46 @@
From 1e5757cbc79685c6294a178d1bea76a52cffcae9 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Thu, 26 May 2011 19:39:18 -0700
Subject: [PATCH 13/19] OMAP2+: cpufreq: only supports OPP library
OMAP2 is the only family using clk_[init|exit]_cpufreq_table, however,
the cpufreq code does not currently use clk_init_cpufreq_table. As a
result, it is unusuable for OMAP2 and only usable only on platforms
using OPP library.
Remove the unbalanced clk_exit_cpufreq_table(). Any platforms where
OPPs are not availble will fail on init because a freq table will not
be properly initialized.
Signed-off-by: Nishanth Menon <nm@ti.com>
[khilman@ti.com: changelog edits, and graceful failure mode changes]
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index acf18e8..3af7cda 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -1,7 +1,7 @@
/*
* OMAP2PLUS cpufreq driver
*
- * CPU frequency scaling for OMAP
+ * CPU frequency scaling for OMAP using OPP information
*
* Copyright (C) 2005 Nokia Corporation
* Written by Tony Lindgren <tony@atomide.com>
@@ -203,7 +203,6 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
static int omap_cpu_exit(struct cpufreq_policy *policy)
{
- clk_exit_cpufreq_table(&freq_table);
clk_put(mpu_clk);
return 0;
}
--
1.6.6.1
@@ -0,0 +1,61 @@
From bec0338ead64cdd8515ae4c94462ffbfd6ae6418 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Thu, 26 May 2011 19:39:19 -0700
Subject: [PATCH 14/19] OMAP2+: cpufreq: put clk if cpu_init failed
Release the mpu_clk in fail paths.
Reported-by: Todd Poynor <toddpoynor@google.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 14 +++++++++++---
1 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index 3af7cda..e019297 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -162,8 +162,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
if (IS_ERR(mpu_clk))
return PTR_ERR(mpu_clk);
- if (policy->cpu >= NR_CPUS)
- return -EINVAL;
+ if (policy->cpu >= NR_CPUS) {
+ result = -EINVAL;
+ goto fail_ck;
+ }
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
result = opp_init_cpufreq_table(mpu_dev, &freq_table);
@@ -171,12 +173,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
if (result) {
dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
__func__, policy->cpu, result);
- return result;
+ goto fail_ck;
}
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
if (!result)
cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+ else
+ goto fail_ck;
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
@@ -199,6 +203,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 300 * 1000;
return 0;
+
+fail_ck:
+ clk_put(mpu_clk);
+ return result;
}
static int omap_cpu_exit(struct cpufreq_policy *policy)
--
1.6.6.1
@@ -0,0 +1,90 @@
From 0054f5049a4e65a359eca6fa8c6668fb047c9270 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm@ti.com>
Date: Thu, 26 May 2011 19:39:20 -0700
Subject: [PATCH 15/19] OMAP2+: cpufreq: fix freq_table leak
We use a single frequency table for multiple CPUs. But, with
OMAP4, since we have multiple CPUs, the cpu_init call for CPU1
causes freq_table previously allocated for CPU0 to be overwritten.
In addition, we dont free the table on exit path.
We solve this by maintaining an atomic type counter to ensure
just a single table exists at a given time.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 22 +++++++++++++++++-----
1 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index e019297..a962a31 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -39,6 +39,7 @@
#include <mach/hardware.h>
static struct cpufreq_frequency_table *freq_table;
+static atomic_t freq_table_users = ATOMIC_INIT(0);
static struct clk *mpu_clk;
static char *mpu_clk_name;
static struct device *mpu_dev;
@@ -153,6 +154,12 @@ skip_lpj:
return ret;
}
+static inline void freq_table_free(void)
+{
+ if (atomic_dec_and_test(&freq_table_users))
+ opp_free_cpufreq_table(mpu_dev, &freq_table);
+}
+
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
{
int result = 0;
@@ -168,7 +175,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
}
policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
- result = opp_init_cpufreq_table(mpu_dev, &freq_table);
+
+ if (atomic_inc_return(&freq_table_users) == 1)
+ result = opp_init_cpufreq_table(mpu_dev, &freq_table);
if (result) {
dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
@@ -177,10 +186,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
}
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
- if (!result)
- cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
- else
- goto fail_ck;
+ if (result)
+ goto fail_table;
+
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
@@ -204,6 +213,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
return 0;
+fail_table:
+ freq_table_free();
fail_ck:
clk_put(mpu_clk);
return result;
@@ -211,6 +222,7 @@ fail_ck:
static int omap_cpu_exit(struct cpufreq_policy *policy)
{
+ freq_table_free();
clk_put(mpu_clk);
return 0;
}
--
1.6.6.1
@@ -0,0 +1,58 @@
From 255f1830ab71e130bbdffd84e61fc7a8c3791120 Mon Sep 17 00:00:00 2001
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
Date: Fri, 3 Jun 2011 17:46:57 +0530
Subject: [PATCH 16/19] OMAP2+: CPUfreq: Remove superfluous check in target() for online CPU's.
Current OMAP2PLUS CPUfreq tagret() functions returns when all
the CPU's are not online. This breaks CPUfreq when secondary CPUs
are offlined on SMP system.
The intention of that check was just avoid CPU frequency change
during the window when CPU becomes online but it's cpufreq_init is
not done yet. Otherwise it can lead to notifiers being sent on
a CPU which is not yet registered to the governor.
But this race conditions is already managed by the CPUfreq
core driver by updating the available cpumask accordingly.
OMAP CPUFReq driver make use same cpumask for the notifiers
so the above problem doesn't exist. In my initial implementation
of the OMAP4 CPUFreq driver, I was using 'for_each_online_cpu()'
for notifiers which lead me to add that check. Later I fixed
the notifies but didn't realise that the check has become
redundant then.
Fix it by removing the superfluous check in target().
Thanks for Nishant Menon <nm@ti.com> for reporting issue
with hot-plug and Kevin Hilman <khilman@ti.com> for his
comment on excessive check in target().
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reported-by: Nishanth Menon <nm@ti.com>
Tested-by: Vishwanath BS <vishwanath.bs@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
Tested-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index a962a31..eaefa49 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -70,10 +70,6 @@ static int omap_target(struct cpufreq_policy *policy,
int ret = 0;
struct cpufreq_freqs freqs;
- /* Changes not allowed until all CPUs are online */
- if (is_smp() && (num_online_cpus() < NR_CPUS))
- return ret;
-
if (!freq_table) {
dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
policy->cpu);
--
1.6.6.1
@@ -0,0 +1,48 @@
From 3bf92d672cb3ee7c1ec39f1f0fcf6e8dbde2ceb9 Mon Sep 17 00:00:00 2001
From: Colin Cross <ccross@google.com>
Date: Mon, 6 Jun 2011 21:05:29 -0500
Subject: [PATCH 17/19] OMAP2+: cpufreq: notify even with bad boot frequency
Sometimes, bootloaders starts up with a frequency which is not
in the OPP table. At cpu_init, policy->cur contains the frequency
we pick at boot. It is possible that system might have fixed
it's boot frequency later on as part of power initialization.
After this condition, the first call to omap_target results in the
following:
omap_getspeed(actual device frequency) != policy->cur(frequency that
cpufreq thinks that the system is at), and it is possible that
freqs.old == freqs.new (because the governor requested a scale down).
We exit without triggering the notifiers in the current code, which
does'nt let code which depends on cpufreq_notify_transition to have
accurate information as to what the system frequency is.
Instead, we do a normal transition if policy->cur is wrong, then,
freqs.old will be the actual cpu frequency, freqs.new will be the
actual new cpu frequency and all required notifiers have the accurate
information.
Acked-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Colin Cross <ccross@google.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index eaefa49..8598928 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -93,7 +93,7 @@ static int omap_target(struct cpufreq_policy *policy,
freqs.old = omap_getspeed(policy->cpu);
freqs.cpu = policy->cpu;
- if (freqs.old == freqs.new)
+ if (freqs.old == freqs.new && policy->cur == freqs.new)
return ret;
if (!is_smp()) {
--
1.6.6.1
@@ -0,0 +1,42 @@
From 6e092f78e67d722be6036131df6aa0b8b2fec879 Mon Sep 17 00:00:00 2001
From: Todd Poynor <toddpoynor@google.com>
Date: Tue, 7 Jun 2011 13:57:52 -0700
Subject: [PATCH 18/19] OMAP2+: cpufreq: Enable all CPUs in shared policy mask
Enable all CPUs in the shared policy in the CPU init callback.
Otherwise, the governor CPUFREQ_GOV_START event is invoked with
a policy that only includes the first CPU, leaving other CPUs
uninitialized by the governor.
Signed-off-by: Todd Poynor <toddpoynor@google.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index 8598928..1f3b2e1 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -159,7 +159,6 @@ static inline void freq_table_free(void)
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
{
int result = 0;
- static cpumask_var_t cpumask;
mpu_clk = clk_get(NULL, mpu_clk_name);
if (IS_ERR(mpu_clk))
@@ -200,8 +199,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
*/
if (is_smp()) {
policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
- cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
- cpumask_copy(policy->cpus, cpumask);
+ cpumask_setall(policy->cpus);
}
/* FIXME: what's the actual transition time? */
--
1.6.6.1
@@ -0,0 +1,121 @@
From e8fa6ffc7822b7c7e81fafb112f3064f31c5c0e3 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@arm.linux.org.uk>
Date: Mon, 11 Jul 2011 23:10:04 +0530
Subject: [PATCH 19/19] OMAP2+: CPUfreq: update lpj with reference value to avoid progressive error.
Adjust _both_ the per-cpu loops_per_jiffy and global lpj. Calibrate them
with with reference to the initial values to avoid a progressively
bigger and bigger error in the value over time.
While at this, re-use the notifiers for UP/SMP since on
UP machine or UP_ON_SMP policy->cpus mask would contain only
the boot CPU.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
[santosh.shilimkar@ti.com: re-based against omap cpufreq
upstream branch and fixed notifiers]
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Kevin Hilman <khilman@ti.com>
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
arch/arm/mach-omap2/omap2plus-cpufreq.c | 50 ++++++++++++++++--------------
1 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
index 1f3b2e1..de82e87 100644
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
@@ -38,6 +38,16 @@
#include <mach/hardware.h>
+#ifdef CONFIG_SMP
+struct lpj_info {
+ unsigned long ref;
+ unsigned int freq;
+};
+
+static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
+static struct lpj_info global_lpj_ref;
+#endif
+
static struct cpufreq_frequency_table *freq_table;
static atomic_t freq_table_users = ATOMIC_INIT(0);
static struct clk *mpu_clk;
@@ -96,37 +106,18 @@ static int omap_target(struct cpufreq_policy *policy,
if (freqs.old == freqs.new && policy->cur == freqs.new)
return ret;
- if (!is_smp()) {
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- goto set_freq;
- }
-
/* notifiers */
for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
-set_freq:
#ifdef CONFIG_CPU_FREQ_DEBUG
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
#endif
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
-
- /*
- * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies
- * won't get updated when UP machine cpufreq build with
- * CONFIG_SMP enabled. Below code is added only to manage that
- * scenario
- */
freqs.new = omap_getspeed(policy->cpu);
- if (!is_smp()) {
- loops_per_jiffy =
- cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- goto skip_lpj;
- }
#ifdef CONFIG_SMP
/*
@@ -134,10 +125,24 @@ set_freq:
* cpufreq driver. So, update the per-CPU loops_per_jiffy value
* on frequency transition. We need to update all dependent CPUs.
*/
- for_each_cpu(i, policy->cpus)
+ for_each_cpu(i, policy->cpus) {
+ struct lpj_info *lpj = &per_cpu(lpj_ref, i);
+ if (!lpj->freq) {
+ lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
+ lpj->freq = freqs.old;
+ }
+
per_cpu(cpu_data, i).loops_per_jiffy =
- cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy,
- freqs.old, freqs.new);
+ cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
+ }
+
+ /* And don't forget to adjust the global one */
+ if (!global_lpj_ref.freq) {
+ global_lpj_ref.ref = loops_per_jiffy;
+ global_lpj_ref.freq = freqs.old;
+ }
+ loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
+ freqs.new);
#endif
/* notifiers */
@@ -146,7 +151,6 @@ set_freq:
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
-skip_lpj:
return ret;
}
--
1.6.6.1
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
require linux.inc
DESCRIPTION = "Linux kernel for TI processors"
KERNEL_IMAGETYPE = "uImage"
COMPATIBLE_MACHINE = "(beagleboard)"
# Somewhere after 3.0rc7
SRCREV_pn-${PN} = "e6625fa48e6580a74b7e700efd7e6463e282810b"
# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
MACHINE_KERNEL_PR_append = "a"
FILESPATHPKG_prepend = "linux-3.0:"
SRC_URI += "git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git;protocol=git \
file://beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch \
file://pm-wip/cpufreq/0001-PM-OPP-introduce-function-to-free-cpufreq-table.patch \
file://pm-wip/cpufreq/0002-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch \
file://pm-wip/cpufreq/0003-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch \
file://pm-wip/cpufreq/0004-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch \
file://pm-wip/cpufreq/0005-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch \
file://pm-wip/cpufreq/0006-cpufreq-fixup-after-new-OPP-layer-merged.patch \
file://pm-wip/cpufreq/0007-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch \
file://pm-wip/cpufreq/0008-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch \
file://pm-wip/cpufreq/0009-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch \
file://pm-wip/cpufreq/0010-OMAP2-cpufreq-move-clk-name-decision-to-init.patch \
file://pm-wip/cpufreq/0011-OMAP2-cpufreq-deny-initialization-if-no-mpudev.patch \
file://pm-wip/cpufreq/0012-OMAP2-cpufreq-dont-support-freq_table.patch \
file://pm-wip/cpufreq/0013-OMAP2-cpufreq-only-supports-OPP-library.patch \
file://pm-wip/cpufreq/0014-OMAP2-cpufreq-put-clk-if-cpu_init-failed.patch \
file://pm-wip/cpufreq/0015-OMAP2-cpufreq-fix-freq_table-leak.patch \
file://pm-wip/cpufreq/0016-OMAP2-CPUfreq-Remove-superfluous-check-in-target-for.patch \
file://pm-wip/cpufreq/0017-OMAP2-cpufreq-notify-even-with-bad-boot-frequency.patch \
file://pm-wip/cpufreq/0018-OMAP2-cpufreq-Enable-all-CPUs-in-shared-policy-mask.patch \
file://pm-wip/cpufreq/0019-OMAP2-CPUfreq-update-lpj-with-reference-value-to-avo.patch \
file://for_3.1/pm-misc/0001-OMAP3-SR-disable-interrupt-by-default.patch \
file://for_3.1/pm-misc/0002-OMAP3-SR-enable-disable-SR-only-on-need.patch \
file://for_3.1/pm-misc/0003-OMAP3-SR-fix-cosmetic-indentation.patch \
file://for_3.1/pm-misc/0004-OMAP3-PM-debug-remove-sleep_while_idle-feature.patch \
file://for_3.1/pm-misc/0005-OMAP2-PM-debug-remove-register-dumping.patch \
file://for_3.1/pm-misc/0006-OMAP3-PM-debug-remove-register-dumping.patch \
file://for_3.1/pm-misc/0007-OMAP2-PM-fix-section-mismatch-in-pm_dbg_init.patch \
file://defconfig"
SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
"
S = "${WORKDIR}/git"