Tien Fong Chee | 4502975 | 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 | |
Tien Fong Chee | 31a2cf1 | 2018-12-10 21:29:44 +0800 | [diff] [blame] | 77 | int request_firmware_into_buf(struct udevice *dev, |
Tien Fong Chee | 4502975 | 2018-07-06 16:27:08 +0800 | [diff] [blame] | 78 | const char *name, |
Tien Fong Chee | 31a2cf1 | 2018-12-10 21:29:44 +0800 | [diff] [blame] | 79 | void *buf, size_t size, u32 offset) |
Tien Fong Chee | 4502975 | 2018-07-06 16:27:08 +0800 | [diff] [blame] | 80 | -------------------------------------------------------------------- |
| 81 | Load firmware into a previously allocated buffer |
| 82 | |
| 83 | Parameters: |
| 84 | |
Tien Fong Chee | 31a2cf1 | 2018-12-10 21:29:44 +0800 | [diff] [blame] | 85 | 1. struct udevice *dev |
| 86 | An instance of a driver |
Tien Fong Chee | 4502975 | 2018-07-06 16:27:08 +0800 | [diff] [blame] | 87 | |
| 88 | 2. const char *name |
| 89 | name of firmware file |
| 90 | |
| 91 | 3. void *buf |
| 92 | address of buffer to load firmware into |
| 93 | |
| 94 | 4. size_t size |
| 95 | size of buffer |
| 96 | |
| 97 | 5. u32 offset |
| 98 | offset of a file for start reading into buffer |
| 99 | |
Tien Fong Chee | 4502975 | 2018-07-06 16:27:08 +0800 | [diff] [blame] | 100 | return: |
| 101 | size of total read |
| 102 | -ve when error |
| 103 | |
| 104 | Description: |
Tien Fong Chee | 31a2cf1 | 2018-12-10 21:29:44 +0800 | [diff] [blame] | 105 | The firmware is loaded directly into the buffer pointed to by buf |
Tien Fong Chee | 4502975 | 2018-07-06 16:27:08 +0800 | [diff] [blame] | 106 | |
| 107 | Example of creating firmware loader instance and calling |
| 108 | request_firmware_into_buf API: |
| 109 | if (uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &dev)) { |
Tien Fong Chee | 31a2cf1 | 2018-12-10 21:29:44 +0800 | [diff] [blame] | 110 | request_firmware_into_buf(dev, filename, buffer_location, |
| 111 | buffer_size, offset_ofreading); |
Tien Fong Chee | 4502975 | 2018-07-06 16:27:08 +0800 | [diff] [blame] | 112 | } |