Commit 18d5c4d14392af877928f2adddd5fc7329b64af6
1 parent
6d0dff1b43
Exists in
v3.2_SMARCT335xPSP_04.06.00.11
and in
2 other branches
Add SmartReflex support early driver patches (0001-Smartreflex-support-for-ES-2.…
…x-and-suspend-resume.patch) while working to get the driver upstream.
Showing 3 changed files with 812 additions and 595 deletions Side-by-side Diff
arch/arm/mach-omap2/am33xx-smartreflex-class2.c
Changes suppressed. Click to show
... | ... | @@ -28,6 +28,7 @@ |
28 | 28 | #include <linux/regulator/consumer.h> |
29 | 29 | #include <linux/cpufreq.h> |
30 | 30 | #include <linux/opp.h> |
31 | +#include <linux/pm.h> | |
31 | 32 | |
32 | 33 | #include <plat/common.h> |
33 | 34 | #include <plat/smartreflex.h> |
... | ... | @@ -37,6 +38,9 @@ |
37 | 38 | |
38 | 39 | #define CLK_NAME_LEN 40 |
39 | 40 | |
41 | +/* Global reference used for suspend/resume only */ | |
42 | +static struct am33xx_sr *global_sr_info; | |
43 | + | |
40 | 44 | static inline void sr_write_reg(struct am33xx_sr *sr, int offset, u32 value, |
41 | 45 | u32 srid) |
42 | 46 | { |
43 | 47 | |
44 | 48 | |
45 | 49 | |
46 | 50 | |
47 | 51 | |
48 | 52 | |
49 | 53 | |
50 | 54 | |
51 | 55 | |
52 | 56 | |
53 | 57 | |
54 | 58 | |
55 | 59 | |
... | ... | @@ -60,63 +64,68 @@ |
60 | 64 | return readl(sr->sen[srid].base + offset); |
61 | 65 | } |
62 | 66 | |
63 | -static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen) { | |
64 | - u32 gn, rn, mul; | |
67 | +static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen) | |
68 | +{ | |
69 | + u32 gn, rn, mul; | |
65 | 70 | |
66 | - for (gn = 0; gn < GAIN_MAXLIMIT; gn++) { | |
67 | - mul = 1 << (gn + 8); | |
68 | - rn = mul / sensor; | |
69 | - if (rn < R_MAXLIMIT) { | |
70 | - *sengain = gn; | |
71 | - *rnsen = rn; | |
72 | - } | |
73 | - } | |
71 | + for (gn = 0; gn < GAIN_MAXLIMIT; gn++) { | |
72 | + mul = 1 << (gn + 8); | |
73 | + rn = mul / sensor; | |
74 | + if (rn < R_MAXLIMIT) { | |
75 | + *sengain = gn; | |
76 | + *rnsen = rn; | |
77 | + } | |
78 | + } | |
74 | 79 | } |
75 | 80 | |
76 | -static u32 cal_test_nvalue(u32 sennval, u32 senpval) { | |
77 | - u32 senpgain=0, senngain=0; | |
78 | - u32 rnsenp=0, rnsenn=0; | |
81 | +static u32 cal_test_nvalue(u32 sennval, u32 senpval) | |
82 | +{ | |
83 | + u32 senpgain = 0, senngain = 0; | |
84 | + u32 rnsenp = 0, rnsenn = 0; | |
79 | 85 | |
80 | - /* Calculating the gain and reciprocal of the SenN and SenP values */ | |
81 | - cal_reciprocal(senpval, &senpgain, &rnsenp); | |
82 | - cal_reciprocal(sennval, &senngain, &rnsenn); | |
86 | + /* Calculating the gain and reciprocal of the SenN and SenP values */ | |
87 | + cal_reciprocal(senpval, &senpgain, &rnsenp); | |
88 | + cal_reciprocal(sennval, &senngain, &rnsenn); | |
83 | 89 | |
84 | - return (senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) | | |
85 | - (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) | | |
86 | - (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) | | |
87 | - (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT); | |
90 | + return (senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) | | |
91 | + (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) | | |
92 | + (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) | | |
93 | + (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT); | |
88 | 94 | } |
89 | 95 | |
96 | +/* margin is defined similar to the SenVal register. | |
97 | + SenP margin is 31:16 bits | |
98 | + SenN margin is 15:00 bits | |
99 | +*/ | |
90 | 100 | static unsigned int sr_adjust_efuse_nvalue(unsigned int opp_no, |
91 | - unsigned int orig_opp_nvalue, | |
92 | - unsigned int mv_delta) { | |
93 | - unsigned int new_opp_nvalue; | |
94 | - unsigned int senp_gain, senn_gain, rnsenp, rnsenn, pnt_delta, nnt_delta; | |
95 | - unsigned int new_senn, new_senp, senn, senp; | |
101 | + unsigned int orig_opp_nvalue, | |
102 | + unsigned int margin) { | |
103 | + unsigned int new_opp_nvalue, senp_gain, senn_gain, rnsenp, rnsenn; | |
104 | + unsigned int pnt_delta, nnt_delta, new_senn, new_senp, senn, senp; | |
96 | 105 | |
97 | - /* calculate SenN and SenP from the efuse value */ | |
98 | - senp_gain = ((orig_opp_nvalue >> 20) & 0xf); | |
99 | - senn_gain = ((orig_opp_nvalue >> 16) & 0xf); | |
100 | - rnsenp = ((orig_opp_nvalue >> 8) & 0xff); | |
101 | - rnsenn = (orig_opp_nvalue & 0xff); | |
106 | + /* calculate SenN and SenP from the efuse value */ | |
107 | + senp_gain = ((orig_opp_nvalue >> 20) & 0xf); | |
108 | + senn_gain = ((orig_opp_nvalue >> 16) & 0xf); | |
109 | + rnsenp = ((orig_opp_nvalue >> 8) & 0xff); | |
110 | + rnsenn = (orig_opp_nvalue & 0xff); | |
102 | 111 | |
103 | - senp = ((1<<(senp_gain+8))/(rnsenp)); | |
104 | - senn = ((1<<(senn_gain+8))/(rnsenn)); | |
112 | + senp = ((1<<(senp_gain+8))/(rnsenp)); | |
113 | + senn = ((1<<(senn_gain+8))/(rnsenn)); | |
105 | 114 | |
106 | - /* calculate the voltage delta */ | |
107 | - pnt_delta = (26 * mv_delta)/10; | |
108 | - nnt_delta = (3 * mv_delta); | |
115 | + /* calculate the voltage delta */ | |
116 | + pnt_delta = (margin >> 16) & 0xffff; | |
117 | + nnt_delta = margin & 0xffff; | |
109 | 118 | |
110 | - /* now lets add the voltage delta to the sensor values */ | |
111 | - new_senn = senn + nnt_delta; | |
112 | - new_senp = senp + pnt_delta; | |
119 | + /* now lets add the voltage delta to the sensor values */ | |
120 | + new_senn = senn + nnt_delta; | |
121 | + new_senp = senp + pnt_delta; | |
113 | 122 | |
114 | - new_opp_nvalue = cal_test_nvalue(new_senn, new_senp); | |
123 | + new_opp_nvalue = cal_test_nvalue(new_senn, new_senp); | |
115 | 124 | |
116 | - printk("Compensating OPP%d for %dmV Orig nvalue:0x%x New nvalue:0x%x \n", | |
117 | - opp_no, mv_delta, orig_opp_nvalue, new_opp_nvalue); | |
125 | + printk(KERN_DEBUG "Compensating OPP%d: Orig nvalue:0x%x New nvalue:0x%x\n", | |
126 | + opp_no, orig_opp_nvalue, new_opp_nvalue); | |
118 | 127 | |
119 | - return new_opp_nvalue; | |
128 | + return new_opp_nvalue; | |
120 | 129 | } |
121 | 130 | |
122 | 131 | /* irq_sr_reenable - Re-enable SR interrupts (triggered by delayed work queue) |
123 | 132 | |
124 | 133 | |
125 | 134 | |
126 | 135 | |
127 | 136 | |
128 | 137 | |
129 | 138 | |
130 | 139 | |
131 | 140 | |
132 | 141 | |
133 | 142 | |
134 | 143 | |
135 | 144 | |
136 | 145 | |
137 | 146 | |
138 | 147 | |
139 | 148 | |
... | ... | @@ -128,56 +137,105 @@ |
128 | 137 | */ |
129 | 138 | static void irq_sr_reenable(struct work_struct *work) |
130 | 139 | { |
131 | - u32 srid; | |
140 | + u32 srid; | |
132 | 141 | struct am33xx_sr_sensor *sens; |
133 | - struct am33xx_sr *sr; | |
142 | + struct am33xx_sr *sr; | |
134 | 143 | |
135 | - sens = container_of((void *)work, struct am33xx_sr_sensor, | |
136 | - work_reenable); | |
144 | + sens = container_of((void *)work, struct am33xx_sr_sensor, | |
145 | + work_reenable); | |
137 | 146 | |
138 | - srid = sens->sr_id; | |
147 | + srid = sens->sr_id; | |
139 | 148 | |
140 | - sr = container_of((void *)sens, struct am33xx_sr, sen[srid]); | |
149 | + sr = container_of((void *)sens, struct am33xx_sr, sen[srid]); | |
141 | 150 | |
142 | - dev_dbg(&sr->pdev->dev, "%s: SR %d\n", __func__, srid); | |
151 | + dev_dbg(&sr->pdev->dev, "%s: SR %d\n", __func__, srid); | |
143 | 152 | |
144 | - /* Must clear IRQ status */ | |
145 | - sens->irq_status = 0; | |
153 | + /* Must clear IRQ status */ | |
154 | + sens->irq_status = 0; | |
146 | 155 | |
147 | - /* Re-enable the interrupt */ | |
156 | + /* moved from initial irq handler to solve problem of extra | |
157 | + interrupts (Clear bounds interrupt) */ | |
158 | + sr_modify_reg(sr, IRQSTATUS, IRQSTATUS_MCBOUNDSINT, | |
159 | + IRQSTATUS_MCBOUNDSINT, srid); | |
160 | + | |
161 | + /* Re-enable the interrupt */ | |
148 | 162 | sr_modify_reg(sr, IRQENABLE_SET, IRQENABLE_MCUBOUNDSINT, |
149 | 163 | IRQENABLE_MCUBOUNDSINT, srid); |
150 | - | |
151 | - /* Restart the module after voltage set */ | |
152 | - sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, | |
153 | - SRCONFIG_SRENABLE, srid); | |
154 | 164 | } |
155 | 165 | |
156 | 166 | /* get_errvolt - get error voltage from SR error register |
157 | 167 | * @sr: contains SR driver data |
158 | 168 | * @srid: contains the srid, indicates which SR moduel lswe are using |
169 | + * @curr_volt: current voltage for domain (in microvolts) | |
170 | + * @reset: set to 1 to reset the internal state machine | |
159 | 171 | * |
160 | - * Read the error from SENSOR error register and then convert | |
172 | + * Reads the error from SENSOR error register and then convert | |
161 | 173 | * to voltage delta, return value is the voltage delta in micro |
162 | 174 | * volt. |
163 | 175 | */ |
164 | -static int get_errvolt(struct am33xx_sr *sr, s32 srid) | |
176 | +static int get_errvolt(struct am33xx_sr *sr, int srid, int curr_volt, | |
177 | + int reset) | |
165 | 178 | { |
166 | - struct am33xx_sr_sensor *sens; | |
167 | - int senerror_reg; | |
168 | - s32 uvoltage; | |
169 | - s8 terror; | |
179 | + struct am33xx_sr_sensor *sens; | |
180 | + int senerror_reg, gain; | |
181 | + s32 uvoltage = 0; | |
182 | + s8 avg_error; | |
170 | 183 | |
171 | - sens = &sr->sen[srid]; | |
184 | + sens = &sr->sen[srid]; | |
172 | 185 | |
186 | + /* used when OPP changes to reset the state machine */ | |
187 | + if (reset > 0) { | |
188 | + sens->state = 0; | |
189 | + return 0; | |
190 | + } | |
191 | + | |
192 | + /* Read the AvgError */ | |
173 | 193 | senerror_reg = sr_read_reg(sr, SENERROR_V2, srid); |
174 | 194 | senerror_reg = (senerror_reg & 0x0000FF00); |
175 | - terror = (s8)(senerror_reg >> 8); | |
195 | + avg_error = (s8)(senerror_reg >> 8); | |
176 | 196 | |
177 | - /* math defined in SR functional spec */ | |
178 | - uvoltage = ((terror) * sr->uvoltage_step_size) >> 7; | |
179 | - uvoltage = uvoltage * sens->opp_data[sens->curr_opp].e2v_gain; | |
197 | + switch (sens->state) { | |
198 | + case 0: /* save the current voltage and AvgError for state 1 */ | |
199 | + sens->saved_volt = curr_volt; | |
200 | + sens->avg_error_nom = avg_error; | |
180 | 201 | |
202 | + /* calculate -5% voltage (spec vmin) */ | |
203 | + uvoltage = -(curr_volt * 5) / 100; | |
204 | + | |
205 | + sens->state = 1; | |
206 | + break; | |
207 | + case 1: /* guard against divide by zero (should not happen) */ | |
208 | + if (sens->avg_error_nom == avg_error) { | |
209 | + dev_err(&sr->pdev->dev, | |
210 | + "%s: SR %d: Same AvgError for 2 different voltages\n", | |
211 | + __func__, srid); | |
212 | + sens->state = 0; | |
213 | + break; | |
214 | + } | |
215 | + | |
216 | + /* calculate what the gain should be based on slope */ | |
217 | + gain = abs(sens->saved_volt - curr_volt) / | |
218 | + abs(sens->avg_error_nom - avg_error); | |
219 | + uvoltage = gain * avg_error; | |
220 | + | |
221 | + dev_dbg(&sr->pdev->dev, | |
222 | + "SR %d: State 1 calculated %duV gain, vmin = %d\n", | |
223 | + srid, gain, curr_volt + uvoltage); | |
224 | + | |
225 | + /* store computed gain for state 2 */ | |
226 | + sens->opp_data[sens->curr_opp].e2v_gain = (gain / 100); | |
227 | + sens->state = 2; | |
228 | + break; | |
229 | + case 2: /* remain in this state to converge to final voltage */ | |
230 | + uvoltage = (avg_error * sr->uvoltage_step_size) >> 7; | |
231 | + uvoltage = uvoltage * sens->opp_data[sens->curr_opp].e2v_gain; | |
232 | + break; | |
233 | + default: | |
234 | + dev_err(&sr->pdev->dev, | |
235 | + "%s: SR %d: Invalid state for get_errvolt\n", | |
236 | + __func__, srid); | |
237 | + } | |
238 | + | |
181 | 239 | return uvoltage; |
182 | 240 | } |
183 | 241 | |
184 | 242 | |
185 | 243 | |
186 | 244 | |
187 | 245 | |
188 | 246 | |
189 | 247 | |
190 | 248 | |
191 | 249 | |
192 | 250 | |
... | ... | @@ -204,48 +262,46 @@ |
204 | 262 | |
205 | 263 | sr = container_of((void *)work, struct am33xx_sr, work); |
206 | 264 | |
207 | - for (i = 0; i < sr->no_of_sens; i++) { | |
208 | - if (sr->sen[i].irq_status != 1) | |
209 | - continue; | |
265 | + for (i = 0; i < sr->no_of_sens; i++) { | |
266 | + if (sr->sen[i].irq_status != 1) | |
267 | + continue; | |
210 | 268 | |
211 | - /* Get the current voltage from PMIC */ | |
212 | - prev_volt = regulator_get_voltage(sr->sen[i].reg); | |
269 | + /* Get the current voltage from PMIC */ | |
270 | + prev_volt = regulator_get_voltage(sr->sen[i].reg); | |
213 | 271 | |
214 | - if (prev_volt < 0) { | |
215 | - dev_err(&sr->pdev->dev, | |
216 | - "%s: SR %d: regulator_get_voltage error %d\n", | |
217 | - __func__, i, prev_volt); | |
272 | + if (prev_volt < 0) { | |
273 | + dev_err(&sr->pdev->dev, | |
274 | + "%s: SR %d: regulator_get_voltage error %d\n", | |
275 | + __func__, i, prev_volt); | |
218 | 276 | |
219 | - goto reenable; | |
220 | - } | |
277 | + goto reenable; | |
278 | + } | |
221 | 279 | |
222 | - delta_v = get_errvolt(sr, i); | |
223 | - new_volt = prev_volt + delta_v; | |
280 | + delta_v = get_errvolt(sr, i, prev_volt, 0); | |
281 | + new_volt = prev_volt + delta_v; | |
224 | 282 | |
225 | - /* this is the primary output for debugging SR activity */ | |
226 | - dev_dbg(&sr->pdev->dev, | |
227 | - "%s: SR %d: prev volt=%d, delta_v=%d, req_volt=%d\n", | |
228 | - __func__, i, prev_volt, delta_v, new_volt); | |
283 | + if (delta_v != 0) { | |
284 | + ret = regulator_set_voltage(sr->sen[i].reg, new_volt, | |
285 | + new_volt + sr->uvoltage_step_size); | |
229 | 286 | |
230 | - /* Clear the counter, SR module disable */ | |
231 | - sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, | |
232 | - ~SRCONFIG_SRENABLE, i); | |
287 | + if (ret < 0) | |
288 | + dev_err(&sr->pdev->dev, | |
289 | + "%s: regulator_set_voltage failed! (err %d)\n", | |
290 | + __func__, ret); | |
291 | + } | |
233 | 292 | |
234 | - if (delta_v != 0) { | |
235 | - ret = regulator_set_voltage(sr->sen[i].reg, new_volt, | |
236 | - new_volt + sr->uvoltage_step_size); | |
293 | + /* this is the primary output for debugging SR activity */ | |
294 | + printk(KERN_DEBUG "SR %d: curr=%d, delta_v=%d, calc=%d, act=%d, gain=%02x\n", | |
295 | + i, prev_volt, delta_v, new_volt, | |
296 | + regulator_get_voltage(sr->sen[i].reg), | |
297 | + sr->sen[i].opp_data[sr->sen[i].curr_opp].e2v_gain); | |
237 | 298 | |
238 | - if (ret < 0) | |
239 | - dev_err(&sr->pdev->dev, | |
240 | - "%s: regulator_set_voltage failed! (err %d)\n", | |
241 | - __func__, ret); | |
242 | - } | |
243 | 299 | reenable: |
244 | - /* allow time for voltage to settle before re-enabling SR | |
245 | - module and interrupt */ | |
246 | - schedule_delayed_work(&sr->sen[i].work_reenable, | |
247 | - msecs_to_jiffies(sr->irq_delay)); | |
248 | - } | |
300 | + /* allow time for voltage to settle before re-enabling SR | |
301 | + module and interrupt */ | |
302 | + schedule_delayed_work(&sr->sen[i].work_reenable, | |
303 | + msecs_to_jiffies(sr->irq_delay)); | |
304 | + } | |
249 | 305 | } |
250 | 306 | |
251 | 307 | /* sr_class2_irq - sr irq handling |
252 | 308 | |
253 | 309 | |
254 | 310 | |
255 | 311 | |
... | ... | @@ -267,32 +323,28 @@ |
267 | 323 | static irqreturn_t sr_class2_irq(int irq, void *data) |
268 | 324 | { |
269 | 325 | u32 srid; |
270 | - struct am33xx_sr *sr; | |
271 | - struct am33xx_sr_sensor *sr_sensor = (struct am33xx_sr_sensor *)data; | |
326 | + struct am33xx_sr *sr; | |
327 | + struct am33xx_sr_sensor *sr_sensor = (struct am33xx_sr_sensor *)data; | |
272 | 328 | |
273 | - srid = sr_sensor->sr_id; | |
329 | + srid = sr_sensor->sr_id; | |
274 | 330 | |
275 | - sr = container_of(data, struct am33xx_sr, sen[srid]); | |
331 | + sr = container_of(data, struct am33xx_sr, sen[srid]); | |
276 | 332 | |
277 | 333 | sr->sen[srid].irq_status = 1; |
278 | 334 | |
279 | - /* Clear MCUBounds Interrupt */ | |
280 | - sr_modify_reg(sr, IRQSTATUS, IRQSTATUS_MCBOUNDSINT, | |
281 | - IRQSTATUS_MCBOUNDSINT, srid); | |
282 | - | |
283 | 335 | /* Disable the interrupt and re-enable in set_voltage() */ |
284 | 336 | sr_modify_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUBOUNDSINT, |
285 | 337 | IRQENABLE_MCUBOUNDSINT, srid); |
286 | 338 | |
287 | - /* Causes set_voltage() to get called at a later time. Set_voltage() | |
288 | - will check the irq_status flags to determine which SR needs to | |
289 | - be serviced. This was previously done with schedule_work, but | |
290 | - I observed a crash in set_voltage() when changing OPPs on weak | |
291 | - silicon, which may have been related to insufficient voltage | |
292 | - settling time for OPP change. This additional delay avoids the | |
293 | - crash. */ | |
294 | - schedule_delayed_work(&sr->work, | |
295 | - msecs_to_jiffies(250)); | |
339 | + /* Causes set_voltage() to get called at a later time. Set_voltage() | |
340 | + will check the irq_status flags to determine which SR needs to | |
341 | + be serviced. This was previously done with schedule_work, but | |
342 | + I observed a crash in set_voltage() when changing OPPs on weak | |
343 | + silicon, which may have been related to insufficient voltage | |
344 | + settling time for OPP change. This additional delay avoids the | |
345 | + crash. */ | |
346 | + schedule_delayed_work(&sr->work, | |
347 | + msecs_to_jiffies(250)); | |
296 | 348 | |
297 | 349 | return IRQ_HANDLED; |
298 | 350 | } |
299 | 351 | |
300 | 352 | |
301 | 353 | |
302 | 354 | |
303 | 355 | |
... | ... | @@ -317,31 +369,31 @@ |
317 | 369 | |
318 | 370 | static inline int sr_set_nvalues(struct am33xx_sr *sr, u32 srid) |
319 | 371 | { |
320 | - int i; | |
321 | - struct am33xx_sr_sensor *sens = &sr->sen[srid]; | |
372 | + int i; | |
373 | + struct am33xx_sr_sensor *sens = &sr->sen[srid]; | |
322 | 374 | |
323 | - for (i = 0; i < sens->no_of_opps; i++) { | |
324 | - /* Read nTarget value form EFUSE register*/ | |
325 | - sens->opp_data[i].nvalue = readl(AM33XX_CTRL_REGADDR | |
375 | + for (i = 0; i < sens->no_of_opps; i++) { | |
376 | + /* Read nTarget value form EFUSE register*/ | |
377 | + sens->opp_data[i].nvalue = readl(AM33XX_CTRL_REGADDR | |
326 | 378 | (sens->opp_data[i].efuse_offs)) & 0xFFFFFF; |
327 | 379 | |
328 | - /* validate nTarget value */ | |
329 | - if (sens->opp_data[i].nvalue == 0) | |
330 | - return -EINVAL; | |
380 | + /* validate nTarget value */ | |
381 | + if (sens->opp_data[i].nvalue == 0) | |
382 | + return -EINVAL; | |
331 | 383 | |
332 | - /* adjust nTarget based on margin in mv */ | |
333 | - sens->opp_data[i].adj_nvalue = sr_adjust_efuse_nvalue(i, | |
334 | - sens->opp_data[i].nvalue, | |
335 | - sens->opp_data[i].margin); | |
384 | + /* adjust nTarget based on margin in mv */ | |
385 | + sens->opp_data[i].adj_nvalue = sr_adjust_efuse_nvalue(i, | |
386 | + sens->opp_data[i].nvalue, | |
387 | + sens->opp_data[i].margin); | |
336 | 388 | |
337 | - dev_dbg(&sr->pdev->dev, | |
338 | - "NValueReciprocal value (from efuse) = %08x\n", | |
339 | - sens->opp_data[i].nvalue); | |
389 | + dev_dbg(&sr->pdev->dev, | |
390 | + "NValueReciprocal value (from efuse) = %08x\n", | |
391 | + sens->opp_data[i].nvalue); | |
340 | 392 | |
341 | - dev_dbg(&sr->pdev->dev, | |
342 | - "Adjusted NValueReciprocal value = %08x\n", | |
343 | - sens->opp_data[i].adj_nvalue); | |
344 | - } | |
393 | + dev_dbg(&sr->pdev->dev, | |
394 | + "Adjusted NValueReciprocal value = %08x\n", | |
395 | + sens->opp_data[i].adj_nvalue); | |
396 | + } | |
345 | 397 | return 0; |
346 | 398 | } |
347 | 399 | |
... | ... | @@ -354,7 +406,7 @@ |
354 | 406 | */ |
355 | 407 | static void sr_configure(struct am33xx_sr *sr, u32 srid) |
356 | 408 | { |
357 | - struct am33xx_sr_sensor *sens = &sr->sen[srid]; | |
409 | + struct am33xx_sr_sensor *sens = &sr->sen[srid]; | |
358 | 410 | |
359 | 411 | /* Configuring the SR module with clock length, enabling the |
360 | 412 | * error generator, enable SR module, enable individual N and P |
361 | 413 | |
362 | 414 | |
... | ... | @@ -370,11 +422,11 @@ |
370 | 422 | sr_modify_reg(sr, ERRCONFIG_V2, (SR_ERRWEIGHT_MASK | |
371 | 423 | SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK), |
372 | 424 | ((sens->opp_data[sens->curr_opp].err_weight << |
373 | - ERRCONFIG_ERRWEIGHT_SHIFT) | | |
425 | + ERRCONFIG_ERRWEIGHT_SHIFT) | | |
374 | 426 | (sens->opp_data[sens->curr_opp].err_maxlimit << |
375 | - ERRCONFIG_ERRMAXLIMIT_SHIFT) | | |
427 | + ERRCONFIG_ERRMAXLIMIT_SHIFT) | | |
376 | 428 | (sens->opp_data[sens->curr_opp].err_minlimit << |
377 | - ERRCONFIG_ERRMINLIMIT_SHIFT)), | |
429 | + ERRCONFIG_ERRMINLIMIT_SHIFT)), | |
378 | 430 | srid); |
379 | 431 | } |
380 | 432 | |
381 | 433 | |
382 | 434 | |
383 | 435 | |
384 | 436 | |
... | ... | @@ -387,21 +439,26 @@ |
387 | 439 | */ |
388 | 440 | static void sr_enable(struct am33xx_sr *sr, u32 srid) |
389 | 441 | { |
390 | - struct am33xx_sr_sensor *sens; | |
442 | + struct am33xx_sr_sensor *sens; | |
391 | 443 | |
392 | - sens = &sr->sen[srid]; | |
444 | + if (sr->is_suspended) { | |
445 | + dev_dbg(&sr->pdev->dev, "%s: in suspended state\n", __func__); | |
446 | + return; | |
447 | + } | |
393 | 448 | |
449 | + sens = &sr->sen[srid]; | |
450 | + | |
394 | 451 | /* Check if SR is already enabled. If yes do nothing */ |
395 | 452 | if (sr_read_reg(sr, SRCONFIG, srid) & SRCONFIG_SRENABLE) |
396 | 453 | return; |
397 | 454 | |
398 | 455 | if (sens->opp_data[sens->curr_opp].nvalue == 0) |
399 | 456 | dev_err(&sr->pdev->dev, |
400 | - "%s: OPP doesn't support SmartReflex\n", __func__); | |
457 | + "%s: OPP doesn't support SmartReflex\n", __func__); | |
401 | 458 | |
402 | 459 | /* Writing the nReciprocal value to the register */ |
403 | 460 | sr_write_reg(sr, NVALUERECIPROCAL, |
404 | - sens->opp_data[sens->curr_opp].adj_nvalue, srid); | |
461 | + sens->opp_data[sens->curr_opp].adj_nvalue, srid); | |
405 | 462 | |
406 | 463 | /* Enable the interrupt */ |
407 | 464 | sr_modify_reg(sr, IRQENABLE_SET, IRQENABLE_MCUBOUNDSINT, |
... | ... | @@ -420,6 +477,11 @@ |
420 | 477 | */ |
421 | 478 | static void sr_disable(struct am33xx_sr *sr, u32 srid) |
422 | 479 | { |
480 | + if (sr->is_suspended) { | |
481 | + dev_dbg(&sr->pdev->dev, "%s: in suspended state\n", __func__); | |
482 | + return; | |
483 | + } | |
484 | + | |
423 | 485 | /* Disable the interrupt */ |
424 | 486 | sr_modify_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUBOUNDSINT, |
425 | 487 | IRQENABLE_MCUBOUNDSINT, srid); |
426 | 488 | |
427 | 489 | |
428 | 490 | |
429 | 491 | |
430 | 492 | |
... | ... | @@ -440,31 +502,31 @@ |
440 | 502 | int i; |
441 | 503 | |
442 | 504 | if ((sr->sen[SR_CORE].opp_data[0].nvalue == 0) || |
443 | - (sr->sen[SR_MPU].opp_data[0].nvalue == 0)) { | |
505 | + (sr->sen[SR_MPU].opp_data[0].nvalue == 0)) { | |
444 | 506 | dev_err(&sr->pdev->dev, "SR module not enabled, nTarget" |
445 | 507 | " values are not found\n"); |
446 | 508 | return; |
447 | 509 | } |
448 | 510 | |
449 | - if (sr->autocomp_active == 1) { | |
511 | + if (sr->autocomp_active) { | |
450 | 512 | dev_warn(&sr->pdev->dev, "SR VDD autocomp already active\n"); |
451 | 513 | return; |
452 | 514 | } |
453 | 515 | |
454 | 516 | for (i = 0; i < sr->no_of_sens; i++) { |
455 | - /* Read current regulator value and voltage */ | |
456 | - sr->sen[i].init_volt_mv = regulator_get_voltage(sr->sen[i].reg); | |
517 | + /* Read current regulator value and voltage */ | |
518 | + sr->sen[i].init_volt_mv = regulator_get_voltage(sr->sen[i].reg); | |
457 | 519 | |
458 | - dev_dbg(&sr->pdev->dev, "%s: regulator %d, init_volt = %d\n", | |
459 | - __func__, i, sr->sen[i].init_volt_mv); | |
520 | + dev_dbg(&sr->pdev->dev, "%s: regulator %d, init_volt = %d\n", | |
521 | + __func__, i, sr->sen[i].init_volt_mv); | |
460 | 522 | |
461 | 523 | if (sr_clk_enable(sr, i)) |
462 | - return; | |
524 | + return; | |
463 | 525 | sr_configure(sr, i); |
464 | 526 | sr_enable(sr, i); |
465 | 527 | } |
466 | 528 | |
467 | - sr->autocomp_active = 1; | |
529 | + sr->autocomp_active = true; | |
468 | 530 | } |
469 | 531 | |
470 | 532 | /* sr_stop_vddautocomp - Stop VDD auto compensation |
471 | 533 | |
472 | 534 | |
473 | 535 | |
... | ... | @@ -477,22 +539,22 @@ |
477 | 539 | { |
478 | 540 | int i; |
479 | 541 | |
480 | - if (sr->autocomp_active == 0) { | |
542 | + if (!sr->autocomp_active) { | |
481 | 543 | dev_warn(&sr->pdev->dev, "SR VDD autocomp is not active\n"); |
482 | 544 | return; |
483 | 545 | } |
484 | 546 | |
485 | - /* cancel bottom half interrupt handlers that haven't run yet */ | |
547 | + /* cancel bottom half interrupt handlers that haven't run yet */ | |
486 | 548 | cancel_delayed_work_sync(&sr->work); |
487 | 549 | |
488 | 550 | for (i = 0; i < sr->no_of_sens; i++) { |
489 | - /* cancel any outstanding SR IRQ re-enables on work queue */ | |
490 | - cancel_delayed_work_sync(&sr->sen[i].work_reenable); | |
551 | + /* cancel any outstanding SR IRQ re-enables on work queue */ | |
552 | + cancel_delayed_work_sync(&sr->sen[i].work_reenable); | |
491 | 553 | sr_disable(sr, i); |
492 | 554 | sr_clk_disable(sr, i); |
493 | 555 | } |
494 | 556 | |
495 | - sr->autocomp_active = 0; | |
557 | + sr->autocomp_active = false; | |
496 | 558 | } |
497 | 559 | |
498 | 560 | /* am33xx_sr_autocomp_show - Store user input value and stop SR |
... | ... | @@ -513,7 +575,8 @@ |
513 | 575 | |
514 | 576 | static int am33xx_sr_margin_show(void *data, u64 *val) |
515 | 577 | { |
516 | - struct am33xx_sr_opp_data *sr_opp_data = (struct am33xx_sr_opp_data *)data; | |
578 | + struct am33xx_sr_opp_data *sr_opp_data = | |
579 | + (struct am33xx_sr_opp_data *)data; | |
517 | 580 | |
518 | 581 | *val = (u64) sr_opp_data->margin; |
519 | 582 | |
520 | 583 | |
521 | 584 | |
522 | 585 | |
523 | 586 | |
524 | 587 | |
525 | 588 | |
526 | 589 | |
... | ... | @@ -522,35 +585,35 @@ |
522 | 585 | |
523 | 586 | static int am33xx_sr_margin_update(void *data, u64 val) |
524 | 587 | { |
525 | - struct am33xx_sr_opp_data *sr_opp_data = | |
526 | - (struct am33xx_sr_opp_data *)data; | |
527 | - struct am33xx_sr_sensor *sr_sensor; | |
528 | - struct am33xx_sr *sr_info; | |
588 | + struct am33xx_sr_opp_data *sr_opp_data = | |
589 | + (struct am33xx_sr_opp_data *)data; | |
590 | + struct am33xx_sr_sensor *sr_sensor; | |
591 | + struct am33xx_sr *sr_info; | |
529 | 592 | |
530 | - /* work back to the sr_info pointer */ | |
531 | - sr_sensor = container_of((void *)sr_opp_data, struct am33xx_sr_sensor, | |
532 | - opp_data[sr_opp_data->opp_id]); | |
593 | + /* work back to the sr_info pointer */ | |
594 | + sr_sensor = container_of((void *)sr_opp_data, struct am33xx_sr_sensor, | |
595 | + opp_data[sr_opp_data->opp_id]); | |
533 | 596 | |
534 | - sr_info = container_of((void *)sr_sensor, struct am33xx_sr, | |
535 | - sen[sr_sensor->sr_id]); | |
597 | + sr_info = container_of((void *)sr_sensor, struct am33xx_sr, | |
598 | + sen[sr_sensor->sr_id]); | |
536 | 599 | |
537 | - /* store the value of margin */ | |
538 | - sr_opp_data->margin = (s32)val; | |
600 | + /* store the value of margin */ | |
601 | + sr_opp_data->margin = (s32)val; | |
539 | 602 | |
540 | - dev_warn(&sr_info->pdev->dev, "%s: new margin=%d, srid=%d, opp=%d\n", | |
541 | - __func__, sr_opp_data->margin, sr_sensor->sr_id, | |
542 | - sr_opp_data->opp_id); | |
603 | + dev_warn(&sr_info->pdev->dev, "%s: new margin=%d, srid=%d, opp=%d\n", | |
604 | + __func__, sr_opp_data->margin, sr_sensor->sr_id, | |
605 | + sr_opp_data->opp_id); | |
543 | 606 | |
544 | - /* updata ntarget values based upon new margin */ | |
545 | - if (sr_set_nvalues(sr_info, sr_sensor->sr_id) == -EINVAL) | |
546 | - dev_err(&sr_info->pdev->dev, | |
547 | - "%s: Zero NValue read from EFUSE\n", __func__); | |
607 | + /* updata ntarget values based upon new margin */ | |
608 | + if (sr_set_nvalues(sr_info, sr_sensor->sr_id) == -EINVAL) | |
609 | + dev_err(&sr_info->pdev->dev, | |
610 | + "%s: Zero NValue read from EFUSE\n", __func__); | |
548 | 611 | |
549 | - /* restart SmartReflex to adapt to new values */ | |
550 | - sr_stop_vddautocomp(sr_info); | |
551 | - sr_start_vddautocomp(sr_info); | |
612 | + /* restart SmartReflex to adapt to new values */ | |
613 | + sr_stop_vddautocomp(sr_info); | |
614 | + sr_start_vddautocomp(sr_info); | |
552 | 615 | |
553 | - return 0; | |
616 | + return 0; | |
554 | 617 | } |
555 | 618 | |
556 | 619 | /* am33xx_sr_autocomp_store - Store user input and start SR |
557 | 620 | |
558 | 621 | |
559 | 622 | |
560 | 623 | |
... | ... | @@ -564,21 +627,25 @@ |
564 | 627 | { |
565 | 628 | struct am33xx_sr *sr_info = (struct am33xx_sr *) data; |
566 | 629 | |
630 | + if (sr_info->is_suspended) { | |
631 | + pr_warning("%s: in suspended state\n", __func__); | |
632 | + return -EBUSY; | |
633 | + } | |
634 | + | |
567 | 635 | /* Sanity check */ |
568 | 636 | if (val && (val != 1)) { |
569 | 637 | dev_warn(&sr_info->pdev->dev, "%s: Invalid argument %llu\n", |
570 | - __func__, val); | |
638 | + __func__, val); | |
571 | 639 | return -EINVAL; |
572 | 640 | } |
573 | 641 | |
574 | 642 | if (!val) { |
575 | - sr_info->disabled_by_user = 1; | |
643 | + sr_info->disabled_by_user = true; | |
576 | 644 | sr_stop_vddautocomp(sr_info); |
577 | - } | |
578 | - else { | |
579 | - sr_info->disabled_by_user = 0; | |
645 | + } else { | |
646 | + sr_info->disabled_by_user = false; | |
580 | 647 | sr_start_vddautocomp(sr_info); |
581 | - } | |
648 | + } | |
582 | 649 | |
583 | 650 | return 0; |
584 | 651 | } |
... | ... | @@ -618,7 +685,7 @@ |
618 | 685 | */ |
619 | 686 | static int sr_debugfs_entries(struct am33xx_sr *sr_info) |
620 | 687 | { |
621 | - struct am33xx_sr_sensor *sens; | |
688 | + struct am33xx_sr_sensor *sens; | |
622 | 689 | struct dentry *dbg_dir, *sen_dir, *opp_dir; |
623 | 690 | int i, j; |
624 | 691 | |
625 | 692 | |
626 | 693 | |
... | ... | @@ -629,13 +696,13 @@ |
629 | 696 | return PTR_ERR(dbg_dir); |
630 | 697 | } |
631 | 698 | |
632 | - (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir, | |
699 | + (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, dbg_dir, | |
633 | 700 | (void *)sr_info, &sr_fops); |
634 | - (void) debugfs_create_u32("interrupt_delay", S_IRUGO | S_IWUGO, | |
701 | + (void) debugfs_create_u32("interrupt_delay", S_IRUGO | S_IWUSR, | |
635 | 702 | dbg_dir, &sr_info->irq_delay); |
636 | 703 | |
637 | 704 | for (i = 0; i < sr_info->no_of_sens; i++) { |
638 | - sens = &sr_info->sen[i]; | |
705 | + sens = &sr_info->sen[i]; | |
639 | 706 | sen_dir = debugfs_create_dir(sens->name, dbg_dir); |
640 | 707 | if (IS_ERR(sen_dir)) { |
641 | 708 | dev_err(&sr_info->pdev->dev, "%s: Unable to create" |
642 | 709 | |
643 | 710 | |
644 | 711 | |
645 | 712 | |
... | ... | @@ -643,37 +710,37 @@ |
643 | 710 | return PTR_ERR(sen_dir); |
644 | 711 | } |
645 | 712 | |
646 | - (void)debugfs_create_u32("initial_voltage", S_IRUGO, sen_dir, | |
713 | + (void)debugfs_create_u32("initial_voltage", S_IRUGO, sen_dir, | |
647 | 714 | &sens->init_volt_mv); |
648 | - (void)debugfs_create_file("current_voltage", S_IRUGO, sen_dir, | |
715 | + (void)debugfs_create_file("current_voltage", S_IRUGO, sen_dir, | |
649 | 716 | (void *)sens, &curr_volt_fops); |
650 | 717 | |
651 | - for (j = 0; j < sr_info->sen[i].no_of_opps; j++) { | |
652 | - char tmp[20]; | |
718 | + for (j = 0; j < sr_info->sen[i].no_of_opps; j++) { | |
719 | + char tmp[20]; | |
653 | 720 | |
654 | - sprintf(&tmp[0], "opp%d", j); | |
655 | - opp_dir = debugfs_create_dir(tmp, sen_dir); | |
656 | - if (IS_ERR(opp_dir)) { | |
657 | - dev_err(&sr_info->pdev->dev, | |
658 | - "%s: Unable to create debugfs directory\n", | |
659 | - __func__); | |
660 | - return PTR_ERR(opp_dir); | |
661 | - } | |
721 | + sprintf(&tmp[0], "opp%d", j); | |
722 | + opp_dir = debugfs_create_dir(tmp, sen_dir); | |
723 | + if (IS_ERR(opp_dir)) { | |
724 | + dev_err(&sr_info->pdev->dev, | |
725 | + "%s: Unable to create debugfs directory\n", | |
726 | + __func__); | |
727 | + return PTR_ERR(opp_dir); | |
728 | + } | |
662 | 729 | |
663 | - (void)debugfs_create_file("margin", S_IRUGO | S_IWUGO, | |
664 | - opp_dir, (void *)&sens->opp_data[j], | |
665 | - &margin_fops); | |
666 | - (void)debugfs_create_x32("err2voltgain", | |
667 | - S_IRUGO | S_IWUGO, | |
668 | - opp_dir, | |
669 | - &sens->opp_data[j].e2v_gain); | |
670 | - (void)debugfs_create_x32("nvalue", S_IRUGO, | |
671 | - opp_dir, | |
672 | - &sens->opp_data[j].nvalue); | |
673 | - (void)debugfs_create_x32("adj_nvalue", S_IRUGO, | |
674 | - opp_dir, | |
675 | - &sens->opp_data[j].adj_nvalue); | |
676 | - } | |
730 | + (void)debugfs_create_file("margin", S_IRUGO | S_IWUSR, | |
731 | + opp_dir, (void *)&sens->opp_data[j], | |
732 | + &margin_fops); | |
733 | + (void)debugfs_create_x32("err2voltgain", | |
734 | + S_IRUGO | S_IWUSR, | |
735 | + opp_dir, | |
736 | + &sens->opp_data[j].e2v_gain); | |
737 | + (void)debugfs_create_x32("nvalue", S_IRUGO, | |
738 | + opp_dir, | |
739 | + &sens->opp_data[j].nvalue); | |
740 | + (void)debugfs_create_x32("adj_nvalue", S_IRUGO, | |
741 | + opp_dir, | |
742 | + &sens->opp_data[j].adj_nvalue); | |
743 | + } | |
677 | 744 | } |
678 | 745 | return 0; |
679 | 746 | } |
680 | 747 | |
681 | 748 | |
682 | 749 | |
683 | 750 | |
684 | 751 | |
685 | 752 | |
686 | 753 | |
687 | 754 | |
688 | 755 | |
... | ... | @@ -688,51 +755,64 @@ |
688 | 755 | |
689 | 756 | /* Find and return current OPP. This should change to use system APIs, |
690 | 757 | but voltdm is not currently populated, and opp APIs are also not working. */ |
691 | -static int get_current_opp(struct am33xx_sr *sr, u32 srid, u32 freq) { | |
692 | - int i; | |
758 | +static int get_current_opp(struct am33xx_sr *sr, u32 srid, u32 freq) | |
759 | +{ | |
760 | + int i; | |
693 | 761 | |
694 | - for (i = 0; i < sr->sen[srid].no_of_opps; i++) { | |
695 | - if (sr->sen[srid].opp_data[i].frequency == freq) | |
696 | - return i; | |
697 | - } | |
762 | + for (i = 0; i < sr->sen[srid].no_of_opps; i++) { | |
763 | + if (sr->sen[srid].opp_data[i].frequency == freq) | |
764 | + return i; | |
765 | + } | |
698 | 766 | |
699 | - return -EINVAL; | |
767 | + return -EINVAL; | |
700 | 768 | } |
701 | 769 | |
702 | 770 | static int am33xx_sr_cpufreq_transition(struct notifier_block *nb, |
703 | 771 | unsigned long val, void *data) |
704 | 772 | { |
705 | - struct am33xx_sr *sr; | |
706 | - struct cpufreq_freqs *cpu; | |
773 | + struct am33xx_sr *sr; | |
774 | + struct cpufreq_freqs *cpu; | |
707 | 775 | |
708 | 776 | sr = container_of(nb, struct am33xx_sr, freq_transition); |
709 | 777 | |
710 | - /* We are required to disable SR while OPP change is occurring */ | |
778 | + /* We are required to disable SR while OPP change is occurring */ | |
711 | 779 | if (val == CPUFREQ_PRECHANGE) { |
712 | - dev_dbg(&sr->pdev->dev, "%s: prechange\n", __func__); | |
713 | - sr_stop_vddautocomp(sr); | |
780 | + dev_dbg(&sr->pdev->dev, "%s: prechange\n", __func__); | |
781 | + | |
782 | + printk(KERN_DEBUG "%s: prechange\n", __func__); | |
783 | + | |
784 | + sr_stop_vddautocomp(sr); | |
785 | + | |
714 | 786 | } else if (val == CPUFREQ_POSTCHANGE) { |
715 | - cpu = (struct cpufreq_freqs *)data; | |
716 | - dev_dbg(&sr->pdev->dev, | |
717 | - "%s: postchange, cpu=%d, old=%d, new=%d\n", | |
718 | - __func__, cpu->cpu, cpu->old, cpu->new); | |
787 | + cpu = (struct cpufreq_freqs *)data; | |
788 | + dev_dbg(&sr->pdev->dev, | |
789 | + "%s: postchange, cpu=%d, old=%d, new=%d\n", | |
790 | + __func__, cpu->cpu, cpu->old, cpu->new); | |
719 | 791 | |
720 | - /* update current OPP */ | |
721 | - sr->sen[SR_MPU].curr_opp = get_current_opp(sr, SR_MPU, | |
722 | - cpu->new*1000); | |
723 | - if (sr->sen[SR_MPU].curr_opp == -EINVAL) { | |
724 | - dev_err(&sr->pdev->dev, "%s: cannot determine opp\n", | |
725 | - __func__); | |
726 | - return -EINVAL; | |
727 | - } | |
792 | + printk(KERN_DEBUG "%s: postchange\n", __func__); | |
728 | 793 | |
729 | - dev_dbg(&sr->pdev->dev, "%s: postchange, new opp=%d\n", | |
730 | - __func__, sr->sen[SR_MPU].curr_opp); | |
794 | + /* update current OPP */ | |
795 | + sr->sen[SR_MPU].curr_opp = get_current_opp(sr, SR_MPU, | |
796 | + cpu->new*1000); | |
797 | + if (sr->sen[SR_MPU].curr_opp == -EINVAL) { | |
798 | + dev_err(&sr->pdev->dev, "%s: cannot determine opp\n", | |
799 | + __func__); | |
800 | + return -EINVAL; | |
801 | + } | |
731 | 802 | |
732 | - /* this handles the case when the user has disabled SR via | |
733 | - debugfs, therefore we do not want to enable SR */ | |
734 | - if (sr->disabled_by_user == 0) | |
735 | - sr_start_vddautocomp(sr); | |
803 | + dev_dbg(&sr->pdev->dev, "%s: postchange, new opp=%d\n", | |
804 | + __func__, sr->sen[SR_MPU].curr_opp); | |
805 | + | |
806 | + /* reset the voltage calculation algorithm for MPU */ | |
807 | + get_errvolt(sr, SR_MPU, 0, 1); | |
808 | + | |
809 | + /* this handles the case when the user has disabled SR via | |
810 | + debugfs, therefore we do not want to enable SR */ | |
811 | + if (sr->disabled_by_user == false) { | |
812 | + printk(KERN_DEBUG "%s: postchange, new opp=%d\n", | |
813 | + __func__, sr->sen[SR_MPU].curr_opp); | |
814 | + sr_start_vddautocomp(sr); | |
815 | + } | |
736 | 816 | } |
737 | 817 | |
738 | 818 | return 0; |
... | ... | @@ -740,7 +820,7 @@ |
740 | 820 | |
741 | 821 | static inline int am33xx_sr_cpufreq_register(struct am33xx_sr *sr) |
742 | 822 | { |
743 | - sr->freq_transition.notifier_call = am33xx_sr_cpufreq_transition; | |
823 | + sr->freq_transition.notifier_call = am33xx_sr_cpufreq_transition; | |
744 | 824 | |
745 | 825 | return cpufreq_register_notifier(&sr->freq_transition, |
746 | 826 | CPUFREQ_TRANSITION_NOTIFIER); |
... | ... | @@ -754,6 +834,67 @@ |
754 | 834 | |
755 | 835 | #endif |
756 | 836 | |
837 | +static void print_die_id(void) | |
838 | +{ | |
839 | + writel(0xF47765F2, AM33XX_CTRL_REGADDR(0x1828)); | |
840 | + writel(0x703E6C3D, AM33XX_CTRL_REGADDR(0x1844)); | |
841 | + writel(0x3724C7D6, AM33XX_CTRL_REGADDR(0x182C)); | |
842 | + writel(0x7A733E49, AM33XX_CTRL_REGADDR(0x184C)); | |
843 | + | |
844 | + printk(KERN_DEBUG "DIEID: %08x %08x %08x %08x\n", | |
845 | + readl(AM33XX_CTRL_REGADDR(0x183C)), | |
846 | + readl(AM33XX_CTRL_REGADDR(0x1848)), | |
847 | + readl(AM33XX_CTRL_REGADDR(0x1824)), | |
848 | + readl(AM33XX_CTRL_REGADDR(0x1850))); | |
849 | + | |
850 | + printk(KERN_DEBUG "EFUSE SMA register val = %08x\n", | |
851 | + readl(AM33XX_CTRL_REGADDR(0x7fc))); | |
852 | +} | |
853 | + | |
854 | +static int am33xx_sr_suspend(struct device *dev) | |
855 | +{ | |
856 | + if (global_sr_info == NULL) | |
857 | + return -EINVAL; | |
858 | + | |
859 | + /* if we are already disabled or suspended, do nothing */ | |
860 | + if (global_sr_info->disabled_by_user) | |
861 | + return 0; | |
862 | + | |
863 | + if (global_sr_info->is_suspended) | |
864 | + return 0; | |
865 | + | |
866 | +#ifdef CONFIG_CPU_FREQ | |
867 | + am33xx_sr_cpufreq_deregister(global_sr_info); | |
868 | +#endif | |
869 | + sr_stop_vddautocomp(global_sr_info); | |
870 | + global_sr_info->is_suspended = true; | |
871 | + | |
872 | + return 0; | |
873 | +} | |
874 | + | |
875 | +static int am33xx_sr_resume(struct device *dev) | |
876 | +{ | |
877 | + if (global_sr_info == NULL) | |
878 | + return -EINVAL; | |
879 | + | |
880 | + /* ensure we don't enable SR if it was disabled before suspend */ | |
881 | + if (global_sr_info->disabled_by_user) | |
882 | + return 0; | |
883 | + | |
884 | + if (!global_sr_info->is_suspended) | |
885 | + return 0; | |
886 | + | |
887 | + global_sr_info->is_suspended = false; | |
888 | + sr_start_vddautocomp(global_sr_info); | |
889 | + | |
890 | +#ifdef CONFIG_CPU_FREQ | |
891 | + if (am33xx_sr_cpufreq_register(global_sr_info)) { | |
892 | + printk(KERN_ERR "failed to register cpufreq\n"); | |
893 | + } | |
894 | +#endif | |
895 | + return 0; | |
896 | +} | |
897 | + | |
757 | 898 | static int __init am33xx_sr_probe(struct platform_device *pdev) |
758 | 899 | { |
759 | 900 | struct am33xx_sr *sr_info; |
760 | 901 | |
... | ... | @@ -761,13 +902,9 @@ |
761 | 902 | struct resource *res[MAX_SENSORS]; |
762 | 903 | int irq; |
763 | 904 | int ret; |
764 | - int i,j; | |
905 | + int i, j; | |
765 | 906 | |
766 | - if (omap_rev() != AM335X_REV_ES1_0) { | |
767 | - dev_err(&pdev->dev, "%s: Smartreflex requires ES 1.0\n", | |
768 | - __func__); | |
769 | - return -EINVAL; | |
770 | - } | |
907 | + print_die_id(); | |
771 | 908 | |
772 | 909 | sr_info = kzalloc(sizeof(struct am33xx_sr), GFP_KERNEL); |
773 | 910 | if (!sr_info) { |
... | ... | @@ -776,6 +913,8 @@ |
776 | 913 | return -ENOMEM; |
777 | 914 | } |
778 | 915 | |
916 | + global_sr_info = sr_info; | |
917 | + | |
779 | 918 | pdata = pdev->dev.platform_data; |
780 | 919 | if (!pdata) { |
781 | 920 | dev_err(&pdev->dev, "%s: platform data missing\n", __func__); |
782 | 921 | |
783 | 922 | |
784 | 923 | |
785 | 924 | |
786 | 925 | |
787 | 926 | |
788 | 927 | |
789 | 928 | |
790 | 929 | |
791 | 930 | |
... | ... | @@ -787,77 +926,77 @@ |
787 | 926 | sr_info->sen[SR_CORE].name = "smartreflex0"; |
788 | 927 | sr_info->sen[SR_MPU].name = "smartreflex1"; |
789 | 928 | sr_info->ip_type = pdata->ip_type; |
790 | - sr_info->irq_delay = pdata->irq_delay; | |
791 | - sr_info->no_of_sens = pdata->no_of_sens; | |
792 | - sr_info->no_of_vds = pdata->no_of_vds; | |
929 | + sr_info->irq_delay = pdata->irq_delay; | |
930 | + sr_info->no_of_sens = pdata->no_of_sens; | |
931 | + sr_info->no_of_vds = pdata->no_of_vds; | |
793 | 932 | sr_info->uvoltage_step_size = pdata->vstep_size_uv; |
794 | 933 | sr_info->autocomp_active = false; |
795 | - sr_info->disabled_by_user = false; | |
934 | + sr_info->disabled_by_user = false; | |
796 | 935 | |
797 | 936 | for (i = 0; i < sr_info->no_of_sens; i++) { |
798 | - u32 curr_freq=0; | |
937 | + u32 curr_freq = 0; | |
799 | 938 | |
800 | - sr_info->sen[i].reg_name = pdata->vd_name[i]; | |
939 | + sr_info->sen[i].reg_name = pdata->vd_name[i]; | |
801 | 940 | |
802 | - /* this should be determined from voltdm or opp layer, but | |
803 | - those approaches are not working */ | |
804 | - sr_info->sen[i].no_of_opps = pdata->sr_sdata[i].no_of_opps; | |
805 | - sr_info->sen[i].sr_id = i; | |
941 | + /* this should be determined from voltdm or opp layer, but | |
942 | + those approaches are not working */ | |
943 | + sr_info->sen[i].no_of_opps = pdata->sr_sdata[i].no_of_opps; | |
944 | + sr_info->sen[i].sr_id = i; | |
806 | 945 | |
807 | - /* Reading per OPP Values */ | |
808 | - for (j = 0; j < sr_info->sen[i].no_of_opps; j++) { | |
809 | - sr_info->sen[i].opp_data[j].efuse_offs = | |
810 | - pdata->sr_sdata[i].sr_opp_data[j].efuse_offs; | |
811 | - sr_info->sen[i].opp_data[j].e2v_gain = | |
812 | - pdata->sr_sdata[i].sr_opp_data[j].e2v_gain; | |
813 | - sr_info->sen[i].opp_data[j].err_weight = | |
814 | - pdata->sr_sdata[i].sr_opp_data[j].err_weight; | |
815 | - sr_info->sen[i].opp_data[j].err_minlimit = | |
816 | - pdata->sr_sdata[i].sr_opp_data[j].err_minlimit; | |
817 | - sr_info->sen[i].opp_data[j].err_maxlimit = | |
818 | - pdata->sr_sdata[i].sr_opp_data[j].err_maxlimit; | |
819 | - sr_info->sen[i].opp_data[j].margin = | |
820 | - pdata->sr_sdata[i].sr_opp_data[j].margin; | |
821 | - sr_info->sen[i].opp_data[j].nominal_volt = | |
822 | - pdata->sr_sdata[i].sr_opp_data[j].nominal_volt; | |
823 | - sr_info->sen[i].opp_data[j].frequency = | |
824 | - pdata->sr_sdata[i].sr_opp_data[j].frequency; | |
825 | - sr_info->sen[i].opp_data[j].opp_id = j; | |
826 | - } | |
946 | + /* Reading per OPP Values */ | |
947 | + for (j = 0; j < sr_info->sen[i].no_of_opps; j++) { | |
948 | + sr_info->sen[i].opp_data[j].efuse_offs = | |
949 | + pdata->sr_sdata[i].sr_opp_data[j].efuse_offs; | |
950 | + sr_info->sen[i].opp_data[j].e2v_gain = | |
951 | + pdata->sr_sdata[i].sr_opp_data[j].e2v_gain; | |
952 | + sr_info->sen[i].opp_data[j].err_weight = | |
953 | + pdata->sr_sdata[i].sr_opp_data[j].err_weight; | |
954 | + sr_info->sen[i].opp_data[j].err_minlimit = | |
955 | + pdata->sr_sdata[i].sr_opp_data[j].err_minlimit; | |
956 | + sr_info->sen[i].opp_data[j].err_maxlimit = | |
957 | + pdata->sr_sdata[i].sr_opp_data[j].err_maxlimit; | |
958 | + sr_info->sen[i].opp_data[j].margin = | |
959 | + pdata->sr_sdata[i].sr_opp_data[j].margin; | |
960 | + sr_info->sen[i].opp_data[j].nominal_volt = | |
961 | + pdata->sr_sdata[i].sr_opp_data[j].nominal_volt; | |
962 | + sr_info->sen[i].opp_data[j].frequency = | |
963 | + pdata->sr_sdata[i].sr_opp_data[j].frequency; | |
964 | + sr_info->sen[i].opp_data[j].opp_id = j; | |
965 | + } | |
827 | 966 | |
828 | - if (i == SR_MPU) { | |
829 | - /* hardcoded CPU NR */ | |
830 | - curr_freq = cpufreq_get(0); | |
967 | + if (i == SR_MPU) { | |
968 | + /* hardcoded CPU NR */ | |
969 | + curr_freq = cpufreq_get(0); | |
831 | 970 | |
832 | - /* update current OPP */ | |
833 | - sr_info->sen[i].curr_opp = get_current_opp(sr_info, i, | |
834 | - curr_freq*1000); | |
835 | - if (sr_info->sen[i].curr_opp == -EINVAL) { | |
836 | - dev_err(&sr_info->pdev->dev, | |
837 | - "%s: cannot determine opp\n",__func__); | |
838 | - ret = -EINVAL; | |
839 | - goto err_free_sr_info; | |
840 | - } | |
841 | - } else { | |
842 | - sr_info->sen[i].curr_opp = | |
843 | - pdata->sr_sdata[i].default_opp; | |
844 | - } | |
971 | + /* update current OPP */ | |
972 | + sr_info->sen[i].curr_opp = get_current_opp(sr_info, i, | |
973 | + curr_freq*1000); | |
974 | + if (sr_info->sen[i].curr_opp == -EINVAL) { | |
975 | + dev_err(&sr_info->pdev->dev, | |
976 | + "%s: cannot determine opp\n", __func__); | |
977 | + ret = -EINVAL; | |
978 | + goto err_free_sr_info; | |
979 | + } | |
980 | + } else { | |
981 | + sr_info->sen[i].curr_opp = | |
982 | + pdata->sr_sdata[i].default_opp; | |
983 | + } | |
845 | 984 | |
846 | - dev_dbg(&pdev->dev, | |
847 | - "%s: SR%d, curr_opp=%d, no_of_opps=%d, step_size=%d\n", | |
848 | - __func__, i, sr_info->sen[i].curr_opp, | |
849 | - sr_info->sen[i].no_of_opps, | |
850 | - sr_info->uvoltage_step_size); | |
985 | + dev_dbg(&pdev->dev, | |
986 | + "%s: SR%d, curr_opp=%d, no_of_opps=%d, step_size=%d\n", | |
987 | + __func__, i, sr_info->sen[i].curr_opp, | |
988 | + sr_info->sen[i].no_of_opps, | |
989 | + sr_info->uvoltage_step_size); | |
851 | 990 | |
852 | - ret = sr_set_nvalues(sr_info, i); | |
853 | - if (ret == -EINVAL) { | |
854 | - dev_err(&sr_info->pdev->dev, | |
855 | - "%s: Zero NValue read from EFUSE\n", __func__); | |
856 | - goto err_free_sr_info; | |
857 | - } | |
991 | + ret = sr_set_nvalues(sr_info, i); | |
992 | + if (ret == -EINVAL) { | |
993 | + dev_err(&sr_info->pdev->dev, | |
994 | + "%s: Zero NValue read from EFUSE\n", __func__); | |
995 | + goto err_free_sr_info; | |
996 | + } | |
858 | 997 | |
859 | - INIT_DELAYED_WORK(&sr_info->sen[i].work_reenable, | |
860 | - irq_sr_reenable); | |
998 | + INIT_DELAYED_WORK(&sr_info->sen[i].work_reenable, | |
999 | + irq_sr_reenable); | |
861 | 1000 | |
862 | 1001 | sr_info->res_name[i] = kzalloc(CLK_NAME_LEN + 1, GFP_KERNEL); |
863 | 1002 | |
... | ... | @@ -907,7 +1046,7 @@ |
907 | 1046 | |
908 | 1047 | ret = request_irq(sr_info->sen[i].irq, sr_class2_irq, |
909 | 1048 | IRQF_DISABLED, sr_info->sen[i].name, |
910 | - (void *)&sr_info->sen[i]); | |
1049 | + (void *)&sr_info->sen[i]); | |
911 | 1050 | if (ret) { |
912 | 1051 | dev_err(&pdev->dev, "%s: Could not install SR ISR\n", |
913 | 1052 | __func__); |
914 | 1053 | |
915 | 1054 | |
916 | 1055 | |
... | ... | @@ -917,22 +1056,22 @@ |
917 | 1056 | sr_info->sen[i].senn_en = pdata->sr_sdata[i].senn_mod; |
918 | 1057 | sr_info->sen[i].senp_en = pdata->sr_sdata[i].senp_mod; |
919 | 1058 | |
920 | - sr_info->sen[i].reg = | |
921 | - regulator_get(NULL, sr_info->sen[i].reg_name); | |
922 | - if (IS_ERR(sr_info->sen[i].reg)) { | |
923 | - ret = -EINVAL; | |
924 | - goto err_free_irq; | |
925 | - } | |
1059 | + sr_info->sen[i].reg = | |
1060 | + regulator_get(NULL, sr_info->sen[i].reg_name); | |
1061 | + if (IS_ERR(sr_info->sen[i].reg)) { | |
1062 | + ret = -EINVAL; | |
1063 | + goto err_free_irq; | |
1064 | + } | |
926 | 1065 | |
927 | - /* Read current regulator value and voltage */ | |
928 | - sr_info->sen[i].init_volt_mv = | |
929 | - regulator_get_voltage(sr_info->sen[i].reg); | |
1066 | + /* Read current regulator value and voltage */ | |
1067 | + sr_info->sen[i].init_volt_mv = | |
1068 | + regulator_get_voltage(sr_info->sen[i].reg); | |
930 | 1069 | |
931 | - dev_dbg(&pdev->dev, "%s: regulator %d, init_volt = %d\n", | |
932 | - __func__, i, sr_info->sen[i].init_volt_mv); | |
1070 | + dev_dbg(&pdev->dev, "%s: regulator %d, init_volt = %d\n", | |
1071 | + __func__, i, sr_info->sen[i].init_volt_mv); | |
933 | 1072 | } /* for() */ |
934 | 1073 | |
935 | - /* set_voltage() will be used as the bottom half IRQ handler */ | |
1074 | + /* set_voltage() will be used as the bottom half IRQ handler */ | |
936 | 1075 | INIT_DELAYED_WORK(&sr_info->work, set_voltage); |
937 | 1076 | |
938 | 1077 | #ifdef CONFIG_CPU_FREQ |
939 | 1078 | |
940 | 1079 | |
941 | 1080 | |
... | ... | @@ -943,22 +1082,24 @@ |
943 | 1082 | } |
944 | 1083 | #endif |
945 | 1084 | |
1085 | +#ifdef CONFIG_DEBUG_FS | |
946 | 1086 | /* debugfs entries */ |
947 | 1087 | ret = sr_debugfs_entries(sr_info); |
948 | 1088 | if (ret) |
949 | 1089 | dev_warn(&pdev->dev, "%s: Debugfs entries are not created\n", |
950 | 1090 | __func__); |
1091 | +#endif | |
951 | 1092 | |
952 | 1093 | platform_set_drvdata(pdev, sr_info); |
953 | 1094 | |
954 | 1095 | dev_info(&pdev->dev, "%s: Driver initialized\n", __func__); |
955 | 1096 | |
956 | - /* disabled_by_user used to ensure SR doesn't come on via CPUFREQ | |
957 | - scaling if user has disabled SR via debugfs on enable_on_init */ | |
1097 | + /* disabled_by_user used to ensure SR doesn't come on via CPUFREQ | |
1098 | + scaling if user has disabled SR via debugfs on enable_on_init */ | |
958 | 1099 | if (pdata->enable_on_init) |
959 | 1100 | sr_start_vddautocomp(sr_info); |
960 | - else | |
961 | - sr_info->disabled_by_user = 1; | |
1101 | + else | |
1102 | + sr_info->disabled_by_user = true; | |
962 | 1103 | |
963 | 1104 | return ret; |
964 | 1105 | |
... | ... | @@ -967,8 +1108,8 @@ |
967 | 1108 | #endif |
968 | 1109 | |
969 | 1110 | err_reg_put: |
970 | - i--; /* back up i by one to walk back through the for loop */ | |
971 | - regulator_put(sr_info->sen[i].reg); | |
1111 | + i--; /* back up i by one to walk back through the for loop */ | |
1112 | + regulator_put(sr_info->sen[i].reg); | |
972 | 1113 | err_free_irq: |
973 | 1114 | free_irq(sr_info->sen[i].irq, (void *)sr_info); |
974 | 1115 | err_put_clock: |
... | ... | @@ -978,11 +1119,10 @@ |
978 | 1119 | err_release_mem: |
979 | 1120 | release_mem_region(res[i]->start, resource_size(res[i])); |
980 | 1121 | err_free_mem: |
981 | - kfree(sr_info->res_name[i]); | |
982 | - /* unwind back through the for loop */ | |
983 | - if (i != 0) { | |
984 | - goto err_reg_put; | |
985 | - } | |
1122 | + kfree(sr_info->res_name[i]); | |
1123 | + /* unwind back through the for loop */ | |
1124 | + if (i != 0) | |
1125 | + goto err_reg_put; | |
986 | 1126 | |
987 | 1127 | err_free_sr_info: |
988 | 1128 | kfree(sr_info); |
989 | 1129 | |
990 | 1130 | |
991 | 1131 | |
992 | 1132 | |
... | ... | @@ -1010,27 +1150,31 @@ |
1010 | 1150 | #endif |
1011 | 1151 | |
1012 | 1152 | for (i = 0; i < sr_info->no_of_sens; i++) { |
1013 | - regulator_put(sr_info->sen[i].reg); | |
1014 | - irq = platform_get_irq_byname(pdev, sr_info->sen[i].name); | |
1153 | + regulator_put(sr_info->sen[i].reg); | |
1154 | + irq = platform_get_irq_byname(pdev, sr_info->sen[i].name); | |
1015 | 1155 | free_irq(irq, (void *)sr_info); |
1016 | 1156 | clk_put(sr_info->sen[i].fck); |
1017 | 1157 | iounmap(sr_info->sen[i].base); |
1018 | 1158 | res[i] = platform_get_resource_byname(pdev, |
1019 | 1159 | IORESOURCE_MEM, sr_info->sen[i].name); |
1020 | 1160 | release_mem_region(res[i]->start, resource_size(res[i])); |
1021 | - kfree(sr_info->res_name[i]); | |
1161 | + kfree(sr_info->res_name[i]); | |
1022 | 1162 | } |
1023 | 1163 | |
1024 | 1164 | kfree(sr_info); |
1025 | 1165 | |
1026 | - dev_info(&pdev->dev, "%s: SR has been removed\n", __func__); | |
1166 | + dev_info(&pdev->dev, "%s: SR has been removed\n", __func__); | |
1027 | 1167 | return 0; |
1028 | 1168 | } |
1029 | 1169 | |
1170 | +static SIMPLE_DEV_PM_OPS(am33xx_sr_dev_pm_ops, am33xx_sr_suspend, | |
1171 | + am33xx_sr_resume); | |
1172 | + | |
1030 | 1173 | static struct platform_driver smartreflex_driver = { |
1031 | 1174 | .driver = { |
1032 | 1175 | .name = "smartreflex", |
1033 | 1176 | .owner = THIS_MODULE, |
1177 | + .pm = &am33xx_sr_dev_pm_ops, | |
1034 | 1178 | }, |
1035 | 1179 | .remove = am33xx_sr_remove, |
1036 | 1180 | }; |
arch/arm/mach-omap2/devices.c
... | ... | @@ -1231,244 +1231,313 @@ |
1231 | 1231 | /* The values below are based upon silicon characterization data. |
1232 | 1232 | * Each OPP and sensor combination potentially has different values. |
1233 | 1233 | * The values of ERR2VOLT_GAIN and ERR_MIN_LIMIT also change based on |
1234 | - * the PMIC step size. Values have been given to cover the AM335 EVM | |
1234 | + * the PMIC step size. Values have been given to cover the AM335 EVM | |
1235 | 1235 | * (12.5mV step) and the Beaglebone (25mV step). If the step |
1236 | 1236 | * size changes, you should update these values, and don't forget to |
1237 | 1237 | * change the step size in the platform data structure, am33xx_sr_pdata. |
1238 | 1238 | */ |
1239 | 1239 | |
1240 | -#define AM33XX_SR0_OPP50_CNTRL_OFFSET 0x07B8 | |
1241 | -#define AM33XX_SR0_OPP50_EVM_ERR2VOLT_GAIN 0xC | |
1242 | -#define AM33XX_SR0_OPP50_EVM_ERR_MIN_LIMIT 0xF5 | |
1243 | -#define AM33XX_SR0_OPP50_BB_ERR2VOLT_GAIN 0x6 | |
1244 | -#define AM33XX_SR0_OPP50_BB_ERR_MIN_LIMIT 0xEA | |
1245 | -#define AM33XX_SR0_OPP50_ERR_MAX_LIMIT 0x2 | |
1246 | -#define AM33XX_SR0_OPP50_ERR_WEIGHT 0x4 | |
1247 | -#define AM33XX_SR0_OPP50_MARGIN 0 | |
1240 | +#define AM33XX_SR0_OPP50_CNTRL_OFFSET 0x07B8 | |
1241 | +#define AM33XX_SR0_OPP50_EVM_ERR_MIN_LIMIT 0xF0 | |
1242 | +#define AM33XX_SR0_OPP50_BB_ERR_MIN_LIMIT 0xEA | |
1243 | +#define AM33XX_SR0_OPP50_ERR_MAX_LIMIT 0x2 | |
1244 | +#define AM33XX_SR0_OPP50_ERR_WEIGHT 0x4 | |
1245 | +#define AM33XX_SR0_OPP50_MARGIN 0 | |
1248 | 1246 | |
1249 | -#define AM33XX_SR0_OPP100_CNTRL_OFFSET 0x07BC | |
1250 | -#define AM33XX_SR0_OPP100_EVM_ERR2VOLT_GAIN 0x12 | |
1251 | -#define AM33XX_SR0_OPP100_EVM_ERR_MIN_LIMIT 0xF8 | |
1252 | -#define AM33XX_SR0_OPP100_BB_ERR2VOLT_GAIN 0x9 | |
1253 | -#define AM33XX_SR0_OPP100_BB_ERR_MIN_LIMIT 0xF1 | |
1254 | -#define AM33XX_SR0_OPP100_ERR_MAX_LIMIT 0x2 | |
1255 | -#define AM33XX_SR0_OPP100_ERR_WEIGHT 0x4 | |
1256 | -#define AM33XX_SR0_OPP100_MARGIN 0 | |
1247 | +#define AM33XX_SR0_OPP100_CNTRL_OFFSET 0x07BC | |
1248 | +#define AM33XX_SR0_OPP100_EVM_ERR_MIN_LIMIT 0xF0 | |
1249 | +#define AM33XX_SR0_OPP100_BB_ERR_MIN_LIMIT 0xF1 | |
1250 | +#define AM33XX_SR0_OPP100_ERR_MAX_LIMIT 0x2 | |
1251 | +#define AM33XX_SR0_OPP100_ERR_WEIGHT 0x4 | |
1252 | +#define AM33XX_SR0_OPP100_MARGIN 0 | |
1257 | 1253 | |
1258 | -#define AM33XX_SR1_OPP50_CNTRL_OFFSET 0x0770 | |
1259 | -#define AM33XX_SR1_OPP50_EVM_ERR2VOLT_GAIN 0x5 | |
1260 | -#define AM33XX_SR1_OPP50_EVM_ERR_MIN_LIMIT 0xE6 | |
1261 | -#define AM33XX_SR1_OPP50_BB_ERR2VOLT_GAIN 0x2 | |
1262 | -#define AM33XX_SR1_OPP50_BB_ERR_MIN_LIMIT 0xC0 | |
1263 | -#define AM33XX_SR1_OPP50_ERR_MAX_LIMIT 0x2 | |
1264 | -#define AM33XX_SR1_OPP50_ERR_WEIGHT 0x4 | |
1265 | -#define AM33XX_SR1_OPP50_MARGIN 0 | |
1254 | +#define AM33XX_SR1_OPP50_CNTRL_OFFSET 0x0770 | |
1255 | +#define AM33XX_SR1_OPP50_EVM_ERR_MIN_LIMIT 0xFA | |
1256 | +#define AM33XX_SR1_OPP50_BB_ERR_MIN_LIMIT 0xC0 | |
1257 | +#define AM33XX_SR1_OPP50_ERR_MAX_LIMIT 0x2 | |
1258 | +#define AM33XX_SR1_OPP50_ERR_WEIGHT 0x4 | |
1259 | +#define AM33XX_SR1_OPP50_MARGIN 0 | |
1266 | 1260 | |
1267 | -#define AM33XX_SR1_OPP100_CNTRL_OFFSET 0x0774 | |
1268 | -#define AM33XX_SR1_OPP100_EVM_ERR2VOLT_GAIN 0x8 | |
1269 | -#define AM33XX_SR1_OPP100_EVM_ERR_MIN_LIMIT 0xF0 | |
1270 | -#define AM33XX_SR1_OPP100_BB_ERR2VOLT_GAIN 0x4 | |
1271 | -#define AM33XX_SR1_OPP100_BB_ERR_MIN_LIMIT 0xDF | |
1272 | -#define AM33XX_SR1_OPP100_ERR_MAX_LIMIT 0x2 | |
1273 | -#define AM33XX_SR1_OPP100_ERR_WEIGHT 0x4 | |
1274 | -#define AM33XX_SR1_OPP100_MARGIN 0 | |
1261 | +#define AM33XX_SR1_OPP100_CNTRL_OFFSET 0x0774 | |
1262 | +#define AM33XX_SR1_OPP100_EVM_ERR_MIN_LIMIT 0xFB | |
1263 | +#define AM33XX_SR1_OPP100_BB_ERR_MIN_LIMIT 0xDF | |
1264 | +#define AM33XX_SR1_OPP100_ERR_MAX_LIMIT 0x2 | |
1265 | +#define AM33XX_SR1_OPP100_ERR_WEIGHT 0x4 | |
1266 | +#define AM33XX_SR1_OPP100_MARGIN 0 | |
1275 | 1267 | |
1276 | -#define AM33XX_SR1_OPP120_CNTRL_OFFSET 0x0778 | |
1277 | -#define AM33XX_SR1_OPP120_EVM_ERR2VOLT_GAIN 0xB | |
1278 | -#define AM33XX_SR1_OPP120_EVM_ERR_MIN_LIMIT 0xF4 | |
1279 | -#define AM33XX_SR1_OPP120_BB_ERR2VOLT_GAIN 0x5 | |
1280 | -#define AM33XX_SR1_OPP120_BB_ERR_MIN_LIMIT 0xE6 | |
1281 | -#define AM33XX_SR1_OPP120_ERR_MAX_LIMIT 0x2 | |
1282 | -#define AM33XX_SR1_OPP120_ERR_WEIGHT 0x4 | |
1283 | -#define AM33XX_SR1_OPP120_MARGIN 0 | |
1268 | +#define AM33XX_SR1_OPP120_CNTRL_OFFSET 0x0778 | |
1269 | +#define AM33XX_SR1_OPP120_EVM_ERR_MIN_LIMIT 0xFC | |
1270 | +#define AM33XX_SR1_OPP120_BB_ERR_MIN_LIMIT 0xE6 | |
1271 | +#define AM33XX_SR1_OPP120_ERR_MAX_LIMIT 0x2 | |
1272 | +#define AM33XX_SR1_OPP120_ERR_WEIGHT 0x7 | |
1273 | +#define AM33XX_SR1_OPP120_MARGIN 0 | |
1284 | 1274 | |
1285 | -#define AM33XX_SR1_OPPTURBO_CNTRL_OFFSET 0x077C | |
1286 | -#define AM33XX_SR1_OPPTURBO_EVM_ERR2VOLT_GAIN 0xC | |
1287 | -#define AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT 0xF5 | |
1288 | -#define AM33XX_SR1_OPPTURBO_BB_ERR2VOLT_GAIN 0x6 | |
1289 | -#define AM33XX_SR1_OPPTURBO_BB_ERR_MIN_LIMIT 0xEA | |
1290 | -#define AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT 0x2 | |
1291 | -#define AM33XX_SR1_OPPTURBO_ERR_WEIGHT 0x4 | |
1292 | -#define AM33XX_SR1_OPPTURBO_MARGIN 0 | |
1275 | +#define AM33XX_SR1_OPPTURBO_CNTRL_OFFSET 0x077C | |
1276 | +#define AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT 0xFD | |
1277 | +#define AM33XX_SR1_OPPTURBO_BB_ERR_MIN_LIMIT 0xEA | |
1278 | +#define AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT 0x2 | |
1279 | +#define AM33XX_SR1_OPPTURBO_ERR_WEIGHT 0x7 | |
1280 | +#define AM33XX_SR1_OPPTURBO_MARGIN 0 | |
1293 | 1281 | |
1282 | +/* bits 31:16 = SenP margin; bit 15:0 = SenN margin */ | |
1283 | + | |
1284 | +#define AM33XX_SR1_OPPNITRO_MARGIN 0x018B019A | |
1285 | + | |
1294 | 1286 | /* the voltages and frequencies should probably be defined in opp3xxx_data.c. |
1295 | 1287 | Once SR is integrated to the mainline driver, and voltdm is working |
1296 | 1288 | correctly in AM335x, these can be removed. */ |
1297 | -#define AM33XX_VDD_MPU_OPP50_UV 950000 | |
1298 | -#define AM33XX_VDD_MPU_OPP100_UV 1100000 | |
1299 | -#define AM33XX_VDD_MPU_OPP120_UV 1200000 | |
1300 | -#define AM33XX_VDD_MPU_OPPTURBO_UV 1260000 | |
1301 | -#define AM33XX_VDD_CORE_OPP50_UV 950000 | |
1302 | -#define AM33XX_VDD_CORE_OPP100_UV 1100000 | |
1289 | +#define AM33XX_VDD_MPU_OPP50_UV 950000 | |
1290 | +#define AM33XX_VDD_MPU_OPP100_UV 1100000 | |
1291 | +#define AM33XX_VDD_MPU_OPP120_UV 1200000 | |
1292 | +#define AM33XX_VDD_MPU_OPPTURBO_UV 1260000 | |
1293 | +#define AM33XX_VDD_CORE_OPP50_UV 950000 | |
1294 | +#define AM33XX_VDD_CORE_OPP100_UV 1100000 | |
1303 | 1295 | |
1304 | -#define AM33XX_VDD_MPU_OPP50_FREQ 275000000 | |
1305 | -#define AM33XX_VDD_MPU_OPP100_FREQ 500000000 | |
1306 | -#define AM33XX_VDD_MPU_OPP120_FREQ 600000000 | |
1307 | -#define AM33XX_VDD_MPU_OPPTURBO_FREQ 720000000 | |
1296 | +#define AM33XX_VDD_MPU_OPP50_FREQ 275000000 | |
1297 | +#define AM33XX_VDD_MPU_OPP100_FREQ 500000000 | |
1298 | +#define AM33XX_VDD_MPU_OPP120_FREQ 600000000 | |
1299 | +#define AM33XX_VDD_MPU_OPPTURBO_FREQ 720000000 | |
1308 | 1300 | |
1301 | +#define AM33XX_ES2_0_VDD_MPU_OPP50_UV 950000 | |
1302 | +#define AM33XX_ES2_0_VDD_MPU_OPP100_UV 1100000 | |
1303 | +#define AM33XX_ES2_0_VDD_MPU_OPP120_UV 1200000 | |
1304 | +#define AM33XX_ES2_0_VDD_MPU_OPPTURBO_UV 1260000 | |
1305 | +#define AM33XX_ES2_0_VDD_MPU_OPPNITRO_UV 1320000 | |
1306 | + | |
1307 | +#define AM33XX_ES2_0_VDD_MPU_OPP50_FREQ 300000000 | |
1308 | +#define AM33XX_ES2_0_VDD_MPU_OPP100_FREQ 600000000 | |
1309 | +#define AM33XX_ES2_0_VDD_MPU_OPP120_FREQ 720000000 | |
1310 | +#define AM33XX_ES2_0_VDD_MPU_OPPTURBO_FREQ 800000000 | |
1311 | +#define AM33XX_ES2_0_VDD_MPU_OPPNITRO_FREQ 1000000000 | |
1312 | + | |
1313 | +static struct am33xx_sr_opp_data sr1_opp_data_2_0[] = { | |
1314 | + { | |
1315 | + .efuse_offs = AM33XX_SR1_OPP50_CNTRL_OFFSET, | |
1316 | + .e2v_gain = 0, | |
1317 | + .err_minlimit = AM33XX_SR1_OPP50_EVM_ERR_MIN_LIMIT, | |
1318 | + .err_maxlimit = AM33XX_SR1_OPP50_ERR_MAX_LIMIT, | |
1319 | + .err_weight = AM33XX_SR1_OPP50_ERR_WEIGHT, | |
1320 | + .margin = AM33XX_SR1_OPP50_MARGIN, | |
1321 | + .nominal_volt = AM33XX_ES2_0_VDD_MPU_OPP50_UV, | |
1322 | + .frequency = AM33XX_ES2_0_VDD_MPU_OPP50_FREQ, | |
1323 | + }, | |
1324 | + { | |
1325 | + .efuse_offs = AM33XX_SR1_OPP100_CNTRL_OFFSET, | |
1326 | + .e2v_gain = 0, | |
1327 | + .err_minlimit = AM33XX_SR1_OPP100_EVM_ERR_MIN_LIMIT, | |
1328 | + .err_maxlimit = AM33XX_SR1_OPP100_ERR_MAX_LIMIT, | |
1329 | + .err_weight = AM33XX_SR1_OPP100_ERR_WEIGHT, | |
1330 | + .margin = AM33XX_SR1_OPP100_MARGIN, | |
1331 | + .nominal_volt = AM33XX_ES2_0_VDD_MPU_OPP100_UV, | |
1332 | + .frequency = AM33XX_ES2_0_VDD_MPU_OPP100_FREQ, | |
1333 | + }, | |
1334 | + { | |
1335 | + .efuse_offs = AM33XX_SR1_OPP120_CNTRL_OFFSET, | |
1336 | + .e2v_gain = 0, | |
1337 | + .err_minlimit = AM33XX_SR1_OPP120_EVM_ERR_MIN_LIMIT, | |
1338 | + .err_maxlimit = AM33XX_SR1_OPP120_ERR_MAX_LIMIT, | |
1339 | + .err_weight = AM33XX_SR1_OPP120_ERR_WEIGHT, | |
1340 | + .margin = AM33XX_SR1_OPP120_MARGIN, | |
1341 | + .nominal_volt = AM33XX_ES2_0_VDD_MPU_OPP120_UV, | |
1342 | + .frequency = AM33XX_ES2_0_VDD_MPU_OPP120_FREQ, | |
1343 | + }, | |
1344 | + { | |
1345 | + .efuse_offs = AM33XX_SR1_OPPTURBO_CNTRL_OFFSET, | |
1346 | + .e2v_gain = 0, | |
1347 | + .err_minlimit = AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT, | |
1348 | + .err_maxlimit = AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT, | |
1349 | + .err_weight = AM33XX_SR1_OPPTURBO_ERR_WEIGHT, | |
1350 | + .margin = AM33XX_SR1_OPPTURBO_MARGIN, | |
1351 | + .nominal_volt = AM33XX_ES2_0_VDD_MPU_OPPTURBO_UV, | |
1352 | + .frequency = AM33XX_ES2_0_VDD_MPU_OPPTURBO_FREQ, | |
1353 | + }, | |
1354 | + { | |
1355 | + /* NITRO can use the TURBO data, except for margin */ | |
1356 | + .efuse_offs = AM33XX_SR1_OPPTURBO_CNTRL_OFFSET, | |
1357 | + .e2v_gain = 0, | |
1358 | + .err_minlimit = AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT, | |
1359 | + .err_maxlimit = AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT, | |
1360 | + .err_weight = AM33XX_SR1_OPPTURBO_ERR_WEIGHT, | |
1361 | + .margin = AM33XX_SR1_OPPNITRO_MARGIN, | |
1362 | + .nominal_volt = AM33XX_ES2_0_VDD_MPU_OPPNITRO_UV, | |
1363 | + .frequency = AM33XX_ES2_0_VDD_MPU_OPPNITRO_FREQ, | |
1364 | + }, | |
1365 | +}; | |
1366 | + | |
1309 | 1367 | static struct am33xx_sr_opp_data sr1_opp_data[] = { |
1310 | - { | |
1311 | - .efuse_offs = AM33XX_SR1_OPP50_CNTRL_OFFSET, | |
1312 | - .e2v_gain = AM33XX_SR1_OPP50_EVM_ERR2VOLT_GAIN, | |
1313 | - .err_minlimit = AM33XX_SR1_OPP50_EVM_ERR_MIN_LIMIT, | |
1314 | - .err_maxlimit = AM33XX_SR1_OPP50_ERR_MAX_LIMIT, | |
1315 | - .err_weight = AM33XX_SR1_OPP50_ERR_WEIGHT, | |
1316 | - .margin = AM33XX_SR1_OPP50_MARGIN, | |
1317 | - .nominal_volt = AM33XX_VDD_MPU_OPP50_UV, | |
1318 | - .frequency = AM33XX_VDD_MPU_OPP50_FREQ, | |
1319 | - }, | |
1320 | - { | |
1321 | - .efuse_offs = AM33XX_SR1_OPP100_CNTRL_OFFSET, | |
1322 | - .e2v_gain = AM33XX_SR1_OPP100_EVM_ERR2VOLT_GAIN, | |
1323 | - .err_minlimit = AM33XX_SR1_OPP100_EVM_ERR_MIN_LIMIT, | |
1324 | - .err_maxlimit = AM33XX_SR1_OPP100_ERR_MAX_LIMIT, | |
1325 | - .err_weight = AM33XX_SR1_OPP100_ERR_WEIGHT, | |
1326 | - .margin = AM33XX_SR1_OPP100_MARGIN, | |
1327 | - .nominal_volt = AM33XX_VDD_MPU_OPP100_UV, | |
1328 | - .frequency = AM33XX_VDD_MPU_OPP100_FREQ, | |
1329 | - }, | |
1330 | - { | |
1331 | - .efuse_offs = AM33XX_SR1_OPP120_CNTRL_OFFSET, | |
1332 | - .e2v_gain = AM33XX_SR1_OPP120_EVM_ERR2VOLT_GAIN, | |
1333 | - .err_minlimit = AM33XX_SR1_OPP120_EVM_ERR_MIN_LIMIT, | |
1334 | - .err_maxlimit = AM33XX_SR1_OPP120_ERR_MAX_LIMIT, | |
1335 | - .err_weight = AM33XX_SR1_OPP120_ERR_WEIGHT, | |
1336 | - .margin = AM33XX_SR1_OPP120_MARGIN, | |
1337 | - .nominal_volt = AM33XX_VDD_MPU_OPP120_UV, | |
1338 | - .frequency = AM33XX_VDD_MPU_OPP120_FREQ, | |
1339 | - }, | |
1340 | - { | |
1341 | - .efuse_offs = AM33XX_SR1_OPPTURBO_CNTRL_OFFSET, | |
1342 | - .e2v_gain = AM33XX_SR1_OPPTURBO_EVM_ERR2VOLT_GAIN, | |
1343 | - .err_minlimit = AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT, | |
1344 | - .err_maxlimit = AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT, | |
1345 | - .err_weight = AM33XX_SR1_OPPTURBO_ERR_WEIGHT, | |
1346 | - .margin = AM33XX_SR1_OPPTURBO_MARGIN, | |
1347 | - .nominal_volt = AM33XX_VDD_MPU_OPPTURBO_UV, | |
1348 | - .frequency = AM33XX_VDD_MPU_OPPTURBO_FREQ, | |
1349 | - }, | |
1368 | + { | |
1369 | + .efuse_offs = AM33XX_SR1_OPP50_CNTRL_OFFSET, | |
1370 | + .e2v_gain = 0, | |
1371 | + .err_minlimit = AM33XX_SR1_OPP50_EVM_ERR_MIN_LIMIT, | |
1372 | + .err_maxlimit = AM33XX_SR1_OPP50_ERR_MAX_LIMIT, | |
1373 | + .err_weight = AM33XX_SR1_OPP50_ERR_WEIGHT, | |
1374 | + .margin = AM33XX_SR1_OPP50_MARGIN, | |
1375 | + .nominal_volt = AM33XX_VDD_MPU_OPP50_UV, | |
1376 | + .frequency = AM33XX_VDD_MPU_OPP50_FREQ, | |
1377 | + }, | |
1378 | + { | |
1379 | + .efuse_offs = AM33XX_SR1_OPP100_CNTRL_OFFSET, | |
1380 | + .e2v_gain = 0, | |
1381 | + .err_minlimit = AM33XX_SR1_OPP100_EVM_ERR_MIN_LIMIT, | |
1382 | + .err_maxlimit = AM33XX_SR1_OPP100_ERR_MAX_LIMIT, | |
1383 | + .err_weight = AM33XX_SR1_OPP100_ERR_WEIGHT, | |
1384 | + .margin = AM33XX_SR1_OPP100_MARGIN, | |
1385 | + .nominal_volt = AM33XX_VDD_MPU_OPP100_UV, | |
1386 | + .frequency = AM33XX_VDD_MPU_OPP100_FREQ, | |
1387 | + }, | |
1388 | + { | |
1389 | + .efuse_offs = AM33XX_SR1_OPP120_CNTRL_OFFSET, | |
1390 | + .e2v_gain = 0, | |
1391 | + .err_minlimit = AM33XX_SR1_OPP120_EVM_ERR_MIN_LIMIT, | |
1392 | + .err_maxlimit = AM33XX_SR1_OPP120_ERR_MAX_LIMIT, | |
1393 | + .err_weight = AM33XX_SR1_OPP120_ERR_WEIGHT, | |
1394 | + .margin = AM33XX_SR1_OPP120_MARGIN, | |
1395 | + .nominal_volt = AM33XX_VDD_MPU_OPP120_UV, | |
1396 | + .frequency = AM33XX_VDD_MPU_OPP120_FREQ, | |
1397 | + }, | |
1398 | + { | |
1399 | + .efuse_offs = AM33XX_SR1_OPPTURBO_CNTRL_OFFSET, | |
1400 | + .e2v_gain = 0, | |
1401 | + .err_minlimit = AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT, | |
1402 | + .err_maxlimit = AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT, | |
1403 | + .err_weight = AM33XX_SR1_OPPTURBO_ERR_WEIGHT, | |
1404 | + .margin = AM33XX_SR1_OPPTURBO_MARGIN, | |
1405 | + .nominal_volt = AM33XX_VDD_MPU_OPPTURBO_UV, | |
1406 | + .frequency = AM33XX_VDD_MPU_OPPTURBO_FREQ, | |
1407 | + }, | |
1350 | 1408 | }; |
1351 | 1409 | |
1352 | 1410 | static struct am33xx_sr_opp_data sr0_opp_data[] = { |
1353 | - { | |
1354 | - .efuse_offs = AM33XX_SR0_OPP50_CNTRL_OFFSET, | |
1355 | - .e2v_gain = AM33XX_SR0_OPP50_EVM_ERR2VOLT_GAIN, | |
1356 | - .err_minlimit = AM33XX_SR0_OPP50_EVM_ERR_MIN_LIMIT, | |
1357 | - .err_maxlimit = AM33XX_SR0_OPP50_ERR_MAX_LIMIT, | |
1358 | - .err_weight = AM33XX_SR0_OPP50_ERR_WEIGHT, | |
1359 | - .margin = AM33XX_SR0_OPP50_MARGIN, | |
1360 | - .nominal_volt = AM33XX_VDD_CORE_OPP50_UV, | |
1361 | - }, | |
1362 | - { | |
1363 | - .efuse_offs = AM33XX_SR0_OPP100_CNTRL_OFFSET, | |
1364 | - .e2v_gain = AM33XX_SR0_OPP100_EVM_ERR2VOLT_GAIN, | |
1365 | - .err_minlimit = AM33XX_SR0_OPP100_EVM_ERR_MIN_LIMIT, | |
1366 | - .err_maxlimit = AM33XX_SR0_OPP100_ERR_MAX_LIMIT, | |
1367 | - .err_weight = AM33XX_SR0_OPP100_ERR_WEIGHT, | |
1368 | - .margin = AM33XX_SR0_OPP100_MARGIN, | |
1369 | - .nominal_volt = AM33XX_VDD_CORE_OPP100_UV, | |
1370 | - }, | |
1411 | + { | |
1412 | + .efuse_offs = AM33XX_SR0_OPP50_CNTRL_OFFSET, | |
1413 | + .e2v_gain = 0, | |
1414 | + .err_minlimit = AM33XX_SR0_OPP50_EVM_ERR_MIN_LIMIT, | |
1415 | + .err_maxlimit = AM33XX_SR0_OPP50_ERR_MAX_LIMIT, | |
1416 | + .err_weight = AM33XX_SR0_OPP50_ERR_WEIGHT, | |
1417 | + .margin = AM33XX_SR0_OPP50_MARGIN, | |
1418 | + .nominal_volt = AM33XX_VDD_CORE_OPP50_UV, | |
1419 | + }, | |
1420 | + { | |
1421 | + .efuse_offs = AM33XX_SR0_OPP100_CNTRL_OFFSET, | |
1422 | + .e2v_gain = 0, | |
1423 | + .err_minlimit = AM33XX_SR0_OPP100_EVM_ERR_MIN_LIMIT, | |
1424 | + .err_maxlimit = AM33XX_SR0_OPP100_ERR_MAX_LIMIT, | |
1425 | + .err_weight = AM33XX_SR0_OPP100_ERR_WEIGHT, | |
1426 | + .margin = AM33XX_SR0_OPP100_MARGIN, | |
1427 | + .nominal_volt = AM33XX_VDD_CORE_OPP100_UV, | |
1428 | + }, | |
1371 | 1429 | }; |
1372 | 1430 | |
1431 | +static struct am33xx_sr_sdata sr_sensor_data_2_0[] = { | |
1432 | + { | |
1433 | + .sr_opp_data = sr0_opp_data, | |
1434 | + /* note that OPP50 is NOT used in Linux kernel for AM335x */ | |
1435 | + .no_of_opps = 0x2, | |
1436 | + .default_opp = 0x1, | |
1437 | + .senn_mod = 0x1, | |
1438 | + .senp_mod = 0x1, | |
1439 | + }, | |
1440 | + { | |
1441 | + .sr_opp_data = sr1_opp_data_2_0, | |
1442 | + /* the opp data below should be determined | |
1443 | + dynamically during SR probe */ | |
1444 | + .no_of_opps = 0x5, | |
1445 | + .default_opp = 0x3, | |
1446 | + .senn_mod = 0x1, | |
1447 | + .senp_mod = 0x1, | |
1448 | + }, | |
1449 | +}; | |
1450 | + | |
1373 | 1451 | static struct am33xx_sr_sdata sr_sensor_data[] = { |
1374 | - { | |
1375 | - .sr_opp_data = sr0_opp_data, | |
1376 | - /* note that OPP50 is NOT used in Linux kernel for AM335x */ | |
1377 | - .no_of_opps = 0x2, | |
1378 | - .default_opp = 0x1, | |
1379 | - .senn_mod = 0x1, | |
1380 | - .senp_mod = 0x1, | |
1381 | - }, | |
1382 | - { | |
1383 | - .sr_opp_data = sr1_opp_data, | |
1384 | - /* the opp data below should be determined | |
1385 | - dynamically during SR probe */ | |
1386 | - .no_of_opps = 0x4, | |
1387 | - .default_opp = 0x3, | |
1388 | - .senn_mod = 0x1, | |
1389 | - .senp_mod = 0x1, | |
1390 | - }, | |
1452 | + { | |
1453 | + .sr_opp_data = sr0_opp_data, | |
1454 | + /* note that OPP50 is NOT used in Linux kernel for AM335x */ | |
1455 | + .no_of_opps = 0x2, | |
1456 | + .default_opp = 0x1, | |
1457 | + .senn_mod = 0x1, | |
1458 | + .senp_mod = 0x1, | |
1459 | + }, | |
1460 | + { | |
1461 | + .sr_opp_data = sr1_opp_data, | |
1462 | + /* the opp data below should be determined | |
1463 | + dynamically during SR probe */ | |
1464 | + .no_of_opps = 0x4, | |
1465 | + .default_opp = 0x3, | |
1466 | + .senn_mod = 0x1, | |
1467 | + .senp_mod = 0x1, | |
1468 | + }, | |
1391 | 1469 | }; |
1392 | 1470 | |
1393 | 1471 | static struct am33xx_sr_platform_data am33xx_sr_pdata = { |
1394 | - .vd_name[0] = "vdd_core", | |
1395 | - .vd_name[1] = "vdd_mpu", | |
1396 | - .ip_type = 2, | |
1397 | - .irq_delay = 1000, | |
1398 | - .no_of_vds = 2, | |
1399 | - .no_of_sens = ARRAY_SIZE(sr_sensor_data), | |
1400 | - .vstep_size_uv = 12500, | |
1401 | - .enable_on_init = true, | |
1402 | - .sr_sdata = sr_sensor_data, | |
1472 | + .vd_name[0] = "vdd_core", | |
1473 | + .vd_name[1] = "vdd_mpu", | |
1474 | + .ip_type = 2, | |
1475 | + .irq_delay = 1000, | |
1476 | + .no_of_vds = 2, | |
1477 | + .no_of_sens = ARRAY_SIZE(sr_sensor_data), | |
1478 | + .vstep_size_uv = 12500, | |
1479 | + .enable_on_init = true, | |
1480 | + .sr_sdata = sr_sensor_data, | |
1403 | 1481 | }; |
1404 | 1482 | |
1405 | 1483 | static struct resource am33xx_sr_resources[] = { |
1406 | - { | |
1407 | - .name = "smartreflex0", | |
1408 | - .start = AM33XX_SR0_BASE, | |
1409 | - .end = AM33XX_SR0_BASE + SZ_4K - 1, | |
1410 | - .flags = IORESOURCE_MEM, | |
1411 | - }, | |
1412 | - { | |
1413 | - .name = "smartreflex0", | |
1414 | - .start = AM33XX_IRQ_SMARTREFLEX0, | |
1415 | - .end = AM33XX_IRQ_SMARTREFLEX0, | |
1416 | - .flags = IORESOURCE_IRQ, | |
1417 | - }, | |
1418 | - { | |
1419 | - .name = "smartreflex1", | |
1420 | - .start = AM33XX_SR1_BASE, | |
1421 | - .end = AM33XX_SR1_BASE + SZ_4K - 1, | |
1422 | - .flags = IORESOURCE_MEM, | |
1423 | - }, | |
1424 | - { | |
1425 | - .name = "smartreflex1", | |
1426 | - .start = AM33XX_IRQ_SMARTREFLEX1, | |
1427 | - .end = AM33XX_IRQ_SMARTREFLEX1, | |
1428 | - .flags = IORESOURCE_IRQ, | |
1429 | - }, | |
1484 | + { | |
1485 | + .name = "smartreflex0", | |
1486 | + .start = AM33XX_SR0_BASE, | |
1487 | + .end = AM33XX_SR0_BASE + SZ_4K - 1, | |
1488 | + .flags = IORESOURCE_MEM, | |
1489 | + }, | |
1490 | + { | |
1491 | + .name = "smartreflex0", | |
1492 | + .start = AM33XX_IRQ_SMARTREFLEX0, | |
1493 | + .end = AM33XX_IRQ_SMARTREFLEX0, | |
1494 | + .flags = IORESOURCE_IRQ, | |
1495 | + }, | |
1496 | + { | |
1497 | + .name = "smartreflex1", | |
1498 | + .start = AM33XX_SR1_BASE, | |
1499 | + .end = AM33XX_SR1_BASE + SZ_4K - 1, | |
1500 | + .flags = IORESOURCE_MEM, | |
1501 | + }, | |
1502 | + { | |
1503 | + .name = "smartreflex1", | |
1504 | + .start = AM33XX_IRQ_SMARTREFLEX1, | |
1505 | + .end = AM33XX_IRQ_SMARTREFLEX1, | |
1506 | + .flags = IORESOURCE_IRQ, | |
1507 | + }, | |
1430 | 1508 | }; |
1431 | 1509 | |
1432 | 1510 | /* VCORE for SR regulator init */ |
1433 | 1511 | static struct platform_device am33xx_sr_device = { |
1434 | - .name = "smartreflex", | |
1435 | - .id = -1, | |
1436 | - .num_resources = ARRAY_SIZE(am33xx_sr_resources), | |
1437 | - .resource = am33xx_sr_resources, | |
1438 | - .dev = { | |
1439 | - .platform_data = &am33xx_sr_pdata, | |
1440 | - }, | |
1512 | + .name = "smartreflex", | |
1513 | + .id = -1, | |
1514 | + .num_resources = ARRAY_SIZE(am33xx_sr_resources), | |
1515 | + .resource = am33xx_sr_resources, | |
1516 | + .dev = { | |
1517 | + .platform_data = &am33xx_sr_pdata, | |
1518 | + }, | |
1441 | 1519 | }; |
1442 | 1520 | |
1443 | 1521 | void __init am33xx_sr_init(void) |
1444 | 1522 | { |
1445 | - /* For beaglebone, update voltage step size and related parameters | |
1446 | - appropriately. All other AM33XX platforms are good with the | |
1447 | - structure defaults as initialized above. */ | |
1448 | - if ((am33xx_evmid == BEAGLE_BONE_OLD) || | |
1449 | - (am33xx_evmid == BEAGLE_BONE_A3)) { | |
1450 | - printk(KERN_ERR "address of pdata = %08x\n", (u32)&am33xx_sr_pdata); | |
1451 | - am33xx_sr_pdata.vstep_size_uv = 25000; | |
1452 | - /* CORE */ | |
1453 | - sr0_opp_data[0].e2v_gain = AM33XX_SR0_OPP50_BB_ERR2VOLT_GAIN; | |
1454 | - sr0_opp_data[0].err_minlimit = AM33XX_SR0_OPP50_BB_ERR_MIN_LIMIT; | |
1455 | - sr0_opp_data[1].e2v_gain = AM33XX_SR0_OPP100_BB_ERR2VOLT_GAIN; | |
1456 | - sr0_opp_data[1].err_minlimit = AM33XX_SR0_OPP100_BB_ERR_MIN_LIMIT; | |
1457 | - /* MPU */ | |
1458 | - sr1_opp_data[0].e2v_gain = AM33XX_SR1_OPP50_BB_ERR2VOLT_GAIN; | |
1459 | - sr1_opp_data[0].err_minlimit = AM33XX_SR1_OPP50_BB_ERR_MIN_LIMIT; | |
1460 | - sr1_opp_data[1].e2v_gain = AM33XX_SR1_OPP100_BB_ERR2VOLT_GAIN; | |
1461 | - sr1_opp_data[1].err_minlimit = AM33XX_SR1_OPP100_BB_ERR_MIN_LIMIT; | |
1462 | - sr1_opp_data[2].e2v_gain = AM33XX_SR1_OPP120_BB_ERR2VOLT_GAIN; | |
1463 | - sr1_opp_data[2].err_minlimit = AM33XX_SR1_OPP120_BB_ERR_MIN_LIMIT; | |
1464 | - sr1_opp_data[3].e2v_gain = AM33XX_SR1_OPPTURBO_BB_ERR2VOLT_GAIN; | |
1465 | - sr1_opp_data[3].err_minlimit = AM33XX_SR1_OPPTURBO_BB_ERR_MIN_LIMIT; | |
1466 | - } | |
1523 | + if (omap_rev() != AM335X_REV_ES1_0) | |
1524 | + am33xx_sr_pdata.sr_sdata = sr_sensor_data_2_0; | |
1467 | 1525 | |
1468 | - if (platform_device_register(&am33xx_sr_device)) | |
1469 | - printk(KERN_ERR "failed to register am33xx_sr device\n"); | |
1470 | - else | |
1471 | - printk(KERN_INFO "registered am33xx_sr device\n"); | |
1526 | + /* For beaglebone, update voltage step size and related parameters | |
1527 | + appropriately. All other AM33XX platforms are good with the | |
1528 | + structure defaults as initialized above. */ | |
1529 | + if ((am33xx_evmid == BEAGLE_BONE_OLD) || | |
1530 | + (am33xx_evmid == BEAGLE_BONE_A3)) { | |
1531 | + printk(KERN_ERR "address of pdata = %08x\n", | |
1532 | + (u32)&am33xx_sr_pdata); | |
1533 | + | |
1534 | + am33xx_sr_pdata.vstep_size_uv = 25000; | |
1535 | + } | |
1536 | + | |
1537 | + if (platform_device_register(&am33xx_sr_device)) | |
1538 | + printk(KERN_ERR "failed to register am33xx_sr device\n"); | |
1539 | + else | |
1540 | + printk(KERN_INFO "registered am33xx_sr device\n"); | |
1472 | 1541 | } |
1473 | 1542 | #else |
1474 | 1543 | inline void am33xx_sr_init(void) {} |
arch/arm/plat-omap/include/plat/smartreflex.h
... | ... | @@ -238,14 +238,14 @@ |
238 | 238 | |
239 | 239 | #ifdef CONFIG_AM33XX_SMARTREFLEX |
240 | 240 | |
241 | -#define SR_CORE (0) | |
242 | -#define SR_MPU (1) | |
241 | +#define SR_CORE (0) | |
242 | +#define SR_MPU (1) | |
243 | 243 | #define SRCLKLENGTH_125MHZ_SYSCLK (0x78 << 12) |
244 | -#define GAIN_MAXLIMIT (16) | |
245 | -#define R_MAXLIMIT (256) | |
246 | -#define MAX_SENSORS 2 | |
244 | +#define GAIN_MAXLIMIT (16) | |
245 | +#define R_MAXLIMIT (256) | |
246 | +#define MAX_SENSORS (2) | |
247 | 247 | /* GG: eventually this should be determined at runtime */ |
248 | -#define AM33XX_OPP_COUNT 4 | |
248 | +#define AM33XX_OPP_COUNT (5) | |
249 | 249 | |
250 | 250 | /** |
251 | 251 | * struct am33xx_sr_opp_data - Smartreflex data per OPP |
252 | 252 | |
... | ... | @@ -264,17 +264,17 @@ |
264 | 264 | */ |
265 | 265 | struct am33xx_sr_opp_data { |
266 | 266 | u32 efuse_offs; |
267 | - u32 nvalue; | |
268 | - u32 adj_nvalue; | |
267 | + u32 nvalue; | |
268 | + u32 adj_nvalue; | |
269 | 269 | s32 e2v_gain; |
270 | 270 | u32 err_weight; |
271 | 271 | u32 err_minlimit; |
272 | 272 | u32 err_maxlimit; |
273 | - s32 margin; | |
274 | - u32 nominal_volt; /* nominal_volt and frequency may be removed | |
275 | - once am33xx voltdm layer works */ | |
276 | - u32 frequency; | |
277 | - u32 opp_id; | |
273 | + s32 margin; | |
274 | + u32 nominal_volt; /* nominal_volt and frequency may be removed | |
275 | + once am33xx voltdm layer works */ | |
276 | + u32 frequency; | |
277 | + u32 opp_id; | |
278 | 278 | }; |
279 | 279 | |
280 | 280 | /** |
281 | 281 | |
282 | 282 | |
283 | 283 | |
284 | 284 | |
285 | 285 | |
286 | 286 | |
287 | 287 | |
288 | 288 | |
289 | 289 | |
290 | 290 | |
... | ... | @@ -290,50 +290,54 @@ |
290 | 290 | */ |
291 | 291 | struct am33xx_sr_sdata { |
292 | 292 | struct am33xx_sr_opp_data *sr_opp_data; |
293 | - u32 no_of_opps; | |
294 | - u32 default_opp; | |
293 | + u32 no_of_opps; | |
294 | + u32 default_opp; | |
295 | 295 | u32 senn_mod; |
296 | 296 | u32 senp_mod; |
297 | 297 | }; |
298 | 298 | |
299 | 299 | struct am33xx_sr_sensor { |
300 | - u32 sr_id; | |
300 | + u32 sr_id; | |
301 | 301 | u32 irq; |
302 | 302 | u32 irq_status; |
303 | 303 | u32 senn_en; |
304 | 304 | u32 senp_en; |
305 | 305 | char *name; |
306 | - char *reg_name; | |
306 | + char *reg_name; | |
307 | 307 | void __iomem *base; |
308 | - int init_volt_mv; | |
309 | - int curr_opp; | |
310 | - u32 no_of_opps; | |
311 | - struct delayed_work work_reenable; | |
312 | - struct regulator *reg; | |
313 | - struct am33xx_sr_opp_data opp_data[AM33XX_OPP_COUNT]; | |
308 | + int init_volt_mv; | |
309 | + int curr_opp; | |
310 | + u32 no_of_opps; | |
311 | + int state; | |
312 | + s8 avg_error_nom; | |
313 | + int saved_volt; | |
314 | + struct delayed_work work_reenable; | |
315 | + struct regulator *reg; | |
316 | + struct am33xx_sr_opp_data opp_data[AM33XX_OPP_COUNT]; | |
314 | 317 | struct clk *fck; |
315 | - struct voltagedomain *voltdm; | |
316 | - struct omap_volt_data *volt_data; | |
318 | + struct voltagedomain *voltdm; | |
319 | + struct omap_volt_data *volt_data; | |
317 | 320 | }; |
318 | 321 | |
319 | 322 | struct am33xx_sr { |
320 | - u32 autocomp_active; | |
323 | + bool autocomp_active; | |
324 | + bool is_suspended; | |
321 | 325 | u32 sens_per_vd; |
322 | - u32 no_of_sens; | |
323 | - u32 no_of_vds; | |
326 | + u32 no_of_sens; | |
327 | + u32 no_of_vds; | |
324 | 328 | u32 ip_type; |
325 | - u32 irq_delay; | |
326 | - u32 disabled_by_user; | |
329 | + u32 irq_delay; | |
330 | + bool disabled_by_user; | |
327 | 331 | int uvoltage_step_size; |
328 | - char *res_name[MAX_SENSORS]; | |
332 | + char *res_name[MAX_SENSORS]; | |
329 | 333 | #ifdef CONFIG_CPU_FREQ |
330 | 334 | struct notifier_block freq_transition; |
331 | 335 | #endif |
332 | - /*struct work_struct work;*/ | |
333 | - struct delayed_work work; | |
336 | + struct delayed_work work; | |
334 | 337 | struct sr_platform_data *sr_data; |
335 | 338 | struct am33xx_sr_sensor sen[MAX_SENSORS]; |
336 | 339 | struct platform_device *pdev; |
340 | + struct list_head node; | |
337 | 341 | }; |
338 | 342 | |
339 | 343 | /** |
... | ... | @@ -354,7 +358,7 @@ |
354 | 358 | struct am33xx_sr_sdata *sr_sdata; |
355 | 359 | char *vd_name[2]; |
356 | 360 | u32 ip_type; |
357 | - u32 irq_delay; | |
361 | + u32 irq_delay; | |
358 | 362 | u32 no_of_vds; |
359 | 363 | u32 no_of_sens; |
360 | 364 | u32 vstep_size_uv; |