/**
* 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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 5
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;
}