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