Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

omap: opp: add OMAP3 OPP table data and common init

Add OPP data for OMAP34xx and OMAP36xx and initialization functions
to populate OPP tables based on current SoC.
introduce an OMAP generic opp initialization routine which OMAP3
and OMAP4+ SoCs can use to register their OPP definitions.

Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>

authored by

Nishanth Menon and committed by
Kevin Hilman
fd1478cd 4584acc3

+314
+25
Documentation/arm/OMAP/omap_pm
··· 127 127 10. (*pdata->cpu_set_freq)(unsigned long f) 128 128 129 129 11. (*pdata->cpu_get_freq)(void) 130 + 131 + Customizing OPP for platform 132 + ============================ 133 + Defining CONFIG_PM should enable OPP layer for the silicon 134 + and the registration of OPP table should take place automatically. 135 + However, in special cases, the default OPP table may need to be 136 + tweaked, for e.g.: 137 + * enable default OPPs which are disabled by default, but which 138 + could be enabled on a platform 139 + * Disable an unsupported OPP on the platform 140 + * Define and add a custom opp table entry 141 + in these cases, the board file needs to do additional steps as follows: 142 + arch/arm/mach-omapx/board-xyz.c 143 + #include "pm.h" 144 + .... 145 + static void __init omap_xyz_init_irq(void) 146 + { 147 + .... 148 + /* Initialize the default table */ 149 + omapx_opp_init(); 150 + /* Do customization to the defaults */ 151 + .... 152 + } 153 + NOTE: omapx_opp_init will be omap3_opp_init or as required 154 + based on the omap family.
+2
arch/arm/mach-omap2/Kconfig
··· 35 35 select CPU_V7 36 36 select USB_ARCH_HAS_EHCI 37 37 select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4 38 + select ARCH_HAS_OPP 39 + select PM_OPP if PM 38 40 39 41 config ARCH_OMAP4 40 42 bool "TI OMAP4"
+6
arch/arm/mach-omap2/Makefile
··· 49 49 obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o 50 50 # obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o 51 51 52 + # OPP table initialization 53 + ifeq ($(CONFIG_PM_OPP),y) 54 + obj-y += opp.o 55 + obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o 56 + endif 57 + 52 58 # Power Management 53 59 ifeq ($(CONFIG_PM),y) 54 60 obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
+72
arch/arm/mach-omap2/omap_opp_data.h
··· 1 + /* 2 + * OMAP SoC specific OPP Data helpers 3 + * 4 + * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ 5 + * Nishanth Menon 6 + * Kevin Hilman 7 + * Copyright (C) 2010 Nokia Corporation. 8 + * Eduardo Valentin 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + * 14 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 15 + * kind, whether express or implied; without even the implied warranty 16 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + */ 19 + #ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H 20 + #define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H 21 + 22 + #include <plat/omap_hwmod.h> 23 + 24 + /* 25 + * *BIG FAT WARNING*: 26 + * USE the following ONLY in opp data initialization common to an SoC. 27 + * DO NOT USE these in board files/pm core etc. 28 + */ 29 + 30 + /** 31 + * struct omap_opp_def - OMAP OPP Definition 32 + * @hwmod_name: Name of the hwmod for this domain 33 + * @freq: Frequency in hertz corresponding to this OPP 34 + * @u_volt: Nominal voltage in microvolts corresponding to this OPP 35 + * @default_available: True/false - is this OPP available by default 36 + * 37 + * OMAP SOCs have a standard set of tuples consisting of frequency and voltage 38 + * pairs that the device will support per voltage domain. This is called 39 + * Operating Points or OPP. The actual definitions of OMAP Operating Points 40 + * varies over silicon within the same family of devices. For a specific 41 + * domain, you can have a set of {frequency, voltage} pairs and this is denoted 42 + * by an array of omap_opp_def. As the kernel boots and more information is 43 + * available, a set of these are activated based on the precise nature of 44 + * device the kernel boots up on. It is interesting to remember that each IP 45 + * which belongs to a voltage domain may define their own set of OPPs on top 46 + * of this - but this is handled by the appropriate driver. 47 + */ 48 + struct omap_opp_def { 49 + char *hwmod_name; 50 + 51 + unsigned long freq; 52 + unsigned long u_volt; 53 + 54 + bool default_available; 55 + }; 56 + 57 + /* 58 + * Initialization wrapper used to define an OPP for OMAP variants. 59 + */ 60 + #define OPP_INITIALIZER(_hwmod_name, _enabled, _freq, _uv) \ 61 + { \ 62 + .hwmod_name = _hwmod_name, \ 63 + .default_available = _enabled, \ 64 + .freq = _freq, \ 65 + .u_volt = _uv, \ 66 + } 67 + 68 + /* Use this to initialize the default table */ 69 + extern int __init omap_init_opp_table(struct omap_opp_def *opp_def, 70 + u32 opp_def_size); 71 + 72 + #endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
+93
arch/arm/mach-omap2/opp.c
··· 1 + /* 2 + * OMAP SoC specific OPP wrapper function 3 + * 4 + * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ 5 + * Nishanth Menon 6 + * Kevin Hilman 7 + * Copyright (C) 2010 Nokia Corporation. 8 + * Eduardo Valentin 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + * 14 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 15 + * kind, whether express or implied; without even the implied warranty 16 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + */ 19 + #include <linux/module.h> 20 + #include <linux/opp.h> 21 + 22 + #include <plat/omap_device.h> 23 + 24 + #include "omap_opp_data.h" 25 + 26 + /* Temp variable to allow multiple calls */ 27 + static u8 __initdata omap_table_init; 28 + 29 + /** 30 + * omap_init_opp_table() - Initialize opp table as per the CPU type 31 + * @opp_def: opp default list for this silicon 32 + * @opp_def_size: number of opp entries for this silicon 33 + * 34 + * Register the initial OPP table with the OPP library based on the CPU 35 + * type. This is meant to be used only by SoC specific registration. 36 + */ 37 + int __init omap_init_opp_table(struct omap_opp_def *opp_def, 38 + u32 opp_def_size) 39 + { 40 + int i, r; 41 + 42 + if (!opp_def || !opp_def_size) { 43 + pr_err("%s: invalid params!\n", __func__); 44 + return -EINVAL; 45 + } 46 + 47 + /* 48 + * Initialize only if not already initialized even if the previous 49 + * call failed, because, no reason we'd succeed again. 50 + */ 51 + if (omap_table_init) 52 + return -EEXIST; 53 + omap_table_init = 1; 54 + 55 + /* Lets now register with OPP library */ 56 + for (i = 0; i < opp_def_size; i++) { 57 + struct omap_hwmod *oh; 58 + struct device *dev; 59 + 60 + if (!opp_def->hwmod_name) { 61 + pr_err("%s: NULL name of omap_hwmod, failing [%d].\n", 62 + __func__, i); 63 + return -EINVAL; 64 + } 65 + oh = omap_hwmod_lookup(opp_def->hwmod_name); 66 + if (!oh || !oh->od) { 67 + pr_warn("%s: no hwmod or odev for %s, [%d] " 68 + "cannot add OPPs.\n", __func__, 69 + opp_def->hwmod_name, i); 70 + return -EINVAL; 71 + } 72 + dev = &oh->od->pdev.dev; 73 + 74 + r = opp_add(dev, opp_def->freq, opp_def->u_volt); 75 + if (r) { 76 + dev_err(dev, "%s: add OPP %ld failed for %s [%d] " 77 + "result=%d\n", 78 + __func__, opp_def->freq, 79 + opp_def->hwmod_name, i, r); 80 + } else { 81 + if (!opp_def->default_available) 82 + r = opp_disable(dev, opp_def->freq); 83 + if (r) 84 + dev_err(dev, "%s: disable %ld failed for %s " 85 + "[%d] result=%d\n", 86 + __func__, opp_def->freq, 87 + opp_def->hwmod_name, i, r); 88 + } 89 + opp_def++; 90 + } 91 + 92 + return 0; 93 + }
+107
arch/arm/mach-omap2/opp3xxx_data.c
··· 1 + /* 2 + * OMAP3 OPP table definitions. 3 + * 4 + * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ 5 + * Nishanth Menon 6 + * Kevin Hilman 7 + * Copyright (C) 2010 Nokia Corporation. 8 + * Eduardo Valentin 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + * 14 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 15 + * kind, whether express or implied; without even the implied warranty 16 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + */ 19 + #include <linux/module.h> 20 + 21 + #include <plat/cpu.h> 22 + 23 + #include "omap_opp_data.h" 24 + 25 + static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { 26 + /* MPU OPP1 */ 27 + OPP_INITIALIZER("mpu", true, 125000000, 975000), 28 + /* MPU OPP2 */ 29 + OPP_INITIALIZER("mpu", true, 250000000, 1075000), 30 + /* MPU OPP3 */ 31 + OPP_INITIALIZER("mpu", true, 500000000, 1200000), 32 + /* MPU OPP4 */ 33 + OPP_INITIALIZER("mpu", true, 550000000, 1270000), 34 + /* MPU OPP5 */ 35 + OPP_INITIALIZER("mpu", true, 600000000, 1350000), 36 + 37 + /* 38 + * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is 39 + * almost the same than the one at 83MHz thus providing very little 40 + * gain for the power point of view. In term of energy it will even 41 + * increase the consumption due to the very negative performance 42 + * impact that frequency will do to the MPU and the whole system in 43 + * general. 44 + */ 45 + OPP_INITIALIZER("l3_main", false, 41500000, 975000), 46 + /* L3 OPP2 */ 47 + OPP_INITIALIZER("l3_main", true, 83000000, 1050000), 48 + /* L3 OPP3 */ 49 + OPP_INITIALIZER("l3_main", true, 166000000, 1150000), 50 + 51 + /* DSP OPP1 */ 52 + OPP_INITIALIZER("iva", true, 90000000, 975000), 53 + /* DSP OPP2 */ 54 + OPP_INITIALIZER("iva", true, 180000000, 1075000), 55 + /* DSP OPP3 */ 56 + OPP_INITIALIZER("iva", true, 360000000, 1200000), 57 + /* DSP OPP4 */ 58 + OPP_INITIALIZER("iva", true, 400000000, 1270000), 59 + /* DSP OPP5 */ 60 + OPP_INITIALIZER("iva", true, 430000000, 1350000), 61 + }; 62 + 63 + static struct omap_opp_def __initdata omap36xx_opp_def_list[] = { 64 + /* MPU OPP1 - OPP50 */ 65 + OPP_INITIALIZER("mpu", true, 300000000, 1012500), 66 + /* MPU OPP2 - OPP100 */ 67 + OPP_INITIALIZER("mpu", true, 600000000, 1200000), 68 + /* MPU OPP3 - OPP-Turbo */ 69 + OPP_INITIALIZER("mpu", false, 800000000, 1325000), 70 + /* MPU OPP4 - OPP-SB */ 71 + OPP_INITIALIZER("mpu", false, 1000000000, 1375000), 72 + 73 + /* L3 OPP1 - OPP50 */ 74 + OPP_INITIALIZER("l3_main", true, 100000000, 1000000), 75 + /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ 76 + OPP_INITIALIZER("l3_main", true, 200000000, 1200000), 77 + 78 + /* DSP OPP1 - OPP50 */ 79 + OPP_INITIALIZER("iva", true, 260000000, 1012500), 80 + /* DSP OPP2 - OPP100 */ 81 + OPP_INITIALIZER("iva", true, 520000000, 1200000), 82 + /* DSP OPP3 - OPP-Turbo */ 83 + OPP_INITIALIZER("iva", false, 660000000, 1325000), 84 + /* DSP OPP4 - OPP-SB */ 85 + OPP_INITIALIZER("iva", false, 800000000, 1375000), 86 + }; 87 + 88 + /** 89 + * omap3_opp_init() - initialize omap3 opp table 90 + */ 91 + static int __init omap3_opp_init(void) 92 + { 93 + int r = -ENODEV; 94 + 95 + if (!cpu_is_omap34xx()) 96 + return r; 97 + 98 + if (cpu_is_omap3630()) 99 + r = omap_init_opp_table(omap36xx_opp_def_list, 100 + ARRAY_SIZE(omap36xx_opp_def_list)); 101 + else 102 + r = omap_init_opp_table(omap34xx_opp_def_list, 103 + ARRAY_SIZE(omap34xx_opp_def_list)); 104 + 105 + return r; 106 + } 107 + device_initcall(omap3_opp_init);
+9
arch/arm/mach-omap2/pm.h
··· 20 20 extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); 21 21 extern int omap3_idle_init(void); 22 22 23 + #if defined(CONFIG_PM_OPP) 24 + extern int omap3_opp_init(void); 25 + #else 26 + static inline int omap3_opp_init(void) 27 + { 28 + return -EINVAL; 29 + } 30 + #endif 31 + 23 32 struct cpuidle_params { 24 33 u8 valid; 25 34 u32 sleep_latency;