diff --git a/drivers/soc/qcom/msm_subsystem_restart.c b/drivers/soc/qcom/msm_subsystem_restart.c index f5da1990d992..d18d6186dc71 100644 --- a/drivers/soc/qcom/msm_subsystem_restart.c +++ b/drivers/soc/qcom/msm_subsystem_restart.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -43,9 +42,6 @@ static uint disable_restart_work; module_param(disable_restart_work, uint, 0644); -static int enable_debug; -module_param(enable_debug, int, 0644); - /* The maximum shutdown timeout is the product of MAX_LOOPS and DELAY_MS. */ #define SHUTDOWN_ACK_MAX_LOOPS 100 #define SHUTDOWN_ACK_DELAY_MS 100 @@ -176,7 +172,6 @@ struct restart_log { * @restart_order: order of other devices this devices restarts with * @crash_count: number of times the device has crashed * @do_ramdump_on_put: ramdump on subsystem_put() if true - * @err_ready: completion variable to record error ready from subsystem * @crashed: indicates if subsystem has crashed * @notif_state: current state of subsystem in terms of subsys notifications */ @@ -200,7 +195,6 @@ struct subsys_device { bool do_ramdump_on_put; struct cdev char_dev; dev_t dev_no; - struct completion err_ready; enum crash_status crashed; int notif_state; struct list_head list; @@ -211,12 +205,6 @@ 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); -} -EXPORT_SYMBOL(complete_err_ready); - static struct subsys_tracking *subsys_get_track(struct subsys_device *subsys) { struct subsys_soc_restart_order *order = subsys->restart_order; @@ -637,62 +625,6 @@ static void notify_each_subsys_device(struct subsys_device **list, } } -static void enable_all_irqs(struct subsys_device *dev) -{ - if (dev->desc->err_ready_irq) - enable_irq(dev->desc->err_ready_irq); - if (dev->desc->wdog_bite_irq && dev->desc->wdog_bite_handler) { - enable_irq(dev->desc->wdog_bite_irq); - irq_set_irq_wake(dev->desc->wdog_bite_irq, 1); - } - if (dev->desc->err_fatal_irq && dev->desc->err_fatal_handler) - 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->shutdown_ack_irq && dev->desc->shutdown_ack_handler) - enable_irq(dev->desc->shutdown_ack_irq); - if (dev->desc->ramdump_disable_irq && - dev->desc->ramdump_disable_handler) - enable_irq(dev->desc->ramdump_disable_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) -{ - if (dev->desc->err_ready_irq) - disable_irq(dev->desc->err_ready_irq); - if (dev->desc->wdog_bite_irq && dev->desc->wdog_bite_handler) { - disable_irq(dev->desc->wdog_bite_irq); - irq_set_irq_wake(dev->desc->wdog_bite_irq, 0); - } - if (dev->desc->err_fatal_irq && dev->desc->err_fatal_handler) - 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->shutdown_ack_irq && dev->desc->shutdown_ack_handler) - disable_irq(dev->desc->shutdown_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); - } -} - -static int wait_for_err_ready(struct subsys_device *subsys) -{ - /* - * 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; - - return wait_for_completion_interruptible(&subsys->err_ready); -} - static int subsystem_shutdown(struct subsys_device *dev, void *data) { const char *name = dev->desc->name; @@ -712,7 +644,6 @@ static int subsystem_shutdown(struct subsys_device *dev, void *data) } dev->crash_count++; subsys_set_state(dev, SUBSYS_OFFLINE); - disable_all_irqs(dev); return 0; } @@ -742,7 +673,6 @@ static int subsystem_powerup(struct subsys_device *dev, void *data) int ret; pr_info("[%s:%d]: Powering up %s\n", current->comm, current->pid, name); - reinit_completion(&dev->err_ready); ret = dev->desc->powerup(dev->desc); if (ret < 0) { @@ -759,9 +689,7 @@ static int subsystem_powerup(struct subsys_device *dev, void *data) pr_err("Powerup failure on %s\n", name); return ret; } - enable_all_irqs(dev); - ret = wait_for_err_ready(dev); if (ret) { notify_each_subsys_device(&dev, 1, SUBSYS_POWERUP_FAILURE, NULL); @@ -803,32 +731,12 @@ static int subsys_start(struct subsys_device *subsys) notify_each_subsys_device(&subsys, 1, SUBSYS_BEFORE_POWERUP, NULL); - - reinit_completion(&subsys->err_ready); ret = subsys->desc->powerup(subsys->desc); if (ret) { notify_each_subsys_device(&subsys, 1, SUBSYS_POWERUP_FAILURE, NULL); return ret; } - enable_all_irqs(subsys); - - if (subsys->desc->is_not_loadable) { - subsys_set_state(subsys, SUBSYS_ONLINE); - return 0; - } - - ret = wait_for_err_ready(subsys); - if (ret) { - /* pil-boot succeeded but we need to shutdown - * the device because error ready timed out. - */ - notify_each_subsys_device(&subsys, 1, SUBSYS_POWERUP_FAILURE, - NULL); - subsys->desc->shutdown(subsys->desc, false); - disable_all_irqs(subsys); - return ret; - } subsys_set_state(subsys, SUBSYS_ONLINE); notify_each_subsys_device(&subsys, 1, SUBSYS_AFTER_POWERUP, @@ -855,7 +763,6 @@ static void subsys_stop(struct subsys_device *subsys) subsys->desc->shutdown(subsys->desc, false); subsys_set_state(subsys, SUBSYS_OFFLINE); - disable_all_irqs(subsys); notify_each_subsys_device(&subsys, 1, SUBSYS_AFTER_SHUTDOWN, NULL); } @@ -1351,19 +1258,6 @@ static void subsys_device_release(struct device *dev) ida_simple_remove(&subsys_ida, subsys->id); kfree(subsys); } -static irqreturn_t subsys_err_ready_intr_handler(int irq, void *subsys) -{ - struct subsys_device *subsys_dev = subsys; - - dev_info(subsys_dev->desc->dev, - "Subsystem error monitoring/handling services are up\n"); - - if (subsys_dev->desc->is_not_loadable) - return IRQ_HANDLED; - - complete(&subsys_dev->err_ready); - return IRQ_HANDLED; -} static int subsys_char_device_add(struct subsys_device *subsys_dev) { @@ -1511,84 +1405,12 @@ err: return tmp; } -static int __get_irq(struct subsys_desc *desc, const char *prop, - unsigned int *irq) -{ - int irql = 0; - struct device_node *dnode = desc->dev->of_node; - - if (of_property_match_string(dnode, "interrupt-names", prop) < 0) - return -ENOENT; - - irql = of_irq_get_byname(dnode, prop); - if (irql < 0) { - pr_err("[%s]: Error getting IRQ \"%s\"\n", desc->name, - prop); - return irql; - } - *irq = irql; - return 0; -} - -static int __get_smem_state(struct subsys_desc *desc, const char *prop, - int *smem_bit) -{ - struct device_node *dnode = desc->dev->of_node; - - if (of_find_property(dnode, "qcom,smem-states", NULL)) { - desc->state = qcom_smem_state_get(desc->dev, prop, smem_bit); - if (IS_ERR_OR_NULL(desc->state)) { - pr_err("Could not get smem-states %s\n", prop); - return PTR_ERR(desc->state); - } - return 0; - } - return -ENOENT; -} - static int subsys_parse_devicetree(struct subsys_desc *desc) { struct subsys_soc_restart_order *order; - int ret; struct platform_device *pdev = container_of(desc->dev, struct platform_device, dev); - ret = __get_irq(desc, "qcom,err-fatal", &desc->err_fatal_irq); - if (ret && ret != -ENOENT) - return ret; - - ret = __get_irq(desc, "qcom,err-ready", &desc->err_ready_irq); - if (ret && ret != -ENOENT) - return ret; - - ret = __get_irq(desc, "qcom,stop-ack", &desc->stop_ack_irq); - if (ret && ret != -ENOENT) - return ret; - - ret = __get_irq(desc, "qcom,ramdump-disabled", - &desc->ramdump_disable_irq); - if (ret && ret != -ENOENT) - return ret; - - ret = __get_irq(desc, "qcom,shutdown-ack", &desc->shutdown_ack_irq); - if (ret && ret != -ENOENT) - return ret; - - ret = __get_irq(desc, "qcom,wdog", &desc->wdog_bite_irq); - if (ret && ret != -ENOENT) - return ret; - - ret = __get_smem_state(desc, "qcom,force-stop", &desc->force_stop_bit); - if (ret && ret != -ENOENT) - return 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; - } - desc->ignore_ssr_failure = of_property_read_bool(pdev->dev.of_node, "qcom,ignore-ssr-failure"); @@ -1610,130 +1432,6 @@ static int subsys_parse_devicetree(struct subsys_desc *desc) return 0; } -static int subsys_setup_irqs(struct subsys_device *subsys) -{ - struct subsys_desc *desc = subsys->desc; - int ret; - - if (desc->err_fatal_irq && desc->err_fatal_handler) { - ret = devm_request_threaded_irq(desc->dev, desc->err_fatal_irq, - NULL, - desc->err_fatal_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - desc->name, desc); - if (ret < 0) { - dev_err(desc->dev, "[%s]: Unable to register error fatal IRQ handler: %d, irq is %d\n", - desc->name, ret, desc->err_fatal_irq); - return ret; - } - disable_irq(desc->err_fatal_irq); - } - - if (desc->stop_ack_irq && desc->stop_ack_handler) { - ret = devm_request_threaded_irq(desc->dev, desc->stop_ack_irq, - NULL, - desc->stop_ack_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - desc->name, desc); - if (ret < 0) { - dev_err(desc->dev, "[%s]: Unable to register stop ack handler: %d\n", - desc->name, ret); - return ret; - } - disable_irq(desc->stop_ack_irq); - } - - if (desc->wdog_bite_irq && desc->wdog_bite_handler) { - ret = devm_request_irq(desc->dev, desc->wdog_bite_irq, - desc->wdog_bite_handler, - IRQF_TRIGGER_RISING, desc->name, desc); - if (ret < 0) { - dev_err(desc->dev, "[%s]: Unable to register wdog bite handler: %d\n", - desc->name, ret); - return ret; - } - disable_irq(desc->wdog_bite_irq); - } - - if (desc->shutdown_ack_irq && desc->shutdown_ack_handler) { - ret = devm_request_threaded_irq(desc->dev, - desc->shutdown_ack_irq, - NULL, - desc->shutdown_ack_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - desc->name, desc); - if (ret < 0) { - dev_err(desc->dev, "[%s]: Unable to register shutdown ack handler: %d\n", - desc->name, ret); - return ret; - } - disable_irq(desc->shutdown_ack_irq); - } - - if (desc->ramdump_disable_irq && desc->ramdump_disable_handler) { - ret = devm_request_threaded_irq(desc->dev, - desc->ramdump_disable_irq, - NULL, - desc->ramdump_disable_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - desc->name, desc); - if (ret < 0) { - dev_err(desc->dev, "[%s]: Unable to register shutdown ack handler: %d\n", - desc->name, ret); - return ret; - } - disable_irq(desc->ramdump_disable_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_threaded_irq(desc->dev, - desc->err_ready_irq, - NULL, - subsys_err_ready_intr_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "error_ready_interrupt", subsys); - if (ret < 0) { - dev_err(desc->dev, - "[%s]: Unable to register err ready handler\n", - desc->name); - return ret; - } - disable_irq(desc->err_ready_irq); - } - - return 0; -} - -static void subsys_free_irqs(struct subsys_device *subsys) -{ - struct subsys_desc *desc = subsys->desc; - - if (desc->err_fatal_irq && desc->err_fatal_handler) - devm_free_irq(desc->dev, desc->err_fatal_irq, desc); - if (desc->stop_ack_irq && desc->stop_ack_handler) - devm_free_irq(desc->dev, desc->stop_ack_irq, desc); - if (desc->shutdown_ack_irq && desc->shutdown_ack_handler) - devm_free_irq(desc->dev, desc->shutdown_ack_irq, desc); - if (desc->ramdump_disable_irq && desc->ramdump_disable_handler) - devm_free_irq(desc->dev, desc->ramdump_disable_irq, desc); - if (desc->wdog_bite_irq && desc->wdog_bite_handler) - devm_free_irq(desc->dev, desc->wdog_bite_irq, desc); - if (desc->err_ready_irq) - devm_free_irq(desc->dev, desc->err_ready_irq, subsys); -} - struct subsys_device *subsys_register(struct subsys_desc *desc) { struct subsys_device *subsys; @@ -1775,7 +1473,6 @@ struct subsys_device *subsys_register(struct subsys_desc *desc) dev_set_name(&subsys->dev, "subsys%d", subsys->id); mutex_init(&subsys->track.lock); - init_completion(&subsys->err_ready); ret = device_register(&subsys->dev); if (ret) { @@ -1832,16 +1529,7 @@ struct subsys_device *subsys_register(struct subsys_desc *desc) list_add_tail(&subsys->list, &subsys_list); mutex_unlock(&subsys_list_lock); - if (ofnode) { - ret = subsys_setup_irqs(subsys); - if (ret < 0) - goto err_setup_irqs; - } - return subsys; -err_setup_irqs: - if (subsys->desc->edge) - sysmon_glink_unregister(desc); err_sysmon_glink_register: sysmon_notifier_unregister(subsys->desc); err_sysmon_notifier: @@ -1873,7 +1561,6 @@ void subsys_unregister(struct subsys_device *subsys) mutex_unlock(&subsys_list_lock); if (device) { - subsys_free_irqs(subsys); subsys_remove_restart_order(device); } mutex_lock(&subsys->track.lock); diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index fda0cba15c5a..caa0c3be0d02 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ struct reg_info { * @u32 bits_arr[2]: array of bit positions in SCSR registers */ struct pil_tz_data { + struct device *dev; struct reg_info *regs; struct reg_info *proxy_regs; struct clk **clks; @@ -98,6 +100,7 @@ struct pil_tz_data { struct icc_path *bus_client; bool enable_bus_scaling; bool keep_proxy_regs_on; + struct completion err_ready; struct completion stop_ack; struct completion shutdown_ack; struct pil_desc desc; @@ -109,6 +112,15 @@ struct pil_tz_data { void __iomem *err_status; void __iomem *err_status_spare; u32 bits_arr[2]; + int err_fatal_irq; + int err_ready_irq; + int stop_ack_irq; + int wdog_bite_irq; + int generic_irq; + int ramdump_disable_irq; + int shutdown_ack_irq; + int force_stop_bit; + struct qcom_smem_state *state; }; enum pas_id { @@ -130,6 +142,34 @@ static struct icc_path *scm_perf_client; static int scm_pas_bw_count; static DEFINE_MUTEX(scm_pas_bw_mutex); +static void subsys_disable_all_irqs(struct pil_tz_data *d); +static void subsys_enable_all_irqs(struct pil_tz_data *d); + +static int enable_debug; +module_param(enable_debug, int, 0644); + +static int wait_for_err_ready(struct pil_tz_data *d) +{ + int ret; + + /* + * If subsys is using generic_irq in which case err_ready_irq will be 0, + * don't return. + */ + if ((d->generic_irq <= 0 && !d->err_ready_irq) || + enable_debug == 1 || pil_is_timeout_disabled()) + return 0; + + ret = wait_for_completion_interruptible_timeout(&d->err_ready, + msecs_to_jiffies(10000)); + if (!ret) { + pr_err("[%s]: Error ready timed out\n", d->desc.name); + return -ETIMEDOUT; + } + + return 0; +} + static int scm_pas_enable_bw(void) { int ret = 0; @@ -711,20 +751,21 @@ static int subsys_shutdown(const struct subsys_desc *subsys, bool force_stop) int ret; if (!subsys_get_crash_status(d->subsys) && force_stop && - subsys->state) { - qcom_smem_state_update_bits(subsys->state, - BIT(subsys->force_stop_bit), - BIT(subsys->force_stop_bit)); + d->state) { + qcom_smem_state_update_bits(d->state, + BIT(d->force_stop_bit), + BIT(d->force_stop_bit)); ret = wait_for_completion_timeout(&d->stop_ack, msecs_to_jiffies(STOP_ACK_TIMEOUT_MS)); if (!ret) pr_warn("Timed out on stop ack from %s.\n", subsys->name); - qcom_smem_state_update_bits(subsys->state, - BIT(subsys->force_stop_bit), 0); + qcom_smem_state_update_bits(d->state, + BIT(d->force_stop_bit), 0); } pil_shutdown(&d->desc); + subsys_disable_all_irqs(d); return 0; } @@ -733,11 +774,28 @@ static int subsys_powerup(const struct subsys_desc *subsys) struct pil_tz_data *d = subsys_to_data(subsys); int ret = 0; - if (subsys->stop_ack_irq) + reinit_completion(&d->err_ready); + + if (d->stop_ack_irq) reinit_completion(&d->stop_ack); d->desc.fw_name = subsys->fw_name; ret = pil_boot(&d->desc); + if (ret) { + pr_err("pil_boot failed for %s\n", d->subsys_desc.name); + return ret; + } + + pr_info("pil_boot is successful from %s and waiting for error ready\n", + d->subsys_desc.name); + subsys_enable_all_irqs(d); + ret = wait_for_err_ready(d); + if (ret) { + pr_err("%s failed to get error ready for %s\n", __func__, + d->subsys_desc.name); + pil_shutdown(&d->desc); + subsys_disable_all_irqs(d); + } return ret; } @@ -763,17 +821,28 @@ static void subsys_crash_shutdown(const struct subsys_desc *subsys) { struct pil_tz_data *d = subsys_to_data(subsys); - if (subsys->state && !subsys_get_crash_status(d->subsys)) { - qcom_smem_state_update_bits(subsys->state, - BIT(subsys->force_stop_bit), - BIT(subsys->force_stop_bit)); + if (d->state && !subsys_get_crash_status(d->subsys)) { + qcom_smem_state_update_bits(d->state, + BIT(d->force_stop_bit), + BIT(d->force_stop_bit)); mdelay(CRASH_STOP_ACK_TO_MS); } } -static irqreturn_t subsys_err_fatal_intr_handler (int irq, void *dev_id) + +static irqreturn_t subsys_err_ready_intr_handler(int irq, void *drv_data) { - struct pil_tz_data *d = subsys_to_data(dev_id); + struct pil_tz_data *d = drv_data; + + pr_info("Subsystem error monitoring/handling services are up from%s\n", + d->subsys_desc.name); + complete(&d->err_ready); + return IRQ_HANDLED; +} + +static irqreturn_t subsys_err_fatal_intr_handler (int irq, void *drv_data) +{ + struct pil_tz_data *d = drv_data; pr_err("Fatal error on %s!\n", d->subsys_desc.name); if (subsys_get_crash_status(d->subsys)) { @@ -788,9 +857,9 @@ static irqreturn_t subsys_err_fatal_intr_handler (int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *dev_id) +static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *drv_data) { - struct pil_tz_data *d = subsys_to_data(dev_id); + struct pil_tz_data *d = drv_data; if (subsys_get_crash_status(d->subsys)) return IRQ_HANDLED; @@ -806,18 +875,18 @@ static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id) +static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *drv_data) { - struct pil_tz_data *d = subsys_to_data(dev_id); + struct pil_tz_data *d = drv_data; pr_info("Received stop ack interrupt from %s\n", d->subsys_desc.name); complete(&d->stop_ack); return IRQ_HANDLED; } -static irqreturn_t subsys_shutdown_ack_intr_handler(int irq, void *dev_id) +static irqreturn_t subsys_shutdown_ack_intr_handler(int irq, void *drv_data) { - struct pil_tz_data *d = subsys_to_data(dev_id); + struct pil_tz_data *d = drv_data; pr_info("Received stop shutdown interrupt from %s\n", d->subsys_desc.name); @@ -825,9 +894,9 @@ static irqreturn_t subsys_shutdown_ack_intr_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t subsys_ramdump_disable_intr_handler(int irq, void *dev_id) +static irqreturn_t subsys_ramdump_disable_intr_handler(int irq, void *drv_data) { - struct pil_tz_data *d = subsys_to_data(dev_id); + struct pil_tz_data *d = drv_data; pr_info("Received ramdump disable interrupt from %s\n", d->subsys_desc.name); @@ -876,7 +945,7 @@ static void clear_err_ready(struct pil_tz_data *d) d->subsys_desc.name); __raw_writel(BIT(d->bits_arr[ERR_READY]), d->irq_clear); - complete_err_ready(d->subsys); + complete(&d->err_ready); } static void clear_sw_init_done_error(struct pil_tz_data *d, int err) @@ -914,9 +983,9 @@ static void clear_wdog(struct pil_tz_data *d) } } -static irqreturn_t subsys_generic_handler(int irq, void *dev_id) +static irqreturn_t subsys_generic_handler(int irq, void *drv_data) { - struct pil_tz_data *d = subsys_to_data(dev_id); + struct pil_tz_data *d = drv_data; uint32_t status_val, err_value; err_value = __raw_readl(d->err_status_spare); @@ -946,6 +1015,229 @@ static void mask_scsr_irqs(struct pil_tz_data *d) ~BIT(d->bits_arr[PBL_DONE]), d->irq_mask); } +static void subsys_enable_all_irqs(struct pil_tz_data *d) +{ + if (d->err_ready_irq) + enable_irq(d->err_ready_irq); + if (d->wdog_bite_irq) { + enable_irq(d->wdog_bite_irq); + irq_set_irq_wake(d->wdog_bite_irq, 1); + } + if (d->err_fatal_irq) + enable_irq(d->err_fatal_irq); + if (d->stop_ack_irq) + enable_irq(d->stop_ack_irq); + if (d->shutdown_ack_irq) + enable_irq(d->shutdown_ack_irq); + if (d->ramdump_disable_irq) + enable_irq(d->ramdump_disable_irq); + if (d->generic_irq) { + enable_irq(d->generic_irq); + irq_set_irq_wake(d->generic_irq, 1); + } +} + +static void subsys_disable_all_irqs(struct pil_tz_data *d) +{ + if (d->err_ready_irq) + disable_irq(d->err_ready_irq); + if (d->wdog_bite_irq) { + disable_irq(d->wdog_bite_irq); + irq_set_irq_wake(d->wdog_bite_irq, 0); + } + if (d->err_fatal_irq) + disable_irq(d->err_fatal_irq); + if (d->stop_ack_irq) + disable_irq(d->stop_ack_irq); + if (d->shutdown_ack_irq) + disable_irq(d->shutdown_ack_irq); + if (d->generic_irq) { + disable_irq(d->generic_irq); + irq_set_irq_wake(d->generic_irq, 0); + } +} + +static int __get_irq(struct platform_device *pdev, const char *prop, + unsigned int *irq) +{ + int irql = 0; + struct device_node *dnode = pdev->dev.of_node; + + if (of_property_match_string(dnode, "interrupt-names", prop) < 0) + return -ENOENT; + + irql = of_irq_get_byname(dnode, prop); + if (irql < 0) { + pr_err("[%s]: Error getting IRQ \"%s\"\n", pdev->name, + prop); + return irql; + } + *irq = irql; + return 0; +} + +static int __get_smem_state(struct pil_tz_data *d, const char *prop, + int *smem_bit) +{ + struct device_node *dnode = d->dev->of_node; + + if (of_find_property(dnode, "qcom,smem-states", NULL)) { + d->state = qcom_smem_state_get(d->dev, prop, smem_bit); + if (IS_ERR_OR_NULL(d->state)) { + pr_err("Could not get smem-states %s\n", prop); + return PTR_ERR(d->state); + } + return 0; + } + return -ENOENT; +} + + +static int subsys_parse_irqs(struct platform_device *pdev) +{ + int ret; + struct pil_tz_data *d = platform_get_drvdata(pdev); + + ret = __get_irq(pdev, "qcom,err-fatal", &d->err_fatal_irq); + if (ret && ret != -ENOENT) + return ret; + + ret = __get_irq(pdev, "qcom,err-ready", &d->err_ready_irq); + if (ret && ret != -ENOENT) + return ret; + + ret = __get_irq(pdev, "qcom,stop-ack", &d->stop_ack_irq); + if (ret && ret != -ENOENT) + return ret; + + ret = __get_irq(pdev, "qcom,ramdump-disabled", + &d->ramdump_disable_irq); + if (ret && ret != -ENOENT) + return ret; + + ret = __get_irq(pdev, "qcom,shutdown-ack", &d->shutdown_ack_irq); + if (ret && ret != -ENOENT) + return ret; + + ret = __get_irq(pdev, "qcom,wdog", &d->wdog_bite_irq); + if (ret && ret != -ENOENT) + return ret; + + ret = __get_smem_state(d, "qcom,force-stop", &d->force_stop_bit); + if (ret && ret != -ENOENT) + return ret; + + if (of_property_read_bool(pdev->dev.of_node, + "qcom,pil-generic-irq-handler")) { + ret = platform_get_irq(pdev, 0); + if (ret > 0) + d->generic_irq = ret; + } + + return 0; +} + +static int subsys_setup_irqs(struct platform_device *pdev) +{ + int ret; + struct pil_tz_data *d = platform_get_drvdata(pdev); + + if (d->err_fatal_irq) { + ret = devm_request_threaded_irq(&pdev->dev, d->err_fatal_irq, + NULL, subsys_err_fatal_intr_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + d->desc.name, d); + if (ret < 0) { + dev_err(&pdev->dev, "[%s]: Unable to register error fatal IRQ handler: %d, irq is %d\n", + d->desc.name, ret, d->err_fatal_irq); + return ret; + } + disable_irq(d->err_fatal_irq); + } + + if (d->stop_ack_irq) { + ret = devm_request_threaded_irq(&pdev->dev, d->stop_ack_irq, + NULL, subsys_stop_ack_intr_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + d->desc.name, d); + if (ret < 0) { + dev_err(&pdev->dev, "[%s]: Unable to register stop ack handler: %d\n", + d->desc.name, ret); + return ret; + } + disable_irq(d->stop_ack_irq); + } + + if (d->wdog_bite_irq) { + ret = devm_request_irq(&pdev->dev, d->wdog_bite_irq, + subsys_wdog_bite_irq_handler, + IRQF_TRIGGER_RISING, d->desc.name, d); + if (ret < 0) { + dev_err(&pdev->dev, "[%s]: Unable to register wdog bite handler: %d\n", + d->desc.name, ret); + return ret; + } + disable_irq(d->wdog_bite_irq); + } + + if (d->shutdown_ack_irq) { + ret = devm_request_threaded_irq(&pdev->dev, + d->shutdown_ack_irq, + NULL, subsys_shutdown_ack_intr_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + d->desc.name, d); + if (ret < 0) { + dev_err(&pdev->dev, "[%s]: Unable to register shutdown ack handler: %d\n", + d->desc.name, ret); + return ret; + } + disable_irq(d->shutdown_ack_irq); + } + + if (d->ramdump_disable_irq) { + ret = devm_request_threaded_irq(d->dev, + d->ramdump_disable_irq, + NULL, subsys_ramdump_disable_intr_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + d->desc.name, d); + if (ret < 0) { + dev_err(&pdev->dev, "[%s]: Unable to register shutdown ack handler: %d\n", + d->desc.name, ret); + return ret; + } + disable_irq(d->ramdump_disable_irq); + } + + if (d->generic_irq) { + ret = devm_request_irq(&pdev->dev, d->generic_irq, + subsys_generic_handler, + IRQF_TRIGGER_HIGH, d->desc.name, d); + if (ret < 0) { + dev_err(&pdev->dev, "[%s]: Unable to register generic irq handler: %d\n", + d->desc.name, ret); + return ret; + } + disable_irq(d->generic_irq); + } + + if (d->err_ready_irq) { + ret = devm_request_threaded_irq(d->dev, + d->err_ready_irq, + NULL, subsys_err_ready_intr_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "error_ready_interrupt", d); + if (ret < 0) { + dev_err(&pdev->dev, + "[%s]: Unable to register err ready handler\n", + d->desc.name); + return ret; + } + disable_irq(d->err_ready_irq); + } + + return 0; +} + static int pil_tz_generic_probe(struct platform_device *pdev) { struct pil_tz_data *d; @@ -992,11 +1284,16 @@ static int pil_tz_generic_probe(struct platform_device *pdev) } } + d->dev = &pdev->dev; d->desc.dev = &pdev->dev; d->desc.owner = THIS_MODULE; d->desc.ops = &pil_ops_trusted; d->desc.proxy_timeout = PROXY_TIMEOUT_MS; + rc = subsys_parse_irqs(pdev); + if (rc) + return rc; + d->desc.clear_fw_region = true; rc = of_property_read_u32(pdev->dev.of_node, "qcom,proxy-timeout-ms", @@ -1023,6 +1320,8 @@ static int pil_tz_generic_probe(struct platform_device *pdev) goto err_deregister_bus; init_completion(&d->stop_ack); + init_completion(&d->err_ready); + d->subsys_desc.name = d->desc.name; d->subsys_desc.owner = THIS_MODULE; d->subsys_desc.dev = &pdev->dev; @@ -1033,7 +1332,6 @@ static int pil_tz_generic_probe(struct platform_device *pdev) d->subsys_desc.crash_shutdown = subsys_crash_shutdown; 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); @@ -1089,17 +1387,8 @@ static int pil_tz_generic_probe(struct platform_device *pdev) goto err_ramdump; } mask_scsr_irqs(d); - - } 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->subsys_desc.shutdown_ack_handler = - subsys_shutdown_ack_intr_handler; - d->subsys_desc.ramdump_disable_handler = - subsys_ramdump_disable_intr_handler; } + d->desc.signal_aop = of_property_read_bool(pdev->dev.of_node, "qcom,signal-aop"); if (d->desc.signal_aop) { @@ -1139,6 +1428,12 @@ static int pil_tz_generic_probe(struct platform_device *pdev) goto err_subsys; } + rc = subsys_setup_irqs(pdev); + if (rc) { + subsys_unregister(d->subsys); + goto err_subsys; + } + return 0; err_subsys: destroy_ramdump_device(d->minidump_dev); diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h index 11878bbe7dbe..5612d886ca6e 100644 --- a/include/soc/qcom/subsystem_restart.h +++ b/include/soc/qcom/subsystem_restart.h @@ -69,8 +69,6 @@ struct subsys_notif_timeout { * @crash_shutdown: Shutdown a subsystem when the system crashes (can't sleep) * @ramdump: Collect a ramdump of the subsystem * @free_memory: Free the memory associated with this subsystem - * @is_not_loadable: Indicate if subsystem firmware is not loadable via pil - * framework * @no_auth: Set if subsystem does not rely on PIL to authenticate and bring * it out of reset * @ssctl_instance_id: Instance id used to connect with SSCTL service @@ -95,20 +93,8 @@ struct subsys_desc { void (*crash_shutdown)(const struct subsys_desc *desc); int (*ramdump)(int need_dumps, const struct subsys_desc *desc); void (*free_memory)(const struct subsys_desc *desc); - irqreturn_t (*err_fatal_handler)(int irq, void *dev_id); - irqreturn_t (*stop_ack_handler)(int irq, void *dev_id); - irqreturn_t (*shutdown_ack_handler)(int irq, void *dev_id); - irqreturn_t (*ramdump_disable_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); struct completion shutdown_ack; - 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_bit; int ramdump_disable_irq; int shutdown_ack_irq; @@ -164,7 +150,6 @@ extern enum crash_status subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void notify_before_auth_and_reset(struct device *device); -void complete_err_ready(struct subsys_device *subsys); static inline void complete_shutdown_ack(struct subsys_desc *desc) { complete(&desc->shutdown_ack);