From patchwork Sat Jun 11 20:46:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 581158 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp712941max; Sat, 11 Jun 2022 13:47:30 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxO5mMZ4jXevR+B4Sb2FjbGgg0GsKTtXRCMUD0KAqOymYBQ48PMFxXxw8dCv+C2HEUrOS2r X-Received: by 2002:a05:6638:1b0e:b0:332:adf:5db8 with SMTP id cb14-20020a0566381b0e00b003320adf5db8mr6985127jab.200.1654980450398; Sat, 11 Jun 2022 13:47:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654980450; cv=none; d=google.com; s=arc-20160816; b=FCfhq2uZ4glilaJT1G0DsB+570wy9hgx9KeD5XhgyBr79VnA8ZqPvXmbmrQ7L+x83Z zhFzzm5/SevWu5EC5odCtidQE7K0DAw3iGlvgL8xl1FBeQzhqFN0XO/fFKvwqlNHMNVZ VuO6dB1awXtPPvMwtp430xySPvT73FMeJhPehjxdMnTGQ9A9mOnsw24MAE9YyCDpCCbC V382+9gBf0Tr0GaORmsSVci1NkTTnf9zZUELbL6PL053GnJ3Oy2yrd4OLI21zRQ1zYSu xwJ2t5Uo/o8Y6cVRj6BHgiaTfEVWvvJ18sLCW2xci8Eg/0uSfhcFSPYzAxjaRfHPcULk HLWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature; bh=KVeFonmBJ+8ElS2S3DJZc1evp03zBLOPTs54ViZe9rI=; b=ztBwfIk0B17nGQ10TWrdKj7LXCvcShDgoeMSAt/uulScdwr2//v26z2e9GMRTxvuQQ UIuDpZqCh3UIpvqmwKNdJerKiqQlel+a9Y8eVbhhMPV2d3Re/WAGxfHb/H6xcGvQ040o J3ZM4CNburP5iIr1qzeuCuDsM7jNBuiUc6UHBoSghC0AyBJWWCRwKh9fMlORJcuaIoa1 pVHr/xxgaN9IM/gGguvTNLxKeAOGLhuhawy2r56ez3QHogxPt+NPBpZ682QpN1h+P6aE REMpK+oVWe5UQRuprRzmi/th47mSRetm0ztxRki7/zinPB2HjPYvF2JeqSPQ0exsnV3n /AtQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=VNhZ4ylx; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id j1-20020a05663822c100b0032af6245acesi4123254jat.53.2022.06.11.13.47.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jun 2022 13:47:30 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=VNhZ4ylx; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 572798440D; Sat, 11 Jun 2022 22:47:19 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="VNhZ4ylx"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 66C7D84418; Sat, 11 Jun 2022 22:47:17 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ej1-x629.google.com (mail-ej1-x629.google.com [IPv6:2a00:1450:4864:20::629]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 354458440A for ; Sat, 11 Jun 2022 22:47:10 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=zajec5@gmail.com Received: by mail-ej1-x629.google.com with SMTP id n10so4154739ejk.5 for ; Sat, 11 Jun 2022 13:47:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=KVeFonmBJ+8ElS2S3DJZc1evp03zBLOPTs54ViZe9rI=; b=VNhZ4ylxFT+9aZ3DF1PBnm574in+3ZH0iAhReGS6WJYBSQ6cGlPLsZar5dVJTbxnT6 I0u6TWviVpZbZecoivK+BeYpDGn972LHbC3AIv+343GxvBDm6BYzwhplxMtQfwLvOlqo Lm78Rh+LRB/pt1MZHzsAYrrkWzd3G+DF696jYUibKGieF/4IPKLjSZncF+Dh64rxNIx4 T1wvW9gvRJJpjAvmLqrdjYjZN9Hpi4+pKjH8anxdOsW37eCYYIp4kls/yhLI/BgwMi0U 8Ydxmd6LAvWNzd7x6VwwcpzfXEikmFSU6fm5nzmi04+9lHk0pc7gBP6YlZOtC9KhRLkW dRUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=KVeFonmBJ+8ElS2S3DJZc1evp03zBLOPTs54ViZe9rI=; b=B5aqavuEJ76iR4nwAwRbITnSyMWMhS8KfjjJMrth083bWRAJm8TlgHErHPLmdSJtgk pOLy0oD7jj35IcEitP3PzRvOL50mAac4AxvkUK94f3BWo6szz0stocE0lzfIGLvBSo5O 53w/JT/qVy7rZukbsfhM9GPkhyTcNM/1UXkTo4VHfx8aIQIVwF/LHPqPU9AcjeBq+K5G BYcq0GIEE4bPSFK0u2KeTqXFo9lhbubMGiDQHdO23UTr/EJlTMWpSZO82QElR3Ye25Wd U5QZ8nN+KW12E+pMo7LmpELHPkAwh0E7xQFiuun7f2WLY0Tj+G9jNrngSxGThQEA5hIO yT/A== X-Gm-Message-State: AOAM531bRGVForvJRLLl81l40MUJyscdCHySYEHax/i3Qzum23gs1kep CUihcuib/V81P2iPBaOjdB4= X-Received: by 2002:a17:906:9244:b0:70c:f626:944d with SMTP id c4-20020a170906924400b0070cf626944dmr41572371ejx.496.1654980429683; Sat, 11 Jun 2022 13:47:09 -0700 (PDT) Received: from localhost.lan (ip-194-187-74-233.konfederacka.maverick.com.pl. [194.187.74.233]) by smtp.gmail.com with ESMTPSA id 22-20020a170906301600b006f52dbc192bsm1490672ejz.37.2022.06.11.13.47.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jun 2022 13:47:09 -0700 (PDT) From: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= To: Srinivas Kandagatla , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra Cc: Tom Rini , Ahmad Fatoum , linux-arm-kernel@lists.infradead.org, u-boot@lists.denx.de, devicetree@vger.kernel.org, linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= Subject: [PATCH V3 1/2] mtd: allow getting MTD device associated with a specific DT node Date: Sat, 11 Jun 2022 22:46:50 +0200 Message-Id: <20220611204651.19947-1-zajec5@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean From: Rafał Miłecki MTD subsystem API allows interacting with MTD devices (e.g. reading, writing, handling bad blocks). So far a random driver could get MTD device only by its name (get_mtd_device_nm()). This change allows getting them also by a DT node. This API is required for drivers handling DT defined MTD partitions in a specific way (e.g. U-Boot (sub)partition with environment variables). Signed-off-by: Rafał Miłecki Acked-by: Miquel Raynal --- V3: First introduction of of_get_mtd_device_by_node() mtd maintainers: please let know how would you like this patch processed. Would that be OK for you to Review/Ack it and let it go through NVMEM tree? --- drivers/mtd/mtdcore.c | 28 ++++++++++++++++++++++++++++ include/linux/mtd/mtd.h | 1 + 2 files changed, 29 insertions(+) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 9eb0680db312..7dc214271c85 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1154,6 +1154,34 @@ int __get_mtd_device(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(__get_mtd_device); +/** + * of_get_mtd_device_by_node - obtain an MTD device associated with a given node + * + * @np: device tree node + */ +struct mtd_info *of_get_mtd_device_by_node(struct device_node *np) +{ + struct mtd_info *mtd = NULL; + struct mtd_info *tmp; + int err; + + mutex_lock(&mtd_table_mutex); + + err = -ENODEV; + mtd_for_each_device(tmp) { + if (mtd_get_of_node(tmp) == np) { + mtd = tmp; + err = __get_mtd_device(mtd); + break; + } + } + + mutex_unlock(&mtd_table_mutex); + + return err ? ERR_PTR(err) : mtd; +} +EXPORT_SYMBOL_GPL(of_get_mtd_device_by_node); + /** * get_mtd_device_nm - obtain a validated handle for an MTD device by * device name diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 955aee14b0f7..6fc841ceef31 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -677,6 +677,7 @@ extern int mtd_device_unregister(struct mtd_info *master); extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); extern int __get_mtd_device(struct mtd_info *mtd); extern void __put_mtd_device(struct mtd_info *mtd); +extern struct mtd_info *of_get_mtd_device_by_node(struct device_node *np); extern struct mtd_info *get_mtd_device_nm(const char *name); extern void put_mtd_device(struct mtd_info *mtd); From patchwork Sat Jun 11 20:46:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 581157 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp712846max; Sat, 11 Jun 2022 13:47:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy6qYQfiq5q45RJ//wkY0TfKMNqLM+3/ST2pT7QNzCQEXZgraT/sLpoa/cn/F4pS9VFhbzL X-Received: by 2002:a05:6e02:158a:b0:2d5:12f0:4dce with SMTP id m10-20020a056e02158a00b002d512f04dcemr21326207ilu.159.1654980439899; Sat, 11 Jun 2022 13:47:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654980439; cv=none; d=google.com; s=arc-20160816; b=nwZSXgUG+0wdK9dDf4Xqo8XWS4wk9PkE1Ytezc8euUpAz19QLkVAElfx/jFY8VEsvW ZG4gjfBjCw0fe8JwZYrO2Bid/cSHI3VlH7CIvQtl6jRTCmKLavNLEL67M5sb37vRjokS iREagDxUL4f8BMMf8EMegeQ0lPZcE2/cXSwwrZQp7QPcSmyIGH2cRuyNq4sojVnWS6rl w8Fy7mLbJmMvey/Z4U3jl+wpEtNYXLozwwvGCwx4AoQop79elIM07CYLlsXFOt3Js+ZO UhZIxcvUe6AUvEd+yJF7zwL9qAMxZeNWM/IaU7rBcmOp6iJc5xVIF9mZ0pcVbc0DAP8l pUJA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=pPGokfyfSUs/WTSM4zIFDX4BDdVMjvsS1wW+kXKgMVY=; b=HKJifrr7xipLLcwP5G9bhlp3X/OreIdZ5gtx6w5UsrqfhT/2gK6dUgCKcjsQ5PEeQB jCD9R4FMjkfaLvI+17fBxfDo6LvGWhIn6r/F4lzPsdpX+ZiV8wa1FE+MMYIaIKIYYjpu 7rxZ1cZIEFzHI0sO6xZUnZEIYSW9XKfgM4Odn0csDwV+k3Bzr2GV5Gp2gz0TVlSBBPiw mdHs5rLTTwbD8mMYa3baVoOrxjsh3mIpNeHLN1rc/V1S8P9ab10GlXPq3iL+hqFMG8RQ 4rCFDgBdGu+Sb/bbCrNZBYsHOPapLV04Y4HPBhHcRdrFFVYHZUobdiwVvPr/DPDgkxMu r6Cg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=fTdCyj5s; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id k6-20020a5d97c6000000b00669745dfdd4si3544754ios.8.2022.06.11.13.47.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jun 2022 13:47:19 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=fTdCyj5s; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0259884413; Sat, 11 Jun 2022 22:47:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fTdCyj5s"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C803184413; Sat, 11 Jun 2022 22:47:14 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ej1-x62e.google.com (mail-ej1-x62e.google.com [IPv6:2a00:1450:4864:20::62e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id ABF038440D for ; Sat, 11 Jun 2022 22:47:11 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=zajec5@gmail.com Received: by mail-ej1-x62e.google.com with SMTP id n10so4154798ejk.5 for ; Sat, 11 Jun 2022 13:47:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pPGokfyfSUs/WTSM4zIFDX4BDdVMjvsS1wW+kXKgMVY=; b=fTdCyj5sKkyo5gZl9XuSnBt6drXY+MIoleIJ/Qkr9ddIiQ05qtqFTyOnrapd0QZ1ac apv0FIMWMS/LZyfB47w7iih7ypugBr6cUL8HUB/ipmdLg2WS9A7uFQ1BOWG+wXKhIy+F jF9FTGNVwKqdUYYzU4YOliGeOstfXgEIvjtP5o4w4H7YVQJ55mun6qNNNBheHJ41Rulb k5PlER238rl+8V7wmcBDEG8kI9xyoYOWgynn35QlrxoCxc/5Y6yV5b1Xwj7QZ8cagMHv uJDuKJVTztQTcBcfgM+mJ1reBkosq6gAu8ZaNdYjHv4vLxuvQSm7P5UUiTFiuEHLwK7p F8Mg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pPGokfyfSUs/WTSM4zIFDX4BDdVMjvsS1wW+kXKgMVY=; b=FL/2PdtYe2/CXuHLi1f7raWzjbHo06VPx5bbBmE8cMzs4JWZREtXb6BE/M0fAvs4/G bRGssuSSwjnz3qvNcM7TWq1G1LnPQaPt9q5PX1FTdZc6oZsrSDh0IGMFGOuV6VJJk9H4 uP4yhjLB96ZnUBHyUceSz4IVN1h5KtKJZHU90vXB9oacMJwku2lydqZDBdx7FZTlvnEE H82z/vgFiyuSaBatcPlsAKGfTbhFkePhLqP0am4N+l9OampGtLakE9lS/sXywoUEfAqI qSA+uxRszl40UNxuJ+WH/bj10NREGzHp66YLVm1K9BOjUwgU0QtIx421QBJyOU+Bb0xy DqBw== X-Gm-Message-State: AOAM530B7tOMFu8ZX5lCaGBwqblQqCkl+oujUYCaU0/5dMCl4TKekuey rKn0maENoVj+6PWFem+j1Zo= X-Received: by 2002:a17:906:64d6:b0:712:1022:492b with SMTP id p22-20020a17090664d600b007121022492bmr11715611ejn.264.1654980431147; Sat, 11 Jun 2022 13:47:11 -0700 (PDT) Received: from localhost.lan (ip-194-187-74-233.konfederacka.maverick.com.pl. [194.187.74.233]) by smtp.gmail.com with ESMTPSA id 22-20020a170906301600b006f52dbc192bsm1490672ejz.37.2022.06.11.13.47.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jun 2022 13:47:10 -0700 (PDT) From: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= To: Srinivas Kandagatla , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra Cc: Tom Rini , Ahmad Fatoum , linux-arm-kernel@lists.infradead.org, u-boot@lists.denx.de, devicetree@vger.kernel.org, linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= Subject: [PATCH V3 2/2] nvmem: add driver handling U-Boot environment variables Date: Sat, 11 Jun 2022 22:46:51 +0200 Message-Id: <20220611204651.19947-2-zajec5@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220611204651.19947-1-zajec5@gmail.com> References: <20220611204651.19947-1-zajec5@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean From: Rafał Miłecki U-Boot stores its setup as environment variables. It's a list of key-value pairs stored on flash device with a custom header. This commit adds an NVMEM driver that: 1. Provides NVMEM access to environment vars binary data 2. Extracts variables as NVMEM cells Current Linux's NVMEM sysfs API allows reading whole NVMEM data block. It can be used by user-space tools for reading U-Boot env vars block without the hassle of finding its location. Parsing will still need to be re-done there. Kernel-parsed NVMEM cells can be read however by Linux drivers. This may be uesful for Ethernet drivers for reading device MAC address which is often stored as U-Boot env variable. Signed-off-by: Rafał Miłecki --- V3: Use of_get_mtd_device_by_node() (thanks Ahmad) & update description V2: Drop ARCH_BCM4908 dependency as there are plenty architectures using U-Boot bootloader. Thanks Srinivas. As noticed by Ahmad a missing NVMEM subsystem feature is user-space access to parsed NVMEM cells. That is something I started working on some time ago and I'm planning to get back to at some point, please check: [PATCH 2/2] nvmem: expose NVMEM cells in sysfs https://lore.kernel.org/lkml/20211220064730.28806-2-zajec5@gmail.com/ --- MAINTAINERS | 1 + drivers/nvmem/Kconfig | 11 ++ drivers/nvmem/Makefile | 2 + drivers/nvmem/u-boot-env.c | 231 +++++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 drivers/nvmem/u-boot-env.c diff --git a/MAINTAINERS b/MAINTAINERS index 475e28365385..43b427fa76b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20411,6 +20411,7 @@ U-BOOT ENVIRONMENT VARIABLES M: Rafał Miłecki S: Maintained F: Documentation/devicetree/bindings/nvmem/u-boot,env.yaml +F: drivers/nvmem/u-boot-env.c UACCE ACCELERATOR FRAMEWORK M: Zhangfei Gao diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index d72d879a6d34..5f1b32b953b9 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -344,4 +344,15 @@ config NVMEM_APPLE_EFUSES This driver can also be built as a module. If so, the module will be called nvmem-apple-efuses. +config NVMEM_U_BOOT_ENV + tristate "U-Boot environment variables support" + depends on OF && MTD + select CRC32 + help + U-Boot stores its setup as environment variables. This driver adds + support for verifying & exporting such data. It also exposes variables + as NVMEM cells so they can be referenced by other drivers. + + If compiled as module it will be called nvmem_u-boot-env. + endif diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index c710b64f9fe4..399f9972d45b 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -69,3 +69,5 @@ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o nvmem-apple-efuses-y := apple-efuses.o obj-$(CONFIG_MICROCHIP_OTPC) += nvmem-microchip-otpc.o nvmem-microchip-otpc-y := microchip-otpc.o +obj-$(CONFIG_NVMEM_U_BOOT_ENV) += nvmem_u-boot-env.o +nvmem_u-boot-env-y := u-boot-env.o diff --git a/drivers/nvmem/u-boot-env.c b/drivers/nvmem/u-boot-env.c new file mode 100644 index 000000000000..92c2dd11d99f --- /dev/null +++ b/drivers/nvmem/u-boot-env.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Rafał Miłecki + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum u_boot_env_format { + U_BOOT_FORMAT_SINGLE, + U_BOOT_FORMAT_REDUNDANT, +}; + +struct u_boot_env { + struct device *dev; + enum u_boot_env_format format; + + /* Parent device */ + struct mtd_info *mtd; + size_t offset; + size_t size; + + /* Cells */ + struct nvmem_cell_info *cells; + int ncells; +}; + +struct u_boot_env_image_single { + __le32 crc32; + uint8_t data[0]; +} __packed; + +struct u_boot_env_image_redundant { + __le32 crc32; + u8 mark; + uint8_t data[0]; +} __packed; + +static int u_boot_env_read(void *context, unsigned int offset, void *val, + size_t bytes) +{ + struct u_boot_env *priv = context; + struct device *dev = priv->dev; + size_t bytes_read; + int err; + + err = mtd_read(priv->mtd, priv->offset + offset, bytes, &bytes_read, val); + if (err && !mtd_is_bitflip(err)) { + dev_err(dev, "Failed to read from mtd: %d\n", err); + return err; + } + + if (bytes_read != bytes) { + dev_err(dev, "Failed to read %zd bytes\n", bytes); + return -EIO; + } + + return 0; +} + +static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) +{ + struct device *dev = priv->dev; + char *data = buf + data_offset; + char *var, *value, *eq; + int idx; + + priv->ncells = 0; + for (var = data; var < data + data_len && *var; var += strlen(var) + 1) + priv->ncells++; + + priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); + if (!priv->cells) + return -ENOMEM; + + for (var = data, idx = 0; + var < data + data_len && *var; + var = value + strlen(value) + 1, idx++) { + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + + priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); + if (!priv->cells[idx].name) + return -ENOMEM; + priv->cells[idx].offset = data_offset + value - data; + priv->cells[idx].bytes = strlen(value); + } + + if (WARN_ON(idx != priv->ncells)) + priv->ncells = idx; + + return 0; +} + +static int u_boot_env_parse(struct u_boot_env *priv) +{ + struct device *dev = priv->dev; + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + size_t data_offset; + size_t data_len; + uint32_t crc32; + uint32_t calc; + size_t bytes; + uint8_t *buf; + int err; + + buf = kcalloc(1, priv->size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + + err = mtd_read(priv->mtd, priv->offset, priv->size, &bytes, buf); + if ((err && !mtd_is_bitflip(err)) || bytes != priv->size) { + dev_err(dev, "Failed to read from mtd: %d\n", err); + goto err_kfree; + } + + switch (priv->format) { + case U_BOOT_FORMAT_SINGLE: + crc32_offset = offsetof(struct u_boot_env_image_single, crc32); + crc32_data_offset = offsetof(struct u_boot_env_image_single, data); + data_offset = offsetof(struct u_boot_env_image_single, data); + break; + case U_BOOT_FORMAT_REDUNDANT: + crc32_offset = offsetof(struct u_boot_env_image_redundant, crc32); + crc32_data_offset = offsetof(struct u_boot_env_image_redundant, mark); + data_offset = offsetof(struct u_boot_env_image_redundant, data); + break; + } + crc32 = le32_to_cpu(*(uint32_t *)(buf + crc32_offset)); + crc32_data_len = priv->size - crc32_data_offset; + data_len = priv->size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { + dev_err(dev, "Invalid calculated CRC32: 0x%08x (expected: 0x%08x)\n", calc, crc32); + err = -EINVAL; + goto err_kfree; + } + + buf[priv->size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); + if (err) + dev_err(dev, "Failed to add cells: %d\n", err); + +err_kfree: + kfree(buf); +err_out: + return err; +} + +static const struct of_device_id u_boot_env_of_match_table[] = { + { .compatible = "u-boot,env", .data = (void *)U_BOOT_FORMAT_SINGLE, }, + { .compatible = "u-boot,env-redundant-bool", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, + { .compatible = "u-boot,env-redundant-count", .data = (void *)U_BOOT_FORMAT_REDUNDANT, }, + {}, +}; + +static int u_boot_env_probe(struct platform_device *pdev) +{ + struct nvmem_config config = { + .name = "u-boot-env", + .reg_read = u_boot_env_read, + }; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct of_device_id *of_id; + struct u_boot_env *priv; + int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->dev = dev; + + of_id = of_match_device(u_boot_env_of_match_table, dev); + if (!of_id) + return -EINVAL; + priv->format = (uintptr_t)of_id->data; + + if (of_property_read_u32(np, "reg", (u32 *)&priv->offset) || + of_property_read_u32_index(np, "reg", 1, (u32 *)&priv->size)) { + dev_err(dev, "Failed to read \"reg\" property\n"); + return -EINVAL; + } + + priv->mtd = of_get_mtd_device_by_node(np->parent); + if (IS_ERR(priv->mtd)) { + dev_err(dev, "Failed to get %pOF MTD: %ld\n", np->parent, PTR_ERR(priv->mtd)); + return PTR_ERR(priv->mtd); + } + + err = u_boot_env_parse(priv); + if (err) + return err; + + config.dev = dev; + config.cells = priv->cells; + config.ncells = priv->ncells; + config.priv = priv; + config.size = priv->size; + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); +} + +static struct platform_driver u_boot_env_driver = { + .probe = u_boot_env_probe, + .driver = { + .name = "u_boot_env", + .of_match_table = u_boot_env_of_match_table, + }, +}; +module_platform_driver(u_boot_env_driver); + +MODULE_AUTHOR("Rafał Miłecki"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, u_boot_env_of_match_table);