From patchwork Tue Dec 15 22:26:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 58469 Delivered-To: patches@linaro.org Received: by 10.112.89.199 with SMTP id bq7csp329265lbb; Tue, 15 Dec 2015 14:26:05 -0800 (PST) X-Received: by 10.66.155.8 with SMTP id vs8mr47464828pab.18.1450218365394; Tue, 15 Dec 2015 14:26:05 -0800 (PST) Return-Path: Received: from mail-pf0-x236.google.com (mail-pf0-x236.google.com. [2607:f8b0:400e:c00::236]) by mx.google.com with ESMTPS id 9si370338pft.153.2015.12.15.14.26.05 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 15 Dec 2015 14:26:05 -0800 (PST) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 2607:f8b0:400e:c00::236 as permitted sender) client-ip=2607:f8b0:400e:c00::236; Authentication-Results: mx.google.com; spf=pass (google.com: domain of john.stultz@linaro.org designates 2607:f8b0:400e:c00::236 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dkim=pass header.i=@linaro.org Received: by mail-pf0-x236.google.com with SMTP id o64so877577pfb.3 for ; Tue, 15 Dec 2015 14:26:05 -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=GgPEm1UPljoXlbv1r1QuIFDnvmD7baEfQeljSTKo4to=; b=BW1Tqb7cF5tpL/+Qh74SBXN6WTN9xjzGwaqpSLV5DWQyAY0L1kw/26FfGNsPVfuCVu b2AZWym+WeQ7PcyHlwEJsiDR9mlTGxelKGeJ6zAesJJObwQEIYfUd6ZlQ9HvetaxAEA/ YX4bJZRlNf8fQL7kBRptQmY0kqebOzLORPju8= 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=GgPEm1UPljoXlbv1r1QuIFDnvmD7baEfQeljSTKo4to=; b=XWSMyEi7+6TGp2LNMompHB4h/DZp9pwjVTwzlqeh19qWReXGUSab+tNXashGH8e+hT Pq7BQq7BK6eVFp2tvWW1SldXkRavUxTmlkiZZOzWqxMyRBGy0KOtN9Cap5K414JbZ2Ev QoqpQmMcH9A67MQjX/BP+FAiJoj32d3aIsg8j7scffsCtsRRKbTbhtHPTnxY4V8zrmNQ S7IScOufZHVVsuoElXHvWGlA9k8P8KkgEccoUBpURNhcA71F7fkbvFJH1oH/I0cJZsDl A6BLfHjiVGuFLBbkIZdypPWHrpkUolxQ3gcVt+T8FrWNNzw5TxJud5qbXoJDDMu2jKda iLKw== X-Gm-Message-State: ALoCoQnCv9HDh2Qn2uc7GvVq+L53msM18XBibK6TGUY4M2JtYymzKjlOEKPYqgC4w1kCsOgutVRKJhd1FTeV5QbzQYn+dI58uQ== X-Received: by 10.98.64.156 with SMTP id f28mr477669pfd.110.1450218365009; Tue, 15 Dec 2015 14:26:05 -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 sv8sm4585389pab.13.2015.12.15.14.26.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 15 Dec 2015 14:26:03 -0800 (PST) From: John Stultz To: dev@lists.96boards.org Cc: John Stultz , Vishal Bhoj , haojian.zhuang@linaro.org, guodong.xu@linaro.org Subject: [PATCH 1/2] firmware: Introduce reboot_reason driver Date: Tue, 15 Dec 2015 14:26:00 -0800 Message-Id: <1450218361-9144-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);