Loading Documentation/devicetree/bindings/arm/msm/imem.txt +10 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,11 @@ USB Diag Cookies: Memory region used to store USB PID and serial numbers to be used by bootloader in download mode. SSR Minidump Offset ------------------- -Compatible: "qcom,msm-imem-minidump" -reg: start address and size of ssr imem region Required properties: -compatible: "qcom,msm-imem-diag-dload" -reg: start address and size of USB Diag download mode region in imem Loading Loading @@ -115,4 +120,9 @@ Example: compatible = "qcom,msm-imem-emergency_download_mode"; reg = <0xfe0 12>; }; ss_mdump@b88 { compatible = "qcom,msm-imem-minidump"; reg = <0xb88 28>; }; }; Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt +1 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,7 @@ Optional properties: wordline clamp, and compiler memory clamp during MSS restart. - qcom,qdsp6v56-1-10: Boolean- Present if the qdsp version is v56 1.10 - qcom,override-acc-1: Override the default ACC settings with this value if present. - qcom,minidump-id: Unique id for each subsystem One child node to represent the MBA image may be specified, when the MBA image needs to be loaded in a specifically carved out memory region. Loading drivers/soc/qcom/peripheral-loader.c +107 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,9 @@ #endif #define PIL_NUM_DESC 10 #define NUM_OF_ENCRYPTED_KEY 3 static void __iomem *pil_info_base; static void __iomem *pil_minidump_base; /** * proxy_timeout - Override for proxy vote timeouts Loading @@ -77,6 +79,18 @@ struct pil_mdt { struct elf32_phdr phdr[]; }; /** * struct boot_minidump_smem_region - Representation of SMEM TOC * @region_name: Name of modem segment to be dumped * @region_base_address: Where segment start from * @region_size: Size of segment to be dumped */ struct boot_minidump_smem_region { char region_name[16]; u64 region_base_address; u64 region_size; }; /** * struct pil_seg - memory map representing one segment * @next: points to next seg mentor NULL if last segment Loading Loading @@ -131,11 +145,67 @@ struct pil_priv { phys_addr_t region_end; void *region; struct pil_image_info __iomem *info; struct md_ssr_ss_info __iomem *minidump; int minidump_id; int id; int unvoted_flag; size_t region_size; }; static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev) { struct boot_minidump_smem_region __iomem *region_info; struct ramdump_segment *ramdump_segs, *s; struct pil_priv *priv = desc->priv; void __iomem *subsys_smem_base; void __iomem *offset; int ss_mdump_seg_cnt; int ret, i; memcpy(&offset, &priv->minidump, sizeof(priv->minidump)); offset = offset + sizeof(priv->minidump->md_ss_smem_regions_baseptr); /* There are 3 encryption keys which also need to be dumped */ ss_mdump_seg_cnt = readb_relaxed(offset) + NUM_OF_ENCRYPTED_KEY; subsys_smem_base = ioremap(__raw_readl(priv->minidump), ss_mdump_seg_cnt * sizeof(*region_info)); region_info = (struct boot_minidump_smem_region __iomem *)subsys_smem_base; ramdump_segs = kcalloc(ss_mdump_seg_cnt, sizeof(*ramdump_segs), GFP_KERNEL); if (!ramdump_segs) return -ENOMEM; if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_linux(desc, priv->region_start, (priv->region_end - priv->region_start)); s = ramdump_segs; for (i = 0; i < ss_mdump_seg_cnt; i++) { memcpy(&offset, ®ion_info, sizeof(region_info)); memcpy(&s->name, ®ion_info, sizeof(region_info)); offset = offset + sizeof(region_info->region_name); s->address = __raw_readl(offset); offset = offset + sizeof(region_info->region_base_address); s->size = __raw_readl(offset); s++; region_info++; } ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt); kfree(ramdump_segs); if (ret) pil_err(desc, "%s: Ramdump collection failed for subsys %s rc:%d\n", __func__, desc->name, ret); writel_relaxed(0, &priv->minidump->md_ss_smem_regions_baseptr); writeb_relaxed(1, &priv->minidump->md_ss_ssr_cause); if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_subsys(desc, priv->region_start, (priv->region_end - priv->region_start)); return ret; } /** * pil_do_ramdump() - Ramdump an image * @desc: descriptor from pil_desc_init() Loading @@ -151,6 +221,9 @@ int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev) int count = 0, ret; struct ramdump_segment *ramdump_segs, *s; if (priv->minidump && (__raw_readl(priv->minidump) > 0)) return pil_do_minidump(desc, ramdump_dev); list_for_each_entry(seg, &priv->segs, list) count++; Loading Loading @@ -1011,9 +1084,10 @@ bool is_timeout_disabled(void) int pil_desc_init(struct pil_desc *desc) { struct pil_priv *priv; int ret; void __iomem *addr; int ret, ss_imem_offset_mdump; char buf[sizeof(priv->info->name)]; struct device_node *ofnode = desc->dev->of_node; if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote, "Invalid proxy voting. Ignoring\n")) Loading @@ -1036,6 +1110,22 @@ int pil_desc_init(struct pil_desc *desc) strlcpy(buf, desc->name, sizeof(buf)); __iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4); } if (of_property_read_u32(ofnode, "qcom,minidump-id", &priv->minidump_id)) pr_debug("minidump-id not found for %s\n", desc->name); else { ss_imem_offset_mdump = sizeof(struct md_ssr_ss_info) * priv->minidump_id; if (pil_minidump_base) { /* Add 0x4 to get start of struct md_ssr_ss_info base * from struct md_ssr_toc for any subsystem, * struct md_ssr_ss_info is actually the pointer * of ToC in smem for any subsystem. */ addr = pil_minidump_base + ss_imem_offset_mdump + 0x4; priv->minidump = (struct md_ssr_ss_info __iomem *)addr; } } ret = pil_parse_devicetree(desc); if (ret) Loading Loading @@ -1144,6 +1234,20 @@ static int __init msm_pil_init(void) for (i = 0; i < resource_size(&res)/sizeof(u32); i++) writel_relaxed(0, pil_info_base + (i * sizeof(u32))); np = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-minidump"); if (!np) { pr_warn("pil: failed to find qcom,msm-imem-minidump node\n"); goto out; } else { pil_minidump_base = of_iomap(np, 0); if (!pil_minidump_base) { pr_err("unable to map pil minidump imem offset\n"); goto out; } } for (i = 0; i < sizeof(struct md_ssr_toc)/sizeof(u32); i++) writel_relaxed(0, pil_minidump_base + (i * sizeof(u32))); writel_relaxed(1, pil_minidump_base); out: return register_pm_notifier(&pil_pm_notifier); } Loading @@ -1154,6 +1258,8 @@ static void __exit msm_pil_exit(void) unregister_pm_notifier(&pil_pm_notifier); if (pil_info_base) iounmap(pil_info_base); if (pil_minidump_base) iounmap(pil_minidump_base); } module_exit(msm_pil_exit); Loading drivers/soc/qcom/peripheral-loader.h +28 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,34 @@ struct pil_image_info { __le32 size; } __attribute__((__packed__)); #define MAX_NUM_OF_SS 3 /** * struct md_ssr_ss_info - Info in imem about smem ToC * @md_ss_smem_regions_baseptr: Start physical address of SMEM TOC * @md_ss_num_of_regions: number of segments that need to be dumped * @md_ss_encryption_status: status of encryption of segments * @md_ss_ssr_cause: ssr cause enum */ struct md_ssr_ss_info { u32 md_ss_smem_regions_baseptr; u8 md_ss_num_of_regions; u8 md_ss_encryption_status; u8 md_ss_ssr_cause; u8 reserved; }; /** * struct md_ssr_toc - Wrapper of struct md_ssr_ss_info * @md_ssr_toc_init: flag to indicate to MSS SW about imem init done * @md_ssr_ss: Instance of struct md_ssr_ss_info for a subsystem */ struct md_ssr_toc /* Shared IMEM ToC struct */ { u32 md_ssr_toc_init; struct md_ssr_ss_info md_ssr_ss[MAX_NUM_OF_SS]; }; /** * struct pil_reset_ops - PIL operations * @init_image: prepare an image for authentication Loading drivers/soc/qcom/pil-msa.c +8 −1 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ #define MSS_PDC_OFFSET 8 #define MSS_PDC_MASK BIT(MSS_PDC_OFFSET) /* Timeout value for MBA boot when minidump is enabled */ #define MBA_ENCRYPTION_TIMEOUT 3000 enum scm_cmd { PAS_MEM_SETUP_CMD = 2, }; Loading Loading @@ -298,7 +300,12 @@ static int pil_msa_wait_for_mba_ready(struct q6v5_data *drv) struct device *dev = drv->desc.dev; int ret; u32 status; u64 val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000; u64 val; if (of_property_read_bool(dev->of_node, "qcom,minidump-id")) pbl_mba_boot_timeout_ms = MBA_ENCRYPTION_TIMEOUT; val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000; /* Wait for PBL completion. */ ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status, Loading Loading
Documentation/devicetree/bindings/arm/msm/imem.txt +10 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,11 @@ USB Diag Cookies: Memory region used to store USB PID and serial numbers to be used by bootloader in download mode. SSR Minidump Offset ------------------- -Compatible: "qcom,msm-imem-minidump" -reg: start address and size of ssr imem region Required properties: -compatible: "qcom,msm-imem-diag-dload" -reg: start address and size of USB Diag download mode region in imem Loading Loading @@ -115,4 +120,9 @@ Example: compatible = "qcom,msm-imem-emergency_download_mode"; reg = <0xfe0 12>; }; ss_mdump@b88 { compatible = "qcom,msm-imem-minidump"; reg = <0xb88 28>; }; };
Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt +1 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,7 @@ Optional properties: wordline clamp, and compiler memory clamp during MSS restart. - qcom,qdsp6v56-1-10: Boolean- Present if the qdsp version is v56 1.10 - qcom,override-acc-1: Override the default ACC settings with this value if present. - qcom,minidump-id: Unique id for each subsystem One child node to represent the MBA image may be specified, when the MBA image needs to be loaded in a specifically carved out memory region. Loading
drivers/soc/qcom/peripheral-loader.c +107 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,9 @@ #endif #define PIL_NUM_DESC 10 #define NUM_OF_ENCRYPTED_KEY 3 static void __iomem *pil_info_base; static void __iomem *pil_minidump_base; /** * proxy_timeout - Override for proxy vote timeouts Loading @@ -77,6 +79,18 @@ struct pil_mdt { struct elf32_phdr phdr[]; }; /** * struct boot_minidump_smem_region - Representation of SMEM TOC * @region_name: Name of modem segment to be dumped * @region_base_address: Where segment start from * @region_size: Size of segment to be dumped */ struct boot_minidump_smem_region { char region_name[16]; u64 region_base_address; u64 region_size; }; /** * struct pil_seg - memory map representing one segment * @next: points to next seg mentor NULL if last segment Loading Loading @@ -131,11 +145,67 @@ struct pil_priv { phys_addr_t region_end; void *region; struct pil_image_info __iomem *info; struct md_ssr_ss_info __iomem *minidump; int minidump_id; int id; int unvoted_flag; size_t region_size; }; static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev) { struct boot_minidump_smem_region __iomem *region_info; struct ramdump_segment *ramdump_segs, *s; struct pil_priv *priv = desc->priv; void __iomem *subsys_smem_base; void __iomem *offset; int ss_mdump_seg_cnt; int ret, i; memcpy(&offset, &priv->minidump, sizeof(priv->minidump)); offset = offset + sizeof(priv->minidump->md_ss_smem_regions_baseptr); /* There are 3 encryption keys which also need to be dumped */ ss_mdump_seg_cnt = readb_relaxed(offset) + NUM_OF_ENCRYPTED_KEY; subsys_smem_base = ioremap(__raw_readl(priv->minidump), ss_mdump_seg_cnt * sizeof(*region_info)); region_info = (struct boot_minidump_smem_region __iomem *)subsys_smem_base; ramdump_segs = kcalloc(ss_mdump_seg_cnt, sizeof(*ramdump_segs), GFP_KERNEL); if (!ramdump_segs) return -ENOMEM; if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_linux(desc, priv->region_start, (priv->region_end - priv->region_start)); s = ramdump_segs; for (i = 0; i < ss_mdump_seg_cnt; i++) { memcpy(&offset, ®ion_info, sizeof(region_info)); memcpy(&s->name, ®ion_info, sizeof(region_info)); offset = offset + sizeof(region_info->region_name); s->address = __raw_readl(offset); offset = offset + sizeof(region_info->region_base_address); s->size = __raw_readl(offset); s++; region_info++; } ret = do_minidump(ramdump_dev, ramdump_segs, ss_mdump_seg_cnt); kfree(ramdump_segs); if (ret) pil_err(desc, "%s: Ramdump collection failed for subsys %s rc:%d\n", __func__, desc->name, ret); writel_relaxed(0, &priv->minidump->md_ss_smem_regions_baseptr); writeb_relaxed(1, &priv->minidump->md_ss_ssr_cause); if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_subsys(desc, priv->region_start, (priv->region_end - priv->region_start)); return ret; } /** * pil_do_ramdump() - Ramdump an image * @desc: descriptor from pil_desc_init() Loading @@ -151,6 +221,9 @@ int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev) int count = 0, ret; struct ramdump_segment *ramdump_segs, *s; if (priv->minidump && (__raw_readl(priv->minidump) > 0)) return pil_do_minidump(desc, ramdump_dev); list_for_each_entry(seg, &priv->segs, list) count++; Loading Loading @@ -1011,9 +1084,10 @@ bool is_timeout_disabled(void) int pil_desc_init(struct pil_desc *desc) { struct pil_priv *priv; int ret; void __iomem *addr; int ret, ss_imem_offset_mdump; char buf[sizeof(priv->info->name)]; struct device_node *ofnode = desc->dev->of_node; if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote, "Invalid proxy voting. Ignoring\n")) Loading @@ -1036,6 +1110,22 @@ int pil_desc_init(struct pil_desc *desc) strlcpy(buf, desc->name, sizeof(buf)); __iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4); } if (of_property_read_u32(ofnode, "qcom,minidump-id", &priv->minidump_id)) pr_debug("minidump-id not found for %s\n", desc->name); else { ss_imem_offset_mdump = sizeof(struct md_ssr_ss_info) * priv->minidump_id; if (pil_minidump_base) { /* Add 0x4 to get start of struct md_ssr_ss_info base * from struct md_ssr_toc for any subsystem, * struct md_ssr_ss_info is actually the pointer * of ToC in smem for any subsystem. */ addr = pil_minidump_base + ss_imem_offset_mdump + 0x4; priv->minidump = (struct md_ssr_ss_info __iomem *)addr; } } ret = pil_parse_devicetree(desc); if (ret) Loading Loading @@ -1144,6 +1234,20 @@ static int __init msm_pil_init(void) for (i = 0; i < resource_size(&res)/sizeof(u32); i++) writel_relaxed(0, pil_info_base + (i * sizeof(u32))); np = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-minidump"); if (!np) { pr_warn("pil: failed to find qcom,msm-imem-minidump node\n"); goto out; } else { pil_minidump_base = of_iomap(np, 0); if (!pil_minidump_base) { pr_err("unable to map pil minidump imem offset\n"); goto out; } } for (i = 0; i < sizeof(struct md_ssr_toc)/sizeof(u32); i++) writel_relaxed(0, pil_minidump_base + (i * sizeof(u32))); writel_relaxed(1, pil_minidump_base); out: return register_pm_notifier(&pil_pm_notifier); } Loading @@ -1154,6 +1258,8 @@ static void __exit msm_pil_exit(void) unregister_pm_notifier(&pil_pm_notifier); if (pil_info_base) iounmap(pil_info_base); if (pil_minidump_base) iounmap(pil_minidump_base); } module_exit(msm_pil_exit); Loading
drivers/soc/qcom/peripheral-loader.h +28 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,34 @@ struct pil_image_info { __le32 size; } __attribute__((__packed__)); #define MAX_NUM_OF_SS 3 /** * struct md_ssr_ss_info - Info in imem about smem ToC * @md_ss_smem_regions_baseptr: Start physical address of SMEM TOC * @md_ss_num_of_regions: number of segments that need to be dumped * @md_ss_encryption_status: status of encryption of segments * @md_ss_ssr_cause: ssr cause enum */ struct md_ssr_ss_info { u32 md_ss_smem_regions_baseptr; u8 md_ss_num_of_regions; u8 md_ss_encryption_status; u8 md_ss_ssr_cause; u8 reserved; }; /** * struct md_ssr_toc - Wrapper of struct md_ssr_ss_info * @md_ssr_toc_init: flag to indicate to MSS SW about imem init done * @md_ssr_ss: Instance of struct md_ssr_ss_info for a subsystem */ struct md_ssr_toc /* Shared IMEM ToC struct */ { u32 md_ssr_toc_init; struct md_ssr_ss_info md_ssr_ss[MAX_NUM_OF_SS]; }; /** * struct pil_reset_ops - PIL operations * @init_image: prepare an image for authentication Loading
drivers/soc/qcom/pil-msa.c +8 −1 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ #define MSS_PDC_OFFSET 8 #define MSS_PDC_MASK BIT(MSS_PDC_OFFSET) /* Timeout value for MBA boot when minidump is enabled */ #define MBA_ENCRYPTION_TIMEOUT 3000 enum scm_cmd { PAS_MEM_SETUP_CMD = 2, }; Loading Loading @@ -298,7 +300,12 @@ static int pil_msa_wait_for_mba_ready(struct q6v5_data *drv) struct device *dev = drv->desc.dev; int ret; u32 status; u64 val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000; u64 val; if (of_property_read_bool(dev->of_node, "qcom,minidump-id")) pbl_mba_boot_timeout_ms = MBA_ENCRYPTION_TIMEOUT; val = is_timeout_disabled() ? 0 : pbl_mba_boot_timeout_ms * 1000; /* Wait for PBL completion. */ ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status, Loading