Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework
@ 2026-05-17 18:06 Lothar Rubusch
  2026-05-17 18:06 ` [PATCH] crypto: atmel - add capability-based I2C client selection Lothar Rubusch
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

This patch series introduces a staged refactoring of the Atmel crypto I2C
drivers in preparation for a shared core-based architecture. The goal is to
consolidate I2C client management and selection logic into a common
atmel-i2c core driver while keeping ECC (ECDH) and SHA204A client drivers
functionally separate but interoperating through shared infrastructure.

The series moves existing ECC-specific client tracking into a shared
management structure, relocates allocation and selection logic, and
introduces capability-based filtering for hardware selection. This allows
individual crypto drivers to request hardware clients based on supported
features while still benefiting from a unified least-loaded selection
strategy.

Subsequent patches extend this base by:
- migrating client management fully into the core driver,
- introducing explicit capability advertisement by each hardware client,
- updating ECC and SHA204A drivers to participate in capability-aware allocation,
- and cleaning up probe/remove paths to ensure consistent lifecycle handling.

No functional behavioral changes are intended at this stage beyond internal
refactoring and preparation for future feature expansion. The series is
designed to preserve existing crypto functionality while gradually
centralizing shared logic in the atmel-i2c core layer, reducing duplication
and improving maintainability across all Atmel crypto drivers.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
Lothar Rubusch (12):
  crypto: atmel-ecc - rename driver_data before moving it into atmel-i2c
  crypto: atmel - rename atmel_ecc_driver_data to atmel_i2c_client_mgmt
  crypto: atmel - move i2c client management instance into core driver
  crypto: atmel-ecc - simplify probe error handling
  crypto: atmel - factor out i2c client unregistration helper
  crypto: atmel-sha204a - add i2c hw client list and improve probe error
    handling
  crypto: atmel-sha204a - switch to module_i2c_driver
  crypto: atmel-ecc - switch to module_i2c_driver
  crypto: atmel-ecc - simplify remove path and relax busy handling
  crypto: atmel-sha204a - guard remove path against missing client data
  crypto: atmel - move i2c client selection to core driver
  crypto: atmel - add capability-based I2C client selection

 drivers/crypto/atmel-ecc.c     | 98 ++++++++--------------------------
 drivers/crypto/atmel-i2c.c     | 54 +++++++++++++++++++
 drivers/crypto/atmel-i2c.h     | 12 ++++-
 drivers/crypto/atmel-sha204a.c | 44 +++++++++------
 4 files changed, 115 insertions(+), 93 deletions(-)


base-commit: 6c9dddeb582fde005360f4fe02c760d45ca05fb5
-- 
2.53.0



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] crypto: atmel - add capability-based I2C client selection
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 01/12] crypto: atmel-ecc - rename driver_data before moving it into atmel-i2c Lothar Rubusch
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Add capability filtering to the I2C client allocator to support
feature-aware selection of hardware clients.

Each client now exposes supported features via a capability mask. The
allocator selects only clients matching the requested capability and still
prefers the least-loaded device.

ECC marks ECDH support during probe and requests matching clients during
tfm setup. SHA204A exposes no capabilities for now.

This is preparatory work for upcoming features that will extend hardware
usage beyond a single algorithm type.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c     | 4 +++-
 drivers/crypto/atmel-i2c.c     | 5 ++++-
 drivers/crypto/atmel-i2c.h     | 8 +++++++-
 drivers/crypto/atmel-sha204a.c | 2 ++
 4 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index f877f236552f..0eeee9ae6c48 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -214,7 +214,7 @@ static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm)
 	struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
 
 	ctx->curve_id = ECC_CURVE_NIST_P256;
-	ctx->client = atmel_i2c_client_alloc();
+	ctx->client = 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);
@@ -286,6 +286,8 @@ static int atmel_ecc_probe(struct i2c_client *client)
 
 	i2c_priv = i2c_get_clientdata(client);
 
+	i2c_priv->caps = BIT(ATMEL_CAP_ECDH);
+
 	spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
 	list_add_tail(&i2c_priv->i2c_client_list_node,
 		      &atmel_i2c_mgmt.i2c_client_list);
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index 4beab68997c4..b7ee2ec37531 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -57,7 +57,7 @@ static void atmel_i2c_checksum(struct atmel_i2c_cmd *cmd)
 	*__crc16 = cpu_to_le16(bitrev16(crc16(0, data, len)));
 }
 
-struct i2c_client *atmel_i2c_client_alloc(void)
+struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap)
 {
 	struct atmel_i2c_client_priv *i2c_priv, *min_i2c_priv = NULL;
 	struct i2c_client *client = ERR_PTR(-ENODEV);
@@ -73,6 +73,9 @@ struct i2c_client *atmel_i2c_client_alloc(void)
 
 	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 = atomic_read(&i2c_priv->tfm_count);
 		if (tfm_cnt < min_tfm_cnt) {
 			min_tfm_cnt = tfm_cnt;
diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
index ba5a860011c8..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
 
 /* Used for binding tfm objects to i2c clients. */
+enum atmel_i2c_capability {
+	ATMEL_CAP_ECDH = 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 client
  * @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 send
@@ -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;
 };
 
 /**
@@ -190,7 +196,7 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid);
 int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
 			    struct scatterlist *pubkey);
 
-struct i2c_client *atmel_i2c_client_alloc(void);
+struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap);
 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 923e462ff6b0..1a28c6434669 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 *client)
 
 	i2c_priv = i2c_get_clientdata(client);
 
+	i2c_priv->caps = 0;
+
 	/* add to client list */
 	spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
 	list_add_tail(&i2c_priv->i2c_client_list_node,
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 01/12] crypto: atmel-ecc - rename driver_data before moving it into atmel-i2c
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
  2026-05-17 18:06 ` [PATCH] crypto: atmel - add capability-based I2C client selection Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 02/12] crypto: atmel - rename atmel_ecc_driver_data to atmel_i2c_client_mgmt Lothar Rubusch
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Rename the local driver_data instance to atmel_i2c_mgmt in
preparation for moving the shared I2C client management
infrastructure into the atmel-i2c core driver in a subsequent
change.

No functional changes intended.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 9660f6426a84..c9f798ebf44f 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -23,7 +23,7 @@
 #include <crypto/kpp.h>
 #include "atmel-i2c.h"
 
-static struct atmel_ecc_driver_data driver_data;
+static struct atmel_ecc_driver_data atmel_i2c_mgmt;
 
 /**
  * struct atmel_ecdh_ctx - transformation context
@@ -209,14 +209,14 @@ static struct i2c_client *atmel_ecc_i2c_client_alloc(void)
 	int min_tfm_cnt = INT_MAX;
 	int tfm_cnt;
 
-	spin_lock(&driver_data.i2c_list_lock);
+	spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
 
-	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);
 	}
 
-	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 = atomic_read(&i2c_priv->tfm_count);
 		if (tfm_cnt < min_tfm_cnt) {
@@ -232,7 +232,7 @@ static struct i2c_client *atmel_ecc_i2c_client_alloc(void)
 		client = min_i2c_priv->client;
 	}
 
-	spin_unlock(&driver_data.i2c_list_lock);
+	spin_unlock(&atmel_i2c_mgmt.i2c_list_lock);
 
 	return client;
 }
@@ -323,16 +323,16 @@ static int atmel_ecc_probe(struct i2c_client *client)
 
 	i2c_priv = i2c_get_clientdata(client);
 
-	spin_lock(&driver_data.i2c_list_lock);
+	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);
 
 	ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
 	if (ret) {
-		spin_lock(&driver_data.i2c_list_lock);
+		spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
 		list_del(&i2c_priv->i2c_client_list_node);
-		spin_unlock(&driver_data.i2c_list_lock);
+		spin_unlock(&atmel_i2c_mgmt.i2c_list_lock);
 
 		dev_err(&client->dev, "%s alg registration failed\n",
 			atmel_ecdh_nist_p256.base.cra_driver_name);
@@ -363,9 +363,9 @@ static void atmel_ecc_remove(struct i2c_client *client)
 
 	crypto_unregister_kpp(&atmel_ecdh_nist_p256);
 
-	spin_lock(&driver_data.i2c_list_lock);
+	spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
 	list_del(&i2c_priv->i2c_client_list_node);
-	spin_unlock(&driver_data.i2c_list_lock);
+	spin_unlock(&atmel_i2c_mgmt.i2c_list_lock);
 }
 
 static const struct of_device_id atmel_ecc_dt_ids[] = {
@@ -394,8 +394,8 @@ static struct i2c_driver atmel_ecc_driver = {
 
 static int __init atmel_ecc_init(void)
 {
-	spin_lock_init(&driver_data.i2c_list_lock);
-	INIT_LIST_HEAD(&driver_data.i2c_client_list);
+	spin_lock_init(&atmel_i2c_mgmt.i2c_list_lock);
+	INIT_LIST_HEAD(&atmel_i2c_mgmt.i2c_client_list);
 	return i2c_add_driver(&atmel_ecc_driver);
 }
 
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/12] crypto: atmel - rename atmel_ecc_driver_data to atmel_i2c_client_mgmt
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
  2026-05-17 18:06 ` [PATCH] crypto: atmel - add capability-based I2C client selection Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 01/12] crypto: atmel-ecc - rename driver_data before moving it into atmel-i2c Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 03/12] crypto: atmel - move i2c client management instance into core driver Lothar Rubusch
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Rename struct atmel_ecc_driver_data to atmel_i2c_client_mgmt to reflect its
generic role in shared I2C client tracking and locking.

A subsequent change will move the client management infrastructure into the
atmel-i2c core driver.

No functional changes intended.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 2 +-
 drivers/crypto/atmel-i2c.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index c9f798ebf44f..9feae468b7ff 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -23,7 +23,7 @@
 #include <crypto/kpp.h>
 #include "atmel-i2c.h"
 
-static struct atmel_ecc_driver_data atmel_i2c_mgmt;
+static struct atmel_i2c_client_mgmt atmel_i2c_mgmt;
 
 /**
  * struct atmel_ecdh_ctx - transformation context
diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
index 72f04c15682f..98a79dcae2b6 100644
--- a/drivers/crypto/atmel-i2c.h
+++ b/drivers/crypto/atmel-i2c.h
@@ -115,7 +115,7 @@ struct atmel_i2c_cmd {
 #define ECDH_PREFIX_MODE		0x00
 
 /* 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;
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/12] crypto: atmel - move i2c client management instance into core driver
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (2 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 02/12] crypto: atmel - rename atmel_ecc_driver_data to atmel_i2c_client_mgmt Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 04/12] crypto: atmel-ecc - simplify probe error handling Lothar Rubusch
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Move the atmel_i2c client management instance from the ECC driver into the
atmel-i2c core driver.

This is a preparatory step for consolidating shared I2C client tracking
infrastructure in the core, allowing ECC and SHA204A drivers to operate on
a common management instance.

The symbol is exported via EXPORT_SYMBOL_GPL() and declared extern in the
shared header.

No functional change intended.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 2 --
 drivers/crypto/atmel-i2c.c | 6 ++++++
 drivers/crypto/atmel-i2c.h | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 9feae468b7ff..76fb1d0cf075 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -23,8 +23,6 @@
 #include <crypto/kpp.h>
 #include "atmel-i2c.h"
 
-static struct atmel_i2c_client_mgmt atmel_i2c_mgmt;
-
 /**
  * struct atmel_ecdh_ctx - transformation context
  * @client     : pointer to i2c client device
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index 0e275dbdc8c5..db24f65ae90e 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -21,6 +21,12 @@
 #include <linux/workqueue.h>
 #include "atmel-i2c.h"
 
+struct atmel_i2c_client_mgmt atmel_i2c_mgmt = {
+	.i2c_list_lock = __SPIN_LOCK_UNLOCKED(atmel_i2c_mgmt.i2c_list_lock),
+	.i2c_client_list = LIST_HEAD_INIT(atmel_i2c_mgmt.i2c_client_list),
+};
+EXPORT_SYMBOL_GPL(atmel_i2c_mgmt);
+
 static const struct {
 	u8 value;
 	const char *error_text;
diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
index 98a79dcae2b6..a3385e8f0dc9 100644
--- a/drivers/crypto/atmel-i2c.h
+++ b/drivers/crypto/atmel-i2c.h
@@ -119,6 +119,7 @@ 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;
 
 /**
  * atmel_i2c_client_priv - i2c_client private data
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/12] crypto: atmel-ecc - simplify probe error handling
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (3 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 03/12] crypto: atmel - move i2c client management instance into core driver Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 05/12] crypto: atmel - factor out i2c client unregistration helper Lothar Rubusch
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Replace early return in atmel_ecc_probe() with explicit error handling
using a goto-based cleanup path.

Add comments to clarify client list insertion and algorithm registration
steps.

No functional change intended.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 76fb1d0cf075..696ab1d51fc6 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -328,17 +328,20 @@ static int atmel_ecc_probe(struct i2c_client *client)
 
 	ret = crypto_register_kpp(&atmel_ecdh_nist_p256);
 	if (ret) {
-		spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
-		list_del(&i2c_priv->i2c_client_list_node);
-		spin_unlock(&atmel_i2c_mgmt.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");
 	}
 
 	return ret;
+
+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);
+	return ret;
 }
 
 static void atmel_ecc_remove(struct i2c_client *client)
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/12] crypto: atmel - factor out i2c client unregistration helper
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (4 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 04/12] crypto: atmel-ecc - simplify probe error handling Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 06/12] crypto: atmel-sha204a - add i2c hw client list and improve probe error handling Lothar Rubusch
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Move the i2c client removal logic into a dedicated helper
atmel_i2c_unregister_client() in the atmel-i2c core.

Convert ECC driver remove path to use the new helper and
ensure queue flushing is performed after removing the device
from the shared client list.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 5 ++---
 drivers/crypto/atmel-i2c.c | 9 +++++++++
 drivers/crypto/atmel-i2c.h | 2 ++
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index 696ab1d51fc6..e5dd77008b97 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -364,9 +364,8 @@ static void atmel_ecc_remove(struct i2c_client *client)
 
 	crypto_unregister_kpp(&atmel_ecdh_nist_p256);
 
-	spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
-	list_del(&i2c_priv->i2c_client_list_node);
-	spin_unlock(&atmel_i2c_mgmt.i2c_list_lock);
+	atmel_i2c_flush_queue();
+	atmel_i2c_unregister_client(i2c_priv);
 }
 
 static const struct of_device_id atmel_ecc_dt_ids[] = {
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index db24f65ae90e..861af52d7a88 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -354,6 +354,15 @@ static int device_sanity_check(struct i2c_client *client)
 	return ret;
 }
 
+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 a3385e8f0dc9..43a0c1cfcd94 100644
--- a/drivers/crypto/atmel-i2c.h
+++ b/drivers/crypto/atmel-i2c.h
@@ -190,4 +190,6 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid);
 int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
 			    struct scatterlist *pubkey);
 
+void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv);
+
 #endif /* __ATMEL_I2C_H__ */
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/12] crypto: atmel-sha204a - add i2c hw client list and improve probe error handling
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (5 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 05/12] crypto: atmel - factor out i2c client unregistration helper Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 07/12] crypto: atmel-sha204a - switch to module_i2c_driver Lothar Rubusch
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Add registration of the SHA204A I2C client into the shared atmel_i2c client
management list during probe.

This allows the driver to participate in the common hardware selection
infrastructure used by Atmel crypto devices.

Improve error handling in atmel_sha204a_probe() by ensuring that partial
initialization (hwrng registration or sysfs creation) results in proper
cleanup of the client list entry.

No functional change intended beyond improved lifecycle handling.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-sha204a.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index 6e6ac4770416..cdfdcf2e43a7 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -173,6 +173,13 @@ static int atmel_sha204a_probe(struct i2c_client *client)
 
 	i2c_priv = i2c_get_clientdata(client);
 
+	/* 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));
 
 	i2c_priv->hwrng.name = dev_name(&client->dev);
@@ -183,15 +190,24 @@ static int atmel_sha204a_probe(struct i2c_client *client)
 		i2c_priv->hwrng.quality = *quality;
 
 	ret = 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;
+	}
 
 	ret = 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;
 	}
 
+	return ret;
+
+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);
+
 	return ret;
 }
 
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/12] crypto: atmel-sha204a - switch to module_i2c_driver
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (6 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 06/12] crypto: atmel-sha204a - add i2c hw client list and improve probe error handling Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 08/12] crypto: atmel-ecc " Lothar Rubusch
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Replace custom module init/exit functions with module_i2c_driver() for
driver registration.

Update remove path to unregister the client from the shared I2C management
list before flushing pending work and cleaning up sysfs and hwrng
resources.

No functional change intended.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-sha204a.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index cdfdcf2e43a7..613ed5e7b3f6 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -216,6 +216,8 @@ static void atmel_sha204a_remove(struct i2c_client *client)
 	struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
 
 	devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng);
+
+	atmel_i2c_unregister_client(i2c_priv);
 	atmel_i2c_flush_queue();
 
 	sysfs_remove_group(&client->dev.kobj, &atmel_sha204a_groups);
@@ -246,19 +248,7 @@ static struct i2c_driver atmel_sha204a_driver = {
 	.driver.of_match_table	= atmel_sha204a_dt_ids,
 };
 
-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);
 
 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
 MODULE_DESCRIPTION("Microchip / Atmel SHA204A (I2C) driver");
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/12] crypto: atmel-ecc - switch to module_i2c_driver
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (7 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 07/12] crypto: atmel-sha204a - switch to module_i2c_driver Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 09/12] crypto: atmel-ecc - simplify remove path and relax busy handling Lothar Rubusch
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Replace custom module init/exit functions with module_i2c_driver() for
simplified driver registration.

Initialization of the shared I2C client management structure is handled by
the core driver and no longer performed in the ECC module init path.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index e5dd77008b97..dcfc09d24497 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -392,21 +392,7 @@ static struct i2c_driver atmel_ecc_driver = {
 	.id_table	= atmel_ecc_id,
 };
 
-static int __init atmel_ecc_init(void)
-{
-	spin_lock_init(&atmel_i2c_mgmt.i2c_list_lock);
-	INIT_LIST_HEAD(&atmel_i2c_mgmt.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);
 
 MODULE_AUTHOR("Tudor Ambarus");
 MODULE_DESCRIPTION("Microchip / Atmel ECC (I2C) driver");
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/12] crypto: atmel-ecc - simplify remove path and relax busy handling
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (8 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 08/12] crypto: atmel-ecc " Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 10/12] crypto: atmel-sha204a - guard remove path against missing client data Lothar Rubusch
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Simplify atmel_ecc_remove() by removing early exit logic and
centralizing client retrieval and validation.

Previously the driver returned early when active transform users
were detected, which could leave partially initialized state
without proper cleanup.

Replace this with a warning when active transforms are present,
but continue with full teardown of crypto registration and
device cleanup.

This ensures consistent removal behaviour even when the device
is still in use.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index dcfc09d24497..ce7a2e750ba8 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -346,21 +346,14 @@ static int atmel_ecc_probe(struct i2c_client *client)
 
 static void atmel_ecc_remove(struct i2c_client *client)
 {
-	struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
+	struct atmel_i2c_client_priv *i2c_priv;
 
-	/* 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");
+	i2c_priv = i2c_get_clientdata(client);
+	if (WARN_ON(!i2c_priv))
 		return;
-	}
+
+	if (atomic_read(&i2c_priv->tfm_count))
+		dev_warn(&client->dev, "Device is busy, remove it anyhow\n");
 
 	crypto_unregister_kpp(&atmel_ecdh_nist_p256);
 
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/12] crypto: atmel-sha204a - guard remove path against missing client data
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (9 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 09/12] crypto: atmel-ecc - simplify remove path and relax busy handling Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 11/12] crypto: atmel - move i2c client selection to core driver Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 12/12] crypto: atmel - add capability-based I2C client selection Lothar Rubusch
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Retrieve the I2C client private data in atmel_sha204a_remove() only
after sysfs cleanup and add a NULL check before continuing device
teardown.

This prevents dereferencing invalid or partially initialized client
state during driver removal and makes the teardown path more robust
against inconsistent probe/remove sequences.

No functional change intended.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-sha204a.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index 613ed5e7b3f6..923e462ff6b0 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -213,7 +213,11 @@ static int atmel_sha204a_probe(struct i2c_client *client)
 
 static void atmel_sha204a_remove(struct i2c_client *client)
 {
-	struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client);
+	struct atmel_i2c_client_priv *i2c_priv;
+
+	i2c_priv = i2c_get_clientdata(client);
+	if (WARN_ON(!i2c_priv))
+		return;
 
 	devm_hwrng_unregister(&client->dev, &i2c_priv->hwrng);
 
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/12] crypto: atmel - move i2c client selection to core driver
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (10 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 10/12] crypto: atmel-sha204a - guard remove path against missing client data Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  2026-05-17 18:06 ` [PATCH 12/12] crypto: atmel - add capability-based I2C client selection Lothar Rubusch
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Move the I2C client selection/allocation logic from the ECC-specific driver
into the shared Atmel I2C core.

This consolidates hardware client selection in a single place, allowing all
Atmel crypto drivers to reuse the same balancing logic for selecting the
least-loaded I2C client based on the current transformation count.

No functional change is intended.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c | 37 +------------------------------------
 drivers/crypto/atmel-i2c.c | 36 ++++++++++++++++++++++++++++++++++++
 drivers/crypto/atmel-i2c.h |  1 +
 3 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index ce7a2e750ba8..f877f236552f 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;
 }
 
-static struct i2c_client *atmel_ecc_i2c_client_alloc(void)
-{
-	struct atmel_i2c_client_priv *i2c_priv, *min_i2c_priv = NULL;
-	struct i2c_client *client = ERR_PTR(-ENODEV);
-	int min_tfm_cnt = 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 = atomic_read(&i2c_priv->tfm_count);
-		if (tfm_cnt < min_tfm_cnt) {
-			min_tfm_cnt = tfm_cnt;
-			min_i2c_priv = i2c_priv;
-		}
-		if (!min_tfm_cnt)
-			break;
-	}
-
-	if (min_i2c_priv) {
-		atomic_inc(&min_i2c_priv->tfm_count);
-		client = 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 = i2c_get_clientdata(client);
@@ -249,7 +214,7 @@ static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm)
 	struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
 
 	ctx->curve_id = ECC_CURVE_NIST_P256;
-	ctx->client = atmel_ecc_i2c_client_alloc();
+	ctx->client = atmel_i2c_client_alloc();
 	if (IS_ERR(ctx->client)) {
 		pr_err("tfm - i2c_client binding failed\n");
 		return PTR_ERR(ctx->client);
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index 861af52d7a88..4beab68997c4 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -57,6 +57,42 @@ static void atmel_i2c_checksum(struct atmel_i2c_cmd *cmd)
 	*__crc16 = cpu_to_le16(bitrev16(crc16(0, data, len)));
 }
 
+struct i2c_client *atmel_i2c_client_alloc(void)
+{
+	struct atmel_i2c_client_priv *i2c_priv, *min_i2c_priv = NULL;
+	struct i2c_client *client = ERR_PTR(-ENODEV);
+	int min_tfm_cnt = 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 = atomic_read(&i2c_priv->tfm_count);
+		if (tfm_cnt < min_tfm_cnt) {
+			min_tfm_cnt = tfm_cnt;
+			min_i2c_priv = i2c_priv;
+		}
+		if (!min_tfm_cnt)
+			break;
+	}
+
+	if (min_i2c_priv) {
+		atomic_inc(&min_i2c_priv->tfm_count);
+		client = 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 = COMMAND;
diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
index 43a0c1cfcd94..ba5a860011c8 100644
--- a/drivers/crypto/atmel-i2c.h
+++ b/drivers/crypto/atmel-i2c.h
@@ -190,6 +190,7 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid);
 int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
 			    struct scatterlist *pubkey);
 
+struct i2c_client *atmel_i2c_client_alloc(void);
 void atmel_i2c_unregister_client(struct atmel_i2c_client_priv *i2c_priv);
 
 #endif /* __ATMEL_I2C_H__ */
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 12/12] crypto: atmel - add capability-based I2C client selection
  2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
                   ` (11 preceding siblings ...)
  2026-05-17 18:06 ` [PATCH 11/12] crypto: atmel - move i2c client selection to core driver Lothar Rubusch
@ 2026-05-17 18:06 ` Lothar Rubusch
  12 siblings, 0 replies; 14+ messages in thread
From: Lothar Rubusch @ 2026-05-17 18:06 UTC (permalink / raw)
  To: thorsten.blum, herbert, davem, nicolas.ferre, alexandre.belloni,
	claudiu.beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch

Add capability filtering to the I2C client allocator to support
feature-aware selection of hardware clients.

Each client now exposes supported features via a capability mask. The
allocator selects only clients matching the requested capability and still
prefers the least-loaded device.

ECC marks ECDH support during probe and requests matching clients during
tfm setup. SHA204A exposes no capabilities for now.

This is preparatory work for upcoming features that will extend hardware
usage beyond a single algorithm type.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
 drivers/crypto/atmel-ecc.c     | 4 +++-
 drivers/crypto/atmel-i2c.c     | 5 ++++-
 drivers/crypto/atmel-i2c.h     | 8 +++++++-
 drivers/crypto/atmel-sha204a.c | 2 ++
 4 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
index f877f236552f..0eeee9ae6c48 100644
--- a/drivers/crypto/atmel-ecc.c
+++ b/drivers/crypto/atmel-ecc.c
@@ -214,7 +214,7 @@ static int atmel_ecdh_init_tfm(struct crypto_kpp *tfm)
 	struct atmel_ecdh_ctx *ctx = kpp_tfm_ctx(tfm);
 
 	ctx->curve_id = ECC_CURVE_NIST_P256;
-	ctx->client = atmel_i2c_client_alloc();
+	ctx->client = 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);
@@ -286,6 +286,8 @@ static int atmel_ecc_probe(struct i2c_client *client)
 
 	i2c_priv = i2c_get_clientdata(client);
 
+	i2c_priv->caps = BIT(ATMEL_CAP_ECDH);
+
 	spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
 	list_add_tail(&i2c_priv->i2c_client_list_node,
 		      &atmel_i2c_mgmt.i2c_client_list);
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index 4beab68997c4..b7ee2ec37531 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -57,7 +57,7 @@ static void atmel_i2c_checksum(struct atmel_i2c_cmd *cmd)
 	*__crc16 = cpu_to_le16(bitrev16(crc16(0, data, len)));
 }
 
-struct i2c_client *atmel_i2c_client_alloc(void)
+struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap)
 {
 	struct atmel_i2c_client_priv *i2c_priv, *min_i2c_priv = NULL;
 	struct i2c_client *client = ERR_PTR(-ENODEV);
@@ -73,6 +73,9 @@ struct i2c_client *atmel_i2c_client_alloc(void)
 
 	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 = atomic_read(&i2c_priv->tfm_count);
 		if (tfm_cnt < min_tfm_cnt) {
 			min_tfm_cnt = tfm_cnt;
diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h
index ba5a860011c8..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
 
 /* Used for binding tfm objects to i2c clients. */
+enum atmel_i2c_capability {
+	ATMEL_CAP_ECDH = 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 client
  * @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 send
@@ -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;
 };
 
 /**
@@ -190,7 +196,7 @@ void atmel_i2c_init_genkey_cmd(struct atmel_i2c_cmd *cmd, u16 keyid);
 int atmel_i2c_init_ecdh_cmd(struct atmel_i2c_cmd *cmd,
 			    struct scatterlist *pubkey);
 
-struct i2c_client *atmel_i2c_client_alloc(void);
+struct i2c_client *atmel_i2c_client_alloc(enum atmel_i2c_capability cap);
 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 923e462ff6b0..1a28c6434669 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 *client)
 
 	i2c_priv = i2c_get_clientdata(client);
 
+	i2c_priv->caps = 0;
+
 	/* add to client list */
 	spin_lock(&atmel_i2c_mgmt.i2c_list_lock);
 	list_add_tail(&i2c_priv->i2c_client_list_node,
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-05-17 18:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-17 18:06 [PATCH 00/12] crypto: atmel - introduce shared i2c core client management and capability-based selection framework Lothar Rubusch
2026-05-17 18:06 ` [PATCH] crypto: atmel - add capability-based I2C client selection Lothar Rubusch
2026-05-17 18:06 ` [PATCH 01/12] crypto: atmel-ecc - rename driver_data before moving it into atmel-i2c Lothar Rubusch
2026-05-17 18:06 ` [PATCH 02/12] crypto: atmel - rename atmel_ecc_driver_data to atmel_i2c_client_mgmt Lothar Rubusch
2026-05-17 18:06 ` [PATCH 03/12] crypto: atmel - move i2c client management instance into core driver Lothar Rubusch
2026-05-17 18:06 ` [PATCH 04/12] crypto: atmel-ecc - simplify probe error handling Lothar Rubusch
2026-05-17 18:06 ` [PATCH 05/12] crypto: atmel - factor out i2c client unregistration helper Lothar Rubusch
2026-05-17 18:06 ` [PATCH 06/12] crypto: atmel-sha204a - add i2c hw client list and improve probe error handling Lothar Rubusch
2026-05-17 18:06 ` [PATCH 07/12] crypto: atmel-sha204a - switch to module_i2c_driver Lothar Rubusch
2026-05-17 18:06 ` [PATCH 08/12] crypto: atmel-ecc " Lothar Rubusch
2026-05-17 18:06 ` [PATCH 09/12] crypto: atmel-ecc - simplify remove path and relax busy handling Lothar Rubusch
2026-05-17 18:06 ` [PATCH 10/12] crypto: atmel-sha204a - guard remove path against missing client data Lothar Rubusch
2026-05-17 18:06 ` [PATCH 11/12] crypto: atmel - move i2c client selection to core driver Lothar Rubusch
2026-05-17 18:06 ` [PATCH 12/12] crypto: atmel - add capability-based I2C client selection Lothar Rubusch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox