1.. SPDX-License-Identifier: GPL-2.0+
2.. Copyright (C) 2018-2019 Intel Corporation <www.intel.com>
3
4File System Firmware Loader
5===========================
6
7This is file system firmware loader for U-Boot framework, which has very close
8to some Linux Firmware API. For the details of Linux Firmware API, you can refer
9to https://01.org/linuxgraphics/gfx-docs/drm/driver-api/firmware/index.html.
10
11File system firmware loader can be used to load whatever(firmware, image,
12and binary) from the storage device in file system format into target location
13such as memory, then consumer driver such as FPGA driver can program FPGA image
14from the target location into FPGA.
15
16To enable firmware loader, CONFIG_FS_LOADER need to be set at
17<board_name>_defconfig such as "CONFIG_FS_LOADER=y".
18
19Firmware Loader API core features
20---------------------------------
21
22Firmware storage device described in device tree source
23-------------------------------------------------------
24For passing data like storage device phandle and partition where the
25firmware loading from to the firmware loader driver, those data could be
26defined in fs-loader node as shown in below:
27
28Example for block device::
29
30	fs_loader0: fs-loader {
31		bootph-all;
32		compatible = "u-boot,fs-loader";
33		phandlepart = <&mmc 1>;
34	};
35
36<&mmc 1> means block storage device pointer and its partition.
37
38Above example is a description for block storage, but for UBI storage
39device, it can be described in FDT as shown in below:
40
41Example for ubi::
42
43	fs_loader1: fs-loader {
44		bootph-all;
45		compatible = "u-boot,fs-loader";
46		mtdpart = "UBI",
47		ubivol = "ubi0";
48	};
49
50Then, firmware-loader property can be added with any device node, which
51driver would use the firmware loader for loading.
52
53The value of the firmware-loader property should be set with phandle
54of the fs-loader node. For example::
55
56	firmware-loader = <&fs_loader0>;
57
58If there are majority of devices using the same fs-loader node, then
59firmware-loader property can be added under /chosen node instead of
60adding to each of device node.
61
62For example::
63
64	/{
65		chosen {
66			firmware-loader = <&fs_loader0>;
67		};
68	};
69
70In each respective driver of devices using firmware loader, the firmware
71loaded instance	should be created by DT phandle.
72
73For example of getting DT phandle from /chosen and creating instance:
74
75.. code-block:: c
76
77	chosen_node = ofnode_path("/chosen");
78	if (!ofnode_valid(chosen_node)) {
79		debug("/chosen node was not found.\n");
80		return -ENOENT;
81	}
82
83	phandle_p = ofnode_get_property(chosen_node, "firmware-loader", &size);
84	if (!phandle_p) {
85		debug("firmware-loader property was not found.\n");
86		return -ENOENT;
87	}
88
89	phandle = fdt32_to_cpu(*phandle_p);
90	ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
91					     phandle, &dev);
92	if (ret)
93		return ret;
94
95Firmware loader driver is also designed to support U-Boot environment
96variables, so all these data from FDT can be overwritten
97through the U-Boot environment variable during run time.
98
99For examples:
100
101storage_interface:
102  Storage interface, it can be "mmc", "usb", "sata" or "ubi".
103fw_dev_part:
104  Block device number and its partition, it can be "0:1".
105fw_ubi_mtdpart:
106  UBI device mtd partition, it can be "UBI".
107fw_ubi_volume:
108  UBI volume, it can be "ubi0".
109
110When above environment variables are set, environment values would be
111used instead of data from FDT.
112The benefit of this design allows user to change storage attribute data
113at run time through U-Boot console and saving the setting as default
114environment values in the storage for the next power cycle, so no
115compilation is required for both driver and FDT.
116
117File system firmware Loader API
118-------------------------------
119
120.. code-block:: c
121
122	int request_firmware_into_buf(struct udevice *dev,
123				      const char *name,
124				      void *buf, size_t size, u32 offset)
125
126Load firmware into a previously allocated buffer
127
128Parameters:
129
130* struct udevice \*dev: An instance of a driver
131* const char \*name: name of firmware file
132* void \*buf: address of buffer to load firmware into
133* size_t size: size of buffer
134* u32 offset: offset of a file for start reading into buffer
135
136Returns:
137	size of total read
138	-ve when error
139
140Description:
141	The firmware is loaded directly into the buffer pointed to by buf
142
143Example of calling request_firmware_into_buf API after creating firmware loader
144instance:
145
146.. code-block:: c
147
148	ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
149					     phandle, &dev);
150	if (ret)
151		return ret;
152
153	request_firmware_into_buf(dev, filename, buffer_location, buffer_size,
154				 offset_ofreading);
155