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 <plat/dsp.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  */
handle_constraints_set(struct bridge_dev_context * dev_context,void * pargs)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  */
handle_hibernation_from_dsp(struct bridge_dev_context * dev_context)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  */
sleep_dsp(struct bridge_dev_context * dev_context,u32 dw_cmd,void * pargs)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  */
wake_dsp(struct bridge_dev_context * dev_context,void * pargs)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  */
dsp_peripheral_clk_ctrl(struct bridge_dev_context * dev_context,void * pargs)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 	/* DBC_ASSERT(clk_id_index < MBX_PM_MAX_RESOURCES); */
307 	if (clk_id_index == MBX_PM_MAX_RESOURCES) {
308 		/* return with a more meaningfull error code */
309 		return -EPERM;
310 	}
311 	ext_clk_cmd = (ext_clk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
312 	switch (ext_clk_cmd) {
313 	case BPWR_DISABLE_CLOCK:
314 		status = dsp_clk_disable(bpwr_clks[clk_id_index].clk);
315 		dsp_clk_wakeup_event_ctrl(bpwr_clks[clk_id_index].clk_id,
316 					  false);
317 		if (!status) {
318 			(dev_context->dsp_per_clks) &=
319 				(~((u32) (1 << bpwr_clks[clk_id_index].clk)));
320 		}
321 		break;
322 	case BPWR_ENABLE_CLOCK:
323 		status = dsp_clk_enable(bpwr_clks[clk_id_index].clk);
324 		dsp_clk_wakeup_event_ctrl(bpwr_clks[clk_id_index].clk_id, true);
325 		if (!status)
326 			(dev_context->dsp_per_clks) |=
327 				(1 << bpwr_clks[clk_id_index].clk);
328 		break;
329 	default:
330 		dev_dbg(bridge, "%s: Unsupported CMD\n", __func__);
331 		/* unsupported cmd */
332 		/* TODO -- provide support for AUTOIDLE Enable/Disable
333 		 * commands */
334 	}
335 	return status;
336 }
337 
338 /*
339  *  ========pre_scale_dsp========
340  *  Sends prescale notification to DSP
341  *
342  */
pre_scale_dsp(struct bridge_dev_context * dev_context,void * pargs)343 int pre_scale_dsp(struct bridge_dev_context *dev_context, void *pargs)
344 {
345 #ifdef CONFIG_TIDSPBRIDGE_DVFS
346 	u32 level;
347 	u32 voltage_domain;
348 
349 	voltage_domain = *((u32 *) pargs);
350 	level = *((u32 *) pargs + 1);
351 
352 	dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
353 		__func__, voltage_domain, level);
354 	if ((dev_context->brd_state == BRD_HIBERNATION) ||
355 	    (dev_context->brd_state == BRD_RETENTION) ||
356 	    (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
357 		dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n");
358 		return 0;
359 	} else if ((dev_context->brd_state == BRD_RUNNING)) {
360 		/* Send a prenotificatio to DSP */
361 		dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__);
362 		sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY);
363 		return 0;
364 	} else {
365 		return -EPERM;
366 	}
367 #endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
368 	return 0;
369 }
370 
371 /*
372  *  ========post_scale_dsp========
373  *  Sends postscale notification to DSP
374  *
375  */
post_scale_dsp(struct bridge_dev_context * dev_context,void * pargs)376 int post_scale_dsp(struct bridge_dev_context *dev_context,
377 							void *pargs)
378 {
379 	int status = 0;
380 #ifdef CONFIG_TIDSPBRIDGE_DVFS
381 	u32 level;
382 	u32 voltage_domain;
383 	struct io_mgr *hio_mgr;
384 
385 	status = dev_get_io_mgr(dev_context->dev_obj, &hio_mgr);
386 	if (!hio_mgr)
387 		return -EFAULT;
388 
389 	voltage_domain = *((u32 *) pargs);
390 	level = *((u32 *) pargs + 1);
391 	dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
392 		__func__, voltage_domain, level);
393 	if ((dev_context->brd_state == BRD_HIBERNATION) ||
394 	    (dev_context->brd_state == BRD_RETENTION) ||
395 	    (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
396 		/* Update the OPP value in shared memory */
397 		io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
398 		dev_dbg(bridge, "OPP: %s IVA in sleep. Wrote to shm\n",
399 			__func__);
400 	} else if ((dev_context->brd_state == BRD_RUNNING)) {
401 		/* Update the OPP value in shared memory */
402 		io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
403 		/* Send a post notification to DSP */
404 		sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_POSTNOTIFY);
405 		dev_dbg(bridge, "OPP: %s wrote to shm. Sent post notification "
406 			"to DSP\n", __func__);
407 	} else {
408 		status = -EPERM;
409 	}
410 #endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */
411 	return status;
412 }
413 
dsp_clk_wakeup_event_ctrl(u32 clock_id,bool enable)414 void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
415 {
416 	struct cfg_hostres *resources;
417 	int status = 0;
418 	u32 iva2_grpsel;
419 	u32 mpu_grpsel;
420 	struct dev_object *hdev_object = NULL;
421 	struct bridge_dev_context *bridge_context = NULL;
422 
423 	hdev_object = (struct dev_object *)drv_get_first_dev_object();
424 	if (!hdev_object)
425 		return;
426 
427 	status = dev_get_bridge_context(hdev_object, &bridge_context);
428 	if (!bridge_context)
429 		return;
430 
431 	resources = bridge_context->resources;
432 	if (!resources)
433 		return;
434 
435 	switch (clock_id) {
436 	case BPWR_GP_TIMER5:
437 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
438 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
439 		if (enable) {
440 			iva2_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
441 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
442 		} else {
443 			mpu_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
444 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
445 		}
446 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
447 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
448 		break;
449 	case BPWR_GP_TIMER6:
450 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
451 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
452 		if (enable) {
453 			iva2_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
454 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
455 		} else {
456 			mpu_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
457 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
458 		}
459 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
460 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
461 		break;
462 	case BPWR_GP_TIMER7:
463 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
464 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
465 		if (enable) {
466 			iva2_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
467 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
468 		} else {
469 			mpu_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
470 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
471 		}
472 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
473 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
474 		break;
475 	case BPWR_GP_TIMER8:
476 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
477 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
478 		if (enable) {
479 			iva2_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
480 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
481 		} else {
482 			mpu_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
483 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
484 		}
485 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
486 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
487 		break;
488 	case BPWR_MCBSP1:
489 		iva2_grpsel = readl(resources->core_pm_base + 0xA8);
490 		mpu_grpsel = readl(resources->core_pm_base + 0xA4);
491 		if (enable) {
492 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
493 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
494 		} else {
495 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
496 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
497 		}
498 		writel(iva2_grpsel, resources->core_pm_base + 0xA8);
499 		writel(mpu_grpsel, resources->core_pm_base + 0xA4);
500 		break;
501 	case BPWR_MCBSP2:
502 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
503 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
504 		if (enable) {
505 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
506 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
507 		} else {
508 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
509 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
510 		}
511 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
512 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
513 		break;
514 	case BPWR_MCBSP3:
515 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
516 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
517 		if (enable) {
518 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
519 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
520 		} else {
521 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
522 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
523 		}
524 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
525 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
526 		break;
527 	case BPWR_MCBSP4:
528 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
529 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
530 		if (enable) {
531 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
532 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
533 		} else {
534 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
535 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
536 		}
537 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
538 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
539 		break;
540 	case BPWR_MCBSP5:
541 		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
542 		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
543 		if (enable) {
544 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
545 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
546 		} else {
547 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
548 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
549 		}
550 		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
551 		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
552 		break;
553 	}
554 }
555