upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / staging / tidspbridge / rmgr / mgr.c
1 /*
2  * mgr.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Implementation of Manager interface to the device object at the
7  * driver level. This queries the NDB data base and retrieves the
8  * data about Node and Processor.
9  *
10  * Copyright (C) 2005-2006 Texas Instruments, Inc.
11  *
12  * This package is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  *
16  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 #include <linux/types.h>
22
23 /*  ----------------------------------- DSP/BIOS Bridge */
24 #include <dspbridge/dbdefs.h>
25
26 /*  ----------------------------------- Trace & Debug */
27 #include <dspbridge/dbc.h>
28
29 /*  ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/cfg.h>
31 #include <dspbridge/sync.h>
32
33 /*  ----------------------------------- Others */
34 #include <dspbridge/dbdcd.h>
35 #include <dspbridge/drv.h>
36 #include <dspbridge/dev.h>
37
38 /*  ----------------------------------- This */
39 #include <dspbridge/mgr.h>
40
41 /*  ----------------------------------- Defines, Data Structures, Typedefs */
42 #define ZLDLLNAME               ""
43
44 struct mgr_object {
45         struct dcd_manager *hdcd_mgr;   /* Proc/Node data manager */
46 };
47
48 /*  ----------------------------------- Globals */
49 static u32 refs;
50
51 /*
52  *  ========= mgr_create =========
53  *  Purpose:
54  *      MGR Object gets created only once during driver Loading.
55  */
56 int mgr_create(struct mgr_object **mgr_obj,
57                       struct cfg_devnode *dev_node_obj)
58 {
59         int status = 0;
60         struct mgr_object *pmgr_obj = NULL;
61
62         DBC_REQUIRE(mgr_obj != NULL);
63         DBC_REQUIRE(refs > 0);
64
65         pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL);
66         if (pmgr_obj) {
67                 status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->hdcd_mgr);
68                 if (!status) {
69                         /* If succeeded store the handle in the MGR Object */
70                         status = cfg_set_object((u32) pmgr_obj, REG_MGR_OBJECT);
71                         if (!status) {
72                                 *mgr_obj = pmgr_obj;
73                         } else {
74                                 dcd_destroy_manager(pmgr_obj->hdcd_mgr);
75                                 kfree(pmgr_obj);
76                         }
77                 } else {
78                         /* failed to Create DCD Manager */
79                         kfree(pmgr_obj);
80                 }
81         } else {
82                 status = -ENOMEM;
83         }
84
85         DBC_ENSURE(status || pmgr_obj);
86         return status;
87 }
88
89 /*
90  *  ========= mgr_destroy =========
91  *     This function is invoked during bridge driver unloading.Frees MGR object.
92  */
93 int mgr_destroy(struct mgr_object *hmgr_obj)
94 {
95         int status = 0;
96         struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj;
97
98         DBC_REQUIRE(refs > 0);
99         DBC_REQUIRE(hmgr_obj);
100
101         /* Free resources */
102         if (hmgr_obj->hdcd_mgr)
103                 dcd_destroy_manager(hmgr_obj->hdcd_mgr);
104
105         kfree(pmgr_obj);
106         /* Update the Registry with NULL for MGR Object */
107         (void)cfg_set_object(0, REG_MGR_OBJECT);
108
109         return status;
110 }
111
112 /*
113  *  ======== mgr_enum_node_info ========
114  *      Enumerate and get configuration information about nodes configured
115  *      in the node database.
116  */
117 int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
118                               u32 undb_props_size, u32 *pu_num_nodes)
119 {
120         int status = 0;
121         struct dsp_uuid node_uuid, temp_uuid;
122         u32 temp_index = 0;
123         u32 node_index = 0;
124         struct dcd_genericobj gen_obj;
125         struct mgr_object *pmgr_obj = NULL;
126
127         DBC_REQUIRE(pndb_props != NULL);
128         DBC_REQUIRE(pu_num_nodes != NULL);
129         DBC_REQUIRE(undb_props_size >= sizeof(struct dsp_ndbprops));
130         DBC_REQUIRE(refs > 0);
131
132         *pu_num_nodes = 0;
133         /* Get The Manager Object from the Registry */
134         status = cfg_get_object((u32 *) &pmgr_obj, REG_MGR_OBJECT);
135         if (status)
136                 goto func_cont;
137
138         DBC_ASSERT(pmgr_obj);
139         /* Forever loop till we hit failed or no more items in the
140          * Enumeration. We will exit the loop other than 0; */
141         while (status == 0) {
142                 status = dcd_enumerate_object(temp_index++, DSP_DCDNODETYPE,
143                                               &temp_uuid);
144                 if (status == 0) {
145                         node_index++;
146                         if (node_id == (node_index - 1))
147                                 node_uuid = temp_uuid;
148
149                 }
150         }
151         if (!status) {
152                 if (node_id > (node_index - 1)) {
153                         status = -EINVAL;
154                 } else {
155                         status = dcd_get_object_def(pmgr_obj->hdcd_mgr,
156                                                     (struct dsp_uuid *)
157                                                     &node_uuid, DSP_DCDNODETYPE,
158                                                     &gen_obj);
159                         if (!status) {
160                                 /* Get the Obj def */
161                                 *pndb_props =
162                                     gen_obj.obj_data.node_obj.ndb_props;
163                                 *pu_num_nodes = node_index;
164                         }
165                 }
166         }
167
168 func_cont:
169         DBC_ENSURE((!status && *pu_num_nodes > 0) ||
170                    (status && *pu_num_nodes == 0));
171
172         return status;
173 }
174
175 /*
176  *  ======== mgr_enum_processor_info ========
177  *      Enumerate and get configuration information about available
178  *      DSP processors.
179  */
180 int mgr_enum_processor_info(u32 processor_id,
181                                    struct dsp_processorinfo *
182                                    processor_info, u32 processor_info_size,
183                                    u8 *pu_num_procs)
184 {
185         int status = 0;
186         int status1 = 0;
187         int status2 = 0;
188         struct dsp_uuid temp_uuid;
189         u32 temp_index = 0;
190         u32 proc_index = 0;
191         struct dcd_genericobj gen_obj;
192         struct mgr_object *pmgr_obj = NULL;
193         struct mgr_processorextinfo *ext_info;
194         struct dev_object *hdev_obj;
195         struct drv_object *hdrv_obj;
196         u8 dev_type;
197         struct cfg_devnode *dev_node;
198         bool proc_detect = false;
199
200         DBC_REQUIRE(processor_info != NULL);
201         DBC_REQUIRE(pu_num_procs != NULL);
202         DBC_REQUIRE(processor_info_size >= sizeof(struct dsp_processorinfo));
203         DBC_REQUIRE(refs > 0);
204
205         *pu_num_procs = 0;
206         status = cfg_get_object((u32 *) &hdrv_obj, REG_DRV_OBJECT);
207         if (!status) {
208                 status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
209                 if (!status) {
210                         status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
211                         status = dev_get_dev_node(hdev_obj, &dev_node);
212                         if (dev_type != DSP_UNIT)
213                                 status = -EPERM;
214
215                         if (!status)
216                                 processor_info->processor_type = DSPTYPE64;
217                 }
218         }
219         if (status)
220                 goto func_end;
221
222         /* Get The Manager Object from the Registry */
223         if (cfg_get_object((u32 *) &pmgr_obj, REG_MGR_OBJECT)) {
224                 dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__);
225                 goto func_end;
226         }
227         DBC_ASSERT(pmgr_obj);
228         /* Forever loop till we hit no more items in the
229          * Enumeration. We will exit the loop other than 0; */
230         while (status1 == 0) {
231                 status1 = dcd_enumerate_object(temp_index++,
232                                                DSP_DCDPROCESSORTYPE,
233                                                &temp_uuid);
234                 if (status1 != 0)
235                         break;
236
237                 proc_index++;
238                 /* Get the Object properties to find the Device/Processor
239                  * Type */
240                 if (proc_detect != false)
241                         continue;
242
243                 status2 = dcd_get_object_def(pmgr_obj->hdcd_mgr,
244                                              (struct dsp_uuid *)&temp_uuid,
245                                              DSP_DCDPROCESSORTYPE, &gen_obj);
246                 if (!status2) {
247                         /* Get the Obj def */
248                         if (processor_info_size <
249                             sizeof(struct mgr_processorextinfo)) {
250                                 *processor_info = gen_obj.obj_data.proc_info;
251                         } else {
252                                 /* extended info */
253                                 ext_info = (struct mgr_processorextinfo *)
254                                     processor_info;
255                                 *ext_info = gen_obj.obj_data.ext_proc_obj;
256                         }
257                         dev_dbg(bridge, "%s: Got proctype  from DCD %x\n",
258                                 __func__, processor_info->processor_type);
259                         /* See if we got the needed processor */
260                         if (dev_type == DSP_UNIT) {
261                                 if (processor_info->processor_type ==
262                                     DSPPROCTYPE_C64)
263                                         proc_detect = true;
264                         } else if (dev_type == IVA_UNIT) {
265                                 if (processor_info->processor_type ==
266                                     IVAPROCTYPE_ARM7)
267                                         proc_detect = true;
268                         }
269                         /* User applciatiuons aonly check for chip type, so
270                          * this clumsy overwrite */
271                         processor_info->processor_type = DSPTYPE64;
272                 } else {
273                         dev_dbg(bridge, "%s: Failed to get DCD processor info "
274                                 "%x\n", __func__, status2);
275                         status = -EPERM;
276                 }
277         }
278         *pu_num_procs = proc_index;
279         if (proc_detect == false) {
280                 dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use "
281                         "CFG registry\n", __func__);
282                 processor_info->processor_type = DSPTYPE64;
283         }
284 func_end:
285         return status;
286 }
287
288 /*
289  *  ======== mgr_exit ========
290  *      Decrement reference count, and free resources when reference count is
291  *      0.
292  */
293 void mgr_exit(void)
294 {
295         DBC_REQUIRE(refs > 0);
296         refs--;
297         if (refs == 0)
298                 dcd_exit();
299
300         DBC_ENSURE(refs >= 0);
301 }
302
303 /*
304  *  ======== mgr_get_dcd_handle ========
305  *      Retrieves the MGR handle. Accessor Function.
306  */
307 int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
308                               u32 *dcd_handle)
309 {
310         int status = -EPERM;
311         struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle;
312
313         DBC_REQUIRE(refs > 0);
314         DBC_REQUIRE(dcd_handle != NULL);
315
316         *dcd_handle = (u32) NULL;
317         if (pmgr_obj) {
318                 *dcd_handle = (u32) pmgr_obj->hdcd_mgr;
319                 status = 0;
320         }
321         DBC_ENSURE((!status && *dcd_handle != (u32) NULL) ||
322                    (status && *dcd_handle == (u32) NULL));
323
324         return status;
325 }
326
327 /*
328  *  ======== mgr_init ========
329  *      Initialize MGR's private state, keeping a reference count on each call.
330  */
331 bool mgr_init(void)
332 {
333         bool ret = true;
334         bool init_dcd = false;
335
336         DBC_REQUIRE(refs >= 0);
337
338         if (refs == 0) {
339                 init_dcd = dcd_init();  /*  DCD Module */
340
341                 if (!init_dcd)
342                         ret = false;
343         }
344
345         if (ret)
346                 refs++;
347
348         DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
349
350         return ret;
351 }
352
353 /*
354  *  ======== mgr_wait_for_bridge_events ========
355  *      Block on any Bridge event(s)
356  */
357 int mgr_wait_for_bridge_events(struct dsp_notification **anotifications,
358                                       u32 count, u32 *pu_index,
359                                       u32 utimeout)
360 {
361         int status;
362         struct sync_object *sync_events[MAX_EVENTS];
363         u32 i;
364
365         DBC_REQUIRE(count < MAX_EVENTS);
366
367         for (i = 0; i < count; i++)
368                 sync_events[i] = anotifications[i]->handle;
369
370         status = sync_wait_on_multiple_events(sync_events, count, utimeout,
371                                               pu_index);
372
373         return status;
374
375 }