mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] net: ksz8864: Add support for KSZ87xx switches
@ 2021-10-11 18:42 Trent Piepho
  2021-10-12  7:45 ` Sascha Hauer
  0 siblings, 1 reply; 2+ messages in thread
From: Trent Piepho @ 2021-10-11 18:42 UTC (permalink / raw)
  To: Barebox List; +Cc: Trent Piepho

This adds support for the ksz8765, ksz8794, and ksz8795 switches.

IDs for OF bindings are added.  The base chip type is "ksz8795", the
same as the Linux driver, for the ksz87xx switches added here.
"ksz8864rmn" is used for the existing switch.

The registers for these switch chips, as least as far as this simple
driver is concerned, are the same as the existing ksz8864 support.

The difference in the ksz87xx chips is the format of the command and
address bytes:

C = command
A = address (used bits)
a = address (unused bits)
p = turn around padding bit

ksz8864: 00000CCC  AAAAAAAA
ksz8795: CCCaaaaA  AAAAAAAp

CCC and AAAAAAAA are the same, it's just where they are that changes.
This is parameterized in the read/write reg functions by using two
values for the address width and pad width.

Signed-off-by: Trent Piepho <trent.piepho@igorinstitute.com>
---
 drivers/net/ksz8864rmn.c | 66 ++++++++++++++++++++++++++++++----------
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ksz8864rmn.c b/drivers/net/ksz8864rmn.c
index 85063ff0d..72ab86579 100644
--- a/drivers/net/ksz8864rmn.c
+++ b/drivers/net/ksz8864rmn.c
@@ -31,48 +31,55 @@
 #define CMD_WRITE		0x02
 #define CMD_READ		0x03
 
+enum ksz_type {
+	unknown,
+	ksz87,
+	ksz88
+};
+
 struct micrel_switch_priv {
 	struct cdev             cdev;
 	struct spi_device       *spi;
 	unsigned int		p_enable;
+	unsigned int		addr_width;
+	unsigned int		pad;
 };
 
-static int micrel_switch_read_reg(struct spi_device *spi, uint8_t reg)
+static int micrel_switch_read_reg(const struct micrel_switch_priv *priv, uint8_t reg)
 {
 	uint8_t tx[2];
 	uint8_t rx[1];
 	int ret;
 
-	tx[0] = CMD_READ;
-	tx[1] = reg;
+	tx[0] = CMD_READ << (priv->addr_width + priv->pad - 8) | reg >> (8 - priv->pad);
+	tx[1] = reg << priv->pad;
 
-	ret = spi_write_then_read(spi, tx, 2, rx, 1);
+	ret = spi_write_then_read(priv->spi, tx, 2, rx, 1);
 	if (ret < 0)
 		return ret;
 
 	return rx[0];
 }
 
-static void micrel_switch_write_reg(struct spi_device *spi, uint8_t reg, uint8_t val)
+static void micrel_switch_write_reg(const struct micrel_switch_priv *priv, uint8_t reg, uint8_t val)
 {
 	uint8_t tx[3];
 
-	tx[0] = CMD_WRITE;
-	tx[1] = reg;
+	tx[0] = CMD_WRITE << (priv->addr_width + priv->pad - 8) | reg >> (8 - priv->pad);
+	tx[1] = reg << priv->pad;
 	tx[2] = val;
 
-	spi_write_then_read(spi, tx, 3, NULL, 0);
+	spi_write_then_read(priv->spi, tx, 3, NULL, 0);
 }
 
 static int micrel_switch_enable_set(struct param_d *param, void *_priv)
 {
 	struct micrel_switch_priv *priv = _priv;
-	struct spi_device *spi = priv->spi;
 
 	if (priv->p_enable)
-		micrel_switch_write_reg(spi, REG_ID1, 1);
+		micrel_switch_write_reg(priv, REG_ID1, 1);
 	else
-		micrel_switch_write_reg(spi, REG_ID1, 0);
+		micrel_switch_write_reg(priv, REG_ID1, 0);
 
 	return 0;
 }
@@ -84,7 +91,7 @@ static ssize_t micel_switch_read(struct cdev *cdev, void *_buf, size_t count, lo
 	struct micrel_switch_priv *priv = cdev->priv;
 
 	for (i = 0; i < count; i++) {
-		ret = micrel_switch_read_reg(priv->spi, offset);
+		ret = micrel_switch_read_reg(priv, offset);
 		if (ret < 0)
 			return ret;
 		*buf = ret;
@@ -102,7 +109,7 @@ static ssize_t micel_switch_write(struct cdev *cdev, const void *_buf, size_t co
 	struct micrel_switch_priv *priv = cdev->priv;
 
 	for (i = 0; i < count; i++) {
-		micrel_switch_write_reg(priv->spi, offset, *buf);
+		micrel_switch_write_reg(priv, offset, *buf);
 		buf++;
 		offset++;
 	}
@@ -119,6 +126,11 @@ static int micrel_switch_probe(struct device_d *dev)
 {
 	struct micrel_switch_priv *priv;
 	int ret = 0;
+	enum ksz_type kind = (enum ksz_type)device_get_match_data(dev);
+	uint8_t id;
+
+	if (kind == unknown)
+		return -ENODEV;
 
 	priv = xzalloc(sizeof(*priv));
 
@@ -128,12 +140,27 @@ static int micrel_switch_probe(struct device_d *dev)
 	priv->spi->mode = SPI_MODE_0;
 	priv->spi->bits_per_word = 8;
 
-	ret = micrel_switch_read_reg(priv->spi, REG_ID0);
+	switch (kind) {
+	case ksz87:
+		priv->addr_width = 12;
+		priv->pad = 1;
+		id = 0x87;
+		break;
+	case ksz88:
+		priv->addr_width = 8;
+		priv->pad = 0;
+		id = 0x95;
+		break;
+	default:
+		return -ENODEV;
+	};
+
+	ret = micrel_switch_read_reg(priv, REG_ID0);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "failed to read device id\n");
 		return ret;
 	}
-	if (ret != 0x95) {
+	if (ret != id) {
 		dev_err(&priv->spi->dev, "unknown device id: %02x\n", ret);
 		return -ENODEV;
 	}
@@ -149,13 +176,20 @@ static int micrel_switch_probe(struct device_d *dev)
 			NULL, &priv->p_enable, priv);
 
 	priv->p_enable = 1;
-	micrel_switch_write_reg(priv->spi, REG_ID1, 1);
+	micrel_switch_write_reg(priv, REG_ID1, 1);
 
 	return 0;
 }
 
+static const struct platform_device_id ksz_ids[] = {
+	{ .name = "ksz8864rmn", .driver_data = ksz88 },
+	{ .name = "ksz8795", .driver_data = ksz87 },
+	{ }
+};
+
 static struct driver_d micrel_switch_driver = {
 	.name  = "ksz8864rmn",
 	.probe = micrel_switch_probe,
+	.id_table = ksz_ids,
 };
 device_spi_driver(micrel_switch_driver);
-- 
2.31.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


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

end of thread, other threads:[~2021-10-12  7:46 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-11 18:42 [PATCH] net: ksz8864: Add support for KSZ87xx switches Trent Piepho
2021-10-12  7:45 ` Sascha Hauer

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