1 /* SPDX-License-Identifier: MIT */ 2 #ifndef __NVKM_FIRMWARE_H__ 3 #define __NVKM_FIRMWARE_H__ 4 #include <core/memory.h> 5 #include <core/option.h> 6 #include <core/subdev.h> 7 8 struct nvkm_firmware { 9 const struct nvkm_firmware_func { 10 enum nvkm_firmware_type { 11 NVKM_FIRMWARE_IMG_RAM, 12 NVKM_FIRMWARE_IMG_DMA, 13 NVKM_FIRMWARE_IMG_SGT, 14 } type; 15 } *func; 16 const char *name; 17 struct nvkm_device *device; 18 19 int len; 20 u8 *img; 21 u64 phys; 22 23 struct nvkm_firmware_mem { 24 struct nvkm_memory memory; 25 union { 26 struct scatterlist sgl; /* DMA */ 27 struct sg_table sgt; /* SGT */ 28 }; 29 } mem; 30 }; 31 32 int nvkm_firmware_ctor(const struct nvkm_firmware_func *, const char *name, struct nvkm_device *, 33 const void *ptr, int len, struct nvkm_firmware *); 34 void nvkm_firmware_dtor(struct nvkm_firmware *); 35 36 int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, int ver, 37 const struct firmware **); 38 void nvkm_firmware_put(const struct firmware *); 39 40 int nvkm_firmware_load_blob(const struct nvkm_subdev *subdev, const char *path, 41 const char *name, int ver, struct nvkm_blob *); 42 int nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *path, 43 const char *name, int ver, 44 const struct firmware **); 45 46 #define nvkm_firmware_load(s,l,o,p...) ({ \ 47 struct nvkm_subdev *_s = (s); \ 48 const char *_opts = (o); \ 49 char _option[32]; \ 50 typeof(l[0]) *_list = (l), *_next, *_fwif = NULL; \ 51 int _ver, _fwv, _ret = 0; \ 52 \ 53 snprintf(_option, sizeof(_option), "Nv%sFw", _opts); \ 54 _ver = nvkm_longopt(_s->device->cfgopt, _option, -2); \ 55 if (_ver >= -1) { \ 56 for (_next = _list; !_fwif && _next->load; _next++) { \ 57 if (_next->version == _ver) \ 58 _fwif = _next; \ 59 } \ 60 _ret = _fwif ? 0 : -EINVAL; \ 61 } \ 62 \ 63 if (_ret == 0) { \ 64 snprintf(_option, sizeof(_option), "Nv%sFwVer", _opts); \ 65 _fwv = _fwif ? _fwif->version : -1; \ 66 _ver = nvkm_longopt(_s->device->cfgopt, _option, _fwv); \ 67 for (_next = _fwif ? _fwif : _list; _next->load; _next++) { \ 68 _fwv = (_ver >= 0) ? _ver : _next->version; \ 69 _ret = _next->load(p, _fwv, _next); \ 70 if (_ret == 0 || _ver >= 0) { \ 71 _fwif = _next; \ 72 break; \ 73 } \ 74 } \ 75 } \ 76 \ 77 if (_ret) \ 78 _fwif = ERR_PTR(_ret); \ 79 _fwif; \ 80 }) 81 #endif 82