Loading drivers/platform/msm/gsi/gsi.c +10 −0 Original line number Diff line number Diff line Loading @@ -2727,6 +2727,16 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) } EXPORT_SYMBOL(gsi_enable_fw); void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, unsigned long *size) { if (base_offset) *base_offset = GSI_GSI_INST_RAM_BASE_OFFS; if (size) *size = GSI_GSI_INST_RAM_SIZE; } EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size); static int msm_gsi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; Loading drivers/platform/msm/gsi/gsi_reg.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -1838,5 +1838,7 @@ #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_SHFT 0x0 #define GSI_GSI_INST_RAM_BASE_OFFS 0x4000 #define GSI_GSI_INST_RAM_SIZE 0x4000 #endif /* __GSI_REG_H__ */ drivers/platform/msm/ipa/ipa_v3/ipa.c +1 −1 Original line number Diff line number Diff line Loading @@ -4015,7 +4015,7 @@ static int ipa3_trigger_fw_loading_mdms(void) IPADBG("FWs are available for loading\n"); result = ipa3_load_fws(fw); result = ipa3_load_fws(fw, ipa3_res.transport_mem_base); if (result) { IPAERR("IPA FWs loading has failed\n"); release_firmware(fw); Loading drivers/platform/msm/ipa/ipa_v3/ipa_i.h +1 −1 Original line number Diff line number Diff line Loading @@ -2031,7 +2031,7 @@ int ipa3_uc_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr); void ipa3_inc_acquire_wakelock(void); void ipa3_dec_release_wakelock(void); int ipa3_load_fws(const struct firmware *firmware); int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base); int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data); const char *ipa_hw_error_str(enum ipa3_hw_errors err_type); int ipa_gsi_ch20_wa(void); Loading drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +139 −50 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -3968,40 +3968,36 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl) return res; } /** * ipa3_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. * * @firmware: Structure which contains the FW data from the user space. * * Return value: 0 on success, negative otherwise * */ int ipa3_load_fws(const struct firmware *firmware) static int ipa3_load_single_fw(const struct firmware *firmware, const struct elf32_phdr *phdr) { const struct elf32_hdr *ehdr; const struct elf32_phdr *phdr; const uint8_t *elf_phdr_ptr; uint32_t *elf_data_ptr; int phdr_idx, index; uint32_t *fw_mem_base; int index; const uint32_t *elf_data_ptr; ehdr = (struct elf32_hdr *) firmware->data; if (phdr->p_offset > firmware->size) { IPAERR("Invalid ELF: offset=%u is beyond elf_size=%zu\n", phdr->p_offset, firmware->size); return -EINVAL; } if ((firmware->size - phdr->p_offset) < phdr->p_filesz) { IPAERR("Invalid ELF: offset=%u filesz=%u elf_size=%zu\n", phdr->p_offset, phdr->p_filesz, firmware->size); return -EINVAL; } elf_phdr_ptr = firmware->data + sizeof(*ehdr); if (phdr->p_memsz % sizeof(uint32_t)) { IPAERR("FW mem size %u doesn't align to 32bit\n", phdr->p_memsz); return -EFAULT; } for (phdr_idx = 0; phdr_idx < ehdr->e_phnum; phdr_idx++) { /* * The ELF program header will contain the starting * address to which the firmware needs to copied. */ phdr = (struct elf32_phdr *)elf_phdr_ptr; if (phdr->p_filesz > phdr->p_memsz) { IPAERR("FW image too big src_size=%u dst_size=%u\n", phdr->p_filesz, phdr->p_memsz); return -EFAULT; } /* * p_vaddr will contain the starting address to which the * FW needs to be loaded. * p_memsz will contain the size of the IRAM. * p_filesz will contain the size of the FW image. */ fw_mem_base = ioremap(phdr->p_vaddr, phdr->p_memsz); if (!fw_mem_base) { IPAERR("Failed to map 0x%x for the size of %u\n", Loading @@ -4012,31 +4008,124 @@ int ipa3_load_fws(const struct firmware *firmware) /* Set the entire region to 0s */ memset(fw_mem_base, 0, phdr->p_memsz); /* * p_offset will contain and absolute offset from the beginning * of the ELF file. */ elf_data_ptr = (uint32_t *) ((uint8_t *)firmware->data + phdr->p_offset); if (phdr->p_memsz % sizeof(uint32_t)) { IPAERR("FW size %u doesn't align to 32bit\n", phdr->p_memsz); return -EFAULT; } elf_data_ptr = (uint32_t *)(firmware->data + phdr->p_offset); /* Write the FW */ for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); index++) { for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); index++) { writel_relaxed(*elf_data_ptr, &fw_mem_base[index]); elf_data_ptr++; } iounmap(fw_mem_base); elf_phdr_ptr = elf_phdr_ptr + sizeof(*phdr); return 0; } IPADBG("IPA FWs (GSI FW, HPS and DPS) were loaded\n"); /** * ipa3_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. * * @firmware: Structure which contains the FW data from the user space. * @gsi_mem_base: GSI base address * * Return value: 0 on success, negative otherwise * */ int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base) { const struct elf32_hdr *ehdr; const struct elf32_phdr *phdr; unsigned long gsi_iram_ofst; unsigned long gsi_iram_size; phys_addr_t ipa_reg_mem_base; u32 ipa_reg_ofst; int rc; if (!gsi_mem_base) { IPAERR("Invalid GSI base address\n"); return -EINVAL; } ipa_assert_on(!firmware); /* One program header per FW image: GSI, DPS and HPS */ if (firmware->size < (sizeof(*ehdr) + 3 * sizeof(*phdr))) { IPAERR("Missing ELF and Program headers firmware size=%zu\n", firmware->size); return -EINVAL; } ehdr = (struct elf32_hdr *) firmware->data; ipa_assert_on(!ehdr); if (ehdr->e_phnum != 3) { IPAERR("Unexpected number of ELF program headers\n"); return -EINVAL; } phdr = (struct elf32_phdr *)(firmware->data + sizeof(*ehdr)); /* * Each ELF program header represents a FW image and contains: * p_vaddr : The starting address to which the FW needs to loaded. * p_memsz : The size of the IRAM (where the image loaded) * p_filesz: The size of the FW image embedded inside the ELF * p_offset: Absolute offset to the image from the head of the ELF */ /* Load GSI FW image */ gsi_get_inst_ram_offset_and_size(&gsi_iram_ofst, &gsi_iram_size); if (phdr->p_vaddr != (gsi_mem_base + gsi_iram_ofst)) { IPAERR( "Invalid GSI FW img load addr vaddr=0x%x gsi_mem_base=%pa gsi_iram_ofst=0x%lx\n" , phdr->p_vaddr, &gsi_mem_base, gsi_iram_ofst); return -EINVAL; } if (phdr->p_memsz > gsi_iram_size) { IPAERR("Invalid GSI FW img size memsz=%d gsi_iram_size=%lu\n", phdr->p_memsz, gsi_iram_size); return -EINVAL; } rc = ipa3_load_single_fw(firmware, phdr); if (rc) return rc; phdr++; ipa_reg_mem_base = ipa3_ctx->ipa_wrapper_base + ipahal_get_reg_base(); /* Load IPA DPS FW image */ ipa_reg_ofst = ipahal_get_reg_ofst(IPA_DPS_SEQUENCER_FIRST); if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { IPAERR( "Invalid IPA DPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); return -EINVAL; } if (phdr->p_memsz > ipahal_get_dps_img_mem_size()) { IPAERR("Invalid IPA DPS img size memsz=%d dps_mem_size=%u\n", phdr->p_memsz, ipahal_get_dps_img_mem_size()); return -EINVAL; } rc = ipa3_load_single_fw(firmware, phdr); if (rc) return rc; phdr++; /* Load IPA HPS FW image */ ipa_reg_ofst = ipahal_get_reg_ofst(IPA_HPS_SEQUENCER_FIRST); if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { IPAERR( "Invalid IPA HPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); return -EINVAL; } if (phdr->p_memsz > ipahal_get_hps_img_mem_size()) { IPAERR("Invalid IPA HPS img size memsz=%d dps_mem_size=%u\n", phdr->p_memsz, ipahal_get_hps_img_mem_size()); return -EINVAL; } rc = ipa3_load_single_fw(firmware, phdr); if (rc) return rc; IPADBG("IPA FWs (GSI FW, DPS and HPS) loaded successfully\n"); return 0; } Loading Loading
drivers/platform/msm/gsi/gsi.c +10 −0 Original line number Diff line number Diff line Loading @@ -2727,6 +2727,16 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) } EXPORT_SYMBOL(gsi_enable_fw); void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, unsigned long *size) { if (base_offset) *base_offset = GSI_GSI_INST_RAM_BASE_OFFS; if (size) *size = GSI_GSI_INST_RAM_SIZE; } EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size); static int msm_gsi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; Loading
drivers/platform/msm/gsi/gsi_reg.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -1838,5 +1838,7 @@ #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_SHFT 0x0 #define GSI_GSI_INST_RAM_BASE_OFFS 0x4000 #define GSI_GSI_INST_RAM_SIZE 0x4000 #endif /* __GSI_REG_H__ */
drivers/platform/msm/ipa/ipa_v3/ipa.c +1 −1 Original line number Diff line number Diff line Loading @@ -4015,7 +4015,7 @@ static int ipa3_trigger_fw_loading_mdms(void) IPADBG("FWs are available for loading\n"); result = ipa3_load_fws(fw); result = ipa3_load_fws(fw, ipa3_res.transport_mem_base); if (result) { IPAERR("IPA FWs loading has failed\n"); release_firmware(fw); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_i.h +1 −1 Original line number Diff line number Diff line Loading @@ -2031,7 +2031,7 @@ int ipa3_uc_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr); void ipa3_inc_acquire_wakelock(void); void ipa3_dec_release_wakelock(void); int ipa3_load_fws(const struct firmware *firmware); int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base); int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data); const char *ipa_hw_error_str(enum ipa3_hw_errors err_type); int ipa_gsi_ch20_wa(void); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +139 −50 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -3968,40 +3968,36 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl) return res; } /** * ipa3_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. * * @firmware: Structure which contains the FW data from the user space. * * Return value: 0 on success, negative otherwise * */ int ipa3_load_fws(const struct firmware *firmware) static int ipa3_load_single_fw(const struct firmware *firmware, const struct elf32_phdr *phdr) { const struct elf32_hdr *ehdr; const struct elf32_phdr *phdr; const uint8_t *elf_phdr_ptr; uint32_t *elf_data_ptr; int phdr_idx, index; uint32_t *fw_mem_base; int index; const uint32_t *elf_data_ptr; ehdr = (struct elf32_hdr *) firmware->data; if (phdr->p_offset > firmware->size) { IPAERR("Invalid ELF: offset=%u is beyond elf_size=%zu\n", phdr->p_offset, firmware->size); return -EINVAL; } if ((firmware->size - phdr->p_offset) < phdr->p_filesz) { IPAERR("Invalid ELF: offset=%u filesz=%u elf_size=%zu\n", phdr->p_offset, phdr->p_filesz, firmware->size); return -EINVAL; } elf_phdr_ptr = firmware->data + sizeof(*ehdr); if (phdr->p_memsz % sizeof(uint32_t)) { IPAERR("FW mem size %u doesn't align to 32bit\n", phdr->p_memsz); return -EFAULT; } for (phdr_idx = 0; phdr_idx < ehdr->e_phnum; phdr_idx++) { /* * The ELF program header will contain the starting * address to which the firmware needs to copied. */ phdr = (struct elf32_phdr *)elf_phdr_ptr; if (phdr->p_filesz > phdr->p_memsz) { IPAERR("FW image too big src_size=%u dst_size=%u\n", phdr->p_filesz, phdr->p_memsz); return -EFAULT; } /* * p_vaddr will contain the starting address to which the * FW needs to be loaded. * p_memsz will contain the size of the IRAM. * p_filesz will contain the size of the FW image. */ fw_mem_base = ioremap(phdr->p_vaddr, phdr->p_memsz); if (!fw_mem_base) { IPAERR("Failed to map 0x%x for the size of %u\n", Loading @@ -4012,31 +4008,124 @@ int ipa3_load_fws(const struct firmware *firmware) /* Set the entire region to 0s */ memset(fw_mem_base, 0, phdr->p_memsz); /* * p_offset will contain and absolute offset from the beginning * of the ELF file. */ elf_data_ptr = (uint32_t *) ((uint8_t *)firmware->data + phdr->p_offset); if (phdr->p_memsz % sizeof(uint32_t)) { IPAERR("FW size %u doesn't align to 32bit\n", phdr->p_memsz); return -EFAULT; } elf_data_ptr = (uint32_t *)(firmware->data + phdr->p_offset); /* Write the FW */ for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); index++) { for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); index++) { writel_relaxed(*elf_data_ptr, &fw_mem_base[index]); elf_data_ptr++; } iounmap(fw_mem_base); elf_phdr_ptr = elf_phdr_ptr + sizeof(*phdr); return 0; } IPADBG("IPA FWs (GSI FW, HPS and DPS) were loaded\n"); /** * ipa3_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. * * @firmware: Structure which contains the FW data from the user space. * @gsi_mem_base: GSI base address * * Return value: 0 on success, negative otherwise * */ int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base) { const struct elf32_hdr *ehdr; const struct elf32_phdr *phdr; unsigned long gsi_iram_ofst; unsigned long gsi_iram_size; phys_addr_t ipa_reg_mem_base; u32 ipa_reg_ofst; int rc; if (!gsi_mem_base) { IPAERR("Invalid GSI base address\n"); return -EINVAL; } ipa_assert_on(!firmware); /* One program header per FW image: GSI, DPS and HPS */ if (firmware->size < (sizeof(*ehdr) + 3 * sizeof(*phdr))) { IPAERR("Missing ELF and Program headers firmware size=%zu\n", firmware->size); return -EINVAL; } ehdr = (struct elf32_hdr *) firmware->data; ipa_assert_on(!ehdr); if (ehdr->e_phnum != 3) { IPAERR("Unexpected number of ELF program headers\n"); return -EINVAL; } phdr = (struct elf32_phdr *)(firmware->data + sizeof(*ehdr)); /* * Each ELF program header represents a FW image and contains: * p_vaddr : The starting address to which the FW needs to loaded. * p_memsz : The size of the IRAM (where the image loaded) * p_filesz: The size of the FW image embedded inside the ELF * p_offset: Absolute offset to the image from the head of the ELF */ /* Load GSI FW image */ gsi_get_inst_ram_offset_and_size(&gsi_iram_ofst, &gsi_iram_size); if (phdr->p_vaddr != (gsi_mem_base + gsi_iram_ofst)) { IPAERR( "Invalid GSI FW img load addr vaddr=0x%x gsi_mem_base=%pa gsi_iram_ofst=0x%lx\n" , phdr->p_vaddr, &gsi_mem_base, gsi_iram_ofst); return -EINVAL; } if (phdr->p_memsz > gsi_iram_size) { IPAERR("Invalid GSI FW img size memsz=%d gsi_iram_size=%lu\n", phdr->p_memsz, gsi_iram_size); return -EINVAL; } rc = ipa3_load_single_fw(firmware, phdr); if (rc) return rc; phdr++; ipa_reg_mem_base = ipa3_ctx->ipa_wrapper_base + ipahal_get_reg_base(); /* Load IPA DPS FW image */ ipa_reg_ofst = ipahal_get_reg_ofst(IPA_DPS_SEQUENCER_FIRST); if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { IPAERR( "Invalid IPA DPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); return -EINVAL; } if (phdr->p_memsz > ipahal_get_dps_img_mem_size()) { IPAERR("Invalid IPA DPS img size memsz=%d dps_mem_size=%u\n", phdr->p_memsz, ipahal_get_dps_img_mem_size()); return -EINVAL; } rc = ipa3_load_single_fw(firmware, phdr); if (rc) return rc; phdr++; /* Load IPA HPS FW image */ ipa_reg_ofst = ipahal_get_reg_ofst(IPA_HPS_SEQUENCER_FIRST); if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { IPAERR( "Invalid IPA HPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); return -EINVAL; } if (phdr->p_memsz > ipahal_get_hps_img_mem_size()) { IPAERR("Invalid IPA HPS img size memsz=%d dps_mem_size=%u\n", phdr->p_memsz, ipahal_get_hps_img_mem_size()); return -EINVAL; } rc = ipa3_load_single_fw(firmware, phdr); if (rc) return rc; IPADBG("IPA FWs (GSI FW, DPS and HPS) loaded successfully\n"); return 0; } Loading