Pull cpuidle into release branch
[pandora-kernel.git] / arch / mips / fw / cfe / cfe_api.c
1 /*
2  * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 /*  *********************************************************************
20     *
21     *  Broadcom Common Firmware Environment (CFE)
22     *
23     *  Device Function stubs                    File: cfe_api.c
24     *
25     *  This module contains device function stubs (small routines to
26     *  call the standard "iocb" interface entry point to CFE).
27     *  There should be one routine here per iocb function call.
28     *
29     *  Authors:  Mitch Lichtenberg, Chris Demetriou
30     *
31     ********************************************************************* */
32
33 #include <asm/fw/cfe/cfe_api.h>
34 #include "cfe_api_int.h"
35
36 /* Cast from a native pointer to a cfe_xptr_t and back.  */
37 #define XPTR_FROM_NATIVE(n)     ((cfe_xptr_t) (intptr_t) (n))
38 #define NATIVE_FROM_XPTR(x)     ((void *) (intptr_t) (x))
39
40 #ifdef CFE_API_IMPL_NAMESPACE
41 #define cfe_iocb_dispatch(a)            __cfe_iocb_dispatch(a)
42 #endif
43 int cfe_iocb_dispatch(cfe_xiocb_t * xiocb);
44
45 #if defined(CFE_API_common) || defined(CFE_API_ALL)
46 /*
47  * Declare the dispatch function with args of "intptr_t".
48  * This makes sure whatever model we're compiling in
49  * puts the pointers in a single register.  For example,
50  * combining -mlong64 and -mips1 or -mips2 would lead to
51  * trouble, since the handle and IOCB pointer will be
52  * passed in two registers each, and CFE expects one.
53  */
54
55 static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0;
56 static cfe_xuint_t cfe_handle = 0;
57
58 int cfe_init(cfe_xuint_t handle, cfe_xuint_t ept)
59 {
60         cfe_dispfunc = NATIVE_FROM_XPTR(ept);
61         cfe_handle = handle;
62         return 0;
63 }
64
65 int cfe_iocb_dispatch(cfe_xiocb_t * xiocb)
66 {
67         if (!cfe_dispfunc)
68                 return -1;
69         return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
70 }
71 #endif                          /* CFE_API_common || CFE_API_ALL */
72
73 #if defined(CFE_API_close) || defined(CFE_API_ALL)
74 int cfe_close(int handle)
75 {
76         cfe_xiocb_t xiocb;
77
78         xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
79         xiocb.xiocb_status = 0;
80         xiocb.xiocb_handle = handle;
81         xiocb.xiocb_flags = 0;
82         xiocb.xiocb_psize = 0;
83
84         cfe_iocb_dispatch(&xiocb);
85
86         return xiocb.xiocb_status;
87
88 }
89 #endif                          /* CFE_API_close || CFE_API_ALL */
90
91 #if defined(CFE_API_cpu_start) || defined(CFE_API_ALL)
92 int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
93 {
94         cfe_xiocb_t xiocb;
95
96         xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
97         xiocb.xiocb_status = 0;
98         xiocb.xiocb_handle = 0;
99         xiocb.xiocb_flags = 0;
100         xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
101         xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
102         xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
103         xiocb.plist.xiocb_cpuctl.gp_val = gp;
104         xiocb.plist.xiocb_cpuctl.sp_val = sp;
105         xiocb.plist.xiocb_cpuctl.a1_val = a1;
106         xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
107
108         cfe_iocb_dispatch(&xiocb);
109
110         return xiocb.xiocb_status;
111 }
112 #endif                          /* CFE_API_cpu_start || CFE_API_ALL */
113
114 #if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL)
115 int cfe_cpu_stop(int cpu)
116 {
117         cfe_xiocb_t xiocb;
118
119         xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
120         xiocb.xiocb_status = 0;
121         xiocb.xiocb_handle = 0;
122         xiocb.xiocb_flags = 0;
123         xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
124         xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
125         xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
126
127         cfe_iocb_dispatch(&xiocb);
128
129         return xiocb.xiocb_status;
130 }
131 #endif                          /* CFE_API_cpu_stop || CFE_API_ALL */
132
133 #if defined(CFE_API_enumenv) || defined(CFE_API_ALL)
134 int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
135 {
136         cfe_xiocb_t xiocb;
137
138         xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
139         xiocb.xiocb_status = 0;
140         xiocb.xiocb_handle = 0;
141         xiocb.xiocb_flags = 0;
142         xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
143         xiocb.plist.xiocb_envbuf.enum_idx = idx;
144         xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
145         xiocb.plist.xiocb_envbuf.name_length = namelen;
146         xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
147         xiocb.plist.xiocb_envbuf.val_length = vallen;
148
149         cfe_iocb_dispatch(&xiocb);
150
151         return xiocb.xiocb_status;
152 }
153 #endif                          /* CFE_API_enumenv || CFE_API_ALL */
154
155 #if defined(CFE_API_enummem) || defined(CFE_API_ALL)
156 int
157 cfe_enummem(int idx, int flags, cfe_xuint_t * start, cfe_xuint_t * length,
158             cfe_xuint_t * type)
159 {
160         cfe_xiocb_t xiocb;
161
162         xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
163         xiocb.xiocb_status = 0;
164         xiocb.xiocb_handle = 0;
165         xiocb.xiocb_flags = flags;
166         xiocb.xiocb_psize = sizeof(xiocb_meminfo_t);
167         xiocb.plist.xiocb_meminfo.mi_idx = idx;
168
169         cfe_iocb_dispatch(&xiocb);
170
171         if (xiocb.xiocb_status < 0)
172                 return xiocb.xiocb_status;
173
174         *start = xiocb.plist.xiocb_meminfo.mi_addr;
175         *length = xiocb.plist.xiocb_meminfo.mi_size;
176         *type = xiocb.plist.xiocb_meminfo.mi_type;
177
178         return 0;
179 }
180 #endif                          /* CFE_API_enummem || CFE_API_ALL */
181
182 #if defined(CFE_API_exit) || defined(CFE_API_ALL)
183 int cfe_exit(int warm, int status)
184 {
185         cfe_xiocb_t xiocb;
186
187         xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
188         xiocb.xiocb_status = 0;
189         xiocb.xiocb_handle = 0;
190         xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
191         xiocb.xiocb_psize = sizeof(xiocb_exitstat_t);
192         xiocb.plist.xiocb_exitstat.status = status;
193
194         cfe_iocb_dispatch(&xiocb);
195
196         return xiocb.xiocb_status;
197 }
198 #endif                          /* CFE_API_exit || CFE_API_ALL */
199
200 #if defined(CFE_API_flushcache) || defined(CFE_API_ALL)
201 int cfe_flushcache(int flg)
202 {
203         cfe_xiocb_t xiocb;
204
205         xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
206         xiocb.xiocb_status = 0;
207         xiocb.xiocb_handle = 0;
208         xiocb.xiocb_flags = flg;
209         xiocb.xiocb_psize = 0;
210
211         cfe_iocb_dispatch(&xiocb);
212
213         return xiocb.xiocb_status;
214 }
215 #endif                          /* CFE_API_flushcache || CFE_API_ALL */
216
217 #if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL)
218 int cfe_getdevinfo(char *name)
219 {
220         cfe_xiocb_t xiocb;
221
222         xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
223         xiocb.xiocb_status = 0;
224         xiocb.xiocb_handle = 0;
225         xiocb.xiocb_flags = 0;
226         xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
227         xiocb.plist.xiocb_buffer.buf_offset = 0;
228         xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
229         xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
230
231         cfe_iocb_dispatch(&xiocb);
232
233         if (xiocb.xiocb_status < 0)
234                 return xiocb.xiocb_status;
235         return xiocb.plist.xiocb_buffer.buf_devflags;
236 }
237 #endif                          /* CFE_API_getdevinfo || CFE_API_ALL */
238
239 #if defined(CFE_API_getenv) || defined(CFE_API_ALL)
240 int cfe_getenv(char *name, char *dest, int destlen)
241 {
242         cfe_xiocb_t xiocb;
243
244         *dest = 0;
245
246         xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
247         xiocb.xiocb_status = 0;
248         xiocb.xiocb_handle = 0;
249         xiocb.xiocb_flags = 0;
250         xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
251         xiocb.plist.xiocb_envbuf.enum_idx = 0;
252         xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
253         xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
254         xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
255         xiocb.plist.xiocb_envbuf.val_length = destlen;
256
257         cfe_iocb_dispatch(&xiocb);
258
259         return xiocb.xiocb_status;
260 }
261 #endif                          /* CFE_API_getenv || CFE_API_ALL */
262
263 #if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL)
264 int cfe_getfwinfo(cfe_fwinfo_t * info)
265 {
266         cfe_xiocb_t xiocb;
267
268         xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
269         xiocb.xiocb_status = 0;
270         xiocb.xiocb_handle = 0;
271         xiocb.xiocb_flags = 0;
272         xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t);
273
274         cfe_iocb_dispatch(&xiocb);
275
276         if (xiocb.xiocb_status < 0)
277                 return xiocb.xiocb_status;
278
279         info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
280         info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
281         info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
282         info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
283         info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
284         info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
285         info->fwi_bootarea_size =
286             xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
287 #if 0
288         info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
289         info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
290         info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
291 #endif
292
293         return 0;
294 }
295 #endif                          /* CFE_API_getfwinfo || CFE_API_ALL */
296
297 #if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL)
298 int cfe_getstdhandle(int flg)
299 {
300         cfe_xiocb_t xiocb;
301
302         xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
303         xiocb.xiocb_status = 0;
304         xiocb.xiocb_handle = 0;
305         xiocb.xiocb_flags = flg;
306         xiocb.xiocb_psize = 0;
307
308         cfe_iocb_dispatch(&xiocb);
309
310         if (xiocb.xiocb_status < 0)
311                 return xiocb.xiocb_status;
312         return xiocb.xiocb_handle;
313 }
314 #endif                          /* CFE_API_getstdhandle || CFE_API_ALL */
315
316 #if defined(CFE_API_getticks) || defined(CFE_API_ALL)
317 int64_t
318 #ifdef CFE_API_IMPL_NAMESPACE
319 __cfe_getticks(void)
320 #else
321 cfe_getticks(void)
322 #endif
323 {
324         cfe_xiocb_t xiocb;
325
326         xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
327         xiocb.xiocb_status = 0;
328         xiocb.xiocb_handle = 0;
329         xiocb.xiocb_flags = 0;
330         xiocb.xiocb_psize = sizeof(xiocb_time_t);
331         xiocb.plist.xiocb_time.ticks = 0;
332
333         cfe_iocb_dispatch(&xiocb);
334
335         return xiocb.plist.xiocb_time.ticks;
336
337 }
338 #endif                          /* CFE_API_getticks || CFE_API_ALL */
339
340 #if defined(CFE_API_inpstat) || defined(CFE_API_ALL)
341 int cfe_inpstat(int handle)
342 {
343         cfe_xiocb_t xiocb;
344
345         xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
346         xiocb.xiocb_status = 0;
347         xiocb.xiocb_handle = handle;
348         xiocb.xiocb_flags = 0;
349         xiocb.xiocb_psize = sizeof(xiocb_inpstat_t);
350         xiocb.plist.xiocb_inpstat.inp_status = 0;
351
352         cfe_iocb_dispatch(&xiocb);
353
354         if (xiocb.xiocb_status < 0)
355                 return xiocb.xiocb_status;
356         return xiocb.plist.xiocb_inpstat.inp_status;
357 }
358 #endif                          /* CFE_API_inpstat || CFE_API_ALL */
359
360 #if defined(CFE_API_ioctl) || defined(CFE_API_ALL)
361 int
362 cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
363           int length, int *retlen, cfe_xuint_t offset)
364 {
365         cfe_xiocb_t xiocb;
366
367         xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
368         xiocb.xiocb_status = 0;
369         xiocb.xiocb_handle = handle;
370         xiocb.xiocb_flags = 0;
371         xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
372         xiocb.plist.xiocb_buffer.buf_offset = offset;
373         xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
374         xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
375         xiocb.plist.xiocb_buffer.buf_length = length;
376
377         cfe_iocb_dispatch(&xiocb);
378
379         if (retlen)
380                 *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
381         return xiocb.xiocb_status;
382 }
383 #endif                          /* CFE_API_ioctl || CFE_API_ALL */
384
385 #if defined(CFE_API_open) || defined(CFE_API_ALL)
386 int cfe_open(char *name)
387 {
388         cfe_xiocb_t xiocb;
389
390         xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
391         xiocb.xiocb_status = 0;
392         xiocb.xiocb_handle = 0;
393         xiocb.xiocb_flags = 0;
394         xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
395         xiocb.plist.xiocb_buffer.buf_offset = 0;
396         xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
397         xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
398
399         cfe_iocb_dispatch(&xiocb);
400
401         if (xiocb.xiocb_status < 0)
402                 return xiocb.xiocb_status;
403         return xiocb.xiocb_handle;
404 }
405 #endif                          /* CFE_API_open || CFE_API_ALL */
406
407 #if defined(CFE_API_read) || defined(CFE_API_ALL)
408 int cfe_read(int handle, unsigned char *buffer, int length)
409 {
410         return cfe_readblk(handle, 0, buffer, length);
411 }
412 #endif                          /* CFE_API_read || CFE_API_ALL */
413
414 #if defined(CFE_API_readblk) || defined(CFE_API_ALL)
415 int
416 cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer,
417             int length)
418 {
419         cfe_xiocb_t xiocb;
420
421         xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
422         xiocb.xiocb_status = 0;
423         xiocb.xiocb_handle = handle;
424         xiocb.xiocb_flags = 0;
425         xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
426         xiocb.plist.xiocb_buffer.buf_offset = offset;
427         xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
428         xiocb.plist.xiocb_buffer.buf_length = length;
429
430         cfe_iocb_dispatch(&xiocb);
431
432         if (xiocb.xiocb_status < 0)
433                 return xiocb.xiocb_status;
434         return xiocb.plist.xiocb_buffer.buf_retlen;
435 }
436 #endif                          /* CFE_API_readblk || CFE_API_ALL */
437
438 #if defined(CFE_API_setenv) || defined(CFE_API_ALL)
439 int cfe_setenv(char *name, char *val)
440 {
441         cfe_xiocb_t xiocb;
442
443         xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
444         xiocb.xiocb_status = 0;
445         xiocb.xiocb_handle = 0;
446         xiocb.xiocb_flags = 0;
447         xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
448         xiocb.plist.xiocb_envbuf.enum_idx = 0;
449         xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
450         xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
451         xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
452         xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val);
453
454         cfe_iocb_dispatch(&xiocb);
455
456         return xiocb.xiocb_status;
457 }
458 #endif                          /* CFE_API_setenv || CFE_API_ALL */
459
460 #if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \
461     && !defined(CFE_API_STRLEN_CUSTOM)
462 int cfe_strlen(char *name)
463 {
464         int count = 0;
465
466         while (*name++)
467                 count++;
468
469         return count;
470 }
471 #endif                          /* CFE_API_strlen || CFE_API_ALL */
472
473 #if defined(CFE_API_write) || defined(CFE_API_ALL)
474 int cfe_write(int handle, unsigned char *buffer, int length)
475 {
476         return cfe_writeblk(handle, 0, buffer, length);
477 }
478 #endif                          /* CFE_API_write || CFE_API_ALL */
479
480 #if defined(CFE_API_writeblk) || defined(CFE_API_ALL)
481 int
482 cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer,
483              int length)
484 {
485         cfe_xiocb_t xiocb;
486
487         xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
488         xiocb.xiocb_status = 0;
489         xiocb.xiocb_handle = handle;
490         xiocb.xiocb_flags = 0;
491         xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
492         xiocb.plist.xiocb_buffer.buf_offset = offset;
493         xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
494         xiocb.plist.xiocb_buffer.buf_length = length;
495
496         cfe_iocb_dispatch(&xiocb);
497
498         if (xiocb.xiocb_status < 0)
499                 return xiocb.xiocb_status;
500         return xiocb.plist.xiocb_buffer.buf_retlen;
501 }
502 #endif                          /* CFE_API_writeblk || CFE_API_ALL */