diff options
-rw-r--r-- | Documentation/arm/OMAP/omap_pm | 25 | ||||
-rw-r--r-- | arch/arm/mach-omap2/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_opp_data.h | 72 | ||||
-rw-r--r-- | arch/arm/mach-omap2/opp.c | 93 | ||||
-rw-r--r-- | arch/arm/mach-omap2/opp3xxx_data.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.h | 9 |
7 files changed, 314 insertions, 0 deletions
diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm index 5389440aade3..9012bb039094 100644 --- a/Documentation/arm/OMAP/omap_pm +++ b/Documentation/arm/OMAP/omap_pm | |||
@@ -127,3 +127,28 @@ implementation needs: | |||
127 | 10. (*pdata->cpu_set_freq)(unsigned long f) | 127 | 10. (*pdata->cpu_set_freq)(unsigned long f) |
128 | 128 | ||
129 | 11. (*pdata->cpu_get_freq)(void) | 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. | ||
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 92b004ba5a10..e752cb397ba7 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -35,6 +35,8 @@ config ARCH_OMAP3 | |||
35 | select CPU_V7 | 35 | select CPU_V7 |
36 | select USB_ARCH_HAS_EHCI | 36 | select USB_ARCH_HAS_EHCI |
37 | select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4 | 37 | select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4 |
38 | select ARCH_HAS_OPP | ||
39 | select PM_OPP if PM | ||
38 | 40 | ||
39 | config ARCH_OMAP4 | 41 | config ARCH_OMAP4 |
40 | bool "TI OMAP4" | 42 | bool "TI OMAP4" |
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b86b06292388..fa16806092e5 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -49,6 +49,12 @@ obj-$(CONFIG_ARCH_OMAP4) += mux44xx.o | |||
49 | obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o | 49 | obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o |
50 | # obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o | 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 | # Power Management | 58 | # Power Management |
53 | ifeq ($(CONFIG_PM),y) | 59 | ifeq ($(CONFIG_PM),y) |
54 | obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o | 60 | obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o |
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h new file mode 100644 index 000000000000..46ac27dd6c84 --- /dev/null +++ b/arch/arm/mach-omap2/omap_opp_data.h | |||
@@ -0,0 +1,72 @@ | |||
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 */ | ||
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c new file mode 100644 index 000000000000..ab8b35b780b5 --- /dev/null +++ b/arch/arm/mach-omap2/opp.c | |||
@@ -0,0 +1,93 @@ | |||
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 | } | ||
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c new file mode 100644 index 000000000000..0486fce8a92c --- /dev/null +++ b/arch/arm/mach-omap2/opp3xxx_data.c | |||
@@ -0,0 +1,107 @@ | |||
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); | ||
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 0d75bfd1fdbe..2031f157a6ee 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h | |||
@@ -20,6 +20,15 @@ extern int omap3_can_sleep(void); | |||
20 | extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); | 20 | extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); |
21 | extern int omap3_idle_init(void); | 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 | struct cpuidle_params { | 32 | struct cpuidle_params { |
24 | u8 valid; | 33 | u8 valid; |
25 | u32 sleep_latency; | 34 | u32 sleep_latency; |