diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch')
-rw-r--r-- | extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch b/extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch new file mode 100644 index 00000000..6c4ca2ab --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap/dvfs/0011-OMAP-Introduce-dependent-voltage-domain-support.patch | |||
@@ -0,0 +1,195 @@ | |||
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. | ||
5 | |||
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. | ||
14 | |||
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(-) | ||
19 | |||
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 | }; | ||
26 | |||
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 | } | ||
78 | |||
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; | ||
162 | |||
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) | ||
166 | |||
167 | curr_volt = omap_voltage_get_nom_volt(voltdm); | ||
168 | |||
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) | ||
184 | |||
185 | mutex_unlock(&vdd->scaling_mutex); | ||
186 | |||
187 | + /* Scale dependent vdds */ | ||
188 | + scale_dep_vdd(vdd); | ||
189 | + | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | -- | ||
194 | 1.6.6.1 | ||
195 | |||