From patchwork Fri Mar 9 13:32:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Wahren X-Patchwork-Id: 10270607 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 D033860236 for ; Fri, 9 Mar 2018 13:33:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B77AE29D56 for ; Fri, 9 Mar 2018 13:33:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AB93A29D5A; Fri, 9 Mar 2018 13:33:45 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0B1AA29D56 for ; Fri, 9 Mar 2018 13:33:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=xcPH0VWOdZFILStt8jdWndUTp1LbvkruMpAk7NzfnmU=; b=EB3BjLnNn4TYZBEApcoV9/vxE/ AFbJdGeZzTwI9o+rEViap1q2VcYn/a7wtwWWPhPgvRC5JK5d4+XdRqXnme4wyRNvQ8rSPUfNIwDT1 ZB53rIg89pJXk1a0l4udwKoUI9XSOHaOj0u6UiYogxkddL5KRo1zk46ak+bMK/Ke2wPo182gPGVE+ V1EODeWtZoM1exyhMQ3CoFVLx0IMCVA5EY2EdKJOQbaCsT+6w7Xt6JSDtDmXu4tioErgEdVjIbbzN 1rgvbPrU9ppJIFJs2932+lenT07Ac75QfkBQC/DJi+7VGouFBkciSgG+09DzHIg1t83sAyPCDvNeT Yp7WuVjw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1euI9R-0003Is-JB; Fri, 09 Mar 2018 13:33:37 +0000 Received: from mout.kundenserver.de ([217.72.192.73]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1euI8w-00030r-Ey; Fri, 09 Mar 2018 13:33:10 +0000 Received: from localhost.localdomain ([95.90.209.156]) by mrelayeu.kundenserver.de (mreue103 [212.227.15.183]) with ESMTPSA (Nemesis) id 0Lnlkd-1eSO6D0iC7-00htJf; Fri, 09 Mar 2018 14:32:46 +0100 From: Stefan Wahren To: Srinivas Kandagatla , Rob Herring , Mark Rutland , Eric Anholt , Phil Elwell Subject: [PATCH RFC 2/3] nvmem: add driver for Raspberry Pi OTP Date: Fri, 9 Mar 2018 14:32:07 +0100 Message-Id: <1520602328-28972-3-git-send-email-stefan.wahren@i2se.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520602328-28972-1-git-send-email-stefan.wahren@i2se.com> References: <1520602328-28972-1-git-send-email-stefan.wahren@i2se.com> X-Provags-ID: V03:K0:9D7ZTHLoVKJ/rgqKftjE7pBrMGCp6cp4aA9IZ3fBFlzI5p8Jd0o OJ9Kd7oaxNVdyBWOHoSRdrYEI95VYChH5n1BpPxYPasON88c0R1fNAexwWJtu0zoDP0dSEX CgDdwYb6MdpGWMin7pcqUNL9kPIafqewPPXVEfOCITC02/HVwa/TBbJcXLhGOtVOQ2oVXL+ DJiOAioUPWiugR6PRuCyw== X-UI-Out-Filterresults: notjunk:1; V01:K0:vFQo4SHnwa8=:e8NbxWMVUqlwSDAt02eqP3 vJ8r6h3gOkm0qErz6+CpU64HbZcTB/2P7Y9msL/ZQVn1tWt/vC02TWY1VaC2oHVG2SqnyaFeF eLJgn+LLdqhM7DRIWvANvhEB5W1cgm1tRFT1k/E8iuOy3zLaZJMxcxksTkHUzq8usAiPv9ZKi sF7AzyxZOIGE4wyaE0ufqGiWgfFr/oXfEx2zU2XW4BxWHaG8P4agJoC0SxEMbnvOIiilYtm+d dYyJONy01IGZhaIGPrBU62DMxNCK8celY1fo76Mp8Qj6MC6f7Tp/W9qhB1a+feYJ9/qVDg2Lk z4MrBTqvAonrR+H87qN8R4CewxjQjckyXYlZpBrlzvbfHNJ8kkSZUwGZe8y6MOjAx1kdq1HVQ TAxBjEqTdEc8hgy0y933fBh3EqnY05gZ+2Ea47Ey5PREVsR0j4YAAgupjRpAU/Hc7m7CYdQ67 ipoKx77usfnfO7mdMzcMUfditmRroLIYMzTfHJjar2xVKF9KVYnlhPN2X7otMg4iSaFuLeHXN claBsgu6Ffleh02LHhnen23F3xLdJKb/5XV/UQAvOrY3XJCzCnrVfnYe9FnfYk9tbTsbnAo2Y ccd12HUIjP3Ra6cJ8fDrzS3Q5r4o53j0Tur+mrbEs+7Kg5vpJ6540n5e/WVyv71jGsbjmon2V 6/t4t9VZTv+4x9STV97guvzoDhntJsZtqjxwXHFOXg8bVknsyqeTsSQu6YjZe1/wkjtXXFXV+ e5l6cAw2xgbegY4NVRA0ZQGu4VRr6cMAI4tNsg== X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180309_053306_901437_62A085C8 X-CRM114-Status: GOOD ( 19.02 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stefan Wahren , devicetree@vger.kernel.org, Florian Fainelli , Scott Branden , Ray Jui , bcm-kernel-feedback-list@broadcom.com, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This patch brings read-only support for the Raspberry Pi Customer OTP. The driver accesses the OTP via the mailbox property interface provided by the VPU firmware. Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt --- drivers/nvmem/Kconfig | 10 +++ drivers/nvmem/Makefile | 2 + drivers/nvmem/raspberrypi-otp.c | 138 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 drivers/nvmem/raspberrypi-otp.c diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index ff505af..76b8af3 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -175,4 +175,14 @@ config NVMEM_SNVS_LPGPR This driver can also be built as a module. If so, the module will be called nvmem-snvs-lpgpr. +config NVMEM_RASPBERRYPI_OTP + tristate "Raspberry Pi Customer OTP support" + depends on (ARCH_BCM2835 && RASPBERRYPI_FIRMWARE) || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) + depends on RASPBERRYPI_FIRMWARE + help + This is a driver for access to the Customer OTP on the Raspberry Pi. + + This driver can also be built as a module. If so, the module + will be called nvmem-raspberrypi-otp. + endif diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index e54dcfa..3b53b0b 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -37,3 +37,5 @@ obj-$(CONFIG_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o nvmem_meson_mx_efuse-y := meson-mx-efuse.o obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o nvmem_snvs_lpgpr-y := snvs_lpgpr.o +obj-$(CONFIG_NVMEM_RASPBERRYPI_OTP) += nvmem-raspberrypi-otp.o +nvmem-raspberrypi-otp-y := raspberrypi-otp.o diff --git a/drivers/nvmem/raspberrypi-otp.c b/drivers/nvmem/raspberrypi-otp.c new file mode 100644 index 0000000..e925435 --- /dev/null +++ b/drivers/nvmem/raspberrypi-otp.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Raspberry Pi Customer OTP driver + * + * Copyright (C) 2018 Stefan Wahren + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define CUSTOMER_CELLS 8 + +struct rpi_otp { + struct nvmem_device *nvmem; + struct rpi_firmware *fw; +}; + +/* + * Packet definition used by RPI_FIRMWARE_GET_CUSTOMER_OTP + */ +struct rpi_customer_otp_packet { + u32 index; + u32 length; + u32 cells[CUSTOMER_CELLS]; +}; + +static int rpi_otp_read(void *context, unsigned int offset, void *val, + size_t bytes) +{ + struct rpi_customer_otp_packet packet; + struct rpi_otp *otp = context; + u32 *buf = val; + int ret; + + packet.index = 0; + packet.length = CUSTOMER_CELLS; + memset(packet.cells, 0xff, sizeof(packet.cells)); + + ret = rpi_firmware_property(otp->fw, RPI_FIRMWARE_GET_CUSTOMER_OTP, + &packet, sizeof(packet)); + + if (ret) + return ret; + + /* Request rejected by firmware */ + if (packet.index) + return -EIO; + + while (bytes) { + if ((offset / 4) < sizeof(packet.cells)) + *buf = packet.cells[offset / 4]; + else + *buf = 0; + + buf++; + bytes -= 4; + offset += 4; + } + + return 0; +} + +static struct nvmem_config ocotp_config = { + .name = "rpi-customer-otp", + .size = CUSTOMER_CELLS * 4, + .stride = 4, + .word_size = 4, + .reg_read = rpi_otp_read, +}; + +static int rpi_otp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct of_device_id *match; + struct device_node *fw_node; + struct rpi_otp *otp; + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match) + return -EINVAL; + + otp = devm_kzalloc(dev, sizeof(*otp), GFP_KERNEL); + if (!otp) + return -ENOMEM; + + fw_node = of_get_parent(dev->of_node); + if (!fw_node) { + dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + + otp->fw = rpi_firmware_get(fw_node); + of_node_put(fw_node); + if (!otp->fw) + return -EPROBE_DEFER; + + ocotp_config.priv = otp; + ocotp_config.dev = dev; + otp->nvmem = nvmem_register(&ocotp_config); + if (IS_ERR(otp->nvmem)) + return PTR_ERR(otp->nvmem); + + platform_set_drvdata(pdev, otp); + + return 0; +} + +static int rpi_otp_remove(struct platform_device *pdev) +{ + struct rpi_otp *otp = platform_get_drvdata(pdev); + + return nvmem_unregister(otp->nvmem); +} + +static const struct of_device_id rpi_otp_of_match[] = { + { .compatible = "raspberrypi,bcm2835-customer-otp", }, + { /* sentinel */}, +}; +MODULE_DEVICE_TABLE(of, rpi_otp_of_match); + +static struct platform_driver rpi_otp_driver = { + .probe = rpi_otp_probe, + .remove = rpi_otp_remove, + .driver = { + .name = "rpi-customer-otp", + .of_match_table = rpi_otp_of_match, + }, +}; +module_platform_driver(rpi_otp_driver); + +MODULE_AUTHOR("Stefan Wahren "); +MODULE_DESCRIPTION("Raspberry Pi Customer OTP driver"); +MODULE_LICENSE("GPL v2");