/arch/mips/fw/cfe/cfe_api.c

http://github.com/mirrors/linux · C · 419 lines · 307 code · 89 blank · 23 comment · 10 complexity · 8682a996c0767b60e933fd020235602d MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
  4. */
  5. /*
  6. *
  7. * Broadcom Common Firmware Environment (CFE)
  8. *
  9. * This module contains device function stubs (small routines to
  10. * call the standard "iocb" interface entry point to CFE).
  11. * There should be one routine here per iocb function call.
  12. *
  13. * Authors: Mitch Lichtenberg, Chris Demetriou
  14. */
  15. #include <asm/fw/cfe/cfe_api.h>
  16. #include "cfe_api_int.h"
  17. /* Cast from a native pointer to a cfe_xptr_t and back. */
  18. #define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
  19. #define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
  20. int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
  21. /*
  22. * Declare the dispatch function with args of "intptr_t".
  23. * This makes sure whatever model we're compiling in
  24. * puts the pointers in a single register. For example,
  25. * combining -mlong64 and -mips1 or -mips2 would lead to
  26. * trouble, since the handle and IOCB pointer will be
  27. * passed in two registers each, and CFE expects one.
  28. */
  29. static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
  30. static u64 cfe_handle;
  31. int cfe_init(u64 handle, u64 ept)
  32. {
  33. cfe_dispfunc = NATIVE_FROM_XPTR(ept);
  34. cfe_handle = handle;
  35. return 0;
  36. }
  37. int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
  38. {
  39. if (!cfe_dispfunc)
  40. return -1;
  41. return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
  42. }
  43. int cfe_close(int handle)
  44. {
  45. struct cfe_xiocb xiocb;
  46. xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
  47. xiocb.xiocb_status = 0;
  48. xiocb.xiocb_handle = handle;
  49. xiocb.xiocb_flags = 0;
  50. xiocb.xiocb_psize = 0;
  51. cfe_iocb_dispatch(&xiocb);
  52. return xiocb.xiocb_status;
  53. }
  54. int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
  55. {
  56. struct cfe_xiocb xiocb;
  57. xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
  58. xiocb.xiocb_status = 0;
  59. xiocb.xiocb_handle = 0;
  60. xiocb.xiocb_flags = 0;
  61. xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
  62. xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
  63. xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
  64. xiocb.plist.xiocb_cpuctl.gp_val = gp;
  65. xiocb.plist.xiocb_cpuctl.sp_val = sp;
  66. xiocb.plist.xiocb_cpuctl.a1_val = a1;
  67. xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
  68. cfe_iocb_dispatch(&xiocb);
  69. return xiocb.xiocb_status;
  70. }
  71. int cfe_cpu_stop(int cpu)
  72. {
  73. struct cfe_xiocb xiocb;
  74. xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
  75. xiocb.xiocb_status = 0;
  76. xiocb.xiocb_handle = 0;
  77. xiocb.xiocb_flags = 0;
  78. xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
  79. xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
  80. xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
  81. cfe_iocb_dispatch(&xiocb);
  82. return xiocb.xiocb_status;
  83. }
  84. int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
  85. {
  86. struct cfe_xiocb xiocb;
  87. xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
  88. xiocb.xiocb_status = 0;
  89. xiocb.xiocb_handle = 0;
  90. xiocb.xiocb_flags = 0;
  91. xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
  92. xiocb.plist.xiocb_envbuf.enum_idx = idx;
  93. xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
  94. xiocb.plist.xiocb_envbuf.name_length = namelen;
  95. xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
  96. xiocb.plist.xiocb_envbuf.val_length = vallen;
  97. cfe_iocb_dispatch(&xiocb);
  98. return xiocb.xiocb_status;
  99. }
  100. int
  101. cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
  102. {
  103. struct cfe_xiocb xiocb;
  104. xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
  105. xiocb.xiocb_status = 0;
  106. xiocb.xiocb_handle = 0;
  107. xiocb.xiocb_flags = flags;
  108. xiocb.xiocb_psize = sizeof(struct xiocb_meminfo);
  109. xiocb.plist.xiocb_meminfo.mi_idx = idx;
  110. cfe_iocb_dispatch(&xiocb);
  111. if (xiocb.xiocb_status < 0)
  112. return xiocb.xiocb_status;
  113. *start = xiocb.plist.xiocb_meminfo.mi_addr;
  114. *length = xiocb.plist.xiocb_meminfo.mi_size;
  115. *type = xiocb.plist.xiocb_meminfo.mi_type;
  116. return 0;
  117. }
  118. int cfe_exit(int warm, int status)
  119. {
  120. struct cfe_xiocb xiocb;
  121. xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
  122. xiocb.xiocb_status = 0;
  123. xiocb.xiocb_handle = 0;
  124. xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
  125. xiocb.xiocb_psize = sizeof(struct xiocb_exitstat);
  126. xiocb.plist.xiocb_exitstat.status = status;
  127. cfe_iocb_dispatch(&xiocb);
  128. return xiocb.xiocb_status;
  129. }
  130. int cfe_flushcache(int flg)
  131. {
  132. struct cfe_xiocb xiocb;
  133. xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
  134. xiocb.xiocb_status = 0;
  135. xiocb.xiocb_handle = 0;
  136. xiocb.xiocb_flags = flg;
  137. xiocb.xiocb_psize = 0;
  138. cfe_iocb_dispatch(&xiocb);
  139. return xiocb.xiocb_status;
  140. }
  141. int cfe_getdevinfo(char *name)
  142. {
  143. struct cfe_xiocb xiocb;
  144. xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
  145. xiocb.xiocb_status = 0;
  146. xiocb.xiocb_handle = 0;
  147. xiocb.xiocb_flags = 0;
  148. xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
  149. xiocb.plist.xiocb_buffer.buf_offset = 0;
  150. xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
  151. xiocb.plist.xiocb_buffer.buf_length = strlen(name);
  152. cfe_iocb_dispatch(&xiocb);
  153. if (xiocb.xiocb_status < 0)
  154. return xiocb.xiocb_status;
  155. return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
  156. }
  157. int cfe_getenv(char *name, char *dest, int destlen)
  158. {
  159. struct cfe_xiocb xiocb;
  160. *dest = 0;
  161. xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
  162. xiocb.xiocb_status = 0;
  163. xiocb.xiocb_handle = 0;
  164. xiocb.xiocb_flags = 0;
  165. xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
  166. xiocb.plist.xiocb_envbuf.enum_idx = 0;
  167. xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
  168. xiocb.plist.xiocb_envbuf.name_length = strlen(name);
  169. xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
  170. xiocb.plist.xiocb_envbuf.val_length = destlen;
  171. cfe_iocb_dispatch(&xiocb);
  172. return xiocb.xiocb_status;
  173. }
  174. int cfe_getfwinfo(cfe_fwinfo_t * info)
  175. {
  176. struct cfe_xiocb xiocb;
  177. xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
  178. xiocb.xiocb_status = 0;
  179. xiocb.xiocb_handle = 0;
  180. xiocb.xiocb_flags = 0;
  181. xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo);
  182. cfe_iocb_dispatch(&xiocb);
  183. if (xiocb.xiocb_status < 0)
  184. return xiocb.xiocb_status;
  185. info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
  186. info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
  187. info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
  188. info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
  189. info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
  190. info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
  191. info->fwi_bootarea_size =
  192. xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
  193. #if 0
  194. info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
  195. info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
  196. info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
  197. #endif
  198. return 0;
  199. }
  200. int cfe_getstdhandle(int flg)
  201. {
  202. struct cfe_xiocb xiocb;
  203. xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
  204. xiocb.xiocb_status = 0;
  205. xiocb.xiocb_handle = 0;
  206. xiocb.xiocb_flags = flg;
  207. xiocb.xiocb_psize = 0;
  208. cfe_iocb_dispatch(&xiocb);
  209. if (xiocb.xiocb_status < 0)
  210. return xiocb.xiocb_status;
  211. return xiocb.xiocb_handle;
  212. }
  213. int64_t
  214. cfe_getticks(void)
  215. {
  216. struct cfe_xiocb xiocb;
  217. xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
  218. xiocb.xiocb_status = 0;
  219. xiocb.xiocb_handle = 0;
  220. xiocb.xiocb_flags = 0;
  221. xiocb.xiocb_psize = sizeof(struct xiocb_time);
  222. xiocb.plist.xiocb_time.ticks = 0;
  223. cfe_iocb_dispatch(&xiocb);
  224. return xiocb.plist.xiocb_time.ticks;
  225. }
  226. int cfe_inpstat(int handle)
  227. {
  228. struct cfe_xiocb xiocb;
  229. xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
  230. xiocb.xiocb_status = 0;
  231. xiocb.xiocb_handle = handle;
  232. xiocb.xiocb_flags = 0;
  233. xiocb.xiocb_psize = sizeof(struct xiocb_inpstat);
  234. xiocb.plist.xiocb_inpstat.inp_status = 0;
  235. cfe_iocb_dispatch(&xiocb);
  236. if (xiocb.xiocb_status < 0)
  237. return xiocb.xiocb_status;
  238. return xiocb.plist.xiocb_inpstat.inp_status;
  239. }
  240. int
  241. cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
  242. int length, int *retlen, u64 offset)
  243. {
  244. struct cfe_xiocb xiocb;
  245. xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
  246. xiocb.xiocb_status = 0;
  247. xiocb.xiocb_handle = handle;
  248. xiocb.xiocb_flags = 0;
  249. xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
  250. xiocb.plist.xiocb_buffer.buf_offset = offset;
  251. xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
  252. xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
  253. xiocb.plist.xiocb_buffer.buf_length = length;
  254. cfe_iocb_dispatch(&xiocb);
  255. if (retlen)
  256. *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
  257. return xiocb.xiocb_status;
  258. }
  259. int cfe_open(char *name)
  260. {
  261. struct cfe_xiocb xiocb;
  262. xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
  263. xiocb.xiocb_status = 0;
  264. xiocb.xiocb_handle = 0;
  265. xiocb.xiocb_flags = 0;
  266. xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
  267. xiocb.plist.xiocb_buffer.buf_offset = 0;
  268. xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
  269. xiocb.plist.xiocb_buffer.buf_length = strlen(name);
  270. cfe_iocb_dispatch(&xiocb);
  271. if (xiocb.xiocb_status < 0)
  272. return xiocb.xiocb_status;
  273. return xiocb.xiocb_handle;
  274. }
  275. int cfe_read(int handle, unsigned char *buffer, int length)
  276. {
  277. return cfe_readblk(handle, 0, buffer, length);
  278. }
  279. int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
  280. {
  281. struct cfe_xiocb xiocb;
  282. xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
  283. xiocb.xiocb_status = 0;
  284. xiocb.xiocb_handle = handle;
  285. xiocb.xiocb_flags = 0;
  286. xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
  287. xiocb.plist.xiocb_buffer.buf_offset = offset;
  288. xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
  289. xiocb.plist.xiocb_buffer.buf_length = length;
  290. cfe_iocb_dispatch(&xiocb);
  291. if (xiocb.xiocb_status < 0)
  292. return xiocb.xiocb_status;
  293. return xiocb.plist.xiocb_buffer.buf_retlen;
  294. }
  295. int cfe_setenv(char *name, char *val)
  296. {
  297. struct cfe_xiocb xiocb;
  298. xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
  299. xiocb.xiocb_status = 0;
  300. xiocb.xiocb_handle = 0;
  301. xiocb.xiocb_flags = 0;
  302. xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
  303. xiocb.plist.xiocb_envbuf.enum_idx = 0;
  304. xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
  305. xiocb.plist.xiocb_envbuf.name_length = strlen(name);
  306. xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
  307. xiocb.plist.xiocb_envbuf.val_length = strlen(val);
  308. cfe_iocb_dispatch(&xiocb);
  309. return xiocb.xiocb_status;
  310. }
  311. int cfe_write(int handle, const char *buffer, int length)
  312. {
  313. return cfe_writeblk(handle, 0, buffer, length);
  314. }
  315. int cfe_writeblk(int handle, s64 offset, const char *buffer, int length)
  316. {
  317. struct cfe_xiocb xiocb;
  318. xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
  319. xiocb.xiocb_status = 0;
  320. xiocb.xiocb_handle = handle;
  321. xiocb.xiocb_flags = 0;
  322. xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
  323. xiocb.plist.xiocb_buffer.buf_offset = offset;
  324. xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
  325. xiocb.plist.xiocb_buffer.buf_length = length;
  326. cfe_iocb_dispatch(&xiocb);
  327. if (xiocb.xiocb_status < 0)
  328. return xiocb.xiocb_status;
  329. return xiocb.plist.xiocb_buffer.buf_retlen;
  330. }