/*
 * pwr.c
 *
 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
 *
 * PWR API for controlling DSP power states.
 *
 * Copyright (C) 2005-2006 Texas Instruments, Inc.
 *
 * This package is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*  ----------------------------------- Host OS */
#include <dspbridge/host_os.h>

/*  ----------------------------------- This */
#include <dspbridge/pwr.h>

/*  ----------------------------------- Resource Manager */
#include <dspbridge/devdefs.h>
#include <dspbridge/drv.h>

/*  ----------------------------------- Platform Manager */
#include <dspbridge/dev.h>

/*  ----------------------------------- Link Driver */
#include <dspbridge/dspioctl.h>

/*
 *  ======== pwr_sleep_dsp ========
 *    Send command to DSP to enter sleep state.
 */
int pwr_sleep_dsp(const u32 sleep_code, const u32 timeout)
{
	struct bridge_drv_interface *intf_fxns;
	struct bridge_dev_context *dw_context;
	int status = -EPERM;
	struct dev_object *hdev_obj = NULL;
	u32 ioctlcode = 0;
	u32 arg = timeout;

	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
	     hdev_obj != NULL;
	     hdev_obj =
	     (struct dev_object *)drv_get_next_dev_object((u32) hdev_obj)) {
		if (dev_get_bridge_context(hdev_obj,
						(struct bridge_dev_context **)
						   &dw_context)) {
			continue;
		}
		if (dev_get_intf_fxns(hdev_obj,
						(struct bridge_drv_interface **)
						&intf_fxns)) {
			continue;
		}
		if (sleep_code == PWR_DEEPSLEEP)
			ioctlcode = BRDIOCTL_DEEPSLEEP;
		else if (sleep_code == PWR_EMERGENCYDEEPSLEEP)
			ioctlcode = BRDIOCTL_EMERGENCYSLEEP;
		else
			status = -EINVAL;

		if (status != -EINVAL) {
			status = (*intf_fxns->dev_cntrl) (dw_context,
							      ioctlcode,
							      (void *)&arg);
		}
	}
	return status;
}

/*
 *  ======== pwr_wake_dsp ========
 *    Send command to DSP to wake it from sleep.
 */
int pwr_wake_dsp(const u32 timeout)
{
	struct bridge_drv_interface *intf_fxns;
	struct bridge_dev_context *dw_context;
	int status = -EPERM;
	struct dev_object *hdev_obj = NULL;
	u32 arg = timeout;

	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
	     hdev_obj != NULL;
	     hdev_obj = (struct dev_object *)drv_get_next_dev_object
	     ((u32) hdev_obj)) {
		if (!(dev_get_bridge_context(hdev_obj,
						      (struct bridge_dev_context
						       **)&dw_context))) {
			if (!(dev_get_intf_fxns(hdev_obj,
			      (struct bridge_drv_interface **)&intf_fxns))) {
				status =
				    (*intf_fxns->dev_cntrl) (dw_context,
							BRDIOCTL_WAKEUP,
							(void *)&arg);
			}
		}
	}
	return status;
}

/*
 *  ======== pwr_pm_pre_scale========
 *    Sends pre-notification message to DSP.
 */
int pwr_pm_pre_scale(u16 voltage_domain, u32 level)
{
	struct bridge_drv_interface *intf_fxns;
	struct bridge_dev_context *dw_context;
	int status = -EPERM;
	struct dev_object *hdev_obj = NULL;
	u32 arg[2];

	arg[0] = voltage_domain;
	arg[1] = level;

	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
	     hdev_obj != NULL;
	     hdev_obj = (struct dev_object *)drv_get_next_dev_object
	     ((u32) hdev_obj)) {
		if (!(dev_get_bridge_context(hdev_obj,
						      (struct bridge_dev_context
						       **)&dw_context))) {
			if (!(dev_get_intf_fxns(hdev_obj,
			      (struct bridge_drv_interface **)&intf_fxns))) {
				status =
				    (*intf_fxns->dev_cntrl) (dw_context,
						BRDIOCTL_PRESCALE_NOTIFY,
						(void *)&arg);
			}
		}
	}
	return status;
}

/*
 *  ======== pwr_pm_post_scale========
 *    Sends post-notification message to DSP.
 */
int pwr_pm_post_scale(u16 voltage_domain, u32 level)
{
	struct bridge_drv_interface *intf_fxns;
	struct bridge_dev_context *dw_context;
	int status = -EPERM;
	struct dev_object *hdev_obj = NULL;
	u32 arg[2];

	arg[0] = voltage_domain;
	arg[1] = level;

	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
	     hdev_obj != NULL;
	     hdev_obj = (struct dev_object *)drv_get_next_dev_object
	     ((u32) hdev_obj)) {
		if (!(dev_get_bridge_context(hdev_obj,
						      (struct bridge_dev_context
						       **)&dw_context))) {
			if (!(dev_get_intf_fxns(hdev_obj,
			      (struct bridge_drv_interface **)&intf_fxns))) {
				status =
				    (*intf_fxns->dev_cntrl) (dw_context,
						BRDIOCTL_POSTSCALE_NOTIFY,
						(void *)&arg);
			}
		}
	}
	return status;

}
