diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/arm_ffa/driver.c | 101 | ||||
-rw-r--r-- | drivers/firmware/broadcom/bcm47xx_nvram.c | 18 | ||||
-rw-r--r-- | drivers/firmware/cirrus/Kconfig | 2 | ||||
-rw-r--r-- | drivers/firmware/cirrus/Makefile | 2 | ||||
-rw-r--r-- | drivers/firmware/cirrus/cs_dsp.c | 79 | ||||
-rw-r--r-- | drivers/firmware/efi/cper.c | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/earlycon.c | 8 | ||||
-rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 2 | ||||
-rw-r--r-- | drivers/firmware/efi/efi.c | 19 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 1 | ||||
-rw-r--r-- | drivers/firmware/imx/scu-pd.c | 1 | ||||
-rw-r--r-- | drivers/firmware/raspberrypi.c | 47 | ||||
-rw-r--r-- | drivers/firmware/tegra/Kconfig | 1 | ||||
-rw-r--r-- | drivers/firmware/tegra/bpmp-debugfs.c | 62 | ||||
-rw-r--r-- | drivers/firmware/tegra/bpmp-tegra186.c | 36 | ||||
-rw-r--r-- | drivers/firmware/tegra/bpmp-tegra210.c | 15 | ||||
-rw-r--r-- | drivers/firmware/tegra/bpmp.c | 33 | ||||
-rw-r--r-- | drivers/firmware/tegra/ivc.c | 150 | ||||
-rw-r--r-- | drivers/firmware/ti_sci.c | 24 | ||||
-rw-r--r-- | drivers/firmware/xilinx/zynqmp.c | 7 |
20 files changed, 317 insertions, 294 deletions
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index d5e86ef40b89..fa85c64d3ded 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -36,81 +36,6 @@ #include "common.h" #define FFA_DRIVER_VERSION FFA_VERSION_1_0 - -#define FFA_SMC(calling_convention, func_num) \ - ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \ - ARM_SMCCC_OWNER_STANDARD, (func_num)) - -#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num)) -#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num)) - -#define FFA_ERROR FFA_SMC_32(0x60) -#define FFA_SUCCESS FFA_SMC_32(0x61) -#define FFA_INTERRUPT FFA_SMC_32(0x62) -#define FFA_VERSION FFA_SMC_32(0x63) -#define FFA_FEATURES FFA_SMC_32(0x64) -#define FFA_RX_RELEASE FFA_SMC_32(0x65) -#define FFA_RXTX_MAP FFA_SMC_32(0x66) -#define FFA_FN64_RXTX_MAP FFA_SMC_64(0x66) -#define FFA_RXTX_UNMAP FFA_SMC_32(0x67) -#define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68) -#define FFA_ID_GET FFA_SMC_32(0x69) -#define FFA_MSG_POLL FFA_SMC_32(0x6A) -#define FFA_MSG_WAIT FFA_SMC_32(0x6B) -#define FFA_YIELD FFA_SMC_32(0x6C) -#define FFA_RUN FFA_SMC_32(0x6D) -#define FFA_MSG_SEND FFA_SMC_32(0x6E) -#define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_32(0x6F) -#define FFA_FN64_MSG_SEND_DIRECT_REQ FFA_SMC_64(0x6F) -#define FFA_MSG_SEND_DIRECT_RESP FFA_SMC_32(0x70) -#define FFA_FN64_MSG_SEND_DIRECT_RESP FFA_SMC_64(0x70) -#define FFA_MEM_DONATE FFA_SMC_32(0x71) -#define FFA_FN64_MEM_DONATE FFA_SMC_64(0x71) -#define FFA_MEM_LEND FFA_SMC_32(0x72) -#define FFA_FN64_MEM_LEND FFA_SMC_64(0x72) -#define FFA_MEM_SHARE FFA_SMC_32(0x73) -#define FFA_FN64_MEM_SHARE FFA_SMC_64(0x73) -#define FFA_MEM_RETRIEVE_REQ FFA_SMC_32(0x74) -#define FFA_FN64_MEM_RETRIEVE_REQ FFA_SMC_64(0x74) -#define FFA_MEM_RETRIEVE_RESP FFA_SMC_32(0x75) -#define FFA_MEM_RELINQUISH FFA_SMC_32(0x76) -#define FFA_MEM_RECLAIM FFA_SMC_32(0x77) -#define FFA_MEM_OP_PAUSE FFA_SMC_32(0x78) -#define FFA_MEM_OP_RESUME FFA_SMC_32(0x79) -#define FFA_MEM_FRAG_RX FFA_SMC_32(0x7A) -#define FFA_MEM_FRAG_TX FFA_SMC_32(0x7B) -#define FFA_NORMAL_WORLD_RESUME FFA_SMC_32(0x7C) - -/* - * For some calls it is necessary to use SMC64 to pass or return 64-bit values. - * For such calls FFA_FN_NATIVE(name) will choose the appropriate - * (native-width) function ID. - */ -#ifdef CONFIG_64BIT -#define FFA_FN_NATIVE(name) FFA_FN64_##name -#else -#define FFA_FN_NATIVE(name) FFA_##name -#endif - -/* FFA error codes. */ -#define FFA_RET_SUCCESS (0) -#define FFA_RET_NOT_SUPPORTED (-1) -#define FFA_RET_INVALID_PARAMETERS (-2) -#define FFA_RET_NO_MEMORY (-3) -#define FFA_RET_BUSY (-4) -#define FFA_RET_INTERRUPTED (-5) -#define FFA_RET_DENIED (-6) -#define FFA_RET_RETRY (-7) -#define FFA_RET_ABORTED (-8) - -#define MAJOR_VERSION_MASK GENMASK(30, 16) -#define MINOR_VERSION_MASK GENMASK(15, 0) -#define MAJOR_VERSION(x) ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x)))) -#define MINOR_VERSION(x) ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x)))) -#define PACK_VERSION_INFO(major, minor) \ - (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \ - FIELD_PREP(MINOR_VERSION_MASK, (minor))) -#define FFA_VERSION_1_0 PACK_VERSION_INFO(1, 0) #define FFA_MIN_VERSION FFA_VERSION_1_0 #define SENDER_ID_MASK GENMASK(31, 16) @@ -121,12 +46,6 @@ (FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r))) /* - * FF-A specification mentions explicitly about '4K pages'. This should - * not be confused with the kernel PAGE_SIZE, which is the translation - * granule kernel is configured and may be one among 4K, 16K and 64K. - */ -#define FFA_PAGE_SIZE SZ_4K -/* * Keeping RX TX buffer size as 4K for now * 64K may be preferred to keep it min a page in 64K PAGE_SIZE config */ @@ -178,9 +97,9 @@ static struct ffa_drv_info *drv_info; */ static u32 ffa_compatible_version_find(u32 version) { - u16 major = MAJOR_VERSION(version), minor = MINOR_VERSION(version); - u16 drv_major = MAJOR_VERSION(FFA_DRIVER_VERSION); - u16 drv_minor = MINOR_VERSION(FFA_DRIVER_VERSION); + u16 major = FFA_MAJOR_VERSION(version), minor = FFA_MINOR_VERSION(version); + u16 drv_major = FFA_MAJOR_VERSION(FFA_DRIVER_VERSION); + u16 drv_minor = FFA_MINOR_VERSION(FFA_DRIVER_VERSION); if ((major < drv_major) || (major == drv_major && minor <= drv_minor)) return version; @@ -204,16 +123,16 @@ static int ffa_version_check(u32 *version) if (ver.a0 < FFA_MIN_VERSION) { pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n", - MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0), - MAJOR_VERSION(FFA_MIN_VERSION), - MINOR_VERSION(FFA_MIN_VERSION)); + FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0), + FFA_MAJOR_VERSION(FFA_MIN_VERSION), + FFA_MINOR_VERSION(FFA_MIN_VERSION)); return -EINVAL; } - pr_info("Driver version %d.%d\n", MAJOR_VERSION(FFA_DRIVER_VERSION), - MINOR_VERSION(FFA_DRIVER_VERSION)); - pr_info("Firmware version %d.%d found\n", MAJOR_VERSION(ver.a0), - MINOR_VERSION(ver.a0)); + pr_info("Driver version %d.%d\n", FFA_MAJOR_VERSION(FFA_DRIVER_VERSION), + FFA_MINOR_VERSION(FFA_DRIVER_VERSION)); + pr_info("Firmware version %d.%d found\n", FFA_MAJOR_VERSION(ver.a0), + FFA_MINOR_VERSION(ver.a0)); *version = ffa_compatible_version_find(ver.a0); return 0; diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index bd235833b687..5f47dbf4889a 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -110,6 +110,24 @@ found: return 0; } +int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size) +{ + if (nvram_len) { + pr_warn("nvram already initialized\n"); + return -EEXIST; + } + + if (!bcm47xx_nvram_is_valid(nvram_start)) { + pr_err("No valid NVRAM found\n"); + return -ENOENT; + } + + bcm47xx_nvram_copy(nvram_start, res_size); + + return 0; +} +EXPORT_SYMBOL_GPL(bcm47xx_nvram_init_from_iomem); + /* * On bcm47xx we need access to the NVRAM very early, so we can't use mtd * subsystem to access flash. We can't even use platform device / driver to diff --git a/drivers/firmware/cirrus/Kconfig b/drivers/firmware/cirrus/Kconfig index f9503cb481d2..3ccbe14e4b0c 100644 --- a/drivers/firmware/cirrus/Kconfig +++ b/drivers/firmware/cirrus/Kconfig @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -config CS_DSP +config FW_CS_DSP tristate default n diff --git a/drivers/firmware/cirrus/Makefile b/drivers/firmware/cirrus/Makefile index f074e2638c9c..b91318ca0ff4 100644 --- a/drivers/firmware/cirrus/Makefile +++ b/drivers/firmware/cirrus/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 # -obj-$(CONFIG_CS_DSP) += cs_dsp.o +obj-$(CONFIG_FW_CS_DSP) += cs_dsp.o diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index 81cc3d0f6eec..f558b390fbfe 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -369,7 +369,7 @@ const char *cs_dsp_mem_region_name(unsigned int type) return NULL; } } -EXPORT_SYMBOL_GPL(cs_dsp_mem_region_name); +EXPORT_SYMBOL_NS_GPL(cs_dsp_mem_region_name, FW_CS_DSP); #ifdef CONFIG_DEBUG_FS static void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, const char *s) @@ -480,7 +480,7 @@ void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root) dsp->debugfs_root = root; } -EXPORT_SYMBOL_GPL(cs_dsp_init_debugfs); +EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP); /** * cs_dsp_cleanup_debugfs() - Removes DSP representation from debugfs @@ -492,17 +492,17 @@ void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp) debugfs_remove_recursive(dsp->debugfs_root); dsp->debugfs_root = NULL; } -EXPORT_SYMBOL_GPL(cs_dsp_cleanup_debugfs); +EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, FW_CS_DSP); #else void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root) { } -EXPORT_SYMBOL_GPL(cs_dsp_init_debugfs); +EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP); void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp) { } -EXPORT_SYMBOL_GPL(cs_dsp_cleanup_debugfs); +EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, FW_CS_DSP); static inline void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, const char *s) @@ -710,7 +710,7 @@ int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int return -ETIMEDOUT; } -EXPORT_SYMBOL_GPL(cs_dsp_coeff_write_acked_control); +EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_acked_control, FW_CS_DSP); static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, unsigned int off, const void *buf, size_t len) @@ -752,7 +752,7 @@ static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, * * Must be called with pwr_lock held. * - * Return: Zero for success, a negative number on error. + * Return: < 0 on error, 1 when the control value changed and 0 when it has not. */ int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, const void *buf, size_t len) @@ -767,18 +767,25 @@ int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, if (len + off * sizeof(u32) > ctl->len) return -EINVAL; - if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) + if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) { ret = -EPERM; - else if (buf != ctl->cache) - memcpy(ctl->cache + off * sizeof(u32), buf, len); + } else if (buf != ctl->cache) { + if (memcmp(ctl->cache + off * sizeof(u32), buf, len)) + memcpy(ctl->cache + off * sizeof(u32), buf, len); + else + return 0; + } ctl->set = 1; if (ctl->enabled && ctl->dsp->running) ret = cs_dsp_coeff_write_ctrl_raw(ctl, off, buf, len); - return ret; + if (ret < 0) + return ret; + + return 1; } -EXPORT_SYMBOL_GPL(cs_dsp_coeff_write_ctrl); +EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_ctrl, FW_CS_DSP); static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, unsigned int off, void *buf, size_t len) @@ -850,7 +857,7 @@ int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, return ret; } -EXPORT_SYMBOL_GPL(cs_dsp_coeff_read_ctrl); +EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_read_ctrl, FW_CS_DSP); static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp) { @@ -1493,7 +1500,7 @@ struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, in return rslt; } -EXPORT_SYMBOL_GPL(cs_dsp_get_ctl); +EXPORT_SYMBOL_NS_GPL(cs_dsp_get_ctl, FW_CS_DSP); static void cs_dsp_ctl_fixup_base(struct cs_dsp *dsp, const struct cs_dsp_alg_region *alg_region) @@ -1583,7 +1590,7 @@ struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp, return NULL; } -EXPORT_SYMBOL_GPL(cs_dsp_find_alg_region); +EXPORT_SYMBOL_NS_GPL(cs_dsp_find_alg_region, FW_CS_DSP); static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp, int type, __be32 id, @@ -2217,7 +2224,7 @@ int cs_dsp_adsp1_init(struct cs_dsp *dsp) return cs_dsp_common_init(dsp); } -EXPORT_SYMBOL_GPL(cs_dsp_adsp1_init); +EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, FW_CS_DSP); /** * cs_dsp_adsp1_power_up() - Load and start the named firmware @@ -2309,7 +2316,7 @@ err_mutex: mutex_unlock(&dsp->pwr_lock); return ret; } -EXPORT_SYMBOL_GPL(cs_dsp_adsp1_power_up); +EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_up, FW_CS_DSP); /** * cs_dsp_adsp1_power_down() - Halts the DSP @@ -2341,7 +2348,7 @@ void cs_dsp_adsp1_power_down(struct cs_dsp *dsp) mutex_unlock(&dsp->pwr_lock); } -EXPORT_SYMBOL_GPL(cs_dsp_adsp1_power_down); +EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_down, FW_CS_DSP); static int cs_dsp_adsp2v2_enable_core(struct cs_dsp *dsp) { @@ -2493,7 +2500,7 @@ int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq) return ret; } -EXPORT_SYMBOL_GPL(cs_dsp_set_dspclk); +EXPORT_SYMBOL_NS_GPL(cs_dsp_set_dspclk, FW_CS_DSP); static void cs_dsp_stop_watchdog(struct cs_dsp *dsp) { @@ -2583,7 +2590,7 @@ err_mutex: return ret; } -EXPORT_SYMBOL_GPL(cs_dsp_power_up); +EXPORT_SYMBOL_NS_GPL(cs_dsp_power_up, FW_CS_DSP); /** * cs_dsp_power_down() - Powers-down the DSP @@ -2617,7 +2624,7 @@ void cs_dsp_power_down(struct cs_dsp *dsp) cs_dsp_dbg(dsp, "Shutdown complete\n"); } -EXPORT_SYMBOL_GPL(cs_dsp_power_down); +EXPORT_SYMBOL_NS_GPL(cs_dsp_power_down, FW_CS_DSP); static int cs_dsp_adsp2_start_core(struct cs_dsp *dsp) { @@ -2703,7 +2710,7 @@ err: return ret; } -EXPORT_SYMBOL_GPL(cs_dsp_run); +EXPORT_SYMBOL_NS_GPL(cs_dsp_run, FW_CS_DSP); /** * cs_dsp_stop() - Stops the firmware @@ -2742,7 +2749,7 @@ void cs_dsp_stop(struct cs_dsp *dsp) cs_dsp_dbg(dsp, "Execution stopped\n"); } -EXPORT_SYMBOL_GPL(cs_dsp_stop); +EXPORT_SYMBOL_NS_GPL(cs_dsp_stop, FW_CS_DSP); static int cs_dsp_halo_start_core(struct cs_dsp *dsp) { @@ -2804,7 +2811,7 @@ int cs_dsp_adsp2_init(struct cs_dsp *dsp) return cs_dsp_common_init(dsp); } -EXPORT_SYMBOL_GPL(cs_dsp_adsp2_init); +EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_init, FW_CS_DSP); /** * cs_dsp_halo_init() - Initialise a cs_dsp structure representing a HALO Core DSP @@ -2818,7 +2825,7 @@ int cs_dsp_halo_init(struct cs_dsp *dsp) return cs_dsp_common_init(dsp); } -EXPORT_SYMBOL_GPL(cs_dsp_halo_init); +EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_init, FW_CS_DSP); /** * cs_dsp_remove() - Clean a cs_dsp before deletion @@ -2838,7 +2845,7 @@ void cs_dsp_remove(struct cs_dsp *dsp) cs_dsp_free_ctl_blk(ctl); } } -EXPORT_SYMBOL_GPL(cs_dsp_remove); +EXPORT_SYMBOL_NS_GPL(cs_dsp_remove, FW_CS_DSP); /** * cs_dsp_read_raw_data_block() - Reads a block of data from DSP memory @@ -2875,7 +2882,7 @@ int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int me return 0; } -EXPORT_SYMBOL_GPL(cs_dsp_read_raw_data_block); +EXPORT_SYMBOL_NS_GPL(cs_dsp_read_raw_data_block, FW_CS_DSP); /** * cs_dsp_read_data_word() - Reads a word from DSP memory @@ -2899,7 +2906,7 @@ int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_add return 0; } -EXPORT_SYMBOL_GPL(cs_dsp_read_data_word); +EXPORT_SYMBOL_NS_GPL(cs_dsp_read_data_word, FW_CS_DSP); /** * cs_dsp_write_data_word() - Writes a word to DSP memory @@ -2925,7 +2932,7 @@ int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_ad return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); } -EXPORT_SYMBOL_GPL(cs_dsp_write_data_word); +EXPORT_SYMBOL_NS_GPL(cs_dsp_write_data_word, FW_CS_DSP); /** * cs_dsp_remove_padding() - Convert unpacked words to packed bytes @@ -2949,7 +2956,7 @@ void cs_dsp_remove_padding(u32 *buf, int nwords) *pack_out++ = (u8)(word >> 16); } } -EXPORT_SYMBOL_GPL(cs_dsp_remove_padding); +EXPORT_SYMBOL_NS_GPL(cs_dsp_remove_padding, FW_CS_DSP); /** * cs_dsp_adsp2_bus_error() - Handle a DSP bus error interrupt @@ -3019,7 +3026,7 @@ void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp) error: mutex_unlock(&dsp->pwr_lock); } -EXPORT_SYMBOL_GPL(cs_dsp_adsp2_bus_error); +EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_bus_error, FW_CS_DSP); /** * cs_dsp_halo_bus_error() - Handle a DSP bus error interrupt @@ -3079,7 +3086,7 @@ void cs_dsp_halo_bus_error(struct cs_dsp *dsp) exit_unlock: mutex_unlock(&dsp->pwr_lock); } -EXPORT_SYMBOL_GPL(cs_dsp_halo_bus_error); +EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_bus_error, FW_CS_DSP); /** * cs_dsp_halo_wdt_expire() - Handle DSP watchdog expiry @@ -3099,7 +3106,7 @@ void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp) mutex_unlock(&dsp->pwr_lock); } -EXPORT_SYMBOL_GPL(cs_dsp_halo_wdt_expire); +EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_wdt_expire, FW_CS_DSP); static const struct cs_dsp_ops cs_dsp_adsp1_ops = { .validate_version = cs_dsp_validate_version, @@ -3221,7 +3228,7 @@ int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val) return 0; } -EXPORT_SYMBOL_GPL(cs_dsp_chunk_write); +EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_write, FW_CS_DSP); /** * cs_dsp_chunk_flush() - Pad remaining data with zero and commit to chunk @@ -3240,7 +3247,7 @@ int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch) return cs_dsp_chunk_write(ch, CS_DSP_DATA_WORD_BITS - ch->cachebits, 0); } -EXPORT_SYMBOL_GPL(cs_dsp_chunk_flush); +EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_flush, FW_CS_DSP); /** * cs_dsp_chunk_read() - Parse data from a DSP memory chunk @@ -3282,7 +3289,7 @@ int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits) return result; } -EXPORT_SYMBOL_GPL(cs_dsp_chunk_read); +EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_read, FW_CS_DSP); MODULE_DESCRIPTION("Cirrus Logic DSP Support"); MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>"); diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index e4e5ea7ce910..053eae13f409 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -290,6 +290,7 @@ int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg) return n; } +EXPORT_SYMBOL_GPL(cper_mem_err_location); int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg) { @@ -310,6 +311,7 @@ int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg) return n; } +EXPORT_SYMBOL_GPL(cper_dimm_err_location); void cper_mem_err_pack(const struct cper_sec_mem_err *mem, struct cper_mem_err_compact *cmem) @@ -331,6 +333,7 @@ void cper_mem_err_pack(const struct cper_sec_mem_err *mem, cmem->mem_array_handle = mem->mem_array_handle; cmem->mem_dev_handle = mem->mem_dev_handle; } +EXPORT_SYMBOL_GPL(cper_mem_err_pack); const char *cper_mem_err_unpack(struct trace_seq *p, struct cper_mem_err_compact *cmem) diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c index a52236e11e5f..4d6c5327471a 100644 --- a/drivers/firmware/efi/earlycon.c +++ b/drivers/firmware/efi/earlycon.c @@ -29,8 +29,8 @@ static void *efi_fb; */ static int __init efi_earlycon_remap_fb(void) { - /* bail if there is no bootconsole or it has been disabled already */ - if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED)) + /* bail if there is no bootconsole or it was unregistered already */ + if (!earlycon_console || !console_is_registered(earlycon_console)) return 0; efi_fb = memremap(fb_base, screen_info.lfb_size, @@ -42,8 +42,8 @@ early_initcall(efi_earlycon_remap_fb); static int __init efi_earlycon_unmap_fb(void) { - /* unmap the bootconsole fb unless keep_bootcon has left it enabled */ - if (efi_fb && !(earlycon_console->flags & CON_ENABLED)) + /* unmap the bootconsole fb unless keep_bootcon left it registered */ + if (efi_fb && !console_is_registered(earlycon_console)) memunmap(efi_fb); return 0; } diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index 3bddc152fcd4..97a9e84840a0 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -207,7 +207,7 @@ static int efi_pstore_erase(struct pstore_record *record) static struct pstore_info efi_pstore_info = { .owner = THIS_MODULE, - .name = "efi", + .name = KBUILD_MODNAME, .flags = PSTORE_FLAGS_DMESG, .open = efi_pstore_open, .close = efi_pstore_close, diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index a46df5d1d094..16dae588f0e3 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -337,6 +337,24 @@ static void __init efi_debugfs_init(void) static inline void efi_debugfs_init(void) {} #endif +static void refresh_nv_rng_seed(struct work_struct *work) +{ + u8 seed[EFI_RANDOM_SEED_SIZE]; + + get_random_bytes(seed, sizeof(seed)); + efi.set_variable(L"RandomSeed", &LINUX_EFI_RANDOM_SEED_TABLE_GUID, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, sizeof(seed), seed); + memzero_explicit(seed, sizeof(seed)); +} +static int refresh_nv_rng_seed_notification(struct notifier_block *nb, unsigned long action, void *data) +{ + static DECLARE_WORK(work, refresh_nv_rng_seed); + schedule_work(&work); + return NOTIFY_DONE; +} +static struct notifier_block refresh_nv_rng_seed_nb = { .notifier_call = refresh_nv_rng_seed_notification }; + /* * We register the efi subsystem with the firmware subsystem and the * efivars subsystem with the efi subsystem, if the system was booted with @@ -413,6 +431,7 @@ static int __init efisubsys_init(void) platform_device_register_simple("efi_secret", 0, NULL, 0); #endif + execute_with_initialized_rng(&refresh_nv_rng_seed_nb); return 0; err_remove_group: diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index ef5045a53ce0..453b67582fee 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -20,6 +20,7 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \ # disable the stackleak plugin cflags-$(CONFIG_ARM64) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fpie $(DISABLE_STACKLEAK_PLUGIN) \ + -fno-unwind-tables -fno-asynchronous-unwind-tables \ $(call cc-option,-mbranch-protection=none) cflags-$(CONFIG_ARM) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fno-builtin -fpic \ diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index af3d057e6421..2a4f07423365 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -108,6 +108,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { /* CONN SS */ { "usb", IMX_SC_R_USB_0, 2, true, 0 }, { "usb0phy", IMX_SC_R_USB_0_PHY, 1, false, 0 }, + { "usb1phy", IMX_SC_R_USB_1_PHY, 1, false, 0}, { "usb2", IMX_SC_R_USB_2, 1, false, 0 }, { "usb2phy", IMX_SC_R_USB_2_PHY, 1, false, 0 }, { "sdhc", IMX_SC_R_SDHC_0, 3, true, 0 }, diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c index 4b8978b254f9..ec07bf26e5eb 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c @@ -228,6 +228,26 @@ static void rpi_register_clk_driver(struct device *dev) -1, NULL, 0); } +unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw, unsigned int id) +{ + struct rpi_firmware_clk_rate_request msg = + RPI_FIRMWARE_CLK_RATE_REQUEST(id); + int ret; + + ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_MAX_CLOCK_RATE, + &msg, sizeof(msg)); + if (ret) + /* + * If our firmware doesn't support that operation, or fails, we + * assume the maximum clock rate is absolute maximum we can + * store over our type. + */ + return UINT_MAX; + + return le32_to_cpu(msg.rate); +} +EXPORT_SYMBOL_GPL(rpi_firmware_clk_get_max_rate); + static void rpi_firmware_delete(struct kref *kref) { struct rpi_firmware *fw = container_of(kref, struct rpi_firmware, @@ -268,12 +288,9 @@ static int rpi_firmware_probe(struct platform_device *pdev) fw->cl.tx_block = true; fw->chan = mbox_request_channel(&fw->cl, 0); - if (IS_ERR(fw->chan)) { - int ret = PTR_ERR(fw->chan); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get mbox channel: %d\n", ret); - return ret; - } + if (IS_ERR(fw->chan)) + return dev_err_probe(dev, PTR_ERR(fw->chan), + "Failed to get mbox channel\n"); init_completion(&fw->c); kref_init(&fw->consumers); @@ -311,6 +328,18 @@ static int rpi_firmware_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id rpi_firmware_of_match[] = { + { .compatible = "raspberrypi,bcm2835-firmware", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rpi_firmware_of_match); + +struct device_node *rpi_firmware_find_node(void) +{ + return of_find_matching_node(NULL, rpi_firmware_of_match); +} +EXPORT_SYMBOL_GPL(rpi_firmware_find_node); + /** * rpi_firmware_get - Get pointer to rpi_firmware structure. * @firmware_node: Pointer to the firmware Device Tree node. @@ -366,12 +395,6 @@ struct rpi_firmware *devm_rpi_firmware_get(struct device *dev, } EXPORT_SYMBOL_GPL(devm_rpi_firmware_get); -static const struct of_device_id rpi_firmware_of_match[] = { - { .compatible = "raspberrypi,bcm2835-firmware", }, - {}, -}; -MODULE_DEVICE_TABLE(of, rpi_firmware_of_match); - static struct platform_driver rpi_firmware_driver = { .driver = { .name = "raspberrypi-firmware", diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig index 1c8ba1f47c7c..cde1ab8bd9d1 100644 --- a/drivers/firmware/tegra/Kconfig +++ b/drivers/firmware/tegra/Kconfig @@ -14,6 +14,7 @@ config TEGRA_IVC config TEGRA_BPMP bool "Tegra BPMP driver" depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC + depends on !CPU_BIG_ENDIAN help BPMP (Boot and Power Management Processor) is designed to off-loading the PM functions which include clock/DVFS/thermal/power from the CPU. diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c index 9d3874cdaaee..3ca2b5d9e66f 100644 --- a/drivers/firmware/tegra/bpmp-debugfs.c +++ b/drivers/firmware/tegra/bpmp-debugfs.c @@ -48,13 +48,9 @@ static int seqbuf_read(struct seqbuf *seqbuf, void *buf, size_t nbyte) return seqbuf_status(seqbuf); } -static int seqbuf_read_u32(struct seqbuf *seqbuf, uint32_t *v) +static int seqbuf_read_u32(struct seqbuf *seqbuf, u32 *v) { - int err; - - err = seqbuf_read(seqbuf, v, 4); - *v = le32_to_cpu(*v); - return err; + return seqbuf_read(seqbuf, v, 4); } static int seqbuf_read_str(struct seqbuf *seqbuf, const char **str) @@ -109,10 +105,10 @@ out: } static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name, - uint32_t *fd, uint32_t *len, bool write) + u32 *fd, u32 *len, bool write) { struct mrq_debug_request req = { - .cmd = cpu_to_le32(write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO), + .cmd = write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO, }; struct mrq_debug_response resp; struct tegra_bpmp_message msg = { @@ -147,10 +143,10 @@ static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name, return 0; } -static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd) +static int mrq_debug_close(struct tegra_bpmp *bpmp, u32 fd) { struct mrq_debug_request req = { - .cmd = cpu_to_le32(CMD_DEBUG_CLOSE), + .cmd = CMD_DEBUG_CLOSE, .frd = { .fd = fd, }, @@ -179,10 +175,10 @@ static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd) } static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name, - char *data, size_t sz_data, uint32_t *nbytes) + char *data, size_t sz_data, u32 *nbytes) { struct mrq_debug_request req = { - .cmd = cpu_to_le32(CMD_DEBUG_READ), + .cmd = CMD_DEBUG_READ, }; struct mrq_debug_response resp; struct tegra_bpmp_message msg = { @@ -196,7 +192,7 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name, .size = sizeof(resp), }, }; - uint32_t fd = 0, len = 0; + u32 fd = 0, len = 0; int remaining, err; mutex_lock(&bpmp_debug_lock); @@ -245,7 +241,7 @@ static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name, uint8_t *data, size_t sz_data) { struct mrq_debug_request req = { - .cmd = cpu_to_le32(CMD_DEBUG_WRITE) + .cmd = CMD_DEBUG_WRITE }; struct mrq_debug_response resp; struct tegra_bpmp_message msg = { @@ -259,7 +255,7 @@ static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name, .size = sizeof(resp), }, }; - uint32_t fd = 0, len = 0; + u32 fd = 0, len = 0; size_t remaining; int err; @@ -308,7 +304,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p) char fnamebuf[256]; const char *filename; struct mrq_debug_request req = { - .cmd = cpu_to_le32(CMD_DEBUG_READ), + .cmd = CMD_DEBUG_READ, }; struct mrq_debug_response resp; struct tegra_bpmp_message msg = { @@ -322,7 +318,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p) .size = sizeof(resp), }, }; - uint32_t fd = 0, len = 0; + u32 fd = 0, len = 0; int remaining, err; filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf)); @@ -406,8 +402,8 @@ static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp, { const size_t pathlen = SZ_256; const size_t bufsize = SZ_16K; - uint32_t dsize, attrs = 0; struct dentry *dentry; + u32 dsize, attrs = 0; struct seqbuf seqbuf; char *buf, *pathbuf; const char *name; @@ -487,12 +483,12 @@ static int mrq_debugfs_read(struct tegra_bpmp *bpmp, size_t *nbytes) { struct mrq_debugfs_request req = { - .cmd = cpu_to_le32(CMD_DEBUGFS_READ), + .cmd = CMD_DEBUGFS_READ, .fop = { - .fnameaddr = cpu_to_le32((uint32_t)name), - .fnamelen = cpu_to_le32((uint32_t)sz_name), - .dataaddr = cpu_to_le32((uint32_t)data), - .datalen = cpu_to_le32((uint32_t)sz_data), + .fnameaddr = (u32)name, + .fnamelen = (u32)sz_name, + .dataaddr = (u32)data, + .datalen = (u32)sz_data, }, }; struct mrq_debugfs_response resp; @@ -525,12 +521,12 @@ static int mrq_debugfs_write(struct tegra_bpmp *bpmp, dma_addr_t data, size_t sz_data) { const struct mrq_debugfs_request req = { - .cmd = cpu_to_le32(CMD_DEBUGFS_WRITE), + .cmd = CMD_DEBUGFS_WRITE, .fop = { - .fnameaddr = cpu_to_le32((uint32_t)name), - .fnamelen = cpu_to_le32((uint32_t)sz_name), - .dataaddr = cpu_to_le32((uint32_t)data), - .datalen = cpu_to_le32((uint32_t)sz_data), + .fnameaddr = (u32)name, + .fnamelen = (u32)sz_name, + .dataaddr = (u32)data, + .datalen = (u32)sz_data, }, }; struct tegra_bpmp_message msg = { @@ -548,10 +544,10 @@ static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr, size_t size, size_t *nbytes) { const struct mrq_debugfs_request req = { - .cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR), + .cmd = CMD_DEBUGFS_DUMPDIR, .dumpdir = { - .dataaddr = cpu_to_le32((uint32_t)addr), - .datalen = cpu_to_le32((uint32_t)size), + .dataaddr = (u32)addr, + .datalen = (u32)size, }, }; struct mrq_debugfs_response resp; @@ -688,10 +684,10 @@ static const struct file_operations debugfs_fops = { }; static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf, - struct dentry *parent, uint32_t depth) + struct dentry *parent, u32 depth) { int err; - uint32_t d, t; + u32 d, t; const char *name; struct dentry *dentry; diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c index 63ab21d89c2c..2e26199041cd 100644 --- a/drivers/firmware/tegra/bpmp-tegra186.c +++ b/drivers/firmware/tegra/bpmp-tegra186.c @@ -18,8 +18,8 @@ struct tegra186_bpmp { struct { struct gen_pool *pool; + void __iomem *virt; dma_addr_t phys; - void *virt; } tx, rx; struct { @@ -40,31 +40,27 @@ mbox_client_to_bpmp(struct mbox_client *client) static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel) { - void *frame; + int err; - frame = tegra_ivc_read_get_next_frame(channel->ivc); - if (IS_ERR(frame)) { - channel->ib = NULL; + err = tegra_ivc_read_get_next_frame(channel->ivc, &channel->ib); + if (err) { + iosys_map_clear(&channel->ib); return false; } - channel->ib = frame; - return true; } static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel) { - void *frame; + int err; - frame = tegra_ivc_write_get_next_frame(channel->ivc); - if (IS_ERR(frame)) { - channel->ob = NULL; + err = tegra_ivc_write_get_next_frame(channel->ivc, &channel->ob); + if (err) { + iosys_map_clear(&channel->ob); return false; } - channel->ob = frame; - return true; } @@ -109,6 +105,7 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel, { struct tegra186_bpmp *priv = bpmp->priv; size_t message_size, queue_size; + struct iosys_map rx, tx; unsigned int offset; int err; @@ -121,10 +118,11 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel, queue_size = tegra_ivc_total_queue_size(message_size); offset = queue_size * index; - err = tegra_ivc_init(channel->ivc, NULL, - priv->rx.virt + offset, priv->rx.phys + offset, - priv->tx.virt + offset, priv->tx.phys + offset, - 1, message_size, tegra186_bpmp_ivc_notify, + iosys_map_set_vaddr_iomem(&rx, priv->rx.virt + offset); + iosys_map_set_vaddr_iomem(&tx, priv->tx.virt + offset); + + err = tegra_ivc_init(channel->ivc, NULL, &rx, priv->rx.phys + offset, &tx, + priv->tx.phys + offset, 1, message_size, tegra186_bpmp_ivc_notify, bpmp); if (err < 0) { dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n", @@ -179,7 +177,7 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) return -EPROBE_DEFER; } - priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys); + priv->tx.virt = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys); if (!priv->tx.virt) { dev_err(bpmp->dev, "failed to allocate from TX pool\n"); return -ENOMEM; @@ -192,7 +190,7 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp) goto free_tx; } - priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys); + priv->rx.virt = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys); if (!priv->rx.virt) { dev_err(bpmp->dev, "failed to allocate from RX pool\n"); err = -ENOMEM; diff --git a/drivers/firmware/tegra/bpmp-tegra210.c b/drivers/firmware/tegra/bpmp-tegra210.c index c9c830f658c3..6295f5640c15 100644 --- a/drivers/firmware/tegra/bpmp-tegra210.c +++ b/drivers/firmware/tegra/bpmp-tegra210.c @@ -137,8 +137,8 @@ static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel, unsigned int index) { struct tegra210_bpmp *priv = bpmp->priv; + void __iomem *p; u32 address; - void *p; /* Retrieve channel base address from BPMP */ writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET, @@ -149,8 +149,9 @@ static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel, if (!p) return -ENOMEM; - channel->ib = p; - channel->ob = p; + iosys_map_set_vaddr_iomem(&channel->ib, p); + iosys_map_set_vaddr_iomem(&channel->ob, p); + channel->index = index; init_completion(&channel->completion); channel->bpmp = bpmp; @@ -199,10 +200,8 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp) } err = platform_get_irq_byname(pdev, "tx"); - if (err < 0) { - dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err); + if (err < 0) return err; - } priv->tx_irq_data = irq_get_irq_data(err); if (!priv->tx_irq_data) { @@ -211,10 +210,8 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp) } err = platform_get_irq_byname(pdev, "rx"); - if (err < 0) { - dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err); + if (err < 0) return err; - } err = devm_request_irq(&pdev->dev, err, rx_irq, IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp); diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index 037db21de510..042c2043929d 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c @@ -201,13 +201,13 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, int err; if (data && size > 0) - memcpy_fromio(data, channel->ib->data, size); + tegra_bpmp_mb_read(data, &channel->ib, size); err = tegra_bpmp_ack_response(channel); if (err < 0) return err; - *ret = channel->ib->code; + *ret = tegra_bpmp_mb_read_field(&channel->ib, code); return 0; } @@ -241,11 +241,11 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel, unsigned int mrq, unsigned long flags, const void *data, size_t size) { - channel->ob->code = mrq; - channel->ob->flags = flags; + tegra_bpmp_mb_write_field(&channel->ob, code, mrq); + tegra_bpmp_mb_write_field(&channel->ob, flags, flags); if (data && size > 0) - memcpy_toio(channel->ob->data, data, size); + tegra_bpmp_mb_write(&channel->ob, data, size); return tegra_bpmp_post_request(channel); } @@ -400,7 +400,7 @@ static struct tegra_bpmp_mrq *tegra_bpmp_find_mrq(struct tegra_bpmp *bpmp, void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code, const void *data, size_t size) { - unsigned long flags = channel->ib->flags; + unsigned long flags = tegra_bpmp_mb_read_field(&channel->ib, flags); struct tegra_bpmp *bpmp = channel->bpmp; int err; @@ -417,10 +417,10 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code, if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel))) return; - channel->ob->code = code; + tegra_bpmp_mb_write_field(&channel->ob, code, code); if (data && size > 0) - memcpy_toio(channel->ob->data, data, size); + tegra_bpmp_mb_write(&channel->ob, data, size); err = tegra_bpmp_post_response(channel); if (WARN_ON(err < 0)) @@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(tegra_bpmp_free_mrq); bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp, unsigned int mrq) { - struct mrq_query_abi_request req = { .mrq = cpu_to_le32(mrq) }; + struct mrq_query_abi_request req = { .mrq = mrq }; struct mrq_query_abi_response resp; struct tegra_bpmp_message msg = { .mrq = MRQ_QUERY_ABI, @@ -529,13 +529,13 @@ static void tegra_bpmp_mrq_handle_ping(unsigned int mrq, struct tegra_bpmp_channel *channel, void *data) { - struct mrq_ping_request *request; + struct mrq_ping_request request; struct mrq_ping_response response; - request = (struct mrq_ping_request *)channel->ib->data; + tegra_bpmp_mb_read(&request, &channel->ib, sizeof(request)); memset(&response, 0, sizeof(response)); - response.reply = request->challenge << 1; + response.reply = request.challenge << 1; tegra_bpmp_mrq_return(channel, 0, &response, sizeof(response)); } @@ -648,7 +648,7 @@ static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag, static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel) { - unsigned long flags = channel->ob->flags; + unsigned long flags = tegra_bpmp_mb_read_field(&channel->ob, flags); if ((flags & MSG_RING) == 0) return; @@ -666,8 +666,11 @@ void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp) count = bpmp->soc->channels.thread.count; busy = bpmp->threaded.busy; - if (tegra_bpmp_is_request_ready(channel)) - tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel); + if (tegra_bpmp_is_request_ready(channel)) { + unsigned int mrq = tegra_bpmp_mb_read_field(&channel->ib, code); + + tegra_bpmp_handle_mrq(bpmp, mrq, channel); + } spin_lock(&bpmp->lock); diff --git a/drivers/firmware/tegra/ivc.c b/drivers/firmware/tegra/ivc.c index e2398cd7ca98..8c9aff9804c0 100644 --- a/drivers/firmware/tegra/ivc.c +++ b/drivers/firmware/tegra/ivc.c @@ -68,6 +68,12 @@ struct tegra_ivc_header { } rx; }; +#define tegra_ivc_header_read_field(hdr, field) \ + iosys_map_rd_field(hdr, 0, struct tegra_ivc_header, field) + +#define tegra_ivc_header_write_field(hdr, field, value) \ + iosys_map_wr_field(hdr, 0, struct tegra_ivc_header, field, value) + static inline void tegra_ivc_invalidate(struct tegra_ivc *ivc, dma_addr_t phys) { if (!ivc->peer) @@ -86,16 +92,15 @@ static inline void tegra_ivc_flush(struct tegra_ivc *ivc, dma_addr_t phys) DMA_TO_DEVICE); } -static inline bool tegra_ivc_empty(struct tegra_ivc *ivc, - struct tegra_ivc_header *header) +static inline bool tegra_ivc_empty(struct tegra_ivc *ivc, struct iosys_map *map) { /* * This function performs multiple checks on the same values with * security implications, so create snapshots with READ_ONCE() to * ensure that these checks use the same values. */ - u32 tx = READ_ONCE(header->tx.count); - u32 rx = READ_ONCE(header->rx.count); + u32 tx = tegra_ivc_header_read_field(map, tx.count); + u32 rx = tegra_ivc_header_read_field(map, rx.count); /* * Perform an over-full check to prevent denial of service attacks @@ -113,11 +118,10 @@ static inline bool tegra_ivc_empty(struct tegra_ivc *ivc, return tx == rx; } -static inline bool tegra_ivc_full(struct tegra_ivc *ivc, - struct tegra_ivc_header *header) +static inline bool tegra_ivc_full(struct tegra_ivc *ivc, struct iosys_map *map) { - u32 tx = READ_ONCE(header->tx.count); - u32 rx = READ_ONCE(header->rx.count); + u32 tx = tegra_ivc_header_read_field(map, tx.count); + u32 rx = tegra_ivc_header_read_field(map, rx.count); /* * Invalid cases where the counters indicate that the queue is over @@ -126,11 +130,10 @@ static inline bool tegra_ivc_full(struct tegra_ivc *ivc, return tx - rx >= ivc->num_frames; } -static inline u32 tegra_ivc_available(struct tegra_ivc *ivc, - struct tegra_ivc_header *header) +static inline u32 tegra_ivc_available(struct tegra_ivc *ivc, struct iosys_map *map) { - u32 tx = READ_ONCE(header->tx.count); - u32 rx = READ_ONCE(header->rx.count); + u32 tx = tegra_ivc_header_read_field(map, tx.count); + u32 rx = tegra_ivc_header_read_field(map, rx.count); /* * This function isn't expected to be used in scenarios where an @@ -143,8 +146,9 @@ static inline u32 tegra_ivc_available(struct tegra_ivc *ivc, static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc) { - WRITE_ONCE(ivc->tx.channel->tx.count, - READ_ONCE(ivc->tx.channel->tx.count) + 1); + unsigned int count = tegra_ivc_header_read_field(&ivc->tx.map, tx.count); + + tegra_ivc_header_write_field(&ivc->tx.map, tx.count, count + 1); if (ivc->tx.position == ivc->num_frames - 1) ivc->tx.position = 0; @@ -154,8 +158,9 @@ static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc) static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc) { - WRITE_ONCE(ivc->rx.channel->rx.count, - READ_ONCE(ivc->rx.channel->rx.count) + 1); + unsigned int count = tegra_ivc_header_read_field(&ivc->rx.map, rx.count); + + tegra_ivc_header_write_field(&ivc->rx.map, rx.count, count + 1); if (ivc->rx.position == ivc->num_frames - 1) ivc->rx.position = 0; @@ -166,6 +171,7 @@ static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc) static inline int tegra_ivc_check_read(struct tegra_ivc *ivc) { unsigned int offset = offsetof(struct tegra_ivc_header, tx.count); + unsigned int state; /* * tx.channel->state is set locally, so it is not synchronized with @@ -175,7 +181,8 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc) * asynchronous transition of rx.channel->state to * TEGRA_IVC_STATE_ACK is not allowed. */ - if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED) + state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state); + if (state != TEGRA_IVC_STATE_ESTABLISHED) return -ECONNRESET; /* @@ -185,12 +192,12 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc) * Synchronization is only necessary when these pointers indicate * empty or full. */ - if (!tegra_ivc_empty(ivc, ivc->rx.channel)) + if (!tegra_ivc_empty(ivc, &ivc->rx.map)) return 0; tegra_ivc_invalidate(ivc, ivc->rx.phys + offset); - if (tegra_ivc_empty(ivc, ivc->rx.channel)) + if (tegra_ivc_empty(ivc, &ivc->rx.map)) return -ENOSPC; return 0; @@ -199,29 +206,34 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc) static inline int tegra_ivc_check_write(struct tegra_ivc *ivc) { unsigned int offset = offsetof(struct tegra_ivc_header, rx.count); + unsigned int state; - if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED) + state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state); + if (state != TEGRA_IVC_STATE_ESTABLISHED) return -ECONNRESET; - if (!tegra_ivc_full(ivc, ivc->tx.channel)) + if (!tegra_ivc_full(ivc, &ivc->tx.map)) return 0; tegra_ivc_invalidate(ivc, ivc->tx.phys + offset); - if (tegra_ivc_full(ivc, ivc->tx.channel)) + if (tegra_ivc_full(ivc, &ivc->tx.map)) return -ENOSPC; return 0; } -static void *tegra_ivc_frame_virt(struct tegra_ivc *ivc, - struct tegra_ivc_header *header, - unsigned int frame) +static int tegra_ivc_frame_virt(struct tegra_ivc *ivc, const struct iosys_map *header, + unsigned int frame, struct iosys_map *map) { + size_t offset = sizeof(struct tegra_ivc_header) + ivc->frame_size * frame; + if (WARN_ON(frame >= ivc->num_frames)) - return ERR_PTR(-EINVAL); + return -EINVAL; - return (void *)(header + 1) + ivc->frame_size * frame; + *map = IOSYS_MAP_INIT_OFFSET(header, offset); + + return 0; } static inline dma_addr_t tegra_ivc_frame_phys(struct tegra_ivc *ivc, @@ -264,16 +276,16 @@ static inline void tegra_ivc_flush_frame(struct tegra_ivc *ivc, } /* directly peek at the next frame rx'ed */ -void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc) +int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map) { int err; if (WARN_ON(ivc == NULL)) - return ERR_PTR(-EINVAL); + return -EINVAL; err = tegra_ivc_check_read(ivc); if (err < 0) - return ERR_PTR(err); + return err; /* * Order observation of ivc->rx.position potentially indicating new @@ -284,7 +296,7 @@ void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc) tegra_ivc_invalidate_frame(ivc, ivc->rx.phys, ivc->rx.position, 0, ivc->frame_size); - return tegra_ivc_frame_virt(ivc, ivc->rx.channel, ivc->rx.position); + return tegra_ivc_frame_virt(ivc, &ivc->rx.map, ivc->rx.position, map); } EXPORT_SYMBOL(tegra_ivc_read_get_next_frame); @@ -320,7 +332,7 @@ int tegra_ivc_read_advance(struct tegra_ivc *ivc) */ tegra_ivc_invalidate(ivc, ivc->rx.phys + tx); - if (tegra_ivc_available(ivc, ivc->rx.channel) == ivc->num_frames - 1) + if (tegra_ivc_available(ivc, &ivc->rx.map) == ivc->num_frames - 1) ivc->notify(ivc, ivc->notify_data); return 0; @@ -328,15 +340,15 @@ int tegra_ivc_read_advance(struct tegra_ivc *ivc) EXPORT_SYMBOL(tegra_ivc_read_advance); /* directly poke at the next frame to be tx'ed */ -void *tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc) +int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map) { int err; err = tegra_ivc_check_write(ivc); if (err < 0) - return ERR_PTR(err); + return err; - return tegra_ivc_frame_virt(ivc, ivc->tx.channel, ivc->tx.position); + return tegra_ivc_frame_virt(ivc, &ivc->tx.map, ivc->tx.position, map); } EXPORT_SYMBOL(tegra_ivc_write_get_next_frame); @@ -376,7 +388,7 @@ int tegra_ivc_write_advance(struct tegra_ivc *ivc) */ tegra_ivc_invalidate(ivc, ivc->tx.phys + rx); - if (tegra_ivc_available(ivc, ivc->tx.channel) == 1) + if (tegra_ivc_available(ivc, &ivc->tx.map) == 1) ivc->notify(ivc, ivc->notify_data); return 0; @@ -387,7 +399,7 @@ void tegra_ivc_reset(struct tegra_ivc *ivc) { unsigned int offset = offsetof(struct tegra_ivc_header, tx.count); - ivc->tx.channel->tx.state = TEGRA_IVC_STATE_SYNC; + tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_SYNC); tegra_ivc_flush(ivc, ivc->tx.phys + offset); ivc->notify(ivc, ivc->notify_data); } @@ -416,13 +428,14 @@ EXPORT_SYMBOL(tegra_ivc_reset); int tegra_ivc_notified(struct tegra_ivc *ivc) { unsigned int offset = offsetof(struct tegra_ivc_header, tx.count); - enum tegra_ivc_state state; + enum tegra_ivc_state rx_state, tx_state; /* Copy the receiver's state out of shared memory. */ tegra_ivc_invalidate(ivc, ivc->rx.phys + offset); - state = READ_ONCE(ivc->rx.channel->tx.state); + rx_state = tegra_ivc_header_read_field(&ivc->rx.map, tx.state); + tx_state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state); - if (state == TEGRA_IVC_STATE_SYNC) { + if (rx_state == TEGRA_IVC_STATE_SYNC) { offset = offsetof(struct tegra_ivc_header, tx.count); /* @@ -436,8 +449,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) * state and won't make progress until we change our state, * so the counters are not in use at this time. */ - ivc->tx.channel->tx.count = 0; - ivc->rx.channel->rx.count = 0; + tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0); + tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0); ivc->tx.position = 0; ivc->rx.position = 0; @@ -452,7 +465,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) * Move to ACK state. We have just cleared our counters, so it * is now safe for the remote end to start using these values. */ - ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ACK; + tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ACK); tegra_ivc_flush(ivc, ivc->tx.phys + offset); /* @@ -460,8 +473,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) */ ivc->notify(ivc, ivc->notify_data); - } else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_SYNC && - state == TEGRA_IVC_STATE_ACK) { + } else if (tx_state == TEGRA_IVC_STATE_SYNC && + rx_state == TEGRA_IVC_STATE_ACK) { offset = offsetof(struct tegra_ivc_header, tx.count); /* @@ -475,8 +488,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) * state and won't make progress until we change our state, * so the counters are not in use at this time. */ - ivc->tx.channel->tx.count = 0; - ivc->rx.channel->rx.count = 0; + tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0); + tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0); ivc->tx.position = 0; ivc->rx.position = 0; @@ -492,7 +505,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) * already cleared its counters, so it is safe to start * writing/reading on this channel. */ - ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED; + tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED); tegra_ivc_flush(ivc, ivc->tx.phys + offset); /* @@ -500,7 +513,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) */ ivc->notify(ivc, ivc->notify_data); - } else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_ACK) { + } else if (tx_state == TEGRA_IVC_STATE_ACK) { offset = offsetof(struct tegra_ivc_header, tx.count); /* @@ -516,7 +529,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) * cleared its counters, so it is safe to start writing/reading * on this channel. */ - ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED; + tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED); tegra_ivc_flush(ivc, ivc->tx.phys + offset); /* @@ -533,7 +546,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc) */ } - if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED) + if (tx_state != TEGRA_IVC_STATE_ESTABLISHED) return -EAGAIN; return 0; @@ -609,8 +622,29 @@ static int tegra_ivc_check_params(unsigned long rx, unsigned long tx, return 0; } -int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx, - dma_addr_t rx_phys, void *tx, dma_addr_t tx_phys, +static inline void iosys_map_copy(struct iosys_map *dst, const struct iosys_map *src) +{ + *dst = *src; +} + +static inline unsigned long iosys_map_get_address(const struct iosys_map *map) +{ + if (map->is_iomem) + return (unsigned long)map->vaddr_iomem; + + return (unsigned long)map->vaddr; +} + +static inline void *iosys_map_get_vaddr(const struct iosys_map *map) +{ + if (WARN_ON(map->is_iomem)) + return NULL; + + return map->vaddr; +} + +int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, const struct iosys_map *rx, + dma_addr_t rx_phys, const struct iosys_map *tx, dma_addr_t tx_phys, unsigned int num_frames, size_t frame_size, void (*notify)(struct tegra_ivc *ivc, void *data), void *data) @@ -628,7 +662,7 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx, if (frame_size > INT_MAX) return -E2BIG; - err = tegra_ivc_check_params((unsigned long)rx, (unsigned long)tx, + err = tegra_ivc_check_params(iosys_map_get_address(rx), iosys_map_get_address(tx), num_frames, frame_size); if (err < 0) return err; @@ -636,12 +670,12 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx, queue_size = tegra_ivc_total_queue_size(num_frames * frame_size); if (peer) { - ivc->rx.phys = dma_map_single(peer, rx, queue_size, + ivc->rx.phys = dma_map_single(peer, iosys_map_get_vaddr(rx), queue_size, DMA_BIDIRECTIONAL); if (dma_mapping_error(peer, ivc->rx.phys)) return -ENOMEM; - ivc->tx.phys = dma_map_single(peer, tx, queue_size, + ivc->tx.phys = dma_map_single(peer, iosys_map_get_vaddr(tx), queue_size, DMA_BIDIRECTIONAL); if (dma_mapping_error(peer, ivc->tx.phys)) { dma_unmap_single(peer, ivc->rx.phys, queue_size, @@ -653,8 +687,8 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx, ivc->tx.phys = tx_phys; } - ivc->rx.channel = rx; - ivc->tx.channel = tx; + iosys_map_copy(&ivc->rx.map, rx); + iosys_map_copy(&ivc->tx.map, tx); ivc->peer = peer; ivc->notify = notify; ivc->notify_data = data; diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index ebc32bbd9b83..039d92a595ec 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -429,15 +429,14 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info, * during noirq phase, so we must manually poll the completion. */ ret = read_poll_timeout_atomic(try_wait_for_completion, done_state, - true, 1, + done_state, 1, info->desc->max_rx_timeout_ms * 1000, false, &xfer->done); } - if (ret == -ETIMEDOUT || !done_state) { + if (ret == -ETIMEDOUT) dev_err(dev, "Mbox timedout in resp(caller: %pS)\n", (void *)_RET_IP_); - } /* * NOTE: we might prefer not to need the mailbox ticker to manage the @@ -3096,7 +3095,7 @@ u16 ti_sci_get_free_resource(struct ti_sci_resource *res) free_bit = find_first_zero_bit(desc->res_map, res_count); if (free_bit != res_count) { - set_bit(free_bit, desc->res_map); + __set_bit(free_bit, desc->res_map); raw_spin_unlock_irqrestore(&res->lock, flags); if (desc->num && free_bit < desc->num) @@ -3127,10 +3126,10 @@ void ti_sci_release_resource(struct ti_sci_resource *res, u16 id) if (desc->num && desc->start <= id && (desc->start + desc->num) > id) - clear_bit(id - desc->start, desc->res_map); + __clear_bit(id - desc->start, desc->res_map); else if (desc->num_sec && desc->start_sec <= id && (desc->start_sec + desc->num_sec) > id) - clear_bit(id - desc->start_sec, desc->res_map); + __clear_bit(id - desc->start_sec, desc->res_map); } raw_spin_unlock_irqrestore(&res->lock, flags); } @@ -3201,9 +3200,8 @@ devm_ti_sci_get_resource_sets(const struct ti_sci_handle *handle, valid_set = true; res_count = res->desc[i].num + res->desc[i].num_sec; - res->desc[i].res_map = - devm_kzalloc(dev, BITS_TO_LONGS(res_count) * - sizeof(*res->desc[i].res_map), GFP_KERNEL); + res->desc[i].res_map = devm_bitmap_zalloc(dev, res_count, + GFP_KERNEL); if (!res->desc[i].res_map) return ERR_PTR(-ENOMEM); } @@ -3400,13 +3398,11 @@ static int ti_sci_probe(struct platform_device *pdev) if (!minfo->xfer_block) return -ENOMEM; - minfo->xfer_alloc_table = devm_kcalloc(dev, - BITS_TO_LONGS(desc->max_msgs), - sizeof(unsigned long), - GFP_KERNEL); + minfo->xfer_alloc_table = devm_bitmap_zalloc(dev, + desc->max_msgs, + GFP_KERNEL); if (!minfo->xfer_alloc_table) return -ENOMEM; - bitmap_zero(minfo->xfer_alloc_table, desc->max_msgs); /* Pre-initialize the buffer pointer to pre-allocated buffers */ for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) { diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index ff5cabe70a2b..6bc6b6c84241 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -843,6 +843,13 @@ int zynqmp_pm_read_pggs(u32 index, u32 *value) } EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs); +int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_TAPDELAY_BYPASS, + index, value, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass); + /** * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status * @value: Status value to be written |