From patchwork Tue Aug 30 13:06:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nishanth Menon X-Patchwork-Id: 9305395 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6EB91607F0 for ; Tue, 30 Aug 2016 13:08:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 60DB128AD2 for ; Tue, 30 Aug 2016 13:08:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 559C828AED; Tue, 30 Aug 2016 13:08:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 50F1728ADC for ; Tue, 30 Aug 2016 13:08:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752007AbcH3NIG (ORCPT ); Tue, 30 Aug 2016 09:08:06 -0400 Received: from devils.ext.ti.com ([198.47.26.153]:42738 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751798AbcH3NID (ORCPT ); Tue, 30 Aug 2016 09:08:03 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id u7UD74rQ016770; Tue, 30 Aug 2016 08:07:04 -0500 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id u7UD72En008508; Tue, 30 Aug 2016 08:07:03 -0500 Received: from dlep32.itg.ti.com (157.170.170.100) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.294.0; Tue, 30 Aug 2016 08:07:01 -0500 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id u7UD72EX014409; Tue, 30 Aug 2016 08:07:02 -0500 From: Nishanth Menon To: Russell King , Sudeep Holla , Santosh Shilimkar CC: Russ Dill , Dave Gerlach , Lokesh Vutla , Peter Ujfalusi , "Andrew F . Davis" , Rob Herring , Tero Kristo , , , , , Nishanth Menon Subject: [PATCH V2 5/5] firmware: ti_sci: Add support for reboot core service Date: Tue, 30 Aug 2016 08:06:47 -0500 Message-ID: <20160830130647.6828-6-nm@ti.com> X-Mailer: git-send-email 2.9.1.200.gb1ec08f In-Reply-To: <20160830130647.6828-1-nm@ti.com> References: <20160830130647.6828-1-nm@ti.com> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Since system controller now has control over SoC power management, it needs to be explicitly requested to reboot the SoC. Add support for it. In some systems however, SoC needs to toggle a GPIO or send event to an external entity (like a PMIC) for a system reboot to take place. To facilitate that, we allow for a DT property to determine if the reboot handler will be registered and further, the service is also made available to other drivers (such as PMIC driver) to sequence the additional operation and trigger the SoC reboot as the last step. Tested-by: Lokesh Vutla Signed-off-by: Nishanth Menon --- Changes since v1: - s/tis_sci_is_response_ack/ti_sci_is_response_ack - Removed binding from this patch into patch #1 of the series. v1: https://patchwork.kernel.org/patch/9291351/ drivers/firmware/ti_sci.c | 85 ++++++++++++++++++++++++++++++++++ drivers/firmware/ti_sci.h | 12 +++++ include/linux/soc/ti/ti_sci_protocol.h | 11 +++++ 3 files changed, 108 insertions(+) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index a9d83201fc40..eee8853835dc 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "ti_sci.h" @@ -90,6 +91,7 @@ struct ti_sci_desc { * struct ti_sci_info - Structure representing a TI SCI instance * @dev: Device pointer * @desc: SoC description for this instance + * @nb: Reboot Notifier block * @d: Debugfs file entry * @debug_region: Memory region where the debug message are available * @debug_region_size: Debug region size @@ -104,6 +106,7 @@ struct ti_sci_desc { */ struct ti_sci_info { struct device *dev; + struct notifier_block nb; const struct ti_sci_desc *desc; struct dentry *d; void __iomem *debug_region; @@ -117,11 +120,15 @@ struct ti_sci_info { struct list_head node; /* protected by ti_sci_list_mutex */ int users; + }; #define cl_to_ti_sci_info(cl) container_of(cl, struct ti_sci_info, cl) #define handle_to_ti_sci_info(handle) container_of(handle, struct ti_sci_info,\ handle) +#define reboot_to_ti_sci_info(nb) container_of(nb,\ + struct ti_sci_info,\ + nb) #ifdef CONFIG_DEBUG_FS /** @@ -1571,6 +1578,52 @@ fail: return ret; } +static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) +{ + struct ti_sci_info *info; + struct ti_sci_msg_req_reboot *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + struct device *dev; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + dev = info->dev; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SYS_RESET, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_req_reboot *)xfer->xfer_buf; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + ret = 0; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -1578,9 +1631,12 @@ fail: static void ti_sci_setup_ops(struct ti_sci_info *info) { struct ti_sci_ops *ops = &info->handle.ops; + struct ti_sci_core_ops *core_ops = &ops->core_ops; struct ti_sci_dev_ops *dops = &ops->dev_ops; struct ti_sci_clk_ops *cops = &ops->clk_ops; + core_ops->reboot_device = ti_sci_cmd_core_reboot; + dops->get_device = ti_sci_cmd_get_device; dops->idle_device = ti_sci_cmd_idle_device; dops->put_device = ti_sci_cmd_put_device; @@ -1739,6 +1795,18 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) } EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); +static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode, + void *cmd) +{ + struct ti_sci_info *info = reboot_to_ti_sci_info(nb); + const struct ti_sci_handle *handle = &info->handle; + + ti_sci_cmd_core_reboot(handle); + + /* call fail OR pass, we should not be here in the first place */ + return NOTIFY_BAD; +} + /* Description for K2G */ static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { .host_id = 2, @@ -1766,6 +1834,7 @@ static int ti_sci_probe(struct platform_device *pdev) struct mbox_client *cl; int ret = -EINVAL; int i; + int reboot = 0; of_id = of_match_device(ti_sci_of_match, dev); if (!of_id) { @@ -1780,6 +1849,8 @@ static int ti_sci_probe(struct platform_device *pdev) info->dev = dev; info->desc = desc; + reboot = of_property_read_bool(dev->of_node, + "ti,system-reboot-controller"); INIT_LIST_HEAD(&info->node); minfo = &info->minfo; @@ -1852,6 +1923,17 @@ static int ti_sci_probe(struct platform_device *pdev) ti_sci_setup_ops(info); + if (reboot) { + info->nb.notifier_call = tisci_reboot_handler; + info->nb.priority = 128; + + ret = register_restart_handler(&info->nb); + if (ret) { + dev_err(dev, "reboot registration fail(%d)\n", ret); + return ret; + } + } + dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n", info->handle.version.abi_major, info->handle.version.abi_minor, info->handle.version.firmware_revision, @@ -1878,6 +1960,9 @@ static int ti_sci_remove(struct platform_device *pdev) info = platform_get_drvdata(pdev); + if (info->nb.notifier_call) + unregister_restart_handler(&info->nb); + mutex_lock(&ti_sci_list_mutex); if (info->users) ret = -EBUSY; diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index f69907cfc128..9b611e9e6f6d 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -46,6 +46,7 @@ #define TI_SCI_MSG_VERSION 0x0002 #define TI_SCI_MSG_WAKE_REASON 0x0003 #define TI_SCI_MSG_GOODBYE 0x0004 +#define TI_SCI_MSG_SYS_RESET 0x0005 /* Device requests */ #define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 @@ -106,6 +107,17 @@ struct ti_sci_msg_resp_version { } __packed; /** + * struct ti_sci_msg_req_reboot - Reboot the SoC + * @hdr: Generic Header + * + * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_reboot { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** * struct ti_sci_msg_req_set_device_state - Set the desired state of the device * @hdr: Generic header * @id: Indicates which device to modify diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 76378fddf609..0ccbc138c26a 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -36,6 +36,16 @@ struct ti_sci_version_info { struct ti_sci_handle; /** + * struct ti_sci_core_ops - SoC Core Operations + * @reboot_device: Reboot the SoC + * Returns 0 for successful request(ideally should never return), + * else returns corresponding error value. + */ +struct ti_sci_core_ops { + int (*reboot_device)(const struct ti_sci_handle *handle); +}; + +/** * struct ti_sci_dev_ops - Device control operations * @get_device: Command to request for device managed by TISCI * Returns 0 for successful exclusive request, else returns @@ -196,6 +206,7 @@ struct ti_sci_clk_ops { * @clk_ops: Clock specific operations */ struct ti_sci_ops { + struct ti_sci_core_ops core_ops; struct ti_sci_dev_ops dev_ops; struct ti_sci_clk_ops clk_ops; };