Loading arch/arm/boot/dts/qcom/msm8226.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -1209,7 +1209,7 @@ vdd_pll-supply = <&pm8226_l8>; qcom,vdd_pll = <1800000>; qcom,firmware-name = "mba"; qcom,firmware-name = "modem"; qcom,pil-self-auth; /* GPIO inputs from mss */ Loading arch/arm/boot/dts/qcom/msm8610.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -878,7 +878,7 @@ vdd_mx-uV = <1050000>; vdd_pll-supply = <&pm8110_l10>; qcom,vdd_pll = <1800000>; qcom,firmware-name = "mba"; qcom,firmware-name = "modem"; qcom,pil-self-auth; /* GPIO inputs from mss */ Loading arch/arm/boot/dts/qcom/msm8974.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -1990,7 +1990,7 @@ vdd_mx-uV = <1050000>; vdd_pll-supply = <&pm8941_l12>; qcom,vdd_pll = <1800000>; qcom,firmware-name = "mba"; qcom,firmware-name = "modem"; qcom,pil-self-auth; /* GPIO inputs from mss */ Loading drivers/soc/qcom/pil-femto-modem.c +8 −7 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ static char *modem_status_str[MODEM_STATUS_LAST] = { }; struct modem_pil_data { struct mba_data image; struct modem_data image; const char *name; u32 num_images; u32 id; Loading Loading @@ -190,7 +190,7 @@ static int pil_femto_modem_start(struct femto_modem_data *drv) struct modem_pil_data *modem = &drv->modem[index]; int img; char *pmi_name = kzalloc((strlen(modem->name) + 5), GFP_KERNEL); struct mba_data *image = &modem->image; struct modem_data *image = &modem->image; if (!pmi_name) { ret = -ENOMEM; Loading Loading @@ -522,7 +522,7 @@ static int pil_femto_modem_desc_probe(struct platform_device *pdev) struct modem_pil_data *modem; struct pil_desc *mba_desc; struct resource *res; struct mba_data *mba; struct modem_data *mba; void __iomem *rmb; int ret; u32 id; Loading Loading @@ -602,12 +602,13 @@ static int pil_femto_modem_desc_probe(struct platform_device *pdev) mba_desc = &mba->desc; mba_desc->name = modem->name; mba_desc->dev = dev; mba_desc->ops = &pil_msa_mba_ops; mba_desc->ops = &pil_msa_femto_mba_ops; mba_desc->owner = THIS_MODULE; mba_desc->proxy_timeout = 0; mba_desc->flags = skip_entry ? PIL_SKIP_ENTRY_CHECK : 0; mba_desc->map_fw_mem = pil_femto_modem_map_fw_mem; mba_desc->unmap_fw_mem = NULL; ret = pil_desc_init(mba_desc); if (ret) return ret; Loading Loading @@ -673,15 +674,15 @@ static int pil_femto_modem_driver_probe( q6->self_auth = 1; q6_desc = &q6->desc; q6_desc->ops = &pil_msa_pbl_ops; q6_desc->ops = &pil_msa_mss_ops; q6_desc->owner = THIS_MODULE; q6_desc->proxy_timeout = 0; q6_desc->map_fw_mem = pil_femto_modem_map_fw_mem; q6_desc->unmap_fw_mem = NULL; /* For this target, PBL interactions are different. */ pil_msa_pbl_ops.proxy_vote = NULL; pil_msa_pbl_ops.proxy_unvote = NULL; pil_msa_mss_ops.proxy_vote = NULL; pil_msa_mss_ops.proxy_unvote = NULL; /* Initialize the number of discovered modems. */ drv->disc_modems = 0; Loading drivers/soc/qcom/pil-msa.c +151 −58 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ */ #include <linux/module.h> #include <linux/device.h> #include <linux/firmware.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/ioport.h> Loading Loading @@ -67,16 +69,15 @@ module_param(pbl_mba_boot_timeout_ms, int, S_IRUGO | S_IWUSR); static int modem_auth_timeout_ms = 10000; module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR); static int pil_msa_pbl_power_up(struct q6v5_data *drv) static int pil_mss_power_up(struct q6v5_data *drv) { int ret = 0; struct device *dev = drv->desc.dev; u32 regval; if (drv->vreg) { ret = regulator_enable(drv->vreg); if (ret) dev_err(dev, "Failed to enable modem regulator.\n"); dev_err(drv->desc.dev, "Failed to enable modem regulator.\n"); } if (drv->cxrail_bhs) { Loading @@ -91,7 +92,7 @@ static int pil_msa_pbl_power_up(struct q6v5_data *drv) return ret; } static int pil_msa_pbl_power_down(struct q6v5_data *drv) static int pil_mss_power_down(struct q6v5_data *drv) { u32 regval; Loading @@ -107,7 +108,7 @@ static int pil_msa_pbl_power_down(struct q6v5_data *drv) return 0; } static int pil_msa_pbl_enable_clks(struct q6v5_data *drv) static int pil_mss_enable_clks(struct q6v5_data *drv) { int ret; Loading @@ -131,7 +132,7 @@ err_ahb_clk: return ret; } static void pil_msa_pbl_disable_clks(struct q6v5_data *drv) static void pil_mss_disable_clks(struct q6v5_data *drv) { clk_disable_unprepare(drv->rom_clk); clk_disable_unprepare(drv->axi_clk); Loading Loading @@ -172,7 +173,7 @@ static int pil_msa_wait_for_mba_ready(struct q6v5_data *drv) return 0; } static int pil_msa_pbl_shutdown(struct pil_desc *pil) int pil_mss_shutdown(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); Loading @@ -189,25 +190,70 @@ static int pil_msa_pbl_shutdown(struct pil_desc *pil) writel_relaxed(1, drv->restart_reg); if (drv->is_booted) { pil_msa_pbl_disable_clks(drv); pil_msa_pbl_power_down(drv); pil_mss_disable_clks(drv); pil_mss_power_down(drv); drv->is_booted = false; } return 0; } static int pil_msa_pbl_reset(struct pil_desc *pil) int pil_mss_make_proxy_votes(struct pil_desc *pil) { int ret; struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); int uv = 0; ret = of_property_read_u32(pil->dev->of_node, "vdd_mx-uV", &uv); if (ret) { dev_err(pil->dev, "missing vdd_mx-uV property\n"); return ret; } ret = regulator_set_voltage(drv->vreg_mx, uv, INT_MAX); if (ret) { dev_err(pil->dev, "Failed to request vreg_mx voltage\n"); return ret; } ret = regulator_enable(drv->vreg_mx); if (ret) { dev_err(pil->dev, "Failed to enable vreg_mx\n"); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); return ret; } ret = pil_q6v5_make_proxy_votes(pil); if (ret) { regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); } return ret; } void pil_mss_remove_proxy_votes(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); pil_q6v5_remove_proxy_votes(pil); regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); } static int pil_mss_reset(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); phys_addr_t start_addr = pil_get_entry_addr(pil); int ret; if (drv->mba_phys) start_addr = drv->mba_phys; /* * Bring subsystem out of reset and enable required * regulators and clocks. */ ret = pil_msa_pbl_power_up(drv); ret = pil_mss_power_up(drv); if (ret) goto err_power; Loading @@ -218,14 +264,17 @@ static int pil_msa_pbl_reset(struct pil_desc *pil) udelay(2); } ret = pil_msa_pbl_enable_clks(drv); ret = pil_mss_enable_clks(drv); if (ret) goto err_clks; /* Program Image Address */ if (drv->self_auth) { writel_relaxed(start_addr, drv->rmb_base + RMB_MBA_IMAGE); /* Ensure write to RMB base occurs before reset is released. */ /* * Ensure write to RMB base occurs before reset * is released. */ mb(); } else { writel_relaxed((start_addr >> 4) & 0x0FFFFFF0, Loading @@ -248,68 +297,72 @@ static int pil_msa_pbl_reset(struct pil_desc *pil) return 0; err_q6v5_reset: pil_msa_pbl_disable_clks(drv); pil_mss_disable_clks(drv); err_clks: if (drv->restart_reg) writel_relaxed(1, drv->restart_reg); pil_msa_pbl_power_down(drv); pil_mss_power_down(drv); err_power: return ret; } static int pil_msa_pbl_make_proxy_votes(struct pil_desc *pil) #define MBA_SIZE SZ_1M int pil_mss_reset_load_mba(struct pil_desc *pil) { int ret; struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); int uv = 0; ret = of_property_read_u32(pil->dev->of_node, "vdd_mx-uV", &uv); char fw_name[30] = "mba.b00"; const struct firmware *fw; void *mba_virt; dma_addr_t mba_phys; int ret, count; const u8 *data; /* Load and authenticate mba image */ ret = request_firmware(&fw, fw_name, pil->dev); if (ret) { dev_err(pil->dev, "missing vdd_mx-uV property\n"); return ret; dev_err(pil->dev, "Failed to locate blob %s\n", fw_name); goto err_request_firmware; } ret = regulator_set_voltage(drv->vreg_mx, uv, INT_MAX); if (ret) { dev_err(pil->dev, "Failed to request vreg_mx voltage\n"); return ret; mba_virt = dma_alloc_coherent(pil->dev, MBA_SIZE, &mba_phys, GFP_KERNEL); if (!mba_virt) { dev_err(pil->dev, "MBA metadata buffer allocation failed\n"); goto err_mss_reset; } ret = regulator_enable(drv->vreg_mx); if (ret) { dev_err(pil->dev, "Failed to enable vreg_mx\n"); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); return ret; } drv->mba_phys = mba_phys; drv->mba_virt = mba_virt; ret = pil_q6v5_make_proxy_votes(pil); /* Load the MBA image into memory */ count = fw->size; data = fw ? fw->data : NULL; memcpy(mba_virt, data, count); wmb(); ret = pil_mss_reset(pil); if (ret) { regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); dev_err(pil->dev, "MBA boot failed.\n"); goto err_mss_reset; } return ret; } /* The MBA doesn't run from DDR, free the memory now. */ dma_free_coherent(pil->dev, MBA_SIZE, drv->mba_virt, drv->mba_phys); static void pil_msa_pbl_remove_proxy_votes(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); pil_q6v5_remove_proxy_votes(pil); regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); } return 0; struct pil_reset_ops pil_msa_pbl_ops = { .proxy_vote = pil_msa_pbl_make_proxy_votes, .proxy_unvote = pil_msa_pbl_remove_proxy_votes, .auth_and_reset = pil_msa_pbl_reset, .shutdown = pil_msa_pbl_shutdown, }; err_mss_reset: release_firmware(fw); err_request_firmware: dma_free_coherent(pil->dev, MBA_SIZE, drv->mba_virt, drv->mba_phys); return ret; } static int pil_msa_mba_init_image(struct pil_desc *pil, const u8 *metadata, size_t size) static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata, size_t size) { struct mba_data *drv = container_of(pil, struct mba_data, desc); struct modem_data *drv = dev_get_drvdata(pil->dev); void *mdata_virt; dma_addr_t mdata_phys; s32 status; Loading Loading @@ -344,14 +397,25 @@ static int pil_msa_mba_init_image(struct pil_desc *pil, } dma_free_coherent(pil->dev, size, mdata_virt, mdata_phys); return ret; } static int pil_msa_mss_reset_mba_load_auth_mdt(struct pil_desc *pil, const u8 *metadata, size_t size) { int ret; ret = pil_mss_reset_load_mba(pil); if (ret) return ret; return pil_msa_auth_modem_mdt(pil, metadata, size); } static int pil_msa_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr, size_t size) { struct mba_data *drv = container_of(pil, struct mba_data, desc); struct modem_data *drv = dev_get_drvdata(pil->dev); s32 status; u32 img_length = readl_relaxed(drv->rmb_base + RMB_PMI_CODE_LENGTH); Loading @@ -375,7 +439,7 @@ static int pil_msa_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr, static int pil_msa_mba_auth(struct pil_desc *pil) { struct mba_data *drv = container_of(pil, struct mba_data, desc); struct modem_data *drv = dev_get_drvdata(pil->dev); int ret; s32 status; Loading @@ -393,8 +457,37 @@ static int pil_msa_mba_auth(struct pil_desc *pil) return ret; } struct pil_reset_ops pil_msa_mba_ops = { .init_image = pil_msa_mba_init_image, /* * To be used only if self-auth is disabled, or if the * MBA image is loaded as segments and not in init_image. */ struct pil_reset_ops pil_msa_mss_ops = { .proxy_vote = pil_mss_make_proxy_votes, .proxy_unvote = pil_mss_remove_proxy_votes, .auth_and_reset = pil_mss_reset, .shutdown = pil_mss_shutdown, }; /* * To be used if self-auth is enabled and the MBA is to be loaded * in init_image and the modem headers are also to be authenticated * in init_image. Modem segments authenticated in auth_and_reset. */ struct pil_reset_ops pil_msa_mss_ops_selfauth = { .init_image = pil_msa_mss_reset_mba_load_auth_mdt, .proxy_vote = pil_mss_make_proxy_votes, .proxy_unvote = pil_mss_remove_proxy_votes, .verify_blob = pil_msa_mba_verify_blob, .auth_and_reset = pil_msa_mba_auth, .shutdown = pil_mss_shutdown, }; /* * To be used if the modem headers are to be authenticated * in init_image, and the modem segments in auth_and_reset. */ struct pil_reset_ops pil_msa_femto_mba_ops = { .init_image = pil_msa_auth_modem_mdt, .verify_blob = pil_msa_mba_verify_blob, .auth_and_reset = pil_msa_mba_auth, }; Loading
arch/arm/boot/dts/qcom/msm8226.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -1209,7 +1209,7 @@ vdd_pll-supply = <&pm8226_l8>; qcom,vdd_pll = <1800000>; qcom,firmware-name = "mba"; qcom,firmware-name = "modem"; qcom,pil-self-auth; /* GPIO inputs from mss */ Loading
arch/arm/boot/dts/qcom/msm8610.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -878,7 +878,7 @@ vdd_mx-uV = <1050000>; vdd_pll-supply = <&pm8110_l10>; qcom,vdd_pll = <1800000>; qcom,firmware-name = "mba"; qcom,firmware-name = "modem"; qcom,pil-self-auth; /* GPIO inputs from mss */ Loading
arch/arm/boot/dts/qcom/msm8974.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -1990,7 +1990,7 @@ vdd_mx-uV = <1050000>; vdd_pll-supply = <&pm8941_l12>; qcom,vdd_pll = <1800000>; qcom,firmware-name = "mba"; qcom,firmware-name = "modem"; qcom,pil-self-auth; /* GPIO inputs from mss */ Loading
drivers/soc/qcom/pil-femto-modem.c +8 −7 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ static char *modem_status_str[MODEM_STATUS_LAST] = { }; struct modem_pil_data { struct mba_data image; struct modem_data image; const char *name; u32 num_images; u32 id; Loading Loading @@ -190,7 +190,7 @@ static int pil_femto_modem_start(struct femto_modem_data *drv) struct modem_pil_data *modem = &drv->modem[index]; int img; char *pmi_name = kzalloc((strlen(modem->name) + 5), GFP_KERNEL); struct mba_data *image = &modem->image; struct modem_data *image = &modem->image; if (!pmi_name) { ret = -ENOMEM; Loading Loading @@ -522,7 +522,7 @@ static int pil_femto_modem_desc_probe(struct platform_device *pdev) struct modem_pil_data *modem; struct pil_desc *mba_desc; struct resource *res; struct mba_data *mba; struct modem_data *mba; void __iomem *rmb; int ret; u32 id; Loading Loading @@ -602,12 +602,13 @@ static int pil_femto_modem_desc_probe(struct platform_device *pdev) mba_desc = &mba->desc; mba_desc->name = modem->name; mba_desc->dev = dev; mba_desc->ops = &pil_msa_mba_ops; mba_desc->ops = &pil_msa_femto_mba_ops; mba_desc->owner = THIS_MODULE; mba_desc->proxy_timeout = 0; mba_desc->flags = skip_entry ? PIL_SKIP_ENTRY_CHECK : 0; mba_desc->map_fw_mem = pil_femto_modem_map_fw_mem; mba_desc->unmap_fw_mem = NULL; ret = pil_desc_init(mba_desc); if (ret) return ret; Loading Loading @@ -673,15 +674,15 @@ static int pil_femto_modem_driver_probe( q6->self_auth = 1; q6_desc = &q6->desc; q6_desc->ops = &pil_msa_pbl_ops; q6_desc->ops = &pil_msa_mss_ops; q6_desc->owner = THIS_MODULE; q6_desc->proxy_timeout = 0; q6_desc->map_fw_mem = pil_femto_modem_map_fw_mem; q6_desc->unmap_fw_mem = NULL; /* For this target, PBL interactions are different. */ pil_msa_pbl_ops.proxy_vote = NULL; pil_msa_pbl_ops.proxy_unvote = NULL; pil_msa_mss_ops.proxy_vote = NULL; pil_msa_mss_ops.proxy_unvote = NULL; /* Initialize the number of discovered modems. */ drv->disc_modems = 0; Loading
drivers/soc/qcom/pil-msa.c +151 −58 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ */ #include <linux/module.h> #include <linux/device.h> #include <linux/firmware.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/ioport.h> Loading Loading @@ -67,16 +69,15 @@ module_param(pbl_mba_boot_timeout_ms, int, S_IRUGO | S_IWUSR); static int modem_auth_timeout_ms = 10000; module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR); static int pil_msa_pbl_power_up(struct q6v5_data *drv) static int pil_mss_power_up(struct q6v5_data *drv) { int ret = 0; struct device *dev = drv->desc.dev; u32 regval; if (drv->vreg) { ret = regulator_enable(drv->vreg); if (ret) dev_err(dev, "Failed to enable modem regulator.\n"); dev_err(drv->desc.dev, "Failed to enable modem regulator.\n"); } if (drv->cxrail_bhs) { Loading @@ -91,7 +92,7 @@ static int pil_msa_pbl_power_up(struct q6v5_data *drv) return ret; } static int pil_msa_pbl_power_down(struct q6v5_data *drv) static int pil_mss_power_down(struct q6v5_data *drv) { u32 regval; Loading @@ -107,7 +108,7 @@ static int pil_msa_pbl_power_down(struct q6v5_data *drv) return 0; } static int pil_msa_pbl_enable_clks(struct q6v5_data *drv) static int pil_mss_enable_clks(struct q6v5_data *drv) { int ret; Loading @@ -131,7 +132,7 @@ err_ahb_clk: return ret; } static void pil_msa_pbl_disable_clks(struct q6v5_data *drv) static void pil_mss_disable_clks(struct q6v5_data *drv) { clk_disable_unprepare(drv->rom_clk); clk_disable_unprepare(drv->axi_clk); Loading Loading @@ -172,7 +173,7 @@ static int pil_msa_wait_for_mba_ready(struct q6v5_data *drv) return 0; } static int pil_msa_pbl_shutdown(struct pil_desc *pil) int pil_mss_shutdown(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); Loading @@ -189,25 +190,70 @@ static int pil_msa_pbl_shutdown(struct pil_desc *pil) writel_relaxed(1, drv->restart_reg); if (drv->is_booted) { pil_msa_pbl_disable_clks(drv); pil_msa_pbl_power_down(drv); pil_mss_disable_clks(drv); pil_mss_power_down(drv); drv->is_booted = false; } return 0; } static int pil_msa_pbl_reset(struct pil_desc *pil) int pil_mss_make_proxy_votes(struct pil_desc *pil) { int ret; struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); int uv = 0; ret = of_property_read_u32(pil->dev->of_node, "vdd_mx-uV", &uv); if (ret) { dev_err(pil->dev, "missing vdd_mx-uV property\n"); return ret; } ret = regulator_set_voltage(drv->vreg_mx, uv, INT_MAX); if (ret) { dev_err(pil->dev, "Failed to request vreg_mx voltage\n"); return ret; } ret = regulator_enable(drv->vreg_mx); if (ret) { dev_err(pil->dev, "Failed to enable vreg_mx\n"); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); return ret; } ret = pil_q6v5_make_proxy_votes(pil); if (ret) { regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); } return ret; } void pil_mss_remove_proxy_votes(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); pil_q6v5_remove_proxy_votes(pil); regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); } static int pil_mss_reset(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); phys_addr_t start_addr = pil_get_entry_addr(pil); int ret; if (drv->mba_phys) start_addr = drv->mba_phys; /* * Bring subsystem out of reset and enable required * regulators and clocks. */ ret = pil_msa_pbl_power_up(drv); ret = pil_mss_power_up(drv); if (ret) goto err_power; Loading @@ -218,14 +264,17 @@ static int pil_msa_pbl_reset(struct pil_desc *pil) udelay(2); } ret = pil_msa_pbl_enable_clks(drv); ret = pil_mss_enable_clks(drv); if (ret) goto err_clks; /* Program Image Address */ if (drv->self_auth) { writel_relaxed(start_addr, drv->rmb_base + RMB_MBA_IMAGE); /* Ensure write to RMB base occurs before reset is released. */ /* * Ensure write to RMB base occurs before reset * is released. */ mb(); } else { writel_relaxed((start_addr >> 4) & 0x0FFFFFF0, Loading @@ -248,68 +297,72 @@ static int pil_msa_pbl_reset(struct pil_desc *pil) return 0; err_q6v5_reset: pil_msa_pbl_disable_clks(drv); pil_mss_disable_clks(drv); err_clks: if (drv->restart_reg) writel_relaxed(1, drv->restart_reg); pil_msa_pbl_power_down(drv); pil_mss_power_down(drv); err_power: return ret; } static int pil_msa_pbl_make_proxy_votes(struct pil_desc *pil) #define MBA_SIZE SZ_1M int pil_mss_reset_load_mba(struct pil_desc *pil) { int ret; struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); int uv = 0; ret = of_property_read_u32(pil->dev->of_node, "vdd_mx-uV", &uv); char fw_name[30] = "mba.b00"; const struct firmware *fw; void *mba_virt; dma_addr_t mba_phys; int ret, count; const u8 *data; /* Load and authenticate mba image */ ret = request_firmware(&fw, fw_name, pil->dev); if (ret) { dev_err(pil->dev, "missing vdd_mx-uV property\n"); return ret; dev_err(pil->dev, "Failed to locate blob %s\n", fw_name); goto err_request_firmware; } ret = regulator_set_voltage(drv->vreg_mx, uv, INT_MAX); if (ret) { dev_err(pil->dev, "Failed to request vreg_mx voltage\n"); return ret; mba_virt = dma_alloc_coherent(pil->dev, MBA_SIZE, &mba_phys, GFP_KERNEL); if (!mba_virt) { dev_err(pil->dev, "MBA metadata buffer allocation failed\n"); goto err_mss_reset; } ret = regulator_enable(drv->vreg_mx); if (ret) { dev_err(pil->dev, "Failed to enable vreg_mx\n"); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); return ret; } drv->mba_phys = mba_phys; drv->mba_virt = mba_virt; ret = pil_q6v5_make_proxy_votes(pil); /* Load the MBA image into memory */ count = fw->size; data = fw ? fw->data : NULL; memcpy(mba_virt, data, count); wmb(); ret = pil_mss_reset(pil); if (ret) { regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); dev_err(pil->dev, "MBA boot failed.\n"); goto err_mss_reset; } return ret; } /* The MBA doesn't run from DDR, free the memory now. */ dma_free_coherent(pil->dev, MBA_SIZE, drv->mba_virt, drv->mba_phys); static void pil_msa_pbl_remove_proxy_votes(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); pil_q6v5_remove_proxy_votes(pil); regulator_disable(drv->vreg_mx); regulator_set_voltage(drv->vreg_mx, 0, INT_MAX); } return 0; struct pil_reset_ops pil_msa_pbl_ops = { .proxy_vote = pil_msa_pbl_make_proxy_votes, .proxy_unvote = pil_msa_pbl_remove_proxy_votes, .auth_and_reset = pil_msa_pbl_reset, .shutdown = pil_msa_pbl_shutdown, }; err_mss_reset: release_firmware(fw); err_request_firmware: dma_free_coherent(pil->dev, MBA_SIZE, drv->mba_virt, drv->mba_phys); return ret; } static int pil_msa_mba_init_image(struct pil_desc *pil, const u8 *metadata, size_t size) static int pil_msa_auth_modem_mdt(struct pil_desc *pil, const u8 *metadata, size_t size) { struct mba_data *drv = container_of(pil, struct mba_data, desc); struct modem_data *drv = dev_get_drvdata(pil->dev); void *mdata_virt; dma_addr_t mdata_phys; s32 status; Loading Loading @@ -344,14 +397,25 @@ static int pil_msa_mba_init_image(struct pil_desc *pil, } dma_free_coherent(pil->dev, size, mdata_virt, mdata_phys); return ret; } static int pil_msa_mss_reset_mba_load_auth_mdt(struct pil_desc *pil, const u8 *metadata, size_t size) { int ret; ret = pil_mss_reset_load_mba(pil); if (ret) return ret; return pil_msa_auth_modem_mdt(pil, metadata, size); } static int pil_msa_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr, size_t size) { struct mba_data *drv = container_of(pil, struct mba_data, desc); struct modem_data *drv = dev_get_drvdata(pil->dev); s32 status; u32 img_length = readl_relaxed(drv->rmb_base + RMB_PMI_CODE_LENGTH); Loading @@ -375,7 +439,7 @@ static int pil_msa_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr, static int pil_msa_mba_auth(struct pil_desc *pil) { struct mba_data *drv = container_of(pil, struct mba_data, desc); struct modem_data *drv = dev_get_drvdata(pil->dev); int ret; s32 status; Loading @@ -393,8 +457,37 @@ static int pil_msa_mba_auth(struct pil_desc *pil) return ret; } struct pil_reset_ops pil_msa_mba_ops = { .init_image = pil_msa_mba_init_image, /* * To be used only if self-auth is disabled, or if the * MBA image is loaded as segments and not in init_image. */ struct pil_reset_ops pil_msa_mss_ops = { .proxy_vote = pil_mss_make_proxy_votes, .proxy_unvote = pil_mss_remove_proxy_votes, .auth_and_reset = pil_mss_reset, .shutdown = pil_mss_shutdown, }; /* * To be used if self-auth is enabled and the MBA is to be loaded * in init_image and the modem headers are also to be authenticated * in init_image. Modem segments authenticated in auth_and_reset. */ struct pil_reset_ops pil_msa_mss_ops_selfauth = { .init_image = pil_msa_mss_reset_mba_load_auth_mdt, .proxy_vote = pil_mss_make_proxy_votes, .proxy_unvote = pil_mss_remove_proxy_votes, .verify_blob = pil_msa_mba_verify_blob, .auth_and_reset = pil_msa_mba_auth, .shutdown = pil_mss_shutdown, }; /* * To be used if the modem headers are to be authenticated * in init_image, and the modem segments in auth_and_reset. */ struct pil_reset_ops pil_msa_femto_mba_ops = { .init_image = pil_msa_auth_modem_mdt, .verify_blob = pil_msa_mba_verify_blob, .auth_and_reset = pil_msa_mba_auth, };