From 5c2ae96b60ade14ea1f4afeb50e2a3de56493bcc Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:24 +0800 Subject: [PATCH 01/16] ARM: socfpga: Description on FPGA bitstream type and file name for Arria 10 This patch adds description on properties about file name used for both peripheral bitstream and core bitstream. Signed-off-by: Tien Fong Chee --- .../fpga/altera-socfpga-a10-fpga-mgr.txt | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt b/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt index 2fd8e7a8473..da210bfc86b 100644 --- a/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt +++ b/doc/device-tree-bindings/fpga/altera-socfpga-a10-fpga-mgr.txt @@ -7,8 +7,31 @@ Required properties: - The second index is for writing FPGA configuration data. - resets : Phandle and reset specifier for the device's reset. - clocks : Clocks used by the device. +- altr,bitstream : Fit image file name for both FPGA peripheral bitstream, + FPGA core bitstream and full bitstream. -Example: + Full bitstream, consist of peripheral bitstream and core + bitstream. + + FPGA peripheral bitstream is used to initialize FPGA IOs, + PLL, IO48 and DDR. This bitstream is required to get DDR up + running. + + FPGA core bitstream contains FPGA design which is used to + program FPGA CRAM and ERAM. + +Example: Bundles both peripheral bitstream and core bitstream into FIT image + called fit_spl_fpga.itb. This FIT image can be created through running + this command: tools/mkimage + -E -p 400 + -f board/altera/arria10-socdk/fit_spl_fpga.its + fit_spl_fpga.itb + + For details of describing structure and contents of the FIT image, + please refer board/altera/arria10-socdk/fit_spl_fpga.its + +- Examples for booting with full release or booting with early IO release, then + follow by entering early user mode: fpga_mgr: fpga-mgr@ffd03000 { compatible = "altr,socfpga-a10-fpga-mgr"; @@ -16,4 +39,5 @@ Example: 0xffcfe400 0x20>; clocks = <&l4_mp_clk>; resets = <&rst FPGAMGR_RESET>; + altr,bitstream = "fit_spl_fpga.itb"; }; From f78b505f81334bb7a49d5807e007790d336340c4 Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:25 +0800 Subject: [PATCH 02/16] ARM: socfpga: Add default FPGA bitstream fitImage for Arria10 SoCDK Add default fitImage file bundling FPGA bitstreams for Arria10. Signed-off-by: Tien Fong Chee --- board/altera/arria10-socdk/fit_spl_fpga.its | 38 +++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 board/altera/arria10-socdk/fit_spl_fpga.its diff --git a/board/altera/arria10-socdk/fit_spl_fpga.its b/board/altera/arria10-socdk/fit_spl_fpga.its new file mode 100644 index 00000000000..adae9972139 --- /dev/null +++ b/board/altera/arria10-socdk/fit_spl_fpga.its @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 + /* + * Copyright (C) 2019 Intel Corporation + * + */ + +/dts-v1/; + +/ { + description = "FIT image with FPGA bistream"; + #address-cells = <1>; + + images { + fpga-periph-1 { + description = "FPGA peripheral bitstream"; + data = /incbin/("../../../ghrd_10as066n2.periph.rbf"); + type = "fpga"; + arch = "arm"; + compression = "none"; + }; + + fpga-core-1 { + description = "FPGA core bitstream"; + data = /incbin/("../../../ghrd_10as066n2.core.rbf"); + type = "fpga"; + arch = "arm"; + compression = "none"; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "Boot with FPGA early IO release config"; + fpga = "fpga-periph-1", "fpga-core-1"; + }; + }; +}; From f4b53b24d04fb223a6d5332c3744b955c462326d Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:26 +0800 Subject: [PATCH 03/16] ARM: socfpga: Cleaning up and ensuring consistent format messages in driver Ensure all the debug messages are always prefix with "FPGA: " and comment beginning with uppercase letter. Signed-off-by: Tien Fong Chee --- drivers/fpga/socfpga_arria10.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index 114dd910ab0..b0abe1955cf 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -94,7 +94,7 @@ int fpgamgr_wait_early_user_mode(void) i++; } - debug("Additional %i sync word needed\n", i); + debug("FPGA: Additional %i sync word needed\n", i); /* restoring original CDRATIO */ fpgamgr_set_cd_ratio(cd_ratio); @@ -172,9 +172,10 @@ static int fpgamgr_set_cdratio_cdwidth(unsigned int cfg_width, u32 *rbf_data, compress = (rbf_data[COMPRESSION_OFFSET] >> 1) & 1; compress = !compress; - debug("header word %d = %08x\n", 69, rbf_data[69]); - debug("header word %d = %08x\n", 229, rbf_data[229]); - debug("read from rbf header: encrypt=%d compress=%d\n", encrypt, compress); + debug("FPGA: Header word %d = %08x.\n", 69, rbf_data[69]); + debug("FPGA: Header word %d = %08x.\n", 229, rbf_data[229]); + debug("FPGA: Read from rbf header: encrypt=%d compress=%d.\n", encrypt, + compress); /* * from the register map description of cdratio in imgcfg_ctrl_02: @@ -455,10 +456,10 @@ int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) { int status; - /* disable all signals from hps peripheral controller to fpga */ + /* Disable all signals from hps peripheral controller to fpga */ writel(0, &system_manager_base->fpgaintf_en_global); - /* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */ + /* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */ socfpga_bridges_reset(); /* Initialize the FPGA Manager */ From c1cf5391807640159edcd363ea1cbaf226a56b58 Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:27 +0800 Subject: [PATCH 04/16] ARM: socfpga: Moving the watchdog reset to the for-loop status polling Current watchdog reset is misplaced after for-loop status polling, so this poses a risk that watchdog can't be reset timely if polling taking longer than watchdog timeout. This patch moving the watchdog reset into polling to ensure the watchdog can be reset timely. Signed-off-by: Tien Fong Chee --- drivers/fpga/socfpga_arria10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index b0abe1955cf..9499d1a0144 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -360,6 +360,7 @@ static int fpgamgr_program_poll_cd(void) printf("nstatus == 0 while waiting for condone\n"); return -EPERM; } + WATCHDOG_RESET(); } if (i == FPGA_TIMEOUT_CNT) @@ -433,7 +434,6 @@ int fpgamgr_program_finish(void) printf("FPGA: Poll CD failed with error code %d\n", status); return -EPERM; } - WATCHDOG_RESET(); /* Ensure the FPGA entering user mode */ status = fpgamgr_program_poll_usermode(); From 0a42a132a4b846031df2c4a7d04692240ed34843 Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:28 +0800 Subject: [PATCH 05/16] ARM: socfpga: Add FPGA drivers for Arria 10 FPGA bitstream loading Add FPGA driver to support program FPGA with FPGA bitstream loading from filesystem. The driver are designed based on generic firmware loader framework. The driver can handle FPGA program operation from loading FPGA bitstream in flash to memory and then to program FPGA. Signed-off-by: Tien Fong Chee --- arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts | 17 + .../include/mach/fpga_manager_arria10.h | 39 +- drivers/fpga/socfpga_arria10.c | 497 +++++++++++++++++- include/image.h | 4 + 4 files changed, 542 insertions(+), 15 deletions(-) diff --git a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts index 998d8112101..cc761967c77 100644 --- a/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts +++ b/arch/arm/dts/socfpga_arria10_socdk_sdmmc.dts @@ -18,6 +18,23 @@ /dts-v1/; #include "socfpga_arria10_socdk.dtsi" +/ { + chosen { + firmware-loader = <&fs_loader0>; + }; + + fs_loader0: fs-loader { + u-boot,dm-pre-reloc; + compatible = "u-boot,fs-loader"; + phandlepart = <&mmc 1>; + }; +}; + +&fpga_mgr { + u-boot,dm-pre-reloc; + altr,bitstream = "fit_spl_fpga.itb"; +}; + &mmc { u-boot,dm-pre-reloc; status = "okay"; diff --git a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h index 09d13f6fd3c..c5f67714aa8 100644 --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h @@ -1,9 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2017 Intel Corporation + * Copyright (C) 2017-2019 Intel Corporation * All rights reserved. */ +#include +#include +#include + #ifndef _FPGA_MANAGER_ARRIA10_H_ #define _FPGA_MANAGER_ARRIA10_H_ @@ -51,6 +55,10 @@ #define ALT_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SET_MSK BIT(24) #define ALT_FPGAMGR_IMGCFG_CTL_02_CDRATIO_LSB 16 +#define FPGA_SOCFPGA_A10_RBF_UNENCRYPTED 0xa65c +#define FPGA_SOCFPGA_A10_RBF_ENCRYPTED 0xa65d +#define FPGA_SOCFPGA_A10_RBF_PERIPH 0x0001 +#define FPGA_SOCFPGA_A10_RBF_CORE 0x8001 #ifndef __ASSEMBLY__ struct socfpga_fpga_manager { @@ -88,12 +96,39 @@ struct socfpga_fpga_manager { u32 imgcfg_fifo_status; }; +enum rbf_type { + unknown, + periph_section, + core_section +}; + +enum rbf_security { + invalid, + unencrypted, + encrypted +}; + +struct rbf_info { + enum rbf_type section; + enum rbf_security security; +}; + +struct fpga_loadfs_info { + fpga_fs_info *fpga_fsinfo; + u32 remaining; + u32 offset; + struct rbf_info rbfinfo; +}; + /* Functions */ int fpgamgr_program_init(u32 * rbf_data, size_t rbf_size); int fpgamgr_program_finish(void); int is_fpgamgr_user_mode(void); int fpgamgr_wait_early_user_mode(void); - +const char *get_fpga_filename(void); +int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize, + u32 offset); +void fpgamgr_program(const void *buf, size_t bsize, u32 offset); #endif /* __ASSEMBLY__ */ #endif /* _FPGA_MANAGER_ARRIA10_H_ */ diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index 9499d1a0144..9df2c430d7d 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2017 Intel Corporation + * Copyright (C) 2017-2019 Intel Corporation */ - #include #include #include @@ -10,8 +9,11 @@ #include #include #include +#include #include +#include #include +#include #include #include @@ -21,6 +23,9 @@ #define COMPRESSION_OFFSET 229 #define FPGA_TIMEOUT_MSEC 1000 /* timeout in ms */ #define FPGA_TIMEOUT_CNT 0x1000000 +#define DEFAULT_DDR_LOAD_ADDRESS 0x400 + +DECLARE_GLOBAL_DATA_PTR; static const struct socfpga_fpga_manager *fpga_manager_base = (void *)SOCFPGA_FPGAMGRREGS_ADDRESS; @@ -448,13 +453,461 @@ int fpgamgr_program_finish(void) return 0; } -/* - * FPGA Manager to program the FPGA. This is the interface used by FPGA driver. - * Return 0 for sucess, non-zero for error. - */ +ofnode get_fpga_mgr_ofnode(ofnode from) +{ + return ofnode_by_compatible(from, "altr,socfpga-a10-fpga-mgr"); +} + +const char *get_fpga_filename(void) +{ + const char *fpga_filename = NULL; + + ofnode fpgamgr_node = get_fpga_mgr_ofnode(ofnode_null()); + + if (ofnode_valid(fpgamgr_node)) + fpga_filename = ofnode_read_string(fpgamgr_node, + "altr,bitstream"); + + return fpga_filename; +} + +static void get_rbf_image_info(struct rbf_info *rbf, u16 *buffer) +{ + /* + * Magic ID starting at: + * -> 1st dword[15:0] in periph.rbf + * -> 2nd dword[15:0] in core.rbf + * Note: dword == 32 bits + */ + u32 word_reading_max = 2; + u32 i; + + for (i = 0; i < word_reading_max; i++) { + if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) { + rbf->security = unencrypted; + } else if (*(buffer + i) == FPGA_SOCFPGA_A10_RBF_ENCRYPTED) { + rbf->security = encrypted; + } else if (*(buffer + i + 1) == + FPGA_SOCFPGA_A10_RBF_UNENCRYPTED) { + rbf->security = unencrypted; + } else if (*(buffer + i + 1) == + FPGA_SOCFPGA_A10_RBF_ENCRYPTED) { + rbf->security = encrypted; + } else { + rbf->security = invalid; + continue; + } + + /* PERIPH RBF(buffer + i + 1), CORE RBF(buffer + i + 2) */ + if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_PERIPH) { + rbf->section = periph_section; + break; + } else if (*(buffer + i + 1) == FPGA_SOCFPGA_A10_RBF_CORE) { + rbf->section = core_section; + break; + } else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_PERIPH) { + rbf->section = periph_section; + break; + } else if (*(buffer + i + 2) == FPGA_SOCFPGA_A10_RBF_CORE) { + rbf->section = core_section; + break; + } + + rbf->section = unknown; + break; + + WATCHDOG_RESET(); + } +} + +#ifdef CONFIG_FS_LOADER +static int first_loading_rbf_to_buffer(struct udevice *dev, + struct fpga_loadfs_info *fpga_loadfs, + u32 *buffer, size_t *buffer_bsize) +{ + u32 *buffer_p = (u32 *)*buffer; + u32 *loadable = buffer_p; + size_t buffer_size = *buffer_bsize; + size_t fit_size; + int ret, i, count, confs_noffset, images_noffset, rbf_offset, rbf_size; + const char *fpga_node_name = NULL; + const char *uname = NULL; + + /* Load image header into buffer */ + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, sizeof(struct image_header), + 0); + if (ret < 0) { + debug("FPGA: Failed to read image header from flash.\n"); + return -ENOENT; + } + + if (image_get_magic((struct image_header *)buffer_p) != FDT_MAGIC) { + debug("FPGA: No FDT magic was found.\n"); + return -EBADF; + } + + fit_size = fdt_totalsize(buffer_p); + + if (fit_size > buffer_size) { + debug("FPGA: FIT image is larger than available buffer.\n"); + debug("Please use FIT external data or increasing buffer.\n"); + return -ENOMEM; + } + + /* Load entire FIT into buffer */ + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, fit_size, 0); + if (ret < 0) + return ret; + + ret = fit_check_format(buffer_p); + if (!ret) { + debug("FPGA: No valid FIT image was found.\n"); + return -EBADF; + } + + confs_noffset = fdt_path_offset(buffer_p, FIT_CONFS_PATH); + images_noffset = fdt_path_offset(buffer_p, FIT_IMAGES_PATH); + if (confs_noffset < 0 || images_noffset < 0) { + debug("FPGA: No Configurations or images nodes were found.\n"); + return -ENOENT; + } + + /* Get default configuration unit name from default property */ + confs_noffset = fit_conf_get_node(buffer_p, NULL); + if (confs_noffset < 0) { + debug("FPGA: No default configuration was found in config.\n"); + return -ENOENT; + } + + count = fit_conf_get_prop_node_count(buffer_p, confs_noffset, + FIT_FPGA_PROP); + if (count < 0) { + debug("FPGA: Invalid configuration format for FPGA node.\n"); + return count; + } + debug("FPGA: FPGA node count: %d\n", count); + + for (i = 0; i < count; i++) { + images_noffset = fit_conf_get_prop_node_index(buffer_p, + confs_noffset, + FIT_FPGA_PROP, i); + uname = fit_get_name(buffer_p, images_noffset, NULL); + if (uname) { + debug("FPGA: %s\n", uname); + + if (strstr(uname, "fpga-periph") && + (!is_fpgamgr_early_user_mode() || + is_fpgamgr_user_mode())) { + fpga_node_name = uname; + printf("FPGA: Start to program "); + printf("peripheral/full bitstream ...\n"); + break; + } else if (strstr(uname, "fpga-core") && + (is_fpgamgr_early_user_mode() && + !is_fpgamgr_user_mode())) { + fpga_node_name = uname; + printf("FPGA: Start to program core "); + printf("bitstream ...\n"); + break; + } + } + WATCHDOG_RESET(); + } + + if (!fpga_node_name) { + debug("FPGA: No suitable bitstream was found, count: %d.\n", i); + return 1; + } + + images_noffset = fit_image_get_node(buffer_p, fpga_node_name); + if (images_noffset < 0) { + debug("FPGA: No node '%s' was found in FIT.\n", + fpga_node_name); + return -ENOENT; + } + + if (!fit_image_get_data_position(buffer_p, images_noffset, + &rbf_offset)) { + debug("FPGA: Data position was found.\n"); + } else if (!fit_image_get_data_offset(buffer_p, images_noffset, + &rbf_offset)) { + /* + * For FIT with external data, figure out where + * the external images start. This is the base + * for the data-offset properties in each image. + */ + rbf_offset += ((fdt_totalsize(buffer_p) + 3) & ~3); + debug("FPGA: Data offset was found.\n"); + } else { + debug("FPGA: No data position/offset was found.\n"); + return -ENOENT; + } + + ret = fit_image_get_data_size(buffer_p, images_noffset, &rbf_size); + if (ret < 0) { + debug("FPGA: No data size was found (err=%d).\n", ret); + return -ENOENT; + } + + if (gd->ram_size < rbf_size) { + debug("FPGA: Using default OCRAM buffer and size.\n"); + } else { + ret = fit_image_get_load(buffer_p, images_noffset, + (ulong *)loadable); + if (ret < 0) { + buffer_p = (u32 *)DEFAULT_DDR_LOAD_ADDRESS; + debug("FPGA: No loadable was found.\n"); + debug("FPGA: Using default DDR load address: 0x%x .\n", + DEFAULT_DDR_LOAD_ADDRESS); + } else { + buffer_p = (u32 *)*loadable; + debug("FPGA: Found loadable address = 0x%x.\n", + *loadable); + } + + buffer_size = rbf_size; + } + + debug("FPGA: External data: offset = 0x%x, size = 0x%x.\n", + rbf_offset, rbf_size); + + fpga_loadfs->remaining = rbf_size; + + /* + * Determine buffer size vs bitstream size, and calculating number of + * chunk by chunk transfer is required due to smaller buffer size + * compare to bitstream + */ + if (rbf_size <= buffer_size) { + /* Loading whole bitstream into buffer */ + buffer_size = rbf_size; + fpga_loadfs->remaining = 0; + } else { + fpga_loadfs->remaining -= buffer_size; + } + + fpga_loadfs->offset = rbf_offset; + /* Loading bitstream into buffer */ + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, buffer_size, + fpga_loadfs->offset); + if (ret < 0) { + debug("FPGA: Failed to read bitstream from flash.\n"); + return -ENOENT; + } + + /* Getting info about bitstream types */ + get_rbf_image_info(&fpga_loadfs->rbfinfo, (u16 *)buffer_p); + + /* Update next reading bitstream offset */ + fpga_loadfs->offset += buffer_size; + + /* Update the final addr for bitstream */ + *buffer = (u32)buffer_p; + + /* Update the size of bitstream to be programmed into FPGA */ + *buffer_bsize = buffer_size; + + return 0; +} + +static int subsequent_loading_rbf_to_buffer(struct udevice *dev, + struct fpga_loadfs_info *fpga_loadfs, + u32 *buffer, size_t *buffer_bsize) +{ + int ret = 0; + u32 *buffer_p = (u32 *)*buffer; + + /* Read the bitstream chunk by chunk. */ + if (fpga_loadfs->remaining > *buffer_bsize) { + fpga_loadfs->remaining -= *buffer_bsize; + } else { + *buffer_bsize = fpga_loadfs->remaining; + fpga_loadfs->remaining = 0; + } + + ret = request_firmware_into_buf(dev, + fpga_loadfs->fpga_fsinfo->filename, + buffer_p, *buffer_bsize, + fpga_loadfs->offset); + if (ret < 0) { + debug("FPGA: Failed to read bitstream from flash.\n"); + return -ENOENT; + } + + /* Update next reading bitstream offset */ + fpga_loadfs->offset += *buffer_bsize; + + return 0; +} + +int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize, + u32 offset) +{ + struct fpga_loadfs_info fpga_loadfs; + struct udevice *dev; + int status, ret, size; + u32 buffer = (uintptr_t)buf; + size_t buffer_sizebytes = bsize; + size_t buffer_sizebytes_ori = bsize; + size_t total_sizeof_image = 0; + ofnode node; + const fdt32_t *phandle_p; + u32 phandle; + + node = get_fpga_mgr_ofnode(ofnode_null()); + + if (ofnode_valid(node)) { + phandle_p = ofnode_get_property(node, "firmware-loader", &size); + if (!phandle_p) { + node = ofnode_path("/chosen"); + if (!ofnode_valid(node)) { + debug("FPGA: /chosen node was not found.\n"); + return -ENOENT; + } + + phandle_p = ofnode_get_property(node, "firmware-loader", + &size); + if (!phandle_p) { + debug("FPGA: firmware-loader property was not"); + debug(" found.\n"); + return -ENOENT; + } + } + } else { + debug("FPGA: FPGA manager node was not found.\n"); + return -ENOENT; + } + + phandle = fdt32_to_cpu(*phandle_p); + ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER, + phandle, &dev); + if (ret) + return ret; + + memset(&fpga_loadfs, 0, sizeof(fpga_loadfs)); + + fpga_loadfs.fpga_fsinfo = fpga_fsinfo; + fpga_loadfs.offset = offset; + + printf("FPGA: Checking FPGA configuration setting ...\n"); + + /* + * Note: Both buffer and buffer_sizebytes values can be altered by + * function below. + */ + ret = first_loading_rbf_to_buffer(dev, &fpga_loadfs, &buffer, + &buffer_sizebytes); + if (ret == 1) { + printf("FPGA: Skipping configuration ...\n"); + return 0; + } else if (ret) { + return ret; + } + + if (fpga_loadfs.rbfinfo.section == core_section && + !(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) { + debug("FPGA : Must be in Early Release mode to program "); + debug("core bitstream.\n"); + return -EPERM; + } + + /* Disable all signals from HPS peripheral controller to FPGA */ + writel(0, &system_manager_base->fpgaintf_en_global); + + /* Disable all axi bridges (hps2fpga, lwhps2fpga & fpga2hps) */ + socfpga_bridges_reset(); + + if (fpga_loadfs.rbfinfo.section == periph_section) { + /* Initialize the FPGA Manager */ + status = fpgamgr_program_init((u32 *)buffer, buffer_sizebytes); + if (status) { + debug("FPGA: Init with peripheral bitstream failed.\n"); + return -EPERM; + } + } + + /* Transfer bitstream to FPGA Manager */ + fpgamgr_program_write((void *)buffer, buffer_sizebytes); + + total_sizeof_image += buffer_sizebytes; + + while (fpga_loadfs.remaining) { + ret = subsequent_loading_rbf_to_buffer(dev, + &fpga_loadfs, + &buffer, + &buffer_sizebytes_ori); + + if (ret) + return ret; + + /* Transfer data to FPGA Manager */ + fpgamgr_program_write((void *)buffer, + buffer_sizebytes_ori); + + total_sizeof_image += buffer_sizebytes_ori; + + WATCHDOG_RESET(); + } + + if (fpga_loadfs.rbfinfo.section == periph_section) { + if (fpgamgr_wait_early_user_mode() != -ETIMEDOUT) { + config_pins(gd->fdt_blob, "shared"); + puts("FPGA: Early Release Succeeded.\n"); + } else { + debug("FPGA: Failed to see Early Release.\n"); + return -EIO; + } + + /* For monolithic bitstream */ + if (is_fpgamgr_user_mode()) { + /* Ensure the FPGA entering config done */ + status = fpgamgr_program_finish(); + if (status) + return status; + + config_pins(gd->fdt_blob, "fpga"); + puts("FPGA: Enter user mode.\n"); + } + } else if (fpga_loadfs.rbfinfo.section == core_section) { + /* Ensure the FPGA entering config done */ + status = fpgamgr_program_finish(); + if (status) + return status; + + config_pins(gd->fdt_blob, "fpga"); + puts("FPGA: Enter user mode.\n"); + } else { + debug("FPGA: Config Error: Unsupported bitstream type.\n"); + return -ENOEXEC; + } + + return (int)total_sizeof_image; +} + +void fpgamgr_program(const void *buf, size_t bsize, u32 offset) +{ + fpga_fs_info fpga_fsinfo; + + fpga_fsinfo.filename = get_fpga_filename(); + + if (fpga_fsinfo.filename) + socfpga_loadfs(&fpga_fsinfo, buf, bsize, offset); +} +#endif + +/* This function is used to load the core bitstream from the OCRAM. */ int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) { - int status; + unsigned long status; + struct rbf_info rbfinfo; + + memset(&rbfinfo, 0, sizeof(rbfinfo)); /* Disable all signals from hps peripheral controller to fpga */ writel(0, &system_manager_base->fpgaintf_en_global); @@ -462,13 +915,31 @@ int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) /* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */ socfpga_bridges_reset(); - /* Initialize the FPGA Manager */ - status = fpgamgr_program_init((u32 *)rbf_data, rbf_size); - if (status) - return status; + /* Getting info about bitstream types */ + get_rbf_image_info(&rbfinfo, (u16 *)rbf_data); - /* Write the RBF data to FPGA Manager */ + if (rbfinfo.section == periph_section) { + /* Initialize the FPGA Manager */ + status = fpgamgr_program_init((u32 *)rbf_data, rbf_size); + if (status) + return status; + } + + if (rbfinfo.section == core_section && + !(is_fpgamgr_early_user_mode() && !is_fpgamgr_user_mode())) { + debug("FPGA : Must be in early release mode to program "); + debug("core bitstream.\n"); + return -EPERM; + } + + /* Write the bitstream to FPGA Manager */ fpgamgr_program_write(rbf_data, rbf_size); - return fpgamgr_program_finish(); + status = fpgamgr_program_finish(); + if (status) { + config_pins(gd->fdt_blob, "fpga"); + puts("FPGA: Enter user mode.\n"); + } + + return status; } diff --git a/include/image.h b/include/image.h index bfe4e0b5e7a..bb7089ef5d1 100644 --- a/include/image.h +++ b/include/image.h @@ -1046,6 +1046,10 @@ int fit_check_format(const void *fit); int fit_conf_find_compat(const void *fit, const void *fdt); int fit_conf_get_node(const void *fit, const char *conf_uname); +int fit_conf_get_prop_node_count(const void *fit, int noffset, + const char *prop_name); +int fit_conf_get_prop_node_index(const void *fit, int noffset, + const char *prop_name, int index); /** * fit_conf_get_prop_node() - Get node refered to by a configuration From f61d52926086bf56c870f06ba5e88bdb41ac246e Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:29 +0800 Subject: [PATCH 06/16] ARM: socfpga: Add the configuration for FPGA SoCFPGA A10 SoCDK Update the default configuration file to enable the necessary functionality to get the SoCFPGA loadfs driver support. This would enable the implementation of programming bitstream into FPGA from MMC. Signed-off-by: Tien Fong Chee --- configs/socfpga_arria10_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/configs/socfpga_arria10_defconfig b/configs/socfpga_arria10_defconfig index 47fe1d96900..1931a1d1536 100644 --- a/configs/socfpga_arria10_defconfig +++ b/configs/socfpga_arria10_defconfig @@ -25,7 +25,18 @@ CONFIG_MTDIDS_DEFAULT="nor0=ff705000.spi.0" # CONFIG_EFI_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="socfpga_arria10_socdk_sdmmc" CONFIG_ENV_IS_IN_MMC=y +CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_DM_MMC=y +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL_EXT_SUPPORT=y +CONFIG_SPL_FS_FAT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_FS_LOADER=y +CONFIG_FPGA_SOCFPGA=y +CONFIG_SPL_FIT=y +CONFIG_FIT=y CONFIG_DM_GPIO=y CONFIG_DWAPB_GPIO=y CONFIG_DM_MMC=y From 1085bb3cbaf8321fdc8d0eaa367192433bd51d44 Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:30 +0800 Subject: [PATCH 07/16] spl: socfpga: Implement fpga bitstream loading with socfpga loadfs Add support for loading FPGA bitstream to get DDR up running before U-Boot is loaded into DDR. Boot device initialization, generic firmware loader and SPL FAT support are required for this whole mechanism to work. Signed-off-by: Tien Fong Chee --- .../include/mach/fpga_manager_arria10.h | 1 + arch/arm/mach-socfpga/spl_a10.c | 31 ++++++++++++++++++- drivers/fpga/socfpga_arria10.c | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h index c5f67714aa8..62249b3695e 100644 --- a/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/fpga_manager_arria10.h @@ -126,6 +126,7 @@ int fpgamgr_program_finish(void); int is_fpgamgr_user_mode(void); int fpgamgr_wait_early_user_mode(void); const char *get_fpga_filename(void); +int is_fpgamgr_early_user_mode(void); int socfpga_loadfs(fpga_fs_info *fpga_fsinfo, const void *buf, size_t bsize, u32 offset); void fpgamgr_program(const void *buf, size_t bsize, u32 offset); diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index c8e73d47c0b..b466307f985 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2012 Altera Corporation + * Copyright (C) 2012-2019 Altera Corporation */ #include @@ -23,6 +23,11 @@ #include #include #include +#include +#include +#include + +#define FPGA_BUFSIZ 16 * 1024 DECLARE_GLOBAL_DATA_PTR; @@ -68,11 +73,35 @@ u32 spl_boot_mode(const u32 boot_device) void spl_board_init(void) { + ALLOC_CACHE_ALIGN_BUFFER(char, buf, FPGA_BUFSIZ); + /* enable console uart printing */ preloader_console_init(); WATCHDOG_RESET(); arch_early_init_r(); + + /* If the full FPGA is already loaded, ie.from EPCQ, config fpga pins */ + if (is_fpgamgr_user_mode()) { + int ret = config_pins(gd->fdt_blob, "shared"); + + if (ret) + return; + + ret = config_pins(gd->fdt_blob, "fpga"); + if (ret) + return; + } else if (!is_fpgamgr_early_user_mode()) { + /* Program IOSSM(early IO release) or full FPGA */ + fpgamgr_program(buf, FPGA_BUFSIZ, 0); + } + + /* If the IOSSM/full FPGA is already loaded, start DDR */ + if (is_fpgamgr_early_user_mode() || is_fpgamgr_user_mode()) + ddr_calibration_sequence(); + + if (!is_fpgamgr_user_mode()) + fpgamgr_program(buf, FPGA_BUFSIZ, 0); } void board_init_f(ulong dummy) diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index 9df2c430d7d..285280e507f 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -69,7 +69,7 @@ static int wait_for_user_mode(void) 1, FPGA_TIMEOUT_MSEC, false); } -static int is_fpgamgr_early_user_mode(void) +int is_fpgamgr_early_user_mode(void) { return (readl(&fpga_manager_base->imgcfg_stat) & ALT_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE_SET_MSK) != 0; From 1a0d0b78412e8bfcb0e4f7ceb883881d79f29303 Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:31 +0800 Subject: [PATCH 08/16] ARM: socfpga: Synchronize the configuration for A10 SoCDK Update the default configuration file to enable the necessary functionality the get the kit working. Signed-off-by: Tien Fong Chee --- configs/socfpga_arria10_defconfig | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/configs/socfpga_arria10_defconfig b/configs/socfpga_arria10_defconfig index 1931a1d1536..09a018c97d1 100644 --- a/configs/socfpga_arria10_defconfig +++ b/configs/socfpga_arria10_defconfig @@ -6,12 +6,15 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200" # CONFIG_USE_BOOTCOMMAND is not set +CONFIG_SYS_CONSOLE_IS_IN_ENV=y +CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y +CONFIG_SYS_CONSOLE_ENV_OVERWRITE=y CONFIG_DEFAULT_FDT_FILE="socfpga_arria10_socdk_sdmmc.dtb" +CONFIG_VERSION_VARIABLE=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_BOUNCE_BUFFER=y CONFIG_SPL_TEXT_BASE=0xFFE00000 CONFIG_SPL_FPGA_SUPPORT=y -CONFIG_SPL_SPI_LOAD=y CONFIG_CMD_ASKENV=y CONFIG_CMD_GREPENV=y # CONFIG_CMD_FLASH is not set @@ -20,9 +23,7 @@ CONFIG_CMD_MMC=y CONFIG_CMD_CACHE=y CONFIG_CMD_EXT4_WRITE=y CONFIG_MTDIDS_DEFAULT="nor0=ff705000.spi.0" -# CONFIG_SPL_DOS_PARTITION is not set -# CONFIG_ISO_PARTITION is not set -# CONFIG_EFI_PARTITION is not set +CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-parent dmas dma-names" CONFIG_DEFAULT_DEVICE_TREE="socfpga_arria10_socdk_sdmmc" CONFIG_ENV_IS_IN_MMC=y CONFIG_SPL_ENV_SUPPORT=y @@ -30,7 +31,6 @@ CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SPL_DM_MMC=y CONFIG_SPL_MMC_SUPPORT=y -CONFIG_SPL_EXT_SUPPORT=y CONFIG_SPL_FS_FAT=y CONFIG_SPL_DRIVERS_MISC_SUPPORT=y CONFIG_FS_LOADER=y @@ -41,9 +41,13 @@ CONFIG_DM_GPIO=y CONFIG_DWAPB_GPIO=y CONFIG_DM_MMC=y CONFIG_MTD_DEVICE=y +CONFIG_MMC_DW=y +CONFIG_PHY_MICREL=y +CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_MII=y +CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_TIMER=y CONFIG_SPL_TIMER=y From da0d5f6f731d44b66eb645920f7a9e6735b490cf Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Tue, 7 May 2019 17:42:32 +0800 Subject: [PATCH 09/16] ARM: socfpga: Increase Malloc pool size to support FAT filesystem in SPL Increasing Malloc pool size up to 0x15000 is required to support FAT in SPL . The result of calculation is come from default max cluster(0x10000) + others(0x2000) + additional memory for headroom(0x3000). Signed-off-by: Tien Fong Chee --- include/configs/socfpga_arria10_socdk.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/configs/socfpga_arria10_socdk.h b/include/configs/socfpga_arria10_socdk.h index 92630c5e6e3..645e66e6b09 100644 --- a/include/configs/socfpga_arria10_socdk.h +++ b/include/configs/socfpga_arria10_socdk.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2015-2017 Altera Corporation + * Copyright (C) 2015-2019 Altera Corporation */ #ifndef __CONFIG_SOCFGPA_ARRIA10_H__ @@ -36,6 +36,9 @@ */ #define CONFIG_SYS_MAX_FLASH_BANKS 1 +/* SPL memory allocation configuration, this is for FAT implementation */ +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00015000 + /* The rest of the configuration is shared */ #include From 8ede7515fe50f670f7a7835a24e0cff7596b6c16 Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Wed, 8 May 2019 11:07:37 +0800 Subject: [PATCH 10/16] configs: stratix10: Enable CONFIG_SPI_FLASH_USE_4K_SECTORS Fix SPI flash environment erase size error. CONFIG_ENV_SECT_SIZE is set to 4KB. Enable CONFIG_SPI_FLASH_USE_4K_SECTORS to allow erase one environment sector. Fix error below: SOCFPGA_STRATIX10 # saveenv Saving Environment to SPI Flash... SF: Detected mt25qu02g with page size 256 Bytes, erase size 64 KiB, total 256 MiB Erasing SPI flash...SF: Erase offset/length not multiple of erase size Failed (-22) Signed-off-by: Ley Foon Tan --- configs/socfpga_stratix10_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/socfpga_stratix10_defconfig b/configs/socfpga_stratix10_defconfig index 18cc9594500..fbab388b43c 100644 --- a/configs/socfpga_stratix10_defconfig +++ b/configs/socfpga_stratix10_defconfig @@ -42,7 +42,6 @@ CONFIG_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0x2003 CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y -# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_DM_ETH=y From 460a97f3a2d4308b804f833b1a0beb0cf92c925e Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 9 May 2019 22:11:55 +0200 Subject: [PATCH 11/16] timer: dw-apb: remove unused DECLARE_GLOBAL_DATA_PTR The dw-apb timer does not use 'gd', so remove its declaration. Signed-off-by: Simon Goldschmidt --- drivers/timer/dw-apb-timer.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/timer/dw-apb-timer.c b/drivers/timer/dw-apb-timer.c index cb48801af16..86312b8dc76 100644 --- a/drivers/timer/dw-apb-timer.c +++ b/drivers/timer/dw-apb-timer.c @@ -17,8 +17,6 @@ #define DW_APB_CURR_VAL 0x4 #define DW_APB_CTRL 0x8 -DECLARE_GLOBAL_DATA_PTR; - struct dw_apb_timer_priv { fdt_addr_t regs; }; From 46b633d7b4ed7a3053093ba901559f61d0ed92c6 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 9 May 2019 22:11:56 +0200 Subject: [PATCH 12/16] spi: cadence_qspi: convert to livetree Convert 'cadence_spi_ofdata_to_platdata' to use dev_read_* functions to read driver parameters and 'dev_read_first_subnode'/'ofnode_read_*' to read flash (child node) parameters. Tested on socfpga_socrates (socfpga gen5). Signed-off-by: Simon Goldschmidt --- drivers/spi/cadence_qspi.c | 39 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 41c87004d8c..e2e54cd2772 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -18,8 +18,6 @@ #define CQSPI_INDIRECT_READ 2 #define CQSPI_INDIRECT_WRITE 3 -DECLARE_GLOBAL_DATA_PTR; - static int cadence_spi_write_speed(struct udevice *bus, uint hz) { struct cadence_spi_platdata *plat = bus->platdata; @@ -295,36 +293,37 @@ static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen, static int cadence_spi_ofdata_to_platdata(struct udevice *bus) { struct cadence_spi_platdata *plat = bus->platdata; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(bus); - int subnode; + ofnode subnode; plat->regbase = (void *)devfdt_get_addr_index(bus, 0); plat->ahbbase = (void *)devfdt_get_addr_index(bus, 1); - plat->is_decoded_cs = fdtdec_get_bool(blob, node, "cdns,is-decoded-cs"); - plat->fifo_depth = fdtdec_get_uint(blob, node, "cdns,fifo-depth", 128); - plat->fifo_width = fdtdec_get_uint(blob, node, "cdns,fifo-width", 4); - plat->trigger_address = fdtdec_get_uint(blob, node, - "cdns,trigger-address", 0); + plat->is_decoded_cs = dev_read_bool(bus, "cdns,is-decoded-cs"); + plat->fifo_depth = dev_read_u32_default(bus, "cdns,fifo-depth", 128); + plat->fifo_width = dev_read_u32_default(bus, "cdns,fifo-width", 4); + plat->trigger_address = dev_read_u32_default(bus, + "cdns,trigger-address", + 0); /* All other paramters are embedded in the child node */ - subnode = fdt_first_subnode(blob, node); - if (subnode < 0) { + subnode = dev_read_first_subnode(bus); + if (!ofnode_valid(subnode)) { printf("Error: subnode with SPI flash config missing!\n"); return -ENODEV; } /* Use 500 KHz as a suitable default */ - plat->max_hz = fdtdec_get_uint(blob, subnode, "spi-max-frequency", - 500000); + plat->max_hz = ofnode_read_u32_default(subnode, "spi-max-frequency", + 500000); /* Read other parameters from DT */ - plat->page_size = fdtdec_get_uint(blob, subnode, "page-size", 256); - plat->block_size = fdtdec_get_uint(blob, subnode, "block-size", 16); - plat->tshsl_ns = fdtdec_get_uint(blob, subnode, "cdns,tshsl-ns", 200); - plat->tsd2d_ns = fdtdec_get_uint(blob, subnode, "cdns,tsd2d-ns", 255); - plat->tchsh_ns = fdtdec_get_uint(blob, subnode, "cdns,tchsh-ns", 20); - plat->tslch_ns = fdtdec_get_uint(blob, subnode, "cdns,tslch-ns", 20); + plat->page_size = ofnode_read_u32_default(subnode, "page-size", 256); + plat->block_size = ofnode_read_u32_default(subnode, "block-size", 16); + plat->tshsl_ns = ofnode_read_u32_default(subnode, "cdns,tshsl-ns", + 200); + plat->tsd2d_ns = ofnode_read_u32_default(subnode, "cdns,tsd2d-ns", + 255); + plat->tchsh_ns = ofnode_read_u32_default(subnode, "cdns,tchsh-ns", 20); + plat->tslch_ns = ofnode_read_u32_default(subnode, "cdns,tslch-ns", 20); debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n", __func__, plat->regbase, plat->ahbbase, plat->max_hz, From 27c3e07bcbddba1bc5f0ac3d58a2d1a1a99de5ea Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 9 May 2019 22:11:57 +0200 Subject: [PATCH 13/16] spi: designware: convert to livetree Convert 'dw_spi_ofdata_to_platdata' to use 'dev_read_u32_default' instead of 'fdtdec_get_int' and get rid of DECLARE_GLOBAL_DATA_PTR. Signed-off-by: Simon Goldschmidt --- drivers/spi/designware_spi.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index dadb6fa18b0..7d58cfae55e 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -22,8 +22,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - /* Register offsets */ #define DW_SPI_CTRL0 0x00 #define DW_SPI_CTRL1 0x04 @@ -155,14 +153,12 @@ static int request_gpio_cs(struct udevice *bus) static int dw_spi_ofdata_to_platdata(struct udevice *bus) { struct dw_spi_platdata *plat = bus->platdata; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(bus); plat->regs = (struct dw_spi *)devfdt_get_addr(bus); /* Use 500KHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 500000); + plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", + 500000); debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs, plat->frequency); From 41b22c0acc957b927d1496dd43e4db0fe8233e90 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 9 May 2019 22:11:58 +0200 Subject: [PATCH 14/16] serial: altera_uart: convert to livetree Convert 'altera_uart_ofdata_to_platdata' to use 'dev_read_u32_default' instead of 'fdtdec_get_int' and get rid of DECLARE_GLOBAL_DATA_PTR. Signed-off-by: Simon Goldschmidt --- drivers/serial/altera_uart.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 67d47199aa4..436cf2331df 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -10,8 +10,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - /* status register */ #define ALTERA_UART_TMT BIT(5) /* tx empty */ #define ALTERA_UART_TRDY BIT(6) /* tx ready */ @@ -91,8 +89,7 @@ static int altera_uart_ofdata_to_platdata(struct udevice *dev) plat->regs = map_physmem(devfdt_get_addr(dev), sizeof(struct altera_uart_regs), MAP_NOCACHE); - plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "clock-frequency", 0); + plat->uartclk = dev_read_u32_default(dev, "clock-frequency", 0); return 0; } From 6cdd0a4e5424d7600b556d8e0f3f7f65b6b5854d Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 9 May 2019 22:11:59 +0200 Subject: [PATCH 15/16] reset: socfpga: convert to livetree Convert 'socfpga_reset_probe' to use 'dev_read_u32_default' instead of 'fdtdec_get_int'. Signed-off-by: Simon Goldschmidt --- drivers/reset/reset-socfpga.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index cb8312619fa..ee4cbcb02ff 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -107,14 +107,12 @@ static const struct reset_ops socfpga_reset_ops = { static int socfpga_reset_probe(struct udevice *dev) { struct socfpga_reset_data *data = dev_get_priv(dev); - const void *blob = gd->fdt_blob; - int node = dev_of_offset(dev); u32 modrst_offset; void __iomem *membase; membase = devfdt_get_addr_ptr(dev); - modrst_offset = fdtdec_get_int(blob, node, "altr,modrst-offset", 0x10); + modrst_offset = dev_read_u32_default(dev, "altr,modrst-offset", 0x10); data->modrst_base = membase + modrst_offset; return 0; From 1b898ffc040b5977a07af755b8ba3aa151914800 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 9 May 2019 22:12:00 +0200 Subject: [PATCH 16/16] gpio: dwapb_gpio: convert to livetree Convert 'gpio_dwapb_bind' to iterate over subnodes using livetree functions (inspired from mt7621_gpio.c). Signed-off-by: Simon Goldschmidt --- drivers/gpio/dwapb_gpio.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index e55fb4ac73d..04a2381acd8 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -17,8 +17,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - #define GPIO_SWPORT_DR(p) (0x00 + (p) * 0xc) #define GPIO_SWPORT_DDR(p) (0x04 + (p) * 0xc) #define GPIO_INTEN 0x30 @@ -150,10 +148,10 @@ static int gpio_dwapb_probe(struct udevice *dev) static int gpio_dwapb_bind(struct udevice *dev) { struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); - const void *blob = gd->fdt_blob; struct udevice *subdev; fdt_addr_t base; - int ret, node, bank = 0; + int ret, bank = 0; + ofnode node; /* If this is a child device, there is nothing to do here */ if (plat) @@ -165,10 +163,9 @@ static int gpio_dwapb_bind(struct udevice *dev) return -ENXIO; } - for (node = fdt_first_subnode(blob, dev_of_offset(dev)); - node > 0; - node = fdt_next_subnode(blob, node)) { - if (!fdtdec_get_bool(blob, node, "gpio-controller")) + for (node = dev_read_first_subnode(dev); ofnode_valid(node); + node = dev_read_next_subnode(node)) { + if (!ofnode_read_bool(node, "gpio-controller")) continue; plat = devm_kcalloc(dev, 1, sizeof(*plat), GFP_KERNEL); @@ -177,15 +174,15 @@ static int gpio_dwapb_bind(struct udevice *dev) plat->base = base; plat->bank = bank; - plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0); - plat->name = fdt_stringlist_get(blob, node, "bank-name", 0, - NULL); - if (!plat->name) { + plat->pins = ofnode_read_u32_default(node, "snps,nr-gpios", 0); + + if (ofnode_read_string_index(node, "bank-name", 0, + &plat->name)) { /* * Fall back to node name. This means accessing pins * via bank name won't work. */ - plat->name = fdt_get_name(blob, node, NULL); + plat->name = ofnode_get_name(node); } ret = device_bind(dev, dev->driver, plat->name, @@ -193,7 +190,7 @@ static int gpio_dwapb_bind(struct udevice *dev) if (ret) return ret; - dev_set_of_offset(subdev, node); + dev->node = node; bank++; }