/** * omap_hsi_wakeup - Prepare HSI for wakeup from suspend mode (RET/OFF) * * Return value :* -ENODEV if HSI platform device or HSI controller or CAWAKE * Padconf has not been found * * -EPERM if HSI is not allowed to wakeup the platform. * * else 0. */ int omap_hsi_wakeup(void) { struct platform_device *pdev; struct hsi_dev *hsi_ctrl; /* TODO: optimize and call this only once, then store and use result * for subsequent accesses */ pdev = hsi_get_hsi_platform_device(); if (!pdev) return -ENODEV; if (!device_may_wakeup(&pdev->dev)) { dev_info(&pdev->dev, "Modem not allowed to wakeup platform"); return -EPERM; } hsi_ctrl = hsi_get_hsi_controller_data(pdev); if (!hsi_ctrl) return -ENODEV; dev_info(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad"); /* CAWAKE falling or rising edge detected */ hsi_ctrl->hsi_port->cawake_off_event = true; tasklet_hi_schedule(&hsi_ctrl->hsi_port->hsi_tasklet); /* Disable interrupt until Bottom Half has cleared */ /* the IRQ status register */ disable_irq_nosync(hsi_ctrl->hsi_port->irq); return 0; }
/** * omap_hsi_wakeup - Prepare HSI for wakeup from suspend mode (RET/OFF) * * @hsi_port - reference to the HSI port which triggered wakeup. * Range [1, 2] * * Return value : * 0 if HSI tasklet scheduled. * * negative value else. */ int omap_hsi_wakeup(int hsi_port) { static struct platform_device *pdev; static struct hsi_dev *hsi_ctrl; int i; if (!pdev) { pdev = hsi_get_hsi_platform_device(); if (!pdev) return -ENODEV; } if (!device_may_wakeup(&pdev->dev)) { dev_info(&pdev->dev, "Modem not allowed to wakeup platform\n"); return -EPERM; } if (!hsi_ctrl) { hsi_ctrl = hsi_get_hsi_controller_data(pdev); if (!hsi_ctrl) return -ENODEV; } for (i = 0; i < omap_hsi_platform_data.num_ports; i++) { if (omap_hsi_platform_data.ctx->pctx[i].port_number == hsi_port) break; } if (i == omap_hsi_platform_data.num_ports) return -ENODEV; /* Check no other interrupt handler has already scheduled the tasklet */ if (test_and_set_bit(HSI_FLAGS_TASKLET_LOCK, &hsi_ctrl->hsi_port[i].flags)) return -EBUSY; //dev_dbg(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad port " // "%d\n", hsi_port); /* CAWAKE falling or rising edge detected */ hsi_ctrl->hsi_port[i].cawake_off_event = true; tasklet_hi_schedule(&hsi_ctrl->hsi_port[i].hsi_tasklet); /* Disable interrupt until Bottom Half has cleared */ /* the IRQ status register */ disable_irq_nosync(hsi_ctrl->hsi_port[i].irq); return 0; }
/** * omap_hsi_prepare_suspend - Prepare HSI for suspend mode (OFF) * * Return value : -ENODEV if HSI controller has not been found, else 0. * */ int omap_hsi_prepare_suspend(void) { struct platform_device *pdev; struct hsi_dev *hsi_ctrl; pdev = hsi_get_hsi_platform_device(); hsi_ctrl = hsi_get_hsi_controller_data(pdev); if (!hsi_ctrl) return -ENODEV; if (device_may_wakeup(&pdev->dev)) omap_mux_enable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN); else omap_mux_disable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN); return 0; }
/** * omap_hsi_prepare_idle - Prepare HSI for idle to low power * * Return value : -ENODEV if HSI controller has not been found, else 0. * */ int omap_hsi_prepare_idle(void) { struct platform_device *pdev; struct hsi_dev *hsi_ctrl; pdev = hsi_get_hsi_platform_device(); hsi_ctrl = hsi_get_hsi_controller_data(pdev); if (!hsi_ctrl) return -ENODEV; /* If hsi_clocks_disable_channel() is used, it prevents board to */ /* enter sleep, due to the checks of HSI controller status. */ /* This is why we call directly the omap_device_xxx() function here */ hsi_runtime_suspend(hsi_ctrl->dev); omap_device_idle(pdev); return 0; }
/** * omap_hsi_resume_idle - Prepare HSI for wakeup from low power * * Return value :* -ENODEV if HSI platform device or HSI controller or CAWAKE * Padconf has not been found * * -EPERM if HSI is not allowed to wakeup the platform. * * else 0. * */ int omap_hsi_resume_idle(void) { struct platform_device *pdev; struct hsi_dev *hsi_ctrl; u16 val; pdev = hsi_get_hsi_platform_device(); if (!pdev) return -ENODEV; if (!device_may_wakeup(&pdev->dev)) return -EPERM; hsi_ctrl = hsi_get_hsi_controller_data(pdev); if (!hsi_ctrl) return -ENODEV; /* Check for IO pad wakeup */ val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN); if (val == -ENODEV) return val; if (val & OMAP44XX_PADCONF_WAKEUPEVENT0) { dev_dbg(hsi_ctrl->dev, "HSI WAKEUP DETECTED from PADCONF : " "0x%04x\n", val); /* CAWAKE falling or rising edge detected */ hsi_ctrl->hsi_port->cawake_off_event = true; tasklet_hi_schedule(&hsi_ctrl->hsi_port->hsi_tasklet); /* Disable interrupt until Bottom Half has cleared */ /* the IRQ status register */ disable_irq_nosync(hsi_ctrl->hsi_port->irq); } return 0; }
/** * omap_hsi_prepare_suspend - Prepare HSI for suspend mode (OFF) * * Return value : -ENODEV if HSI controller has not been found, else 0. * */ int omap_hsi_prepare_suspend(void) { struct platform_device *pdev; struct hsi_dev *hsi_ctrl; u16 val; pdev = hsi_get_hsi_platform_device(); hsi_ctrl = hsi_get_hsi_controller_data(pdev); if (!hsi_ctrl) return -ENODEV; /* If HSI is enabled, CAWAKE IO wakeup has been disabled and */ /* we don't want to re-enable it here. HSI interrupt shall be */ /* generated normally because HSI HW is ON. */ if (hsi_ctrl->clock_enabled) { dev_info(hsi_ctrl->dev, "Platform Suspend while HSI active\n"); return 0; } /* Check for IO pad wakeup */ val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN); if (val == -ENODEV) return -ENODEV; /* HSI can only wakeup OMAP if CAWAKE is muxed */ if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE) return 0; if (device_may_wakeup(&pdev->dev)) omap_hsi_wakeup_enable(hsi_ctrl, 0); else omap_hsi_wakeup_disable(hsi_ctrl, 0); return 0; }