diff options
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/mgr.c')
-rw-r--r-- | drivers/staging/tidspbridge/rmgr/mgr.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/mgr.c b/drivers/staging/tidspbridge/rmgr/mgr.c new file mode 100644 index 000000000000..b1a68ac08d70 --- /dev/null +++ b/drivers/staging/tidspbridge/rmgr/mgr.c @@ -0,0 +1,374 @@ +/* + * mgr.c + * + * DSP-BIOS Bridge driver support functions for TI OMAP processors. + * + * Implementation of Manager interface to the device object at the + * driver level. This queries the NDB data base and retrieves the + * data about Node and Processor. + * + * 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. + */ + +/* ----------------------------------- DSP/BIOS Bridge */ +#include <dspbridge/std.h> +#include <dspbridge/dbdefs.h> + +/* ----------------------------------- Trace & Debug */ +#include <dspbridge/dbc.h> + +/* ----------------------------------- OS Adaptation Layer */ +#include <dspbridge/cfg.h> +#include <dspbridge/sync.h> + +/* ----------------------------------- Others */ +#include <dspbridge/dbdcd.h> +#include <dspbridge/drv.h> +#include <dspbridge/dev.h> + +/* ----------------------------------- This */ +#include <dspbridge/mgr.h> + +/* ----------------------------------- Defines, Data Structures, Typedefs */ +#define ZLDLLNAME "" + +struct mgr_object { + struct dcd_manager *hdcd_mgr; /* Proc/Node data manager */ +}; + +/* ----------------------------------- Globals */ +static u32 refs; + +/* + * ========= mgr_create ========= + * Purpose: + * MGR Object gets created only once during driver Loading. + */ +int mgr_create(OUT struct mgr_object **phMgrObject, + struct cfg_devnode *dev_node_obj) +{ + int status = 0; + struct mgr_object *pmgr_obj = NULL; + + DBC_REQUIRE(phMgrObject != NULL); + DBC_REQUIRE(refs > 0); + + pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL); + if (pmgr_obj) { + status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->hdcd_mgr); + if (DSP_SUCCEEDED(status)) { + /* If succeeded store the handle in the MGR Object */ + status = cfg_set_object((u32) pmgr_obj, REG_MGR_OBJECT); + if (DSP_SUCCEEDED(status)) { + *phMgrObject = pmgr_obj; + } else { + dcd_destroy_manager(pmgr_obj->hdcd_mgr); + kfree(pmgr_obj); + } + } else { + /* failed to Create DCD Manager */ + kfree(pmgr_obj); + } + } else { + status = -ENOMEM; + } + + DBC_ENSURE(DSP_FAILED(status) || pmgr_obj); + return status; +} + +/* + * ========= mgr_destroy ========= + * This function is invoked during bridge driver unloading.Frees MGR object. + */ +int mgr_destroy(struct mgr_object *hmgr_obj) +{ + int status = 0; + struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj; + + DBC_REQUIRE(refs > 0); + DBC_REQUIRE(hmgr_obj); + + /* Free resources */ + if (hmgr_obj->hdcd_mgr) + dcd_destroy_manager(hmgr_obj->hdcd_mgr); + + kfree(pmgr_obj); + /* Update the Registry with NULL for MGR Object */ + (void)cfg_set_object(0, REG_MGR_OBJECT); + + return status; +} + +/* + * ======== mgr_enum_node_info ======== + * Enumerate and get configuration information about nodes configured + * in the node database. + */ +int mgr_enum_node_info(u32 node_id, OUT struct dsp_ndbprops *pndb_props, + u32 undb_props_size, OUT u32 *pu_num_nodes) +{ + int status = 0; + struct dsp_uuid node_uuid, temp_uuid; + u32 temp_index = 0; + u32 node_index = 0; + struct dcd_genericobj gen_obj; + struct mgr_object *pmgr_obj = NULL; + + DBC_REQUIRE(pndb_props != NULL); + DBC_REQUIRE(pu_num_nodes != NULL); + DBC_REQUIRE(undb_props_size >= sizeof(struct dsp_ndbprops)); + DBC_REQUIRE(refs > 0); + + *pu_num_nodes = 0; + /* Get The Manager Object from the Registry */ + status = cfg_get_object((u32 *) &pmgr_obj, REG_MGR_OBJECT); + if (DSP_FAILED(status)) + goto func_cont; + + DBC_ASSERT(pmgr_obj); + /* Forever loop till we hit failed or no more items in the + * Enumeration. We will exit the loop other than 0; */ + while (status == 0) { + status = dcd_enumerate_object(temp_index++, DSP_DCDNODETYPE, + &temp_uuid); + if (status == 0) { + node_index++; + if (node_id == (node_index - 1)) + node_uuid = temp_uuid; + + } + } + if (DSP_SUCCEEDED(status)) { + if (node_id > (node_index - 1)) { + status = -EINVAL; + } else { + status = dcd_get_object_def(pmgr_obj->hdcd_mgr, + (struct dsp_uuid *) + &node_uuid, DSP_DCDNODETYPE, + &gen_obj); + if (DSP_SUCCEEDED(status)) { + /* Get the Obj def */ + *pndb_props = + gen_obj.obj_data.node_obj.ndb_props; + *pu_num_nodes = node_index; + } + } + } + +func_cont: + DBC_ENSURE((DSP_SUCCEEDED(status) && *pu_num_nodes > 0) || + (DSP_FAILED(status) && *pu_num_nodes == 0)); + + return status; +} + +/* + * ======== mgr_enum_processor_info ======== + * Enumerate and get configuration information about available + * DSP processors. + */ +int mgr_enum_processor_info(u32 processor_id, + OUT struct dsp_processorinfo * + processor_info, u32 processor_info_size, + OUT u8 *pu_num_procs) +{ + int status = 0; + int status1 = 0; + int status2 = 0; + struct dsp_uuid temp_uuid; + u32 temp_index = 0; + u32 proc_index = 0; + struct dcd_genericobj gen_obj; + struct mgr_object *pmgr_obj = NULL; + struct mgr_processorextinfo *ext_info; + struct dev_object *hdev_obj; + struct drv_object *hdrv_obj; + u8 dev_type; + struct cfg_devnode *dev_node; + bool proc_detect = false; + + DBC_REQUIRE(processor_info != NULL); + DBC_REQUIRE(pu_num_procs != NULL); + DBC_REQUIRE(processor_info_size >= sizeof(struct dsp_processorinfo)); + DBC_REQUIRE(refs > 0); + + *pu_num_procs = 0; + status = cfg_get_object((u32 *) &hdrv_obj, REG_DRV_OBJECT); + if (DSP_SUCCEEDED(status)) { + status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj); + if (DSP_SUCCEEDED(status)) { + status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type); + status = dev_get_dev_node(hdev_obj, &dev_node); + if (dev_type != DSP_UNIT) + status = -EPERM; + + if (DSP_SUCCEEDED(status)) + processor_info->processor_type = DSPTYPE64; + } + } + if (DSP_FAILED(status)) + goto func_end; + + /* Get The Manager Object from the Registry */ + if (DSP_FAILED(cfg_get_object((u32 *) &pmgr_obj, REG_MGR_OBJECT))) { + dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__); + goto func_end; + } + DBC_ASSERT(pmgr_obj); + /* Forever loop till we hit no more items in the + * Enumeration. We will exit the loop other than 0; */ + while (status1 == 0) { + status1 = dcd_enumerate_object(temp_index++, + DSP_DCDPROCESSORTYPE, + &temp_uuid); + if (status1 != 0) + break; + + proc_index++; + /* Get the Object properties to find the Device/Processor + * Type */ + if (proc_detect != false) + continue; + + status2 = dcd_get_object_def(pmgr_obj->hdcd_mgr, + (struct dsp_uuid *)&temp_uuid, + DSP_DCDPROCESSORTYPE, &gen_obj); + if (DSP_SUCCEEDED(status2)) { + /* Get the Obj def */ + if (processor_info_size < + sizeof(struct mgr_processorextinfo)) { + *processor_info = gen_obj.obj_data.proc_info; + } else { + /* extended info */ + ext_info = (struct mgr_processorextinfo *) + processor_info; + *ext_info = gen_obj.obj_data.ext_proc_obj; + } + dev_dbg(bridge, "%s: Got proctype from DCD %x\n", + __func__, processor_info->processor_type); + /* See if we got the needed processor */ + if (dev_type == DSP_UNIT) { + if (processor_info->processor_type == + DSPPROCTYPE_C64) + proc_detect = true; + } else if (dev_type == IVA_UNIT) { + if (processor_info->processor_type == + IVAPROCTYPE_ARM7) + proc_detect = true; + } + /* User applciatiuons aonly check for chip type, so + * this clumsy overwrite */ + processor_info->processor_type = DSPTYPE64; + } else { + dev_dbg(bridge, "%s: Failed to get DCD processor info " + "%x\n", __func__, status2); + status = -EPERM; + } + } + *pu_num_procs = proc_index; + if (proc_detect == false) { + dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use " + "CFG registry\n", __func__); + processor_info->processor_type = DSPTYPE64; + } +func_end: + return status; +} + +/* + * ======== mgr_exit ======== + * Decrement reference count, and free resources when reference count is + * 0. + */ +void mgr_exit(void) +{ + DBC_REQUIRE(refs > 0); + refs--; + if (refs == 0) + dcd_exit(); + + DBC_ENSURE(refs >= 0); +} + +/* + * ======== mgr_get_dcd_handle ======== + * Retrieves the MGR handle. Accessor Function. + */ +int mgr_get_dcd_handle(struct mgr_object *hMGRHandle, + OUT u32 *phDCDHandle) +{ + int status = -EPERM; + struct mgr_object *pmgr_obj = (struct mgr_object *)hMGRHandle; + + DBC_REQUIRE(refs > 0); + DBC_REQUIRE(phDCDHandle != NULL); + + *phDCDHandle = (u32) NULL; + if (pmgr_obj) { + *phDCDHandle = (u32) pmgr_obj->hdcd_mgr; + status = 0; + } + DBC_ENSURE((DSP_SUCCEEDED(status) && *phDCDHandle != (u32) NULL) || + (DSP_FAILED(status) && *phDCDHandle == (u32) NULL)); + + return status; +} + +/* + * ======== mgr_init ======== + * Initialize MGR's private state, keeping a reference count on each call. + */ +bool mgr_init(void) +{ + bool ret = true; + bool init_dcd = false; + + DBC_REQUIRE(refs >= 0); + + if (refs == 0) { + init_dcd = dcd_init(); /* DCD Module */ + + if (!init_dcd) + ret = false; + } + + if (ret) + refs++; + + DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0))); + + return ret; +} + +/* + * ======== mgr_wait_for_bridge_events ======== + * Block on any Bridge event(s) + */ +int mgr_wait_for_bridge_events(struct dsp_notification **anotifications, + u32 count, OUT u32 *pu_index, + u32 utimeout) +{ + int status; + struct sync_object *sync_events[MAX_EVENTS]; + u32 i; + + DBC_REQUIRE(count < MAX_EVENTS); + + for (i = 0; i < count; i++) + sync_events[i] = anotifications[i]->handle; + + status = sync_wait_on_multiple_events(sync_events, count, utimeout, + pu_index); + + return status; + +} |