Tien Fong Chee | 188d08f | 2018-07-06 16:27:08 +0800 | [diff] [blame^] | 1 | # Copyright (C) 2018 Intel Corporation <www.intel.com> |
| 2 | # |
| 3 | # SPDX-License-Identifier: GPL-2.0 |
| 4 | |
| 5 | Introduction |
| 6 | ============ |
| 7 | |
| 8 | This is file system firmware loader for U-Boot framework, which has very close |
| 9 | to some Linux Firmware API. For the details of Linux Firmware API, you can refer |
| 10 | to https://01.org/linuxgraphics/gfx-docs/drm/driver-api/firmware/index.html. |
| 11 | |
| 12 | File system firmware loader can be used to load whatever(firmware, image, |
| 13 | and binary) from the storage device in file system format into target location |
| 14 | such as memory, then consumer driver such as FPGA driver can program FPGA image |
| 15 | from the target location into FPGA. |
| 16 | |
| 17 | To enable firmware loader, CONFIG_FS_LOADER need to be set at |
| 18 | <board_name>_defconfig such as "CONFIG_FS_LOADER=y". |
| 19 | |
| 20 | Firmware Loader API core features |
| 21 | --------------------------------- |
| 22 | |
| 23 | Firmware storage device described in device tree source |
| 24 | ------------------------------------------------------- |
| 25 | For passing data like storage device phandle and partition where the |
| 26 | firmware loading from to the firmware loader driver, those data could be |
| 27 | defined in fs-loader node as shown in below: |
| 28 | |
| 29 | Example for block device: |
| 30 | fs_loader0: fs-loader@0 { |
| 31 | u-boot,dm-pre-reloc; |
| 32 | compatible = "u-boot,fs-loader"; |
| 33 | phandlepart = <&mmc 1>; |
| 34 | }; |
| 35 | |
| 36 | <&mmc 1> means block storage device pointer and its partition. |
| 37 | |
| 38 | Above example is a description for block storage, but for UBI storage |
| 39 | device, it can be described in FDT as shown in below: |
| 40 | |
| 41 | Example for ubi: |
| 42 | fs_loader1: fs-loader@1 { |
| 43 | u-boot,dm-pre-reloc; |
| 44 | compatible = "u-boot,fs-loader"; |
| 45 | mtdpart = "UBI", |
| 46 | ubivol = "ubi0"; |
| 47 | }; |
| 48 | |
| 49 | Then, firmware_loader property would be set with the path of fs_loader |
| 50 | node under /chosen node such as: |
| 51 | /{ |
| 52 | chosen { |
| 53 | firmware_loader = &fs_loader0; |
| 54 | }; |
| 55 | }; |
| 56 | |
| 57 | However, this driver is also designed to support U-boot environment |
| 58 | variables, so all these data from FDT can be overwritten |
| 59 | through the U-boot environment variable during run time. |
| 60 | For examples: |
| 61 | "storage_interface" - Storage interface, it can be "mmc", "usb", "sata" |
| 62 | or "ubi". |
| 63 | "fw_dev_part" - Block device number and its partition, it can be "0:1". |
| 64 | "fw_ubi_mtdpart" - UBI device mtd partition, it can be "UBI". |
| 65 | "fw_ubi_volume" - UBI volume, it can be "ubi0". |
| 66 | |
| 67 | When above environment variables are set, environment values would be |
| 68 | used instead of data from FDT. |
| 69 | The benefit of this design allows user to change storage attribute data |
| 70 | at run time through U-boot console and saving the setting as default |
| 71 | environment values in the storage for the next power cycle, so no |
| 72 | compilation is required for both driver and FDT. |
| 73 | |
| 74 | File system firmware Loader API |
| 75 | ------------------------------- |
| 76 | |
| 77 | int request_firmware_into_buf(struct device_platdata *plat, |
| 78 | const char *name, |
| 79 | void *buf, size_t size, u32 offset, |
| 80 | struct firmware **firmwarep) |
| 81 | -------------------------------------------------------------------- |
| 82 | Load firmware into a previously allocated buffer |
| 83 | |
| 84 | Parameters: |
| 85 | |
| 86 | 1. struct device_platdata *plat |
| 87 | Platform data such as storage and partition firmware loading from |
| 88 | |
| 89 | 2. const char *name |
| 90 | name of firmware file |
| 91 | |
| 92 | 3. void *buf |
| 93 | address of buffer to load firmware into |
| 94 | |
| 95 | 4. size_t size |
| 96 | size of buffer |
| 97 | |
| 98 | 5. u32 offset |
| 99 | offset of a file for start reading into buffer |
| 100 | |
| 101 | 6. struct firmware **firmwarep |
| 102 | pointer to firmware image |
| 103 | |
| 104 | return: |
| 105 | size of total read |
| 106 | -ve when error |
| 107 | |
| 108 | Description: |
| 109 | The firmware is loaded directly into the buffer pointed to by buf and |
| 110 | the @firmwarep data member is pointed at buf |
| 111 | |
| 112 | Note: Memory would be allocated for firmware image, hence user should |
| 113 | free() *firmwarep and *firmwarep->priv structs after usage of |
| 114 | request_firmware_into_buf(), otherwise it will always leak memory |
| 115 | while subsequent calls of request_firmware_into_buf() with the same |
| 116 | *firmwarep argument. Those arguments can be free through calling API |
| 117 | below release_firmware(); |
| 118 | |
| 119 | Example of creating firmware loader instance and calling |
| 120 | request_firmware_into_buf API: |
| 121 | if (uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &dev)) { |
| 122 | request_firmware_into_buf(dev->plat, filename, buffer_location, |
| 123 | buffer_size, offset_ofreading, &fw); |
| 124 | } |
| 125 | |
| 126 | void release_firmware(struct firmware *firmware) |
| 127 | ------------------------------------------------ |
| 128 | Release the resource associated with a firmware image |
| 129 | |
| 130 | Parameters: |
| 131 | |
| 132 | 1. struct firmware *firmware |
| 133 | Firmware resource to release |