Commit afa54fe7c23f729cc8c3e13b14715e53cd6464b4

Authored by Rajendra Nayak
Committed by Afzal Mohammed
1 parent 54d8f4c298
Exists in master

OMAP: OPP: Do a round_rate before adding into OPP table

Most clock rates can vary to some extent based on the exact
 M/N values used to lock a dpll.
 Do a round_rate before updating the rates into the OPP table
 so that the 'exact' rates appear and a subsequent clk_set_rate
 works without issues.

 Signed-off-by: Rajendra Nayak <rnayak@ti.com>
 Signed-off-by: Nishanth Menon <nm@ti.com>
[vaibhav.bedia@ti.com: Pull in for AM33xx]
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Afzal Mohammed <afzal@ti.com>

Showing 1 changed file with 19 additions and 0 deletions Inline Diff

arch/arm/mach-omap2/opp.c
1 /* 1 /*
2 * OMAP SoC specific OPP wrapper function 2 * OMAP SoC specific OPP wrapper function
3 * 3 *
4 * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ 4 * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
5 * Nishanth Menon 5 * Nishanth Menon
6 * Kevin Hilman 6 * Kevin Hilman
7 * Copyright (C) 2010 Nokia Corporation. 7 * Copyright (C) 2010 Nokia Corporation.
8 * Eduardo Valentin 8 * Eduardo Valentin
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 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 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 * 13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
15 * kind, whether express or implied; without even the implied warranty 15 * kind, whether express or implied; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details. 17 * GNU General Public License for more details.
18 */ 18 */
19 #include <linux/module.h> 19 #include <linux/module.h>
20 #include <linux/opp.h> 20 #include <linux/opp.h>
21 #include <linux/clk.h>
21 22
22 #include <plat/omap_device.h> 23 #include <plat/omap_device.h>
23 #include <plat/dvfs.h> 24 #include <plat/dvfs.h>
25 #include <plat/clock.h>
24 26
25 #include "omap_opp_data.h" 27 #include "omap_opp_data.h"
26 28
27 /* Temp variable to allow multiple calls */ 29 /* Temp variable to allow multiple calls */
28 static u8 __initdata omap_table_init; 30 static u8 __initdata omap_table_init;
29 31
30 /** 32 /**
31 * omap_init_opp_table() - Initialize opp table as per the CPU type 33 * omap_init_opp_table() - Initialize opp table as per the CPU type
32 * @opp_def: opp default list for this silicon 34 * @opp_def: opp default list for this silicon
33 * @opp_def_size: number of opp entries for this silicon 35 * @opp_def_size: number of opp entries for this silicon
34 * 36 *
35 * Register the initial OPP table with the OPP library based on the CPU 37 * Register the initial OPP table with the OPP library based on the CPU
36 * type. This is meant to be used only by SoC specific registration. 38 * type. This is meant to be used only by SoC specific registration.
37 */ 39 */
38 int __init omap_init_opp_table(struct omap_opp_def *opp_def, 40 int __init omap_init_opp_table(struct omap_opp_def *opp_def,
39 u32 opp_def_size) 41 u32 opp_def_size)
40 { 42 {
41 int i, r; 43 int i, r;
44 struct clk *clk;
45 long round_rate;
42 46
43 if (!opp_def || !opp_def_size) { 47 if (!opp_def || !opp_def_size) {
44 pr_err("%s: invalid params!\n", __func__); 48 pr_err("%s: invalid params!\n", __func__);
45 return -EINVAL; 49 return -EINVAL;
46 } 50 }
47 51
48 /* 52 /*
49 * Initialize only if not already initialized even if the previous 53 * Initialize only if not already initialized even if the previous
50 * call failed, because, no reason we'd succeed again. 54 * call failed, because, no reason we'd succeed again.
51 */ 55 */
52 if (omap_table_init) 56 if (omap_table_init)
53 return -EEXIST; 57 return -EEXIST;
54 omap_table_init = 1; 58 omap_table_init = 1;
55 59
56 /* Lets now register with OPP library */ 60 /* Lets now register with OPP library */
57 for (i = 0; i < opp_def_size; i++) { 61 for (i = 0; i < opp_def_size; i++) {
58 struct omap_hwmod *oh; 62 struct omap_hwmod *oh;
59 struct device *dev; 63 struct device *dev;
60 64
61 if (!opp_def->hwmod_name) { 65 if (!opp_def->hwmod_name) {
62 WARN(1, "%s: NULL name of omap_hwmod, failing" 66 WARN(1, "%s: NULL name of omap_hwmod, failing"
63 " [%d].\n", __func__, i); 67 " [%d].\n", __func__, i);
64 goto next; 68 goto next;
65 } 69 }
66 oh = omap_hwmod_lookup(opp_def->hwmod_name); 70 oh = omap_hwmod_lookup(opp_def->hwmod_name);
67 if (!oh || !oh->od) { 71 if (!oh || !oh->od) {
68 WARN(1, "%s: no hwmod or odev for %s, [%d] " 72 WARN(1, "%s: no hwmod or odev for %s, [%d] "
69 "cannot add OPPs.\n", __func__, 73 "cannot add OPPs.\n", __func__,
70 opp_def->hwmod_name, i); 74 opp_def->hwmod_name, i);
71 goto next; 75 goto next;
72 } 76 }
73 dev = &oh->od->pdev->dev; 77 dev = &oh->od->pdev->dev;
74 78
79 clk = omap_clk_get_by_name(opp_def->clk_name);
80 if (clk) {
81 round_rate = clk_round_rate(clk, opp_def->freq);
82 if (round_rate > 0) {
83 opp_def->freq = round_rate;
84 } else {
85 WARN(1, "%s: round_rate for clock %s failed\n",
86 __func__, opp_def->clk_name);
87 goto next; /* skip Bad OPP */
88 }
89 } else {
90 WARN(1, "%s: No clock by name %s found\n", __func__,
91 opp_def->clk_name);
92 goto next; /* skip Bad OPP */
93 }
75 r = opp_add(dev, opp_def->freq, opp_def->u_volt); 94 r = opp_add(dev, opp_def->freq, opp_def->u_volt);
76 if (r) { 95 if (r) {
77 dev_err(dev, "%s: add OPP %ld failed for %s [%d] " 96 dev_err(dev, "%s: add OPP %ld failed for %s [%d] "
78 "result=%d\n", 97 "result=%d\n",
79 __func__, opp_def->freq, 98 __func__, opp_def->freq,
80 opp_def->hwmod_name, i, r); 99 opp_def->hwmod_name, i, r);
81 } else { 100 } else {
82 if (!opp_def->default_available) 101 if (!opp_def->default_available)
83 r = opp_disable(dev, opp_def->freq); 102 r = opp_disable(dev, opp_def->freq);
84 if (r) 103 if (r)
85 dev_err(dev, "%s: disable %ld failed for %s " 104 dev_err(dev, "%s: disable %ld failed for %s "
86 "[%d] result=%d\n", 105 "[%d] result=%d\n",
87 __func__, opp_def->freq, 106 __func__, opp_def->freq,
88 opp_def->hwmod_name, i, r); 107 opp_def->hwmod_name, i, r);
89 108
90 r = omap_dvfs_register_device(dev, 109 r = omap_dvfs_register_device(dev,
91 opp_def->voltdm_name, opp_def->clk_name); 110 opp_def->voltdm_name, opp_def->clk_name);
92 if (r) 111 if (r)
93 dev_err(dev, "%s:%s:err dvfs register %d %d\n", 112 dev_err(dev, "%s:%s:err dvfs register %d %d\n",
94 __func__, opp_def->hwmod_name, r, i); 113 __func__, opp_def->hwmod_name, r, i);
95 } 114 }
96 next: 115 next:
97 opp_def++; 116 opp_def++;
98 } 117 }
99 118
100 return 0; 119 return 0;
101 } 120 }
102 121