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