diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/staging/tidspbridge/rmgr/mgr.c | |
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/mgr.c')
| -rw-r--r-- | drivers/staging/tidspbridge/rmgr/mgr.c | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/mgr.c b/drivers/staging/tidspbridge/rmgr/mgr.c new file mode 100644 index 00000000..b32ba0ad --- /dev/null +++ b/drivers/staging/tidspbridge/rmgr/mgr.c @@ -0,0 +1,352 @@ +/* + * 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. + */ + +#include <linux/types.h> + +/* ----------------------------------- Host OS */ +#include <dspbridge/host_os.h> + +/* ----------------------------------- DSP/BIOS Bridge */ +#include <dspbridge/dbdefs.h> + +/* ----------------------------------- OS Adaptation Layer */ +#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 *dcd_mgr; /* Proc/Node data manager */ +}; + +/* ----------------------------------- Globals */ +static u32 refs; + +/* + * ========= mgr_create ========= + * Purpose: + * MGR Object gets created only once during driver Loading. + */ +int mgr_create(struct mgr_object **mgr_obj, + struct cfg_devnode *dev_node_obj) +{ + int status = 0; + struct mgr_object *pmgr_obj = NULL; + struct drv_data *drv_datap = dev_get_drvdata(bridge); + + pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL); + if (pmgr_obj) { + status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->dcd_mgr); + if (!status) { + /* If succeeded store the handle in the MGR Object */ + if (drv_datap) { + drv_datap->mgr_object = (void *)pmgr_obj; + } else { + status = -EPERM; + pr_err("%s: Failed to store MGR object\n", + __func__); + } + + if (!status) { + *mgr_obj = pmgr_obj; + } else { + dcd_destroy_manager(pmgr_obj->dcd_mgr); + kfree(pmgr_obj); + } + } else { + /* failed to Create DCD Manager */ + kfree(pmgr_obj); + } + } else { + status = -ENOMEM; + } + + 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; + struct drv_data *drv_datap = dev_get_drvdata(bridge); + + /* Free resources */ + if (hmgr_obj->dcd_mgr) + dcd_destroy_manager(hmgr_obj->dcd_mgr); + + kfree(pmgr_obj); + /* Update the driver data with NULL for MGR Object */ + if (drv_datap) { + drv_datap->mgr_object = NULL; + } else { + status = -EPERM; + pr_err("%s: Failed to store MGR object\n", __func__); + } + + 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, struct dsp_ndbprops *pndb_props, + u32 undb_props_size, u32 *pu_num_nodes) +{ + int status = 0; + struct dsp_uuid node_uuid; + u32 node_index = 0; + struct dcd_genericobj gen_obj; + struct mgr_object *pmgr_obj = NULL; + struct drv_data *drv_datap = dev_get_drvdata(bridge); + + *pu_num_nodes = 0; + /* Get the Manager Object from the driver data */ + if (!drv_datap || !drv_datap->mgr_object) { + pr_err("%s: Failed to retrieve the object handle\n", __func__); + return -ENODATA; + } + pmgr_obj = drv_datap->mgr_object; + + /* Forever loop till we hit failed or no more items in the + * Enumeration. We will exit the loop other than 0; */ + while (!status) { + status = dcd_enumerate_object(node_index++, DSP_DCDNODETYPE, + &node_uuid); + if (status) + break; + *pu_num_nodes = node_index; + if (node_id == (node_index - 1)) { + status = dcd_get_object_def(pmgr_obj->dcd_mgr, + &node_uuid, DSP_DCDNODETYPE, &gen_obj); + if (status) + break; + /* Get the Obj def */ + *pndb_props = gen_obj.obj_data.node_obj.ndb_props; + } + } + + /* the last status is not 0, but neither an error */ + if (status > 0) + status = 0; + + return status; +} + +/* + * ======== mgr_enum_processor_info ======== + * Enumerate and get configuration information about available + * DSP processors. + */ +int mgr_enum_processor_info(u32 processor_id, + struct dsp_processorinfo * + processor_info, u32 processor_info_size, + 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; + struct drv_data *drv_datap = dev_get_drvdata(bridge); + bool proc_detect = false; + + *pu_num_procs = 0; + + /* Retrieve the Object handle from the driver data */ + if (!drv_datap || !drv_datap->drv_object) { + status = -ENODATA; + pr_err("%s: Failed to retrieve the object handle\n", __func__); + } else { + hdrv_obj = drv_datap->drv_object; + } + + if (!status) { + status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj); + if (!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 (!status) + processor_info->processor_type = DSPTYPE64; + } + } + if (status) + goto func_end; + + /* Get The Manager Object from the driver data */ + if (drv_datap && drv_datap->mgr_object) { + pmgr_obj = drv_datap->mgr_object; + } else { + dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__); + goto func_end; + } + /* 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->dcd_mgr, + (struct dsp_uuid *)&temp_uuid, + DSP_DCDPROCESSORTYPE, &gen_obj); + if (!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 applications only check for chip type, so + * this is a 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) +{ + refs--; + if (refs == 0) + dcd_exit(); +} + +/* + * ======== mgr_get_dcd_handle ======== + * Retrieves the MGR handle. Accessor Function. + */ +int mgr_get_dcd_handle(struct mgr_object *mgr_handle, + u32 *dcd_handle) +{ + int status = -EPERM; + struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle; + + *dcd_handle = (u32) NULL; + if (pmgr_obj) { + *dcd_handle = (u32) pmgr_obj->dcd_mgr; + status = 0; + } + + return status; +} + +/* + * ======== mgr_init ======== + * Initialize MGR's private state, keeping a reference count on each call. + */ +bool mgr_init(void) +{ + bool ret = true; + + if (refs == 0) + ret = dcd_init(); /* DCD Module */ + + if (ret) + refs++; + + 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, u32 *pu_index, + u32 utimeout) +{ + int status; + struct sync_object *sync_events[MAX_EVENTS]; + u32 i; + + 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; + +} |
