]> Pileus Git - ~andy/linux/blob - drivers/staging/tidspbridge/rmgr/mgr.c
Merge tag 'metag-v3.9-rc1-v4' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan...
[~andy/linux] / 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 /*  ----------------------------------- Host OS */
24 #include <dspbridge/host_os.h>
25
26 /*  ----------------------------------- DSP/BIOS Bridge */
27 #include <dspbridge/dbdefs.h>
28
29 /*  ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/sync.h>
31
32 /*  ----------------------------------- Others */
33 #include <dspbridge/dbdcd.h>
34 #include <dspbridge/drv.h>
35 #include <dspbridge/dev.h>
36
37 /*  ----------------------------------- This */
38 #include <dspbridge/mgr.h>
39
40 /*  ----------------------------------- Defines, Data Structures, Typedefs */
41 #define ZLDLLNAME               ""
42
43 struct mgr_object {
44         struct dcd_manager *dcd_mgr;    /* Proc/Node data manager */
45 };
46
47 /*  ----------------------------------- Globals */
48 static u32 refs;
49
50 /*
51  *  ========= mgr_create =========
52  *  Purpose:
53  *      MGR Object gets created only once during driver Loading.
54  */
55 int mgr_create(struct mgr_object **mgr_obj,
56                       struct cfg_devnode *dev_node_obj)
57 {
58         int status = 0;
59         struct mgr_object *pmgr_obj = NULL;
60         struct drv_data *drv_datap = dev_get_drvdata(bridge);
61
62         pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL);
63         if (pmgr_obj) {
64                 status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->dcd_mgr);
65                 if (!status) {
66                         /* If succeeded store the handle in the MGR Object */
67                         if (drv_datap) {
68                                 drv_datap->mgr_object = (void *)pmgr_obj;
69                         } else {
70                                 status = -EPERM;
71                                 pr_err("%s: Failed to store MGR object\n",
72                                                                 __func__);
73                         }
74
75                         if (!status) {
76                                 *mgr_obj = pmgr_obj;
77                         } else {
78                                 dcd_destroy_manager(pmgr_obj->dcd_mgr);
79                                 kfree(pmgr_obj);
80                         }
81                 } else {
82                         /* failed to Create DCD Manager */
83                         kfree(pmgr_obj);
84                 }
85         } else {
86                 status = -ENOMEM;
87         }
88
89         return status;
90 }
91
92 /*
93  *  ========= mgr_destroy =========
94  *     This function is invoked during bridge driver unloading.Frees MGR object.
95  */
96 int mgr_destroy(struct mgr_object *hmgr_obj)
97 {
98         int status = 0;
99         struct mgr_object *pmgr_obj = (struct mgr_object *)hmgr_obj;
100         struct drv_data *drv_datap = dev_get_drvdata(bridge);
101
102         /* Free resources */
103         if (hmgr_obj->dcd_mgr)
104                 dcd_destroy_manager(hmgr_obj->dcd_mgr);
105
106         kfree(pmgr_obj);
107         /* Update the driver data with NULL for MGR Object */
108         if (drv_datap) {
109                 drv_datap->mgr_object = NULL;
110         } else {
111                 status = -EPERM;
112                 pr_err("%s: Failed to store MGR object\n", __func__);
113         }
114
115         return status;
116 }
117
118 /*
119  *  ======== mgr_enum_node_info ========
120  *      Enumerate and get configuration information about nodes configured
121  *      in the node database.
122  */
123 int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
124                               u32 undb_props_size, u32 *pu_num_nodes)
125 {
126         int status = 0;
127         struct dsp_uuid node_uuid;
128         u32 node_index = 0;
129         struct dcd_genericobj gen_obj;
130         struct mgr_object *pmgr_obj = NULL;
131         struct drv_data *drv_datap = dev_get_drvdata(bridge);
132
133         *pu_num_nodes = 0;
134         /* Get the Manager Object from the driver data */
135         if (!drv_datap || !drv_datap->mgr_object) {
136                 pr_err("%s: Failed to retrieve the object handle\n", __func__);
137                 return -ENODATA;
138         }
139         pmgr_obj = drv_datap->mgr_object;
140
141         /* Forever loop till we hit failed or no more items in the
142          * Enumeration. We will exit the loop other than 0; */
143         while (!status) {
144                 status = dcd_enumerate_object(node_index++, DSP_DCDNODETYPE,
145                                 &node_uuid);
146                 if (status)
147                         break;
148                 *pu_num_nodes = node_index;
149                 if (node_id == (node_index - 1)) {
150                         status = dcd_get_object_def(pmgr_obj->dcd_mgr,
151                                         &node_uuid, DSP_DCDNODETYPE, &gen_obj);
152                         if (status)
153                                 break;
154                         /* Get the Obj def */
155                         *pndb_props = gen_obj.obj_data.node_obj.ndb_props;
156                 }
157         }
158
159         /* the last status is not 0, but neither an error */
160         if (status > 0)
161                 status = 0;
162
163         return status;
164 }
165
166 /*
167  *  ======== mgr_enum_processor_info ========
168  *      Enumerate and get configuration information about available
169  *      DSP processors.
170  */
171 int mgr_enum_processor_info(u32 processor_id,
172                                    struct dsp_processorinfo *
173                                    processor_info, u32 processor_info_size,
174                                    u8 *pu_num_procs)
175 {
176         int status = 0;
177         int status1 = 0;
178         int status2 = 0;
179         struct dsp_uuid temp_uuid;
180         u32 temp_index = 0;
181         u32 proc_index = 0;
182         struct dcd_genericobj gen_obj;
183         struct mgr_object *pmgr_obj = NULL;
184         struct mgr_processorextinfo *ext_info;
185         struct dev_object *hdev_obj;
186         struct drv_object *hdrv_obj;
187         u8 dev_type;
188         struct cfg_devnode *dev_node;
189         struct drv_data *drv_datap = dev_get_drvdata(bridge);
190         bool proc_detect = false;
191
192         *pu_num_procs = 0;
193
194         /* Retrieve the Object handle from the driver data */
195         if (!drv_datap || !drv_datap->drv_object) {
196                 status = -ENODATA;
197                 pr_err("%s: Failed to retrieve the object handle\n", __func__);
198         } else {
199                 hdrv_obj = drv_datap->drv_object;
200         }
201
202         if (!status) {
203                 status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj);
204                 if (!status) {
205                         status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type);
206                         status = dev_get_dev_node(hdev_obj, &dev_node);
207                         if (dev_type != DSP_UNIT)
208                                 status = -EPERM;
209
210                         if (!status)
211                                 processor_info->processor_type = DSPTYPE64;
212                 }
213         }
214         if (status)
215                 goto func_end;
216
217         /* Get The Manager Object from the driver data */
218         if (drv_datap && drv_datap->mgr_object) {
219                 pmgr_obj = drv_datap->mgr_object;
220         } else {
221                 dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__);
222                 goto func_end;
223         }
224         /* Forever loop till we hit no more items in the
225          * Enumeration. We will exit the loop other than 0; */
226         while (status1 == 0) {
227                 status1 = dcd_enumerate_object(temp_index++,
228                                                DSP_DCDPROCESSORTYPE,
229                                                &temp_uuid);
230                 if (status1 != 0)
231                         break;
232
233                 proc_index++;
234                 /* Get the Object properties to find the Device/Processor
235                  * Type */
236                 if (proc_detect != false)
237                         continue;
238
239                 status2 = dcd_get_object_def(pmgr_obj->dcd_mgr,
240                                              (struct dsp_uuid *)&temp_uuid,
241                                              DSP_DCDPROCESSORTYPE, &gen_obj);
242                 if (!status2) {
243                         /* Get the Obj def */
244                         if (processor_info_size <
245                             sizeof(struct mgr_processorextinfo)) {
246                                 *processor_info = gen_obj.obj_data.proc_info;
247                         } else {
248                                 /* extended info */
249                                 ext_info = (struct mgr_processorextinfo *)
250                                     processor_info;
251                                 *ext_info = gen_obj.obj_data.ext_proc_obj;
252                         }
253                         dev_dbg(bridge, "%s: Got proctype  from DCD %x\n",
254                                 __func__, processor_info->processor_type);
255                         /* See if we got the needed processor */
256                         if (dev_type == DSP_UNIT) {
257                                 if (processor_info->processor_type ==
258                                     DSPPROCTYPE_C64)
259                                         proc_detect = true;
260                         } else if (dev_type == IVA_UNIT) {
261                                 if (processor_info->processor_type ==
262                                     IVAPROCTYPE_ARM7)
263                                         proc_detect = true;
264                         }
265                         /* User applications only check for chip type, so
266                          * this is a clumsy overwrite */
267                         processor_info->processor_type = DSPTYPE64;
268                 } else {
269                         dev_dbg(bridge, "%s: Failed to get DCD processor info "
270                                 "%x\n", __func__, status2);
271                         status = -EPERM;
272                 }
273         }
274         *pu_num_procs = proc_index;
275         if (proc_detect == false) {
276                 dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use "
277                         "CFG registry\n", __func__);
278                 processor_info->processor_type = DSPTYPE64;
279         }
280 func_end:
281         return status;
282 }
283
284 /*
285  *  ======== mgr_exit ========
286  *      Decrement reference count, and free resources when reference count is
287  *      0.
288  */
289 void mgr_exit(void)
290 {
291         refs--;
292         if (refs == 0)
293                 dcd_exit();
294 }
295
296 /*
297  *  ======== mgr_get_dcd_handle ========
298  *      Retrieves the MGR handle. Accessor Function.
299  */
300 int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
301                               u32 *dcd_handle)
302 {
303         int status = -EPERM;
304         struct mgr_object *pmgr_obj = (struct mgr_object *)mgr_handle;
305
306         *dcd_handle = (u32) NULL;
307         if (pmgr_obj) {
308                 *dcd_handle = (u32) pmgr_obj->dcd_mgr;
309                 status = 0;
310         }
311
312         return status;
313 }
314
315 /*
316  *  ======== mgr_init ========
317  *      Initialize MGR's private state, keeping a reference count on each call.
318  */
319 bool mgr_init(void)
320 {
321         bool ret = true;
322
323         if (refs == 0)
324                 ret = dcd_init();       /*  DCD Module */
325
326         if (ret)
327                 refs++;
328
329         return ret;
330 }
331
332 /*
333  *  ======== mgr_wait_for_bridge_events ========
334  *      Block on any Bridge event(s)
335  */
336 int mgr_wait_for_bridge_events(struct dsp_notification **anotifications,
337                                       u32 count, u32 *pu_index,
338                                       u32 utimeout)
339 {
340         int status;
341         struct sync_object *sync_events[MAX_EVENTS];
342         u32 i;
343
344         for (i = 0; i < count; i++)
345                 sync_events[i] = anotifications[i]->handle;
346
347         status = sync_wait_on_multiple_events(sync_events, count, utimeout,
348                                               pu_index);
349
350         return status;
351
352 }