stratix10-soc-fpga-mgr.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2019-2024 Ruslan Bukin <br@bsdpad.com>
  5. *
  6. * This software was developed by SRI International and the University of
  7. * Cambridge Computer Laboratory (Department of Computer Science and
  8. * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
  9. * DARPA SSITH research programme.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. */
  32. /*
  33. * Intel Stratix 10 FPGA Manager.
  34. *
  35. * FPGA Programming Example:
  36. * dd if=cheri.core.rbf of=/dev/fpga_partial0 bs=512k
  37. */
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/bus.h>
  41. #include <sys/kernel.h>
  42. #include <sys/module.h>
  43. #include <sys/malloc.h>
  44. #include <sys/rman.h>
  45. #include <sys/timeet.h>
  46. #include <sys/timetc.h>
  47. #include <sys/conf.h>
  48. #include <sys/uio.h>
  49. #include <sys/sx.h>
  50. #include <dev/ofw/openfirm.h>
  51. #include <dev/ofw/ofw_bus.h>
  52. #include <dev/ofw/ofw_bus_subr.h>
  53. #include <arm64/intel/stratix10-svc.h>
  54. #include <machine/bus.h>
  55. #include <machine/cpu.h>
  56. #include <machine/intr.h>
  57. #define SVC_BUF_SIZE (512 * 1024)
  58. struct fpgamgr_s10_softc {
  59. struct cdev *mgr_cdev;
  60. struct cdev *mgr_cdev_partial;
  61. device_t dev;
  62. device_t s10_svc_dev;
  63. struct s10_svc_mem mem;
  64. struct sx sx;
  65. int opened;
  66. };
  67. static int
  68. fpga_open(struct cdev *dev, int flags __unused,
  69. int fmt __unused, struct thread *td __unused)
  70. {
  71. struct fpgamgr_s10_softc *sc;
  72. struct s10_svc_msg msg;
  73. int ret;
  74. int err;
  75. sc = dev->si_drv1;
  76. sx_xlock(&sc->sx);
  77. if (sc->opened) {
  78. sx_xunlock(&sc->sx);
  79. return (EBUSY);
  80. }
  81. err = s10_svc_allocate_memory(sc->s10_svc_dev,
  82. &sc->mem, SVC_BUF_SIZE);
  83. if (err != 0) {
  84. sx_xunlock(&sc->sx);
  85. return (ENXIO);
  86. }
  87. bzero(&msg, sizeof(struct s10_svc_msg));
  88. msg.command = COMMAND_RECONFIG;
  89. if (dev == sc->mgr_cdev_partial)
  90. msg.flags |= COMMAND_RECONFIG_FLAG_PARTIAL;
  91. ret = s10_svc_send(sc->s10_svc_dev, &msg);
  92. if (ret != 0) {
  93. sx_xunlock(&sc->sx);
  94. return (ENXIO);
  95. }
  96. sc->opened = 1;
  97. sx_xunlock(&sc->sx);
  98. return (0);
  99. }
  100. static int
  101. fpga_submit(struct cdev *dev)
  102. {
  103. struct fpgamgr_s10_softc *sc;
  104. struct s10_svc_msg msg;
  105. int ret;
  106. sc = dev->si_drv1;
  107. bzero(&msg, sizeof(struct s10_svc_msg));
  108. msg.command = COMMAND_RECONFIG_DATA_SUBMIT;
  109. msg.payload = (void *)sc->mem.paddr;
  110. msg.payload_length = sc->mem.fill;
  111. ret = s10_svc_send(sc->s10_svc_dev, &msg);
  112. if (ret != 0) {
  113. device_printf(sc->dev, "Failed to submit data\n");
  114. s10_svc_free_memory(sc->s10_svc_dev, &sc->mem);
  115. sc->opened = 0;
  116. return (ENXIO);
  117. }
  118. /* Claim memory buffer back. */
  119. bzero(&msg, sizeof(struct s10_svc_msg));
  120. msg.command = COMMAND_RECONFIG_DATA_CLAIM;
  121. ret = s10_svc_send(sc->s10_svc_dev, &msg);
  122. if (ret)
  123. device_printf(sc->dev, "Can't claim buffer back.\n");
  124. return (ret);
  125. }
  126. static int
  127. fpga_write(struct cdev *dev, struct uio *uio, int ioflag)
  128. {
  129. struct fpgamgr_s10_softc *sc;
  130. vm_offset_t addr;
  131. int error;
  132. int amnt;
  133. int ret;
  134. sc = dev->si_drv1;
  135. sx_xlock(&sc->sx);
  136. if (sc->opened == 0) {
  137. /* Device closed. */
  138. sx_xunlock(&sc->sx);
  139. return (ENXIO);
  140. }
  141. while (uio->uio_resid > 0) {
  142. addr = sc->mem.vaddr + sc->mem.fill;
  143. amnt = MIN(uio->uio_resid, (SVC_BUF_SIZE - sc->mem.fill));
  144. error = uiomove((void *)addr, amnt, uio);
  145. if (error) {
  146. device_printf(sc->dev, "uiomove returned error %d\n",
  147. error);
  148. break;
  149. }
  150. sc->mem.fill += amnt;
  151. if (sc->mem.fill == SVC_BUF_SIZE) {
  152. ret = fpga_submit(dev);
  153. if (ret) {
  154. sx_xunlock(&sc->sx);
  155. return (ret);
  156. }
  157. sc->mem.fill = 0;
  158. }
  159. }
  160. sx_xunlock(&sc->sx);
  161. return (0);
  162. }
  163. static int
  164. fpga_close(struct cdev *dev, int flags __unused,
  165. int fmt __unused, struct thread *td __unused)
  166. {
  167. struct fpgamgr_s10_softc *sc;
  168. int ret;
  169. sc = dev->si_drv1;
  170. sx_xlock(&sc->sx);
  171. if (sc->opened == 0) {
  172. /* Device closed. */
  173. sx_xunlock(&sc->sx);
  174. return (ENXIO);
  175. }
  176. if (sc->mem.fill > 0) {
  177. ret = fpga_submit(dev);
  178. if (ret) {
  179. sx_xunlock(&sc->sx);
  180. return (ret);
  181. }
  182. sc->mem.fill = 0;
  183. }
  184. s10_svc_free_memory(sc->s10_svc_dev, &sc->mem);
  185. sc->opened = 0;
  186. sx_xunlock(&sc->sx);
  187. return (0);
  188. }
  189. static int
  190. fpga_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
  191. struct thread *td)
  192. {
  193. return (0);
  194. }
  195. static struct cdevsw fpga_cdevsw = {
  196. .d_version = D_VERSION,
  197. .d_open = fpga_open,
  198. .d_close = fpga_close,
  199. .d_write = fpga_write,
  200. .d_ioctl = fpga_ioctl,
  201. .d_name = "FPGA Manager",
  202. };
  203. static int
  204. fpgamgr_s10_probe(device_t dev)
  205. {
  206. if (!ofw_bus_status_okay(dev))
  207. return (ENXIO);
  208. if (!ofw_bus_is_compatible(dev, "intel,stratix10-soc-fpga-mgr"))
  209. return (ENXIO);
  210. device_set_desc(dev, "Stratix 10 SOC FPGA Manager");
  211. return (BUS_PROBE_DEFAULT);
  212. }
  213. static int
  214. fpgamgr_s10_attach(device_t dev)
  215. {
  216. struct fpgamgr_s10_softc *sc;
  217. devclass_t dc;
  218. sc = device_get_softc(dev);
  219. sc->dev = dev;
  220. dc = devclass_find("s10_svc");
  221. if (dc == NULL)
  222. return (ENXIO);
  223. sc->s10_svc_dev = devclass_get_device(dc, 0);
  224. if (sc->s10_svc_dev == NULL)
  225. return (ENXIO);
  226. sc->mgr_cdev = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
  227. 0600, "fpga%d", device_get_unit(sc->dev));
  228. if (sc->mgr_cdev == NULL) {
  229. device_printf(dev, "Failed to create character device.\n");
  230. return (ENXIO);
  231. }
  232. sc->mgr_cdev_partial = make_dev(&fpga_cdevsw, 0, UID_ROOT, GID_WHEEL,
  233. 0600, "fpga_partial%d", device_get_unit(sc->dev));
  234. if (sc->mgr_cdev_partial == NULL) {
  235. device_printf(dev, "Failed to create character device.\n");
  236. return (ENXIO);
  237. }
  238. sx_init(&sc->sx, "s10 fpga");
  239. sc->mgr_cdev->si_drv1 = sc;
  240. sc->mgr_cdev_partial->si_drv1 = sc;
  241. return (0);
  242. }
  243. static int
  244. fpgamgr_s10_detach(device_t dev)
  245. {
  246. struct fpgamgr_s10_softc *sc;
  247. sc = device_get_softc(dev);
  248. destroy_dev(sc->mgr_cdev);
  249. destroy_dev(sc->mgr_cdev_partial);
  250. sx_destroy(&sc->sx);
  251. return (0);
  252. }
  253. static device_method_t fpgamgr_s10_methods[] = {
  254. DEVMETHOD(device_probe, fpgamgr_s10_probe),
  255. DEVMETHOD(device_attach, fpgamgr_s10_attach),
  256. DEVMETHOD(device_detach, fpgamgr_s10_detach),
  257. { 0, 0 }
  258. };
  259. static driver_t fpgamgr_s10_driver = {
  260. "fpgamgr_s10",
  261. fpgamgr_s10_methods,
  262. sizeof(struct fpgamgr_s10_softc),
  263. };
  264. DRIVER_MODULE(fpgamgr_s10, simplebus, fpgamgr_s10_driver, 0, 0);