[glsdk/meta-ti-glsdk.git] / recipes-bsp / linux / linux-omap / dvfs / 0011-OMAP-Introduce-dependent-voltage-domain-support.patch
1 From b1b41c78d5a19260605fcb259a51ca7cd71c097a Mon Sep 17 00:00:00 2001
2 From: Thara Gopinath <thara@ti.com>
3 Date: Fri, 2 Jul 2010 13:06:57 +0530
4 Subject: [PATCH 11/20] OMAP: Introduce dependent voltage domain support.
6 There could be dependencies between various voltage domains for
7 maintaining system performance or hardware limitation reasons
8 like VDD<X> should be at voltage v1 when VDD<Y> is at voltage v2.
9 This patch introduce dependent vdd information structures in the
10 voltage layer which can be used to populate these dependencies
11 for a voltage domain. This patch also adds support to scale
12 the dependent vdd and the scalable devices belonging to it
13 during the scaling of a main vdd through omap_voltage_scale.
15 Signed-off-by: Thara Gopinath <thara@ti.com>
16 ---
17 arch/arm/mach-omap2/voltage.c | 122 +++++++++++++++++++++++++++++++++++++++++
18 1 files changed, 122 insertions(+), 0 deletions(-)
20 diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
21 index 9adf9d1..c83d968 100644
22 --- a/arch/arm/mach-omap2/voltage.c
23 +++ b/arch/arm/mach-omap2/voltage.c
24 @@ -123,6 +123,36 @@ struct vc_reg_info {
25 };
27 /**
28 + * omap_vdd_dep_volt - Table containing the parent vdd voltage and the
29 + * dependent vdd voltage corresponding to it.
30 + *
31 + * @main_vdd_volt : The main vdd voltage
32 + * @dep_vdd_volt : The voltage at which the dependent vdd should be
33 + * when the main vdd is at <main_vdd_volt> voltage
34 + */
35 +struct omap_vdd_dep_volt {
36 + u32 main_vdd_volt;
37 + u32 dep_vdd_volt;
38 +};
39 +
40 +/**
41 + * omap_vdd_dep_info - Dependent vdd info
42 + *
43 + * @name : Dependent vdd name
44 + * @voltdm : Dependent vdd pointer
45 + * @dep_table : Table containing the dependent vdd voltage
46 + * corresponding to every main vdd voltage.
47 + * @cur_dep_volt : The voltage to which dependent vdd should be put
48 + * to for the current main vdd voltage.
49 + */
50 +struct omap_vdd_dep_info {
51 + char *name;
52 + struct voltagedomain *voltdm;
53 + struct omap_vdd_dep_volt *dep_table;
54 + unsigned long cur_dep_volt;
55 +};
56 +
57 +/**
58 * struct omap_vdd_user_list - The per vdd user list
59 *
60 * @dev: The device asking for the vdd to be set at a particular
61 @@ -174,11 +204,13 @@ struct omap_vdd_info {
62 struct vp_reg_val vp_reg;
63 struct vc_reg_info vc_reg;
64 struct voltagedomain voltdm;
65 + struct omap_vdd_dep_info *dep_vdd_info;
66 struct dentry *debug_dir;
67 spinlock_t user_lock;
68 struct plist_head user_list;
69 struct mutex scaling_mutex;
70 struct list_head dev_list;
71 + int nr_dep_vdd;
72 u32 curr_volt;
73 u16 ocp_mod;
74 u8 prm_irqst_reg;
75 @@ -1160,6 +1192,80 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
76 return 0;
77 }
79 +static int calc_dep_vdd_volt(struct device *dev,
80 + struct omap_vdd_info *main_vdd, unsigned long main_volt)
81 +{
82 + struct omap_vdd_dep_info *dep_vdds;
83 + int i, ret = 0;
84 +
85 + if (!main_vdd->dep_vdd_info) {
86 + pr_debug("%s: No dependent VDD's for vdd_%s\n",
87 + __func__, main_vdd->voltdm.name);
88 + return 0;
89 + }
90 +
91 + dep_vdds = main_vdd->dep_vdd_info;
92 +
93 + for (i = 0; i < main_vdd->nr_dep_vdd; i++) {
94 + struct omap_vdd_dep_volt *volt_table = dep_vdds[i].dep_table;
95 + int nr_volt = 0;
96 + unsigned long dep_volt = 0, act_volt = 0;
97 +
98 + while (volt_table[nr_volt].main_vdd_volt != 0) {
99 + if (volt_table[nr_volt].main_vdd_volt == main_volt) {
100 + dep_volt = volt_table[nr_volt].dep_vdd_volt;
101 + break;
102 + }
103 + nr_volt++;
104 + }
105 + if (!dep_volt) {
106 + pr_warning("%s: Not able to find a matching volt for"
107 + "vdd_%s corresponding to vdd_%s %ld volt\n",
108 + __func__, dep_vdds[i].name,
109 + main_vdd->voltdm.name, main_volt);
110 + ret = -EINVAL;
111 + continue;
112 + }
113 +
114 + if (!dep_vdds[i].voltdm)
115 + dep_vdds[i].voltdm =
116 + omap_voltage_domain_lookup(dep_vdds[i].name);
117 +
118 + act_volt = dep_volt;
119 +
120 + /* See if dep_volt is possible for the vdd*/
121 + ret = omap_voltage_add_request(dep_vdds[i].voltdm, dev,
122 + &act_volt);
123 +
124 + /*
125 + * Currently we do not bother if the dep volt and act volt are
126 + * different. We could add a check if needed.
127 + */
128 + dep_vdds[i].cur_dep_volt = act_volt;
129 + }
130 +
131 + return ret;
132 +}
133 +
134 +static int scale_dep_vdd(struct omap_vdd_info *main_vdd)
135 +{
136 + struct omap_vdd_dep_info *dep_vdds;
137 + int i;
138 +
139 + if (!main_vdd->dep_vdd_info) {
140 + pr_debug("%s: No dependent VDD's for vdd_%s\n",
141 + __func__, main_vdd->voltdm.name);
142 + return 0;
143 + }
144 +
145 + dep_vdds = main_vdd->dep_vdd_info;
146 +
147 + for (i = 0; i < main_vdd->nr_dep_vdd; i++)
148 + omap_voltage_scale(dep_vdds[i].voltdm,
149 + dep_vdds[i].cur_dep_volt);
150 + return 0;
151 +}
152 +
153 /* Public functions */
154 /**
155 * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
156 @@ -1675,6 +1781,8 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
157 int is_volt_scaled = 0;
158 struct omap_vdd_info *vdd;
159 struct omap_vdd_dev_list *temp_dev;
160 + struct plist_node *node;
161 + struct omap_vdd_user_list *user;
163 if (!voltdm || IS_ERR(voltdm)) {
164 pr_warning("%s: VDD specified does not exist!\n", __func__);
165 @@ -1687,6 +1795,17 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
167 curr_volt = omap_voltage_get_nom_volt(voltdm);
169 + /* Find the device requesting the voltage scaling */
170 + node = plist_first(&vdd->user_list);
171 + user = container_of(node, struct omap_vdd_user_list, node);
172 +
173 + /* calculate the voltages for dependent vdd's */
174 + if (calc_dep_vdd_volt(user->dev, vdd, volt)) {
175 + pr_warning("%s: Error in calculating dependent vdd voltages"
176 + "for vdd_%s\n", __func__, voltdm->name);
177 + return -EINVAL;
178 + }
179 +
180 if (curr_volt == volt) {
181 is_volt_scaled = 1;
182 } else if (curr_volt < volt) {
183 @@ -1721,6 +1840,9 @@ int omap_voltage_scale(struct voltagedomain *voltdm, unsigned long volt)
185 mutex_unlock(&vdd->scaling_mutex);
187 + /* Scale dependent vdds */
188 + scale_dep_vdd(vdd);
189 +
190 return 0;
191 }
193 --
194 1.6.6.1