All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lars Povlsen <lars.povlsen@microchip.com>
To: Mark Brown <broonie@kernel.org>, SoC Team <soc@kernel.org>
Cc: Lars Povlsen <lars.povlsen@microchip.com>,
	Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>,
	<linux-spi@vger.kernel.org>, <devicetree@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	Alexandre Belloni <alexandre.belloni@bootlin.com>
Subject: [PATCH 07/10] spi: spi-dw-mchp: Add Sparx5 support
Date: Wed, 13 May 2020 16:00:28 +0200	[thread overview]
Message-ID: <20200513140031.25633-8-lars.povlsen@microchip.com> (raw)
In-Reply-To: <20200513140031.25633-1-lars.povlsen@microchip.com>

This adds support for the Sparx5 SoC in the spi-dw-mchp SPI controller.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 drivers/spi/spi-dw-mchp.c | 211 ++++++++++++++++++++++++++++++++++----
 1 file changed, 189 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-dw-mchp.c b/drivers/spi/spi-dw-mchp.c
index 0828a7616d9ab..3abdd44a550ea 100644
--- a/drivers/spi/spi-dw-mchp.c
+++ b/drivers/spi/spi-dw-mchp.c
@@ -28,21 +28,22 @@

 #define MAX_CS		4

-#define MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL	0x24
-#define OCELOT_IF_SI_OWNER_OFFSET		4
-#define JAGUAR2_IF_SI_OWNER_OFFSET		6
 #define MSCC_IF_SI_OWNER_MASK			GENMASK(1, 0)
 #define MSCC_IF_SI_OWNER_SISL			0
 #define MSCC_IF_SI_OWNER_SIBM			1
 #define MSCC_IF_SI_OWNER_SIMC			2

 #define MSCC_SPI_MST_SW_MODE			0x14
-#define MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE	BIT(13)
-#define MSCC_SPI_MST_SW_MODE_SW_SPI_CS(x)	(x << 5)

 struct dw_spi_mchp_props {
 	const char *syscon_name;
-	u32 si_owner_bit;
+	u32 general_ctrl_off;
+	u32 si_owner_bit, si_owner2_bit;
+	u32 pinctrl_bit_off;
+	u32 cs_bit_off;
+	u32 ss_force_ena_off;
+	u32 ss_force_val_off;
+	u32 bootmaster_cs;
 };

 struct dw_spi_mchp {
@@ -53,44 +54,176 @@ struct dw_spi_mchp {
 	void __iomem			*spi_mst;
 	const struct dw_spi_mchp_props	*props;
 	u32				gen_owner;
+	u32				if2mask;
 };

 static const struct dw_spi_mchp_props dw_spi_mchp_props_ocelot = {
 	.syscon_name		= "mscc,ocelot-cpu-syscon",
+	.general_ctrl_off	= 0x24,
 	.si_owner_bit		= 4,
+	.pinctrl_bit_off	= 13,
+	.cs_bit_off		= 5,
+	.bootmaster_cs		= 0,
 };

 static const struct dw_spi_mchp_props dw_spi_mchp_props_jaguar2 = {
 	.syscon_name		= "mscc,ocelot-cpu-syscon",
+	.general_ctrl_off	= 0x24,
 	.si_owner_bit		= 6,
+	.pinctrl_bit_off	= 13,
+	.cs_bit_off		= 5,
+	.bootmaster_cs		= 0,
+};
+
+static const struct dw_spi_mchp_props dw_spi_mchp_props_sparx5 = {
+	.syscon_name		= "microchip,sparx5-cpu-syscon",
+	.general_ctrl_off	= 0x88,
+	.si_owner_bit		= 6,
+	.si_owner2_bit		= 4,
+	.ss_force_ena_off	= 0xa4,
+	.ss_force_val_off	= 0xa8,
+	.bootmaster_cs		= 0,
 };

 /*
- * The Designware SPI controller (referred to as master in the documentation)
- * automatically deasserts chip select when the tx fifo is empty. The chip
- * selects then needs to be either driven as GPIOs or, for the first 4 using the
- * the SPI boot controller registers. the final chip select is an OR gate
- * between the Designware SPI controller and the SPI boot controller.
+ * Set the owner of the SPI interface
  */
-static void dw_spi_mchp_set_cs(struct spi_device *spi, bool enable)
+static void dw_spi_mchp_set_owner(struct dw_spi_mchp *dwsmchp,
+				  const struct dw_spi_mchp_props *props,
+				  u8 owner, u8 owner2)
+{
+	u32 val, msk;
+
+	val = (owner << props->si_owner_bit);
+	msk = (MSCC_IF_SI_OWNER_MASK << props->si_owner_bit);
+	if (props->si_owner2_bit) {
+		val |= owner2 << props->si_owner2_bit;
+		msk |= (MSCC_IF_SI_OWNER_MASK << props->si_owner2_bit);
+	}
+	if (dwsmchp->gen_owner != val) {
+		regmap_update_bits(dwsmchp->syscon, props->general_ctrl_off,
+				   msk, val);
+		dwsmchp->gen_owner = val;
+	}
+}
+
+static void dw_spi_mchp_set_cs_owner(struct dw_spi_mchp *dwsmchp,
+				     const struct dw_spi_mchp_props *props,
+				     u8 cs, u8 owner)
 {
+	u8 dummy = (owner == MSCC_IF_SI_OWNER_SIBM ?
+		    MSCC_IF_SI_OWNER_SIMC : MSCC_IF_SI_OWNER_SIBM);
+	if (props->si_owner2_bit && (dwsmchp->if2mask & BIT(cs))) {
+		/* SPI2 */
+		dw_spi_mchp_set_owner(dwsmchp, props, dummy, owner);
+	} else {
+		/* SPI1 */
+		dw_spi_mchp_set_owner(dwsmchp, props, owner, dummy);
+	}
+}
+
+/*
+ * The Designware SPI controller (referred to as master in the
+ * documentation) automatically deasserts chip select when the tx fifo
+ * is empty. The chip selects then needs to be either driven as GPIOs
+ * or, for the first 4 using the the SPI boot controller
+ * registers. the final chip select is an OR gate between the
+ * Designware SPI controller and the SPI boot controller.  nselect is
+ * an active low signal
+ */
+static void dw_spi_mchp_set_cs(struct spi_device *spi, bool nEnable)
+{
+	bool enable = !nEnable;	/* This keeps changing in the API... */
 	struct dw_spi *dws = spi_master_get_devdata(spi->master);
 	struct dw_spi_mchp *dwsmchp = container_of(dws, struct dw_spi_mchp,
 						   dws);
-	u32 cs = spi->chip_select;
+	const struct dw_spi_mchp_props *props = dwsmchp->props;
+	u8 cs = spi->chip_select;

-	if (cs < 4) {
-		u32 sw_mode = MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE;
+	if (enable)
+		dw_spi_mchp_set_cs_owner(dwsmchp, props, cs,
+					 MSCC_IF_SI_OWNER_SIMC);

-		if (!enable)
-			sw_mode |= MSCC_SPI_MST_SW_MODE_SW_SPI_CS(BIT(cs));
+	if (dwsmchp->spi_mst && (cs < MAX_CS)) {
+		u32 sw_mode;

+		if (enable)
+			sw_mode = BIT(props->pinctrl_bit_off) |
+				(BIT(cs) << props->cs_bit_off);
+		else
+			sw_mode = 0;
 		writel(sw_mode, dwsmchp->spi_mst + MSCC_SPI_MST_SW_MODE);
+	} else if (props->ss_force_ena_off) {
+		if (enable) {
+			/* Ensure CS toggles, so start off all disabled */
+			regmap_write(dwsmchp->syscon, props->ss_force_val_off,
+				     ~0);
+			/* CS override drive enable */
+			regmap_write(dwsmchp->syscon, props->ss_force_ena_off,
+				     1);
+			/* Allow settle */
+			udelay(1);
+			/* Now set CSx enabled */
+			regmap_write(dwsmchp->syscon, props->ss_force_val_off,
+				     ~BIT(cs));
+		} else {
+			/* CS value */
+			regmap_write(dwsmchp->syscon, props->ss_force_val_off,
+				     ~0);
+			/* CS override drive disable */
+			regmap_write(dwsmchp->syscon, props->ss_force_ena_off,
+				     0);
+		}
 	}

-	dw_spi_set_cs(spi, enable);
+	dw_spi_set_cs(spi, nEnable);
+}
+
+static int dw_mchp_bootmaster_exec_mem_op(struct spi_mem *mem,
+					  const struct spi_mem_op *op)
+{
+	struct spi_device *spi = mem->spi;
+	int ret = -ENOTSUPP;
+
+	/* Only reads, addrsize 1..4 */
+	if (!op->data.nbytes || !op->addr.nbytes || op->addr.nbytes > 4 ||
+	    op->data.dir != SPI_MEM_DATA_IN)
+		return ret;
+
+	/* Only handle (normal+fast) 3/4 bytes read */
+	if (op->cmd.opcode != SPINOR_OP_READ &&
+	    op->cmd.opcode != SPINOR_OP_READ_FAST &&
+	    op->cmd.opcode != SPINOR_OP_READ_4B &&
+	    op->cmd.opcode != SPINOR_OP_READ_FAST_4B)
+		return ret;
+
+	/* CS0..3, only 16M reach */
+	if ((spi->chip_select < MAX_CS) &&
+	    (op->addr.val + op->data.nbytes) < SZ_16M) {
+		struct dw_spi *dws = spi_master_get_devdata(spi->master);
+		struct dw_spi_mchp *dwsmchp = container_of(dws,
+							   struct dw_spi_mchp,
+							   dws);
+		const struct dw_spi_mchp_props *props = dwsmchp->props;
+		u8 __iomem *src = dwsmchp->read_map +
+			(spi->chip_select * SZ_16M) + op->addr.val;
+
+		if (props->bootmaster_cs != spi->chip_select)
+			return ret;
+
+		/* Make boot master owner of SI interface */
+		dw_spi_mchp_set_cs_owner(dwsmchp, props, spi->chip_select,
+					 MSCC_IF_SI_OWNER_SIBM);
+		memcpy(op->data.buf.in, src, op->data.nbytes);
+		ret = op->data.nbytes;
+	}
+	return ret;
 }

+static const struct spi_controller_mem_ops dw_mchp_bootmaster_mem_ops = {
+	.exec_op = dw_mchp_bootmaster_exec_mem_op,
+};
+
 static int dw_spi_mchp_init(struct platform_device *pdev,
 			    struct dw_spi *dws,
 			    struct dw_spi_mchp *dwsmchp,
@@ -107,6 +240,18 @@ static int dw_spi_mchp_init(struct platform_device *pdev,
 		}
 	}

+	/* See if we have a direct read window */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (res && resource_size(res) >= (SZ_16M*MAX_CS)) {
+		void __iomem *ptr = devm_ioremap_resource(&pdev->dev, res);
+
+		if (!IS_ERR(ptr)) {
+			dwsmchp->read_map = ptr;
+			dws->mem_ops = &dw_mchp_bootmaster_mem_ops;
+			dev_info(&pdev->dev, "Enabling fast memory operations\n");
+		}
+	}
+
 	dwsmchp->syscon =
 		syscon_regmap_lookup_by_compatible(props->syscon_name);
 	if (IS_ERR(dwsmchp->syscon)) {
@@ -119,10 +264,9 @@ static int dw_spi_mchp_init(struct platform_device *pdev,
 	if (dwsmchp->spi_mst)
 		writel(0, dwsmchp->spi_mst + MSCC_SPI_MST_SW_MODE);

-	/* Select the owner of the SI interface */
-	regmap_update_bits(dwsmchp->syscon, MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL,
-			   MSCC_IF_SI_OWNER_MASK << props->si_owner_bit,
-			   MSCC_IF_SI_OWNER_SIMC << props->si_owner_bit);
+	/* SPI2 mapping bitmask */
+	device_property_read_u32(&pdev->dev, "interface-mapping-mask",
+				 &dwsmchp->if2mask);

 	dwsmchp->dws.set_cs = dw_spi_mchp_set_cs;

@@ -180,6 +324,27 @@ static int dw_spi_mchp_probe(struct platform_device *pdev)
 	dws->rx_sample_dly = DIV_ROUND_UP(rx_sample_dly,
 					  (dws->max_freq / 1000000));

+	if (pdev->dev.of_node) {
+		int i;
+
+		for (i = 0; i < dws->num_cs; i++) {
+			int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
+					"cs-gpios", i);
+
+			if (cs_gpio == -EPROBE_DEFER) {
+				ret = cs_gpio;
+				goto out;
+			}
+
+			if (gpio_is_valid(cs_gpio)) {
+				ret = devm_gpio_request(&pdev->dev, cs_gpio,
+						dev_name(&pdev->dev));
+				if (ret)
+					goto out;
+			}
+		}
+	}
+
 	props = device_get_match_data(&pdev->dev);
 	if (props)
 		ret = dw_spi_mchp_init(pdev, dws, dwsmchp, props);
@@ -213,6 +378,8 @@ static int dw_spi_mchp_remove(struct platform_device *pdev)
 static const struct of_device_id dw_spi_mchp_of_match[] = {
 	{ .compatible = "mscc,ocelot-spi", .data = &dw_spi_mchp_props_ocelot},
 	{ .compatible = "mscc,jaguar2-spi", .data = &dw_spi_mchp_props_jaguar2},
+	{ .compatible = "microchip,sparx5-spi",
+	  .data = &dw_spi_mchp_props_sparx5},
 	{ /* end of table */}
 };
 MODULE_DEVICE_TABLE(of, dw_spi_mchp_of_match);
--
2.26.2

WARNING: multiple messages have this Message-ID (diff)
From: Lars Povlsen <lars.povlsen@microchip.com>
To: Mark Brown <broonie@kernel.org>, SoC Team <soc@kernel.org>
Cc: devicetree@vger.kernel.org,
	Alexandre Belloni <alexandre.belloni@bootlin.com>,
	linux-kernel@vger.kernel.org, linux-spi@vger.kernel.org,
	Lars Povlsen <lars.povlsen@microchip.com>,
	Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH 07/10] spi: spi-dw-mchp: Add Sparx5 support
Date: Wed, 13 May 2020 16:00:28 +0200	[thread overview]
Message-ID: <20200513140031.25633-8-lars.povlsen@microchip.com> (raw)
In-Reply-To: <20200513140031.25633-1-lars.povlsen@microchip.com>

This adds support for the Sparx5 SoC in the spi-dw-mchp SPI controller.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 drivers/spi/spi-dw-mchp.c | 211 ++++++++++++++++++++++++++++++++++----
 1 file changed, 189 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-dw-mchp.c b/drivers/spi/spi-dw-mchp.c
index 0828a7616d9ab..3abdd44a550ea 100644
--- a/drivers/spi/spi-dw-mchp.c
+++ b/drivers/spi/spi-dw-mchp.c
@@ -28,21 +28,22 @@

 #define MAX_CS		4

-#define MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL	0x24
-#define OCELOT_IF_SI_OWNER_OFFSET		4
-#define JAGUAR2_IF_SI_OWNER_OFFSET		6
 #define MSCC_IF_SI_OWNER_MASK			GENMASK(1, 0)
 #define MSCC_IF_SI_OWNER_SISL			0
 #define MSCC_IF_SI_OWNER_SIBM			1
 #define MSCC_IF_SI_OWNER_SIMC			2

 #define MSCC_SPI_MST_SW_MODE			0x14
-#define MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE	BIT(13)
-#define MSCC_SPI_MST_SW_MODE_SW_SPI_CS(x)	(x << 5)

 struct dw_spi_mchp_props {
 	const char *syscon_name;
-	u32 si_owner_bit;
+	u32 general_ctrl_off;
+	u32 si_owner_bit, si_owner2_bit;
+	u32 pinctrl_bit_off;
+	u32 cs_bit_off;
+	u32 ss_force_ena_off;
+	u32 ss_force_val_off;
+	u32 bootmaster_cs;
 };

 struct dw_spi_mchp {
@@ -53,44 +54,176 @@ struct dw_spi_mchp {
 	void __iomem			*spi_mst;
 	const struct dw_spi_mchp_props	*props;
 	u32				gen_owner;
+	u32				if2mask;
 };

 static const struct dw_spi_mchp_props dw_spi_mchp_props_ocelot = {
 	.syscon_name		= "mscc,ocelot-cpu-syscon",
+	.general_ctrl_off	= 0x24,
 	.si_owner_bit		= 4,
+	.pinctrl_bit_off	= 13,
+	.cs_bit_off		= 5,
+	.bootmaster_cs		= 0,
 };

 static const struct dw_spi_mchp_props dw_spi_mchp_props_jaguar2 = {
 	.syscon_name		= "mscc,ocelot-cpu-syscon",
+	.general_ctrl_off	= 0x24,
 	.si_owner_bit		= 6,
+	.pinctrl_bit_off	= 13,
+	.cs_bit_off		= 5,
+	.bootmaster_cs		= 0,
+};
+
+static const struct dw_spi_mchp_props dw_spi_mchp_props_sparx5 = {
+	.syscon_name		= "microchip,sparx5-cpu-syscon",
+	.general_ctrl_off	= 0x88,
+	.si_owner_bit		= 6,
+	.si_owner2_bit		= 4,
+	.ss_force_ena_off	= 0xa4,
+	.ss_force_val_off	= 0xa8,
+	.bootmaster_cs		= 0,
 };

 /*
- * The Designware SPI controller (referred to as master in the documentation)
- * automatically deasserts chip select when the tx fifo is empty. The chip
- * selects then needs to be either driven as GPIOs or, for the first 4 using the
- * the SPI boot controller registers. the final chip select is an OR gate
- * between the Designware SPI controller and the SPI boot controller.
+ * Set the owner of the SPI interface
  */
-static void dw_spi_mchp_set_cs(struct spi_device *spi, bool enable)
+static void dw_spi_mchp_set_owner(struct dw_spi_mchp *dwsmchp,
+				  const struct dw_spi_mchp_props *props,
+				  u8 owner, u8 owner2)
+{
+	u32 val, msk;
+
+	val = (owner << props->si_owner_bit);
+	msk = (MSCC_IF_SI_OWNER_MASK << props->si_owner_bit);
+	if (props->si_owner2_bit) {
+		val |= owner2 << props->si_owner2_bit;
+		msk |= (MSCC_IF_SI_OWNER_MASK << props->si_owner2_bit);
+	}
+	if (dwsmchp->gen_owner != val) {
+		regmap_update_bits(dwsmchp->syscon, props->general_ctrl_off,
+				   msk, val);
+		dwsmchp->gen_owner = val;
+	}
+}
+
+static void dw_spi_mchp_set_cs_owner(struct dw_spi_mchp *dwsmchp,
+				     const struct dw_spi_mchp_props *props,
+				     u8 cs, u8 owner)
 {
+	u8 dummy = (owner == MSCC_IF_SI_OWNER_SIBM ?
+		    MSCC_IF_SI_OWNER_SIMC : MSCC_IF_SI_OWNER_SIBM);
+	if (props->si_owner2_bit && (dwsmchp->if2mask & BIT(cs))) {
+		/* SPI2 */
+		dw_spi_mchp_set_owner(dwsmchp, props, dummy, owner);
+	} else {
+		/* SPI1 */
+		dw_spi_mchp_set_owner(dwsmchp, props, owner, dummy);
+	}
+}
+
+/*
+ * The Designware SPI controller (referred to as master in the
+ * documentation) automatically deasserts chip select when the tx fifo
+ * is empty. The chip selects then needs to be either driven as GPIOs
+ * or, for the first 4 using the the SPI boot controller
+ * registers. the final chip select is an OR gate between the
+ * Designware SPI controller and the SPI boot controller.  nselect is
+ * an active low signal
+ */
+static void dw_spi_mchp_set_cs(struct spi_device *spi, bool nEnable)
+{
+	bool enable = !nEnable;	/* This keeps changing in the API... */
 	struct dw_spi *dws = spi_master_get_devdata(spi->master);
 	struct dw_spi_mchp *dwsmchp = container_of(dws, struct dw_spi_mchp,
 						   dws);
-	u32 cs = spi->chip_select;
+	const struct dw_spi_mchp_props *props = dwsmchp->props;
+	u8 cs = spi->chip_select;

-	if (cs < 4) {
-		u32 sw_mode = MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE;
+	if (enable)
+		dw_spi_mchp_set_cs_owner(dwsmchp, props, cs,
+					 MSCC_IF_SI_OWNER_SIMC);

-		if (!enable)
-			sw_mode |= MSCC_SPI_MST_SW_MODE_SW_SPI_CS(BIT(cs));
+	if (dwsmchp->spi_mst && (cs < MAX_CS)) {
+		u32 sw_mode;

+		if (enable)
+			sw_mode = BIT(props->pinctrl_bit_off) |
+				(BIT(cs) << props->cs_bit_off);
+		else
+			sw_mode = 0;
 		writel(sw_mode, dwsmchp->spi_mst + MSCC_SPI_MST_SW_MODE);
+	} else if (props->ss_force_ena_off) {
+		if (enable) {
+			/* Ensure CS toggles, so start off all disabled */
+			regmap_write(dwsmchp->syscon, props->ss_force_val_off,
+				     ~0);
+			/* CS override drive enable */
+			regmap_write(dwsmchp->syscon, props->ss_force_ena_off,
+				     1);
+			/* Allow settle */
+			udelay(1);
+			/* Now set CSx enabled */
+			regmap_write(dwsmchp->syscon, props->ss_force_val_off,
+				     ~BIT(cs));
+		} else {
+			/* CS value */
+			regmap_write(dwsmchp->syscon, props->ss_force_val_off,
+				     ~0);
+			/* CS override drive disable */
+			regmap_write(dwsmchp->syscon, props->ss_force_ena_off,
+				     0);
+		}
 	}

-	dw_spi_set_cs(spi, enable);
+	dw_spi_set_cs(spi, nEnable);
+}
+
+static int dw_mchp_bootmaster_exec_mem_op(struct spi_mem *mem,
+					  const struct spi_mem_op *op)
+{
+	struct spi_device *spi = mem->spi;
+	int ret = -ENOTSUPP;
+
+	/* Only reads, addrsize 1..4 */
+	if (!op->data.nbytes || !op->addr.nbytes || op->addr.nbytes > 4 ||
+	    op->data.dir != SPI_MEM_DATA_IN)
+		return ret;
+
+	/* Only handle (normal+fast) 3/4 bytes read */
+	if (op->cmd.opcode != SPINOR_OP_READ &&
+	    op->cmd.opcode != SPINOR_OP_READ_FAST &&
+	    op->cmd.opcode != SPINOR_OP_READ_4B &&
+	    op->cmd.opcode != SPINOR_OP_READ_FAST_4B)
+		return ret;
+
+	/* CS0..3, only 16M reach */
+	if ((spi->chip_select < MAX_CS) &&
+	    (op->addr.val + op->data.nbytes) < SZ_16M) {
+		struct dw_spi *dws = spi_master_get_devdata(spi->master);
+		struct dw_spi_mchp *dwsmchp = container_of(dws,
+							   struct dw_spi_mchp,
+							   dws);
+		const struct dw_spi_mchp_props *props = dwsmchp->props;
+		u8 __iomem *src = dwsmchp->read_map +
+			(spi->chip_select * SZ_16M) + op->addr.val;
+
+		if (props->bootmaster_cs != spi->chip_select)
+			return ret;
+
+		/* Make boot master owner of SI interface */
+		dw_spi_mchp_set_cs_owner(dwsmchp, props, spi->chip_select,
+					 MSCC_IF_SI_OWNER_SIBM);
+		memcpy(op->data.buf.in, src, op->data.nbytes);
+		ret = op->data.nbytes;
+	}
+	return ret;
 }

+static const struct spi_controller_mem_ops dw_mchp_bootmaster_mem_ops = {
+	.exec_op = dw_mchp_bootmaster_exec_mem_op,
+};
+
 static int dw_spi_mchp_init(struct platform_device *pdev,
 			    struct dw_spi *dws,
 			    struct dw_spi_mchp *dwsmchp,
@@ -107,6 +240,18 @@ static int dw_spi_mchp_init(struct platform_device *pdev,
 		}
 	}

+	/* See if we have a direct read window */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (res && resource_size(res) >= (SZ_16M*MAX_CS)) {
+		void __iomem *ptr = devm_ioremap_resource(&pdev->dev, res);
+
+		if (!IS_ERR(ptr)) {
+			dwsmchp->read_map = ptr;
+			dws->mem_ops = &dw_mchp_bootmaster_mem_ops;
+			dev_info(&pdev->dev, "Enabling fast memory operations\n");
+		}
+	}
+
 	dwsmchp->syscon =
 		syscon_regmap_lookup_by_compatible(props->syscon_name);
 	if (IS_ERR(dwsmchp->syscon)) {
@@ -119,10 +264,9 @@ static int dw_spi_mchp_init(struct platform_device *pdev,
 	if (dwsmchp->spi_mst)
 		writel(0, dwsmchp->spi_mst + MSCC_SPI_MST_SW_MODE);

-	/* Select the owner of the SI interface */
-	regmap_update_bits(dwsmchp->syscon, MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL,
-			   MSCC_IF_SI_OWNER_MASK << props->si_owner_bit,
-			   MSCC_IF_SI_OWNER_SIMC << props->si_owner_bit);
+	/* SPI2 mapping bitmask */
+	device_property_read_u32(&pdev->dev, "interface-mapping-mask",
+				 &dwsmchp->if2mask);

 	dwsmchp->dws.set_cs = dw_spi_mchp_set_cs;

@@ -180,6 +324,27 @@ static int dw_spi_mchp_probe(struct platform_device *pdev)
 	dws->rx_sample_dly = DIV_ROUND_UP(rx_sample_dly,
 					  (dws->max_freq / 1000000));

+	if (pdev->dev.of_node) {
+		int i;
+
+		for (i = 0; i < dws->num_cs; i++) {
+			int cs_gpio = of_get_named_gpio(pdev->dev.of_node,
+					"cs-gpios", i);
+
+			if (cs_gpio == -EPROBE_DEFER) {
+				ret = cs_gpio;
+				goto out;
+			}
+
+			if (gpio_is_valid(cs_gpio)) {
+				ret = devm_gpio_request(&pdev->dev, cs_gpio,
+						dev_name(&pdev->dev));
+				if (ret)
+					goto out;
+			}
+		}
+	}
+
 	props = device_get_match_data(&pdev->dev);
 	if (props)
 		ret = dw_spi_mchp_init(pdev, dws, dwsmchp, props);
@@ -213,6 +378,8 @@ static int dw_spi_mchp_remove(struct platform_device *pdev)
 static const struct of_device_id dw_spi_mchp_of_match[] = {
 	{ .compatible = "mscc,ocelot-spi", .data = &dw_spi_mchp_props_ocelot},
 	{ .compatible = "mscc,jaguar2-spi", .data = &dw_spi_mchp_props_jaguar2},
+	{ .compatible = "microchip,sparx5-spi",
+	  .data = &dw_spi_mchp_props_sparx5},
 	{ /* end of table */}
 };
 MODULE_DEVICE_TABLE(of, dw_spi_mchp_of_match);
--
2.26.2

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2020-05-13 14:01 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-13 14:00 [PATCH 00/10] spi: Adding support for Microchip Sparx5 SoC Lars Povlsen
2020-05-13 14:00 ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 01/10] spi: dw: Add support for polled operation via no IRQ specified in DT Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-13 14:20   ` Mark Brown
2020-05-14 13:04     ` Serge Semin
2020-05-14 13:04       ` Serge Semin
2020-05-15  9:11       ` Lars Povlsen
2020-05-15  9:11         ` Lars Povlsen
2020-05-13 14:37   ` Mark Brown
2020-05-19 10:21     ` Lars Povlsen
2020-05-19 10:21       ` Lars Povlsen
2020-05-13 14:55   ` Andy Shevchenko
2020-05-13 14:55     ` Andy Shevchenko
2020-05-19 10:25     ` Lars Povlsen
2020-05-19 10:25       ` Lars Povlsen
2020-06-02 19:10   ` Serge Semin
2020-06-02 19:10     ` Serge Semin
2020-06-09  9:13     ` Lars Povlsen
2020-06-09  9:13       ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 02/10] spi: dw: Add support for RX sample delay register Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-06-02 19:39   ` Serge Semin
2020-06-02 19:39     ` Serge Semin
2020-06-09 10:04     ` Lars Povlsen
2020-06-09 10:04       ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 03/10] spi: dw: Add support for client driver memory operations Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 04/10] dt-bindings: spi: Add bindings for spi-dw-mchp Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-13 14:52   ` Mark Brown
2020-05-19 11:47     ` Lars Povlsen
2020-05-19 11:47       ` Lars Povlsen
2020-05-19 11:58       ` Mark Brown
2020-05-19 12:10         ` Lars Povlsen
2020-05-19 12:10           ` Lars Povlsen
2020-06-02 19:49   ` Serge Semin
2020-06-02 19:49     ` Serge Semin
2020-06-09 10:27     ` Lars Povlsen
2020-06-09 10:27       ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 05/10] spi: spi-dw-mmio: Spin off MSCC platforms into spi-dw-mchp Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-13 15:18   ` Mark Brown
2020-05-19 12:05     ` Lars Povlsen
2020-05-19 12:05       ` Lars Povlsen
2020-06-02 21:12       ` Serge Semin
2020-06-02 21:12         ` Serge Semin
2020-06-10 14:28         ` Lars Povlsen
2020-06-10 14:28           ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 06/10] dt-bindings: spi: spi-dw-mchp: Add Sparx5 support Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-13 15:25   ` Mark Brown
2020-06-02 23:07   ` Serge Semin
2020-06-02 23:07     ` Serge Semin
2020-06-10 12:27     ` Lars Povlsen
2020-06-10 12:27       ` Lars Povlsen
2020-05-13 14:00 ` Lars Povlsen [this message]
2020-05-13 14:00   ` [PATCH 07/10] " Lars Povlsen
2020-05-14 10:25   ` Mark Brown
2020-05-19  9:29     ` Lars Povlsen
2020-05-19  9:29       ` Lars Povlsen
2020-06-02 23:22   ` Serge Semin
2020-06-02 23:22     ` Serge Semin
2020-05-13 14:00 ` [PATCH 08/10] arm64: dts: sparx5: Add SPI controller Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 09/10] arm64: dts: sparx5: Add spi-nor support Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-13 14:00 ` [PATCH 10/10] arm64: dts: sparx5: Add spi-nand devices Lars Povlsen
2020-05-13 14:00   ` Lars Povlsen
2020-05-29 16:21 ` [PATCH 00/10] spi: Adding support for Microchip Sparx5 SoC Serge Semin
2020-05-29 16:21   ` Serge Semin
2020-06-02  8:18   ` Lars Povlsen
2020-06-02  8:18     ` Lars Povlsen
2020-06-02  8:21     ` Serge Semin
2020-06-02  8:21       ` Serge Semin
2020-06-02  9:56     ` Mark Brown
2020-06-02 23:44     ` Serge Semin
2020-06-02 23:44       ` Serge Semin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200513140031.25633-8-lars.povlsen@microchip.com \
    --to=lars.povlsen@microchip.com \
    --cc=UNGLinuxDriver@microchip.com \
    --cc=alexandre.belloni@bootlin.com \
    --cc=broonie@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-spi@vger.kernel.org \
    --cc=soc@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.