Merge branch 'kirkwood/boards' of git://git.infradead.org/users/jcooper/linux into...
[deliverable/linux.git] / drivers / staging / tidspbridge / core / tiomap3430_pwr.c
1 /*
2 * tiomap_pwr.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Implementation of DSP wake/sleep routines.
7 *
8 * Copyright (C) 2007-2008 Texas Instruments, Inc.
9 *
10 * This package is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 */
18
19 /* ----------------------------------- Host OS */
20 #include <dspbridge/host_os.h>
21
22 #include <linux/platform_data/dsp-omap.h>
23
24 /* ----------------------------------- DSP/BIOS Bridge */
25 #include <dspbridge/dbdefs.h>
26 #include <dspbridge/drv.h>
27 #include <dspbridge/io_sm.h>
28
29 /* ----------------------------------- Platform Manager */
30 #include <dspbridge/brddefs.h>
31 #include <dspbridge/dev.h>
32 #include <dspbridge/io.h>
33
34 /* ------------------------------------ Hardware Abstraction Layer */
35 #include <hw_defs.h>
36 #include <hw_mmu.h>
37
38 #include <dspbridge/pwr.h>
39
40 /* ----------------------------------- Bridge Driver */
41 #include <dspbridge/dspdeh.h>
42 #include <dspbridge/wdt.h>
43
44 /* ----------------------------------- specific to this file */
45 #include "_tiomap.h"
46 #include "_tiomap_pwr.h"
47 #include <mach-omap2/prm-regbits-34xx.h>
48 #include <mach-omap2/cm-regbits-34xx.h>
49
50 #define PWRSTST_TIMEOUT 200
51
52 /*
53 * ======== handle_constraints_set ========
54 * Sets new DSP constraint
55 */
56 int handle_constraints_set(struct bridge_dev_context *dev_context,
57 void *pargs)
58 {
59 #ifdef CONFIG_TIDSPBRIDGE_DVFS
60 u32 *constraint_val;
61 struct omap_dsp_platform_data *pdata =
62 omap_dspbridge_dev->dev.platform_data;
63
64 constraint_val = (u32 *) (pargs);
65 /* Read the target value requested by DSP */
66 dev_dbg(bridge, "OPP: %s opp requested = 0x%x\n", __func__,
67 (u32) *(constraint_val + 1));
68
69 /* Set the new opp value */
70 if (pdata->dsp_set_min_opp)
71 (*pdata->dsp_set_min_opp) ((u32) *(constraint_val + 1));
72 #endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
73 return 0;
74 }
75
76 /*
77 * ======== handle_hibernation_from_dsp ========
78 * Handle Hibernation requested from DSP
79 */
80 int handle_hibernation_from_dsp(struct bridge_dev_context *dev_context)
81 {
82 int status = 0;
83 #ifdef CONFIG_PM
84 u16 timeout = PWRSTST_TIMEOUT / 10;
85 u32 pwr_state;
86 #ifdef CONFIG_TIDSPBRIDGE_DVFS
87 u32 opplevel;
88 struct io_mgr *hio_mgr;
89 #endif
90 struct omap_dsp_platform_data *pdata =
91 omap_dspbridge_dev->dev.platform_data;
92
93 pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD, OMAP2_PM_PWSTST) &
94 OMAP_POWERSTATEST_MASK;
95 /* Wait for DSP to move into OFF state */
96 while ((pwr_state != PWRDM_POWER_OFF) && --timeout) {
97 if (msleep_interruptible(10)) {
98 pr_err("Waiting for DSP OFF mode interrupted\n");
99 return -EPERM;
100 }
101 pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
102 OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
103 }
104 if (timeout == 0) {
105 pr_err("%s: Timed out waiting for DSP off mode\n", __func__);
106 status = -ETIMEDOUT;
107 return status;
108 } else {
109
110 /* Save mailbox settings */
111 omap_mbox_save_ctx(dev_context->mbox);
112
113 /* Turn off DSP Peripheral clocks and DSP Load monitor timer */
114 status = dsp_clock_disable_all(dev_context->dsp_per_clks);
115
116 /* Disable wdt on hibernation. */
117 dsp_wdt_enable(false);
118
119 if (!status) {
120 /* Update the Bridger Driver state */
121 dev_context->brd_state = BRD_DSP_HIBERNATION;
122 #ifdef CONFIG_TIDSPBRIDGE_DVFS
123 status =
124 dev_get_io_mgr(dev_context->dev_obj, &hio_mgr);
125 if (!hio_mgr) {
126 status = DSP_EHANDLE;
127 return status;
128 }
129 io_sh_msetting(hio_mgr, SHM_GETOPP, &opplevel);
130
131 /*
132 * Set the OPP to low level before moving to OFF
133 * mode
134 */
135 if (pdata->dsp_set_min_opp)
136 (*pdata->dsp_set_min_opp) (VDD1_OPP1);
137 status = 0;
138 #endif /* CONFIG_TIDSPBRIDGE_DVFS */
139 }
140 }
141 #endif
142 return status;
143 }
144
145 /*
146 * ======== sleep_dsp ========
147 * Put DSP in low power consuming state.
148 */
149 int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd,
150 void *pargs)
151 {
152 int status = 0;
153 #ifdef CONFIG_PM
154 #ifdef CONFIG_TIDSPBRIDGE_NTFY_PWRERR
155 struct deh_mgr *hdeh_mgr;
156 #endif /* CONFIG_TIDSPBRIDGE_NTFY_PWRERR */
157 u16 timeout = PWRSTST_TIMEOUT / 10;
158 u32 pwr_state, target_pwr_state;
159 struct omap_dsp_platform_data *pdata =
160 omap_dspbridge_dev->dev.platform_data;
161
162 /* Check if sleep code is valid */
163 if ((dw_cmd != PWR_DEEPSLEEP) && (dw_cmd != PWR_EMERGENCYDEEPSLEEP))
164 return -EINVAL;
165
166 switch (dev_context->brd_state) {
167 case BRD_RUNNING:
168 omap_mbox_save_ctx(dev_context->mbox);
169 if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
170 sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
171 dev_dbg(bridge, "PM: %s - sent hibernate cmd to DSP\n",
172 __func__);
173 target_pwr_state = PWRDM_POWER_OFF;
174 } else {
175 sm_interrupt_dsp(dev_context, MBX_PM_DSPRETENTION);
176 target_pwr_state = PWRDM_POWER_RET;
177 }
178 break;
179 case BRD_RETENTION:
180 omap_mbox_save_ctx(dev_context->mbox);
181 if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
182 sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
183 target_pwr_state = PWRDM_POWER_OFF;
184 } else
185 return 0;
186 break;
187 case BRD_HIBERNATION:
188 case BRD_DSP_HIBERNATION:
189 /* Already in Hibernation, so just return */
190 dev_dbg(bridge, "PM: %s - DSP already in hibernation\n",
191 __func__);
192 return 0;
193 case BRD_STOPPED:
194 dev_dbg(bridge, "PM: %s - Board in STOP state\n", __func__);
195 return 0;
196 default:
197 dev_dbg(bridge, "PM: %s - Bridge in Illegal state\n", __func__);
198 return -EPERM;
199 }
200
201 /* Get the PRCM DSP power domain status */
202 pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD, OMAP2_PM_PWSTST) &
203 OMAP_POWERSTATEST_MASK;
204
205 /* Wait for DSP to move into target power state */
206 while ((pwr_state != target_pwr_state) && --timeout) {
207 if (msleep_interruptible(10)) {
208 pr_err("Waiting for DSP to Suspend interrupted\n");
209 return -EPERM;
210 }
211 pwr_state = (*pdata->dsp_prm_read)(OMAP3430_IVA2_MOD,
212 OMAP2_PM_PWSTST) & OMAP_POWERSTATEST_MASK;
213 }
214
215 if (!timeout) {
216 pr_err("%s: Timed out waiting for DSP off mode, state %x\n",
217 __func__, pwr_state);
218 #ifdef CONFIG_TIDSPBRIDGE_NTFY_PWRERR
219 dev_get_deh_mgr(dev_context->dev_obj, &hdeh_mgr);
220 bridge_deh_notify(hdeh_mgr, DSP_PWRERROR, 0);
221 #endif /* CONFIG_TIDSPBRIDGE_NTFY_PWRERR */
222 return -ETIMEDOUT;
223 } else {
224 /* Update the Bridger Driver state */
225 if (dsp_test_sleepstate == PWRDM_POWER_OFF)
226 dev_context->brd_state = BRD_HIBERNATION;
227 else
228 dev_context->brd_state = BRD_RETENTION;
229
230 /* Disable wdt on hibernation. */
231 dsp_wdt_enable(false);
232
233 /* Turn off DSP Peripheral clocks */
234 status = dsp_clock_disable_all(dev_context->dsp_per_clks);
235 if (status)
236 return status;
237 #ifdef CONFIG_TIDSPBRIDGE_DVFS
238 else if (target_pwr_state == PWRDM_POWER_OFF) {
239 /*
240 * Set the OPP to low level before moving to OFF mode
241 */
242 if (pdata->dsp_set_min_opp)
243 (*pdata->dsp_set_min_opp) (VDD1_OPP1);
244 }
245 #endif /* CONFIG_TIDSPBRIDGE_DVFS */
246 }
247 #endif /* CONFIG_PM */
248 return status;
249 }
250
251 /*
252 * ======== wake_dsp ========
253 * Wake up DSP from sleep.
254 */
255 int wake_dsp(struct bridge_dev_context *dev_context, void *pargs)
256 {
257 int status = 0;
258 #ifdef CONFIG_PM
259
260 /* Check the board state, if it is not 'SLEEP' then return */
261 if (dev_context->brd_state == BRD_RUNNING ||
262 dev_context->brd_state == BRD_STOPPED) {
263 /* The Device is in 'RET' or 'OFF' state and Bridge state is not
264 * 'SLEEP', this means state inconsistency, so return */
265 return 0;
266 }
267
268 /* Send a wakeup message to DSP */
269 sm_interrupt_dsp(dev_context, MBX_PM_DSPWAKEUP);
270
271 /* Set the device state to RUNNIG */
272 dev_context->brd_state = BRD_RUNNING;
273 #endif /* CONFIG_PM */
274 return status;
275 }
276
277 /*
278 * ======== dsp_peripheral_clk_ctrl ========
279 * Enable/Disable the DSP peripheral clocks as needed..
280 */
281 int dsp_peripheral_clk_ctrl(struct bridge_dev_context *dev_context,
282 void *pargs)
283 {
284 u32 ext_clk = 0;
285 u32 ext_clk_id = 0;
286 u32 ext_clk_cmd = 0;
287 u32 clk_id_index = MBX_PM_MAX_RESOURCES;
288 u32 tmp_index;
289 u32 dsp_per_clks_before;
290 int status = 0;
291
292 dsp_per_clks_before = dev_context->dsp_per_clks;
293
294 ext_clk = (u32) *((u32 *) pargs);
295 ext_clk_id = ext_clk & MBX_PM_CLK_IDMASK;
296
297 /* process the power message -- TODO, keep it in a separate function */
298 for (tmp_index = 0; tmp_index < MBX_PM_MAX_RESOURCES; tmp_index++) {
299 if (ext_clk_id == bpwr_clkid[tmp_index]) {
300 clk_id_index = tmp_index;
301 break;
302 }
303 }
304 /* TODO -- Assert may be a too hard restriction here.. May be we should
305 * just return with failure when the CLK ID does not match */
306 if (clk_id_index == MBX_PM_MAX_RESOURCES) {
307 /* return with a more meaningfull error code */
308 return -EPERM;
309 }
310 ext_clk_cmd = (ext_clk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
311 switch (ext_clk_cmd) {
312 case BPWR_DISABLE_CLOCK:
313 status = dsp_clk_disable(bpwr_clks[clk_id_index].clk);
314 dsp_clk_wakeup_event_ctrl(bpwr_clks[clk_id_index].clk_id,
315 false);
316 if (!status) {
317 (dev_context->dsp_per_clks) &=
318 (~((u32) (1 << bpwr_clks[clk_id_index].clk)));
319 }
320 break;
321 case BPWR_ENABLE_CLOCK:
322 status = dsp_clk_enable(bpwr_clks[clk_id_index].clk);
323 dsp_clk_wakeup_event_ctrl(bpwr_clks[clk_id_index].clk_id, true);
324 if (!status)
325 (dev_context->dsp_per_clks) |=
326 (1 << bpwr_clks[clk_id_index].clk);
327 break;
328 default:
329 dev_dbg(bridge, "%s: Unsupported CMD\n", __func__);
330 /* unsupported cmd */
331 /* TODO -- provide support for AUTOIDLE Enable/Disable
332 * commands */
333 }
334 return status;
335 }
336
337 /*
338 * ========pre_scale_dsp========
339 * Sends prescale notification to DSP
340 *
341 */
342 int pre_scale_dsp(struct bridge_dev_context *dev_context, void *pargs)
343 {
344 #ifdef CONFIG_TIDSPBRIDGE_DVFS
345 u32 level;
346 u32 voltage_domain;
347
348 voltage_domain = *((u32 *) pargs);
349 level = *((u32 *) pargs + 1);
350
351 dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
352 __func__, voltage_domain, level);
353 if ((dev_context->brd_state == BRD_HIBERNATION) ||
354 (dev_context->brd_state == BRD_RETENTION) ||
355 (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
356 dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n");
357 return 0;
358 } else if ((dev_context->brd_state == BRD_RUNNING)) {
359 /* Send a prenotificatio to DSP */
360 dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__);
361 sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY);
362 return 0;
363 } else {
364 return -EPERM;
365 }
366 #endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
367 return 0;
368 }
369
370 /*
371 * ========post_scale_dsp========
372 * Sends postscale notification to DSP
373 *
374 */
375 int post_scale_dsp(struct bridge_dev_context *dev_context,
376 void *pargs)
377 {
378 int status = 0;
379 #ifdef CONFIG_TIDSPBRIDGE_DVFS
380 u32 level;
381 u32 voltage_domain;
382 struct io_mgr *hio_mgr;
383
384 status = dev_get_io_mgr(dev_context->dev_obj, &hio_mgr);
385 if (!hio_mgr)
386 return -EFAULT;
387
388 voltage_domain = *((u32 *) pargs);
389 level = *((u32 *) pargs + 1);
390 dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
391 __func__, voltage_domain, level);
392 if ((dev_context->brd_state == BRD_HIBERNATION) ||
393 (dev_context->brd_state == BRD_RETENTION) ||
394 (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
395 /* Update the OPP value in shared memory */
396 io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
397 dev_dbg(bridge, "OPP: %s IVA in sleep. Wrote to shm\n",
398 __func__);
399 } else if ((dev_context->brd_state == BRD_RUNNING)) {
400 /* Update the OPP value in shared memory */
401 io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
402 /* Send a post notification to DSP */
403 sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_POSTNOTIFY);
404 dev_dbg(bridge, "OPP: %s wrote to shm. Sent post notification "
405 "to DSP\n", __func__);
406 } else {
407 status = -EPERM;
408 }
409 #endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
410 return status;
411 }
412
413 void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
414 {
415 struct cfg_hostres *resources;
416 int status = 0;
417 u32 iva2_grpsel;
418 u32 mpu_grpsel;
419 struct dev_object *hdev_object = NULL;
420 struct bridge_dev_context *bridge_context = NULL;
421
422 hdev_object = (struct dev_object *)drv_get_first_dev_object();
423 if (!hdev_object)
424 return;
425
426 status = dev_get_bridge_context(hdev_object, &bridge_context);
427 if (!bridge_context)
428 return;
429
430 resources = bridge_context->resources;
431 if (!resources)
432 return;
433
434 switch (clock_id) {
435 case BPWR_GP_TIMER5:
436 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
437 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
438 if (enable) {
439 iva2_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
440 mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
441 } else {
442 mpu_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
443 iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
444 }
445 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
446 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
447 break;
448 case BPWR_GP_TIMER6:
449 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
450 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
451 if (enable) {
452 iva2_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
453 mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
454 } else {
455 mpu_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
456 iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
457 }
458 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
459 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
460 break;
461 case BPWR_GP_TIMER7:
462 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
463 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
464 if (enable) {
465 iva2_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
466 mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
467 } else {
468 mpu_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
469 iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
470 }
471 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
472 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
473 break;
474 case BPWR_GP_TIMER8:
475 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
476 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
477 if (enable) {
478 iva2_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
479 mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
480 } else {
481 mpu_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
482 iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
483 }
484 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
485 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
486 break;
487 case BPWR_MCBSP1:
488 iva2_grpsel = readl(resources->core_pm_base + 0xA8);
489 mpu_grpsel = readl(resources->core_pm_base + 0xA4);
490 if (enable) {
491 iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
492 mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
493 } else {
494 mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
495 iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
496 }
497 writel(iva2_grpsel, resources->core_pm_base + 0xA8);
498 writel(mpu_grpsel, resources->core_pm_base + 0xA4);
499 break;
500 case BPWR_MCBSP2:
501 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
502 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
503 if (enable) {
504 iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
505 mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
506 } else {
507 mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
508 iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
509 }
510 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
511 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
512 break;
513 case BPWR_MCBSP3:
514 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
515 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
516 if (enable) {
517 iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
518 mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
519 } else {
520 mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
521 iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
522 }
523 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
524 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
525 break;
526 case BPWR_MCBSP4:
527 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
528 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
529 if (enable) {
530 iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
531 mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
532 } else {
533 mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
534 iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
535 }
536 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
537 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
538 break;
539 case BPWR_MCBSP5:
540 iva2_grpsel = readl(resources->per_pm_base + 0xA8);
541 mpu_grpsel = readl(resources->per_pm_base + 0xA4);
542 if (enable) {
543 iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
544 mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
545 } else {
546 mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
547 iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
548 }
549 writel(iva2_grpsel, resources->per_pm_base + 0xA8);
550 writel(mpu_grpsel, resources->per_pm_base + 0xA4);
551 break;
552 }
553 }
This page took 0.042216 seconds and 5 git commands to generate.