Loading Documentation/devicetree/bindings/pil/subsys-pil-tz.txt +3 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,9 @@ Optional properties: - qcom,sysmon-id: platform device id that sysmon is probed with for the subsystem. - qcom,pil-force-shutdown: Boolean. If set, the SSR framework will not trigger graceful shutdown on behalf of the subsystem driver. - qcom,pil-generic-irq-handler: generic interrupt handler used for communication with subsytem based on bit values in scsr registers. - qcom,spss-scsr-bits: array of bit positions into the scsr registers used in generic handler. Example: qcom,venus@fdce0000 { Loading drivers/soc/qcom/subsys-pil-tz.c +86 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,15 @@ #define STOP_ACK_TIMEOUT_MS 1000 #define CRASH_STOP_ACK_TO_MS 200 #define COLD_BOOT_DONE 0 #define GDSC_DONE 1 #define RAM_WIPE_DONE 2 #define CPU_BOOT_DONE 3 #define WDOG_BITE 4 #define CLR_WDOG_BITE 5 #define ERR_READY 6 #define PBL_DONE 7 #define desc_to_data(d) container_of(d, struct pil_tz_data, desc) #define subsys_to_data(d) container_of(d, struct pil_tz_data, subsys_desc) Loading Loading @@ -80,6 +89,7 @@ struct reg_info { * @desc: PIL descriptor * @subsys: subsystem device pointer * @subsys_desc: subsystem descriptor * @u32 bits_arr[8]: array of bit positions in SCSR registers */ struct pil_tz_data { struct reg_info *regs; Loading @@ -100,6 +110,11 @@ struct pil_tz_data { struct pil_desc desc; struct subsys_device *subsys; struct subsys_desc subsys_desc; void __iomem *irq_status; void __iomem *irq_clear; void __iomem *irq_mask; void __iomem *err_status; u32 bits_arr[8]; }; enum scm_cmd { Loading Loading @@ -896,9 +911,54 @@ static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t subsys_generic_handler(int irq, void *dev_id) { struct pil_tz_data *d = subsys_to_data(dev_id); uint32_t status_val, clear_val, err_value; if (subsys_get_crash_status(d->subsys)) return IRQ_HANDLED; /* Masking interrupts not handled by HLOS */ clear_val = __raw_readl(d->irq_mask); __raw_writel(clear_val | BIT(d->bits_arr[COLD_BOOT_DONE]) | BIT(d->bits_arr[GDSC_DONE]) | BIT(d->bits_arr[RAM_WIPE_DONE]) | BIT(d->bits_arr[CPU_BOOT_DONE]), d->irq_mask); status_val = __raw_readl(d->irq_status); if (status_val & BIT(d->bits_arr[WDOG_BITE])) { pr_err("wdog bite received from %s!\n", d->subsys_desc.name); clear_val = __raw_readl(d->irq_clear); __raw_writel(clear_val | BIT(d->bits_arr[CLR_WDOG_BITE]), d->irq_clear); subsys_set_crash_status(d->subsys, true); log_failure_reason(d); subsystem_restart_dev(d->subsys); } else if (status_val & BIT(d->bits_arr[ERR_READY])) { pr_debug("Subsystem error services up received from %s!\n", d->subsys_desc.name); clear_val = __raw_readl(d->irq_clear); __raw_writel(clear_val | BIT(d->bits_arr[ERR_READY]), d->irq_clear); complete_err_ready(d->subsys); } else if (status_val & BIT(d->bits_arr[PBL_DONE])) { err_value = __raw_readl(d->err_status); pr_debug("PBL_DONE received from %s!\n", d->subsys_desc.name); if (!err_value) { clear_val = __raw_readl(d->irq_clear); __raw_writel(clear_val | BIT(d->bits_arr[PBL_DONE]), d->irq_clear); } else pr_err("SP-PBL rmb error status: 0x%08x\n", err_value); } return IRQ_HANDLED; } static int pil_tz_driver_probe(struct platform_device *pdev) { struct pil_tz_data *d; struct resource *res; u32 proxy_timeout; int len, rc; Loading Loading @@ -969,10 +1029,32 @@ static int pil_tz_driver_probe(struct platform_device *pdev) d->subsys_desc.ramdump = subsys_ramdump; d->subsys_desc.free_memory = subsys_free_memory; d->subsys_desc.crash_shutdown = subsys_crash_shutdown; d->subsys_desc.err_fatal_handler = subsys_err_fatal_intr_handler; if (of_property_read_bool(pdev->dev.of_node, "qcom,pil-generic-irq-handler")) { d->subsys_desc.generic_handler = subsys_generic_handler; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sp2soc_irq_status"); d->irq_status = devm_ioremap_resource(&pdev->dev, res); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sp2soc_irq_clr"); d->irq_clear = devm_ioremap_resource(&pdev->dev, res); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sp2soc_irq_mask"); d->irq_mask = devm_ioremap_resource(&pdev->dev, res); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb_err"); d->err_status = devm_ioremap_resource(&pdev->dev, res); rc = of_property_read_u32_array(pdev->dev.of_node, "qcom,spss-scsr-bits", d->bits_arr, sizeof(d->bits_arr)/ sizeof(d->bits_arr[0])); if (rc) dev_err(&pdev->dev, "Failed to read qcom,spss-scsr-bits"); } else { d->subsys_desc.err_fatal_handler = subsys_err_fatal_intr_handler; d->subsys_desc.wdog_bite_handler = subsys_wdog_bite_irq_handler; d->subsys_desc.stop_ack_handler = subsys_stop_ack_intr_handler; } d->ramdump_dev = create_ramdump_device(d->subsys_desc.name, &pdev->dev); if (!d->ramdump_dev) { Loading drivers/soc/qcom/subsystem_restart.c +38 −1 Original line number Diff line number Diff line Loading @@ -184,6 +184,11 @@ static struct subsys_device *to_subsys(struct device *d) return container_of(d, struct subsys_device, dev); } void complete_err_ready(struct subsys_device *subsys) { complete(&subsys->err_ready); } static struct subsys_tracking *subsys_get_track(struct subsys_device *subsys) { struct subsys_soc_restart_order *order = subsys->restart_order; Loading Loading @@ -538,6 +543,10 @@ static void enable_all_irqs(struct subsys_device *dev) enable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) enable_irq(dev->desc->stop_ack_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { enable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 1); } } static void disable_all_irqs(struct subsys_device *dev) Loading @@ -552,6 +561,10 @@ static void disable_all_irqs(struct subsys_device *dev) disable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) disable_irq(dev->desc->stop_ack_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { disable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 0); } } int wait_for_shutdown_ack(struct subsys_desc *desc) Loading @@ -577,7 +590,12 @@ static int wait_for_err_ready(struct subsys_device *subsys) { int ret; if (!subsys->desc->err_ready_irq || enable_debug == 1) /* * If subsys is using generic_irq in which case err_ready_irq will be 0, * don't return. */ if ((subsys->desc->generic_irq <= 0 && !subsys->desc->err_ready_irq) || enable_debug == 1) return 0; ret = wait_for_completion_timeout(&subsys->err_ready, Loading Loading @@ -1475,6 +1493,13 @@ static int subsys_parse_devicetree(struct subsys_desc *desc) if (ret > 0) desc->wdog_bite_irq = ret; if (of_property_read_bool(pdev->dev.of_node, "qcom,pil-generic-irq-handler")) { ret = platform_get_irq(pdev, 0); if (ret > 0) desc->generic_irq = ret; } order = ssr_parse_restart_orders(desc); if (IS_ERR(order)) { pr_err("Could not initialize SSR restart order, err = %ld\n", Loading Loading @@ -1526,6 +1551,18 @@ static int subsys_setup_irqs(struct subsys_device *subsys) disable_irq(desc->wdog_bite_irq); } if (desc->generic_irq && desc->generic_handler) { ret = devm_request_irq(desc->dev, desc->generic_irq, desc->generic_handler, IRQF_TRIGGER_HIGH, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register generic irq handler!: %d\n", desc->name, ret); return ret; } disable_irq(desc->generic_irq); } if (desc->err_ready_irq) { ret = devm_request_irq(desc->dev, desc->err_ready_irq, Loading include/soc/qcom/subsystem_restart.h +3 −0 Original line number Diff line number Diff line Loading @@ -66,12 +66,14 @@ struct subsys_desc { irqreturn_t (*err_fatal_handler) (int irq, void *dev_id); irqreturn_t (*stop_ack_handler) (int irq, void *dev_id); irqreturn_t (*wdog_bite_handler) (int irq, void *dev_id); irqreturn_t (*generic_handler)(int irq, void *dev_id); int is_not_loadable; int err_fatal_gpio; unsigned int err_fatal_irq; unsigned int err_ready_irq; unsigned int stop_ack_irq; unsigned int wdog_bite_irq; unsigned int generic_irq; int force_stop_gpio; int ramdump_disable_gpio; int shutdown_ack_gpio; Loading Loading @@ -120,6 +122,7 @@ extern void subsys_set_crash_status(struct subsys_device *dev, bool crashed); extern bool subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void complete_err_ready(struct subsys_device *subsys); extern int wait_for_shutdown_ack(struct subsys_desc *desc); #else Loading Loading
Documentation/devicetree/bindings/pil/subsys-pil-tz.txt +3 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,9 @@ Optional properties: - qcom,sysmon-id: platform device id that sysmon is probed with for the subsystem. - qcom,pil-force-shutdown: Boolean. If set, the SSR framework will not trigger graceful shutdown on behalf of the subsystem driver. - qcom,pil-generic-irq-handler: generic interrupt handler used for communication with subsytem based on bit values in scsr registers. - qcom,spss-scsr-bits: array of bit positions into the scsr registers used in generic handler. Example: qcom,venus@fdce0000 { Loading
drivers/soc/qcom/subsys-pil-tz.c +86 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,15 @@ #define STOP_ACK_TIMEOUT_MS 1000 #define CRASH_STOP_ACK_TO_MS 200 #define COLD_BOOT_DONE 0 #define GDSC_DONE 1 #define RAM_WIPE_DONE 2 #define CPU_BOOT_DONE 3 #define WDOG_BITE 4 #define CLR_WDOG_BITE 5 #define ERR_READY 6 #define PBL_DONE 7 #define desc_to_data(d) container_of(d, struct pil_tz_data, desc) #define subsys_to_data(d) container_of(d, struct pil_tz_data, subsys_desc) Loading Loading @@ -80,6 +89,7 @@ struct reg_info { * @desc: PIL descriptor * @subsys: subsystem device pointer * @subsys_desc: subsystem descriptor * @u32 bits_arr[8]: array of bit positions in SCSR registers */ struct pil_tz_data { struct reg_info *regs; Loading @@ -100,6 +110,11 @@ struct pil_tz_data { struct pil_desc desc; struct subsys_device *subsys; struct subsys_desc subsys_desc; void __iomem *irq_status; void __iomem *irq_clear; void __iomem *irq_mask; void __iomem *err_status; u32 bits_arr[8]; }; enum scm_cmd { Loading Loading @@ -896,9 +911,54 @@ static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id) return IRQ_HANDLED; } static irqreturn_t subsys_generic_handler(int irq, void *dev_id) { struct pil_tz_data *d = subsys_to_data(dev_id); uint32_t status_val, clear_val, err_value; if (subsys_get_crash_status(d->subsys)) return IRQ_HANDLED; /* Masking interrupts not handled by HLOS */ clear_val = __raw_readl(d->irq_mask); __raw_writel(clear_val | BIT(d->bits_arr[COLD_BOOT_DONE]) | BIT(d->bits_arr[GDSC_DONE]) | BIT(d->bits_arr[RAM_WIPE_DONE]) | BIT(d->bits_arr[CPU_BOOT_DONE]), d->irq_mask); status_val = __raw_readl(d->irq_status); if (status_val & BIT(d->bits_arr[WDOG_BITE])) { pr_err("wdog bite received from %s!\n", d->subsys_desc.name); clear_val = __raw_readl(d->irq_clear); __raw_writel(clear_val | BIT(d->bits_arr[CLR_WDOG_BITE]), d->irq_clear); subsys_set_crash_status(d->subsys, true); log_failure_reason(d); subsystem_restart_dev(d->subsys); } else if (status_val & BIT(d->bits_arr[ERR_READY])) { pr_debug("Subsystem error services up received from %s!\n", d->subsys_desc.name); clear_val = __raw_readl(d->irq_clear); __raw_writel(clear_val | BIT(d->bits_arr[ERR_READY]), d->irq_clear); complete_err_ready(d->subsys); } else if (status_val & BIT(d->bits_arr[PBL_DONE])) { err_value = __raw_readl(d->err_status); pr_debug("PBL_DONE received from %s!\n", d->subsys_desc.name); if (!err_value) { clear_val = __raw_readl(d->irq_clear); __raw_writel(clear_val | BIT(d->bits_arr[PBL_DONE]), d->irq_clear); } else pr_err("SP-PBL rmb error status: 0x%08x\n", err_value); } return IRQ_HANDLED; } static int pil_tz_driver_probe(struct platform_device *pdev) { struct pil_tz_data *d; struct resource *res; u32 proxy_timeout; int len, rc; Loading Loading @@ -969,10 +1029,32 @@ static int pil_tz_driver_probe(struct platform_device *pdev) d->subsys_desc.ramdump = subsys_ramdump; d->subsys_desc.free_memory = subsys_free_memory; d->subsys_desc.crash_shutdown = subsys_crash_shutdown; d->subsys_desc.err_fatal_handler = subsys_err_fatal_intr_handler; if (of_property_read_bool(pdev->dev.of_node, "qcom,pil-generic-irq-handler")) { d->subsys_desc.generic_handler = subsys_generic_handler; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sp2soc_irq_status"); d->irq_status = devm_ioremap_resource(&pdev->dev, res); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sp2soc_irq_clr"); d->irq_clear = devm_ioremap_resource(&pdev->dev, res); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sp2soc_irq_mask"); d->irq_mask = devm_ioremap_resource(&pdev->dev, res); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb_err"); d->err_status = devm_ioremap_resource(&pdev->dev, res); rc = of_property_read_u32_array(pdev->dev.of_node, "qcom,spss-scsr-bits", d->bits_arr, sizeof(d->bits_arr)/ sizeof(d->bits_arr[0])); if (rc) dev_err(&pdev->dev, "Failed to read qcom,spss-scsr-bits"); } else { d->subsys_desc.err_fatal_handler = subsys_err_fatal_intr_handler; d->subsys_desc.wdog_bite_handler = subsys_wdog_bite_irq_handler; d->subsys_desc.stop_ack_handler = subsys_stop_ack_intr_handler; } d->ramdump_dev = create_ramdump_device(d->subsys_desc.name, &pdev->dev); if (!d->ramdump_dev) { Loading
drivers/soc/qcom/subsystem_restart.c +38 −1 Original line number Diff line number Diff line Loading @@ -184,6 +184,11 @@ static struct subsys_device *to_subsys(struct device *d) return container_of(d, struct subsys_device, dev); } void complete_err_ready(struct subsys_device *subsys) { complete(&subsys->err_ready); } static struct subsys_tracking *subsys_get_track(struct subsys_device *subsys) { struct subsys_soc_restart_order *order = subsys->restart_order; Loading Loading @@ -538,6 +543,10 @@ static void enable_all_irqs(struct subsys_device *dev) enable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) enable_irq(dev->desc->stop_ack_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { enable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 1); } } static void disable_all_irqs(struct subsys_device *dev) Loading @@ -552,6 +561,10 @@ static void disable_all_irqs(struct subsys_device *dev) disable_irq(dev->desc->err_fatal_irq); if (dev->desc->stop_ack_irq && dev->desc->stop_ack_handler) disable_irq(dev->desc->stop_ack_irq); if (dev->desc->generic_irq && dev->desc->generic_handler) { disable_irq(dev->desc->generic_irq); irq_set_irq_wake(dev->desc->generic_irq, 0); } } int wait_for_shutdown_ack(struct subsys_desc *desc) Loading @@ -577,7 +590,12 @@ static int wait_for_err_ready(struct subsys_device *subsys) { int ret; if (!subsys->desc->err_ready_irq || enable_debug == 1) /* * If subsys is using generic_irq in which case err_ready_irq will be 0, * don't return. */ if ((subsys->desc->generic_irq <= 0 && !subsys->desc->err_ready_irq) || enable_debug == 1) return 0; ret = wait_for_completion_timeout(&subsys->err_ready, Loading Loading @@ -1475,6 +1493,13 @@ static int subsys_parse_devicetree(struct subsys_desc *desc) if (ret > 0) desc->wdog_bite_irq = ret; if (of_property_read_bool(pdev->dev.of_node, "qcom,pil-generic-irq-handler")) { ret = platform_get_irq(pdev, 0); if (ret > 0) desc->generic_irq = ret; } order = ssr_parse_restart_orders(desc); if (IS_ERR(order)) { pr_err("Could not initialize SSR restart order, err = %ld\n", Loading Loading @@ -1526,6 +1551,18 @@ static int subsys_setup_irqs(struct subsys_device *subsys) disable_irq(desc->wdog_bite_irq); } if (desc->generic_irq && desc->generic_handler) { ret = devm_request_irq(desc->dev, desc->generic_irq, desc->generic_handler, IRQF_TRIGGER_HIGH, desc->name, desc); if (ret < 0) { dev_err(desc->dev, "[%s]: Unable to register generic irq handler!: %d\n", desc->name, ret); return ret; } disable_irq(desc->generic_irq); } if (desc->err_ready_irq) { ret = devm_request_irq(desc->dev, desc->err_ready_irq, Loading
include/soc/qcom/subsystem_restart.h +3 −0 Original line number Diff line number Diff line Loading @@ -66,12 +66,14 @@ struct subsys_desc { irqreturn_t (*err_fatal_handler) (int irq, void *dev_id); irqreturn_t (*stop_ack_handler) (int irq, void *dev_id); irqreturn_t (*wdog_bite_handler) (int irq, void *dev_id); irqreturn_t (*generic_handler)(int irq, void *dev_id); int is_not_loadable; int err_fatal_gpio; unsigned int err_fatal_irq; unsigned int err_ready_irq; unsigned int stop_ack_irq; unsigned int wdog_bite_irq; unsigned int generic_irq; int force_stop_gpio; int ramdump_disable_gpio; int shutdown_ack_gpio; Loading Loading @@ -120,6 +122,7 @@ extern void subsys_set_crash_status(struct subsys_device *dev, bool crashed); extern bool subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void complete_err_ready(struct subsys_device *subsys); extern int wait_for_shutdown_ack(struct subsys_desc *desc); #else Loading