Commit b9e7683b authored by Tony Lindgren's avatar Tony Lindgren

Merge branch 'pm-opp' of...

Merge branch 'pm-opp' of ssh://master.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-linus
parents bb3613aa 53da4ce2
......@@ -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();
......
/*
* 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 */
/*
* 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;
}
/*
* 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);
/*
* 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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment