From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3CED53A3E6F for ; Tue, 12 May 2026 22:44:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625852; cv=none; b=T+DMCNak5BJ8MlTpKNj1KlBUJpjWWTtgFrguwOVgp4xEjYR2g3VElowqHQrFp67DH8FDoVjBRVu/KNIjmJCkPfoOKrcN1uf7/dkYaxbhfE++/flqQ5MNyMrOm84M4wEAgxAs49OcFgUpcVthg4rRKFaizoR0cUg2hykbMT+5aVQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625852; c=relaxed/simple; bh=CAJ0dYA0gL3B6kPJiD8HFdKtM9CzlZN+ytYYY5F+eeA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=geoxlUeGTYBsZO9Z+uee4az5ejZeIQ7Mrd/PgpLsFPZnLAqdpsDjPeIWkSrMrFApU3DGzjtM0L1f3Z7oQyTg/waHCi61AZOvd8sOLo1On156DkzEG1HEGxd5KETMbkMKlT9yhzejWM3xvMea6VN+TextqrYBwzSv9OBVtd13CWM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=lvUweJ+y; arc=none smtp.client-ip=209.85.221.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lvUweJ+y" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-4493cf2f982so373913f8f.2 for ; Tue, 12 May 2026 15:44:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625849; x=1779230649; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=61M3DMNG+oWQqxSuQprE2URgrjy5u8AgK8OgQ9rm0Ps=; b=lvUweJ+yu9Vx4xjOCdzNj9OXFq6/F6b1stholp5nxVl5W7lp7Dx7vifMZ8GzatvWnB lVM1gy+cgLc8Nl+rCZO5OfVUEE4jwZx2eA8pdSWSJfSQKr2S4le1ew01gurM3qPeAGaZ uo0WsOIp3JgHwJFym6/iOSM4OdAlfLhd/TL43G+PBJCgJq1ED0MnMGmTjKV+Si00esB9 +1KpCrCxS8YGvKV42xu9lRU3UKD1QfRdMxwR6gC8N7murcKs0SordNUMB8R43pzu39tX swfG9UkykUG1wJA9rfL0fHewqgl0AoTSmSw7k9JWO+jstXGh5a50FbXuwKAgLRn8zDVQ GAFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625849; x=1779230649; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=61M3DMNG+oWQqxSuQprE2URgrjy5u8AgK8OgQ9rm0Ps=; b=CqayGtCQensT3ZZFz0Euw0oX8YV1hP8NOg7ZbnDYevKsKzn1+AirkvFVe5YeHz003G E0pY9W5BWf33vvYUijwaVKisHjpOXQXmO5OGcmG0pFMAJx5uU7nDC/xZTY18GMQxtHMt 8qdNB3caOkxx3FOf0XhKejZRu2dNmlUW1YGHoHDB1ui8agQKQydjoMYyqqmqiRXkj3KP l1z7xJugtxWBGxDsEngTMnDW8mvd2ekI4KMTTkjVd7x14PKeTtiJx5dXh7mImUyrw4Ei x78+vnUvngxeNLXU6I/V/lYqxsxlhQvbXDFsv5deF+N4DBRM7vrZIJyioYZ2pyLVt7pl G1MQ== X-Forwarded-Encrypted: i=1; AFNElJ8VPGeU6Yx2DrF/WSB8nPzfVICzrUVpcncclP/OVRcGWFYRiB8eT6W9gWDJc008goyuCt7cdh0kcZ+n3TM=@vger.kernel.org X-Gm-Message-State: AOJu0Yw8YhunTi27boW4bI8utny4ERODV5n0XoBfgNJXCVwn5kGJ/ilm fE0AOTI2/8nmPuOeGDbV5TgYJfB9O9jL2Lh8GqRPi4ptwzF6ZyyzoPww X-Gm-Gg: Acq92OHqjEBC9dJhVRJRlUUaI5yXxtu6Y9Zl/QTHvYjP9tze+gMziKoCVWipn1DviUI lbrkabmouj8Jz1ljka0dZ2mmUJe6hKl1Q0WlHAW7Dt6Eb6dCxYjt+UX1WoTc5OVW+KjOscelp6n IOBHHVb/E2jX9ahSg5ql972Ip6rwjxhWQsOVGnpuFq8MY+wruM6RLMynOc4a41yb2NS69kXr8LA lLZR/7u3jP2ZM8dEYm7VP4xnPqP1XMIgknhVkGxQBd+FemmzXAb2BX4fuOnzVsWyp9vI1bPkuYq sdKuEeUYKBuj8rN63S31xQQAU9DJFlaJJqMC1Ofx0PgKxba28si2IHTMOcT3Vg/y4g5M+NATC7U RjRbLoq5lsj0Z8sxEbp3wAYVxXy1W+blGiqaffquGQ5E8Qhl2dmZCZASGsLh6goJHQ5m8NaOJOL ntzAqG/GUzT42oPOX+8DhKRHDQL9VTB33i9h6RAeDUeuD9AkTDXiBnzqmWng3Vs+bFsetosAL0D w== X-Received: by 2002:a05:600c:3b16:b0:48a:79da:c87 with SMTP id 5b1f17b1804b1-48fc9a51444mr4274175e9.8.1778625848430; Tue, 12 May 2026 15:44:08 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:08 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 01/12] crypto: atmel - introduce shared I2C client management Date: Tue, 12 May 2026 22:43:38 +0000 Message-Id: <20260512224349.64621-2-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a shared I2C client management infrastructure in the atmel-i2c core and convert the atmel-ecc and atmel-sha204a drivers to use it. Replace the driver-local atmel_ecc_driver_data structure with the common atmel_i2c_mgmt instance, providing a shared client list and locking for compatible Atmel secure element devices. Add a common atmel_i2c_unregister_client() helper to centralize client removal handling. Refactor both drivers to use module_i2c_driver() and move duplicated client list handling into the shared infrastructure. Probe and remove paths are updated accordingly, including consistent error unwinding for client registration failures. Subsequent patches will build on the shared client infrastructure. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 58 ++++++++++++++-------------------- drivers/crypto/atmel-i2c.c | 15 +++++++++ drivers/crypto/atmel-i2c.h | 5 ++- drivers/crypto/atmel-sha204a.c | 38 ++++++++++++---------- 4 files changed, 65 insertions(+), 51 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 3738a4eb8701..cba4238735cc 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -23,8 +23,6 @@ #include #include "atmel-i2c.h" =20 -static struct atmel_ecc_driver_data driver_data; - /** * struct atmel_ecdh_ctx - transformation context * @client : pointer to i2c client device @@ -209,14 +207,14 @@ static struct i2c_client *atmel_ecc_i2c_client_alloc(= void) int min_tfm_cnt =3D INT_MAX; int tfm_cnt; =20 - spin_lock(&driver_data.i2c_list_lock); + spin_lock(&atmel_i2c_mgmt.i2c_list_lock); =20 - if (list_empty(&driver_data.i2c_client_list)) { - spin_unlock(&driver_data.i2c_list_lock); + if (list_empty(&atmel_i2c_mgmt.i2c_client_list)) { + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); return ERR_PTR(-ENODEV); } =20 - list_for_each_entry(i2c_priv, &driver_data.i2c_client_list, + list_for_each_entry(i2c_priv, &atmel_i2c_mgmt.i2c_client_list, i2c_client_list_node) { tfm_cnt =3D atomic_read(&i2c_priv->tfm_count); if (tfm_cnt < min_tfm_cnt) { @@ -232,7 +230,7 @@ static struct i2c_client *atmel_ecc_i2c_client_alloc(vo= id) client =3D min_i2c_priv->client; } =20 - spin_unlock(&driver_data.i2c_list_lock); + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); =20 return client; } @@ -319,27 +317,34 @@ static int atmel_ecc_probe(struct i2c_client *client) =20 ret =3D atmel_i2c_probe(client); if (ret) - return ret; + goto done; =20 i2c_priv =3D i2c_get_clientdata(client); =20 - spin_lock(&driver_data.i2c_list_lock); + /* add to client list */ + spin_lock(&atmel_i2c_mgmt.i2c_list_lock); list_add_tail(&i2c_priv->i2c_client_list_node, - &driver_data.i2c_client_list); - spin_unlock(&driver_data.i2c_list_lock); + &atmel_i2c_mgmt.i2c_client_list); + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); =20 + /* register algorithms */ ret =3D crypto_register_kpp(&atmel_ecdh_nist_p256); if (ret) { - spin_lock(&driver_data.i2c_list_lock); - list_del(&i2c_priv->i2c_client_list_node); - spin_unlock(&driver_data.i2c_list_lock); - dev_err(&client->dev, "%s alg registration failed\n", atmel_ecdh_nist_p256.base.cra_driver_name); + goto err_list_del; } else { dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\= n"); } =20 + goto done; + +err_list_del: + spin_lock(&atmel_i2c_mgmt.i2c_list_lock); + list_del(&i2c_priv->i2c_client_list_node); + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); + +done: return ret; } =20 @@ -361,11 +366,10 @@ static void atmel_ecc_remove(struct i2c_client *clien= t) return; } =20 - crypto_unregister_kpp(&atmel_ecdh_nist_p256); + atmel_i2c_unregister_client(i2c_priv); + atmel_i2c_flush_queue(); =20 - spin_lock(&driver_data.i2c_list_lock); - list_del(&i2c_priv->i2c_client_list_node); - spin_unlock(&driver_data.i2c_list_lock); + crypto_unregister_kpp(&atmel_ecdh_nist_p256); } =20 #ifdef CONFIG_OF @@ -398,21 +402,7 @@ static struct i2c_driver atmel_ecc_driver =3D { .id_table =3D atmel_ecc_id, }; =20 -static int __init atmel_ecc_init(void) -{ - spin_lock_init(&driver_data.i2c_list_lock); - INIT_LIST_HEAD(&driver_data.i2c_client_list); - return i2c_add_driver(&atmel_ecc_driver); -} - -static void __exit atmel_ecc_exit(void) -{ - atmel_i2c_flush_queue(); - i2c_del_driver(&atmel_ecc_driver); -} - -module_init(atmel_ecc_init); -module_exit(atmel_ecc_exit); +module_i2c_driver(atmel_ecc_driver); =20 MODULE_AUTHOR("Tudor Ambarus"); MODULE_DESCRIPTION("Microchip / Atmel ECC (I2C) driver"); diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 0e275dbdc8c5..861af52d7a88 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -21,6 +21,12 @@ #include #include "atmel-i2c.h" =20 +struct atmel_i2c_client_mgmt atmel_i2c_mgmt =3D { + .i2c_list_lock =3D __SPIN_LOCK_UNLOCKED(atmel_i2c_mgmt.i2c_list_lock), + .i2c_client_list =3D LIST_HEAD_INIT(atmel_i2c_mgmt.i2c_client_list), +}; +EXPORT_SYMBOL_GPL(atmel_i2c_mgmt); + static const struct { u8 value; const char *error_text; @@ -348,6 +354,15 @@ static int device_sanity_check(struct i2c_client *clie= nt) return ret; } =20 +void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv) +{ + spin_lock(&atmel_i2c_mgmt.i2c_list_lock); + if (!list_empty(&i2c_priv->i2c_client_list_node)) + list_del_init(&i2c_priv->i2c_client_list_node); + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); +} +EXPORT_SYMBOL(atmel_i2c_unregister_client); + int atmel_i2c_probe(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv; diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 72f04c15682f..43a0c1cfcd94 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -115,10 +115,11 @@ struct atmel_i2c_cmd { #define ECDH_PREFIX_MODE 0x00 =20 /* Used for binding tfm objects to i2c clients. */ -struct atmel_ecc_driver_data { +struct atmel_i2c_client_mgmt { struct list_head i2c_client_list; spinlock_t i2c_list_lock; } ____cacheline_aligned; +extern struct atmel_i2c_client_mgmt atmel_i2c_mgmt; =20 /** * atmel_i2c_client_priv - i2c_client private data @@ -189,4 +190,6 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cm= d, u16 keyid); int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, struct scatterlist *pubkey); =20 +void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv); + #endif /* __ATMEL_I2C_H__ */ diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index ed7d69bf6890..e6808c2bc891 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -169,10 +169,17 @@ static int atmel_sha204a_probe(struct i2c_client *cli= ent) =20 ret =3D atmel_i2c_probe(client); if (ret) - return ret; + goto done; =20 i2c_priv =3D i2c_get_clientdata(client); =20 + /* add to client list */ + spin_lock(&atmel_i2c_mgmt.i2c_list_lock); + list_add_tail(&i2c_priv->i2c_client_list_node, + &atmel_i2c_mgmt.i2c_client_list); + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); + + /* register rng */ memset(&i2c_priv->hwrng, 0, sizeof(i2c_priv->hwrng)); =20 i2c_priv->hwrng.name =3D dev_name(&client->dev); @@ -183,15 +190,26 @@ static int atmel_sha204a_probe(struct i2c_client *cli= ent) i2c_priv->hwrng.quality =3D *quality; =20 ret =3D devm_hwrng_register(&client->dev, &i2c_priv->hwrng); - if (ret) + if (ret) { dev_warn(&client->dev, "failed to register RNG (%d)\n", ret); + goto err_list_del; + } =20 ret =3D sysfs_create_group(&client->dev.kobj, &atmel_sha204a_groups); if (ret) { dev_err(&client->dev, "failed to register sysfs entry\n"); - return ret; + goto err_list_del; } =20 + goto done; + +err_list_del: + sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups); + spin_lock(&atmel_i2c_mgmt.i2c_list_lock); + list_del(&i2c_priv->i2c_client_list_node); + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); + +done: return ret; } =20 @@ -230,19 +248,7 @@ static struct i2c_driver atmel_sha204a_driver =3D { .driver.of_match_table =3D of_match_ptr(atmel_sha204a_dt_ids), }; =20 -static int __init atmel_sha204a_init(void) -{ - return i2c_add_driver(&atmel_sha204a_driver); -} - -static void __exit atmel_sha204a_exit(void) -{ - atmel_i2c_flush_queue(); - i2c_del_driver(&atmel_sha204a_driver); -} - -module_init(atmel_sha204a_init); -module_exit(atmel_sha204a_exit); +module_i2c_driver(atmel_sha204a_driver); =20 MODULE_AUTHOR("Ard Biesheuvel "); MODULE_DESCRIPTION("Microchip / Atmel SHA204A (I2C) driver"); --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 29B383A4F50 for ; Tue, 12 May 2026 22:44:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625853; cv=none; b=NCyI27us+vY1i9nZxla5ccPjtI3rokYWaVZ2Z4gG+mJGmyMpDaliVfhzY2IGT7iLZnG3YpyfjyRuYvXYtAmVGaT/JiCKD4swU3CDuTQxJVxGdHQQXENEsIaT/d/tSHprEf7HkiYivS41G+4Hl/HF5lTUrC0mQ1nza6C0ye/c8uk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625853; c=relaxed/simple; bh=kTzGIg2ZKv2CEMnZnYfRwD9wOU2ZtpB5enjuLO9/y2Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qSh/5ZCf+aJwP7poCqNLnXH/WxV06AEcYyIwnobU/BizknIm1fiGaolqJAqarmTpLSm9PQ2/hNnZwsmeJ8ROvsa/E8Wb4kXgIJyTibhcszrwSnXtCdib/RXke21FE0aJtx7oG7y113zyeSU5CE+tJ+LvnPFNHoYFCcEEt22awL4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nHXDTv52; arc=none smtp.client-ip=209.85.128.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nHXDTv52" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-48e69e60063so5387025e9.1 for ; Tue, 12 May 2026 15:44:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625850; x=1779230650; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9RwkhAyGo0F1Zzezeg5ARZljvoevw6uxnTcs7DFl6kQ=; b=nHXDTv52Gp3cpbf9N3St05Q+wD1k2c0X8te/gFpRNd3HvI+PA1y15p/Jo4iUPOZKhL JaD7IFHAAUBpNFeYYGIyCEkPZicigHhXakUEAqQwY5NFMEeLyFIp31h8hDf/9+J9hvEC MMq/aRqLFSxACvqVxscbcsbMZOcwf13yaQYRjyQ0axcJtWBYK4digHMtnFt9To2PpV/F c67VpO8s2nLX7pht25hL/x2BqXOflBWMO8VzXnjwwwC6hAAAf84SXTa8Jc1ki3LifCBm bfwSwpBk8zy3ZT053I+G0WuHdbE3SsSJtcgCqVEbe5UVH7R4JztC8S3VyCtjmfmGQqog EtDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625850; x=1779230650; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=9RwkhAyGo0F1Zzezeg5ARZljvoevw6uxnTcs7DFl6kQ=; b=ijuGOVoLL6KpdUZdeMng100+smLiEEWoRUpM9X5nSGgOoqURNY4PZo4WjArmNK81PV D/L/Q2tMfPPgIExkRwwR6+HmjgBiGwwf1TLgNCC1QIKuzQEVwVt/Vl+M5tCXa5E4V4Ms sT3HcbNN+af+BkIWvbeiTIznUeR9ineQ05LKvs5q/7+4kf9JW4JBH1xcDkdpxGhxVaQQ bWT7PlGduN91QtY0br5KQwTW7iLbmAWHXrlLVHczoAquesm6iI04bsojtEg4pVu93N4X R6uvOE+JLHpVhlbJyEaNqeTGgfVBy6oWKJ/YBln7Dpqa9qJSQ6BdB2JWjqDxvgK9TefY GmKQ== X-Forwarded-Encrypted: i=1; AFNElJ/zcIQR+xBx8snuiaEkFzWcgV3mtKqr33d9S53OL5kJ6VFnTWWhC0lq1eyOr1uzyW2STaRT8cpfJmsyjsA=@vger.kernel.org X-Gm-Message-State: AOJu0Ywwq1fGF9O5aRoHAQ7aO5vtANKeo7CvzE1d9FiMPqcLVwzdkDp9 slF4gYSzceUILJZId8t/X/N0PcqdbCg0pJSNxxWA71VLR71pJU24qzY5 X-Gm-Gg: Acq92OFazQ6PDoaNsOkWXgzL2wyuPPvvUsxmprYf8WVtoP/rU/hDIzmSqrwAEQrIElc YRSRR8QdTcthGbLaRxcVuB+hCOhNk9Fs1h9aEUoAiBr7e81nhrM3BENThaJZMRsinpU7p80w1K1 ZogUVsFhcUAyLPtxn3gs7NT6zPaNtBzuV4uahNpygmVaOmJGsDknDBQlpkapbv4x+Z5gcmCJlQm 332y9GXcqAjH0wWL6qzJtjS0NYvgjAOzqL9nzPiqhEsPvi75XqARKSYdPW+cYqrdrpzia1gBqIu EGNCOOkyCIPnWkitfvLPLhvfW4hStltg9CPduf5D6fVyybIzG5bZegyqdd+5GXAUYco5LVIm9R7 wlmfylEgKClKLuAAKkj1nxKj6nv7aQre/n7Imv5uRvS/vJiHl+nh35+voBxG4FJSq459IrBh89e Xxzh6kH5lktMY7ylYVNZlatnCOjOExOGwucuvV5McyanoISb0q+HD9wXWYEGBa3dY= X-Received: by 2002:a05:600c:19ce:b0:488:a797:f099 with SMTP id 5b1f17b1804b1-48fc9a34585mr5290375e9.3.1778625849440; Tue, 12 May 2026 15:44:09 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:09 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 02/12] crypto: atmel - move capability-based client allocation into i2c core Date: Tue, 12 May 2026 22:43:39 +0000 Message-Id: <20260512224349.64621-3-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the i2c client allocation logic from atmel-ecc into the shared atmel-i2c core and extend it to support capability-based client selection. Introduce enum atmel_i2c_capability and add capability flags to struct atmel_i2c_client_priv. Devices now advertise their supported features during probe, allowing atmel_i2c_client_alloc() to select a compatible client from the shared i2c client list. The allocation logic continues to balance crypto transformation usage across devices by selecting the client with the lowest tfm_count, but is no longer limited to ECC-capable devices. This centralizes shared client management in the common atmel-i2c core and prepares the infrastructure for additional shared crypto features across compatible Atmel devices. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 39 +++------------------------------- drivers/crypto/atmel-i2c.c | 39 ++++++++++++++++++++++++++++++++++ drivers/crypto/atmel-i2c.h | 7 ++++++ drivers/crypto/atmel-sha204a.c | 2 ++ 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index cba4238735cc..c63d30947bd7 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -200,41 +200,6 @@ static int atmel_ecdh_compute_shared_secret(struct kpp= _request *req) return ret; } =20 -static struct i2c_client *atmel_ecc_i2c_client_alloc(void) -{ - struct atmel_i2c_client_priv *i2c_priv, *min_i2c_priv =3D NULL; - struct i2c_client *client =3D ERR_PTR(-ENODEV); - int min_tfm_cnt =3D INT_MAX; - int tfm_cnt; - - spin_lock(&atmel_i2c_mgmt.i2c_list_lock); - - if (list_empty(&atmel_i2c_mgmt.i2c_client_list)) { - spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); - return ERR_PTR(-ENODEV); - } - - list_for_each_entry(i2c_priv, &atmel_i2c_mgmt.i2c_client_list, - i2c_client_list_node) { - tfm_cnt =3D atomic_read(&i2c_priv->tfm_count); - if (tfm_cnt < min_tfm_cnt) { - min_tfm_cnt =3D tfm_cnt; - min_i2c_priv =3D i2c_priv; - } - if (!min_tfm_cnt) - break; - } - - if (min_i2c_priv) { - atomic_inc(&min_i2c_priv->tfm_count); - client =3D min_i2c_priv->client; - } - - spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); - - return client; -} - static void atmel_ecc_i2c_client_free(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); @@ -249,7 +214,7 @@ static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm) struct atmel_ecdh_ctx *ctx =3D kpp_tfm_ctx(tfm); =20 ctx->curve_id =3D ECC_CURVE_NIST_P256; - ctx->client =3D atmel_ecc_i2c_client_alloc(); + ctx->client =3D atmel_i2c_client_alloc(ATMEL_CAP_ECDH); if (IS_ERR(ctx->client)) { pr_err("tfm - i2c_client binding failed\n"); return PTR_ERR(ctx->client); @@ -321,6 +286,8 @@ static int atmel_ecc_probe(struct i2c_client *client) =20 i2c_priv =3D i2c_get_clientdata(client); =20 + i2c_priv->caps =3D BIT(ATMEL_CAP_ECDH); + /* add to client list */ spin_lock(&atmel_i2c_mgmt.i2c_list_lock); list_add_tail(&i2c_priv->i2c_client_list_node, diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 861af52d7a88..b7ee2ec37531 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -57,6 +57,45 @@ static void atmel_i2c_checksum(struct atmel_i2c_cmd *cmd) *__crc16 =3D cpu_to_le16(bitrev16(crc16(0, data, len))); } =20 +struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap) +{ + struct atmel_i2c_client_priv *i2c_priv, *min_i2c_priv =3D NULL; + struct i2c_client *client =3D ERR_PTR(-ENODEV); + int min_tfm_cnt =3D INT_MAX; + int tfm_cnt; + + spin_lock(&atmel_i2c_mgmt.i2c_list_lock); + + if (list_empty(&atmel_i2c_mgmt.i2c_client_list)) { + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); + return ERR_PTR(-ENODEV); + } + + list_for_each_entry(i2c_priv, &atmel_i2c_mgmt.i2c_client_list, + i2c_client_list_node) { + if (!(i2c_priv->caps & BIT(cap))) + continue; + + tfm_cnt =3D atomic_read(&i2c_priv->tfm_count); + if (tfm_cnt < min_tfm_cnt) { + min_tfm_cnt =3D tfm_cnt; + min_i2c_priv =3D i2c_priv; + } + if (!min_tfm_cnt) + break; + } + + if (min_i2c_priv) { + atomic_inc(&min_i2c_priv->tfm_count); + client =3D min_i2c_priv->client; + } + + spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); + + return client; +} +EXPORT_SYMBOL(atmel_i2c_client_alloc); + void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd) { cmd->word_addr =3D COMMAND; diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 43a0c1cfcd94..70579b438256 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -115,6 +115,10 @@ struct atmel_i2c_cmd { #define ECDH_PREFIX_MODE 0x00 =20 /* Used for binding tfm objects to i2c clients. */ +enum atmel_i2c_capability { + ATMEL_CAP_ECDH =3D 0, +}; + struct atmel_i2c_client_mgmt { struct list_head i2c_client_list; spinlock_t i2c_list_lock; @@ -130,6 +134,7 @@ extern struct atmel_i2c_client_mgmt atmel_i2c_mgmt; * @wake_token_sz : size in bytes of the wake_token * @tfm_count : number of active crypto transformations on i2c c= lient * @hwrng : hold the hardware generated rng + * @caps : feature capability of the particular driver * * Reads and writes from/to the i2c client are sequential. The first byte * transmitted to the device is treated as the byte size. Any attempt to s= end @@ -146,6 +151,7 @@ struct atmel_i2c_client_priv { size_t wake_token_sz; atomic_t tfm_count ____cacheline_aligned; struct hwrng hwrng; + u32 caps; }; =20 /** @@ -190,6 +196,7 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cm= d, u16 keyid); int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, struct scatterlist *pubkey); =20 +struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap); void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv); =20 #endif /* __ATMEL_I2C_H__ */ diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index e6808c2bc891..ab758c9cd410 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -173,6 +173,8 @@ static int atmel_sha204a_probe(struct i2c_client *clien= t) =20 i2c_priv =3D i2c_get_clientdata(client); =20 + i2c_priv->caps =3D 0; + /* add to client list */ spin_lock(&atmel_i2c_mgmt.i2c_list_lock); list_add_tail(&i2c_priv->i2c_client_list_node, --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 152C03A5459 for ; Tue, 12 May 2026 22:44:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625854; cv=none; b=lqdnQIyxhC7X+t/jtHel+zDlVHNXa26wGBA5o3LQp7cQKw+sNHqu7CInE2znjDRPB1U0So+gw3haZPW1UIQjAt9vt6dGSzchtlnDwPaYstrgjaAFYnzYzVk6b2Fqr94Mk+j26vYrfGNmbCP5ehl+Z9uXo5JqpuJq7Wq1uiuhgls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625854; c=relaxed/simple; bh=PPl0u8i7CeGWGfwyBBjG3tIzn/X8jFNZ9qbNXXig3Ro=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dS/AozOHN0rFajbieuTo2h2xQJmmMfbrRVJBKfXJuhdNbjrS7fOhi3/JFVbARrwrlKmL8dLIDKbaPnMVIKAqC2KaM+aqgJsqw7bYzOLHAQsEnf7rYYEhUaQM4VpHiofOVn9IoHvtSvNYe/w8IQlCZrsLR1nDI9VXrMb2yBH3VPQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZM7vzaYr; arc=none smtp.client-ip=209.85.128.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZM7vzaYr" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-4830b67aa6bso7068795e9.0 for ; Tue, 12 May 2026 15:44:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625850; x=1779230650; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WoTuR9u/S7BS3l0dt8ueu9k+dX7v2fjdA6MLehy70Ow=; b=ZM7vzaYrZD5cL0kVJF4rL7vpwpv4ikLl/wtgOnKlp70kko/xvlT8FLIQG+5/7tJ/5r qAZF/7WtXTgIjqudNlNFVMXhHOyIbVmKf9du8UC8H2xxkgEMToebqc5PIuhaxgQwHaz5 bSqIHRB40WGqRQ/esDo2fDc6ra+JrQBSUrcRm8RSe7Hw6SQZklSZzxgDpZ2G50+eoUqh 2h1fZuSBYLJi3iOGUEb0o4JdKawqUrsde4FsbC1zzV5SIx5dOcAOAtBX8sZ2RX48tGKM t44yW13vWWm6DQqd5IDIsnLZqL0cUftGUWmHQe8+35e5E+awj+fLQGpE7/UYabcy5K+c 1OTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625850; x=1779230650; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=WoTuR9u/S7BS3l0dt8ueu9k+dX7v2fjdA6MLehy70Ow=; b=JLS7fby5G2z14JrR29VTjIMsZwJH+5tp0LLosGMiYv/kfWDbYqB0N4WnGsv8gD7hGB sv5OvTFir9sHUpXOztO5bthHUkYKf6cQjiap2BXACYn72RGID2gfDb5vX/WVfB6NzjB5 mKxBGVQpYMkJ2SSncXmLLdwZHnrnTO+f87L5/hnxBIroPSzi0t+Pvpz4ApQjaLpqAq0V es26rdlODsQ/WFwphm3dY6jVESEC2Ru66swPHS18iFTHw5E8BM3IUmEPQcIAeRliO/LS gZv7Xz40O9hm46aYMZIDEOGgviAv5FHtTxFtFZOjfiQrNfxJ3Guoa0zTlG8dsUw9t5+o P4NQ== X-Forwarded-Encrypted: i=1; AFNElJ9zFtVL4qCZAYGk19dMO+s495ELyZKoDLJ0MVJrM3LkX3w8zSKhpxx8u0MmGLv+o32cQw+tEMr6T27p/6s=@vger.kernel.org X-Gm-Message-State: AOJu0YyoswDoBwog/5d8hmPZqd/jBfE1HMn0Uw5W8HKEfmdkeliMtBTL 1S4oiX4lOOXFEPAw/z5AIoK3U3bj0u+EFehJLlfb+sfOKRfxNgR4FzPy8uA7bw== X-Gm-Gg: Acq92OGjZgcYDoloEtQTYyOcdb96EWvVG3+9XHINJTn6Ye2xGXSagfRpdItckEQ+0HP aNZZSITGurJXmU6jNslH/hbSIBIZ/IbzGVP8xWmzKm+AINnKkTQNmsQ4fcR7IFwg7/LoXfkL9Zu RHjP2aHvCknQrPrMYznvPTgQ0Q5qCUmLWD2KCjLqlcrEc3gQkr2nFO2Xb6/3OrFE/m0NcA/voD5 MWL2mzaZGIgtIPolxduIBXkC1nWfx3web7sLWn0ohGDmEj6kC0Gg0nWr60ZoYXlfFGacguJpZBv cpmaCfCCJebGQE+sbICD0ulJPYpkP6IP3FUUz96Cntwxnh2yqBweABeRrlelnnstZH2W4DQzF1R 74oZKo0ax4J+NLmFTJeb8+dyG2HLrHB1D84SSaM24pndrn/PqtxvCi9cXyekWbiM4rMEFDkRkZr 3uqYb7zvSITFQDN2+ZtwvyyTdL83ThSmadDV1wWxXI9AmSGm62Wcv4hWs1n/P5D2I= X-Received: by 2002:a05:600c:35c5:b0:48a:797f:24f8 with SMTP id 5b1f17b1804b1-48fc99a8965mr6254295e9.0.1778625850432; Tue, 12 May 2026 15:44:10 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:10 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 03/12] crypto: atmel - remove obsolete CONFIG_OF guard Date: Tue, 12 May 2026 22:43:40 +0000 Message-Id: <20260512224349.64621-4-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Remove the CONFIG_OF preprocessor guard around the OF device match table in atmel-ecc. OF match tables are expected to be present unconditionally and the MODULE_DEVICE_TABLE(of, ...) handling already accounts for configurations where OF support is disabled. Keeping the additional guard provides no benefit and only adds unnecessary conditional compilation. Also compact the match table formatting while touching the code. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index c63d30947bd7..0dede3707b73 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -339,18 +339,12 @@ static void atmel_ecc_remove(struct i2c_client *clien= t) crypto_unregister_kpp(&atmel_ecdh_nist_p256); } =20 -#ifdef CONFIG_OF static const struct of_device_id atmel_ecc_dt_ids[] =3D { - { - .compatible =3D "atmel,atecc508a", - }, { - .compatible =3D "atmel,atecc608b", - }, { - /* sentinel */ - } + { .compatible =3D "atmel,atecc508a", }, + { .compatible =3D "atmel,atecc608b", }, + { } }; MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids); -#endif =20 static const struct i2c_device_id atmel_ecc_id[] =3D { { "atecc508a" }, --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 004A03A6411 for ; Tue, 12 May 2026 22:44:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625856; cv=none; b=bn4uamJ5bmDc1Gv0hauATprGmjK2n7MNTItVeTgW0vRMhT0TZci26SuBLscG5k+ebz3CRtS2JBvGCPEwao7adXYSRuS4lNZLRlUpfRcbvNZPG1YZAapVcIEltQ7K/Duf7+HM3tse2JEziwidkjwVMvXgOwqvcvUAwzPcFddEuS0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625856; c=relaxed/simple; bh=pLT1wgzVArxBbwkzGjXRSm1Fzalz9DXMwCB8xPgZFWY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sOInM1Viuigvwk8uHT9AWmenLNMUHS/GMs5KmdJYY9KYgjUx74oL2+lcpHq0kV4qKaEbk1Y0FHjZtTLFt1a4hTHqvBsN0X6JigsFMX5SJva9skQhsWzXHNzniVLlacZrDTqEd/UpkJg/qXj7KI9M8r9vg24KhKZcjptx4DEHyyo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OJL+6ZUb; arc=none smtp.client-ip=209.85.128.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OJL+6ZUb" Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-4891b02a0acso6258375e9.3 for ; Tue, 12 May 2026 15:44:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625852; x=1779230652; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=b3oXj7PZ3++PLAjhiteExNTpYw5d8hkPXFmyLO00sz4=; b=OJL+6ZUbHCr8lK/4ftny2x4Fvm2AB91g0Rw90gRw93zu5PzfUvO8lKnopNQT4hY50o Ce/dt7zdLPYYxFofO54IoXI0lNvniQfOWgQwAPrEqoQ+QAmNTVCSw9UYPtPwdXbMMcC+ E6DCHBbMzrENajotlZpWZochGG44iHypM5oufMxVk0HXx5PapkoK6axk4O8l6+xWQxPc IPX6/ugqluti3HNveWvYvmwJ774e6r+wXkd4FxbUIaD1BT3glLgtnw8e8ZFt6/tpyZX9 vK/5BTWVaUhMe8D9Yy3uzYC4dA9TpUkGUcTaV3qhjF5J+uWTdkPWQFcyZR3NJUmwu+kF KB6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625852; x=1779230652; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=b3oXj7PZ3++PLAjhiteExNTpYw5d8hkPXFmyLO00sz4=; b=WR9wstnCXkUpAhYl8TKEEcqL6OG9TSqkTsAZUvD9ZFXY/D6NN6ABmXHO08qsHEyR/k nabsahjwAqAPNiWY5OhPnAgmS3ukNJN0QYMOIT/CNdQDvLDv/3dYv34NbwGZzPwpkrw+ doabpa75lupNBn7LxTBjvhUPgeM659+QjYhH5mPIdqz9VRAOp3qSbiwnrybxCE4xQxiT /3h94do/tim/TUba7BpjDHexjdNhawkUeb3k6QWCCTaZc5obt1Rkhi89a88U07flCweb 6v/vO7vtSjD75NZRhSSS++qhKqRcW9CthY84xg8WO7v6mp4/eJyVaiCxs5PFrQk2Lg5L 9CoQ== X-Forwarded-Encrypted: i=1; AFNElJ9Xc9p+hJgtBoSGqd+RF2N8wJAhtcQq91j6oVGDpb6/h/opDcvBNX42tF2iXWVavx3IJnPH8AVOWGt1Cgs=@vger.kernel.org X-Gm-Message-State: AOJu0YxylR70viDFvQKqu8zLxbh6IrUWAssUTXoYXNfTf864OarayQjH SLeMjnFiD3YTU+aZgWBTDzK5OEAMXofAPJvT2QIhXISDy5vhi0xoJ3Gk X-Gm-Gg: Acq92OEtmU6z7Sk48Jjgr8Cw77Q5VdXprAts1EkW8Zvel28l6DRmmb3Zd9bMGAZ6aKF g8/ubu5KuETN9+Hf1ZtA8X31zZE3rRoEdUu6dqEkuKZm6V8EjkAaco53KodbETRu088n3uJEdxC jR1ZSi41r6Wpb5txMdDkWlbWsVCtXvsyTr5VUGSazyV19cUWYn1nKlwvIhRJStmz2Gkp8/gpVOr 2YGiI1YKQnwSxbiaHlQJOVJrO95BxYmpa6uw6wLtZDOUOqpettoWMfG58uNHjUCk8fn2ghQYi1U 7TJVARtfDpXAt6Sjy7oWoJBQWmHGeP4FrNmnBaQDcAvI3B44Q1XFcPLKtRsx5BevnHjvHTAjwC/ EXMFbBIYm9GwSqMgxcAj1p8FYWSP7/qpRI2yqGzE0XXegn32KiKc6R0fYnmqnduup+cJmg9D3lK Fn5ajBwtQYD8LJqg7+zcES3mkDuMe3+A3BMvKyJZSrPrd7KTGQM10W/dqYmw6lQ1Y= X-Received: by 2002:a05:600c:35c8:b0:48f:c8d4:487a with SMTP id 5b1f17b1804b1-48fc9a50b29mr4615355e9.8.1778625852236; Tue, 12 May 2026 15:44:12 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:11 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 04/12] crypto: atmel - add per-device timing and match-data driven configuration Date: Tue, 12 May 2026 22:43:41 +0000 Message-Id: <20260512224349.64621-5-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The ATSHA204(A) and ATECC device families define different maximum command execution times in their datasheets. The current driver uses a mixed set of timing constants, which can result in insufficient wait times for some devices. Introduce struct atmel_i2c_of_match_data to provide per-device timing information through the device match tables. Store the match data in the client private structure and pass the timing parameters to the command initialization helpers instead of relying on global timing constants. This allows the common atmel-i2c core to use device-specific command timeouts for operations such as READ, RANDOM, GENKEY, and ECDH. Also move the legacy hwrng quality information into the match data structure to consolidate per-device configuration in a single place. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 32 +++++++++++++--- drivers/crypto/atmel-i2c.c | 29 ++++++++------ drivers/crypto/atmel-i2c.h | 36 ++++++++++++------ drivers/crypto/atmel-sha204a.c | 69 ++++++++++++++++++++++++---------- 4 files changed, 120 insertions(+), 46 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 0dede3707b73..7793f7b4e97e 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -76,6 +76,8 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm, = const void *buf, unsigned int len) { struct atmel_ecdh_ctx *ctx =3D kpp_tfm_ctx(tfm); + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(ctx->client= ); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; struct atmel_i2c_cmd *cmd; void *public_key; struct ecdh params; @@ -112,7 +114,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm= , const void *buf, =20 ctx->do_fallback =3D false; =20 - atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2); + atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2, &data->timings); =20 ret =3D atmel_i2c_send_receive(ctx->client, cmd); if (ret) @@ -164,6 +166,8 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_= request *req) { struct crypto_kpp *tfm =3D crypto_kpp_reqtfm(req); struct atmel_ecdh_ctx *ctx =3D kpp_tfm_ctx(tfm); + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(ctx->client= ); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; struct atmel_i2c_work_data *work_data; gfp_t gfp; int ret; @@ -187,7 +191,7 @@ static int atmel_ecdh_compute_shared_secret(struct kpp_= request *req) work_data->ctx =3D ctx; work_data->client =3D ctx->client; =20 - ret =3D atmel_i2c_init_ecdh_cmd(&work_data->cmd, req->src); + ret =3D atmel_i2c_init_ecdh_cmd(&work_data->cmd, req->src, &data->timings= ); if (ret) goto free_work_data; =20 @@ -278,14 +282,22 @@ static struct kpp_alg atmel_ecdh_nist_p256 =3D { static int atmel_ecc_probe(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv; + const struct atmel_i2c_of_match_data *data; int ret; =20 ret =3D atmel_i2c_probe(client); if (ret) goto done; =20 - i2c_priv =3D i2c_get_clientdata(client); + data =3D device_get_match_data(&client->dev); + if (!data) { + dev_err(&client->dev, "no match data found via OF or ID table\n"); + ret =3D -ENODEV; + goto done; + } =20 + i2c_priv =3D i2c_get_clientdata(client); + i2c_priv->data =3D data; i2c_priv->caps =3D BIT(ATMEL_CAP_ECDH); =20 /* add to client list */ @@ -339,9 +351,19 @@ static void atmel_ecc_remove(struct i2c_client *client) crypto_unregister_kpp(&atmel_ecdh_nist_p256); } =20 +static const struct atmel_i2c_of_match_data atecc508a_match_data =3D { + .timings =3D { + .max_exec_time_ecdh =3D 58, + .max_exec_time_genkey =3D 115, + .max_exec_time_random =3D 23, + .max_exec_time_read =3D 1, + .max_exec_time_write =3D 42, + }, +}; + static const struct of_device_id atmel_ecc_dt_ids[] =3D { - { .compatible =3D "atmel,atecc508a", }, - { .compatible =3D "atmel,atecc608b", }, + { .compatible =3D "atmel,atecc508a", .data =3D &atecc508a_match_data, }, + { .compatible =3D "atmel,atecc608b", .data =3D &atecc508a_match_data, }, { } }; MODULE_DEVICE_TABLE(of, atmel_ecc_dt_ids); diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index b7ee2ec37531..7fa7cf9ab3c1 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -96,7 +96,8 @@ struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_= capability cap) } EXPORT_SYMBOL(atmel_i2c_client_alloc); =20 -void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd) +void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd, + const struct atmel_i2c_max_exec_timings *timings) { cmd->word_addr =3D COMMAND; cmd->opcode =3D OPCODE_READ; @@ -110,12 +111,13 @@ void atmel_i2c_init_read_config_cmd(struct atmel_i2c_= cmd *cmd) =20 atmel_i2c_checksum(cmd); =20 - cmd->msecs =3D MAX_EXEC_TIME_READ; + cmd->msecs =3D timings->max_exec_time_read; cmd->rxsize =3D READ_RSP_SIZE; } EXPORT_SYMBOL(atmel_i2c_init_read_config_cmd); =20 -int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd *cmd, u16 addr) +int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd *cmd, u16 addr, + const struct atmel_i2c_max_exec_timings *timings) { if (addr >=3D OTP_ZONE_SIZE / 4) return -EINVAL; @@ -132,14 +134,15 @@ int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd = *cmd, u16 addr) =20 atmel_i2c_checksum(cmd); =20 - cmd->msecs =3D MAX_EXEC_TIME_READ; + cmd->msecs =3D timings->max_exec_time_read; cmd->rxsize =3D READ_RSP_SIZE; =20 return 0; } EXPORT_SYMBOL(atmel_i2c_init_read_otp_cmd); =20 -void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd) +void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd, + const struct atmel_i2c_max_exec_timings *timings) { cmd->word_addr =3D COMMAND; cmd->opcode =3D OPCODE_RANDOM; @@ -149,12 +152,13 @@ void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *= cmd) =20 atmel_i2c_checksum(cmd); =20 - cmd->msecs =3D MAX_EXEC_TIME_RANDOM; + cmd->msecs =3D timings->max_exec_time_random; cmd->rxsize =3D RANDOM_RSP_SIZE; } EXPORT_SYMBOL(atmel_i2c_init_random_cmd); =20 -void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid) +void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid, + const struct atmel_i2c_max_exec_timings *timings) { cmd->word_addr =3D COMMAND; cmd->count =3D GENKEY_COUNT; @@ -165,13 +169,14 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *= cmd, u16 keyid) =20 atmel_i2c_checksum(cmd); =20 - cmd->msecs =3D MAX_EXEC_TIME_GENKEY; + cmd->msecs =3D timings->max_exec_time_genkey; cmd->rxsize =3D GENKEY_RSP_SIZE; } EXPORT_SYMBOL(atmel_i2c_init_genkey_cmd); =20 int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, - struct scatterlist *pubkey) + struct scatterlist *pubkey, + const struct atmel_i2c_max_exec_timings *timings) { size_t copied; =20 @@ -196,7 +201,7 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, =20 atmel_i2c_checksum(cmd); =20 - cmd->msecs =3D MAX_EXEC_TIME_ECDH; + cmd->msecs =3D timings->max_exec_time_ecdh; cmd->rxsize =3D ECDH_RSP_SIZE; =20 return 0; @@ -363,6 +368,8 @@ static inline size_t atmel_i2c_wake_token_sz(u32 bus_cl= k_rate) =20 static int device_sanity_check(struct i2c_client *client) { + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; struct atmel_i2c_cmd *cmd; int ret; =20 @@ -370,7 +377,7 @@ static int device_sanity_check(struct i2c_client *clien= t) if (!cmd) return -ENOMEM; =20 - atmel_i2c_init_read_config_cmd(cmd); + atmel_i2c_init_read_config_cmd(cmd, &data->timings); =20 ret =3D atmel_i2c_send_receive(client, cmd); if (ret) diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 70579b438256..5224a62c16c9 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -57,6 +57,19 @@ struct atmel_i2c_cmd { u16 rxsize; } __packed; =20 +struct atmel_i2c_max_exec_timings { + unsigned int max_exec_time_genkey; + unsigned int max_exec_time_ecdh; + unsigned int max_exec_time_random; + unsigned int max_exec_time_read; + unsigned int max_exec_time_write; +}; + +struct atmel_i2c_of_match_data { + const unsigned short *legacy_hwrng; + struct atmel_i2c_max_exec_timings timings; +}; + /* Status/Error codes */ #define STATUS_SIZE 0x04 #define STATUS_NOERR 0x00 @@ -88,12 +101,6 @@ struct atmel_i2c_cmd { /* Wake Low duration */ #define TWLO_USEC 60 =20 -/* Command execution time (milliseconds) */ -#define MAX_EXEC_TIME_ECDH 58 -#define MAX_EXEC_TIME_GENKEY 115 -#define MAX_EXEC_TIME_READ 1 -#define MAX_EXEC_TIME_RANDOM 50 - /* Command opcode */ #define OPCODE_ECDH 0x43 #define OPCODE_GENKEY 0x40 @@ -135,6 +142,7 @@ extern struct atmel_i2c_client_mgmt atmel_i2c_mgmt; * @tfm_count : number of active crypto transformations on i2c c= lient * @hwrng : hold the hardware generated rng * @caps : feature capability of the particular driver + * @data : preinitialized driver data * * Reads and writes from/to the i2c client are sequential. The first byte * transmitted to the device is treated as the byte size. Any attempt to s= end @@ -152,6 +160,7 @@ struct atmel_i2c_client_priv { atomic_t tfm_count ____cacheline_aligned; struct hwrng hwrng; u32 caps; + const struct atmel_i2c_of_match_data *data; }; =20 /** @@ -189,12 +198,17 @@ void atmel_i2c_flush_queue(void); =20 int atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd= *cmd); =20 -void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd); -int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd *cmd, u16 addr); -void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd); -void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid); +void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd, + const struct atmel_i2c_max_exec_timings *timings); +int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd *cmd, u16 addr, + const struct atmel_i2c_max_exec_timings *timings); +void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd, + const struct atmel_i2c_max_exec_timings *timings); +void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid, + const struct atmel_i2c_max_exec_timings *timings); int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, - struct scatterlist *pubkey); + struct scatterlist *pubkey, + const struct atmel_i2c_max_exec_timings *timings); =20 struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap); void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv); diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index ab758c9cd410..febf9891b167 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -40,14 +40,15 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_wor= k_data *work_data, atomic_dec(&i2c_priv->tfm_count); } =20 -static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *dat= a, +static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *buf, size_t max) { - struct atmel_i2c_client_priv *i2c_priv; + struct atmel_i2c_client_priv *i2c_priv =3D container_of(rng, + struct atmel_i2c_client_priv, + hwrng); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; struct atmel_i2c_work_data *work_data; =20 - i2c_priv =3D container_of(rng, struct atmel_i2c_client_priv, hwrng); - /* keep maximum 1 asynchronous read in flight at any time */ if (!atomic_add_unless(&i2c_priv->tfm_count, 1, 1)) return 0; @@ -55,7 +56,7 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrn= g *rng, void *data, if (rng->priv) { work_data =3D (struct atmel_i2c_work_data *)rng->priv; max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); - memcpy(data, &work_data->cmd.data[RSP_DATA_IDX], max); + memcpy(buf, &work_data->cmd.data[RSP_DATA_IDX], max); rng->priv =3D 0; } else { work_data =3D kmalloc_obj(*work_data, GFP_ATOMIC); @@ -69,42 +70,45 @@ static int atmel_sha204a_rng_read_nonblocking(struct hw= rng *rng, void *data, max =3D 0; } =20 - atmel_i2c_init_random_cmd(&work_data->cmd); + atmel_i2c_init_random_cmd(&work_data->cmd, &data->timings); atmel_i2c_enqueue(work_data, atmel_sha204a_rng_done, rng); =20 return max; } =20 -static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t ma= x, +static int atmel_sha204a_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) { - struct atmel_i2c_client_priv *i2c_priv; + struct atmel_i2c_client_priv *i2c_priv =3D container_of(rng, + struct atmel_i2c_client_priv, + hwrng); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; struct atmel_i2c_cmd cmd; int ret; =20 if (!wait) - return atmel_sha204a_rng_read_nonblocking(rng, data, max); - - i2c_priv =3D container_of(rng, struct atmel_i2c_client_priv, hwrng); + return atmel_sha204a_rng_read_nonblocking(rng, buf, max); =20 - atmel_i2c_init_random_cmd(&cmd); + atmel_i2c_init_random_cmd(&cmd, &data->timings); =20 ret =3D atmel_i2c_send_receive(i2c_priv->client, &cmd); if (ret) return ret; =20 max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); - memcpy(data, &cmd.data[RSP_DATA_IDX], max); + memcpy(buf, &cmd.data[RSP_DATA_IDX], max); =20 return max; } =20 static int atmel_sha204a_otp_read(struct i2c_client *client, u16 addr, u8 = *otp) { + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; struct atmel_i2c_cmd cmd; int ret; =20 - ret =3D atmel_i2c_init_read_otp_cmd(&cmd, addr); + ret =3D atmel_i2c_init_read_otp_cmd(&cmd, addr, &data->timings); if (ret < 0) { dev_err(&client->dev, "failed, invalid otp address %04X\n", addr); @@ -164,6 +168,7 @@ static const struct attribute_group atmel_sha204a_group= s =3D { static int atmel_sha204a_probe(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv; + const struct atmel_i2c_of_match_data *data; const unsigned short *quality; int ret; =20 @@ -171,8 +176,15 @@ static int atmel_sha204a_probe(struct i2c_client *clie= nt) if (ret) goto done; =20 - i2c_priv =3D i2c_get_clientdata(client); + data =3D device_get_match_data(&client->dev); + if (!data) { + dev_err(&client->dev, "no match data found via OF or ID table\n"); + ret =3D -ENODEV; + goto done; + } =20 + i2c_priv =3D i2c_get_clientdata(client); + i2c_priv->data =3D data; i2c_priv->caps =3D 0; =20 /* add to client list */ @@ -187,7 +199,7 @@ static int atmel_sha204a_probe(struct i2c_client *clien= t) i2c_priv->hwrng.name =3D dev_name(&client->dev); i2c_priv->hwrng.read =3D atmel_sha204a_rng_read; =20 - quality =3D i2c_get_match_data(client); + quality =3D i2c_priv->data->legacy_hwrng; if (quality) i2c_priv->hwrng.quality =3D *quality; =20 @@ -227,15 +239,34 @@ static void atmel_sha204a_remove(struct i2c_client *c= lient) kfree((void *)i2c_priv->hwrng.priv); } =20 +static const struct atmel_i2c_of_match_data atsha204_match_data =3D { + .timings =3D { + .max_exec_time_genkey =3D 43, + .max_exec_time_random =3D 50, + .max_exec_time_read =3D 4, + .max_exec_time_write =3D 42, + }, + .legacy_hwrng =3D &atsha204_quality, +}; + +static const struct atmel_i2c_of_match_data atsha204a_match_data =3D { + .timings =3D { + .max_exec_time_genkey =3D 43, + .max_exec_time_random =3D 50, + .max_exec_time_read =3D 4, + .max_exec_time_write =3D 42, + }, +}; + static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused =3D= { - { .compatible =3D "atmel,atsha204", .data =3D &atsha204_quality }, - { .compatible =3D "atmel,atsha204a", }, + { .compatible =3D "atmel,atsha204", .data =3D &atsha204_match_data, }, + { .compatible =3D "atmel,atsha204a", .data =3D &atsha204a_match_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); =20 static const struct i2c_device_id atmel_sha204a_id[] =3D { - { "atsha204", (kernel_ulong_t)&atsha204_quality }, + { "atsha204" }, { "atsha204a" }, { /* sentinel */ } }; --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 286D03A6B8B for ; Tue, 12 May 2026 22:44:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625857; cv=none; b=scyjB86m5hSerXKDaXCbLzNNH1tkh53CGNZzcMXeYQSitH26ND0b1+XJgGS3GVpsgo8PwM1dJHqqy8QZRcSjUgztQM0Be/PHR8mIuCXdXahZzSsVMM9E/cQNMnBqbwy5KhnFSEe8LnNGbJ6NnxWLkR5/WirqBnTsN4ft5P0r2WY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625857; c=relaxed/simple; bh=05+QPQQ8N2qADDVDGXqp4BROqhMTJEI1EdOTxvGr640=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IS2SajPKDFSL0iDh4gjv4Qa8zpw+OBJCNwnu62n3fyxP56SPHfc8DdVH+Qkvz/oXFnZpWUFapUizDrK8KsAuv/t7WZu/NMtpMGk6hsX5yNKlc/yNiY7ZjK992lBxUQilhEROpOaGYMcJVaTIuD86wHgCzu2Wbf08AF66cCvGDFk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=NxjO9uGF; arc=none smtp.client-ip=209.85.128.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NxjO9uGF" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-48e69e60063so5387145e9.1 for ; Tue, 12 May 2026 15:44:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625853; x=1779230653; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FW3Lz2dkj/BvPnoX47K8raPJn2eGQ3HHuGdfSzXvUi0=; b=NxjO9uGFBC3wqElNNP/0CeMxivuVDHyT+2Jtb/6yZo2Mm4QVRpRL6jGbl+rc0D6Zue CAWTd76XWiQXvmEifkyqM5jL7q96y7+Ref5ShcXDLjeWLyyUu9BtvlyeBW45I66/UGe5 3u3fxQGKyLjnu+6ihVYHQr0CUCZcNgBokvoUkUssHbPTcQmZbonJcW7NopgW78Ut4enH Hpi3V+sZWtVeQYc9RffMloBvYy4QD4iLvJ3MwKJR17Q8ZjoWhI67F2mpQqMMdx403ktl c2CHDgTfXrh2yxsZoBJnwEW6rUwjRdkEpyS19aMGRNAcRForKrWGLx5C0uhiTwI64z4D XcNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625853; x=1779230653; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FW3Lz2dkj/BvPnoX47K8raPJn2eGQ3HHuGdfSzXvUi0=; b=a2Q4S/nxWH7oJoc9TOzk6lPyw90w0O/CWtMmG7mm3ydgtqRxGcAyH4zNY+8ccUAdzQ 4Pu8vnaEBqHCzG+RjAMUJyB9P3EodPbVepLgEfym7MqpcbJp/gysjFsK/s40NTsm4y/M yA641QBlKaZOpagutqP4ULH9UlUEsxf6sGoiQ5Ll4H0B8BSicIKMVcf/OWBg6FDPJ5bO ehazntfUfIEVF6HBcVCGFe7KJOCxbDW/faec2ETOMvY/Tr+FJp0h9W57uNGAJfn0ip9H Hm9h26pnXTfq0OQbVE2okaDczs32lRCSWf/e1ltRsI0q1MQd+H6kWZJOGqZW9rP1iGdU Xthw== X-Forwarded-Encrypted: i=1; AFNElJ9rn/AfeAQye30SJ5U5nXlh4AnNUzJA+pKqQ/7W1ob/6ifcBj7OMgEDa7uktDsYSapga/p8ydiD4WLoc/8=@vger.kernel.org X-Gm-Message-State: AOJu0YzaX2H/WNnjRML/qUChSzrZHfeBBDOIMGG36Bja4s2/Fo65Ec4n 4G0U3TQCOcbafMXYnCwI/UQsQlmNhvN5pY7maUp+vRtlSPRMq57IKABq X-Gm-Gg: Acq92OFDdxP/fG/Nb90knkfDbv7bRiqSmx5+CIUYi1lTtGjpBt+xwJuvB1fgsiX1jX+ /O7K+GomEY8cka7dcfH0HFPwadaSkqCag3daIAop1iTKbwpY3G7fiyo3dKSjbRMnArCjO2XRfCY ANmOeoC2qIWUq/yTtztMsIA94e6H34vunX7LsoRw28gu4WxRoLmpwTj31hlCR43Cz4z4vvtVivE 8UK4RplUgcxJNbXhqIFIqNdhnf05t6Zo00MBUMeq/VNnUZTpOAQLZ1bUi0vEk19A84x93g/1M9c eP9bIjcTMn3SPoxnVZr/23qk2HfB2IncVWo3/vGmnDtlhr70sOHXKG5vtmaxkkaLKO861uIeb+w XoE/Uoesqwd/UriicbrZYcjIpXNDy/KV+bGK4R2ekq9hsmPvfPnSRT0JGraDTRL5fUj6KYD5cbR CzJNMRE2LXf4rT2x+L85IvurEo7BfoTXlNQN4VKzYox+NmVw51sV4GvX5eoNpF2DZQ5O7M63Jrj w== X-Received: by 2002:a05:600c:3149:b0:485:f1d6:2b1d with SMTP id 5b1f17b1804b1-48fc99a8c2emr4963905e9.0.1778625853300; Tue, 12 May 2026 15:44:13 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:12 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 05/12] crypto: atmel - move RNG support into common i2c core Date: Tue, 12 May 2026 22:43:42 +0000 Message-Id: <20260512224349.64621-6-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the hardware RNG implementation from atmel-sha204a into the shared atmel-i2c core. The ATSHA204(A) and ATECC devices provide compatible RANDOM commands through the common Atmel I2C interface. Consolidate the RNG handling in the core driver and provide a shared atmel_i2c_register_rng() helper for registering the hwrng device. This removes duplicated RNG code from atmel-sha204a and enables RNG support for other compatible Atmel devices, including the ECC family. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 12 ++++ drivers/crypto/atmel-i2c.c | 93 ++++++++++++++++++++++++++ drivers/crypto/atmel-i2c.h | 4 +- drivers/crypto/atmel-sha204a.c | 115 +++++---------------------------- 4 files changed, 123 insertions(+), 101 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 7793f7b4e97e..67fa5975fa7f 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -306,6 +306,13 @@ static int atmel_ecc_probe(struct i2c_client *client) &atmel_i2c_mgmt.i2c_client_list); spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); =20 + /* register rng */ + ret =3D atmel_i2c_register_rng(i2c_priv, &client->dev); + if (ret) { + dev_err(&client->dev, "failed to register hw_random\n"); + goto err_list_del; + } + /* register algorithms */ ret =3D crypto_register_kpp(&atmel_ecdh_nist_p256); if (ret) { @@ -349,6 +356,11 @@ static void atmel_ecc_remove(struct i2c_client *client) atmel_i2c_flush_queue(); =20 crypto_unregister_kpp(&atmel_ecdh_nist_p256); + + if (i2c_priv->hwrng.priv) { + kfree((void *)i2c_priv->hwrng.priv); + i2c_priv->hwrng.priv =3D 0; + } } =20 static const struct atmel_i2c_of_match_data atecc508a_match_data =3D { diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 7fa7cf9ab3c1..d451017171d8 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -208,6 +208,99 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, } EXPORT_SYMBOL(atmel_i2c_init_ecdh_cmd); =20 +static void atmel_i2c_rng_done(struct atmel_i2c_work_data *work_data, + void *areq, int status) +{ + struct atmel_i2c_client_priv *i2c_priv =3D work_data->ctx; + struct hwrng *rng =3D areq; + + if (status) + dev_warn_ratelimited(&i2c_priv->client->dev, + "i2c transaction failed (%d)\n", + status); + + rng->priv =3D (unsigned long)work_data; + atomic_dec(&i2c_priv->tfm_count); +} + +static int atmel_i2c_rng_read_nonblocking(struct hwrng *rng, void *buf, + size_t max) +{ + struct atmel_i2c_client_priv *i2c_priv =3D container_of(rng, + struct atmel_i2c_client_priv, + hwrng); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + struct atmel_i2c_work_data *work_data; + + /* keep maximum 1 asynchronous read in flight at any time */ + if (!atomic_add_unless(&i2c_priv->tfm_count, 1, 1)) + return 0; + + if (rng->priv) { + work_data =3D (struct atmel_i2c_work_data *)rng->priv; + max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); + memcpy(buf, &work_data->cmd.data[RSP_DATA_IDX], max); + rng->priv =3D 0; + } else { + work_data =3D kmalloc_obj(*work_data, GFP_ATOMIC); + if (!work_data) { + atomic_dec(&i2c_priv->tfm_count); + return -ENOMEM; + } + work_data->ctx =3D i2c_priv; + work_data->client =3D i2c_priv->client; + + max =3D 0; + } + + atmel_i2c_init_random_cmd(&work_data->cmd, &data->timings); + atmel_i2c_enqueue(work_data, atmel_i2c_rng_done, rng); + + return max; +} + +static int atmel_i2c_rng_read(struct hwrng *rng, void *buf, size_t max, + bool wait) +{ + struct atmel_i2c_client_priv *i2c_priv =3D container_of(rng, + struct atmel_i2c_client_priv, + hwrng); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + struct atmel_i2c_cmd cmd; + int ret; + + if (!wait) + return atmel_i2c_rng_read_nonblocking(rng, buf, max); + + atmel_i2c_init_random_cmd(&cmd, &data->timings); + + ret =3D atmel_i2c_send_receive(i2c_priv->client, &cmd); + if (ret) + return ret; + + max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); + memcpy(buf, &cmd.data[RSP_DATA_IDX], max); + + return max; +} + +int atmel_i2c_register_rng(struct atmel_i2c_client_priv *i2c_priv, + struct device *dev) +{ + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + + memset(&i2c_priv->hwrng, 0, sizeof(i2c_priv->hwrng)); + + i2c_priv->hwrng.name =3D dev_name(dev); + i2c_priv->hwrng.read =3D atmel_i2c_rng_read; + + if (data->needs_legacy_hwrng) + i2c_priv->hwrng.quality =3D data->needs_legacy_hwrng; + + return devm_hwrng_register(dev, &i2c_priv->hwrng); +} +EXPORT_SYMBOL(atmel_i2c_register_rng); + /* * After wake and after execution of a command, there will be error, statu= s, or * result bytes in the device's output register that can be retrieved by t= he diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 5224a62c16c9..5f6c9ff0cf64 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -66,7 +66,7 @@ struct atmel_i2c_max_exec_timings { }; =20 struct atmel_i2c_of_match_data { - const unsigned short *legacy_hwrng; + const unsigned short needs_legacy_hwrng; struct atmel_i2c_max_exec_timings timings; }; =20 @@ -209,6 +209,8 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cm= d, u16 keyid, int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, struct scatterlist *pubkey, const struct atmel_i2c_max_exec_timings *timings); +int atmel_i2c_register_rng(struct atmel_i2c_client_priv *i2c_priv, + struct device *dev); =20 struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap); void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv); diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index febf9891b167..ae24d8fbabf9 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -19,88 +19,6 @@ #include #include "atmel-i2c.h" =20 -/* - * According to review by Bill Cox [1], the ATSHA204 has very low entropy. - * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/02385= 8.html - */ -static const unsigned short atsha204_quality =3D 1; - -static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data, - void *areq, int status) -{ - struct atmel_i2c_client_priv *i2c_priv =3D work_data->ctx; - struct hwrng *rng =3D areq; - - if (status) - dev_warn_ratelimited(&i2c_priv->client->dev, - "i2c transaction failed (%d)\n", - status); - - rng->priv =3D (unsigned long)work_data; - atomic_dec(&i2c_priv->tfm_count); -} - -static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *buf, - size_t max) -{ - struct atmel_i2c_client_priv *i2c_priv =3D container_of(rng, - struct atmel_i2c_client_priv, - hwrng); - const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; - struct atmel_i2c_work_data *work_data; - - /* keep maximum 1 asynchronous read in flight at any time */ - if (!atomic_add_unless(&i2c_priv->tfm_count, 1, 1)) - return 0; - - if (rng->priv) { - work_data =3D (struct atmel_i2c_work_data *)rng->priv; - max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); - memcpy(buf, &work_data->cmd.data[RSP_DATA_IDX], max); - rng->priv =3D 0; - } else { - work_data =3D kmalloc_obj(*work_data, GFP_ATOMIC); - if (!work_data) { - atomic_dec(&i2c_priv->tfm_count); - return -ENOMEM; - } - work_data->ctx =3D i2c_priv; - work_data->client =3D i2c_priv->client; - - max =3D 0; - } - - atmel_i2c_init_random_cmd(&work_data->cmd, &data->timings); - atmel_i2c_enqueue(work_data, atmel_sha204a_rng_done, rng); - - return max; -} - -static int atmel_sha204a_rng_read(struct hwrng *rng, void *buf, size_t max, - bool wait) -{ - struct atmel_i2c_client_priv *i2c_priv =3D container_of(rng, - struct atmel_i2c_client_priv, - hwrng); - const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; - struct atmel_i2c_cmd cmd; - int ret; - - if (!wait) - return atmel_sha204a_rng_read_nonblocking(rng, buf, max); - - atmel_i2c_init_random_cmd(&cmd, &data->timings); - - ret =3D atmel_i2c_send_receive(i2c_priv->client, &cmd); - if (ret) - return ret; - - max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); - memcpy(buf, &cmd.data[RSP_DATA_IDX], max); - - return max; -} - static int atmel_sha204a_otp_read(struct i2c_client *client, u16 addr, u8 = *otp) { struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); @@ -169,7 +87,6 @@ static int atmel_sha204a_probe(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv; const struct atmel_i2c_of_match_data *data; - const unsigned short *quality; int ret; =20 ret =3D atmel_i2c_probe(client); @@ -193,25 +110,16 @@ static int atmel_sha204a_probe(struct i2c_client *cli= ent) &atmel_i2c_mgmt.i2c_client_list); spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); =20 - /* register rng */ - memset(&i2c_priv->hwrng, 0, sizeof(i2c_priv->hwrng)); - - i2c_priv->hwrng.name =3D dev_name(&client->dev); - i2c_priv->hwrng.read =3D atmel_sha204a_rng_read; - - quality =3D i2c_priv->data->legacy_hwrng; - if (quality) - i2c_priv->hwrng.quality =3D *quality; - - ret =3D devm_hwrng_register(&client->dev, &i2c_priv->hwrng); + ret =3D sysfs_create_group(&client->dev.kobj, &atmel_sha204a_groups); if (ret) { - dev_warn(&client->dev, "failed to register RNG (%d)\n", ret); + dev_err(&client->dev, "failed to register sysfs entry\n"); goto err_list_del; } =20 - ret =3D sysfs_create_group(&client->dev.kobj, &atmel_sha204a_groups); + /* register rng */ + ret =3D atmel_i2c_register_rng(i2c_priv, &client->dev); if (ret) { - dev_err(&client->dev, "failed to register sysfs entry\n"); + dev_err(&client->dev, "failed to register hw_random\n"); goto err_list_del; } =20 @@ -234,9 +142,12 @@ static void atmel_sha204a_remove(struct i2c_client *cl= ient) devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng); atmel_i2c_flush_queue(); =20 - sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups); + if (i2c_priv->hwrng.priv) { + kfree((void *)i2c_priv->hwrng.priv); + i2c_priv->hwrng.priv =3D 0; + } =20 - kfree((void *)i2c_priv->hwrng.priv); + sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups); } =20 static const struct atmel_i2c_of_match_data atsha204_match_data =3D { @@ -246,7 +157,11 @@ static const struct atmel_i2c_of_match_data atsha204_m= atch_data =3D { .max_exec_time_read =3D 4, .max_exec_time_write =3D 42, }, - .legacy_hwrng =3D &atsha204_quality, + /* + * According to review by Bill Cox [1], the ATSHA204 has very low entropy. + * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/0238= 58.html + */ + .needs_legacy_hwrng =3D 1, }; =20 static const struct atmel_i2c_of_match_data atsha204a_match_data =3D { --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C81023A5427 for ; Tue, 12 May 2026 22:44:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625858; cv=none; b=YtDwf2e5583hlHv+r0ysttwAumWrTdVT9moeZAjhyTKK9j9ysUuTq/KZEcR9eJPMbkt7DzMkGcNioxzOh9TniFPRhw6+5BEcyDBr2uAg7zkYAR7pZjBPgyt6gNLB/uYHAJXh+mcD9gYLuXo4KaSufSoHlhrunexpHWUQTNG2m9s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625858; c=relaxed/simple; bh=B+3rCBiSJ9oF1h8AdWvcbGMayUZTFgBtT78aQ/951Ng=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hUtjlObNn7R+g5n6O5X1xldN9cCXa4NspyEudPJ140hb4L59GxSFbV+JnFSP/uQusrX7uE3Vusp5Ba3B68E3RGGrV1AHGP37GYrfohKHSd8dR18rgOezWMbx0eCaxHSYGRxDSuTe+AbsWDYpyyDwhLNuoGcbHRteLO702SC/5UY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Z6tkeNCV; arc=none smtp.client-ip=209.85.221.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Z6tkeNCV" Received: by mail-wr1-f45.google.com with SMTP id ffacd0b85a97d-43d7670826bso484499f8f.3 for ; Tue, 12 May 2026 15:44:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625854; x=1779230654; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Agx9kWGeXoYnLuy6T8nmbJ6vrFvM27r6/mvFennmg1w=; b=Z6tkeNCVQjRA7GCDBeIIVMcapPUmZGdVtDFwqbv9ncqq8E+2jChmXOxt9GoQJk+5wV hwKCP6wLQnLONDdqiUzD86xfk+30xdVJ1/KWYLd1VbdzDVa7Q5vZDTqlBNW4HGNVj/Zd aBiG2YcesqDeeN7deooBWqFgVQTnXABxOuxulF2KbvcOnkDbKsFIJtumdo68JujZLA4Z FOwKFfDLUbZPBIJWTZatWFWZAsoyvaMcD6zZY5wWmBmlCFYDRI6F3R5jPy/wStMoaOFv YAYRqX0bem/dqutcfW8F84wbe15B+3pxC400iqYwY5v82Mv+bfNFkxm6bQ81xczJHgAn FmGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625854; x=1779230654; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Agx9kWGeXoYnLuy6T8nmbJ6vrFvM27r6/mvFennmg1w=; b=A6bu7WMRuQ8QOjauqvYUUj6VhwoFyjU74K+E8I2OEgsmZHu/ojYnLZUqHulwKsf1m4 bRLqHmpN/9h7cdF5i54RaVT4skfy/0cayxdOgB/kLnRBJial0W8TTS/zomdCAdFoUkLH SFSMB69RpwNLwMXfoxEs1cO3SjZuIzWozXMlZclMzOQ19tZ1XqBmry/JS2Z3x95tjJ9h BBzX9AmywvLThjRMntuEgeX3FAHvvpQ2lYzvn6ZHOaelEYri7z1tXArIwIN0gH2/F9mM aqb4EUPiSpzDzyy4zcc2HZYClzb1+vo9LkHEvQ4H53rV95DkicFHTazjggSbIINE6DQS siHg== X-Forwarded-Encrypted: i=1; AFNElJ/J6DlByEM63fUxJWvbkTu/mQ+CVHRALdhmZMeNjU/xkz45FN9nThQjQHYLt/ldf+V/m8kTm5n6Ufc1oVI=@vger.kernel.org X-Gm-Message-State: AOJu0Yz0o/ZfxBTyzV5Xfl7icOHqfUgSH1ogUhMT7nSaLwJ6CUyoZgtH 3vn9CcjUvhcUruMcawfIUHGsW69TmCjYLbxpfd+BTlcaq6C4j8dHJxtx X-Gm-Gg: Acq92OGpST/WReBdUAeBnyxYm1XsleguFwWnLWoKkneuHcBZhIs6/aWpFPpzWtQnT8A rUJLwdgGsH+qx+WKDcPLqnRCCkdSRHNK5epaEeKK/zICdYvJdM4MCCJdsOX8fNfAv5OcNv4OQoP HyzWXRRMgDrm8rGq4ApgN3ypyIgC9oE2hDK1RFiuimwliiv3lNiKXIHPsmjvfzGkXQXow/kVFyZ 79lNiJEbz7qcLkjRfdrY722A3bkF9jujAGdzMpUPcNo6S2tH2M9ollXqUX5pZpdZIOUAIaO718M Rn4gP88YCFZ8BA89XeZN+ix7SpgpT/6Bj4ydgdeAZCcBUNeW8n+xZezt/KnBHGzz2IF6IjGk0Nw KukGJL7QGBFxWouDUdiizNtxzHheqxcWWLvxDjOYxUaAw1rn+kJzq5mS6rcnKLRnT5K47kpORMn xNptqXsJMkB9uzr5h3DgbYR4T7cfKMCN4FdrcbrufLEv3LWEJGIBRfW5v6diNvh7c= X-Received: by 2002:a05:600c:1385:b0:48e:6db5:76e6 with SMTP id 5b1f17b1804b1-48fc99ede8emr4846485e9.2.1778625854276; Tue, 12 May 2026 15:44:14 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:13 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 06/12] crypto: atmel - move EEPROM access support into common i2c core Date: Tue, 12 May 2026 22:43:43 +0000 Message-Id: <20260512224349.64621-7-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move EEPROM read support from atmel-sha204a and atmel-ecc into the shared atmel-i2c core and provide a generic interface for accessing EEPROM zones on compatible Atmel devices. Introduce enum atmel_i2c_eeprom_zones together with per-device EEPROM zone sizing in struct atmel_i2c_of_match_data. Add common helpers for EEPROM readout and sysfs formatting, and convert existing OTP sysfs handling to use the shared infrastructure. This removes duplicated EEPROM access logic from individual drivers and extends support to ECC devices. The common implementation supports CONFIG, OTP, and DATA zones using device-specific layout information supplied via match data tables. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 36 ++++++++ drivers/crypto/atmel-i2c.c | 153 +++++++++++++++++++++++++-------- drivers/crypto/atmel-i2c.h | 30 +++---- drivers/crypto/atmel-sha204a.c | 65 ++++---------- 4 files changed, 186 insertions(+), 98 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 67fa5975fa7f..b5f2d44ec74c 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -23,6 +23,22 @@ #include #include "atmel-i2c.h" =20 +static ssize_t otp_show(struct device *dev, struct device_attribute *attr,= char *buf) +{ + return atmel_i2c_eeprom_display(dev, attr, buf, ATMEL_EEPROM_OTP_ZONE); +} +static DEVICE_ATTR_RO(otp); + +static struct attribute *atmel_ecc508a_attrs[] =3D { + &dev_attr_otp.attr, + NULL +}; + +static const struct attribute_group atmel_ecc508a_groups =3D { + .name =3D "atecc508a", + .attrs =3D atmel_ecc508a_attrs, +}; + /** * struct atmel_ecdh_ctx - transformation context * @client : pointer to i2c client device @@ -306,6 +322,18 @@ static int atmel_ecc_probe(struct i2c_client *client) &atmel_i2c_mgmt.i2c_client_list); spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); =20 + /* EEPROM read out */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + ret =3D -ENODEV; + goto err_list_del; + } + + ret =3D sysfs_create_group(&client->dev.kobj, &atmel_ecc508a_groups); + if (ret) { + dev_err(&client->dev, "failed to register sysfs entry\n"); + goto err_list_del; + } + /* register rng */ ret =3D atmel_i2c_register_rng(i2c_priv, &client->dev); if (ret) { @@ -326,6 +354,7 @@ static int atmel_ecc_probe(struct i2c_client *client) goto done; =20 err_list_del: + sysfs_remove_group(&client->dev.kobj, &atmel_ecc508a_groups); spin_lock(&atmel_i2c_mgmt.i2c_list_lock); list_del(&i2c_priv->i2c_client_list_node); spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); @@ -361,6 +390,8 @@ static void atmel_ecc_remove(struct i2c_client *client) kfree((void *)i2c_priv->hwrng.priv); i2c_priv->hwrng.priv =3D 0; } + + sysfs_remove_group(&client->dev.kobj, &atmel_ecc508a_groups); } =20 static const struct atmel_i2c_of_match_data atecc508a_match_data =3D { @@ -371,6 +402,11 @@ static const struct atmel_i2c_of_match_data atecc508a_= match_data =3D { .max_exec_time_read =3D 1, .max_exec_time_write =3D 42, }, + .eeprom_zone_size =3D { + [ATMEL_EEPROM_CONFIG_ZONE] =3D 128, + [ATMEL_EEPROM_OTP_ZONE] =3D 64, + [ATMEL_EEPROM_DATA_ZONE] =3D 1208 + }, }; =20 static const struct of_device_id atmel_ecc_dt_ids[] =3D { diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index d451017171d8..26863573a10f 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -21,6 +21,15 @@ #include #include "atmel-i2c.h" =20 +#define ATMEL_I2C_COMMAND 0x03 /* packet function */ + +/* Command opcode */ +#define ATMEL_I2C_OPCODE_ECDH 0x43 +#define ATMEL_I2C_OPCODE_GENKEY 0x40 +#define ATMEL_I2C_OPCODE_READ 0x02 +#define ATMEL_I2C_OPCODE_RANDOM 0x1b +#define ATMEL_I2C_OPCODE_WRITE 0x12 + struct atmel_i2c_client_mgmt atmel_i2c_mgmt =3D { .i2c_list_lock =3D __SPIN_LOCK_UNLOCKED(atmel_i2c_mgmt.i2c_list_lock), .i2c_client_list =3D LIST_HEAD_INIT(atmel_i2c_mgmt.i2c_client_list), @@ -96,56 +105,55 @@ struct i2c_client *atmel_i2c_client_alloc(enum atmel_i= 2c_capability cap) } EXPORT_SYMBOL(atmel_i2c_client_alloc); =20 -void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd, - const struct atmel_i2c_max_exec_timings *timings) +static int atmel_i2c_init_read_eeprom_cmd(struct atmel_i2c_cmd *cmd, u16 a= ddr, + enum atmel_i2c_eeprom_zones zone, + const struct atmel_i2c_of_match_data *data) { - cmd->word_addr =3D COMMAND; - cmd->opcode =3D OPCODE_READ; - /* - * Read the word from Configuration zone that contains the lock bytes - * (UserExtra, Selector, LockValue, LockConfig). - */ - cmd->param1 =3D CONFIGURATION_ZONE; - cmd->param2 =3D cpu_to_le16(DEVICE_LOCK_ADDR); - cmd->count =3D READ_COUNT; + const struct atmel_i2c_max_exec_timings *timings =3D &data->timings; + size_t zone_size =3D data->eeprom_zone_size[zone]; + + if (addr > zone_size) + return -EINVAL; + + cmd->word_addr =3D ATMEL_I2C_COMMAND; + cmd->opcode =3D ATMEL_I2C_OPCODE_READ; + cmd->param1 =3D zone; + cmd->param2 =3D cpu_to_le16(addr); + cmd->count =3D ATMEL_I2C_READ_COUNT; =20 atmel_i2c_checksum(cmd); =20 cmd->msecs =3D timings->max_exec_time_read; - cmd->rxsize =3D READ_RSP_SIZE; + cmd->rxsize =3D ATMEL_I2C_READ_RSP_SIZE; + + return 0; } -EXPORT_SYMBOL(atmel_i2c_init_read_config_cmd); =20 -int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd *cmd, u16 addr, - const struct atmel_i2c_max_exec_timings *timings) +void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd, + const struct atmel_i2c_max_exec_timings *timings) { - if (addr >=3D OTP_ZONE_SIZE / 4) - return -EINVAL; - - cmd->word_addr =3D COMMAND; - cmd->opcode =3D OPCODE_READ; + cmd->word_addr =3D ATMEL_I2C_COMMAND; + cmd->opcode =3D ATMEL_I2C_OPCODE_READ; /* - * Read the word from OTP zone that may contain e.g. serial - * numbers or similar if persistently pre-initialized and locked + * Read the word from Configuration zone that contains the lock bytes + * (UserExtra, Selector, LockValue, LockConfig). */ - cmd->param1 =3D OTP_ZONE; - cmd->param2 =3D cpu_to_le16(addr); - cmd->count =3D READ_COUNT; + cmd->param1 =3D CONFIGURATION_ZONE; + cmd->param2 =3D cpu_to_le16(DEVICE_LOCK_ADDR); + cmd->count =3D ATMEL_I2C_READ_COUNT; =20 atmel_i2c_checksum(cmd); =20 cmd->msecs =3D timings->max_exec_time_read; - cmd->rxsize =3D READ_RSP_SIZE; - - return 0; + cmd->rxsize =3D ATMEL_I2C_READ_RSP_SIZE; } -EXPORT_SYMBOL(atmel_i2c_init_read_otp_cmd); +EXPORT_SYMBOL(atmel_i2c_init_read_config_cmd); =20 void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd, const struct atmel_i2c_max_exec_timings *timings) { - cmd->word_addr =3D COMMAND; - cmd->opcode =3D OPCODE_RANDOM; + cmd->word_addr =3D ATMEL_I2C_COMMAND; + cmd->opcode =3D ATMEL_I2C_OPCODE_RANDOM; cmd->param1 =3D 0; cmd->param2 =3D 0; cmd->count =3D RANDOM_COUNT; @@ -160,9 +168,9 @@ EXPORT_SYMBOL(atmel_i2c_init_random_cmd); void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid, const struct atmel_i2c_max_exec_timings *timings) { - cmd->word_addr =3D COMMAND; + cmd->word_addr =3D ATMEL_I2C_COMMAND; cmd->count =3D GENKEY_COUNT; - cmd->opcode =3D OPCODE_GENKEY; + cmd->opcode =3D ATMEL_I2C_OPCODE_GENKEY; cmd->param1 =3D GENKEY_MODE_PRIVATE; /* a random private key will be generated and stored in slot keyID */ cmd->param2 =3D cpu_to_le16(keyid); @@ -180,9 +188,9 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, { size_t copied; =20 - cmd->word_addr =3D COMMAND; + cmd->word_addr =3D ATMEL_I2C_COMMAND; cmd->count =3D ECDH_COUNT; - cmd->opcode =3D OPCODE_ECDH; + cmd->opcode =3D ATMEL_I2C_OPCODE_ECDH; cmd->param1 =3D ECDH_PREFIX_MODE; /* private key slot */ cmd->param2 =3D cpu_to_le16(DATA_SLOT_2); @@ -301,6 +309,81 @@ int atmel_i2c_register_rng(struct atmel_i2c_client_pri= v *i2c_priv, } EXPORT_SYMBOL(atmel_i2c_register_rng); =20 +static int atmel_i2c_eeprom_read(struct i2c_client *client, u16 addr, + enum atmel_i2c_eeprom_zones zone, u8 *buf) +{ + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + struct atmel_i2c_cmd *cmd; + int ret =3D -1; + + cmd =3D kmalloc_obj(*cmd); + if (!cmd) + return -ENOMEM; + + ret =3D atmel_i2c_init_read_eeprom_cmd(cmd, addr, zone, data); + if (ret < 0) { + dev_err(&client->dev, "failed, invalid eeprom address %04X\n", + addr); + goto err; + } + + ret =3D atmel_i2c_send_receive(client, cmd); + if (ret) + goto err; + + if (cmd->data[0] =3D=3D 0xff) { + dev_err(&client->dev, "failed, device not ready\n"); + ret =3D -EINVAL; + goto err; + } + + memcpy(buf, cmd->data + RSP_DATA_IDX, 4); + +err: + kfree(cmd); + return ret; +} + +ssize_t atmel_i2c_eeprom_display(struct device *dev, + struct device_attribute *attr, + char *buf, + enum atmel_i2c_eeprom_zones zone) +{ + struct i2c_client *client =3D to_i2c_client(dev); + const struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(clien= t); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + const size_t *eeprom =3D data->eeprom_zone_size; + u16 block_addr; + u8 *eeprom_buf; + ssize_t len =3D 0; + int i, ret =3D 0; + + eeprom_buf =3D kcalloc(eeprom[zone], sizeof(*eeprom_buf), GFP_KERNEL); + if (!eeprom_buf) + return -ENOMEM; + + for (block_addr =3D 0; block_addr < eeprom[zone] / 4; block_addr++) { + ret =3D atmel_i2c_eeprom_read(client, block_addr, zone, + eeprom_buf + block_addr * 4); + if (ret < 0) { + dev_err(dev, "failed to read %s zone\n", + zone =3D=3D ATMEL_EEPROM_CONFIG_ZONE ? "CONFIG" + : (zone =3D=3D ATMEL_EEPROM_OTP_ZONE ? "OTP" : "DATA")); + goto err; + } + } + + for (i =3D 0; i < eeprom[zone]; i++) + len +=3D sysfs_emit_at(buf, len, "%02X", eeprom_buf[i]); + len +=3D sysfs_emit_at(buf, len, "\n"); + ret =3D len; +err: + kfree(eeprom_buf); + return ret; +} +EXPORT_SYMBOL(atmel_i2c_eeprom_display); + /* * After wake and after execution of a command, there will be error, statu= s, or * result bytes in the device's output register that can be retrieved by t= he diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 5f6c9ff0cf64..e30e0c417de2 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -12,7 +12,6 @@ =20 #define ATMEL_ECC_PRIORITY 300 =20 -#define COMMAND 0x03 /* packet function */ #define SLEEP_TOKEN 0x01 #define WAKE_TOKEN_MAX_SIZE 8 =20 @@ -30,7 +29,7 @@ #define ECDH_RSP_SIZE (32 + CMD_OVERHEAD_SIZE) #define GENKEY_RSP_SIZE (ATMEL_ECC_PUBKEY_SIZE + \ CMD_OVERHEAD_SIZE) -#define READ_RSP_SIZE (4 + CMD_OVERHEAD_SIZE) +#define ATMEL_I2C_READ_RSP_SIZE (4 + CMD_OVERHEAD_SIZE) #define RANDOM_RSP_SIZE (32 + CMD_OVERHEAD_SIZE) #define MAX_RSP_SIZE GENKEY_RSP_SIZE =20 @@ -57,6 +56,13 @@ struct atmel_i2c_cmd { u16 rxsize; } __packed; =20 +/* Definitions for eeprom organization */ +enum atmel_i2c_eeprom_zones { + ATMEL_EEPROM_CONFIG_ZONE =3D 0, + ATMEL_EEPROM_OTP_ZONE =3D 1, + ATMEL_EEPROM_DATA_ZONE =3D 2, +}; + struct atmel_i2c_max_exec_timings { unsigned int max_exec_time_genkey; unsigned int max_exec_time_ecdh; @@ -68,6 +74,7 @@ struct atmel_i2c_max_exec_timings { struct atmel_i2c_of_match_data { const unsigned short needs_legacy_hwrng; struct atmel_i2c_max_exec_timings timings; + size_t eeprom_zone_size[3]; /* all atmel devices have three zones */ }; =20 /* Status/Error codes */ @@ -77,10 +84,6 @@ struct atmel_i2c_of_match_data { =20 /* Definitions for eeprom organization */ #define CONFIGURATION_ZONE 0 -#define OTP_ZONE 1 - -/* Definitions for eeprom zone sizes */ -#define OTP_ZONE_SIZE 64 =20 /* Definitions for Indexes common to all commands */ #define RSP_DATA_IDX 1 /* buffer index of data in response */ @@ -101,14 +104,8 @@ struct atmel_i2c_of_match_data { /* Wake Low duration */ #define TWLO_USEC 60 =20 -/* Command opcode */ -#define OPCODE_ECDH 0x43 -#define OPCODE_GENKEY 0x40 -#define OPCODE_READ 0x02 -#define OPCODE_RANDOM 0x1b - /* Definitions for the READ Command */ -#define READ_COUNT 7 +#define ATMEL_I2C_READ_COUNT 7 =20 /* Definitions for the RANDOM Command */ #define RANDOM_COUNT 7 @@ -200,8 +197,6 @@ int atmel_i2c_send_receive(struct i2c_client *client, s= truct atmel_i2c_cmd *cmd) =20 void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd, const struct atmel_i2c_max_exec_timings *timings); -int atmel_i2c_init_read_otp_cmd(struct atmel_i2c_cmd *cmd, u16 addr, - const struct atmel_i2c_max_exec_timings *timings); void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd, const struct atmel_i2c_max_exec_timings *timings); void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid, @@ -212,6 +207,11 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, int atmel_i2c_register_rng(struct atmel_i2c_client_priv *i2c_priv, struct device *dev); =20 +ssize_t atmel_i2c_eeprom_display(struct device *dev, + struct device_attribute *attr, + char *buf, + enum atmel_i2c_eeprom_zones zone); + struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap); void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv); =20 diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index ae24d8fbabf9..4f10e826e675 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -19,57 +19,10 @@ #include #include "atmel-i2c.h" =20 -static int atmel_sha204a_otp_read(struct i2c_client *client, u16 addr, u8 = *otp) -{ - struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); - const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; - struct atmel_i2c_cmd cmd; - int ret; - - ret =3D atmel_i2c_init_read_otp_cmd(&cmd, addr, &data->timings); - if (ret < 0) { - dev_err(&client->dev, "failed, invalid otp address %04X\n", - addr); - return ret; - } - - ret =3D atmel_i2c_send_receive(client, &cmd); - if (ret < 0) { - dev_err(&client->dev, "failed to read otp at %04X\n", addr); - return ret; - } - - if (cmd.data[0] =3D=3D 0xff) { - dev_err(&client->dev, "failed, device not ready\n"); - return -EIO; - } - - memcpy(otp, cmd.data+1, 4); - - return ret; -} - static ssize_t otp_show(struct device *dev, struct device_attribute *attr, char *buf) { - u16 addr; - u8 otp[OTP_ZONE_SIZE]; - struct i2c_client *client =3D to_i2c_client(dev); - ssize_t len =3D 0; - int i, ret; - - for (addr =3D 0; addr < OTP_ZONE_SIZE / 4; addr++) { - ret =3D atmel_sha204a_otp_read(client, addr, otp + addr * 4); - if (ret < 0) { - dev_err(dev, "failed to read otp zone\n"); - return ret; - } - } - - for (i =3D 0; i < OTP_ZONE_SIZE; i++) - len +=3D sysfs_emit_at(buf, len, "%02X", otp[i]); - len +=3D sysfs_emit_at(buf, len, "\n"); - return len; + return atmel_i2c_eeprom_display(dev, attr, buf, ATMEL_EEPROM_OTP_ZONE); } static DEVICE_ATTR_RO(otp); =20 @@ -110,6 +63,12 @@ static int atmel_sha204a_probe(struct i2c_client *clien= t) &atmel_i2c_mgmt.i2c_client_list); spin_unlock(&atmel_i2c_mgmt.i2c_list_lock); =20 + /* EEPROM read out */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + ret =3D -ENODEV; + goto err_list_del; + } + ret =3D sysfs_create_group(&client->dev.kobj, &atmel_sha204a_groups); if (ret) { dev_err(&client->dev, "failed to register sysfs entry\n"); @@ -157,6 +116,11 @@ static const struct atmel_i2c_of_match_data atsha204_m= atch_data =3D { .max_exec_time_read =3D 4, .max_exec_time_write =3D 42, }, + .eeprom_zone_size =3D { + [ATMEL_EEPROM_CONFIG_ZONE] =3D 88, + [ATMEL_EEPROM_OTP_ZONE] =3D 64, + [ATMEL_EEPROM_DATA_ZONE] =3D 512 + }, /* * According to review by Bill Cox [1], the ATSHA204 has very low entropy. * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/0238= 58.html @@ -171,6 +135,11 @@ static const struct atmel_i2c_of_match_data atsha204a_= match_data =3D { .max_exec_time_read =3D 4, .max_exec_time_write =3D 42, }, + .eeprom_zone_size =3D { + [ATMEL_EEPROM_CONFIG_ZONE] =3D 88, + [ATMEL_EEPROM_OTP_ZONE] =3D 64, + [ATMEL_EEPROM_DATA_ZONE] =3D 512 + }, }; =20 static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused =3D= { --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0CC33A75A6 for ; Tue, 12 May 2026 22:44:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625858; cv=none; b=mvVP14Luy6KEyZ01nrg+4l66xEe/533chqBhvUIbE/Sr2Io8gyEBtEpB4WU9VWDX/ueoWQPkJyDNYur8hDfz68fdzDwh98BIoCuLFv935tZaF9w6zm43lQyCScjpa0rEwRN8nA6Mj11OubNzfWf7jlwaUeo2qJij9UxM4X8jfIQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625858; c=relaxed/simple; bh=QkPnUvjHa1+OtKWGRGtD7MPg6uzHbcQWt5mYvvIiRZI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mSBihHV1nSa49Y1PX2GZYTxuphw0mr/jWf6nWu9kjlK+OOs07uuMft/X7R2IGzU0AsA64mpUwS0PH7WjDFruFj5m3BwQ8QXu1hchk9kTeDf/sqffRz9ac4VN8NSzNwNjggQhVTyhbDBnkw/KiA9Lu1eFY3KAEzUWH1xNOnMjDMk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=OreJbEIC; arc=none smtp.client-ip=209.85.221.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OreJbEIC" Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-43d7828221bso303408f8f.3 for ; Tue, 12 May 2026 15:44:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625855; x=1779230655; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Xgh7Qwrou5qNvOkoF1+XnxYAOb54Zebpq26aOMB+2tM=; b=OreJbEICdABUqThyVYA2XCUTjQMhakLt8klZ6JFCnMmlnIzXOBTTDQYgQhs4IgUq8C DE+iQ1WTj9F6F0Eu8NOzKGAAek47859vl3r5fmdufHe+g8bnpaJ3MT2Yx42zilW4eOU9 lMUJQ0DOJmFpm2f/DphTCpo9WegJUHtOmwtC1NPAhKXm/yS6wiLRlrz9bSz9a9YoVmPO 9U8F7jV0o6yvJquKbWWkwpbG3LkOeNxtijHmvDUFjDfHDsUNaaFpimhlTKVtBJfj6FiG IwSUK5FDF4dBcKIJWZ+4tVl1KPaKeFLNef5nmWxYgcFINpAWzHkheco2VTV1ByznofEx IaIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625855; x=1779230655; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Xgh7Qwrou5qNvOkoF1+XnxYAOb54Zebpq26aOMB+2tM=; b=QYXyzMZC3kRJiZNcpWF5tB1IGMbMyxZL8csTVzVyxr/6ih0aWBz5wvSHN+vPsplQMC yhN+D9LHMLbzBRIshc0gSeeJhqJFUlnyKYnqkDarICynIBKO5fO3TT56OSAzzQf4aotp J+2F0RimSdlrf20DtSLabtk3DVMhoiaHcDiH6eNT4sJfwHdMkX44Ze6lYUDmae+CChiT bSiBM7U+0wai4RUmQx14rzpuSGV24fN0R0HmCyXZ2FFEBO8wo8lHojQI7YmZW8/xJpdx SY6fNuuiGtP/ur5ArO1NpxajzYvKLvudNsPvm3iPG0JyLla+GkcbeEq4aoUMiWqmlOrW bDuQ== X-Forwarded-Encrypted: i=1; AFNElJ+8Hk7MhmkhbivjjepzKrSJd1nI+ox7b7l4xkliguEA1T/PtnxOkumbucZKslOTSY4dga8iJBK1UIW5Xuo=@vger.kernel.org X-Gm-Message-State: AOJu0Yz0z25qc981xLAO6DeQeqJHPkikG98uPUuN5j0+xUZ4rqaRgPAu 8dWY6xep2UgySWW93Atl5p6ExZxZuabVp+O2p9fB+X77uLrQLeZXT3Pc X-Gm-Gg: Acq92OFmcdi7IlAytfPVXWGVzp0EXmNNn5Nvxas1yb9k2+4ZF9muSzIMUV4nS2lDjfN GfHXE0Qe9eeAyO8IoJ1bBpE/JABGfpL5tp68FjI9HDgAxKPhoSaaQNe1bG4PfzTLWlY0B50MCzT R9Zk3MiVTZ/rXPcnhZS6G/ebAXeyu8xcvW+k8GzcT7jK3b6bPXiD+6me4fg6mOiG2zZ7QdmNjat YhYFzPXW1qU0dlBEK/M8X8Jd3QN8qi1GUnNbX/pMdto46fO3b5D1iO4Qsjsu+5ZrtejvNF+yG3b iD5qMldiQxT5lUUBXP0/rnPCLkyEC3+GXF2239hKO+32hde111+r1yTmwDVdzyYsZdZ816p5MYJ QA3u4jo5N8ua6k91mu3wYFu7D4uFdpe2Gl3cCla8gfRFzf2WrzMmygufsl5L8e5skzVfP/fY8Gc w2+SPcn9TPj9acwEKFES/KxlLZYb+npicqbJ7T/c5SNqyRucrpMTMLSsADvK3losk= X-Received: by 2002:a05:600c:1910:b0:487:1fbb:5a28 with SMTP id 5b1f17b1804b1-48fc9a09523mr5008635e9.1.1778625855234; Tue, 12 May 2026 15:44:15 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:14 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 07/12] crypto: atmel - expose CONFIG zone through sysfs Date: Tue, 12 May 2026 22:43:44 +0000 Message-Id: <20260512224349.64621-8-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Expose the CONFIG EEPROM zone through a read-only sysfs attribute for Atmel I2C crypto devices. The CONFIG zone contains device configuration state, including slot configuration and lock status, which is useful for debugging and verifying provisioning state. Reuse the generic EEPROM display helper provided by the Atmel I2C core driver to expose the CONFIG zone for both SHA204A and ECC devices. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 7 +++++++ drivers/crypto/atmel-sha204a.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index b5f2d44ec74c..f08fdf284b60 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -23,6 +23,12 @@ #include #include "atmel-i2c.h" =20 +static ssize_t config_show(struct device *dev, struct device_attribute *at= tr, char *buf) +{ + return atmel_i2c_eeprom_display(dev, attr, buf, ATMEL_EEPROM_CONFIG_ZONE); +} +static DEVICE_ATTR_ADMIN_RO(config); + static ssize_t otp_show(struct device *dev, struct device_attribute *attr,= char *buf) { return atmel_i2c_eeprom_display(dev, attr, buf, ATMEL_EEPROM_OTP_ZONE); @@ -30,6 +36,7 @@ static ssize_t otp_show(struct device *dev, struct device= _attribute *attr, char static DEVICE_ATTR_RO(otp); =20 static struct attribute *atmel_ecc508a_attrs[] =3D { + &dev_attr_config.attr, &dev_attr_otp.attr, NULL }; diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 4f10e826e675..341554b7b7a2 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -19,6 +19,12 @@ #include #include "atmel-i2c.h" =20 +static ssize_t config_show(struct device *dev, struct device_attribute *at= tr, char *buf) +{ + return atmel_i2c_eeprom_display(dev, attr, buf, ATMEL_EEPROM_CONFIG_ZONE); +} +static DEVICE_ATTR_ADMIN_RO(config); + static ssize_t otp_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -27,6 +33,7 @@ static ssize_t otp_show(struct device *dev, static DEVICE_ATTR_RO(otp); =20 static struct attribute *atmel_sha204a_attrs[] =3D { + &dev_attr_config.attr, &dev_attr_otp.attr, NULL }; --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 004C33A5459 for ; Tue, 12 May 2026 22:44:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625859; cv=none; b=NSgKESoIJUzQEaCXNilkKPT27ZmJR//mGp+h7+6iJi5To+73R6GLd4mMPk5TjDLzT0RUUyCTypK21VMIYCjhruqczW4G7ezbG1oSd1SA2ystmm7JApjowBJg2Kc0Qn0JeTXI/ccRAATz2iOh6oh1YlfBWqTaKkYOZxDpG0nYOu4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625859; c=relaxed/simple; bh=t5T0Hhkj/aVb8XuVjne5yDC88G7QnzRDuV8meaJZ9n4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gReyUhdD61iuQyLT728K9RBgJwyK33s6nEexhqodoDsjgFVNvb8THStPiCd1TrG47xXkmipkYBAItUAoWDjkn+Vl3rDkDomdKKE+GF+cmtF2SA1824/EkSwz4dDe3p4qFxxnoC612IlsOHHEzPeSjSr/takZM+LchzEXa6wH0nQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=K+Phiic+; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="K+Phiic+" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-48e69e60063so5387185e9.1 for ; Tue, 12 May 2026 15:44:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625856; x=1779230656; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wdncnFqQOgUiVSEOFhs+0L3Uf5+UCLHNWz3msC+HnSs=; b=K+Phiic+B6gYIUdlBZ58g8732fY/U1zEikvie7QUlf7p44vgjtwLh55ApK7AmG762d urhAB9JlrG7/RSvlwmUNuWyhzuafHL3kERQmAAp8Dnyf6zvLOKDagPcGUhjboUA61FFB ZTko86FcX3CeWgmyMTe59cw9zgjCfZkTGGqLwBPERqmeCW1biTOs6pU4eqQwg7WlsSC1 lt4x6bkYnzbKWc4LpJQUrCpQlgrpFKTaV+JhDl2l+HCborO2rBpV/Y8/j6cA8Sgc0Dq9 Rq+oINIupQPOyCCY8pT7qt6HVwlMAJL449fgVByBT5mx0xNqdj9kgSEsss9P+j3SRq3Z gqGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625856; x=1779230656; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=wdncnFqQOgUiVSEOFhs+0L3Uf5+UCLHNWz3msC+HnSs=; b=aH5d5lEWO8t0+V3Q5MRwuqJofytrnF+eYGf2AiTBfarhc8Lx0mI3nKtVam5OlOseE+ 0xDVZ5okUH9K4zSutq6H1wF89wgBvfaGV1T4QEA5hYgmUe5yYbb7F7AY4fAyfhZosnHQ UPQYoGLxqDfPUU0r8hRg5XQXmLETHEdx3hSPwGi4lODNuL9X+xPJufLgOgONnIJMOD/E kCg6xtlAXTGbdoqTTH1CZZ9GcAWpVOfOEmlWgzXi35/MVNkc9kNzI5nHK2xTN69FBG/f Sv4ihxB96cwrId6U9fBIqbvFou1VTfPDQDJ84wrYUF3lTyzG9nrltuLBkJfbsOpZOwhs Ka/A== X-Forwarded-Encrypted: i=1; AFNElJ9zQzJ/ZHotj3s9P2n7vTJYTxxM9/5PpNNMxaHoxn62D4C1sz71GQXeF0oYbws8Vz0h+CYMmGaLZlVN0nw=@vger.kernel.org X-Gm-Message-State: AOJu0Yxtamy9h0RIkavPcfLspCS6D7hgFtRA1hFWXUruKdqw2nom7qZF uMxjj7C/JYV1jdWerFxwopnS6KfeyKGQqf85eWQisqzhcCNnbIdkX0Xg X-Gm-Gg: Acq92OET+ZDpjVWiMzxgY5VC513AtB6WLe3YAAPmgaOiAVAEXWI/ccc2RpgNetAbcFJ epVRLzYIBR72wKZS93veJSVs8zh4Yd4tZOfyQc3QWro9YT9wThElSYM0Sdbbvl2oHaDIqevhnos RaqgB24nxVUKgZ85grk3mqeh5sMgg7IAyNnNY1Nv2hvOT0Uzkt9eja024bT2IokfCK1w3AUJeaE 9L4jZut3TyDZm9CHg4wo990Zu+mRhQQlB3ErMgipH4o0KfI7UXRBNiPhtuunsiGdUJJjrHZqIWZ vsMASWElL97V68bmiLrtPuV2UWlx9ORlZX0B5eXUpuCj+Ys2+KnW2T5RJwDD+xokTTTG12mgFpa 731t37wO10IMQpq1uBlK699tI8OMEPfN7rmiKiWN7C5ZQVefLFj5+oU44/GViVrOhq/rWhqu8U2 y63hhhrXNCSSpVbhyYrVDzrvbFQdGMWZwhKw3RcmoolMMvczkyqDq9Jl9cDMN4kaQ= X-Received: by 2002:a05:600c:4447:b0:489:1dc6:d6e with SMTP id 5b1f17b1804b1-48fc9a04fa7mr4375945e9.1.1778625856210; Tue, 12 May 2026 15:44:16 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:15 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 08/12] crypto: atmel - move device sanity check to core driver Date: Tue, 12 May 2026 22:43:45 +0000 Message-Id: <20260512224349.64621-9-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the device sanity check implementation into the shared Atmel I2C core driver and reuse the generic EEPROM access helpers for reading the CONFIG zone lock state. This removes duplicate CONFIG zone handling and consolidates common response index and lock state definitions under the Atmel I2C core namespace. Update both SHA204A and ECC drivers to invoke the shared sanity check helper during probe. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 10 ++++++-- drivers/crypto/atmel-i2c.c | 43 ++++++++++++---------------------- drivers/crypto/atmel-i2c.h | 14 +++-------- drivers/crypto/atmel-sha204a.c | 6 +++++ 4 files changed, 32 insertions(+), 41 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index f08fdf284b60..f6d1a9694d63 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -81,7 +81,7 @@ static void atmel_ecdh_done(struct atmel_i2c_work_data *w= ork_data, void *areq, =20 /* copy the shared secret */ copied =3D sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, n_sz), - &cmd->data[RSP_DATA_IDX], n_sz); + &cmd->data[ATMEL_I2C_RSP_DATA_IDX], n_sz); if (copied !=3D n_sz) status =3D -EINVAL; =20 @@ -144,7 +144,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm= , const void *buf, goto free_public_key; =20 /* save the public key */ - memcpy(public_key, &cmd->data[RSP_DATA_IDX], ATMEL_ECC_PUBKEY_SIZE); + memcpy(public_key, &cmd->data[ATMEL_I2C_RSP_DATA_IDX], ATMEL_ECC_PUBKEY_S= IZE); ctx->public_key =3D public_key; =20 kfree(cmd); @@ -323,6 +323,12 @@ static int atmel_ecc_probe(struct i2c_client *client) i2c_priv->data =3D data; i2c_priv->caps =3D BIT(ATMEL_CAP_ECDH); =20 + ret =3D atmel_i2c_device_sanity_check(client); + if (ret) { + dev_err(&client->dev, "failed to read EEPROM, is hardware attached?\n"); + goto done; + } + /* add to client list */ spin_lock(&atmel_i2c_mgmt.i2c_list_lock); list_add_tail(&i2c_priv->i2c_client_list_node, diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 26863573a10f..50b6bce478d2 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -23,6 +23,11 @@ =20 #define ATMEL_I2C_COMMAND 0x03 /* packet function */ =20 +/* Definitions for the device lock state */ +#define ATMEL_I2C_DEVICE_LOCK_ADDR 0x15 +#define ATMEL_I2C_LOCK_VALUE_IDX (ATMEL_I2C_RSP_DATA_IDX + 2) +#define ATMEL_I2C_LOCK_CONFIG_IDX (ATMEL_I2C_RSP_DATA_IDX + 3) + /* Command opcode */ #define ATMEL_I2C_OPCODE_ECDH 0x43 #define ATMEL_I2C_OPCODE_GENKEY 0x40 @@ -129,26 +134,6 @@ static int atmel_i2c_init_read_eeprom_cmd(struct atmel= _i2c_cmd *cmd, u16 addr, return 0; } =20 -void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd, - const struct atmel_i2c_max_exec_timings *timings) -{ - cmd->word_addr =3D ATMEL_I2C_COMMAND; - cmd->opcode =3D ATMEL_I2C_OPCODE_READ; - /* - * Read the word from Configuration zone that contains the lock bytes - * (UserExtra, Selector, LockValue, LockConfig). - */ - cmd->param1 =3D CONFIGURATION_ZONE; - cmd->param2 =3D cpu_to_le16(DEVICE_LOCK_ADDR); - cmd->count =3D ATMEL_I2C_READ_COUNT; - - atmel_i2c_checksum(cmd); - - cmd->msecs =3D timings->max_exec_time_read; - cmd->rxsize =3D ATMEL_I2C_READ_RSP_SIZE; -} -EXPORT_SYMBOL(atmel_i2c_init_read_config_cmd); - void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd, const struct atmel_i2c_max_exec_timings *timings) { @@ -247,7 +232,7 @@ static int atmel_i2c_rng_read_nonblocking(struct hwrng = *rng, void *buf, if (rng->priv) { work_data =3D (struct atmel_i2c_work_data *)rng->priv; max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); - memcpy(buf, &work_data->cmd.data[RSP_DATA_IDX], max); + memcpy(buf, &work_data->cmd.data[ATMEL_I2C_RSP_DATA_IDX], max); rng->priv =3D 0; } else { work_data =3D kmalloc_obj(*work_data, GFP_ATOMIC); @@ -287,7 +272,7 @@ static int atmel_i2c_rng_read(struct hwrng *rng, void *= buf, size_t max, return ret; =20 max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); - memcpy(buf, &cmd.data[RSP_DATA_IDX], max); + memcpy(buf, &cmd.data[ATMEL_I2C_RSP_DATA_IDX], max); =20 return max; } @@ -338,7 +323,7 @@ static int atmel_i2c_eeprom_read(struct i2c_client *cli= ent, u16 addr, goto err; } =20 - memcpy(buf, cmd->data + RSP_DATA_IDX, 4); + memcpy(buf, cmd->data + ATMEL_I2C_RSP_DATA_IDX, 4); =20 err: kfree(cmd); @@ -542,7 +527,7 @@ static inline size_t atmel_i2c_wake_token_sz(u32 bus_cl= k_rate) return DIV_ROUND_UP(no_of_bits, 8); } =20 -static int device_sanity_check(struct i2c_client *client) +int atmel_i2c_device_sanity_check(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; @@ -553,7 +538,8 @@ static int device_sanity_check(struct i2c_client *clien= t) if (!cmd) return -ENOMEM; =20 - atmel_i2c_init_read_config_cmd(cmd, &data->timings); + atmel_i2c_init_read_eeprom_cmd(cmd, ATMEL_I2C_DEVICE_LOCK_ADDR, + ATMEL_EEPROM_CONFIG_ZONE, data); =20 ret =3D atmel_i2c_send_receive(client, cmd); if (ret) @@ -565,8 +551,8 @@ static int device_sanity_check(struct i2c_client *clien= t) * Failure to lock these zones may permit modification of any secret * keys and may lead to other security problems. */ - if (cmd->data[LOCK_CONFIG_IDX] || cmd->data[LOCK_VALUE_IDX]) { - dev_err(&client->dev, "Configuration or Data and OTP zones are unlocked!= \n"); + if (cmd->data[ATMEL_I2C_LOCK_CONFIG_IDX] || cmd->data[ATMEL_I2C_LOCK_VALU= E_IDX]) { + dev_err(&client->dev, "Config, Data and OTP zones are unlocked!\n"); ret =3D -ENOTSUPP; } =20 @@ -575,6 +561,7 @@ static int device_sanity_check(struct i2c_client *clien= t) kfree(cmd); return ret; } +EXPORT_SYMBOL(atmel_i2c_device_sanity_check); =20 void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv) { @@ -633,7 +620,7 @@ int atmel_i2c_probe(struct i2c_client *client) =20 i2c_set_clientdata(client, i2c_priv); =20 - return device_sanity_check(client); + return 0; } EXPORT_SYMBOL(atmel_i2c_probe); =20 diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index e30e0c417de2..2f76e107340e 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -82,18 +82,10 @@ struct atmel_i2c_of_match_data { #define STATUS_NOERR 0x00 #define STATUS_WAKE_SUCCESSFUL 0x11 =20 -/* Definitions for eeprom organization */ -#define CONFIGURATION_ZONE 0 - /* Definitions for Indexes common to all commands */ -#define RSP_DATA_IDX 1 /* buffer index of data in response */ +#define ATMEL_I2C_RSP_DATA_IDX 1 /* buffer index of data in response */ #define DATA_SLOT_2 2 /* used for ECDH private key */ =20 -/* Definitions for the device lock state */ -#define DEVICE_LOCK_ADDR 0x15 -#define LOCK_VALUE_IDX (RSP_DATA_IDX + 2) -#define LOCK_CONFIG_IDX (RSP_DATA_IDX + 3) - /* * Wake High delay to data communication (microseconds). SDA should be sta= ble * high for this entire duration. @@ -195,8 +187,6 @@ void atmel_i2c_flush_queue(void); =20 int atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd= *cmd); =20 -void atmel_i2c_init_read_config_cmd(struct atmel_i2c_cmd *cmd, - const struct atmel_i2c_max_exec_timings *timings); void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *cmd, const struct atmel_i2c_max_exec_timings *timings); void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid, @@ -207,6 +197,8 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, int atmel_i2c_register_rng(struct atmel_i2c_client_priv *i2c_priv, struct device *dev); =20 +int atmel_i2c_device_sanity_check(struct i2c_client *client); + ssize_t atmel_i2c_eeprom_display(struct device *dev, struct device_attribute *attr, char *buf, diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 341554b7b7a2..88726f6ef87c 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -64,6 +64,12 @@ static int atmel_sha204a_probe(struct i2c_client *client) i2c_priv->data =3D data; i2c_priv->caps =3D 0; =20 + ret =3D atmel_i2c_device_sanity_check(client); + if (ret) { + dev_err(&client->dev, "failed to read EEPROM, is hardware attached?\n"); + goto done; + } + /* add to client list */ spin_lock(&atmel_i2c_mgmt.i2c_list_lock); list_add_tail(&i2c_priv->i2c_client_list_node, --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B3BD73A7F46 for ; Tue, 12 May 2026 22:44:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625860; cv=none; b=C/F48ktaKlf6uE3icFHm7YwXvTtiPP8/wf2jTXVAH//q2pecRjF586o1r/NczVOIra/WBtTxLmGOfQymgpXbJFc4Z3ZFM09yf9jqBjbdFMIjIgAOe5lr+nT0fcl8aZlYmqum4ysedOl4UFWC4Fc8Z8Stp8BFsaBqrpCf4JSti+M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625860; c=relaxed/simple; bh=+tAodrGc85aAkcl5jIPb86A/c/K86nen8bhICVysBBU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=H4dSM1MMGGn5stjIR2SaviNnJ60RS9ZzY9rYlfnbWZnOFE+0teI1U+2sIjASSbM4uf8abJWwsrwPrbD/Cf5SdACwYiESvNutLiw9sLaYO+PbWh+7ry25/iDg9Hf1V2wzPGdgfgmdGUsmZ4YNoHxw/XXoj8DO6cpJPCDh13NPkH8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=f7q9d6o6; arc=none smtp.client-ip=209.85.221.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="f7q9d6o6" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-44b729aa7c5so468866f8f.2 for ; Tue, 12 May 2026 15:44:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625857; x=1779230657; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CQMP+CsFbE9KP3qAcxLaIg4zkOxpF/EIB64y6avymrk=; b=f7q9d6o6xF/0PBHgwXStn4URnaiIhHJSswMKhySSvRBK7HY86uVKm9sGMYr2sS1jQr EbDxSb5AHLGPRE1h4dq6qAMlzHD61gD134+NRABfMjaRtOpCTL4gwvCnx2nNdVMuezQE oW24qRiRipSioL5QC3oqYi4ZMnEfkd6uH/Ru/sJOPqiS48OsyNoIi4ya94cUj6bJ+7t0 9UhWJOvXkK6YCnu61ydsEKHCXOxlZuZi9T1Gfs9LebBreWIBN2BpQn83TxAr8NAtHI0X GbWNH9viN6OOkqybZVHh9JaHNrAP08BxsbgbtbHmWaH7i+mVD49x5kc83n3QTLclNxxH BF0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625857; x=1779230657; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=CQMP+CsFbE9KP3qAcxLaIg4zkOxpF/EIB64y6avymrk=; b=fFIhPZb8yLXRjeB7He0hZoaaXhPyh9NLmgqGIAAJVSVWn35A4rNsMGGxmMyGvhwalg AfEnL1FxmqbueTXNVXK+UGCqF7YsotS9SDSajtzTwRDHTiAD0cMmcuAlj9+OR6LZwfkF B28smhnd5+X1wWDwVj6rDzJxDysdz3qcUA4QqeC+LzzAf2vhME0UHyfnajuR+pKtvs2t f3D/GLjP7m+V6eDDBF4Y1Y8AfB3LZHskFJhFApNIDTDRN8o0UHCNP2V9x6aHOaU5RQ2b z1fiSEPAZoteyo4F8HL5avkJ84YeMU5CAec4mfxkn60rdvDmG3gTZh4DthFWNyikgNd3 qmaw== X-Forwarded-Encrypted: i=1; AFNElJ8d8/jp9np0aiA7VT4bWZqHgzztpdmQJ+MtH0Etx/896cYP6DJPnBJzMXkjJ/+EbRGk6cru2IxQZWd5Tk8=@vger.kernel.org X-Gm-Message-State: AOJu0YxyH0TFSVdF7Ke2zSwaruPBTs1g/LuyWK3ZXpm3w7+DcJQw+AAX S/G4VEhrdGclxu+eVyHtymmKV9bebtWqvKMxcStiaeOhBfWkjoon3QrO X-Gm-Gg: Acq92OHl9QNEv/DqOyJ7BGe8Nj2o07MQrU83TGTRRpx1C9mBnzRg/DK31pC9EdiUakj oK2BfVMLj8T+T0y7iF58S5Oixc0KfJAoc+DvExIY/+Ycdov+YRrttMIbHKGJrgtMIcIerXFFxn4 vmXdt1oDzt2nns3Br8f4/SERFKPwhmAkDCZs51XUKXtvB18fEeaQYvvDjzf1WeBq+27S/ONOE5s QGC0JqR6IZ1jfVLigXCFJmACCC0AU3/SvpWAUlEqr92kesxlPz1giRI73ePKYkbHU7xpMizgbup 5Z1KUSfmawImH38lc5lSztsjG3Qde+BxETZdgDEzDu4P685PtbaOcMFCpNKjaVsNR5Dqn5RkICe kMn2i/XKKr5BXKdomD6/3pDGyVlt6J8pgbbaq35yUzFDpJr/QT06ZPgFV3I+DgoC0f1FetBdmxo 6NhNERLIy7ozD38i99zWf3RzqmUTIIUfYQhv4AbsyVcExxWTCv6Q1tYDXATJFRgNSlbU18wWf35 A== X-Received: by 2002:a05:600c:4e8c:b0:489:6c28:dbc9 with SMTP id 5b1f17b1804b1-48fc9a45602mr4727125e9.7.1778625857153; Tue, 12 May 2026 15:44:17 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:16 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 09/12] crypto: atmel - check client data in remove callbacks Date: Tue, 12 May 2026 22:43:46 +0000 Message-Id: <20260512224349.64621-10-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Check the i2c client private data pointer in the remove callbacks of the Atmel ECC and SHA204A drivers before accessing driver state. Move sysfs group removal ahead of the NULL check so cleanup can still proceed even if client data is unavailable. Also downgrade the busy-device warning in the ECC remove path from dev_emerg() to dev_warn(). Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 20 ++++++-------------- drivers/crypto/atmel-sha204a.c | 7 +++++-- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index f6d1a9694d63..9ad6d42b6eef 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -380,19 +380,13 @@ static void atmel_ecc_remove(struct i2c_client *clien= t) { struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); =20 - /* Return EBUSY if i2c client already allocated. */ - if (atomic_read(&i2c_priv->tfm_count)) { - /* - * After we return here, the memory backing the device is freed. - * That happens no matter what the return value of this function - * is because in the Linux device model there is no error - * handling for unbinding a driver. - * If there is still some action pending, it probably involves - * accessing the freed memory. - */ - dev_emerg(&client->dev, "Device is busy, expect memory corruption.\n"); + sysfs_remove_group(&client->dev.kobj, &atmel_ecc508a_groups); + + if (!i2c_priv) return; - } + + if (atomic_read(&i2c_priv->tfm_count)) + dev_warn(&client->dev, "Device is busy, remove it anyhow\n"); =20 atmel_i2c_unregister_client(i2c_priv); atmel_i2c_flush_queue(); @@ -403,8 +397,6 @@ static void atmel_ecc_remove(struct i2c_client *client) kfree((void *)i2c_priv->hwrng.priv); i2c_priv->hwrng.priv =3D 0; } - - sysfs_remove_group(&client->dev.kobj, &atmel_ecc508a_groups); } =20 static const struct atmel_i2c_of_match_data atecc508a_match_data =3D { diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 88726f6ef87c..6a41024ae40d 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -111,6 +111,11 @@ static void atmel_sha204a_remove(struct i2c_client *cl= ient) { struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); =20 + sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups); + + if (!i2c_priv) + return; + devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng); atmel_i2c_flush_queue(); =20 @@ -118,8 +123,6 @@ static void atmel_sha204a_remove(struct i2c_client *cli= ent) kfree((void *)i2c_priv->hwrng.priv); i2c_priv->hwrng.priv =3D 0; } - - sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups); } =20 static const struct atmel_i2c_of_match_data atsha204_match_data =3D { --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C24BF3A7F70 for ; Tue, 12 May 2026 22:44:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625861; cv=none; b=ihbxpFRz+ld34OMOpMO75AqjGXulQhgmN0g26eduKweeb87Ap5m5wrR5WFccL0hP2pfTAkz2LdseKeqWQoT9pwPDE6L0tMJ67mQri45WYwkxji8mbpoUQ6isBoM3kE1HLeeX4yqYmquD2+/aVLGC33gcUjogrp6kJyELs+f8qKc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625861; c=relaxed/simple; bh=pNjGDy2ibmEHOD1uiiJzIxKcFWHcrE+Moas7jjd56Fg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Zn9xalF5564QNroHMlmLGbaicTDJTy4OwKrBwvijdrLc6SuU5/XYhZJwmTlqyxn3TvTclvK6uAFvT577ePXRy30HzEb02eOOkqL6wzYDN3ZapR6WYu7LWjDxRrtel5qeu2lzvwtN/nAZ2qcZuzAV5m2vR4uJ8tT3f6Wli13YN3k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XyBwroy1; arc=none smtp.client-ip=209.85.221.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XyBwroy1" Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-43d7b879691so438217f8f.1 for ; Tue, 12 May 2026 15:44:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625858; x=1779230658; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oiDLQo6LxMnNaRwvgrfh4SktcEegnVe/AK/y3q5hSoE=; b=XyBwroy18RlFO9R1DaVpmWNbxkGVID3TD3d7Aq+qfeq48/5+di28qpO19x/0VtdNmV ihy7e8xXDWBjLaOj8i4k+VKR6pIt8LxCngfD4zU7hpHYQnX3zbZRquAhpTquAlUcGqy5 EhVncpy0Jg8ZcpPiwX0+/LTz5uzVI3QbAW+5wR8EVuasG/B4CrUACI771XJfqIHQLVv0 oMCFl8UqBaLZbL4MRTuEWwcYD3CPKobbs66QdyDfb08C7+Lfbh0jJtIAYk/CjB9SHbb6 qCwev6QZQV6m6JUxtXOKrLatABdad7hdyQaz6sSfcyi8pXohd9vzF6zCxZTc+NyaHh7+ MbIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625858; x=1779230658; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=oiDLQo6LxMnNaRwvgrfh4SktcEegnVe/AK/y3q5hSoE=; b=GIdmyvsp+Qn5+J1CMy8TkYH+eMXJJd3U152xsurehuJu2Xgh18q4MhDCsTdYHChVf2 MuSb7p107JGRpy5Vatel7Z8qQVkBG6LmMwJr1+XPq6aA0YvqG7+GVW3YFgossekRwA+P 52rUaqI1GiSUSjcCQkmAZovLSfw0utIuYGCvNQkDJrEgDj5CgP4iJtQj0zX05o6K2JgO Oqb0nIrQzFalTFZLRj9NSn528VR/MVdK0t3tVUk7LLj8N4YnxkhOVjf/sVU+jaNCgvmn 9tulc2ybO6UqiGvUQHGzHEiF2cZZl+EmXvj/NoITQr7P21d7gh2/lbypmrHKk7wl859X /bdA== X-Forwarded-Encrypted: i=1; AFNElJ/rFpybPHA4MTxuuuOPInoqPw0TqOwoi4+gR7q/Pz7HT7BnITZhRKHCqanMYmCzSnbdKE+TKo3n54HzfZw=@vger.kernel.org X-Gm-Message-State: AOJu0YxUM0s0uf+DStykzzZJ5RPuf+DiTR5vj5waMIcRH0vXjFhplMut ltcLDG4kpjmvS8aKSsvzqc5iBI7f1EKgvNbUHIqWHrAxUDZmleFxEWlP X-Gm-Gg: Acq92OHd+ZtLtyVpiGGMGMrMVqd3LQx7O/6hv4Ld/gTWwHFiif4wJYERhhQYfwFtQL2 ghn/D7lg/qLama5rZp6KxOJmGbf3/W7xkx1H3mEqCHAJJA80m3hLoGRA0Hacncgsm4EtlK5K3ik LJz6V9dKNoM1mvYP5K9NdNTaxsaXe4iKaak7PYRXf3n5fePl8DWEgRPn0EQNn3PLKaCrM79B19K YfWzupoLqALtqalXOrAc+8uXyHVTn26GCs8tuKhUOVkYdgbkgEAdrJ6vLCn5gz3ionZpC0qK4pj v0MRPJkqoQcI6UnZWYIbIjiwKadsw5VQo/lg66fOspiq7YPAfHG33rzPjVF+Wz0w3HF+W/+f1PW 0CRS2AP8u3zDUcvlobvkEZNIaTG+uggvG6nHQnisfMug3AMsR5Zwi3ZCWm6XILTJdflcpPTPQOP c4pI1oBXTBEvI73DUWFo1dOjOoCHHV3f6bjZDz5GusXMndy/AkZTvbK+DgCJM6TLg= X-Received: by 2002:a05:600c:4595:b0:48a:56d4:7274 with SMTP id 5b1f17b1804b1-48fc9a1c617mr4696215e9.3.1778625858129; Tue, 12 May 2026 15:44:18 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:17 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 10/12] crypto: atmel - update workqueue flags and add flush on exit Date: Tue, 12 May 2026 22:43:47 +0000 Message-Id: <20260512224349.64621-11-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Update workqueue initialization to use WQ_MEM_RECLAIM instead of WQ_PERCPU. WQ_MEM_RECLAIM already provides per-CPU execution semantics via a bound workqueue while also ensuring forward progress via a rescue thread. Add a flush_workqueue() call during module exit to ensure all queued work is completed before destroying the workqueue. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-i2c.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 50b6bce478d2..0ec2d768a763 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -626,12 +626,13 @@ EXPORT_SYMBOL(atmel_i2c_probe); =20 static int __init atmel_i2c_init(void) { - atmel_wq =3D alloc_workqueue("atmel_wq", WQ_PERCPU, 0); + atmel_wq =3D alloc_workqueue("atmel_wq", WQ_MEM_RECLAIM, 0); return atmel_wq ? 0 : -ENOMEM; } =20 static void __exit atmel_i2c_exit(void) { + flush_workqueue(atmel_wq); destroy_workqueue(atmel_wq); } =20 --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0691D3A963E for ; Tue, 12 May 2026 22:44:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625863; cv=none; b=Zk8q+HsQixSqJu155jnHQ84bmab5rqE3JGWcj1ebLhkbhiMNRaY9YuBtCVUqFQplIOSPDnMoA27kauDyyfgSW/Ppp3yt5WZqtoknkDBix7CyEK/p/ZLkbkXMZsx3AmC+S59urmMobm03JLuPBFikNv65zn4ahjZDhzhfOstlJO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625863; c=relaxed/simple; bh=ceyEeOtngEw+ZbyYquQDBLoFGjfTeN3o0bWOHhDN1IY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nTqMWqFWtUdVVL+xxyuDeHRf2oXLvrrnDRgGc2DVmSQfsnQzdruM7oAZ7o4GqvcQc2twM4il3RUu0sLzX3G5JkjFl6m3JKnTLVwoD+vXetURdq1Rig+fOAdTCpPPqigwXq3KV1iLin7cb6/ELQNYfwlozR0X6I17U1SFwmJeex8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hUCcAmyT; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hUCcAmyT" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-4493cf2f982so373944f8f.2 for ; Tue, 12 May 2026 15:44:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625859; x=1779230659; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UPGTYowpPc1Ox/XtvXiBTJJQvGISnFodKgzhMsesERc=; b=hUCcAmyTQ/q9aDshH3jLvt+7FuNe0lEW7rcHLq9GJ4n+baGJ6ZknkYPAdKAt9tHETV GDId5KToBJxfds+YZwb9cwT+87oVdqi2Qf+/0XcTeAp9/p+Pp43zcc9dEgWV/yEFuLPP Cv+5Sc2EkV21Z9SFsWa0y/oYJaurvhi1GefI2SWIhN+xe6jz3kJyJTxBUZDxtl73t84x BnjVLtwRLWVS+2es9ftCjig2QNwhdBbkGs9UIR8TP/3iK0+ZquhSNzUTYXtCqTuG3Mkm NOEbqzgETHsYXoS2HH5UsjPQKyIBeQnBWFJdSPPsfLM1ym7jsRCi6p9C87QY/6W9hAjZ 5fJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625859; x=1779230659; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=UPGTYowpPc1Ox/XtvXiBTJJQvGISnFodKgzhMsesERc=; b=UQ8J5zL8TCCSsPE6oiojqH/JR20teLrkPeQ1Un7j5kDM3hMLXnM+j/giNLXERhkJPD engJCsGtHx5bKjHDKLUEGjesGHV1FS3uw05oj2f0b4g0PM+VkaQNmS/bnp7TbOvRIe1I 1eWZ7CF2K//bEtt9LVPNnnZCTcCIHU0MSOdUnLeVuWqphsAu/gyKPI7eKM+VS3fuUQKX fOtW6K6p33NOotx5ZAWBPC53DU+BX0kvziZXOD726C9IXlpPDHQapBCLJ2jFJIvfrvFD FZJmReqI7ZHLZwcWEUxiHcUhTYPOVdKi1GHzu8NhPhIAaSeFNuXQIOVGrEOfZV7uHm66 X3BA== X-Forwarded-Encrypted: i=1; AFNElJ8hZBodQ76S1p73629JqrMF0N7y91ypLCulHijNVjYAThAnUIEKTL1kcqOpqAH1gDAEg5YLBsMge/a2G+M=@vger.kernel.org X-Gm-Message-State: AOJu0YxHBqjRcgr13waeiQk/TFMexqlJVrGqgJZccW1/NBWks0NVVG3L 54ltB40Rb++7j6ekX3nRFm6AVhTMIz7E3x9tqklgGFLYi/JgyESAbwxL X-Gm-Gg: Acq92OGD9uNHqpZymMko2m39plrLNxUsD29xLvc67TcjOY2UpqIu5oRVSa4+8nvOeTo QNTjn89jtBF9bTvVJhqH7NuAgqSJOkvNnXu+4mVVSS+hH+bHCmVrVpKn9XsqhQh1+8m5w2pHiRZ CSKPI1n8AW9kYJYkLmtpPUboPxpmaglPvfIYBoxX4JZ78DVftOyRvpVUf2SB2+h3n4hmKe/p9O1 NxMMhLxcSY7kINouSodS4snsRVcwRAHGhybfv5z2EXvPxqoc+zeueU0l26ubAVEtr72O9HvAbOB 4XfF4FGX4eJNmScjGL/0+xfB281FnUMsXkKO8X9URIKFNLmi0xWALC1Y5D0bIaNG2gfgt1PFZx8 zmV24lSke6dUsMwPagG6FIcZJo8hl7FnT0gY9rnh/7ot4+VsbumBga+IR9MbUQpXUgZ2UEcd8M/ +dhUfHaWPvGztgRuZJ0q74ki8mK/1jlniczfGsB2eS0u9xdtsS5PTdkixzJAObqovHxLjh+wH7d A== X-Received: by 2002:a05:600c:c4b7:b0:48f:c8dd:f91 with SMTP id 5b1f17b1804b1-48fc9a493a1mr3694165e9.6.1778625859137; Tue, 12 May 2026 15:44:19 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:18 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 11/12] crypto: atmel - refactor and localize driver constants Date: Tue, 12 May 2026 22:43:48 +0000 Message-Id: <20260512224349.64621-12-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" After refactoring the client drivers to use the shared atmel-i2c core, many constants and definitions no longer need global visibility. Move command definitions, timing constants, status codes and related helpers from the public header into the local compile unit of the core driver where possible. As part of this cleanup, rename macros and constants to use consistent ATMEL_I2C_* naming and align them with common kernel driver conventions. Also replace remaining hardcoded values with named constants throughout the driver. This is a preparatory cleanup and does not change functionality. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 4 +- drivers/crypto/atmel-i2c.c | 115 +++++++++++++++++++++++++------------ drivers/crypto/atmel-i2c.h | 76 +++++++++--------------- 3 files changed, 108 insertions(+), 87 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 9ad6d42b6eef..ed8c0ce5562b 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -137,7 +137,7 @@ static int atmel_ecdh_set_secret(struct crypto_kpp *tfm= , const void *buf, =20 ctx->do_fallback =3D false; =20 - atmel_i2c_init_genkey_cmd(cmd, DATA_SLOT_2, &data->timings); + atmel_i2c_init_genkey_cmd(cmd, ATMEL_I2C_ECDH_SLOT_DEFAULT, &data->timing= s); =20 ret =3D atmel_i2c_send_receive(ctx->client, cmd); if (ret) @@ -296,7 +296,7 @@ static struct kpp_alg atmel_ecdh_nist_p256 =3D { .cra_flags =3D CRYPTO_ALG_NEED_FALLBACK, .cra_name =3D "ecdh-nist-p256", .cra_driver_name =3D "atmel-ecdh", - .cra_priority =3D ATMEL_ECC_PRIORITY, + .cra_priority =3D ATMEL_I2C_PRIORITY, .cra_module =3D THIS_MODULE, .cra_ctxsize =3D sizeof(struct atmel_ecdh_ctx), }, diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 0ec2d768a763..53aba2f4bedb 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -21,19 +21,62 @@ #include #include "atmel-i2c.h" =20 -#define ATMEL_I2C_COMMAND 0x03 /* packet function */ +#define ATMEL_I2C_COMMAND 0x03 /* packet function */ +#define ATMEL_I2C_SLEEP_TOKEN 0x01 =20 /* Definitions for the device lock state */ -#define ATMEL_I2C_DEVICE_LOCK_ADDR 0x15 -#define ATMEL_I2C_LOCK_VALUE_IDX (ATMEL_I2C_RSP_DATA_IDX + 2) -#define ATMEL_I2C_LOCK_CONFIG_IDX (ATMEL_I2C_RSP_DATA_IDX + 3) +#define ATMEL_I2C_DEVICE_LOCK_ADDR 0x15 +#define ATMEL_I2C_LOCK_VALUE_IDX (ATMEL_I2C_RSP_DATA_IDX + 2) +#define ATMEL_I2C_LOCK_CONFIG_IDX (ATMEL_I2C_RSP_DATA_IDX + 3) + +/* Definitions for the READ Command */ +#define ATMEL_I2C_READ_COUNT ATMEL_I2C_COUNT_OVERHEAD_SIZE +#define ATMEL_I2C_READ_RSP_SIZE (4 + ATMEL_I2C_RSP_OVERHEAD_SIZE) + +/* Definitions for the RANDOM Command */ +#define ATMEL_I2C_RANDOM_COUNT ATMEL_I2C_COUNT_OVERHEAD_SIZE +#define ATMEL_I2C_RNG_BLOCK_SIZE 32 +#define ATMEL_I2C_RANDOM_RSP_SIZE (ATMEL_I2C_RNG_BLOCK_SIZE + \ + ATMEL_I2C_RSP_OVERHEAD_SIZE) +#define ATMEL_I2C_RANDOM_COUNT ATMEL_I2C_COUNT_OVERHEAD_SIZE + +/* Definitions for the GenKey Command */ +#define ATMEL_I2C_GENKEY_COUNT ATMEL_I2C_COUNT_OVERHEAD_SIZE +#define ATMEL_I2C_GENKEY_MODE_PRIVATE 0x04 + +/* Definitions for the ECDH Command */ +#define ATMEL_I2C_ECDH_COUNT 71 +#define ATMEL_I2C_ECDH_RSP_SIZE (32 + ATMEL_I2C_RSP_OVERHEAD_SIZE) +#define ATMEL_I2C_ECDH_PREFIX_MODE 0x00 =20 /* Command opcode */ -#define ATMEL_I2C_OPCODE_ECDH 0x43 -#define ATMEL_I2C_OPCODE_GENKEY 0x40 -#define ATMEL_I2C_OPCODE_READ 0x02 -#define ATMEL_I2C_OPCODE_RANDOM 0x1b -#define ATMEL_I2C_OPCODE_WRITE 0x12 +#define ATMEL_I2C_OPCODE_ECDH 0x43 +#define ATMEL_I2C_OPCODE_GENKEY 0x40 +#define ATMEL_I2C_OPCODE_READ 0x02 +#define ATMEL_I2C_OPCODE_RANDOM 0x1b +#define ATMEL_I2C_OPCODE_WRITE 0x12 + +/* + * Wake High delay to data communication (microseconds). SDA should be sta= ble + * high for this entire duration. + */ +#define ATMEL_I2C_TWHI_MIN 1500 +#define ATMEL_I2C_TWHI_MAX 1550 + +/* Wake Low duration */ +#define ATMEL_I2C_TWLO_USEC 60 + +/* Status/Error codes */ +enum atmel_i2c_error_codes { + ATMEL_STATUS_OK_NOERR =3D 0x00, /* success */ + ATMEL_STATUS_CHECKMAC_OR_VERIFY_MISCOMPARE =3D 0x01, + ATMEL_STATUS_PARSE_ERROR =3D 0x03, + ATMEL_STATUS_ECC_FAULT =3D 0x05, + ATMEL_STATUS_EXECUTION_FAULT =3D 0x0F, + ATMEL_STATUS_OK_WAKE_SUCCESSFULL =3D 0x11, /* success */ + ATMEL_STATUS_WATCHDOG_EXPIRE =3D 0xEE, + ATMEL_STATUS_CRC_ERROR =3D 0xFF, +}; =20 struct atmel_i2c_client_mgmt atmel_i2c_mgmt =3D { .i2c_list_lock =3D __SPIN_LOCK_UNLOCKED(atmel_i2c_mgmt.i2c_list_lock), @@ -45,12 +88,12 @@ static const struct { u8 value; const char *error_text; } error_list[] =3D { - { 0x01, "CheckMac or Verify miscompare" }, - { 0x03, "Parse Error" }, - { 0x05, "ECC Fault" }, - { 0x0F, "Execution Error" }, - { 0xEE, "Watchdog about to expire" }, - { 0xFF, "CRC or other communication error" }, + { ATMEL_STATUS_CHECKMAC_OR_VERIFY_MISCOMPARE, "CheckMac or Verify miscomp= are" }, + { ATMEL_STATUS_PARSE_ERROR, "Parse Error" }, + { ATMEL_STATUS_ECC_FAULT, "ECC Fault" }, + { ATMEL_STATUS_EXECUTION_FAULT, "Execution Error" }, + { ATMEL_STATUS_WATCHDOG_EXPIRE, "Watchdog about to expire" }, + { ATMEL_STATUS_CRC_ERROR, "CRC or other communication error" }, }; =20 /** @@ -65,7 +108,7 @@ static const struct { static void atmel_i2c_checksum(struct atmel_i2c_cmd *cmd) { u8 *data =3D &cmd->count; - size_t len =3D cmd->count - CRC_SIZE; + size_t len =3D cmd->count - ATMEL_I2C_CRC_SIZE; __le16 *__crc16 =3D (__le16 *)(data + len); =20 *__crc16 =3D cpu_to_le16(bitrev16(crc16(0, data, len))); @@ -141,12 +184,12 @@ void atmel_i2c_init_random_cmd(struct atmel_i2c_cmd *= cmd, cmd->opcode =3D ATMEL_I2C_OPCODE_RANDOM; cmd->param1 =3D 0; cmd->param2 =3D 0; - cmd->count =3D RANDOM_COUNT; + cmd->count =3D ATMEL_I2C_RANDOM_COUNT; =20 atmel_i2c_checksum(cmd); =20 cmd->msecs =3D timings->max_exec_time_random; - cmd->rxsize =3D RANDOM_RSP_SIZE; + cmd->rxsize =3D ATMEL_I2C_RANDOM_RSP_SIZE; } EXPORT_SYMBOL(atmel_i2c_init_random_cmd); =20 @@ -154,16 +197,16 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *= cmd, u16 keyid, const struct atmel_i2c_max_exec_timings *timings) { cmd->word_addr =3D ATMEL_I2C_COMMAND; - cmd->count =3D GENKEY_COUNT; + cmd->count =3D ATMEL_I2C_GENKEY_COUNT; cmd->opcode =3D ATMEL_I2C_OPCODE_GENKEY; - cmd->param1 =3D GENKEY_MODE_PRIVATE; + cmd->param1 =3D ATMEL_I2C_GENKEY_MODE_PRIVATE; /* a random private key will be generated and stored in slot keyID */ cmd->param2 =3D cpu_to_le16(keyid); =20 atmel_i2c_checksum(cmd); =20 cmd->msecs =3D timings->max_exec_time_genkey; - cmd->rxsize =3D GENKEY_RSP_SIZE; + cmd->rxsize =3D ATMEL_I2C_GENKEY_RSP_SIZE; } EXPORT_SYMBOL(atmel_i2c_init_genkey_cmd); =20 @@ -174,11 +217,11 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, size_t copied; =20 cmd->word_addr =3D ATMEL_I2C_COMMAND; - cmd->count =3D ECDH_COUNT; + cmd->count =3D ATMEL_I2C_ECDH_COUNT; cmd->opcode =3D ATMEL_I2C_OPCODE_ECDH; - cmd->param1 =3D ECDH_PREFIX_MODE; + cmd->param1 =3D ATMEL_I2C_ECDH_PREFIX_MODE; /* private key slot */ - cmd->param2 =3D cpu_to_le16(DATA_SLOT_2); + cmd->param2 =3D cpu_to_le16(ATMEL_I2C_ECDH_SLOT_DEFAULT); =20 /* * The device only supports NIST P256 ECC keys. The public key size will @@ -195,7 +238,7 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, atmel_i2c_checksum(cmd); =20 cmd->msecs =3D timings->max_exec_time_ecdh; - cmd->rxsize =3D ECDH_RSP_SIZE; + cmd->rxsize =3D ATMEL_I2C_ECDH_RSP_SIZE; =20 return 0; } @@ -231,7 +274,7 @@ static int atmel_i2c_rng_read_nonblocking(struct hwrng = *rng, void *buf, =20 if (rng->priv) { work_data =3D (struct atmel_i2c_work_data *)rng->priv; - max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); + max =3D min(ATMEL_I2C_RANDOM_RSP_SIZE - ATMEL_I2C_RSP_OVERHEAD_SIZE, max= ); memcpy(buf, &work_data->cmd.data[ATMEL_I2C_RSP_DATA_IDX], max); rng->priv =3D 0; } else { @@ -271,7 +314,7 @@ static int atmel_i2c_rng_read(struct hwrng *rng, void *= buf, size_t max, if (ret) return ret; =20 - max =3D min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max); + max =3D min(ATMEL_I2C_RANDOM_RSP_SIZE - ATMEL_I2C_RSP_OVERHEAD_SIZE, max); memcpy(buf, &cmd.data[ATMEL_I2C_RSP_DATA_IDX], max); =20 return max; @@ -323,7 +366,7 @@ static int atmel_i2c_eeprom_read(struct i2c_client *cli= ent, u16 addr, goto err; } =20 - memcpy(buf, cmd->data + ATMEL_I2C_RSP_DATA_IDX, 4); + memcpy(buf, cmd->data + ATMEL_I2C_RSP_DATA_IDX, ATMEL_I2C_STATUS_RSP_SIZE= ); =20 err: kfree(cmd); @@ -381,10 +424,10 @@ static int atmel_i2c_status(struct device *dev, u8 *s= tatus) int i; u8 err_id =3D status[1]; =20 - if (*status !=3D STATUS_SIZE) + if (*status !=3D ATMEL_I2C_STATUS_RSP_SIZE) return 0; =20 - if (err_id =3D=3D STATUS_WAKE_SUCCESSFUL || err_id =3D=3D STATUS_NOERR) + if (err_id =3D=3D ATMEL_STATUS_OK_WAKE_SUCCESSFULL || err_id =3D=3D ATMEL= _STATUS_OK_NOERR) return 0; =20 for (i =3D 0; i < err_list_len; i++) @@ -403,7 +446,7 @@ static int atmel_i2c_status(struct device *dev, u8 *sta= tus) static int atmel_i2c_wakeup(struct i2c_client *client) { struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); - u8 status[STATUS_RSP_SIZE]; + u8 status[ATMEL_I2C_STATUS_RSP_SIZE]; int ret; =20 /* @@ -418,9 +461,9 @@ static int atmel_i2c_wakeup(struct i2c_client *client) * Wait to wake the device. Typical execution times for ecdh and genkey * are around tens of milliseconds. Delta is chosen to 50 microseconds. */ - usleep_range(TWHI_MIN, TWHI_MAX); + usleep_range(ATMEL_I2C_TWHI_MIN, ATMEL_I2C_TWHI_MAX); =20 - ret =3D i2c_master_recv(client, status, STATUS_SIZE); + ret =3D i2c_master_recv(client, status, ATMEL_I2C_STATUS_RSP_SIZE); if (ret < 0) return ret; =20 @@ -429,7 +472,7 @@ static int atmel_i2c_wakeup(struct i2c_client *client) =20 static int atmel_i2c_sleep(struct i2c_client *client) { - u8 sleep =3D SLEEP_TOKEN; + u8 sleep =3D ATMEL_I2C_SLEEP_TOKEN; =20 return i2c_master_send(client, &sleep, 1); } @@ -461,7 +504,7 @@ int atmel_i2c_send_receive(struct i2c_client *client, s= truct atmel_i2c_cmd *cmd) goto err; =20 /* send the command */ - ret =3D i2c_master_send(client, (u8 *)cmd, cmd->count + WORD_ADDR_SIZE); + ret =3D i2c_master_send(client, (u8 *)cmd, cmd->count + ATMEL_I2C_ADDR_SI= ZE); if (ret < 0) goto err; =20 @@ -521,7 +564,7 @@ EXPORT_SYMBOL(atmel_i2c_flush_queue); =20 static inline size_t atmel_i2c_wake_token_sz(u32 bus_clk_rate) { - u32 no_of_bits =3D DIV_ROUND_UP(TWLO_USEC * bus_clk_rate, USEC_PER_SEC); + u32 no_of_bits =3D DIV_ROUND_UP(ATMEL_I2C_TWLO_USEC * bus_clk_rate, USEC_= PER_SEC); =20 /* return the size of the wake_token in bytes */ return DIV_ROUND_UP(no_of_bits, 8); diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 2f76e107340e..20afe2da4f8d 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -10,28 +10,39 @@ #include #include =20 -#define ATMEL_ECC_PRIORITY 300 +#define ATMEL_I2C_PRIORITY 300 =20 -#define SLEEP_TOKEN 0x01 -#define WAKE_TOKEN_MAX_SIZE 8 +#define ATMEL_I2C_WAKE_TOKEN_MAX_SIZE 8 =20 /* Definitions of Data and Command sizes */ -#define WORD_ADDR_SIZE 1 -#define COUNT_SIZE 1 -#define CRC_SIZE 2 -#define CMD_OVERHEAD_SIZE (COUNT_SIZE + CRC_SIZE) +#define ATMEL_I2C_ADDR_SIZE 1 +#define ATMEL_I2C_OPCODE_SIZE 1 +#define ATMEL_I2C_COUNT_SIZE 1 +#define ATMEL_I2C_PARAM1_SIZE 1 +#define ATMEL_I2C_PARAM2_SIZE 2 +#define ATMEL_I2C_CRC_SIZE 2 + +#define ATMEL_I2C_RSP_OVERHEAD_SIZE (ATMEL_I2C_COUNT_SIZE + \ + ATMEL_I2C_CRC_SIZE) +#define ATMEL_I2C_COUNT_OVERHEAD_SIZE (ATMEL_I2C_OPCODE_SIZE + \ + ATMEL_I2C_COUNT_SIZE + \ + ATMEL_I2C_PARAM1_SIZE + \ + ATMEL_I2C_PARAM2_SIZE + \ + ATMEL_I2C_CRC_SIZE) + +/* Definitions for the status Command */ +#define ATMEL_I2C_STATUS_RSP_SIZE 4 =20 /* size in bytes of the n prime */ #define ATMEL_ECC_NIST_P256_N_SIZE 32 #define ATMEL_ECC_PUBKEY_SIZE (2 * ATMEL_ECC_NIST_P256_N_SIZE) +#define ATMEL_I2C_GENKEY_RSP_SIZE (ATMEL_ECC_PUBKEY_SIZE + \ + ATMEL_I2C_RSP_OVERHEAD_SIZE) +#define ATMEL_I2C_MAX_RSP_SIZE ATMEL_I2C_GENKEY_RSP_SIZE =20 -#define STATUS_RSP_SIZE 4 -#define ECDH_RSP_SIZE (32 + CMD_OVERHEAD_SIZE) -#define GENKEY_RSP_SIZE (ATMEL_ECC_PUBKEY_SIZE + \ - CMD_OVERHEAD_SIZE) -#define ATMEL_I2C_READ_RSP_SIZE (4 + CMD_OVERHEAD_SIZE) -#define RANDOM_RSP_SIZE (32 + CMD_OVERHEAD_SIZE) -#define MAX_RSP_SIZE GENKEY_RSP_SIZE +/* Definitions for Indexes common to all commands */ +#define ATMEL_I2C_RSP_DATA_IDX 1 /* buffer index of data in response */ +#define ATMEL_I2C_ECDH_SLOT_DEFAULT 2 =20 /** * atmel_i2c_cmd - structure used for communicating with the device. @@ -51,7 +62,7 @@ struct atmel_i2c_cmd { u8 opcode; u8 param1; __le16 param2; - u8 data[MAX_RSP_SIZE]; + u8 data[ATMEL_I2C_MAX_RSP_SIZE]; u8 msecs; u16 rxsize; } __packed; @@ -77,39 +88,6 @@ struct atmel_i2c_of_match_data { size_t eeprom_zone_size[3]; /* all atmel devices have three zones */ }; =20 -/* Status/Error codes */ -#define STATUS_SIZE 0x04 -#define STATUS_NOERR 0x00 -#define STATUS_WAKE_SUCCESSFUL 0x11 - -/* Definitions for Indexes common to all commands */ -#define ATMEL_I2C_RSP_DATA_IDX 1 /* buffer index of data in response */ -#define DATA_SLOT_2 2 /* used for ECDH private key */ - -/* - * Wake High delay to data communication (microseconds). SDA should be sta= ble - * high for this entire duration. - */ -#define TWHI_MIN 1500 -#define TWHI_MAX 1550 - -/* Wake Low duration */ -#define TWLO_USEC 60 - -/* Definitions for the READ Command */ -#define ATMEL_I2C_READ_COUNT 7 - -/* Definitions for the RANDOM Command */ -#define RANDOM_COUNT 7 - -/* Definitions for the GenKey Command */ -#define GENKEY_COUNT 7 -#define GENKEY_MODE_PRIVATE 0x04 - -/* Definitions for the ECDH Command */ -#define ECDH_COUNT 71 -#define ECDH_PREFIX_MODE 0x00 - /* Used for binding tfm objects to i2c clients. */ enum atmel_i2c_capability { ATMEL_CAP_ECDH =3D 0, @@ -144,7 +122,7 @@ struct atmel_i2c_client_priv { struct i2c_client *client; struct list_head i2c_client_list_node; struct mutex lock; - u8 wake_token[WAKE_TOKEN_MAX_SIZE]; + u8 wake_token[ATMEL_I2C_WAKE_TOKEN_MAX_SIZE]; size_t wake_token_sz; atomic_t tfm_count ____cacheline_aligned; struct hwrng hwrng; --=20 2.53.0 From nobody Fri Jun 12 20:17:38 2026 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E88D13AA4F2 for ; Tue, 12 May 2026 22:44:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625864; cv=none; b=POFmW1Y83BaFx4FwZFRXTswlUbLSjsVdlomgmJ82wgB4YepBMh880SOBg07vg5bWyj6I8VENubXkZpF0LFCPPbdEVVx9YyeMf6hHAA/eJxE7o196QRRmxeapRayzBobUJVEN0JtHyeaswACddIzMaStjm5Kci0rPa4sWfxUvE+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778625864; c=relaxed/simple; bh=eJKjVKHt8qyfrn8BR6FKrg/GzhN3MUN2y8T19uNxbS4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gWn0nUK3PO63QT94m6bF2cS8tw8ilhIBsChKvFoetTniEudv6UjFvjs0J1BY4wvT/YVlRPurQ+pNkDcGjYdFGi+wmDT3N2ywr6IO38lyyrwWXZEHGhcU/YdyJwxrZYyAj/3SnjimLiiL9Ujc1tuqftBnLDgguUDA7bVHy946Yak= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mbepZS4Q; arc=none smtp.client-ip=209.85.221.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mbepZS4Q" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-4493cf2f982so373948f8f.2 for ; Tue, 12 May 2026 15:44:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778625860; x=1779230660; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=XN/bCwjdleUaVQ6snEpRjLv37bWsbUXevhTIRdq6VYs=; b=mbepZS4QYTNkIIphnrCKV0FPRCXHcBChdvaehUdaYnnX30Ic5y57d1pardALy9ln/2 CIUwIDmLyMFqnhSVJrd8QTCWkVpasxFIG3RjYPd+aaoobcgz6pNzpP1tUVaZjkSG5CmI 4DLLd+ztuJpXIV2w+lSChS8w+XtAeYeMVudPDO2oyKioggg8oA5NrO2ZmTEeGzX14XKT cZzXKbmpvMOWnVQPHuVjkxERU9syRSoMMqLO/1xGYAKnwOlxhAl+01+0pQ8EcFmVKDOp iUHJUX1OJamV1z26ZrbdHSQa3YypXr7Sz39S6bQCmkX0MpJxxe1LPLHZo5zhde8+LAvD DlHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778625860; x=1779230660; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=XN/bCwjdleUaVQ6snEpRjLv37bWsbUXevhTIRdq6VYs=; b=W//adzH5m4Q0fREibDAt2IPWJrM01uepdzIqAm8EKGEIaQiis5eCqLE92Kja1/hs+Q 8LZhlOUV35YVzE1n923di8FvDffxeQQD6fdK7viPzCYFnhRUk2on95RjNcxF87dqCElq boslyBpgQGc4XHNki+JKm2sea0ngPD5MdqsGE/MDUMjvvmUicRLu7yQYNO3MWZKIouWS gWDDq9H4X4moGE5R9MgsHx2Ma/obTo6t6OXt4RGT8DYZTSI+DXez/e+jMNheJF1bETXa 54xKrzYg7bax6tYtfIZ7WlyJ6hP84XGqPvp+7/0XlePwpQqmHZ0R47gz1wtcxO5LoCiL fXRQ== X-Forwarded-Encrypted: i=1; AFNElJ9mk3Gbk1Vc65/ixfqMJvUuj3GsKG9Jb6jpd6XJakcrcjJArK7pBhpgKm4DXjWePLjqFOXox0ovhoSOfik=@vger.kernel.org X-Gm-Message-State: AOJu0YzXoHO2K/IAq4Mv318uH1Jjey47JGt17msqmJWLLKNvrEIl3KKE uIHNc3xQI849S144TXDn8x9oQqrKaxo3/qPHIOF4P8R6khB8rGPIjQyp X-Gm-Gg: Acq92OHgM8GpJ2I2pIMSLFhc25lR0jCl3SqFc34GeY9dP+jE6JEh5HbKcAPfLRu7QQw vqpXNasCk4Wal1fCuUqCa/5/6DUCHs5qWClWgxyLs6x/AB5uThHod1TY0RScs7kB3Zv+r9irpya 54kIXX5+Xd8RYTrDl0BQMsM8af8o3AqubWzdWMh9j+rGTTXrmecCc+nUs2ZCmcLGF12TXmHeYQQ 4Cy026PD7jV2lH6PC/SbCHf/LtFDKkSNUtBh+5wJpeYD8BCGxh7NAdEI+c0dg4GV7wM2czL9J8F 5YJ4PSS3tZwDBW7XVEpK66VCMOaO/+58ARESLqHbe1KHKCrGqMCldufKA1x9shOTDjvJ+Km0cDZ FewRJ1JTm76OxJ2aZCa4DWyaIIqagUoSGuv0TX5mAGDRTdw2YFTCn736mH45FQ8J19PLVAIqMn0 hTvP3gI/q/HBo9OnaUsHAUZCZWqFvy0Y1POAUuViEb98dLN9RFUrytxg+YDek1b0g= X-Received: by 2002:a05:600c:19ce:b0:48a:58e1:6cf7 with SMTP id 5b1f17b1804b1-48fc9a362f9mr4060715e9.4.1778625860150; Tue, 12 May 2026 15:44:20 -0700 (PDT) Received: from menon.v.cablecom.net (84-74-0-139.dclient.hispeed.ch. [84.74.0.139]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fce385ea5sm3194025e9.14.2026.05.12.15.44.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 May 2026 15:44:19 -0700 (PDT) From: Lothar Rubusch To: thorsten.blum@linux.dev, herbert@gondor.apana.org.au, davem@davemloft.net, nicolas.ferre@microchip.com, alexandre.belloni@bootlin.com, claudiu.beznea@tuxon.dev Cc: linux-crypto@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, l.rubusch@gmail.com Subject: [PATCH 12/12] crypto: atmel - add SHA256 ahash support Date: Tue, 12 May 2026 22:43:49 +0000 Message-Id: <20260512224349.64621-13-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260512224349.64621-1-l.rubusch@gmail.com> References: <20260512224349.64621-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add SHA256 ahash support for ATSHA204A and ECC based devices using the hardware SHA engine provided by the Atmel secure element devices. Implement common SHA256 request handling in the atmel-i2c core driver, including init, update, final, finup, digest, export and import operations. Scatterlist input is processed using the crypto hash walker. ATSHA204A devices require software-side SHA256 padding according to FIPS 180-4 before submitting the final data blocks to the device. Newer ECC devices instead support a dedicated SHA final command which performs padding internally in hardware. For these devices, the final block length is passed through the command parameter field. The SHA engine requires a strict multi-command transaction sequence: SHA INIT, followed by one or more SHA COMPUTE operations and, on ECC devices, a terminating SHA FINAL operation. The device SHA context is lost if the device enters sleep mode or if unrelated commands are interleaved during the sequence. To support these hardware requirements, split the existing send/receive helper into a low-level transfer helper and a higher level wrapper handling wakeup, sleep and locking. SHA operations keep the device awake and hold the i2c client lock across the complete hash transaction until the final digest has been retrieved. Register the SHA256 ahash algorithm in both atmel-sha204a and atmel-ecc drivers and add capability based client allocation for SHA operations. Signed-off-by: Lothar Rubusch --- drivers/crypto/atmel-ecc.c | 50 +++++- drivers/crypto/atmel-i2c.c | 273 +++++++++++++++++++++++++++++++-- drivers/crypto/atmel-i2c.h | 40 +++++ drivers/crypto/atmel-sha204a.c | 55 ++++++- 4 files changed, 407 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index ed8c0ce5562b..aacf9e8add7a 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -19,10 +19,50 @@ #include #include #include +#include #include #include +#include #include "atmel-i2c.h" =20 +static int atmel_ecc_sha_init_tfm(struct crypto_tfm *tfm) +{ + struct atmel_i2c_sha_ctx *ctx =3D crypto_tfm_ctx(tfm); + + ctx->client =3D atmel_i2c_client_alloc(ATMEL_CAP_SHA); + if (IS_ERR(ctx->client)) { + pr_err("tfm - i2c_client binding failed\n"); + return PTR_ERR(ctx->client); + } + + return 0; +} + +static struct ahash_alg atmel_ecc_sha =3D { + .init =3D atmel_i2c_sha_init, + .update =3D atmel_i2c_sha_update, + .final =3D atmel_i2c_sha_final, + .finup =3D atmel_i2c_sha_finup, + .digest =3D atmel_i2c_sha_digest, + .export =3D atmel_i2c_sha_export, + .import =3D atmel_i2c_sha_import, + .halg =3D { + .digestsize =3D SHA256_DIGEST_SIZE, + .statesize =3D sizeof(struct atmel_i2c_sha_reqctx), + .base =3D { + .cra_name =3D "sha256", + .cra_driver_name =3D "atmel-sha256", + .cra_init =3D atmel_ecc_sha_init_tfm, + .cra_priority =3D ATMEL_I2C_PRIORITY, + .cra_flags =3D CRYPTO_ALG_TYPE_AHASH, + .cra_blocksize =3D SHA256_BLOCK_SIZE, + .cra_ctxsize =3D sizeof(struct atmel_i2c_sha_ctx), + .cra_reqsize =3D sizeof(struct atmel_i2c_sha_reqctx), + .cra_module =3D THIS_MODULE, + } + } +}; + static ssize_t config_show(struct device *dev, struct device_attribute *at= tr, char *buf) { return atmel_i2c_eeprom_display(dev, attr, buf, ATMEL_EEPROM_CONFIG_ZONE); @@ -321,7 +361,7 @@ static int atmel_ecc_probe(struct i2c_client *client) =20 i2c_priv =3D i2c_get_clientdata(client); i2c_priv->data =3D data; - i2c_priv->caps =3D BIT(ATMEL_CAP_ECDH); + i2c_priv->caps =3D BIT(ATMEL_CAP_ECDH) | BIT(ATMEL_CAP_SHA); =20 ret =3D atmel_i2c_device_sanity_check(client); if (ret) { @@ -364,6 +404,12 @@ static int atmel_ecc_probe(struct i2c_client *client) dev_info(&client->dev, "atmel ecc algorithms registered in /proc/crypto\= n"); } =20 + ret =3D crypto_register_ahash(&atmel_ecc_sha); + if (ret) { + dev_err(&client->dev, "SHA256 registration failed\n"); + goto err_list_del; + } + goto done; =20 err_list_del: @@ -392,6 +438,7 @@ static void atmel_ecc_remove(struct i2c_client *client) atmel_i2c_flush_queue(); =20 crypto_unregister_kpp(&atmel_ecdh_nist_p256); + crypto_unregister_ahash(&atmel_ecc_sha); =20 if (i2c_priv->hwrng.priv) { kfree((void *)i2c_priv->hwrng.priv); @@ -405,6 +452,7 @@ static const struct atmel_i2c_of_match_data atecc508a_m= atch_data =3D { .max_exec_time_genkey =3D 115, .max_exec_time_random =3D 23, .max_exec_time_read =3D 1, + .max_exec_time_sha =3D 9, .max_exec_time_write =3D 42, }, .eeprom_zone_size =3D { diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 53aba2f4bedb..cbdc8c0e5aca 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -19,6 +19,10 @@ #include #include #include +#include +#include +#include + #include "atmel-i2c.h" =20 #define ATMEL_I2C_COMMAND 0x03 /* packet function */ @@ -49,12 +53,17 @@ #define ATMEL_I2C_ECDH_RSP_SIZE (32 + ATMEL_I2C_RSP_OVERHEAD_SIZE) #define ATMEL_I2C_ECDH_PREFIX_MODE 0x00 =20 +/* Definitions for the SHA Command */ +#define ATMEL_I2C_SHA_RSP_SIZE (ATMEL_I2C_RSP_OVERHEAD_SIZE + \ + SHA256_DIGEST_SIZE) + /* Command opcode */ #define ATMEL_I2C_OPCODE_ECDH 0x43 #define ATMEL_I2C_OPCODE_GENKEY 0x40 #define ATMEL_I2C_OPCODE_READ 0x02 #define ATMEL_I2C_OPCODE_RANDOM 0x1b #define ATMEL_I2C_OPCODE_WRITE 0x12 +#define ATMEL_I2C_OPCODE_SHA 0x47 =20 /* * Wake High delay to data communication (microseconds). SDA should be sta= ble @@ -244,6 +253,43 @@ int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, } EXPORT_SYMBOL(atmel_i2c_init_ecdh_cmd); =20 +int atmel_i2c_init_sha_cmd(struct atmel_i2c_cmd *cmd, + u8 *challenge, size_t len, + enum atmel_i2c_sha_engine_cmd sha_engine_cmd, + const struct atmel_i2c_max_exec_timings *timings) +{ + cmd->word_addr =3D ATMEL_I2C_COMMAND; + cmd->opcode =3D ATMEL_I2C_OPCODE_SHA; + cmd->param1 =3D sha_engine_cmd; + + cmd->param2 =3D cpu_to_le16(0); + /* + * Starting with the bigger ECCs, the device learned how to do SHA256 + * padding (FIPS 180-4). Since SHA UPDATE always consumes 64B (SHA256 + * block size), the only length needed to communicate is the number of + * used bytes in the final block. For the Atmel ECC series, this is + * passed in the param2. + */ + if (sha_engine_cmd =3D=3D atmel_sha_ecc_end) + cmd->param2 =3D cpu_to_le16(len); + + cmd->count =3D ATMEL_I2C_COUNT_OVERHEAD_SIZE; + if (sha_engine_cmd =3D=3D atmel_sha_init) { + memset(cmd->data, 0, sizeof(cmd->data)); + } else { + memcpy(cmd->data, challenge, len); + cmd->count +=3D len; + } + + atmel_i2c_checksum(cmd); + + cmd->msecs =3D timings->max_exec_time_sha; + cmd->rxsize =3D atmel_i2c_sha_rsp_size[sha_engine_cmd]; + + return 0; +} +EXPORT_SYMBOL(atmel_i2c_init_sha_cmd); + static void atmel_i2c_rng_done(struct atmel_i2c_work_data *work_data, void *areq, int status) { @@ -492,21 +538,15 @@ static int atmel_i2c_sleep(struct i2c_client *client) * counter other than to put the device into sleep or idle mode and then * wake it up again. */ -int atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd= *cmd) +static int _atmel_i2c_send_receive(struct i2c_client *client, + struct atmel_i2c_cmd *cmd) { - struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); int ret; =20 - mutex_lock(&i2c_priv->lock); - - ret =3D atmel_i2c_wakeup(client); - if (ret) - goto err; - /* send the command */ ret =3D i2c_master_send(client, (u8 *)cmd, cmd->count + ATMEL_I2C_ADDR_SI= ZE); if (ret < 0) - goto err; + return ret; =20 /* delay the appropriate amount of time for command to execute */ msleep(cmd->msecs); @@ -514,6 +554,24 @@ int atmel_i2c_send_receive(struct i2c_client *client, = struct atmel_i2c_cmd *cmd) /* receive the response */ ret =3D i2c_master_recv(client, cmd->data, cmd->rxsize); if (ret < 0) + return ret; + + return 0; +} + +int atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd= *cmd) +{ + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(client); + int ret; + + mutex_lock(&i2c_priv->lock); + + ret =3D atmel_i2c_wakeup(client); + if (ret) + goto err; + + ret =3D _atmel_i2c_send_receive(client, cmd); + if (ret) goto err; =20 /* put the device into low-power mode */ @@ -529,6 +587,203 @@ int atmel_i2c_send_receive(struct i2c_client *client,= struct atmel_i2c_cmd *cmd) } EXPORT_SYMBOL(atmel_i2c_send_receive); =20 +int atmel_i2c_sha_init(struct ahash_request *req) +{ + struct atmel_i2c_sha_reqctx *rctx =3D ahash_request_ctx(req); + struct atmel_i2c_sha_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm); + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(ctx->client= ); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + struct atmel_i2c_cmd *cmd; + int ret; + + rctx->bufcnt =3D 0; + rctx->total =3D 0; + rctx->ctx =3D i2c_get_clientdata(ctx->client); + + cmd =3D kmalloc_obj(*cmd); + if (!cmd) + return -ENOMEM; + + /* SHA init */ + ret =3D atmel_i2c_init_sha_cmd(cmd, NULL, 0, atmel_sha_init, &data->timin= gs); + if (ret) + goto err_free; + + mutex_lock(&i2c_priv->lock); + + ret =3D atmel_i2c_wakeup(ctx->client); + if (ret) + goto err; + + ret =3D _atmel_i2c_send_receive(ctx->client, cmd); + if (ret) + goto err; + + /* we keep the lock hold until error out or _sha_final() is called */ + return 0; +err: + mutex_unlock(&i2c_priv->lock); +err_free: + kfree_sensitive(cmd); + return ret; +} +EXPORT_SYMBOL(atmel_i2c_sha_init); + +int atmel_i2c_sha_update(struct ahash_request *req) +{ + struct atmel_i2c_sha_reqctx *rctx =3D ahash_request_ctx(req); + struct atmel_i2c_sha_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm); + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(ctx->client= ); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + struct atmel_i2c_cmd *cmd; + struct crypto_hash_walk walk; + int nbytes, take, copied =3D 0; + const u8 *pdata; + int ret; + + rctx->total +=3D req->nbytes; + + cmd =3D kmalloc_obj(*cmd); + if (!cmd) { + ret =3D -ENOMEM; + goto err_nomem; + } + + /* + * Note, we are actively holding the i2c_priv->lock while the SHA engine + * operates. This covers init, update and final steps. + */ + nbytes =3D crypto_hash_walk_first(req, &walk); + for (; nbytes > 0; nbytes =3D crypto_hash_walk_done(&walk, copied)) { + copied =3D nbytes; + pdata =3D walk.data; + while (copied > 0) { + take =3D min(copied, SHA256_BLOCK_SIZE - rctx->bufcnt); + + memcpy(rctx->buffer + rctx->bufcnt, pdata, take); + pdata +=3D take; + copied -=3D take; + rctx->bufcnt +=3D take; + if (rctx->bufcnt =3D=3D SHA256_BLOCK_SIZE) { + ret =3D atmel_i2c_init_sha_cmd(cmd, rctx->buffer, + SHA256_BLOCK_SIZE, + atmel_sha_compute, + &data->timings); + if (ret) + goto err; + + ret =3D _atmel_i2c_send_receive(ctx->client, cmd); + if (ret) + goto err; + + rctx->bufcnt =3D 0; + } + } + } + + kfree_sensitive(cmd); + return 0; +err: + kfree_sensitive(cmd); +err_nomem: + mutex_unlock(&i2c_priv->lock); + return ret; +} +EXPORT_SYMBOL(atmel_i2c_sha_update); + +int atmel_i2c_sha_final(struct ahash_request *req) +{ + struct atmel_i2c_sha_reqctx *rctx =3D ahash_request_ctx(req); + struct atmel_i2c_sha_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm); + struct atmel_i2c_client_priv *i2c_priv =3D i2c_get_clientdata(ctx->client= ); + const struct atmel_i2c_of_match_data *data =3D i2c_priv->data; + struct atmel_i2c_cmd *cmd; + u8 final_blocks[2 * SHA256_BLOCK_SIZE]; + u32 total_pad; + __be64 bits; + int i, ret =3D 0; + + cmd =3D kmalloc_obj(*cmd); + if (!cmd) { + ret =3D -ENOMEM; + goto err_nomem; + } + + if (data->needs_sha_padding) { + /* + * Determine if padding fits in current block or needs another, + * SHA256 needs 8 bytes for length at the end of a 64-byte block. + */ + memset(final_blocks, 0, sizeof(final_blocks)); + memcpy(final_blocks, rctx->buffer, rctx->bufcnt); + final_blocks[rctx->bufcnt] =3D 0x80; /* pad bit */ + total_pad =3D SHA256_BLOCK_SIZE * (rctx->bufcnt < 56 ? 1 : 2); + bits =3D cpu_to_be64((u64)rctx->total << 3); /* needs num of bits */ + memcpy(final_blocks + total_pad - 8, &bits, 8); + for (i =3D 0; i < total_pad; i +=3D SHA256_BLOCK_SIZE) { + ret =3D atmel_i2c_init_sha_cmd(cmd, final_blocks + i, + SHA256_BLOCK_SIZE, + atmel_sha_compute, &data->timings); + if (ret) + goto err_or_done; + + ret =3D _atmel_i2c_send_receive(ctx->client, cmd); + if (ret) + goto err_or_done; + } + } else { + ret =3D atmel_i2c_init_sha_cmd(cmd, rctx->buffer, rctx->bufcnt, + atmel_sha_ecc_end, &data->timings); + if (ret) + goto err_or_done; + + ret =3D _atmel_i2c_send_receive(ctx->client, cmd); + if (ret) + goto err_or_done; + } + + memcpy(req->result, &cmd->data[ATMEL_I2C_RSP_DATA_IDX], + SHA256_DIGEST_SIZE); + + /* Sleep returns a positive int on success, API requires 0 on success */ + ret =3D atmel_i2c_sleep(ctx->client); + if (ret < 0) + goto err_or_done; + ret =3D 0; +err_or_done: + kfree_sensitive(cmd); +err_nomem: + mutex_unlock(&i2c_priv->lock); + return ret; +} +EXPORT_SYMBOL(atmel_i2c_sha_final); + +int atmel_i2c_sha_finup(struct ahash_request *req) +{ + return atmel_i2c_sha_update(req) ? : atmel_i2c_sha_final(req); +} +EXPORT_SYMBOL(atmel_i2c_sha_finup); + +int atmel_i2c_sha_digest(struct ahash_request *req) +{ + return atmel_i2c_sha_init(req) ? : atmel_i2c_sha_finup(req); +} +EXPORT_SYMBOL(atmel_i2c_sha_digest); + +int atmel_i2c_sha_export(struct ahash_request *req, void *out) +{ + memcpy(out, ahash_request_ctx(req), sizeof(struct atmel_i2c_sha_reqctx)); + return 0; +} +EXPORT_SYMBOL(atmel_i2c_sha_export); + +int atmel_i2c_sha_import(struct ahash_request *req, const void *in) +{ + memcpy(ahash_request_ctx(req), in, sizeof(struct atmel_i2c_sha_reqctx)); + return 0; +} +EXPORT_SYMBOL(atmel_i2c_sha_import); + static void atmel_i2c_work_handler(struct work_struct *work) { struct atmel_i2c_work_data *work_data =3D diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 20afe2da4f8d..e0021d4ea686 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -7,8 +7,11 @@ #ifndef __ATMEL_I2C_H__ #define __ATMEL_I2C_H__ =20 +#include +#include #include #include +#include =20 #define ATMEL_I2C_PRIORITY 300 =20 @@ -79,11 +82,13 @@ struct atmel_i2c_max_exec_timings { unsigned int max_exec_time_ecdh; unsigned int max_exec_time_random; unsigned int max_exec_time_read; + unsigned int max_exec_time_sha; unsigned int max_exec_time_write; }; =20 struct atmel_i2c_of_match_data { const unsigned short needs_legacy_hwrng; + const unsigned short needs_sha_padding; struct atmel_i2c_max_exec_timings timings; size_t eeprom_zone_size[3]; /* all atmel devices have three zones */ }; @@ -91,6 +96,30 @@ struct atmel_i2c_of_match_data { /* Used for binding tfm objects to i2c clients. */ enum atmel_i2c_capability { ATMEL_CAP_ECDH =3D 0, + ATMEL_CAP_SHA, +}; + +enum atmel_i2c_sha_engine_cmd { + atmel_sha_init =3D 0, + atmel_sha_compute, + atmel_sha_ecc_end, +}; + +size_t atmel_i2c_sha_rsp_size[] =3D { + [atmel_sha_init] =3D ATMEL_I2C_STATUS_RSP_SIZE, + [atmel_sha_compute] =3D SHA256_DIGEST_SIZE + ATMEL_I2C_RSP_OVERHEAD_SIZE, + [atmel_sha_ecc_end] =3D SHA256_DIGEST_SIZE + ATMEL_I2C_RSP_OVERHEAD_SIZE, +}; + +struct atmel_i2c_sha_ctx { + struct i2c_client *client; +}; + +struct atmel_i2c_sha_reqctx { + u8 buffer[SHA256_BLOCK_SIZE]; + size_t bufcnt; + size_t total; /* size of full input, needed for padding */ + struct atmel_i2c_client_priv *ctx; }; =20 struct atmel_i2c_client_mgmt { @@ -172,9 +201,20 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *c= md, u16 keyid, int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd, struct scatterlist *pubkey, const struct atmel_i2c_max_exec_timings *timings); +int atmel_i2c_init_sha_cmd(struct atmel_i2c_cmd *cmd, u8 *challenge, size_= t len, + enum atmel_i2c_sha_engine_cmd sha_engine_cmd, + const struct atmel_i2c_max_exec_timings *timings); int atmel_i2c_register_rng(struct atmel_i2c_client_priv *i2c_priv, struct device *dev); =20 +int atmel_i2c_sha_init(struct ahash_request *req); +int atmel_i2c_sha_update(struct ahash_request *req); +int atmel_i2c_sha_final(struct ahash_request *req); +int atmel_i2c_sha_finup(struct ahash_request *req); +int atmel_i2c_sha_digest(struct ahash_request *req); +int atmel_i2c_sha_export(struct ahash_request *req, void *out); +int atmel_i2c_sha_import(struct ahash_request *req, const void *in); + int atmel_i2c_device_sanity_check(struct i2c_client *client); =20 ssize_t atmel_i2c_eeprom_display(struct device *dev, diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index 6a41024ae40d..74535480edeb 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -17,8 +17,48 @@ #include #include #include +#include + #include "atmel-i2c.h" =20 +static int atmel_sha204a_sha_init_tfm(struct crypto_tfm *tfm) +{ + struct atmel_i2c_sha_ctx *ctx =3D crypto_tfm_ctx(tfm); + + ctx->client =3D atmel_i2c_client_alloc(ATMEL_CAP_SHA); + if (IS_ERR(ctx->client)) { + pr_err("tfm - i2c_client binding failed\n"); + return PTR_ERR(ctx->client); + } + + return 0; +} + +static struct ahash_alg atmel_sha204a_sha =3D { + .init =3D atmel_i2c_sha_init, + .update =3D atmel_i2c_sha_update, + .final =3D atmel_i2c_sha_final, + .finup =3D atmel_i2c_sha_finup, + .digest =3D atmel_i2c_sha_digest, + .export =3D atmel_i2c_sha_export, + .import =3D atmel_i2c_sha_import, + .halg =3D { + .digestsize =3D SHA256_DIGEST_SIZE, + .statesize =3D sizeof(struct atmel_i2c_sha_reqctx), + .base =3D { + .cra_name =3D "sha256", + .cra_driver_name =3D "atmel-sha256", + .cra_init =3D atmel_sha204a_sha_init_tfm, + .cra_priority =3D ATMEL_I2C_PRIORITY, + .cra_flags =3D CRYPTO_ALG_TYPE_AHASH, + .cra_blocksize =3D SHA256_BLOCK_SIZE, + .cra_ctxsize =3D sizeof(struct atmel_i2c_sha_ctx), + .cra_reqsize =3D sizeof(struct atmel_i2c_sha_reqctx), + .cra_module =3D THIS_MODULE, + } + } +}; + static ssize_t config_show(struct device *dev, struct device_attribute *at= tr, char *buf) { return atmel_i2c_eeprom_display(dev, attr, buf, ATMEL_EEPROM_CONFIG_ZONE); @@ -62,7 +102,7 @@ static int atmel_sha204a_probe(struct i2c_client *client) =20 i2c_priv =3D i2c_get_clientdata(client); i2c_priv->data =3D data; - i2c_priv->caps =3D 0; + i2c_priv->caps =3D BIT(ATMEL_CAP_SHA); =20 ret =3D atmel_i2c_device_sanity_check(client); if (ret) { @@ -95,6 +135,13 @@ static int atmel_sha204a_probe(struct i2c_client *clien= t) goto err_list_del; } =20 + /* register algorithms */ + ret =3D crypto_register_ahash(&atmel_sha204a_sha); + if (ret) { + dev_err(&client->dev, "SHA256 registration failed\n"); + goto err_list_del; + } + goto done; =20 err_list_del: @@ -119,6 +166,8 @@ static void atmel_sha204a_remove(struct i2c_client *cli= ent) devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng); atmel_i2c_flush_queue(); =20 + crypto_unregister_ahash(&atmel_sha204a_sha); + if (i2c_priv->hwrng.priv) { kfree((void *)i2c_priv->hwrng.priv); i2c_priv->hwrng.priv =3D 0; @@ -130,6 +179,7 @@ static const struct atmel_i2c_of_match_data atsha204_ma= tch_data =3D { .max_exec_time_genkey =3D 43, .max_exec_time_random =3D 50, .max_exec_time_read =3D 4, + .max_exec_time_sha =3D 22, .max_exec_time_write =3D 42, }, .eeprom_zone_size =3D { @@ -142,6 +192,7 @@ static const struct atmel_i2c_of_match_data atsha204_ma= tch_data =3D { * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/0238= 58.html */ .needs_legacy_hwrng =3D 1, + .needs_sha_padding =3D 1, }; =20 static const struct atmel_i2c_of_match_data atsha204a_match_data =3D { @@ -149,6 +200,7 @@ static const struct atmel_i2c_of_match_data atsha204a_m= atch_data =3D { .max_exec_time_genkey =3D 43, .max_exec_time_random =3D 50, .max_exec_time_read =3D 4, + .max_exec_time_sha =3D 22, .max_exec_time_write =3D 42, }, .eeprom_zone_size =3D { @@ -156,6 +208,7 @@ static const struct atmel_i2c_of_match_data atsha204a_m= atch_data =3D { [ATMEL_EEPROM_OTP_ZONE] =3D 64, [ATMEL_EEPROM_DATA_ZONE] =3D 512 }, + .needs_sha_padding =3D 1, }; =20 static const struct of_device_id atmel_sha204a_dt_ids[] __maybe_unused =3D= { --=20 2.53.0