Merge branch 'pm-opp' of ssh://master.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-linus
This commit is contained in:
Коммит
b9e7683bbc
|
@ -127,3 +127,28 @@ implementation needs:
|
|||
10. (*pdata->cpu_set_freq)(unsigned long f)
|
||||
|
||||
11. (*pdata->cpu_get_freq)(void)
|
||||
|
||||
Customizing OPP for platform
|
||||
============================
|
||||
Defining CONFIG_PM should enable OPP layer for the silicon
|
||||
and the registration of OPP table should take place automatically.
|
||||
However, in special cases, the default OPP table may need to be
|
||||
tweaked, for e.g.:
|
||||
* enable default OPPs which are disabled by default, but which
|
||||
could be enabled on a platform
|
||||
* Disable an unsupported OPP on the platform
|
||||
* Define and add a custom opp table entry
|
||||
in these cases, the board file needs to do additional steps as follows:
|
||||
arch/arm/mach-omapx/board-xyz.c
|
||||
#include "pm.h"
|
||||
....
|
||||
static void __init omap_xyz_init_irq(void)
|
||||
{
|
||||
....
|
||||
/* Initialize the default table */
|
||||
omapx_opp_init();
|
||||
/* Do customization to the defaults */
|
||||
....
|
||||
}
|
||||
NOTE: omapx_opp_init will be omap3_opp_init or as required
|
||||
based on the omap family.
|
||||
|
|
|
@ -35,6 +35,8 @@ config ARCH_OMAP3
|
|||
select CPU_V7
|
||||
select USB_ARCH_HAS_EHCI
|
||||
select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
|
||||
select ARCH_HAS_OPP
|
||||
select PM_OPP if PM
|
||||
|
||||
config ARCH_OMAP4
|
||||
bool "TI OMAP4"
|
||||
|
@ -44,6 +46,8 @@ config ARCH_OMAP4
|
|||
select ARM_GIC
|
||||
select PL310_ERRATA_588369
|
||||
select ARM_ERRATA_720789
|
||||
select ARCH_HAS_OPP
|
||||
select PM_OPP if PM
|
||||
|
||||
comment "OMAP Core Type"
|
||||
depends on ARCH_OMAP2
|
||||
|
|
|
@ -49,6 +49,13 @@ obj-$(CONFIG_ARCH_OMAP4) += mux44xx.o
|
|||
obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o
|
||||
# obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o
|
||||
|
||||
# OPP table initialization
|
||||
ifeq ($(CONFIG_PM_OPP),y)
|
||||
obj-y += opp.o
|
||||
obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o
|
||||
endif
|
||||
|
||||
# Power Management
|
||||
ifeq ($(CONFIG_PM),y)
|
||||
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
|
||||
|
|
|
@ -347,8 +347,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
|
|||
else if (cpu_is_omap44xx())
|
||||
omap44xx_hwmod_init();
|
||||
|
||||
/* The OPP tables have to be registered before a clk init */
|
||||
omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
|
||||
omap_pm_if_early_init();
|
||||
|
||||
if (cpu_is_omap2420())
|
||||
omap2420_clk_init();
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* OMAP SoC specific OPP Data helpers
|
||||
*
|
||||
* Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
* Kevin Hilman
|
||||
* Copyright (C) 2010 Nokia Corporation.
|
||||
* Eduardo Valentin
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
|
||||
#define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
|
||||
|
||||
#include <plat/omap_hwmod.h>
|
||||
|
||||
/*
|
||||
* *BIG FAT WARNING*:
|
||||
* USE the following ONLY in opp data initialization common to an SoC.
|
||||
* DO NOT USE these in board files/pm core etc.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct omap_opp_def - OMAP OPP Definition
|
||||
* @hwmod_name: Name of the hwmod for this domain
|
||||
* @freq: Frequency in hertz corresponding to this OPP
|
||||
* @u_volt: Nominal voltage in microvolts corresponding to this OPP
|
||||
* @default_available: True/false - is this OPP available by default
|
||||
*
|
||||
* OMAP SOCs have a standard set of tuples consisting of frequency and voltage
|
||||
* pairs that the device will support per voltage domain. This is called
|
||||
* Operating Points or OPP. The actual definitions of OMAP Operating Points
|
||||
* varies over silicon within the same family of devices. For a specific
|
||||
* domain, you can have a set of {frequency, voltage} pairs and this is denoted
|
||||
* by an array of omap_opp_def. As the kernel boots and more information is
|
||||
* available, a set of these are activated based on the precise nature of
|
||||
* device the kernel boots up on. It is interesting to remember that each IP
|
||||
* which belongs to a voltage domain may define their own set of OPPs on top
|
||||
* of this - but this is handled by the appropriate driver.
|
||||
*/
|
||||
struct omap_opp_def {
|
||||
char *hwmod_name;
|
||||
|
||||
unsigned long freq;
|
||||
unsigned long u_volt;
|
||||
|
||||
bool default_available;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialization wrapper used to define an OPP for OMAP variants.
|
||||
*/
|
||||
#define OPP_INITIALIZER(_hwmod_name, _enabled, _freq, _uv) \
|
||||
{ \
|
||||
.hwmod_name = _hwmod_name, \
|
||||
.default_available = _enabled, \
|
||||
.freq = _freq, \
|
||||
.u_volt = _uv, \
|
||||
}
|
||||
|
||||
/* Use this to initialize the default table */
|
||||
extern int __init omap_init_opp_table(struct omap_opp_def *opp_def,
|
||||
u32 opp_def_size);
|
||||
|
||||
#endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* OMAP SoC specific OPP wrapper function
|
||||
*
|
||||
* Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
* Kevin Hilman
|
||||
* Copyright (C) 2010 Nokia Corporation.
|
||||
* Eduardo Valentin
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/opp.h>
|
||||
|
||||
#include <plat/omap_device.h>
|
||||
|
||||
#include "omap_opp_data.h"
|
||||
|
||||
/* Temp variable to allow multiple calls */
|
||||
static u8 __initdata omap_table_init;
|
||||
|
||||
/**
|
||||
* omap_init_opp_table() - Initialize opp table as per the CPU type
|
||||
* @opp_def: opp default list for this silicon
|
||||
* @opp_def_size: number of opp entries for this silicon
|
||||
*
|
||||
* Register the initial OPP table with the OPP library based on the CPU
|
||||
* type. This is meant to be used only by SoC specific registration.
|
||||
*/
|
||||
int __init omap_init_opp_table(struct omap_opp_def *opp_def,
|
||||
u32 opp_def_size)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (!opp_def || !opp_def_size) {
|
||||
pr_err("%s: invalid params!\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize only if not already initialized even if the previous
|
||||
* call failed, because, no reason we'd succeed again.
|
||||
*/
|
||||
if (omap_table_init)
|
||||
return -EEXIST;
|
||||
omap_table_init = 1;
|
||||
|
||||
/* Lets now register with OPP library */
|
||||
for (i = 0; i < opp_def_size; i++) {
|
||||
struct omap_hwmod *oh;
|
||||
struct device *dev;
|
||||
|
||||
if (!opp_def->hwmod_name) {
|
||||
pr_err("%s: NULL name of omap_hwmod, failing [%d].\n",
|
||||
__func__, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
oh = omap_hwmod_lookup(opp_def->hwmod_name);
|
||||
if (!oh || !oh->od) {
|
||||
pr_warn("%s: no hwmod or odev for %s, [%d] "
|
||||
"cannot add OPPs.\n", __func__,
|
||||
opp_def->hwmod_name, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev = &oh->od->pdev.dev;
|
||||
|
||||
r = opp_add(dev, opp_def->freq, opp_def->u_volt);
|
||||
if (r) {
|
||||
dev_err(dev, "%s: add OPP %ld failed for %s [%d] "
|
||||
"result=%d\n",
|
||||
__func__, opp_def->freq,
|
||||
opp_def->hwmod_name, i, r);
|
||||
} else {
|
||||
if (!opp_def->default_available)
|
||||
r = opp_disable(dev, opp_def->freq);
|
||||
if (r)
|
||||
dev_err(dev, "%s: disable %ld failed for %s "
|
||||
"[%d] result=%d\n",
|
||||
__func__, opp_def->freq,
|
||||
opp_def->hwmod_name, i, r);
|
||||
}
|
||||
opp_def++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* OMAP3 OPP table definitions.
|
||||
*
|
||||
* Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
* Kevin Hilman
|
||||
* Copyright (C) 2010 Nokia Corporation.
|
||||
* Eduardo Valentin
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "omap_opp_data.h"
|
||||
|
||||
static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
|
||||
/* MPU OPP1 */
|
||||
OPP_INITIALIZER("mpu", true, 125000000, 975000),
|
||||
/* MPU OPP2 */
|
||||
OPP_INITIALIZER("mpu", true, 250000000, 1075000),
|
||||
/* MPU OPP3 */
|
||||
OPP_INITIALIZER("mpu", true, 500000000, 1200000),
|
||||
/* MPU OPP4 */
|
||||
OPP_INITIALIZER("mpu", true, 550000000, 1270000),
|
||||
/* MPU OPP5 */
|
||||
OPP_INITIALIZER("mpu", true, 600000000, 1350000),
|
||||
|
||||
/*
|
||||
* L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
|
||||
* almost the same than the one at 83MHz thus providing very little
|
||||
* gain for the power point of view. In term of energy it will even
|
||||
* increase the consumption due to the very negative performance
|
||||
* impact that frequency will do to the MPU and the whole system in
|
||||
* general.
|
||||
*/
|
||||
OPP_INITIALIZER("l3_main", false, 41500000, 975000),
|
||||
/* L3 OPP2 */
|
||||
OPP_INITIALIZER("l3_main", true, 83000000, 1050000),
|
||||
/* L3 OPP3 */
|
||||
OPP_INITIALIZER("l3_main", true, 166000000, 1150000),
|
||||
|
||||
/* DSP OPP1 */
|
||||
OPP_INITIALIZER("iva", true, 90000000, 975000),
|
||||
/* DSP OPP2 */
|
||||
OPP_INITIALIZER("iva", true, 180000000, 1075000),
|
||||
/* DSP OPP3 */
|
||||
OPP_INITIALIZER("iva", true, 360000000, 1200000),
|
||||
/* DSP OPP4 */
|
||||
OPP_INITIALIZER("iva", true, 400000000, 1270000),
|
||||
/* DSP OPP5 */
|
||||
OPP_INITIALIZER("iva", true, 430000000, 1350000),
|
||||
};
|
||||
|
||||
static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
|
||||
/* MPU OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("mpu", true, 300000000, 1012500),
|
||||
/* MPU OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("mpu", true, 600000000, 1200000),
|
||||
/* MPU OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("mpu", false, 800000000, 1325000),
|
||||
/* MPU OPP4 - OPP-SB */
|
||||
OPP_INITIALIZER("mpu", false, 1000000000, 1375000),
|
||||
|
||||
/* L3 OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("l3_main", true, 100000000, 1000000),
|
||||
/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
|
||||
OPP_INITIALIZER("l3_main", true, 200000000, 1200000),
|
||||
|
||||
/* DSP OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("iva", true, 260000000, 1012500),
|
||||
/* DSP OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("iva", true, 520000000, 1200000),
|
||||
/* DSP OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("iva", false, 660000000, 1325000),
|
||||
/* DSP OPP4 - OPP-SB */
|
||||
OPP_INITIALIZER("iva", false, 800000000, 1375000),
|
||||
};
|
||||
|
||||
/**
|
||||
* omap3_opp_init() - initialize omap3 opp table
|
||||
*/
|
||||
static int __init omap3_opp_init(void)
|
||||
{
|
||||
int r = -ENODEV;
|
||||
|
||||
if (!cpu_is_omap34xx())
|
||||
return r;
|
||||
|
||||
if (cpu_is_omap3630())
|
||||
r = omap_init_opp_table(omap36xx_opp_def_list,
|
||||
ARRAY_SIZE(omap36xx_opp_def_list));
|
||||
else
|
||||
r = omap_init_opp_table(omap34xx_opp_def_list,
|
||||
ARRAY_SIZE(omap34xx_opp_def_list));
|
||||
|
||||
return r;
|
||||
}
|
||||
device_initcall(omap3_opp_init);
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* OMAP4 OPP table definitions.
|
||||
*
|
||||
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
* Kevin Hilman
|
||||
* Thara Gopinath
|
||||
* Copyright (C) 2010 Nokia Corporation.
|
||||
* Eduardo Valentin
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "omap_opp_data.h"
|
||||
|
||||
static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
|
||||
/* MPU OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("mpu", true, 300000000, 1100000),
|
||||
/* MPU OPP2 - OPP100 */
|
||||
OPP_INITIALIZER("mpu", true, 600000000, 1200000),
|
||||
/* MPU OPP3 - OPP-Turbo */
|
||||
OPP_INITIALIZER("mpu", false, 800000000, 1260000),
|
||||
/* MPU OPP4 - OPP-SB */
|
||||
OPP_INITIALIZER("mpu", false, 1008000000, 1350000),
|
||||
/* L3 OPP1 - OPP50 */
|
||||
OPP_INITIALIZER("l3_main_1", true, 100000000, 930000),
|
||||
/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
|
||||
OPP_INITIALIZER("l3_main_1", true, 200000000, 1100000),
|
||||
/* TODO: add IVA, DSP, aess, fdif, gpu */
|
||||
};
|
||||
|
||||
/**
|
||||
* omap4_opp_init() - initialize omap4 opp table
|
||||
*/
|
||||
static int __init omap4_opp_init(void)
|
||||
{
|
||||
int r = -ENODEV;
|
||||
|
||||
if (!cpu_is_omap44xx())
|
||||
return r;
|
||||
|
||||
r = omap_init_opp_table(omap44xx_opp_def_list,
|
||||
ARRAY_SIZE(omap44xx_opp_def_list));
|
||||
|
||||
return r;
|
||||
}
|
||||
device_initcall(omap4_opp_init);
|
|
@ -20,6 +20,20 @@ extern int omap3_can_sleep(void);
|
|||
extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
|
||||
extern int omap3_idle_init(void);
|
||||
|
||||
#if defined(CONFIG_PM_OPP)
|
||||
extern int omap3_opp_init(void);
|
||||
extern int omap4_opp_init(void);
|
||||
#else
|
||||
static inline int omap3_opp_init(void)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int omap4_opp_init(void)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct cpuidle_params {
|
||||
u8 valid;
|
||||
u32 sleep_latency;
|
||||
|
|
|
@ -17,27 +17,10 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/opp.h>
|
||||
|
||||
#include "powerdomain.h"
|
||||
|
||||
/**
|
||||
* struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
|
||||
* @rate: target clock rate
|
||||
* @opp_id: OPP ID
|
||||
* @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
|
||||
*
|
||||
* Operating performance point data. Can vary by OMAP chip and board.
|
||||
*/
|
||||
struct omap_opp {
|
||||
unsigned long rate;
|
||||
u8 opp_id;
|
||||
u16 min_vdd;
|
||||
};
|
||||
|
||||
extern struct omap_opp *mpu_opps;
|
||||
extern struct omap_opp *dsp_opps;
|
||||
extern struct omap_opp *l3_opps;
|
||||
|
||||
/*
|
||||
* agent_id values for use with omap_pm_set_min_bus_tput():
|
||||
*
|
||||
|
@ -59,9 +42,11 @@ extern struct omap_opp *l3_opps;
|
|||
* framework starts. The "_if_" is to avoid name collisions with the
|
||||
* PM idle-loop code.
|
||||
*/
|
||||
int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
|
||||
struct omap_opp *dsp_opp_table,
|
||||
struct omap_opp *l3_opp_table);
|
||||
#ifdef CONFIG_OMAP_PM_NONE
|
||||
#define omap_pm_if_early_init() 0
|
||||
#else
|
||||
int __init omap_pm_if_early_init(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* omap_pm_if_init - OMAP PM init code called after clock fw init
|
||||
|
@ -69,7 +54,11 @@ int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
|
|||
* The main initialization code. OPP tables are passed in here. The
|
||||
* "_if_" is to avoid name collisions with the PM idle-loop code.
|
||||
*/
|
||||
#ifdef CONFIG_OMAP_PM_NONE
|
||||
#define omap_pm_if_init() 0
|
||||
#else
|
||||
int __init omap_pm_if_init(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* omap_pm_if_exit - OMAP PM exit code
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
|
||||
#include <plat/powerdomain.h>
|
||||
|
||||
struct omap_opp *dsp_opps;
|
||||
struct omap_opp *mpu_opps;
|
||||
struct omap_opp *l3_opps;
|
||||
|
||||
/*
|
||||
* Device-driver-originated constraints (via board-*.c files)
|
||||
*/
|
||||
|
@ -308,13 +304,8 @@ int omap_pm_get_dev_context_loss_count(struct device *dev)
|
|||
|
||||
|
||||
/* Should be called before clk framework init */
|
||||
int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
|
||||
struct omap_opp *dsp_opp_table,
|
||||
struct omap_opp *l3_opp_table)
|
||||
int __init omap_pm_if_early_init(void)
|
||||
{
|
||||
mpu_opps = mpu_opp_table;
|
||||
dsp_opps = dsp_opp_table;
|
||||
l3_opps = l3_opp_table;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче