/*
 * dspdrv.c
 *
 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
 *
 * Interface to allocate and free bridge resources.
 *
 * 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 <linux/types.h>
#include <dspbridge/host_os.h>

/*  ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/dbdefs.h>

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

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

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

/*
 *  ======== dsp_init ========
 *  	Allocates bridge resources. Loads a base image onto DSP, if specified.
 */
u32 dsp_init(u32 *init_status)
{
	char dev_node[MAXREGPATHLENGTH] = "TIOMAP1510";
	int status = -EPERM;
	struct drv_object *drv_obj = NULL;
	u32 device_node;
	u32 device_node_string;

	if (!api_init())
		goto func_cont;

	status = drv_create(&drv_obj);
	if (status) {
		api_exit();
		goto func_cont;
	}

	/* End drv_create */
	/* Request Resources */
	status = drv_request_resources((u32) &dev_node, &device_node_string);
	if (!status) {
		/* Attempt to Start the Device */
		status = dev_start_device((struct cfg_devnode *)
					  device_node_string);
		if (status)
			(void)drv_release_resources
			    ((u32) device_node_string, drv_obj);
	} else {
		dev_dbg(bridge, "%s: drv_request_resources Failed\n", __func__);
		status = -EPERM;
	}

	/* Unwind whatever was loaded */
	if (status) {
		/* irrespective of the status of dev_remove_device we continue
		 * unloading. Get the Driver Object iterate through and remove.
		 * Reset the status to E_FAIL to avoid going through
		 * api_init_complete2. */
		for (device_node = drv_get_first_dev_extension();
		     device_node != 0;
		     device_node = drv_get_next_dev_extension(device_node)) {
			(void)dev_remove_device((struct cfg_devnode *)
						device_node);
			(void)drv_release_resources((u32) device_node, drv_obj);
		}
		/* Remove the Driver Object */
		(void)drv_destroy(drv_obj);
		drv_obj = NULL;
		api_exit();
		dev_dbg(bridge, "%s: Logical device failed init\n", __func__);
	}			/* Unwinding the loaded drivers */
func_cont:
	/* Attempt to Start the Board */
	if (!status) {
		/* BRD_AutoStart could fail if the dsp executable is not the
		 * correct one. We should not propagate that error
		 * into the device loader. */
		(void)api_init_complete2();
	} else {
		dev_dbg(bridge, "%s: Failed\n", __func__);
	}			/* End api_init_complete2 */
	*init_status = status;
	/* Return the Driver Object */
	return (u32) drv_obj;
}

/*
 *  ======== dsp_deinit ========
 *  	Frees the resources allocated for bridge.
 */
bool dsp_deinit(u32 device_context)
{
	bool ret = true;
	u32 device_node;
	struct mgr_object *mgr_obj = NULL;
	struct drv_data *drv_datap = dev_get_drvdata(bridge);

	while ((device_node = drv_get_first_dev_extension()) != 0) {
		(void)dev_remove_device((struct cfg_devnode *)device_node);

		(void)drv_release_resources((u32) device_node,
					(struct drv_object *)device_context);
	}

	(void)drv_destroy((struct drv_object *)device_context);

	/* Get the Manager Object from driver data
	 * MGR Destroy will unload the DCD dll */
	if (drv_datap && drv_datap->mgr_object) {
		mgr_obj = drv_datap->mgr_object;
		(void)mgr_destroy(mgr_obj);
	} else {
		pr_err("%s: Failed to retrieve the object handle\n", __func__);
	}

	api_exit();

	return ret;
}
