From patchwork Tue Dec 15 05:59:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 58376 Delivered-To: patches@linaro.org Received: by 10.112.73.68 with SMTP id j4csp1922220lbv; Mon, 14 Dec 2015 21:59:11 -0800 (PST) X-Received: by 10.98.80.69 with SMTP id e66mr22299329pfb.66.1450159151233; Mon, 14 Dec 2015 21:59:11 -0800 (PST) Return-Path: Received: from mail-pf0-x22e.google.com (mail-pf0-x22e.google.com. [2607:f8b0:400e:c00::22e]) by mx.google.com with ESMTPS id h85si12171880pfj.177.2015.12.14.21.59.10 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Dec 2015 21:59:11 -0800 (PST) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 2607:f8b0:400e:c00::22e as permitted sender) client-ip=2607:f8b0:400e:c00::22e; Authentication-Results: mx.google.com; spf=pass (google.com: domain of john.stultz@linaro.org designates 2607:f8b0:400e:c00::22e as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dkim=pass header.i=@linaro.org Received: by pfnn128 with SMTP id n128so118647362pfn.0 for ; Mon, 14 Dec 2015 21:59:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=VDuTkPNaiRduoThtl25B6jS8gUxws5nwgEQgBF8EJjc=; b=Tqw5I7AHgGeUeNcdkwf4RoP2KZgo+xRTl27dkwd/uPYj0rgXSQGPzUILNHOJCVGEWP vJbF6ncavCTn5V+jfCp5nFlRy51m6QGsckpDpSUzJlQRPsE0nHikX4lX07Ts3g5qFQzV WXH7iyrUSNO8zeffuqbi259DIxRRao4O0ohag= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=VDuTkPNaiRduoThtl25B6jS8gUxws5nwgEQgBF8EJjc=; b=El1YP3rqNPK4MG/Nb5Juc7X+B3DXwZ333G71nq67NhaLAv1yHuA8PAUjb5ZFo88Zcc Ki2xvgA8DOAaIWwLrvbQ6/ShtqXDSZFAMLKNMCfOefFifgsOIf0Gi6dEJOszEJqsq7pd KcrIJMIhE1bSPPgxMwqDuRTBiPA9F1KWGWTNx7HekTTYBFrzBFQiACunzozIjASdjFmA nalAnsBRqTDj3TX+zDeUUona8wPty57y8Bqpv6zheICPcA91u9ryYQ9POIuZrgs7GitT +x6CpRjDmcZnF1qZOQxxnRsWjQoOnDm3dl86aSfHVdsV5MoPoISkqewFlIo7JVg3ziCa KfbQ== X-Gm-Message-State: ALoCoQn8jUxiN9rmjacnz9k/Iy6Mq41KQf35qBPxIWljear9RldS6ZOrdY2FKuDR16KWtzDtz4alXb7LQMzRhDCoF0w3qXkGLA== X-Received: by 10.98.44.207 with SMTP id s198mr6816366pfs.11.1450159150873; Mon, 14 Dec 2015 21:59:10 -0800 (PST) Return-Path: Received: from localhost.localdomain (c-76-115-103-22.hsd1.or.comcast.net. [76.115.103.22]) by smtp.gmail.com with ESMTPSA id dg1sm46563156pad.18.2015.12.14.21.59.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 14 Dec 2015 21:59:10 -0800 (PST) From: John Stultz To: Cc: John Stultz , Vishal Bhoj , haojian.zhuang@linaro.org, guodong.xu@linaro.org Subject: [PATCH 1/2] firmware: Introduce reboot_reason driver Date: Mon, 14 Dec 2015 21:59:06 -0800 Message-Id: <1450159147-13626-1-git-send-email-john.stultz@linaro.org> X-Mailer: git-send-email 1.9.1 This patch adds a basic driver to allow for commands like "reboot bootloader" and "reboot recovery" to communicate this reboot-reason to the bootloader. This is commonly done on Android devices, in order to reboot the device into fastboot or recovery mode. It also supports custom OEM specific commands, via "reboot oem-". This driver pulls the phys memory address from DT as well as the magic reason values that are written to the address for each mode. Cc: Vishal Bhoj Cc: haojian.zhuang@linaro.org Cc: guodong.xu@linaro.org Signed-off-by: John Stultz --- drivers/firmware/Kconfig | 9 +++ drivers/firmware/Makefile | 1 + drivers/firmware/reboot_reason_sram.c | 107 ++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 drivers/firmware/reboot_reason_sram.c -- 1.9.1 diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 6517132..de507b6 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -136,6 +136,15 @@ config QCOM_SCM bool depends on ARM || ARM64 +config REBOOT_REASON_SRAM + bool "Pass reboot reason to bootloader via SRAM" + default n + help + On many systems there is a desire to provide a reboot reason to + the bootloader, so that the bootloader can boot into a desired + mode on the next boot. This option enables support for communicating + this reason to the bootloader via SRAM + source "drivers/firmware/google/Kconfig" source "drivers/firmware/efi/Kconfig" diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 3fdd391..5e538bc 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_QCOM_SCM) += qcom_scm.o CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) +obj-$(CONFIG_REBOOT_REASON_SRAM)+= reboot_reason_sram.o obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-$(CONFIG_EFI) += efi/ diff --git a/drivers/firmware/reboot_reason_sram.c b/drivers/firmware/reboot_reason_sram.c new file mode 100644 index 0000000..af87b6d --- /dev/null +++ b/drivers/firmware/reboot_reason_sram.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Types of reasons */ +enum { + NONE, + BOOTLOADER, + RECOVERY, + OEM, + MAX_REASONS +}; + +static u32 reasons[MAX_REASONS]; +static void __iomem *reboot_reason_val_addr; +static struct notifier_block reboot_nb; + +static int reboot_reason(struct notifier_block *nb, unsigned long action, + void *data) +{ + char *cmd = (char *)data; + u32 reason = reasons[NONE]; + + if (!reboot_reason_val_addr) + return NOTIFY_DONE; + + if (cmd != NULL) { + if (!strncmp(cmd, "bootloader", 10)) + reason = reasons[BOOTLOADER]; + else if (!strncmp(cmd, "recovery", 8)) + reason = reasons[RECOVERY]; + else if (!strncmp(cmd, "oem-", 4)) { + unsigned long code; + + if (!kstrtoul(cmd+4, 0, &code)) + reason = reasons[OEM] | (code & 0xff); + } + } + + if (reason != -1) + writel(reason, reboot_reason_val_addr); + return NOTIFY_DONE; +} + +static int reboot_reason_probe(struct platform_device *pdev) +{ + struct resource *res; + u32 val; + int i; + + /* initialize the reasons */ + for (i = 0; i < MAX_REASONS; i++) + reasons[i] = -1; + + /* Try to grab the reason io address */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reboot_reason_val_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(reboot_reason_val_addr)) + return PTR_ERR(reboot_reason_val_addr); + + /* initialize specified reasons from DT */ + if (!of_property_read_u32(pdev->dev.of_node, "reason,none", &val)) + reasons[NONE] = val; + if (!of_property_read_u32(pdev->dev.of_node, "reason,bootloader", &val)) + reasons[BOOTLOADER] = val; + if (!of_property_read_u32(pdev->dev.of_node, "reason,recovery", &val)) + reasons[RECOVERY] = val; + if (!of_property_read_u32(pdev->dev.of_node, "reason,oem", &val)) + reasons[OEM] = val; + + /* Install the notifier */ + reboot_nb.notifier_call = reboot_reason; + reboot_nb.priority = 256; + if (register_reboot_notifier(&reboot_nb)) { + dev_err(&pdev->dev, + "failed to setup restart handler.\n"); + } + return 0; +} + +int reboot_reason_remove(struct platform_device *pdev) +{ + unregister_reboot_notifier(&reboot_nb); + return 0; +} + +static const struct of_device_id reboot_reason_of_match[] = { + { .compatible = "linux,reboot-reason-sram", }, + { }, +}; +MODULE_DEVICE_TABLE(of, reboot_reason_of_match); + +static struct platform_driver reboot_reason_driver = { + .driver = { + .name = "reboot-reason-sram", + .of_match_table = reboot_reason_of_match, + }, + .probe = reboot_reason_probe, + .remove = reboot_reason_remove, +}; +module_platform_driver(reboot_reason_driver);