Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.0/patches/2175685/?format=api
{ "id": 2175685, "url": "http://patchwork.ozlabs.org/api/1.0/patches/2175685/?format=api", "project": { "id": 3, "url": "http://patchwork.ozlabs.org/api/1.0/projects/3/?format=api", "name": "Linux MTD development", "link_name": "linux-mtd", "list_id": "linux-mtd.lists.infradead.org", "list_email": "linux-mtd@lists.infradead.org", "web_url": null, "scm_url": null, "webscm_url": null }, "msgid": "<A41171D3EA8B583B+20251218180205.930961-3-bigfoot@radxa.com>", "date": "2025-12-18T18:02:05", "name": "[2/2] mtd: devices: Add Qualcomm SCM storage driver", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "66d8a702a832f551409dab72a2b161e1241f22fd", "submitter": { "id": 92293, "url": "http://patchwork.ozlabs.org/api/1.0/people/92293/?format=api", "name": "Junhao Xie", "email": "bigfoot@radxa.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-mtd/patch/A41171D3EA8B583B+20251218180205.930961-3-bigfoot@radxa.com/mbox/", "series": [ { "id": 485894, "url": "http://patchwork.ozlabs.org/api/1.0/series/485894/?format=api", "date": "2025-12-18T18:02:03", "name": "mtd: devices: Qualcomm SCM storage support", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/485894/mbox/" } ], "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2175685/checks/", "tags": {}, "headers": { "Return-Path": "\n <linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=GzQu9QDW;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dXJTQ3JKNz1y3l\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 19 Dec 2025 05:04:23 +1100 (AEDT)", "from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1vWIME-00000008yHF-1ksv;\n\tThu, 18 Dec 2025 18:04:10 +0000", "from bg1.exmail.qq.com ([114.132.64.16])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1vWIMA-00000008yFn-4C3T\n\tfor linux-mtd@lists.infradead.org;\n\tThu, 18 Dec 2025 18:04:09 +0000", "from bigfoot-server-arm-node1.classf ( [183.250.239.212])\n\tby bizesmtp.qq.com (ESMTP) with\n\tid ; Fri, 19 Dec 2025 02:02:38 +0800 (CST)" ], "DKIM-Signature": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=kwFGAjxhZ9fTb1mrYv+mLlec7KcmgzDm5eusA3aM0Tg=; b=GzQu9QDWHKikaY\n\tT3JSPaDyXP5XfDfQbNRZabyKdSKDoAL+wkDxR3LCQIKEPNr+EM6Vu62fHoF92Nmfeaga88wIYhb0k\n\tbpR57jZtHx+93Lr2aWKpW1fnFD+VVADwJEwGqImXWyYeWSFzatXK4rIIb1ReiF0UlYafg9Ahs44Xi\n\tcRma5zGzBU8l359/v64nTHcsqee5XSS5tmEKREtkGDiPTqAAwaLOox1vo1zDy2TdTs18x3ZndKukv\n\tf6xe3kZTCL4IMvqJSOOlp9n/RKUW4bNsKeFko8inTlnDGfmsnm1d8lc3XGm+UdTffkhpToKdbOYiE\n\tTP4ubzVr8mhOjs7HeHmA==;", "X-QQ-mid": "esmtpgz12t1766080959t18399a9e", "X-QQ-Originating-IP": "HRY41DCVJM6ztJQhG5rRVPrgnrnvSTWL8ryX4p9C0vg=", "X-QQ-SSF": "0000000000000000000000000000000", "X-QQ-GoodBg": "0", "X-BIZMAIL-ID": "10201982189096493261", "EX-QQ-RecipientCnt": "16", "From": "Junhao Xie <bigfoot@radxa.com>", "To": "Bjorn Andersson <andersson@kernel.org>,\n\tKonrad Dybcio <konradybcio@kernel.org>", "Cc": "Junhao Xie <bigfoot@radxa.com>,\n\tXilin Wu <sophon@radxa.com>,\n\tMiquel Raynal <miquel.raynal@bootlin.com>,\n\tRichard Weinberger <richard@nod.at>,\n\tVignesh Raghavendra <vigneshr@ti.com>,\n\tRodrigo Vivi <rodrigo.vivi@intel.com>,\n\tTomas Winkler <tomasw@gmail.com>,\n\tRaag Jadav <raag.jadav@intel.com>,\n\tKrzysztof Kozlowski <krzk@kernel.org>,\n\tGeert Uytterhoeven <geert+renesas@glider.be>,\n\tAlexander Usyskin <alexander.usyskin@intel.com>,\n\tlinux-kernel@vger.kernel.org,\n\tlinux-arm-msm@vger.kernel.org,\n\tlinux-mtd@lists.infradead.org", "Subject": "[PATCH 2/2] mtd: devices: Add Qualcomm SCM storage driver", "Date": "Fri, 19 Dec 2025 02:02:05 +0800", "Message-ID": "<A41171D3EA8B583B+20251218180205.930961-3-bigfoot@radxa.com>", "X-Mailer": "git-send-email 2.51.2", "In-Reply-To": "<20251218180205.930961-1-bigfoot@radxa.com>", "References": "<20251218180205.930961-1-bigfoot@radxa.com>", "MIME-Version": "1.0", "X-QQ-SENDSIZE": "520", "Feedback-ID": "esmtpgz:radxa.com:qybglogicsvrsz:qybglogicsvrsz4b-0", "X-QQ-XMAILINFO": "N2dNga98lfCamzpaZeQsg+F7CAJB01w0FU8Y/gCzYXOtbbip99Gc5rZY\n\tzEU44CRI73Th6H6iS/q3u8Aqd1aOyLTCpgJYq+KTcEcNrvuijXOw3Rfxe2ztzOqoHbTSoza\n\t7h+7ZVvRJ8PyvaluhD5IrtouZOzZbSmZIt7FIR6VWX6YLK3/T7hIANq19usnoQPB4ZHfkRq\n\tVXlJf+Jb6jL5cA8Mbok8/7t4607rQrAAw9/WqU3MezhSzNKnPVI6IW9746XUpW7HEQaWItE\n\tjkdTtxTuoqAHNc8M9luRS9cHGUy4HfLkYxbj/Ze9ClM/JxKSBSFopCN6Hrj4OLOJ5U94ote\n\tGetyjVX+pWeeaUpF1aJ0UGD/myQ3l+4gGM7qVD45s15AM4xAD4RfdL7RBypcWXVHSZEwXL8\n\tQDvFXHhALVmJTxoI19d18e7MRA/VWLcm+zVI6Bx8A2FH493jGUV0W1/fN6yi2GKDupjKQ3t\n\tRZmOjCrm9H7R0Mqr0KYf8UF0DXhzRaAK53afL9JNbepGgWrPbmTmo4vZgez3dimKctl4YOR\n\tCdEyVjm48QgFY3l6EmRbEts+3R2GE80nxEnXvWoXPVE1vns3Sb9xihmQ/K+e5qHFDccfmhd\n\tseKmpxHtneKLn5SnsKGsfIXpNJIbp+kfU/VX99Tu/nCRoKnkOwPzDjdTn9QhvKbLVAv6CbU\n\tU1OvAh+Wd9DWBlKEFTDK1N3mBC7oVDEEytS16ilkFS4zKcoqbedeu/8YInXJk33xy82EIlj\n\tAHiWZ8I5Gb/UGCdgu8GCDWp2E+xEYE7xMzybAKQ7n+HFcunG1PPxTghxk8vlybigf7tbzN9\n\tTJRIucRXC3Ws5itdSUFT2JiORUhy0gJNx1uphPt8jVgk+rExffXZZGwj69MysiTw3jUiuVY\n\tD+dRNC5BiiZw9zIQjxqS5hg0WhrmVGiGDfnHsg41GSdEiXa8pITJqOBq1RY/nI56OMSD+2s\n\tl0MpyqDby1przAQ3oeQjE4J50RE0OGtHPEvUkQWzkRye9Lr21iFmv3jpYfAM0STPQ2xGx7/\n\t4HIPGJR7ylXVXXzCjAlNAMCDe3PHB0r1NkjRa5jV0bZfWyiV+j", "X-QQ-XMRINFO": "OWPUhxQsoeAVDbp3OJHYyFg=", "X-QQ-RECHKSPAM": "0", "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ", "X-CRM114-CacheID": "sfid-20251218_100408_085259_F101C5B0 ", "X-CRM114-Status": "GOOD ( 25.92 )", "X-Spam-Score": "-1.9 (-)", "X-Spam-Report": "Spam detection software,\n running on the system \"bombadil.infradead.org\",\n has NOT identified this incoming email as spam. The original\n message has been attached to this so you can view it or label\n similar future email. If you have any questions, see\n the administrator of that system for details.\n Content preview: Add MTD driver for accessing storage devices managed by\n Qualcomm's\n TrustZone firmware. On some platforms,\n BIOS/firmware storage (typically SPI\n NOR flash) is not directly accessible from the non-secure [...]\n Content analysis details: (-1.9 points, 5.0 required)\n pts rule name description\n ---- ----------------------\n --------------------------------------------------\n -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no\n trust\n [114.132.64.16 listed in list.dnswl.org]\n -0.0 SPF_PASS SPF: sender matches SPF record\n 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record\n -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1%\n [score: 0.0000]\n 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The\n query to Validity was blocked. See\n https://knowledge.validity.com/hc/en-us/articles/20961730681243\n for more information.\n [114.132.64.16 listed in\n sa-trusted.bondedsender.org]\n 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n Validity was blocked. See\n https://knowledge.validity.com/hc/en-us/articles/20961730681243\n for more information.\n [114.132.64.16 listed in sa-accredit.habeas.com]\n 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n Validity was blocked. See\n https://knowledge.validity.com/hc/en-us/articles/20961730681243\n for more information.\n [114.132.64.16 listed in\n bl.score.senderscore.com]", "X-BeenThere": "linux-mtd@lists.infradead.org", "X-Mailman-Version": "2.1.34", "Precedence": "list", "List-Id": "Linux MTD discussion mailing list <linux-mtd.lists.infradead.org>", "List-Unsubscribe": "<http://lists.infradead.org/mailman/options/linux-mtd>,\n <mailto:linux-mtd-request@lists.infradead.org?subject=unsubscribe>", "List-Archive": "<http://lists.infradead.org/pipermail/linux-mtd/>", "List-Post": "<mailto:linux-mtd@lists.infradead.org>", "List-Help": "<mailto:linux-mtd-request@lists.infradead.org?subject=help>", "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/linux-mtd>,\n <mailto:linux-mtd-request@lists.infradead.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Sender": "\"linux-mtd\" <linux-mtd-bounces@lists.infradead.org>", "Errors-To": "linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org" }, "content": "Add MTD driver for accessing storage devices managed by Qualcomm's\nTrustZone firmware. On some platforms, BIOS/firmware storage (typically\nSPI NOR flash) is not directly accessible from the non-secure world and\nall operations must go through SCM (Secure Channel Manager) calls.\n\nSigned-off-by: Junhao Xie <bigfoot@radxa.com>\nTested-by: Xilin Wu <sophon@radxa.com>\n---\n drivers/mtd/devices/Kconfig | 17 ++\n drivers/mtd/devices/Makefile | 1 +\n drivers/mtd/devices/qcom_scm_storage.c | 256 +++++++++++++++++++++++++\n 3 files changed, 274 insertions(+)\n create mode 100644 drivers/mtd/devices/qcom_scm_storage.c", "diff": "diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig\nindex e518dfeee6542..4f73e89a11947 100644\n--- a/drivers/mtd/devices/Kconfig\n+++ b/drivers/mtd/devices/Kconfig\n@@ -194,6 +194,23 @@ config MTD_INTEL_DG\n \t To compile this driver as a module, choose M here: the module\n \t will be called mtd-intel-dg.\n \n+config MTD_QCOM_SCM_STORAGE\n+\ttristate \"Qualcomm TrustZone protected storage MTD driver\"\n+\tdepends on MTD\n+\tdepends on QCOM_SCM || COMPILE_TEST\n+\thelp\n+\t This provides an MTD device to access storage (typically SPI NOR\n+\t flash) that is managed by Qualcomm's TrustZone firmware. On some\n+\t platforms, the firmware storage is not directly accessible from\n+\t the non-secure world and all operations must go through secure\n+\t monitor calls.\n+\n+\t This driver is only functional on devices where the bootloader\n+\t has configured TrustZone to expose the storage interface.\n+\n+\t To compile this driver as a module, choose M here: the module\n+\t will be called qcom_scm_storage.\n+\n comment \"Disk-On-Chip Device Drivers\"\n \n config MTD_DOCG3\ndiff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile\nindex 9fe4ce9cffde9..d71d07f811fa2 100644\n--- a/drivers/mtd/devices/Makefile\n+++ b/drivers/mtd/devices/Makefile\n@@ -19,6 +19,7 @@ obj-$(CONFIG_MTD_BCM47XXSFLASH)\t+= bcm47xxsflash.o\n obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o\n obj-$(CONFIG_MTD_POWERNV_FLASH)\t+= powernv_flash.o\n obj-$(CONFIG_MTD_INTEL_DG)\t+= mtd_intel_dg.o\n+obj-$(CONFIG_MTD_QCOM_SCM_STORAGE)\t+= qcom_scm_storage.o\n \n \n CFLAGS_docg3.o\t\t\t+= -I$(src)\ndiff --git a/drivers/mtd/devices/qcom_scm_storage.c b/drivers/mtd/devices/qcom_scm_storage.c\nnew file mode 100644\nindex 0000000000000..bf5a9f423ed7c\n--- /dev/null\n+++ b/drivers/mtd/devices/qcom_scm_storage.c\n@@ -0,0 +1,256 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * Qualcomm TrustZone SCM Storage Flash driver\n+ *\n+ * Copyright (c) 2025 Junhao Xie <bigfoot@radxa.com>\n+ */\n+\n+#include <linux/dma-mapping.h>\n+#include <linux/module.h>\n+#include <linux/mtd/mtd.h>\n+#include <linux/platform_device.h>\n+#include <linux/slab.h>\n+\n+#include <linux/firmware/qcom/qcom_scm.h>\n+\n+/*\n+ * This driver provides MTD access to storage devices managed by Qualcomm's\n+ * TrustZone firmware. The storage (typically SPI NOR flash) is not directly\n+ * accessible from the non-secure world and all operations must go through\n+ * SCM (Secure Channel Manager) calls.\n+ *\n+ * A bounce buffer is required because the interface requires\n+ * block-aligned addresses and sizes\n+ */\n+struct qcom_scm_storage {\n+\tstruct device *dev;\n+\tstruct mutex lock;\t/* Protects SCM storage operations */\n+\tstruct mtd_info mtd;\n+\tstruct qcom_scm_storage_info info;\n+\tsize_t buffer_size;\n+\tu8 *buffer;\n+};\n+\n+static int qcom_scm_storage_erase(struct mtd_info *mtd,\n+\t\t\t\t struct erase_info *instr)\n+{\n+\tstruct qcom_scm_storage *host =\n+\t\tcontainer_of(mtd, struct qcom_scm_storage, mtd);\n+\n+\tif (instr->addr % host->info.block_size ||\n+\t instr->len % host->info.block_size)\n+\t\treturn -EINVAL;\n+\n+\tguard(mutex)(&host->lock);\n+\n+\treturn qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR,\n+\t\t\t\t\t QCOM_SCM_STORAGE_ERASE,\n+\t\t\t\t\t instr->addr / host->info.block_size,\n+\t\t\t\t\t 0, instr->len);\n+}\n+\n+static int qcom_scm_storage_read(struct mtd_info *mtd,\n+\t\t\t\t loff_t from, size_t len,\n+\t\t\t\t size_t *retlen, u_char *buf)\n+{\n+\tstruct qcom_scm_storage *host =\n+\t\tcontainer_of(mtd, struct qcom_scm_storage, mtd);\n+\tsize_t block_size = host->info.block_size;\n+\tloff_t block_start, block_off, lba;\n+\tsize_t chunk, to_read;\n+\tint ret = 0;\n+\n+\tif (retlen)\n+\t\t*retlen = 0;\n+\n+\tif (from + len > mtd->size)\n+\t\treturn -EINVAL;\n+\n+\tif (len == 0)\n+\t\treturn 0;\n+\n+\tguard(mutex)(&host->lock);\n+\n+\twhile (len > 0) {\n+\t\tblock_start = round_down(from, block_size);\n+\t\tblock_off = from - block_start;\n+\t\tlba = block_start / block_size;\n+\n+\t\tif (block_off || len < block_size) {\n+\t\t\tchunk = min_t(size_t, block_size - block_off, len);\n+\t\t\tto_read = block_size;\n+\t\t} else {\n+\t\t\tchunk = round_down(len, block_size);\n+\t\t\tchunk = min_t(size_t, chunk, host->buffer_size);\n+\t\t\tto_read = chunk;\n+\t\t}\n+\n+\t\tret = qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR,\n+\t\t\t\t\t\tQCOM_SCM_STORAGE_READ,\n+\t\t\t\t\t\tlba, host->buffer,\n+\t\t\t\t\t\tto_read);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tmemcpy(buf, host->buffer + block_off, chunk);\n+\n+\t\tbuf += chunk;\n+\t\tfrom += chunk;\n+\t\tlen -= chunk;\n+\t\tif (retlen)\n+\t\t\t*retlen += chunk;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int qcom_scm_storage_write(struct mtd_info *mtd,\n+\t\t\t\t loff_t to, size_t len,\n+\t\t\t\t size_t *retlen, const u_char *buf)\n+{\n+\tstruct qcom_scm_storage *host =\n+\t\tcontainer_of(mtd, struct qcom_scm_storage, mtd);\n+\tsize_t block_size = host->info.block_size;\n+\tloff_t block_start, block_off, lba;\n+\tsize_t chunk, to_write;\n+\tint ret = 0;\n+\n+\tif (retlen)\n+\t\t*retlen = 0;\n+\n+\tif (to + len > mtd->size)\n+\t\treturn -EINVAL;\n+\n+\tif (len == 0)\n+\t\treturn 0;\n+\n+\tguard(mutex)(&host->lock);\n+\n+\twhile (len > 0) {\n+\t\tblock_start = round_down(to, block_size);\n+\t\tblock_off = to - block_start;\n+\t\tlba = block_start / block_size;\n+\n+\t\tif (block_off || len < block_size) {\n+\t\t\tchunk = min_t(size_t, block_size - block_off, len);\n+\t\t\tto_write = block_size;\n+\n+\t\t\tret = qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR,\n+\t\t\t\t\t\t\tQCOM_SCM_STORAGE_READ,\n+\t\t\t\t\t\t\tlba, host->buffer,\n+\t\t\t\t\t\t\tblock_size);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t} else {\n+\t\t\tchunk = round_down(len, block_size);\n+\t\t\tchunk = min_t(size_t, chunk, host->buffer_size);\n+\t\t\tto_write = chunk;\n+\t\t}\n+\n+\t\tmemcpy(host->buffer + block_off, buf, chunk);\n+\n+\t\tret = qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR,\n+\t\t\t\t\t\tQCOM_SCM_STORAGE_WRITE,\n+\t\t\t\t\t\tlba, host->buffer,\n+\t\t\t\t\t\tto_write);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tbuf += chunk;\n+\t\tto += chunk;\n+\t\tlen -= chunk;\n+\t\tif (retlen)\n+\t\t\t*retlen += chunk;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int qcom_scm_storage_probe(struct platform_device *pdev)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tstruct qcom_scm_storage *host;\n+\tint ret;\n+\n+\thost = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);\n+\tif (!host)\n+\t\treturn -ENOMEM;\n+\n+\tplatform_set_drvdata(pdev, host);\n+\thost->dev = dev;\n+\n+\tret = devm_mutex_init(dev, &host->lock);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\thost->buffer_size = SZ_256K;\n+\thost->buffer = devm_kzalloc(dev, host->buffer_size, GFP_KERNEL);\n+\tif (!host->buffer)\n+\t\treturn -ENOMEM;\n+\n+\tret = qcom_scm_storage_send_cmd(QCOM_SCM_STORAGE_SPINOR,\n+\t\t\t\t\tQCOM_SCM_STORAGE_GET_INFO,\n+\t\t\t\t\t0, &host->info,\n+\t\t\t\t\tsizeof(host->info));\n+\tif (ret < 0)\n+\t\treturn dev_err_probe(dev, ret,\n+\t\t\t\t \"failed to get storage info\\n\");\n+\n+\tif (!host->info.block_size || !host->info.total_blocks)\n+\t\treturn dev_err_probe(dev, -EINVAL,\n+\t\t\t\t \"invalid storage geometry\\n\");\n+\n+\tif (host->info.block_size > host->buffer_size)\n+\t\treturn dev_err_probe(dev, -EINVAL,\n+\t\t\t\t \"block size %u exceeds buffer size\\n\",\n+\t\t\t\t host->info.block_size);\n+\n+\thost->mtd.name = dev_name(dev);\n+\thost->mtd.owner = THIS_MODULE;\n+\thost->mtd.dev.parent = dev;\n+\thost->mtd.size = host->info.total_blocks * host->info.block_size;\n+\thost->mtd.erasesize = host->info.block_size;\n+\thost->mtd.writesize = host->info.block_size;\n+\thost->mtd.writebufsize = host->info.block_size;\n+\thost->mtd.type = MTD_NORFLASH;\n+\thost->mtd.flags = MTD_WRITEABLE;\n+\thost->mtd._erase = qcom_scm_storage_erase;\n+\thost->mtd._read = qcom_scm_storage_read;\n+\thost->mtd._write = qcom_scm_storage_write;\n+\n+\tret = mtd_device_register(&host->mtd, NULL, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(dev, \"scm storage 0x%llx registered with size %llu bytes\\n\",\n+\t\t host->info.serial_num, host->mtd.size);\n+\n+\treturn 0;\n+}\n+\n+static void qcom_scm_storage_remove(struct platform_device *pdev)\n+{\n+\tstruct qcom_scm_storage *host = platform_get_drvdata(pdev);\n+\n+\tWARN_ON(mtd_device_unregister(&host->mtd));\n+}\n+\n+static const struct platform_device_id qcom_scm_storage_ids[] = {\n+\t{ \"qcom_scm_storage\", 0 },\n+\t{}\n+};\n+MODULE_DEVICE_TABLE(platform, qcom_scm_storage_ids);\n+\n+static struct platform_driver qcom_scm_storage_driver = {\n+\t.probe\t= qcom_scm_storage_probe,\n+\t.remove\t= qcom_scm_storage_remove,\n+\t.driver = {\n+\t\t.name\t= \"qcom_scm_storage\",\n+\t},\n+\t.id_table = qcom_scm_storage_ids,\n+};\n+module_platform_driver(qcom_scm_storage_driver);\n+\n+MODULE_AUTHOR(\"Junhao Xie <bigfoot@radxa.com>\");\n+MODULE_DESCRIPTION(\"Qualcomm TrustZone SCM Storage Flash driver\");\n+MODULE_LICENSE(\"GPL\");\n", "prefixes": [ "2/2" ] }