xref: /openbmc/linux/arch/mips/fw/cfe/cfe_api.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2df78b5c8SAurelien Jarno /*
3df78b5c8SAurelien Jarno  * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
4df78b5c8SAurelien Jarno  */
5df78b5c8SAurelien Jarno 
6417345d8SChristoph Hellwig /*
7df78b5c8SAurelien Jarno  *
8df78b5c8SAurelien Jarno  * Broadcom Common Firmware Environment (CFE)
9df78b5c8SAurelien Jarno  *
10df78b5c8SAurelien Jarno  * This module contains device function stubs (small routines to
11df78b5c8SAurelien Jarno  * call the standard "iocb" interface entry point to CFE).
12df78b5c8SAurelien Jarno  * There should be one routine here per iocb function call.
13df78b5c8SAurelien Jarno  *
14df78b5c8SAurelien Jarno  * Authors:  Mitch Lichtenberg, Chris Demetriou
15417345d8SChristoph Hellwig  */
16*c059ee9dSFlorian Fainelli #include <linux/init.h>
17*c059ee9dSFlorian Fainelli #include <linux/kernel.h>
18*c059ee9dSFlorian Fainelli #include <linux/printk.h>
19*c059ee9dSFlorian Fainelli #include <asm/mipsregs.h>
20df78b5c8SAurelien Jarno #include <asm/fw/cfe/cfe_api.h>
21df78b5c8SAurelien Jarno #include "cfe_api_int.h"
22df78b5c8SAurelien Jarno 
23*c059ee9dSFlorian Fainelli unsigned long __initdata cfe_seal;
24*c059ee9dSFlorian Fainelli 
25df78b5c8SAurelien Jarno /* Cast from a native pointer to a cfe_xptr_t and back.	 */
26df78b5c8SAurelien Jarno #define XPTR_FROM_NATIVE(n)	((cfe_xptr_t) (intptr_t) (n))
27df78b5c8SAurelien Jarno #define NATIVE_FROM_XPTR(x)	((void *) (intptr_t) (x))
28df78b5c8SAurelien Jarno 
29417345d8SChristoph Hellwig int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
30df78b5c8SAurelien Jarno 
31df78b5c8SAurelien Jarno /*
32df78b5c8SAurelien Jarno  * Declare the dispatch function with args of "intptr_t".
33df78b5c8SAurelien Jarno  * This makes sure whatever model we're compiling in
34df78b5c8SAurelien Jarno  * puts the pointers in a single register.  For example,
35df78b5c8SAurelien Jarno  * combining -mlong64 and -mips1 or -mips2 would lead to
36df78b5c8SAurelien Jarno  * trouble, since the handle and IOCB pointer will be
37df78b5c8SAurelien Jarno  * passed in two registers each, and CFE expects one.
38df78b5c8SAurelien Jarno  */
39df78b5c8SAurelien Jarno 
40982f6ffeSRalf Baechle static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
41982f6ffeSRalf Baechle static u64 cfe_handle;
42df78b5c8SAurelien Jarno 
cfe_init(u64 handle,u64 ept)43417345d8SChristoph Hellwig int cfe_init(u64 handle, u64 ept)
44df78b5c8SAurelien Jarno {
45df78b5c8SAurelien Jarno 	cfe_dispfunc = NATIVE_FROM_XPTR(ept);
46df78b5c8SAurelien Jarno 	cfe_handle = handle;
47df78b5c8SAurelien Jarno 	return 0;
48df78b5c8SAurelien Jarno }
49df78b5c8SAurelien Jarno 
cfe_iocb_dispatch(struct cfe_xiocb * xiocb)50417345d8SChristoph Hellwig int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
51df78b5c8SAurelien Jarno {
52df78b5c8SAurelien Jarno 	if (!cfe_dispfunc)
53df78b5c8SAurelien Jarno 		return -1;
54df78b5c8SAurelien Jarno 	return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
55df78b5c8SAurelien Jarno }
56df78b5c8SAurelien Jarno 
cfe_close(int handle)57df78b5c8SAurelien Jarno int cfe_close(int handle)
58df78b5c8SAurelien Jarno {
59417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
60df78b5c8SAurelien Jarno 
61df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
62df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
63df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = handle;
64df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
65df78b5c8SAurelien Jarno 	xiocb.xiocb_psize = 0;
66df78b5c8SAurelien Jarno 
67df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
68df78b5c8SAurelien Jarno 
69df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
70df78b5c8SAurelien Jarno 
71df78b5c8SAurelien Jarno }
72df78b5c8SAurelien Jarno 
cfe_cpu_start(int cpu,void (* fn)(void),long sp,long gp,long a1)73df78b5c8SAurelien Jarno int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
74df78b5c8SAurelien Jarno {
75417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
76df78b5c8SAurelien Jarno 
77df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
78df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
79df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
80df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
81417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
82df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
83df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
84df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.gp_val = gp;
85df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.sp_val = sp;
86df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.a1_val = a1;
87df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
88df78b5c8SAurelien Jarno 
89df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
90df78b5c8SAurelien Jarno 
91df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
92df78b5c8SAurelien Jarno }
93df78b5c8SAurelien Jarno 
cfe_cpu_stop(int cpu)94df78b5c8SAurelien Jarno int cfe_cpu_stop(int cpu)
95df78b5c8SAurelien Jarno {
96417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
97df78b5c8SAurelien Jarno 
98df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
99df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
100df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
101df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
102417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
103df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
104df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
105df78b5c8SAurelien Jarno 
106df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
107df78b5c8SAurelien Jarno 
108df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
109df78b5c8SAurelien Jarno }
110df78b5c8SAurelien Jarno 
cfe_enumenv(int idx,char * name,int namelen,char * val,int vallen)111df78b5c8SAurelien Jarno int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
112df78b5c8SAurelien Jarno {
113417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
114df78b5c8SAurelien Jarno 
115df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
116df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
117df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
118df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
119417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
120df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.enum_idx = idx;
121df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
122df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.name_length = namelen;
123df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
124df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.val_length = vallen;
125df78b5c8SAurelien Jarno 
126df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
127df78b5c8SAurelien Jarno 
128df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
129df78b5c8SAurelien Jarno }
130df78b5c8SAurelien Jarno 
131df78b5c8SAurelien Jarno int
cfe_enummem(int idx,int flags,u64 * start,u64 * length,u64 * type)132417345d8SChristoph Hellwig cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
133df78b5c8SAurelien Jarno {
134417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
135df78b5c8SAurelien Jarno 
136df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
137df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
138df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
139df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = flags;
140417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_meminfo);
141df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_meminfo.mi_idx = idx;
142df78b5c8SAurelien Jarno 
143df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
144df78b5c8SAurelien Jarno 
145df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
146df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
147df78b5c8SAurelien Jarno 
148df78b5c8SAurelien Jarno 	*start = xiocb.plist.xiocb_meminfo.mi_addr;
149df78b5c8SAurelien Jarno 	*length = xiocb.plist.xiocb_meminfo.mi_size;
150df78b5c8SAurelien Jarno 	*type = xiocb.plist.xiocb_meminfo.mi_type;
151df78b5c8SAurelien Jarno 
152df78b5c8SAurelien Jarno 	return 0;
153df78b5c8SAurelien Jarno }
154df78b5c8SAurelien Jarno 
cfe_exit(int warm,int status)155df78b5c8SAurelien Jarno int cfe_exit(int warm, int status)
156df78b5c8SAurelien Jarno {
157417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
158df78b5c8SAurelien Jarno 
159df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
160df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
161df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
162df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
163417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_exitstat);
164df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_exitstat.status = status;
165df78b5c8SAurelien Jarno 
166df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
167df78b5c8SAurelien Jarno 
168df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
169df78b5c8SAurelien Jarno }
170df78b5c8SAurelien Jarno 
cfe_flushcache(int flg)171df78b5c8SAurelien Jarno int cfe_flushcache(int flg)
172df78b5c8SAurelien Jarno {
173417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
174df78b5c8SAurelien Jarno 
175df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
176df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
177df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
178df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = flg;
179df78b5c8SAurelien Jarno 	xiocb.xiocb_psize = 0;
180df78b5c8SAurelien Jarno 
181df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
182df78b5c8SAurelien Jarno 
183df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
184df78b5c8SAurelien Jarno }
185df78b5c8SAurelien Jarno 
cfe_getdevinfo(char * name)186df78b5c8SAurelien Jarno int cfe_getdevinfo(char *name)
187df78b5c8SAurelien Jarno {
188417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
189df78b5c8SAurelien Jarno 
190df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
191df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
192df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
193df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
194417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
195df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_offset = 0;
196df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
197417345d8SChristoph Hellwig 	xiocb.plist.xiocb_buffer.buf_length = strlen(name);
198df78b5c8SAurelien Jarno 
199df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
200df78b5c8SAurelien Jarno 
201df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
202df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
203417345d8SChristoph Hellwig 	return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
204df78b5c8SAurelien Jarno }
205df78b5c8SAurelien Jarno 
cfe_getenv(char * name,char * dest,int destlen)206df78b5c8SAurelien Jarno int cfe_getenv(char *name, char *dest, int destlen)
207df78b5c8SAurelien Jarno {
208417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
209df78b5c8SAurelien Jarno 
210df78b5c8SAurelien Jarno 	*dest = 0;
211df78b5c8SAurelien Jarno 
212df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
213df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
214df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
215df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
216417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
217df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.enum_idx = 0;
218df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
219417345d8SChristoph Hellwig 	xiocb.plist.xiocb_envbuf.name_length = strlen(name);
220df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
221df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.val_length = destlen;
222df78b5c8SAurelien Jarno 
223df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
224df78b5c8SAurelien Jarno 
225df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
226df78b5c8SAurelien Jarno }
227df78b5c8SAurelien Jarno 
cfe_getfwinfo(cfe_fwinfo_t * info)228df78b5c8SAurelien Jarno int cfe_getfwinfo(cfe_fwinfo_t * info)
229df78b5c8SAurelien Jarno {
230417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
231df78b5c8SAurelien Jarno 
232df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
233df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
234df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
235df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
236417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo);
237df78b5c8SAurelien Jarno 
238df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
239df78b5c8SAurelien Jarno 
240df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
241df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
242df78b5c8SAurelien Jarno 
243df78b5c8SAurelien Jarno 	info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
244df78b5c8SAurelien Jarno 	info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
245df78b5c8SAurelien Jarno 	info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
246df78b5c8SAurelien Jarno 	info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
247df78b5c8SAurelien Jarno 	info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
248df78b5c8SAurelien Jarno 	info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
249df78b5c8SAurelien Jarno 	info->fwi_bootarea_size =
250df78b5c8SAurelien Jarno 	    xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
251df78b5c8SAurelien Jarno 
252df78b5c8SAurelien Jarno 	return 0;
253df78b5c8SAurelien Jarno }
254df78b5c8SAurelien Jarno 
cfe_getstdhandle(int flg)255df78b5c8SAurelien Jarno int cfe_getstdhandle(int flg)
256df78b5c8SAurelien Jarno {
257417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
258df78b5c8SAurelien Jarno 
259df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
260df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
261df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
262df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = flg;
263df78b5c8SAurelien Jarno 	xiocb.xiocb_psize = 0;
264df78b5c8SAurelien Jarno 
265df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
266df78b5c8SAurelien Jarno 
267df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
268df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
269df78b5c8SAurelien Jarno 	return xiocb.xiocb_handle;
270df78b5c8SAurelien Jarno }
271df78b5c8SAurelien Jarno 
272df78b5c8SAurelien Jarno int64_t
cfe_getticks(void)273df78b5c8SAurelien Jarno cfe_getticks(void)
274df78b5c8SAurelien Jarno {
275417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
276df78b5c8SAurelien Jarno 
277df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
278df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
279df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
280df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
281417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_time);
282df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_time.ticks = 0;
283df78b5c8SAurelien Jarno 
284df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
285df78b5c8SAurelien Jarno 
286df78b5c8SAurelien Jarno 	return xiocb.plist.xiocb_time.ticks;
287df78b5c8SAurelien Jarno 
288df78b5c8SAurelien Jarno }
289df78b5c8SAurelien Jarno 
cfe_inpstat(int handle)290df78b5c8SAurelien Jarno int cfe_inpstat(int handle)
291df78b5c8SAurelien Jarno {
292417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
293df78b5c8SAurelien Jarno 
294df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
295df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
296df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = handle;
297df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
298417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_inpstat);
299df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_inpstat.inp_status = 0;
300df78b5c8SAurelien Jarno 
301df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
302df78b5c8SAurelien Jarno 
303df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
304df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
305df78b5c8SAurelien Jarno 	return xiocb.plist.xiocb_inpstat.inp_status;
306df78b5c8SAurelien Jarno }
307df78b5c8SAurelien Jarno 
308df78b5c8SAurelien Jarno int
cfe_ioctl(int handle,unsigned int ioctlnum,unsigned char * buffer,int length,int * retlen,u64 offset)309df78b5c8SAurelien Jarno cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
310417345d8SChristoph Hellwig 	  int length, int *retlen, u64 offset)
311df78b5c8SAurelien Jarno {
312417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
313df78b5c8SAurelien Jarno 
314df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
315df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
316df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = handle;
317df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
318417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
319df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_offset = offset;
320df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
321df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
322df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_length = length;
323df78b5c8SAurelien Jarno 
324df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
325df78b5c8SAurelien Jarno 
326df78b5c8SAurelien Jarno 	if (retlen)
327df78b5c8SAurelien Jarno 		*retlen = xiocb.plist.xiocb_buffer.buf_retlen;
328df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
329df78b5c8SAurelien Jarno }
330df78b5c8SAurelien Jarno 
cfe_open(char * name)331df78b5c8SAurelien Jarno int cfe_open(char *name)
332df78b5c8SAurelien Jarno {
333417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
334df78b5c8SAurelien Jarno 
335df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
336df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
337df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
338df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
339417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
340df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_offset = 0;
341df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
342417345d8SChristoph Hellwig 	xiocb.plist.xiocb_buffer.buf_length = strlen(name);
343df78b5c8SAurelien Jarno 
344df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
345df78b5c8SAurelien Jarno 
346df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
347df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
348df78b5c8SAurelien Jarno 	return xiocb.xiocb_handle;
349df78b5c8SAurelien Jarno }
350df78b5c8SAurelien Jarno 
cfe_read(int handle,unsigned char * buffer,int length)351df78b5c8SAurelien Jarno int cfe_read(int handle, unsigned char *buffer, int length)
352df78b5c8SAurelien Jarno {
353df78b5c8SAurelien Jarno 	return cfe_readblk(handle, 0, buffer, length);
354df78b5c8SAurelien Jarno }
355df78b5c8SAurelien Jarno 
cfe_readblk(int handle,s64 offset,unsigned char * buffer,int length)356417345d8SChristoph Hellwig int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
357df78b5c8SAurelien Jarno {
358417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
359df78b5c8SAurelien Jarno 
360df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
361df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
362df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = handle;
363df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
364417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
365df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_offset = offset;
366df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
367df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_length = length;
368df78b5c8SAurelien Jarno 
369df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
370df78b5c8SAurelien Jarno 
371df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
372df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
373df78b5c8SAurelien Jarno 	return xiocb.plist.xiocb_buffer.buf_retlen;
374df78b5c8SAurelien Jarno }
375df78b5c8SAurelien Jarno 
cfe_setenv(char * name,char * val)376df78b5c8SAurelien Jarno int cfe_setenv(char *name, char *val)
377df78b5c8SAurelien Jarno {
378417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
379df78b5c8SAurelien Jarno 
380df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
381df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
382df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = 0;
383df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
384417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
385df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.enum_idx = 0;
386df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
387417345d8SChristoph Hellwig 	xiocb.plist.xiocb_envbuf.name_length = strlen(name);
388df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
389417345d8SChristoph Hellwig 	xiocb.plist.xiocb_envbuf.val_length = strlen(val);
390df78b5c8SAurelien Jarno 
391df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
392df78b5c8SAurelien Jarno 
393df78b5c8SAurelien Jarno 	return xiocb.xiocb_status;
394df78b5c8SAurelien Jarno }
395df78b5c8SAurelien Jarno 
cfe_write(int handle,const char * buffer,int length)39639b6f3aaSMarkos Chandras int cfe_write(int handle, const char *buffer, int length)
397df78b5c8SAurelien Jarno {
398df78b5c8SAurelien Jarno 	return cfe_writeblk(handle, 0, buffer, length);
399df78b5c8SAurelien Jarno }
400df78b5c8SAurelien Jarno 
cfe_writeblk(int handle,s64 offset,const char * buffer,int length)40139b6f3aaSMarkos Chandras int cfe_writeblk(int handle, s64 offset, const char *buffer, int length)
402df78b5c8SAurelien Jarno {
403417345d8SChristoph Hellwig 	struct cfe_xiocb xiocb;
404df78b5c8SAurelien Jarno 
405df78b5c8SAurelien Jarno 	xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
406df78b5c8SAurelien Jarno 	xiocb.xiocb_status = 0;
407df78b5c8SAurelien Jarno 	xiocb.xiocb_handle = handle;
408df78b5c8SAurelien Jarno 	xiocb.xiocb_flags = 0;
409417345d8SChristoph Hellwig 	xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
410df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_offset = offset;
411df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
412df78b5c8SAurelien Jarno 	xiocb.plist.xiocb_buffer.buf_length = length;
413df78b5c8SAurelien Jarno 
414df78b5c8SAurelien Jarno 	cfe_iocb_dispatch(&xiocb);
415df78b5c8SAurelien Jarno 
416df78b5c8SAurelien Jarno 	if (xiocb.xiocb_status < 0)
417df78b5c8SAurelien Jarno 		return xiocb.xiocb_status;
418df78b5c8SAurelien Jarno 	return xiocb.plist.xiocb_buffer.buf_retlen;
419df78b5c8SAurelien Jarno }
420*c059ee9dSFlorian Fainelli 
cfe_die(char * fmt,...)421*c059ee9dSFlorian Fainelli void __init cfe_die(char *fmt, ...)
422*c059ee9dSFlorian Fainelli {
423*c059ee9dSFlorian Fainelli 	unsigned int prid, __maybe_unused rev;
424*c059ee9dSFlorian Fainelli 	char msg[128];
425*c059ee9dSFlorian Fainelli 	va_list ap;
426*c059ee9dSFlorian Fainelli 	int handle;
427*c059ee9dSFlorian Fainelli 	unsigned int count;
428*c059ee9dSFlorian Fainelli 
429*c059ee9dSFlorian Fainelli 	va_start(ap, fmt);
430*c059ee9dSFlorian Fainelli 	vsprintf(msg, fmt, ap);
431*c059ee9dSFlorian Fainelli 	strcat(msg, "\r\n");
432*c059ee9dSFlorian Fainelli 
433*c059ee9dSFlorian Fainelli 	if (cfe_seal != CFE_EPTSEAL)
434*c059ee9dSFlorian Fainelli 		goto no_cfe;
435*c059ee9dSFlorian Fainelli 
436*c059ee9dSFlorian Fainelli 	prid = read_c0_prid();
437*c059ee9dSFlorian Fainelli 	if ((prid & PRID_COMP_MASK) != PRID_COMP_BROADCOM)
438*c059ee9dSFlorian Fainelli 		goto no_cfe;
439*c059ee9dSFlorian Fainelli 
440*c059ee9dSFlorian Fainelli 	rev = prid & PRID_REV_MASK;
441*c059ee9dSFlorian Fainelli 
442*c059ee9dSFlorian Fainelli 	/* disable XKS01 so that CFE can access the registers */
443*c059ee9dSFlorian Fainelli 	switch (prid & PRID_IMP_MASK) {
444*c059ee9dSFlorian Fainelli #ifdef CONFIG_CPU_BMIPS4380
445*c059ee9dSFlorian Fainelli 	case PRID_IMP_BMIPS43XX:
446*c059ee9dSFlorian Fainelli 		if (rev >= PRID_REV_BMIPS4380_LO &&
447*c059ee9dSFlorian Fainelli 		    rev <= PRID_REV_BMIPS4380_HI)
448*c059ee9dSFlorian Fainelli 			__write_32bit_c0_register($22, 3,
449*c059ee9dSFlorian Fainelli 				__read_32bit_c0_register($22, 3) & ~BIT(12));
450*c059ee9dSFlorian Fainelli 		break;
451*c059ee9dSFlorian Fainelli #endif
452*c059ee9dSFlorian Fainelli #ifdef CONFIG_CPU_BMIPS5000
453*c059ee9dSFlorian Fainelli 	case PRID_IMP_BMIPS5000:
454*c059ee9dSFlorian Fainelli 	case PRID_IMP_BMIPS5200:
455*c059ee9dSFlorian Fainelli 		__write_32bit_c0_register($22, 5,
456*c059ee9dSFlorian Fainelli 			__read_32bit_c0_register($22, 5) & ~BIT(8));
457*c059ee9dSFlorian Fainelli 		break;
458*c059ee9dSFlorian Fainelli #endif
459*c059ee9dSFlorian Fainelli 	default:
460*c059ee9dSFlorian Fainelli 		break;
461*c059ee9dSFlorian Fainelli 	}
462*c059ee9dSFlorian Fainelli 
463*c059ee9dSFlorian Fainelli 	handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
464*c059ee9dSFlorian Fainelli 	if (handle < 0)
465*c059ee9dSFlorian Fainelli 		goto no_cfe;
466*c059ee9dSFlorian Fainelli 
467*c059ee9dSFlorian Fainelli 	cfe_write(handle, msg, strlen(msg));
468*c059ee9dSFlorian Fainelli 
469*c059ee9dSFlorian Fainelli 	for (count = 0; count < 0x7fffffff; count++)
470*c059ee9dSFlorian Fainelli 		mb();
471*c059ee9dSFlorian Fainelli 	cfe_exit(0, 1);
472*c059ee9dSFlorian Fainelli 	while (1)
473*c059ee9dSFlorian Fainelli 		;
474*c059ee9dSFlorian Fainelli 
475*c059ee9dSFlorian Fainelli no_cfe:
476*c059ee9dSFlorian Fainelli 	/* probably won't print anywhere useful */
477*c059ee9dSFlorian Fainelli 	panic("%s", msg);
478*c059ee9dSFlorian Fainelli 
479*c059ee9dSFlorian Fainelli 	va_end(ap);
480*c059ee9dSFlorian Fainelli }
481