All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/10] mips: bmips: add SPI support
@ 2017-05-18 19:29 Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                   ` (17 more replies)
  0 siblings, 18 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

Álvaro Fernández Rojas (10):
  drivers: spi: allow limiting reads
  drivers: spi: add config to consider command bytes when writting to
    flash
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/mips/dts/brcm,bcm3380.dtsi       |  13 ++
 arch/mips/dts/brcm,bcm63268.dtsi      |  13 ++
 arch/mips/dts/brcm,bcm6338.dtsi       |  13 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  13 ++
 arch/mips/dts/brcm,bcm6358.dtsi       |  13 ++
 arch/mips/dts/netgear,cg3100d.dts     |  13 ++
 arch/mips/dts/sagem,f at st1704.dts      |  13 ++
 configs/netgear_cg3100d_ram_defconfig |   8 +
 configs/sagem_f at st1704_ram_defconfig  |   8 +
 drivers/mtd/spi/spi_flash.c           |   5 +-
 drivers/spi/Kconfig                   |  26 +++
 drivers/spi/Makefile                  |   1 +
 drivers/spi/bcm63xx_spi.c             | 404 ++++++++++++++++++++++++++++++++++
 include/spi.h                         |  11 +-
 14 files changed, 552 insertions(+), 2 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.1.4

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

* [U-Boot] [PATCH 01/10] drivers: spi: allow limiting reads
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-20  2:29   ` Simon Glass
  2017-05-18 19:29 ` [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash Álvaro Fernández Rojas
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index ab7910b..e44c10f 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -487,6 +487,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index deb65ef..75a994c 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 	u8 option;
-- 
2.1.4

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

* [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-20  2:29   ` Simon Glass
  2017-05-18 19:29 ` [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 drivers/mtd/spi/spi_flash.c | 2 +-
 drivers/spi/Kconfig         | 3 +++
 include/spi.h               | 8 +++++++-
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e44c10f..748cc32 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi_max_write(spi, sizeof(cmd)));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index f3f7dbe..a00d401 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -13,6 +13,9 @@ config DM_SPI
 	  typically use driver-private data instead of extending the
 	  spi_slave structure.
 
+config SPI_MAX_WRITE_CMD_BYTES
+	bool "Include command bytes when determining max write size"
+
 if DM_SPI
 
 config ALTERA_SPI
diff --git a/include/spi.h b/include/spi.h
index 75a994c..310fa4d 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -63,6 +63,12 @@ struct dm_spi_slave_platdata {
 
 #endif /* CONFIG_DM_SPI */
 
+#ifdef CONFIG_SPI_MAX_WRITE_CMD_BYTES
+#define spi_max_write(spi, len)	(spi->max_write_size - len)
+#else
+#define spi_max_write(spi, len)	(spi->max_write_size)
+#endif
+
 /**
  * struct spi_slave - Representation of a SPI slave
  *
@@ -89,7 +95,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.1.4

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-20  2:29   ` Simon Glass
  2017-06-07  7:35   ` Jagan Teki
  2017-05-18 19:29 ` [U-Boot] [PATCH 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                   ` (14 subsequent siblings)
  17 siblings, 2 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
Instead of supporting both HW revisions of the controller in a single build,
support has been split by the selected config to save space.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 drivers/spi/Kconfig       |  23 +++
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 428 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a00d401..d458dd7 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -43,6 +43,29 @@ config ATMEL_SPI
 	  many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
 	  used to access the SPI Flash, such as AT25DF321.
 
+choice
+	prompt "BCM63xx SPI driver"
+	depends on ARCH_BMIPS
+	optional
+
+config BCM6338_SPI
+	bool "BCM6338 SPI driver"
+	select SPI_MAX_WRITE_CMD_BYTES
+	help
+	  Enable the BCM6338 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding this Broadcom
+	  SPI core.
+
+config BCM6358_SPI
+	bool "BCM6358 SPI driver"
+	select SPI_MAX_WRITE_CMD_BYTES
+	help
+	  Enable the BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding this Broadcom
+	  SPI core.
+
+endchoice
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c090562..c9ba648 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM6338_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000..6e64607
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_BCM6338_SPI)
+
+# define SPI_DT_ID		"brcm,bcm6338-spi"
+
+/* SPI Command register */
+# define SPI_CMD_REG		0x00
+
+/* SPI Interrupt registers */
+# define SPI_IR_STAT_REG	0x02
+# define SPI_IR_MASK_REG	0x04
+
+/* SPI Clock register */
+# define SPI_CLK_REG		0x06
+
+/* SPI Fill register */
+# define SPI_FILL_REG		0x07
+
+/* SPI Control register (8 bit) */
+# define SPI_CTL_REG		0x40
+# define SPI_CTL_BYTES_SHIFT	0
+# define SPI_CTL_BYTES_MASK	(0x3f << SPI_CTL_BYTES_SHIFT)
+# define SPI_CTL_TYPE_SHIFT	6
+# define SPI_CTL_TYPE_FD_RW	(0 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_W	(1 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_R	(2 << SPI_CTL_TYPE_SHIFT)
+
+# define bcm63xx_spi_wctl(v,a)	writeb_be(v, a);
+
+/* SPI TX Data registers */
+# define SPI_TX_DATA_REG	0x41
+# define SPI_TX_DATA_SIZE	0x3f
+
+/* SPI RX Data registers */
+# define SPI_RX_DATA_REG	0x80
+# define SPI_RX_DATA_SIZE	0x3f
+
+#elif defined(CONFIG_BCM6358_SPI)
+
+# define SPI_DT_ID		"brcm,bcm6358-spi"
+
+/* SPI Control register (16 bit) */
+# define SPI_CTL_REG		0x000
+# define SPI_CTL_BYTES_SHIFT	0
+# define SPI_CTL_BYTES_MASK	(0x3ff << SPI_CTL_BYTES_SHIFT)
+# define SPI_CTL_TYPE_SHIFT	14
+# define SPI_CTL_TYPE_FD_RW	(0 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_W	(1 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_R	(2 << SPI_CTL_TYPE_SHIFT)
+
+# define bcm63xx_spi_wctl(v,a)	writew_be(v, a);
+
+/* SPI TX Data registers */
+# define SPI_TX_DATA_REG	0x002
+# define SPI_TX_DATA_SIZE	0x21e
+
+/* SPI RX Data registers */
+# define SPI_RX_DATA_REG	0x400
+# define SPI_RX_DATA_SIZE	0x220
+
+/* SPI Command register */
+# define SPI_CMD_REG		0x700
+
+/* SPI Interrupt registers */
+# define SPI_IR_STAT_REG	0x702
+# define SPI_IR_MASK_REG	0x704
+
+/* SPI Clock register */
+# define SPI_CLK_REG		0x706
+
+/* SPI Fill register */
+# define SPI_FILL_REG		0x707
+
+#endif
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+struct bcm63xx_spi_priv {
+	void __iomem *regs;
+	uint8_t num_cs;
+	size_t tx_bytes;
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		error("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->regs + SPI_CLK_REG,
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->regs + SPI_IR_MASK_REG);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			error("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > SPI_RX_DATA_SIZE) {
+			error("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
+			error("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val = 0;
+		uint8_t irq;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
+			val |= SPI_CTL_TYPE_HD_W;
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
+				val |= SPI_CTL_TYPE_FD_RW;
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
+				val |= SPI_CTL_TYPE_HD_R;
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					error("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+		bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
+
+		/* issue the transfer */
+		val = SPI_CMD_OP_START;
+		val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			val |= SPI_CMD_3WIRE_MASK;
+		writew_be(val, priv->regs + SPI_CMD_REG);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
+
+		do {
+			/* read interupts */
+			irq = readb_be(priv->regs + SPI_IR_STAT_REG);
+
+			/* transfer completed */
+			if (irq & SPI_IR_DONE_MASK)
+				break;
+		} while (1);
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{ .compatible = SPI_DT_ID, },
+	{ /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		error("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = SPI_RX_DATA_SIZE;
+	slave->max_write_size = SPI_TX_DATA_SIZE;
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = dev_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+	clk_enable(&clk);
+	clk_free(&clk);
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+	reset_deassert(&rst_ctl);
+	reset_free(&rst_ctl);
+
+	/* initialize hardware */
+	writeb_be(0, priv->regs + SPI_IR_MASK_REG);
+
+	/* set fill register */
+	writeb_be(0xff, priv->regs + SPI_FILL_REG);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.1.4

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

* [U-Boot] [PATCH 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (2 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 arch/mips/dts/brcm,bcm6338.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a43..614792e 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -109,6 +109,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6338-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (3 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 arch/mips/dts/brcm,bcm6348.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643..841f883 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -118,6 +118,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6338-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (4 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 arch/mips/dts/brcm,bcm6358.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf8..11f990d 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -142,6 +142,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.1.4

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

* [U-Boot] [PATCH 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (5 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 arch/mips/dts/brcm,bcm3380.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index e351d58..3c19b90 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -142,6 +142,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.1.4

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

* [U-Boot] [PATCH 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (6 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 arch/mips/dts/brcm,bcm63268.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96b..8beeeef 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -136,6 +136,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.1.4

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

* [U-Boot] [PATCH 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (7 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-18 19:29 ` [U-Boot] [PATCH 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 arch/mips/dts/sagem,f at st1704.dts     | 13 +++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 21 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5..f23cd02 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -14,6 +14,7 @@
 
 	aliases {
 		serial0 = &uart0;
+		spi0 = &spi;
 	};
 
 	chosen {
@@ -44,6 +45,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 8e89c15..d20f95c 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARCH_BMIPS=y
 CONFIG_BAUDRATE=115200
+CONFIG_BCM6338_SPI=y
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
@@ -45,6 +50,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM6338=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (8 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2017-05-18 19:29 ` Álvaro Fernández Rojas
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-18 19:29 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 arch/mips/dts/netgear,cg3100d.dts     | 13 +++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 21 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7..8112c3d 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -14,6 +14,7 @@
 
 	aliases {
 		serial0 = &uart0;
+		spi0 = &spi;
 	};
 
 	chosen {
@@ -90,6 +91,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index a6eff10..da2426b 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -3,6 +3,7 @@ CONFIG_BAUDRATE=115200
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM6358_SPI=y
 CONFIG_BMIPS_BOOT_RAM=y
 CONFIG_BOARD_NETGEAR_CG3100D=y
 # CONFIG_CMD_BOOTD is not set
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="netgear,cg3100d"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -47,6 +52,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM3380=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH 01/10] drivers: spi: allow limiting reads
  2017-05-18 19:29 ` [U-Boot] [PATCH 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-05-20  2:29   ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2017-05-20  2:29 UTC (permalink / raw)
  To: u-boot

On 18 May 2017 at 13:29, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> For some SPI controllers it's not possible to keep the CS active between
> transfers and they are limited to a known number of bytes.
> This splits spi_flash reads into different iterations in order to respect
> the SPI controller limits.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  drivers/mtd/spi/spi_flash.c | 3 +++
>  include/spi.h               | 3 +++
>  2 files changed, 6 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash
  2017-05-18 19:29 ` [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash Álvaro Fernández Rojas
@ 2017-05-20  2:29   ` Simon Glass
  2017-05-20  8:06     ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 187+ messages in thread
From: Simon Glass @ 2017-05-20  2:29 UTC (permalink / raw)
  To: u-boot

Hi Alvaro,

On 18 May 2017 at 13:29, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> Command bytes are part of the written bytes and they should be taken into
> account when sending a spi transfer.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  drivers/mtd/spi/spi_flash.c | 2 +-
>  drivers/spi/Kconfig         | 3 +++
>  include/spi.h               | 8 +++++++-
>  3 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
> index e44c10f..748cc32 100644
> --- a/drivers/mtd/spi/spi_flash.c
> +++ b/drivers/mtd/spi/spi_flash.c
> @@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
>
>                 if (spi->max_write_size)
>                         chunk_len = min(chunk_len,
> -                                       (size_t)spi->max_write_size);
> +                                       spi_max_write(spi, sizeof(cmd)));
>
>                 spi_flash_addr(write_addr, cmd);
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index f3f7dbe..a00d401 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -13,6 +13,9 @@ config DM_SPI
>           typically use driver-private data instead of extending the
>           spi_slave structure.
>
> +config SPI_MAX_WRITE_CMD_BYTES
> +       bool "Include command bytes when determining max write size"

Do you really need this, or can you just always do this? If you need
it, please add detailed help.

> +
>  if DM_SPI
>
>  config ALTERA_SPI
> diff --git a/include/spi.h b/include/spi.h
> index 75a994c..310fa4d 100644
> --- a/include/spi.h
> +++ b/include/spi.h
> @@ -63,6 +63,12 @@ struct dm_spi_slave_platdata {
>
>  #endif /* CONFIG_DM_SPI */
>
> +#ifdef CONFIG_SPI_MAX_WRITE_CMD_BYTES
> +#define spi_max_write(spi, len)        (spi->max_write_size - len)
> +#else
> +#define spi_max_write(spi, len)        (spi->max_write_size)
> +#endif
> +
>  /**
>   * struct spi_slave - Representation of a SPI slave
>   *
> @@ -89,7 +95,7 @@ struct dm_spi_slave_platdata {
>   * @max_read_size:     If non-zero, the maximum number of bytes which can
>   *                     be read at once.
>   * @max_write_size:    If non-zero, the maximum number of bytes which can
> - *                     be written at once, excluding command bytes.
> + *                     be written at once.
>   * @memory_map:                Address of read-only SPI flash access.
>   * @flags:             Indication of SPI flags.
>   */
> --
> 2.1.4
>

Regards,
Simon

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-05-18 19:29 ` [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-05-20  2:29   ` Simon Glass
  2017-06-07  7:35   ` Jagan Teki
  1 sibling, 0 replies; 187+ messages in thread
From: Simon Glass @ 2017-05-20  2:29 UTC (permalink / raw)
  To: u-boot

On 18 May 2017 at 13:29, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
> Instead of supporting both HW revisions of the controller in a single build,
> support has been split by the selected config to save space.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  drivers/spi/Kconfig       |  23 +++
>  drivers/spi/Makefile      |   1 +
>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 428 insertions(+)
>  create mode 100644 drivers/spi/bcm63xx_spi.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash
  2017-05-20  2:29   ` Simon Glass
@ 2017-05-20  8:06     ` Álvaro Fernández Rojas
  2017-05-30  5:04       ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-20  8:06 UTC (permalink / raw)
  To: u-boot

Hi Simon,

El 20/05/2017 a las 4:29, Simon Glass escribió:
> Hi Alvaro,
> 
> On 18 May 2017 at 13:29, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
>> Command bytes are part of the written bytes and they should be taken into
>> account when sending a spi transfer.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> ---
>>  drivers/mtd/spi/spi_flash.c | 2 +-
>>  drivers/spi/Kconfig         | 3 +++
>>  include/spi.h               | 8 +++++++-
>>  3 files changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
>> index e44c10f..748cc32 100644
>> --- a/drivers/mtd/spi/spi_flash.c
>> +++ b/drivers/mtd/spi/spi_flash.c
>> @@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
>>
>>                 if (spi->max_write_size)
>>                         chunk_len = min(chunk_len,
>> -                                       (size_t)spi->max_write_size);
>> +                                       spi_max_write(spi, sizeof(cmd)));
>>
>>                 spi_flash_addr(write_addr, cmd);
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index f3f7dbe..a00d401 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -13,6 +13,9 @@ config DM_SPI
>>           typically use driver-private data instead of extending the
>>           spi_slave structure.
>>
>> +config SPI_MAX_WRITE_CMD_BYTES
>> +       bool "Include command bytes when determining max write size"
> 
> Do you really need this, or can you just always do this? If you need
> it, please add detailed help.
Actually we don't need this at all and we could do it always from a BCM63xx point of view, but there are drivers that are hacking this at a lower level, like the ich one:
https://github.com/Noltari/u-boot/blob/master/drivers/spi/ich.c#L355

In my opinion this is wrong, but I added that new kconfig because I didn't want to break other SPI drivers...

Maybe I should reverse it and make this the default, adding a kconfig option option which doesn't include command bytes for those drivers (fsl_qspi also uses max_write_size, but it's quite complex and didn't check if it would break it...).

> 
>> +
>>  if DM_SPI
>>
>>  config ALTERA_SPI
>> diff --git a/include/spi.h b/include/spi.h
>> index 75a994c..310fa4d 100644
>> --- a/include/spi.h
>> +++ b/include/spi.h
>> @@ -63,6 +63,12 @@ struct dm_spi_slave_platdata {
>>
>>  #endif /* CONFIG_DM_SPI */
>>
>> +#ifdef CONFIG_SPI_MAX_WRITE_CMD_BYTES
>> +#define spi_max_write(spi, len)        (spi->max_write_size - len)
>> +#else
>> +#define spi_max_write(spi, len)        (spi->max_write_size)
>> +#endif
>> +
>>  /**
>>   * struct spi_slave - Representation of a SPI slave
>>   *
>> @@ -89,7 +95,7 @@ struct dm_spi_slave_platdata {
>>   * @max_read_size:     If non-zero, the maximum number of bytes which can
>>   *                     be read at once.
>>   * @max_write_size:    If non-zero, the maximum number of bytes which can
>> - *                     be written at once, excluding command bytes.
>> + *                     be written at once.
>>   * @memory_map:                Address of read-only SPI flash access.
>>   * @flags:             Indication of SPI flags.
>>   */
>> --
>> 2.1.4
>>
> 
> Regards,
> Simon
> 

Regards,
Álvaro.

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

* [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (9 preceding siblings ...)
  2017-05-18 19:29 ` [U-Boot] [PATCH 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
@ 2017-05-22 18:21 ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (9 more replies)
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (6 subsequent siblings)
  17 siblings, 10 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (10):
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/mips/dts/brcm,bcm3380.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm63268.dtsi      |  17 ++
 arch/mips/dts/brcm,bcm6338.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6358.dtsi       |  17 ++
 arch/mips/dts/netgear,cg3100d.dts     |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 configs/netgear_cg3100d_ram_defconfig |   8 +
 configs/sagem_f at st1704_ram_defconfig  |   8 +
 drivers/mtd/spi/spi_flash.c           |   5 +-
 drivers/spi/Kconfig                   |  21 ++
 drivers/spi/Makefile                  |   1 +
 drivers/spi/bcm63xx_spi.c             | 404 ++++++++++++++++++++++++++++++++++
 include/spi.h                         |   5 +-
 14 files changed, 559 insertions(+), 2 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.1.4

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

* [U-Boot] [PATCH v2 01/10] drivers: spi: allow limiting reads
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index ab7910b..e44c10f 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -487,6 +487,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index deb65ef..75a994c 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 	u8 option;
-- 
2.1.4

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

* [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 20:27     ` Simon Glass
  2017-06-07  7:30     ` Jagan Teki
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  9 siblings, 2 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e44c10f..5b8cbc9 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - len);
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index 75a994c..f418ea1 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.1.4

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

* [U-Boot] [PATCH v2 03/10] dm: spi: add BCM63xx SPI driver
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
Instead of supporting both HW revisions of the controller in a single build,
support has been split by the selected config to save space.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v2: no changes

 drivers/spi/Kconfig       |  21 +++
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 426 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index bef864f..e452223 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,27 @@ config ATMEL_SPI
 	  many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
 	  used to access the SPI Flash, such as AT25DF321.
 
+choice
+	prompt "BCM63xx SPI driver"
+	depends on ARCH_BMIPS
+	optional
+
+config BCM6338_SPI
+	bool "BCM6338 SPI driver"
+	help
+	  Enable the BCM6338 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding this Broadcom
+	  SPI core.
+
+config BCM6358_SPI
+	bool "BCM6358 SPI driver"
+	help
+	  Enable the BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding this Broadcom
+	  SPI core.
+
+endchoice
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c090562..c9ba648 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM6338_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000..6e64607
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_BCM6338_SPI)
+
+# define SPI_DT_ID		"brcm,bcm6338-spi"
+
+/* SPI Command register */
+# define SPI_CMD_REG		0x00
+
+/* SPI Interrupt registers */
+# define SPI_IR_STAT_REG	0x02
+# define SPI_IR_MASK_REG	0x04
+
+/* SPI Clock register */
+# define SPI_CLK_REG		0x06
+
+/* SPI Fill register */
+# define SPI_FILL_REG		0x07
+
+/* SPI Control register (8 bit) */
+# define SPI_CTL_REG		0x40
+# define SPI_CTL_BYTES_SHIFT	0
+# define SPI_CTL_BYTES_MASK	(0x3f << SPI_CTL_BYTES_SHIFT)
+# define SPI_CTL_TYPE_SHIFT	6
+# define SPI_CTL_TYPE_FD_RW	(0 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_W	(1 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_R	(2 << SPI_CTL_TYPE_SHIFT)
+
+# define bcm63xx_spi_wctl(v,a)	writeb_be(v, a);
+
+/* SPI TX Data registers */
+# define SPI_TX_DATA_REG	0x41
+# define SPI_TX_DATA_SIZE	0x3f
+
+/* SPI RX Data registers */
+# define SPI_RX_DATA_REG	0x80
+# define SPI_RX_DATA_SIZE	0x3f
+
+#elif defined(CONFIG_BCM6358_SPI)
+
+# define SPI_DT_ID		"brcm,bcm6358-spi"
+
+/* SPI Control register (16 bit) */
+# define SPI_CTL_REG		0x000
+# define SPI_CTL_BYTES_SHIFT	0
+# define SPI_CTL_BYTES_MASK	(0x3ff << SPI_CTL_BYTES_SHIFT)
+# define SPI_CTL_TYPE_SHIFT	14
+# define SPI_CTL_TYPE_FD_RW	(0 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_W	(1 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_R	(2 << SPI_CTL_TYPE_SHIFT)
+
+# define bcm63xx_spi_wctl(v,a)	writew_be(v, a);
+
+/* SPI TX Data registers */
+# define SPI_TX_DATA_REG	0x002
+# define SPI_TX_DATA_SIZE	0x21e
+
+/* SPI RX Data registers */
+# define SPI_RX_DATA_REG	0x400
+# define SPI_RX_DATA_SIZE	0x220
+
+/* SPI Command register */
+# define SPI_CMD_REG		0x700
+
+/* SPI Interrupt registers */
+# define SPI_IR_STAT_REG	0x702
+# define SPI_IR_MASK_REG	0x704
+
+/* SPI Clock register */
+# define SPI_CLK_REG		0x706
+
+/* SPI Fill register */
+# define SPI_FILL_REG		0x707
+
+#endif
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+struct bcm63xx_spi_priv {
+	void __iomem *regs;
+	uint8_t num_cs;
+	size_t tx_bytes;
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		error("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->regs + SPI_CLK_REG,
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->regs + SPI_IR_MASK_REG);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			error("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > SPI_RX_DATA_SIZE) {
+			error("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
+			error("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val = 0;
+		uint8_t irq;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
+			val |= SPI_CTL_TYPE_HD_W;
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
+				val |= SPI_CTL_TYPE_FD_RW;
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
+				val |= SPI_CTL_TYPE_HD_R;
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					error("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+		bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
+
+		/* issue the transfer */
+		val = SPI_CMD_OP_START;
+		val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			val |= SPI_CMD_3WIRE_MASK;
+		writew_be(val, priv->regs + SPI_CMD_REG);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
+
+		do {
+			/* read interupts */
+			irq = readb_be(priv->regs + SPI_IR_STAT_REG);
+
+			/* transfer completed */
+			if (irq & SPI_IR_DONE_MASK)
+				break;
+		} while (1);
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{ .compatible = SPI_DT_ID, },
+	{ /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		error("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = SPI_RX_DATA_SIZE;
+	slave->max_write_size = SPI_TX_DATA_SIZE;
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = dev_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+	clk_enable(&clk);
+	clk_free(&clk);
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+	reset_deassert(&rst_ctl);
+	reset_free(&rst_ctl);
+
+	/* initialize hardware */
+	writeb_be(0, priv->regs + SPI_IR_MASK_REG);
+
+	/* set fill register */
+	writeb_be(0xff, priv->regs + SPI_FILL_REG);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.1.4

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

* [U-Boot] [PATCH v2 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a43..98bda9c 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6338-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH v2 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643..2347b71 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6338-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH v2 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf8..1662783 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.1.4

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

* [U-Boot] [PATCH v2 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index e351d58..31c4ec4 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.1.4

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

* [U-Boot] [PATCH v2 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96b..6e3d9c3 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.1.4

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

* [U-Boot] [PATCH v2 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5..dd0e5b8 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 8e89c15..d20f95c 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARCH_BMIPS=y
 CONFIG_BAUDRATE=115200
+CONFIG_BCM6338_SPI=y
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
@@ -45,6 +50,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM6338=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH v2 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2017-05-22 18:21   ` Álvaro Fernández Rojas
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-22 18:21 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7..5f85c73 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index a6eff10..da2426b 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -3,6 +3,7 @@ CONFIG_BAUDRATE=115200
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM6358_SPI=y
 CONFIG_BMIPS_BOOT_RAM=y
 CONFIG_BOARD_NETGEAR_CG3100D=y
 # CONFIG_CMD_BOOTD is not set
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="netgear,cg3100d"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -47,6 +52,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM3380=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2017-05-22 20:27     ` Simon Glass
  2017-06-07  7:30     ` Jagan Teki
  1 sibling, 0 replies; 187+ messages in thread
From: Simon Glass @ 2017-05-22 20:27 UTC (permalink / raw)
  To: u-boot

On 22 May 2017 at 12:21, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> Command bytes are part of the written bytes and they should be taken into
> account when sending a spi transfer.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v2: Introduce changes requested by Simon Glass:
>   - Always include command bytes when determining max write size.
>
>  drivers/mtd/spi/spi_flash.c | 2 +-
>  include/spi.h               | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash
  2017-05-20  8:06     ` Álvaro Fernández Rojas
@ 2017-05-30  5:04       ` Jagan Teki
  2017-05-30 17:34         ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-05-30  5:04 UTC (permalink / raw)
  To: u-boot

On Sat, May 20, 2017 at 1:36 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Hi Simon,
>
> El 20/05/2017 a las 4:29, Simon Glass escribió:
>> Hi Alvaro,
>>
>> On 18 May 2017 at 13:29, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
>>> Command bytes are part of the written bytes and they should be taken into
>>> account when sending a spi transfer.
>>>
>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>> ---
>>>  drivers/mtd/spi/spi_flash.c | 2 +-
>>>  drivers/spi/Kconfig         | 3 +++
>>>  include/spi.h               | 8 +++++++-
>>>  3 files changed, 11 insertions(+), 2 deletions(-)

Is this patch not part of your v2 BCM-SPI changes?

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash
  2017-05-30  5:04       ` Jagan Teki
@ 2017-05-30 17:34         ` Álvaro Fernández Rojas
  0 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-05-30 17:34 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

El 30/05/2017 a las 7:04, Jagan Teki escribió:
> On Sat, May 20, 2017 at 1:36 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> Hi Simon,
>>
>> El 20/05/2017 a las 4:29, Simon Glass escribió:
>>> Hi Alvaro,
>>>
>>> On 18 May 2017 at 13:29, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
>>>> Command bytes are part of the written bytes and they should be taken into
>>>> account when sending a spi transfer.
>>>>
>>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>>> ---
>>>>  drivers/mtd/spi/spi_flash.c | 2 +-
>>>>  drivers/spi/Kconfig         | 3 +++
>>>>  include/spi.h               | 8 +++++++-
>>>>  3 files changed, 11 insertions(+), 2 deletions(-)
> 
> Is this patch not part of your v2 BCM-SPI changes?
Nope, I removed it and decided to always consider command bytes as suggested by
Simon:
https://lists.denx.de/pipermail/u-boot/2017-May/292445.html

> 
> thanks!
> 

Than,
Álvaro.

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

* [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (10 preceding siblings ...)
  2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-06-03  9:57 ` Álvaro Fernández Rojas
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (9 more replies)
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (5 subsequent siblings)
  17 siblings, 10 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (10):
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/mips/dts/brcm,bcm3380.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm63268.dtsi      |  17 ++
 arch/mips/dts/brcm,bcm6338.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6358.dtsi       |  17 ++
 arch/mips/dts/netgear,cg3100d.dts     |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 configs/netgear_cg3100d_ram_defconfig |   8 +
 configs/sagem_f at st1704_ram_defconfig  |   8 +
 drivers/mtd/spi/spi_flash.c           |   5 +-
 drivers/spi/Kconfig                   |  21 ++
 drivers/spi/Makefile                  |   1 +
 drivers/spi/bcm63xx_spi.c             | 404 ++++++++++++++++++++++++++++++++++
 include/spi.h                         |   5 +-
 14 files changed, 559 insertions(+), 2 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.1.4

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

* [U-Boot] [PATCH v3 01/10] drivers: spi: allow limiting reads
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:06     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 0034a28..5ee33d8 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -487,6 +487,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 8c4b882..d0fa537 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 	u8 option;
-- 
2.1.4

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

* [U-Boot] [PATCH v3 02/10] drivers: spi: consider command bytes when sending transfers
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:08     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 5ee33d8..1e194ce 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index d0fa537..c4e1da6 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.1.4

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

* [U-Boot] [PATCH v3 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:12     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
Instead of supporting both HW revisions of the controller in a single build,
support has been split by the selected config to save space.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |  21 +++
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 426 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index bef864f..0b408db 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,27 @@ config ATMEL_SPI
 	  many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
 	  used to access the SPI Flash, such as AT25DF321.
 
+choice
+	prompt "BCM63xx SPI driver"
+	depends on ARCH_BMIPS
+	optional
+
+config BCM6348_SPI
+	bool "BCM6348 SPI driver"
+	help
+	  Enable the BCM6348 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding this Broadcom
+	  SPI core.
+
+config BCM6358_SPI
+	bool "BCM6358 SPI driver"
+	help
+	  Enable the BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding this Broadcom
+	  SPI core.
+
+endchoice
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c090562..2795a34 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM6348_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000..d3aad70
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_BCM6348_SPI)
+
+# define SPI_DT_ID		"brcm,bcm6348-spi"
+
+/* SPI Command register */
+# define SPI_CMD_REG		0x00
+
+/* SPI Interrupt registers */
+# define SPI_IR_STAT_REG	0x02
+# define SPI_IR_MASK_REG	0x04
+
+/* SPI Clock register */
+# define SPI_CLK_REG		0x06
+
+/* SPI Fill register */
+# define SPI_FILL_REG		0x07
+
+/* SPI Control register (8 bit) */
+# define SPI_CTL_REG		0x40
+# define SPI_CTL_BYTES_SHIFT	0
+# define SPI_CTL_BYTES_MASK	(0x3f << SPI_CTL_BYTES_SHIFT)
+# define SPI_CTL_TYPE_SHIFT	6
+# define SPI_CTL_TYPE_FD_RW	(0 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_W	(1 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_R	(2 << SPI_CTL_TYPE_SHIFT)
+
+# define bcm63xx_spi_wctl(v,a)	writeb_be(v, a);
+
+/* SPI TX Data registers */
+# define SPI_TX_DATA_REG	0x41
+# define SPI_TX_DATA_SIZE	0x3f
+
+/* SPI RX Data registers */
+# define SPI_RX_DATA_REG	0x80
+# define SPI_RX_DATA_SIZE	0x3f
+
+#elif defined(CONFIG_BCM6358_SPI)
+
+# define SPI_DT_ID		"brcm,bcm6358-spi"
+
+/* SPI Control register (16 bit) */
+# define SPI_CTL_REG		0x000
+# define SPI_CTL_BYTES_SHIFT	0
+# define SPI_CTL_BYTES_MASK	(0x3ff << SPI_CTL_BYTES_SHIFT)
+# define SPI_CTL_TYPE_SHIFT	14
+# define SPI_CTL_TYPE_FD_RW	(0 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_W	(1 << SPI_CTL_TYPE_SHIFT)
+# define SPI_CTL_TYPE_HD_R	(2 << SPI_CTL_TYPE_SHIFT)
+
+# define bcm63xx_spi_wctl(v,a)	writew_be(v, a);
+
+/* SPI TX Data registers */
+# define SPI_TX_DATA_REG	0x002
+# define SPI_TX_DATA_SIZE	0x21e
+
+/* SPI RX Data registers */
+# define SPI_RX_DATA_REG	0x400
+# define SPI_RX_DATA_SIZE	0x220
+
+/* SPI Command register */
+# define SPI_CMD_REG		0x700
+
+/* SPI Interrupt registers */
+# define SPI_IR_STAT_REG	0x702
+# define SPI_IR_MASK_REG	0x704
+
+/* SPI Clock register */
+# define SPI_CLK_REG		0x706
+
+/* SPI Fill register */
+# define SPI_FILL_REG		0x707
+
+#endif
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+struct bcm63xx_spi_priv {
+	void __iomem *regs;
+	uint8_t num_cs;
+	size_t tx_bytes;
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		error("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->regs + SPI_CLK_REG,
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->regs + SPI_IR_MASK_REG);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			error("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > SPI_RX_DATA_SIZE) {
+			error("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
+			error("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val = 0;
+		uint8_t irq;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
+			val |= SPI_CTL_TYPE_HD_W;
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
+				val |= SPI_CTL_TYPE_FD_RW;
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
+				val |= SPI_CTL_TYPE_HD_R;
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					error("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+		bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
+
+		/* issue the transfer */
+		val = SPI_CMD_OP_START;
+		val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			val |= SPI_CMD_3WIRE_MASK;
+		writew_be(val, priv->regs + SPI_CMD_REG);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
+
+		do {
+			/* read interupts */
+			irq = readb_be(priv->regs + SPI_IR_STAT_REG);
+
+			/* transfer completed */
+			if (irq & SPI_IR_DONE_MASK)
+				break;
+		} while (1);
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{ .compatible = SPI_DT_ID, },
+	{ /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		error("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = SPI_RX_DATA_SIZE;
+	slave->max_write_size = SPI_TX_DATA_SIZE;
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+	clk_enable(&clk);
+	clk_free(&clk);
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+	reset_deassert(&rst_ctl);
+	reset_free(&rst_ctl);
+
+	/* initialize hardware */
+	writeb_be(0, priv->regs + SPI_IR_MASK_REG);
+
+	/* set fill register */
+	writeb_be(0xff, priv->regs + SPI_FILL_REG);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.1.4

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

* [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:13     ` Daniel Schwierzeck
  2017-06-07  8:00     ` Jagan Teki
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  9 siblings, 2 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a43..0cab44c 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH v3 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:14     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643..540b9fe 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH v3 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:14     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf8..1662783 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.1.4

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

* [U-Boot] [PATCH v3 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:15     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb..f83a6ea 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.1.4

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

* [U-Boot] [PATCH v3 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:15     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96b..6e3d9c3 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.1.4

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

* [U-Boot] [PATCH v3 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:16     ` Daniel Schwierzeck
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5..dd0e5b8 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 8e89c15..3457116 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -3,6 +3,7 @@ CONFIG_BAUDRATE=115200
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM6348_SPI=y
 CONFIG_BMIPS_BOOT_RAM=y
 CONFIG_BOARD_SAGEM_FAST1704=y
 # CONFIG_CMD_BOOTD is not set
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
@@ -45,6 +50,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM6338=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH v3 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2017-06-03  9:57   ` Álvaro Fernández Rojas
  2017-06-04  9:17     ` Daniel Schwierzeck
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-03  9:57 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7..5f85c73 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index a6eff10..da2426b 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -3,6 +3,7 @@ CONFIG_BAUDRATE=115200
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM6358_SPI=y
 CONFIG_BMIPS_BOOT_RAM=y
 CONFIG_BOARD_NETGEAR_CG3100D=y
 # CONFIG_CMD_BOOTD is not set
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="netgear,cg3100d"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -47,6 +52,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM3380=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH v3 01/10] drivers: spi: allow limiting reads
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-06-04  9:06     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:06 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> For some SPI controllers it's not possible to keep the CS active between
> transfers and they are limited to a known number of bytes.
> This splits spi_flash reads into different iterations in order to respect
> the SPI controller limits.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: no changes
>  v2: no changes
> 
>  drivers/mtd/spi/spi_flash.c | 3 +++
>  include/spi.h               | 3 +++
>  2 files changed, 6 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/4a59d244/attachment.sig>

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

* [U-Boot] [PATCH v3 02/10] drivers: spi: consider command bytes when sending transfers
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2017-06-04  9:08     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:08 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> Command bytes are part of the written bytes and they should be taken into
> account when sending a spi transfer.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: Fix bug introduced in v2: sizeof(cmd) vs len
>  v2: Introduce changes requested by Simon Glass:
>   - Always include command bytes when determining max write size.
> 
>  drivers/mtd/spi/spi_flash.c | 2 +-
>  include/spi.h               | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/2f96583e/attachment.sig>

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

* [U-Boot] [PATCH v3 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-06-04  9:12     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:12 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
> Instead of supporting both HW revisions of the controller in a single build,
> support has been split by the selected config to save space.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: rename BCM6338 SPI driver to BCM6348
>   switch to devfdt_get_addr_size_index()
>  v2: no changes
> 
>  drivers/spi/Kconfig       |  21 +++
>  drivers/spi/Makefile      |   1 +
>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 426 insertions(+)
>  create mode 100644 drivers/spi/bcm63xx_spi.c
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/72d02160/attachment.sig>

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

* [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2017-06-04  9:13     ` Daniel Schwierzeck
  2017-06-07  8:00     ` Jagan Teki
  1 sibling, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:13 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> This driver manages the SPI controller present on this SoC.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: rename BCM6338 SPI driver to BCM6348
>  v2: add spi alias
> 
>  arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/e62c3e03/attachment.sig>

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

* [U-Boot] [PATCH v3 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2017-06-04  9:14     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:14 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> This driver manages the SPI controller present on this SoC.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: rename BCM6338 SPI driver to BCM6348
>  v2: add spi alias
> 
>  arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/187d06eb/attachment.sig>

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

* [U-Boot] [PATCH v3 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2017-06-04  9:14     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:14 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> This driver manages the SPI controller present on this SoC.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: no changes
>  v2: add spi alias
> 
>  arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/f42dcf0d/attachment.sig>

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

* [U-Boot] [PATCH v3 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2017-06-04  9:15     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:15 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> This driver manages the SPI controller present on this SoC.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: no changes
>  v2: add spi alias
> 
>  arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/7a42b153/attachment.sig>

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

* [U-Boot] [PATCH v3 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2017-06-04  9:15     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:15 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> This driver manages the low speed SPI controller present on this SoC.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: no changes
>  v2: add spi alias
> 
>  arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/fc732f6c/attachment.sig>

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

* [U-Boot] [PATCH v3 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2017-06-04  9:16     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:16 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> It's a Winbond (w25x32) 4 MB SPI flash.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: rename BCM6338 SPI driver to BCM6348
>  v2: remove spi alias
> 
>  arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
>  configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
>  2 files changed, 20 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/fe8c5482/attachment.sig>

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

* [U-Boot] [PATCH v3 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
@ 2017-06-04  9:17     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-06-04  9:17 UTC (permalink / raw)
  To: u-boot



Am 03.06.2017 um 11:57 schrieb Álvaro Fernández Rojas:
> It's a Spansion (s25fl064a) 8 MB SPI flash.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

> ---
>  v3: no changes
>  v2: remove spi alias
> 
>  arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
>  configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
>  2 files changed, 20 insertions(+)
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170604/b1702c83/attachment.sig>

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

* [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers
  2017-05-22 18:21   ` [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
  2017-05-22 20:27     ` Simon Glass
@ 2017-06-07  7:30     ` Jagan Teki
  2017-06-07 15:33       ` Álvaro Fernández Rojas
  1 sibling, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-07  7:30 UTC (permalink / raw)
  To: u-boot

On Mon, May 22, 2017 at 11:51 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Command bytes are part of the written bytes and they should be taken into
> account when sending a spi transfer.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v2: Introduce changes requested by Simon Glass:
>   - Always include command bytes when determining max write size.
>
>  drivers/mtd/spi/spi_flash.c | 2 +-
>  include/spi.h               | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
> index e44c10f..5b8cbc9 100644
> --- a/drivers/mtd/spi/spi_flash.c
> +++ b/drivers/mtd/spi/spi_flash.c
> @@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
>
>                 if (spi->max_write_size)
>                         chunk_len = min(chunk_len,
> -                                       (size_t)spi->max_write_size);
> +                                       spi->max_write_size - len);

This can be squashed with 01/10 with proper commit message?

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-05-18 19:29 ` [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
  2017-05-20  2:29   ` Simon Glass
@ 2017-06-07  7:35   ` Jagan Teki
  2017-06-07 15:35     ` Álvaro Fernández Rojas
  1 sibling, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-07  7:35 UTC (permalink / raw)
  To: u-boot

On Fri, May 19, 2017 at 12:59 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
> Instead of supporting both HW revisions of the controller in a single build,
> support has been split by the selected config to save space.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  drivers/spi/Kconfig       |  23 +++
>  drivers/spi/Makefile      |   1 +
>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 428 insertions(+)
>  create mode 100644 drivers/spi/bcm63xx_spi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index a00d401..d458dd7 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -43,6 +43,29 @@ config ATMEL_SPI
>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>           used to access the SPI Flash, such as AT25DF321.
>
> +choice
> +       prompt "BCM63xx SPI driver"
> +       depends on ARCH_BMIPS
> +       optional
> +
> +config BCM6338_SPI
> +       bool "BCM6338 SPI driver"
> +       select SPI_MAX_WRITE_CMD_BYTES
> +       help
> +         Enable the BCM6338 SPI driver. This driver can be used to
> +         access the SPI NOR flash on platforms embedding this Broadcom
> +         SPI core.
> +
> +config BCM6358_SPI
> +       bool "BCM6358 SPI driver"
> +       select SPI_MAX_WRITE_CMD_BYTES
> +       help
> +         Enable the BCM6358 SPI driver. This driver can be used to
> +         access the SPI NOR flash on platforms embedding this Broadcom
> +         SPI core.
> +
> +endchoice
> +
>  config CADENCE_QSPI
>         bool "Cadence QSPI driver"
>         help
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index c090562..c9ba648 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
> +obj-$(CONFIG_BCM6338_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
> new file mode 100644
> index 0000000..6e64607
> --- /dev/null
> +++ b/drivers/spi/bcm63xx_spi.c
> @@ -0,0 +1,404 @@
> +/*
> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <spi.h>
> +#include <reset.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#if defined(CONFIG_BCM6338_SPI)
> +
> +# define SPI_DT_ID             "brcm,bcm6338-spi"
> +
> +/* SPI Command register */
> +# define SPI_CMD_REG           0x00
> +
> +/* SPI Interrupt registers */
> +# define SPI_IR_STAT_REG       0x02
> +# define SPI_IR_MASK_REG       0x04
> +
> +/* SPI Clock register */
> +# define SPI_CLK_REG           0x06
> +
> +/* SPI Fill register */
> +# define SPI_FILL_REG          0x07
> +
> +/* SPI Control register (8 bit) */
> +# define SPI_CTL_REG           0x40
> +# define SPI_CTL_BYTES_SHIFT   0
> +# define SPI_CTL_BYTES_MASK    (0x3f << SPI_CTL_BYTES_SHIFT)
> +# define SPI_CTL_TYPE_SHIFT    6
> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
> +
> +# define bcm63xx_spi_wctl(v,a) writeb_be(v, a);
> +
> +/* SPI TX Data registers */
> +# define SPI_TX_DATA_REG       0x41
> +# define SPI_TX_DATA_SIZE      0x3f
> +
> +/* SPI RX Data registers */
> +# define SPI_RX_DATA_REG       0x80
> +# define SPI_RX_DATA_SIZE      0x3f
> +
> +#elif defined(CONFIG_BCM6358_SPI)
> +
> +# define SPI_DT_ID             "brcm,bcm6358-spi"
> +
> +/* SPI Control register (16 bit) */
> +# define SPI_CTL_REG           0x000
> +# define SPI_CTL_BYTES_SHIFT   0
> +# define SPI_CTL_BYTES_MASK    (0x3ff << SPI_CTL_BYTES_SHIFT)
> +# define SPI_CTL_TYPE_SHIFT    14
> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
> +
> +# define bcm63xx_spi_wctl(v,a) writew_be(v, a);
> +
> +/* SPI TX Data registers */
> +# define SPI_TX_DATA_REG       0x002
> +# define SPI_TX_DATA_SIZE      0x21e
> +
> +/* SPI RX Data registers */
> +# define SPI_RX_DATA_REG       0x400
> +# define SPI_RX_DATA_SIZE      0x220
> +
> +/* SPI Command register */
> +# define SPI_CMD_REG           0x700
> +
> +/* SPI Interrupt registers */
> +# define SPI_IR_STAT_REG       0x702
> +# define SPI_IR_MASK_REG       0x704
> +
> +/* SPI Clock register */
> +# define SPI_CLK_REG           0x706
> +
> +/* SPI Fill register */
> +# define SPI_FILL_REG          0x707
> +
> +#endif
> +
> +/* SPI Command register */
> +#define SPI_CMD_OP_SHIFT       0
> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
> +#define SPI_CMD_SLAVE_SHIFT    4
> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
> +#define SPI_CMD_PREPEND_SHIFT  8
> +#define SPI_CMD_PREPEND_BYTES  0xf
> +#define SPI_CMD_3WIRE_SHIFT    12
> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
> +
> +/* SPI Interrupt registers */
> +#define SPI_IR_DONE_SHIFT      0
> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
> +#define SPI_IR_RXOVER_SHIFT    1
> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
> +#define SPI_IR_TXUNDER_SHIFT   2
> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
> +#define SPI_IR_TXOVER_SHIFT    3
> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
> +#define SPI_IR_RXUNDER_SHIFT   4
> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
> +                                SPI_IR_RXOVER_MASK |\
> +                                SPI_IR_TXUNDER_MASK |\
> +                                SPI_IR_TXOVER_MASK |\
> +                                SPI_IR_RXUNDER_MASK)
> +
> +/* SPI Clock register */
> +#define SPI_CLK_SHIFT          0
> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
> +#define SPI_CLK_SSOFF_SHIFT    3
> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
> +#define SPI_CLK_BSWAP_SHIFT    7
> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
> +
> +#define SPI_CLK_CNT            8
> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
> +       { 25000000, SPI_CLK_25MHZ },
> +       { 20000000, SPI_CLK_20MHZ },
> +       { 12500000, SPI_CLK_12_50MHZ },
> +       {  6250000, SPI_CLK_6_250MHZ },
> +       {  3125000, SPI_CLK_3_125MHZ },
> +       {  1563000, SPI_CLK_1_563MHZ },
> +       {   781000, SPI_CLK_0_781MHZ },
> +       {   391000, SPI_CLK_0_391MHZ }
> +};
> +
> +struct bcm63xx_spi_priv {
> +       void __iomem *regs;
> +       uint8_t num_cs;
> +       size_t tx_bytes;
> +};
> +
> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
> +                          struct spi_cs_info *info)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +
> +       if (cs >= priv->num_cs) {
> +               error("no cs %u\n", cs);
> +               return -ENODEV;
> +       }
> +
> +       return 0;
> +}
> +
> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +
> +       if (mode & SPI_LSB_FIRST)
> +               setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
> +       else
> +               clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
> +
> +       return 0;
> +}
> +
> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +       uint8_t clk_cfg;
> +       int i;
> +
> +       /* default to lowest clock configuration */
> +       clk_cfg = SPI_CLK_0_391MHZ;
> +
> +       /* find the closest clock configuration */
> +       for (i = 0; i < SPI_CLK_CNT; i++) {
> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
> +                       break;
> +               }
> +       }
> +
> +       /* write clock configuration */
> +       clrsetbits_8(priv->regs + SPI_CLK_REG,
> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
> +                    clk_cfg | SPI_CLK_SSOFF_2);
> +
> +       return 0;
> +}
> +
> +/*
> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
> + * they are HW controlled.
> + * However, it provides a mechanism to prepend write transfers prior to read
> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
> + * SPI-connected flashes since reading requires prepending a write transfer of
> + * 5 bytes.
> + *
> + * This implementation takes advantage of the prepend mechanism and combines
> + * multiple transfers into a single one where possible (single/multiple write
> + * transfer(s) followed by a final read/write transfer).
> + * However, it's not possible to buffer reads, which means that read transfers
> + * should always be done as the final ones.
> + * On the other hand, take into account that combining write transfers into
> + * a single one is just buffering and doesn't require prepend mechanism.
> + */
> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +               const void *dout, void *din, unsigned long flags)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
> +       size_t data_bytes = bitlen / 8;
> +
> +       if (flags & SPI_XFER_BEGIN) {
> +               /* clear prepends */
> +               priv->tx_bytes = 0;
> +
> +               /* initialize hardware */
> +               writeb_be(0, priv->regs + SPI_IR_MASK_REG);
> +       }
> +
> +       if (din) {
> +               /* buffering reads not possible since cs is hw controlled */
> +               if (!(flags & SPI_XFER_END)) {
> +                       error("unable to buffer reads\n");
> +                       return -EINVAL;
> +               }
> +
> +               /* check rx size */
> +                if (data_bytes > SPI_RX_DATA_SIZE) {
> +                       error("max rx bytes exceeded\n");
> +                       return -EMSGSIZE;
> +               }
> +       }
> +
> +       if (dout) {
> +               /* check tx size */
> +               if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
> +                       error("max tx bytes exceeded\n");
> +                       return -EMSGSIZE;
> +               }
> +
> +               /* copy tx data */
> +               memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
> +                           dout, data_bytes);
> +               priv->tx_bytes += data_bytes;
> +       }
> +
> +       if (flags & SPI_XFER_END) {
> +               struct dm_spi_slave_platdata *plat =
> +                       dev_get_parent_platdata(dev);
> +               uint16_t val = 0;
> +               uint8_t irq;
> +
> +               /* determine control config */
> +               if (dout && !din) {
> +                       /* buffered write transfers */
> +                       val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
> +                       val |= SPI_CTL_TYPE_HD_W;
> +                       priv->tx_bytes = 0;
> +               } else {
> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
> +                               /* full duplex read/write */
> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
> +                               val |= SPI_CTL_TYPE_FD_RW;
> +                               priv->tx_bytes = 0;
> +                       } else {
> +                               /* prepended write transfer */
> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
> +                               val |= SPI_CTL_TYPE_HD_R;
> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
> +                                       error("max prepend bytes exceeded\n");
> +                                       return -EMSGSIZE;
> +                               }
> +                       }
> +               }
> +               bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
> +
> +               /* clear interrupts */
> +               writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
> +
> +               /* issue the transfer */
> +               val = SPI_CMD_OP_START;
> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
> +               if (plat->mode & SPI_3WIRE)
> +                       val |= SPI_CMD_3WIRE_MASK;
> +               writew_be(val, priv->regs + SPI_CMD_REG);
> +
> +               /* enable interrupts */
> +               writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
> +
> +               do {
> +                       /* read interupts */
> +                       irq = readb_be(priv->regs + SPI_IR_STAT_REG);
> +
> +                       /* transfer completed */
> +                       if (irq & SPI_IR_DONE_MASK)
> +                               break;
> +               } while (1);
> +
> +               /* copy rx data */
> +               if (din)
> +                       memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
> +                                     data_bytes);
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct dm_spi_ops bcm63xx_spi_ops = {
> +       .cs_info = bcm63xx_spi_cs_info,
> +       .set_mode = bcm63xx_spi_set_mode,
> +       .set_speed = bcm63xx_spi_set_speed,
> +       .xfer = bcm63xx_spi_xfer,
> +};
> +
> +static const struct udevice_id bcm63xx_spi_ids[] = {
> +       { .compatible = SPI_DT_ID, },
> +       { /* sentinel */ }

Try to add .data with reg_space of respective controller, this will
eventually reduce to driver configs and make it CONFIG_BCM63XX and
reduce unneeded#ifdef.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-06-03  9:57   ` [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
  2017-06-04  9:13     ` Daniel Schwierzeck
@ 2017-06-07  8:00     ` Jagan Teki
  2017-06-07 15:38       ` Álvaro Fernández Rojas
  1 sibling, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-07  8:00 UTC (permalink / raw)
  To: u-boot

On Sat, Jun 3, 2017 at 3:27 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v3: rename BCM6338 SPI driver to BCM6348
>  v2: add spi alias
>
>  arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
> index eb51a43..0cab44c 100644
> --- a/arch/mips/dts/brcm,bcm6338.dtsi
> +++ b/arch/mips/dts/brcm,bcm6338.dtsi
> @@ -12,6 +12,10 @@
>  / {
>         compatible = "brcm,bcm6338";
>
> +       aliases {
> +               spi0 = &spi;
> +       };
> +
>         cpus {
>                 reg = <0xfffe0000 0x4>;
>                 #address-cells = <1>;
> @@ -109,6 +113,19 @@
>                         status = "disabled";
>                 };
>
> +               spi: spi at fffe0c00 {
> +                       compatible = "brcm,bcm6348-spi";
> +                       reg = <0xfffe0c00 0xc0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +                       clocks = <&periph_clk BCM6338_CLK_SPI>;
> +                       resets = <&periph_rst BCM6338_RST_SPI>;
> +                       spi-max-frequency = <20000000>;
> +                       num-cs = <4>;
> +

space?

> +                       status = "disabled";
> +               };

As per dts(or with new node) additions/update we generally rely with
Linux for maximum possible extent So can you try to add this in Linux
first so-that we can have proper sync.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers
  2017-06-07  7:30     ` Jagan Teki
@ 2017-06-07 15:33       ` Álvaro Fernández Rojas
  2017-06-07 17:28         ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-07 15:33 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

El 7/6/17 a las 9:30, Jagan Teki escribió:
> On Mon, May 22, 2017 at 11:51 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> Command bytes are part of the written bytes and they should be taken into
>> account when sending a spi transfer.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> ---
>>  v2: Introduce changes requested by Simon Glass:
>>   - Always include command bytes when determining max write size.
>>
>>  drivers/mtd/spi/spi_flash.c | 2 +-
>>  include/spi.h               | 2 +-
>>  2 files changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
>> index e44c10f..5b8cbc9 100644
>> --- a/drivers/mtd/spi/spi_flash.c
>> +++ b/drivers/mtd/spi/spi_flash.c
>> @@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
>>
>>                 if (spi->max_write_size)
>>                         chunk_len = min(chunk_len,
>> -                                       (size_t)spi->max_write_size);
>> +                                       spi->max_write_size - len);
> 
> This can be squashed with 01/10 with proper commit message?
I think it's better if we keep it as two patches, because they are different features...

> 
> thanks!
> 

Thanks.

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-07  7:35   ` Jagan Teki
@ 2017-06-07 15:35     ` Álvaro Fernández Rojas
  2017-06-07 17:29       ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-07 15:35 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

El 7/6/17 a las 9:35, Jagan Teki escribió:
> On Fri, May 19, 2017 at 12:59 AM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>> Instead of supporting both HW revisions of the controller in a single build,
>> support has been split by the selected config to save space.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> ---
>>  drivers/spi/Kconfig       |  23 +++
>>  drivers/spi/Makefile      |   1 +
>>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 428 insertions(+)
>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index a00d401..d458dd7 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -43,6 +43,29 @@ config ATMEL_SPI
>>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>>           used to access the SPI Flash, such as AT25DF321.
>>
>> +choice
>> +       prompt "BCM63xx SPI driver"
>> +       depends on ARCH_BMIPS
>> +       optional
>> +
>> +config BCM6338_SPI
>> +       bool "BCM6338 SPI driver"
>> +       select SPI_MAX_WRITE_CMD_BYTES
>> +       help
>> +         Enable the BCM6338 SPI driver. This driver can be used to
>> +         access the SPI NOR flash on platforms embedding this Broadcom
>> +         SPI core.
>> +
>> +config BCM6358_SPI
>> +       bool "BCM6358 SPI driver"
>> +       select SPI_MAX_WRITE_CMD_BYTES
>> +       help
>> +         Enable the BCM6358 SPI driver. This driver can be used to
>> +         access the SPI NOR flash on platforms embedding this Broadcom
>> +         SPI core.
>> +
>> +endchoice
>> +
>>  config CADENCE_QSPI
>>         bool "Cadence QSPI driver"
>>         help
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index c090562..c9ba648 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>> +obj-$(CONFIG_BCM6338_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
>>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>> new file mode 100644
>> index 0000000..6e64607
>> --- /dev/null
>> +++ b/drivers/spi/bcm63xx_spi.c
>> @@ -0,0 +1,404 @@
>> +/*
>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>> + *
>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <spi.h>
>> +#include <reset.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#if defined(CONFIG_BCM6338_SPI)
>> +
>> +# define SPI_DT_ID             "brcm,bcm6338-spi"
>> +
>> +/* SPI Command register */
>> +# define SPI_CMD_REG           0x00
>> +
>> +/* SPI Interrupt registers */
>> +# define SPI_IR_STAT_REG       0x02
>> +# define SPI_IR_MASK_REG       0x04
>> +
>> +/* SPI Clock register */
>> +# define SPI_CLK_REG           0x06
>> +
>> +/* SPI Fill register */
>> +# define SPI_FILL_REG          0x07
>> +
>> +/* SPI Control register (8 bit) */
>> +# define SPI_CTL_REG           0x40
>> +# define SPI_CTL_BYTES_SHIFT   0
>> +# define SPI_CTL_BYTES_MASK    (0x3f << SPI_CTL_BYTES_SHIFT)
>> +# define SPI_CTL_TYPE_SHIFT    6
>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>> +
>> +# define bcm63xx_spi_wctl(v,a) writeb_be(v, a);
>> +
>> +/* SPI TX Data registers */
>> +# define SPI_TX_DATA_REG       0x41
>> +# define SPI_TX_DATA_SIZE      0x3f
>> +
>> +/* SPI RX Data registers */
>> +# define SPI_RX_DATA_REG       0x80
>> +# define SPI_RX_DATA_SIZE      0x3f
>> +
>> +#elif defined(CONFIG_BCM6358_SPI)
>> +
>> +# define SPI_DT_ID             "brcm,bcm6358-spi"
>> +
>> +/* SPI Control register (16 bit) */
>> +# define SPI_CTL_REG           0x000
>> +# define SPI_CTL_BYTES_SHIFT   0
>> +# define SPI_CTL_BYTES_MASK    (0x3ff << SPI_CTL_BYTES_SHIFT)
>> +# define SPI_CTL_TYPE_SHIFT    14
>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>> +
>> +# define bcm63xx_spi_wctl(v,a) writew_be(v, a);
>> +
>> +/* SPI TX Data registers */
>> +# define SPI_TX_DATA_REG       0x002
>> +# define SPI_TX_DATA_SIZE      0x21e
>> +
>> +/* SPI RX Data registers */
>> +# define SPI_RX_DATA_REG       0x400
>> +# define SPI_RX_DATA_SIZE      0x220
>> +
>> +/* SPI Command register */
>> +# define SPI_CMD_REG           0x700
>> +
>> +/* SPI Interrupt registers */
>> +# define SPI_IR_STAT_REG       0x702
>> +# define SPI_IR_MASK_REG       0x704
>> +
>> +/* SPI Clock register */
>> +# define SPI_CLK_REG           0x706
>> +
>> +/* SPI Fill register */
>> +# define SPI_FILL_REG          0x707
>> +
>> +#endif
>> +
>> +/* SPI Command register */
>> +#define SPI_CMD_OP_SHIFT       0
>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>> +#define SPI_CMD_SLAVE_SHIFT    4
>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>> +#define SPI_CMD_PREPEND_SHIFT  8
>> +#define SPI_CMD_PREPEND_BYTES  0xf
>> +#define SPI_CMD_3WIRE_SHIFT    12
>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>> +
>> +/* SPI Interrupt registers */
>> +#define SPI_IR_DONE_SHIFT      0
>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>> +#define SPI_IR_RXOVER_SHIFT    1
>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>> +#define SPI_IR_TXUNDER_SHIFT   2
>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>> +#define SPI_IR_TXOVER_SHIFT    3
>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>> +#define SPI_IR_RXUNDER_SHIFT   4
>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>> +                                SPI_IR_RXOVER_MASK |\
>> +                                SPI_IR_TXUNDER_MASK |\
>> +                                SPI_IR_TXOVER_MASK |\
>> +                                SPI_IR_RXUNDER_MASK)
>> +
>> +/* SPI Clock register */
>> +#define SPI_CLK_SHIFT          0
>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_SSOFF_SHIFT    3
>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_BSWAP_SHIFT    7
>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>> +
>> +#define SPI_CLK_CNT            8
>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>> +       { 25000000, SPI_CLK_25MHZ },
>> +       { 20000000, SPI_CLK_20MHZ },
>> +       { 12500000, SPI_CLK_12_50MHZ },
>> +       {  6250000, SPI_CLK_6_250MHZ },
>> +       {  3125000, SPI_CLK_3_125MHZ },
>> +       {  1563000, SPI_CLK_1_563MHZ },
>> +       {   781000, SPI_CLK_0_781MHZ },
>> +       {   391000, SPI_CLK_0_391MHZ }
>> +};
>> +
>> +struct bcm63xx_spi_priv {
>> +       void __iomem *regs;
>> +       uint8_t num_cs;
>> +       size_t tx_bytes;
>> +};
>> +
>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>> +                          struct spi_cs_info *info)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +
>> +       if (cs >= priv->num_cs) {
>> +               error("no cs %u\n", cs);
>> +               return -ENODEV;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +
>> +       if (mode & SPI_LSB_FIRST)
>> +               setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>> +       else
>> +               clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +       uint8_t clk_cfg;
>> +       int i;
>> +
>> +       /* default to lowest clock configuration */
>> +       clk_cfg = SPI_CLK_0_391MHZ;
>> +
>> +       /* find the closest clock configuration */
>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>> +                       break;
>> +               }
>> +       }
>> +
>> +       /* write clock configuration */
>> +       clrsetbits_8(priv->regs + SPI_CLK_REG,
>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>> +
>> +       return 0;
>> +}
>> +
>> +/*
>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>> + * they are HW controlled.
>> + * However, it provides a mechanism to prepend write transfers prior to read
>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>> + * SPI-connected flashes since reading requires prepending a write transfer of
>> + * 5 bytes.
>> + *
>> + * This implementation takes advantage of the prepend mechanism and combines
>> + * multiple transfers into a single one where possible (single/multiple write
>> + * transfer(s) followed by a final read/write transfer).
>> + * However, it's not possible to buffer reads, which means that read transfers
>> + * should always be done as the final ones.
>> + * On the other hand, take into account that combining write transfers into
>> + * a single one is just buffering and doesn't require prepend mechanism.
>> + */
>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>> +               const void *dout, void *din, unsigned long flags)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>> +       size_t data_bytes = bitlen / 8;
>> +
>> +       if (flags & SPI_XFER_BEGIN) {
>> +               /* clear prepends */
>> +               priv->tx_bytes = 0;
>> +
>> +               /* initialize hardware */
>> +               writeb_be(0, priv->regs + SPI_IR_MASK_REG);
>> +       }
>> +
>> +       if (din) {
>> +               /* buffering reads not possible since cs is hw controlled */
>> +               if (!(flags & SPI_XFER_END)) {
>> +                       error("unable to buffer reads\n");
>> +                       return -EINVAL;
>> +               }
>> +
>> +               /* check rx size */
>> +                if (data_bytes > SPI_RX_DATA_SIZE) {
>> +                       error("max rx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +       }
>> +
>> +       if (dout) {
>> +               /* check tx size */
>> +               if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
>> +                       error("max tx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +
>> +               /* copy tx data */
>> +               memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
>> +                           dout, data_bytes);
>> +               priv->tx_bytes += data_bytes;
>> +       }
>> +
>> +       if (flags & SPI_XFER_END) {
>> +               struct dm_spi_slave_platdata *plat =
>> +                       dev_get_parent_platdata(dev);
>> +               uint16_t val = 0;
>> +               uint8_t irq;
>> +
>> +               /* determine control config */
>> +               if (dout && !din) {
>> +                       /* buffered write transfers */
>> +                       val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
>> +                       val |= SPI_CTL_TYPE_HD_W;
>> +                       priv->tx_bytes = 0;
>> +               } else {
>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>> +                               /* full duplex read/write */
>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>> +                               val |= SPI_CTL_TYPE_FD_RW;
>> +                               priv->tx_bytes = 0;
>> +                       } else {
>> +                               /* prepended write transfer */
>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>> +                               val |= SPI_CTL_TYPE_HD_R;
>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>> +                                       error("max prepend bytes exceeded\n");
>> +                                       return -EMSGSIZE;
>> +                               }
>> +                       }
>> +               }
>> +               bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
>> +
>> +               /* clear interrupts */
>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
>> +
>> +               /* issue the transfer */
>> +               val = SPI_CMD_OP_START;
>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>> +               if (plat->mode & SPI_3WIRE)
>> +                       val |= SPI_CMD_3WIRE_MASK;
>> +               writew_be(val, priv->regs + SPI_CMD_REG);
>> +
>> +               /* enable interrupts */
>> +               writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
>> +
>> +               do {
>> +                       /* read interupts */
>> +                       irq = readb_be(priv->regs + SPI_IR_STAT_REG);
>> +
>> +                       /* transfer completed */
>> +                       if (irq & SPI_IR_DONE_MASK)
>> +                               break;
>> +               } while (1);
>> +
>> +               /* copy rx data */
>> +               if (din)
>> +                       memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
>> +                                     data_bytes);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct dm_spi_ops bcm63xx_spi_ops = {
>> +       .cs_info = bcm63xx_spi_cs_info,
>> +       .set_mode = bcm63xx_spi_set_mode,
>> +       .set_speed = bcm63xx_spi_set_speed,
>> +       .xfer = bcm63xx_spi_xfer,
>> +};
>> +
>> +static const struct udevice_id bcm63xx_spi_ids[] = {
>> +       { .compatible = SPI_DT_ID, },
>> +       { /* sentinel */ }
> 
> Try to add .data with reg_space of respective controller, this will
> eventually reduce to driver configs and make it CONFIG_BCM63XX and
> reduce unneeded#ifdef.
This implies adding considerable bloat to the driver...
Is it imperative for the driver to be accepted?

> 
> thanks!
> 

Thanks.

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

* [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-06-07  8:00     ` Jagan Teki
@ 2017-06-07 15:38       ` Álvaro Fernández Rojas
  2017-06-07 17:30         ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-07 15:38 UTC (permalink / raw)
  To: u-boot



El 7/6/17 a las 10:00, Jagan Teki escribió:
> On Sat, Jun 3, 2017 at 3:27 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> This driver manages the SPI controller present on this SoC.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> ---
>>  v3: rename BCM6338 SPI driver to BCM6348
>>  v2: add spi alias
>>
>>  arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
>>  1 file changed, 17 insertions(+)
>>
>> diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
>> index eb51a43..0cab44c 100644
>> --- a/arch/mips/dts/brcm,bcm6338.dtsi
>> +++ b/arch/mips/dts/brcm,bcm6338.dtsi
>> @@ -12,6 +12,10 @@
>>  / {
>>         compatible = "brcm,bcm6338";
>>
>> +       aliases {
>> +               spi0 = &spi;
>> +       };
>> +
>>         cpus {
>>                 reg = <0xfffe0000 0x4>;
>>                 #address-cells = <1>;
>> @@ -109,6 +113,19 @@
>>                         status = "disabled";
>>                 };
>>
>> +               spi: spi at fffe0c00 {
>> +                       compatible = "brcm,bcm6348-spi";
>> +                       reg = <0xfffe0c00 0xc0>;
>> +                       #address-cells = <1>;
>> +                       #size-cells = <0>;
>> +                       clocks = <&periph_clk BCM6338_CLK_SPI>;
>> +                       resets = <&periph_rst BCM6338_RST_SPI>;
>> +                       spi-max-frequency = <20000000>;
>> +                       num-cs = <4>;
>> +
> 
> space?
I added that space on every disabled node for all the bmips .dtsi files...
If you really want it removed I can do that, but it won't be in line with other nodes.

> 
>> +                       status = "disabled";
>> +               };
> 
> As per dts(or with new node) additions/update we generally rely with
> Linux for maximum possible extent So can you try to add this in Linux
> first so-that we can have proper sync.
Actually it's already upstream (even though there aren't any users yet):
https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/spi/spi-bcm63xx.txt

> 
> thanks!
> 

Thanks.

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

* [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers
  2017-06-07 15:33       ` Álvaro Fernández Rojas
@ 2017-06-07 17:28         ` Jagan Teki
  2017-06-07 18:36           ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-07 17:28 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 7, 2017 at 9:03 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Hi Jagan,
>
> El 7/6/17 a las 9:30, Jagan Teki escribió:
>> On Mon, May 22, 2017 at 11:51 PM, Álvaro Fernández Rojas
>> <noltari@gmail.com> wrote:
>>> Command bytes are part of the written bytes and they should be taken into
>>> account when sending a spi transfer.
>>>
>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>> ---
>>>  v2: Introduce changes requested by Simon Glass:
>>>   - Always include command bytes when determining max write size.
>>>
>>>  drivers/mtd/spi/spi_flash.c | 2 +-
>>>  include/spi.h               | 2 +-
>>>  2 files changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
>>> index e44c10f..5b8cbc9 100644
>>> --- a/drivers/mtd/spi/spi_flash.c
>>> +++ b/drivers/mtd/spi/spi_flash.c
>>> @@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
>>>
>>>                 if (spi->max_write_size)
>>>                         chunk_len = min(chunk_len,
>>> -                                       (size_t)spi->max_write_size);
>>> +                                       spi->max_write_size - len);
>>
>> This can be squashed with 01/10 with proper commit message?
> I think it's better if we keep it as two patches, because they are different features...

Fine, but adding immediate change followed by previous change deletion
doesn't look feature that exist.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-07 15:35     ` Álvaro Fernández Rojas
@ 2017-06-07 17:29       ` Jagan Teki
  2017-06-07 18:35         ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-07 17:29 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 7, 2017 at 9:05 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Hi Jagan,
>
> El 7/6/17 a las 9:35, Jagan Teki escribió:
>> On Fri, May 19, 2017 at 12:59 AM, Álvaro Fernández Rojas
>> <noltari@gmail.com> wrote:
>>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>>> Instead of supporting both HW revisions of the controller in a single build,
>>> support has been split by the selected config to save space.
>>>
>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>> ---
>>>  drivers/spi/Kconfig       |  23 +++
>>>  drivers/spi/Makefile      |   1 +
>>>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 428 insertions(+)
>>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>>
>>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>>> index a00d401..d458dd7 100644
>>> --- a/drivers/spi/Kconfig
>>> +++ b/drivers/spi/Kconfig
>>> @@ -43,6 +43,29 @@ config ATMEL_SPI
>>>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>>>           used to access the SPI Flash, such as AT25DF321.
>>>
>>> +choice
>>> +       prompt "BCM63xx SPI driver"
>>> +       depends on ARCH_BMIPS
>>> +       optional
>>> +
>>> +config BCM6338_SPI
>>> +       bool "BCM6338 SPI driver"
>>> +       select SPI_MAX_WRITE_CMD_BYTES
>>> +       help
>>> +         Enable the BCM6338 SPI driver. This driver can be used to
>>> +         access the SPI NOR flash on platforms embedding this Broadcom
>>> +         SPI core.
>>> +
>>> +config BCM6358_SPI
>>> +       bool "BCM6358 SPI driver"
>>> +       select SPI_MAX_WRITE_CMD_BYTES
>>> +       help
>>> +         Enable the BCM6358 SPI driver. This driver can be used to
>>> +         access the SPI NOR flash on platforms embedding this Broadcom
>>> +         SPI core.
>>> +
>>> +endchoice
>>> +
>>>  config CADENCE_QSPI
>>>         bool "Cadence QSPI driver"
>>>         help
>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>> index c090562..c9ba648 100644
>>> --- a/drivers/spi/Makefile
>>> +++ b/drivers/spi/Makefile
>>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>>> +obj-$(CONFIG_BCM6338_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
>>>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>>>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>>> new file mode 100644
>>> index 0000000..6e64607
>>> --- /dev/null
>>> +++ b/drivers/spi/bcm63xx_spi.c
>>> @@ -0,0 +1,404 @@
>>> +/*
>>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>>> + *
>>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>>> + *
>>> + * SPDX-License-Identifier: GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <clk.h>
>>> +#include <dm.h>
>>> +#include <spi.h>
>>> +#include <reset.h>
>>> +#include <asm/io.h>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +#if defined(CONFIG_BCM6338_SPI)
>>> +
>>> +# define SPI_DT_ID             "brcm,bcm6338-spi"
>>> +
>>> +/* SPI Command register */
>>> +# define SPI_CMD_REG           0x00
>>> +
>>> +/* SPI Interrupt registers */
>>> +# define SPI_IR_STAT_REG       0x02
>>> +# define SPI_IR_MASK_REG       0x04
>>> +
>>> +/* SPI Clock register */
>>> +# define SPI_CLK_REG           0x06
>>> +
>>> +/* SPI Fill register */
>>> +# define SPI_FILL_REG          0x07
>>> +
>>> +/* SPI Control register (8 bit) */
>>> +# define SPI_CTL_REG           0x40
>>> +# define SPI_CTL_BYTES_SHIFT   0
>>> +# define SPI_CTL_BYTES_MASK    (0x3f << SPI_CTL_BYTES_SHIFT)
>>> +# define SPI_CTL_TYPE_SHIFT    6
>>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>>> +
>>> +# define bcm63xx_spi_wctl(v,a) writeb_be(v, a);
>>> +
>>> +/* SPI TX Data registers */
>>> +# define SPI_TX_DATA_REG       0x41
>>> +# define SPI_TX_DATA_SIZE      0x3f
>>> +
>>> +/* SPI RX Data registers */
>>> +# define SPI_RX_DATA_REG       0x80
>>> +# define SPI_RX_DATA_SIZE      0x3f
>>> +
>>> +#elif defined(CONFIG_BCM6358_SPI)
>>> +
>>> +# define SPI_DT_ID             "brcm,bcm6358-spi"
>>> +
>>> +/* SPI Control register (16 bit) */
>>> +# define SPI_CTL_REG           0x000
>>> +# define SPI_CTL_BYTES_SHIFT   0
>>> +# define SPI_CTL_BYTES_MASK    (0x3ff << SPI_CTL_BYTES_SHIFT)
>>> +# define SPI_CTL_TYPE_SHIFT    14
>>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>>> +
>>> +# define bcm63xx_spi_wctl(v,a) writew_be(v, a);
>>> +
>>> +/* SPI TX Data registers */
>>> +# define SPI_TX_DATA_REG       0x002
>>> +# define SPI_TX_DATA_SIZE      0x21e
>>> +
>>> +/* SPI RX Data registers */
>>> +# define SPI_RX_DATA_REG       0x400
>>> +# define SPI_RX_DATA_SIZE      0x220
>>> +
>>> +/* SPI Command register */
>>> +# define SPI_CMD_REG           0x700
>>> +
>>> +/* SPI Interrupt registers */
>>> +# define SPI_IR_STAT_REG       0x702
>>> +# define SPI_IR_MASK_REG       0x704
>>> +
>>> +/* SPI Clock register */
>>> +# define SPI_CLK_REG           0x706
>>> +
>>> +/* SPI Fill register */
>>> +# define SPI_FILL_REG          0x707
>>> +
>>> +#endif
>>> +
>>> +/* SPI Command register */
>>> +#define SPI_CMD_OP_SHIFT       0
>>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>>> +#define SPI_CMD_SLAVE_SHIFT    4
>>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>>> +#define SPI_CMD_PREPEND_SHIFT  8
>>> +#define SPI_CMD_PREPEND_BYTES  0xf
>>> +#define SPI_CMD_3WIRE_SHIFT    12
>>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>>> +
>>> +/* SPI Interrupt registers */
>>> +#define SPI_IR_DONE_SHIFT      0
>>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>>> +#define SPI_IR_RXOVER_SHIFT    1
>>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>>> +#define SPI_IR_TXUNDER_SHIFT   2
>>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>>> +#define SPI_IR_TXOVER_SHIFT    3
>>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>>> +#define SPI_IR_RXUNDER_SHIFT   4
>>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>>> +                                SPI_IR_RXOVER_MASK |\
>>> +                                SPI_IR_TXUNDER_MASK |\
>>> +                                SPI_IR_TXOVER_MASK |\
>>> +                                SPI_IR_RXUNDER_MASK)
>>> +
>>> +/* SPI Clock register */
>>> +#define SPI_CLK_SHIFT          0
>>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_SSOFF_SHIFT    3
>>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>>> +#define SPI_CLK_BSWAP_SHIFT    7
>>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>>> +
>>> +#define SPI_CLK_CNT            8
>>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>>> +       { 25000000, SPI_CLK_25MHZ },
>>> +       { 20000000, SPI_CLK_20MHZ },
>>> +       { 12500000, SPI_CLK_12_50MHZ },
>>> +       {  6250000, SPI_CLK_6_250MHZ },
>>> +       {  3125000, SPI_CLK_3_125MHZ },
>>> +       {  1563000, SPI_CLK_1_563MHZ },
>>> +       {   781000, SPI_CLK_0_781MHZ },
>>> +       {   391000, SPI_CLK_0_391MHZ }
>>> +};
>>> +
>>> +struct bcm63xx_spi_priv {
>>> +       void __iomem *regs;
>>> +       uint8_t num_cs;
>>> +       size_t tx_bytes;
>>> +};
>>> +
>>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>>> +                          struct spi_cs_info *info)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>> +
>>> +       if (cs >= priv->num_cs) {
>>> +               error("no cs %u\n", cs);
>>> +               return -ENODEV;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>> +
>>> +       if (mode & SPI_LSB_FIRST)
>>> +               setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>>> +       else
>>> +               clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>> +       uint8_t clk_cfg;
>>> +       int i;
>>> +
>>> +       /* default to lowest clock configuration */
>>> +       clk_cfg = SPI_CLK_0_391MHZ;
>>> +
>>> +       /* find the closest clock configuration */
>>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>>> +                       break;
>>> +               }
>>> +       }
>>> +
>>> +       /* write clock configuration */
>>> +       clrsetbits_8(priv->regs + SPI_CLK_REG,
>>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +/*
>>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>>> + * they are HW controlled.
>>> + * However, it provides a mechanism to prepend write transfers prior to read
>>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>>> + * SPI-connected flashes since reading requires prepending a write transfer of
>>> + * 5 bytes.
>>> + *
>>> + * This implementation takes advantage of the prepend mechanism and combines
>>> + * multiple transfers into a single one where possible (single/multiple write
>>> + * transfer(s) followed by a final read/write transfer).
>>> + * However, it's not possible to buffer reads, which means that read transfers
>>> + * should always be done as the final ones.
>>> + * On the other hand, take into account that combining write transfers into
>>> + * a single one is just buffering and doesn't require prepend mechanism.
>>> + */
>>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>>> +               const void *dout, void *din, unsigned long flags)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>>> +       size_t data_bytes = bitlen / 8;
>>> +
>>> +       if (flags & SPI_XFER_BEGIN) {
>>> +               /* clear prepends */
>>> +               priv->tx_bytes = 0;
>>> +
>>> +               /* initialize hardware */
>>> +               writeb_be(0, priv->regs + SPI_IR_MASK_REG);
>>> +       }
>>> +
>>> +       if (din) {
>>> +               /* buffering reads not possible since cs is hw controlled */
>>> +               if (!(flags & SPI_XFER_END)) {
>>> +                       error("unable to buffer reads\n");
>>> +                       return -EINVAL;
>>> +               }
>>> +
>>> +               /* check rx size */
>>> +                if (data_bytes > SPI_RX_DATA_SIZE) {
>>> +                       error("max rx bytes exceeded\n");
>>> +                       return -EMSGSIZE;
>>> +               }
>>> +       }
>>> +
>>> +       if (dout) {
>>> +               /* check tx size */
>>> +               if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
>>> +                       error("max tx bytes exceeded\n");
>>> +                       return -EMSGSIZE;
>>> +               }
>>> +
>>> +               /* copy tx data */
>>> +               memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
>>> +                           dout, data_bytes);
>>> +               priv->tx_bytes += data_bytes;
>>> +       }
>>> +
>>> +       if (flags & SPI_XFER_END) {
>>> +               struct dm_spi_slave_platdata *plat =
>>> +                       dev_get_parent_platdata(dev);
>>> +               uint16_t val = 0;
>>> +               uint8_t irq;
>>> +
>>> +               /* determine control config */
>>> +               if (dout && !din) {
>>> +                       /* buffered write transfers */
>>> +                       val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
>>> +                       val |= SPI_CTL_TYPE_HD_W;
>>> +                       priv->tx_bytes = 0;
>>> +               } else {
>>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>>> +                               /* full duplex read/write */
>>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>>> +                               val |= SPI_CTL_TYPE_FD_RW;
>>> +                               priv->tx_bytes = 0;
>>> +                       } else {
>>> +                               /* prepended write transfer */
>>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>>> +                               val |= SPI_CTL_TYPE_HD_R;
>>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>>> +                                       error("max prepend bytes exceeded\n");
>>> +                                       return -EMSGSIZE;
>>> +                               }
>>> +                       }
>>> +               }
>>> +               bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
>>> +
>>> +               /* clear interrupts */
>>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
>>> +
>>> +               /* issue the transfer */
>>> +               val = SPI_CMD_OP_START;
>>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>>> +               if (plat->mode & SPI_3WIRE)
>>> +                       val |= SPI_CMD_3WIRE_MASK;
>>> +               writew_be(val, priv->regs + SPI_CMD_REG);
>>> +
>>> +               /* enable interrupts */
>>> +               writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
>>> +
>>> +               do {
>>> +                       /* read interupts */
>>> +                       irq = readb_be(priv->regs + SPI_IR_STAT_REG);
>>> +
>>> +                       /* transfer completed */
>>> +                       if (irq & SPI_IR_DONE_MASK)
>>> +                               break;
>>> +               } while (1);
>>> +
>>> +               /* copy rx data */
>>> +               if (din)
>>> +                       memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
>>> +                                     data_bytes);
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static const struct dm_spi_ops bcm63xx_spi_ops = {
>>> +       .cs_info = bcm63xx_spi_cs_info,
>>> +       .set_mode = bcm63xx_spi_set_mode,
>>> +       .set_speed = bcm63xx_spi_set_speed,
>>> +       .xfer = bcm63xx_spi_xfer,
>>> +};
>>> +
>>> +static const struct udevice_id bcm63xx_spi_ids[] = {
>>> +       { .compatible = SPI_DT_ID, },
>>> +       { /* sentinel */ }
>>
>> Try to add .data with reg_space of respective controller, this will
>> eventually reduce to driver configs and make it CONFIG_BCM63XX and
>> reduce unneeded#ifdef.
> This implies adding considerable bloat to the driver...
> Is it imperative for the driver to be accepted?

Yes, as per as recent U-boot developement we're trying to reduce
defconfig code as possible and even this method can improve code
quality.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-06-07 15:38       ` Álvaro Fernández Rojas
@ 2017-06-07 17:30         ` Jagan Teki
  2017-06-07 18:29           ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-07 17:30 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 7, 2017 at 9:08 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
>
>
> El 7/6/17 a las 10:00, Jagan Teki escribió:
>> On Sat, Jun 3, 2017 at 3:27 PM, Álvaro Fernández Rojas
>> <noltari@gmail.com> wrote:
>>> This driver manages the SPI controller present on this SoC.
>>>
>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>> ---
>>>  v3: rename BCM6338 SPI driver to BCM6348
>>>  v2: add spi alias
>>>
>>>  arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
>>>  1 file changed, 17 insertions(+)
>>>
>>> diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
>>> index eb51a43..0cab44c 100644
>>> --- a/arch/mips/dts/brcm,bcm6338.dtsi
>>> +++ b/arch/mips/dts/brcm,bcm6338.dtsi
>>> @@ -12,6 +12,10 @@
>>>  / {
>>>         compatible = "brcm,bcm6338";
>>>
>>> +       aliases {
>>> +               spi0 = &spi;
>>> +       };
>>> +
>>>         cpus {
>>>                 reg = <0xfffe0000 0x4>;
>>>                 #address-cells = <1>;
>>> @@ -109,6 +113,19 @@
>>>                         status = "disabled";
>>>                 };
>>>
>>> +               spi: spi at fffe0c00 {
>>> +                       compatible = "brcm,bcm6348-spi";
>>> +                       reg = <0xfffe0c00 0xc0>;
>>> +                       #address-cells = <1>;
>>> +                       #size-cells = <0>;
>>> +                       clocks = <&periph_clk BCM6338_CLK_SPI>;
>>> +                       resets = <&periph_rst BCM6338_RST_SPI>;
>>> +                       spi-max-frequency = <20000000>;
>>> +                       num-cs = <4>;
>>> +
>>
>> space?
> I added that space on every disabled node for all the bmips .dtsi files...
> If you really want it removed I can do that, but it won't be in line with other nodes.
>
>>
>>> +                       status = "disabled";
>>> +               };
>>
>> As per dts(or with new node) additions/update we generally rely with
>> Linux for maximum possible extent So can you try to add this in Linux
>> first so-that we can have proper sync.
> Actually it's already upstream (even though there aren't any users yet):
> https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/spi/spi-bcm63xx.txt

But what about dts file, already in upstream?

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-06-07 17:30         ` Jagan Teki
@ 2017-06-07 18:29           ` Álvaro Fernández Rojas
  0 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-07 18:29 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

El 07/06/2017 a las 19:30, Jagan Teki escribió:
> On Wed, Jun 7, 2017 at 9:08 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>>
>>
>> El 7/6/17 a las 10:00, Jagan Teki escribió:
>>> On Sat, Jun 3, 2017 at 3:27 PM, Álvaro Fernández Rojas
>>> <noltari@gmail.com> wrote:
>>>> This driver manages the SPI controller present on this SoC.
>>>>
>>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>>> ---
>>>>  v3: rename BCM6338 SPI driver to BCM6348
>>>>  v2: add spi alias
>>>>
>>>>  arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
>>>>  1 file changed, 17 insertions(+)
>>>>
>>>> diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
>>>> index eb51a43..0cab44c 100644
>>>> --- a/arch/mips/dts/brcm,bcm6338.dtsi
>>>> +++ b/arch/mips/dts/brcm,bcm6338.dtsi
>>>> @@ -12,6 +12,10 @@
>>>>  / {
>>>>         compatible = "brcm,bcm6338";
>>>>
>>>> +       aliases {
>>>> +               spi0 = &spi;
>>>> +       };
>>>> +
>>>>         cpus {
>>>>                 reg = <0xfffe0000 0x4>;
>>>>                 #address-cells = <1>;
>>>> @@ -109,6 +113,19 @@
>>>>                         status = "disabled";
>>>>                 };
>>>>
>>>> +               spi: spi at fffe0c00 {
>>>> +                       compatible = "brcm,bcm6348-spi";
>>>> +                       reg = <0xfffe0c00 0xc0>;
>>>> +                       #address-cells = <1>;
>>>> +                       #size-cells = <0>;
>>>> +                       clocks = <&periph_clk BCM6338_CLK_SPI>;
>>>> +                       resets = <&periph_rst BCM6338_RST_SPI>;
>>>> +                       spi-max-frequency = <20000000>;
>>>> +                       num-cs = <4>;
>>>> +
>>>
>>> space?
>> I added that space on every disabled node for all the bmips .dtsi files...
>> If you really want it removed I can do that, but it won't be in line with other nodes.
>>
>>>
>>>> +                       status = "disabled";
>>>> +               };
>>>
>>> As per dts(or with new node) additions/update we generally rely with
>>> Linux for maximum possible extent So can you try to add this in Linux
>>> first so-that we can have proper sync.
>> Actually it's already upstream (even though there aren't any users yet):
>> https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/spi/spi-bcm63xx.txt
> 
> But what about dts file, already in upstream?
Nope, these boards aren't in upstream since we use them for LEDE/OpenWrt and support has never been upstreamed.
Appart from that, there are currently two targets for bcm63xx -> brcm63xx and bmips, and every driver is being adapted to device tree slowly (adding support for bmips too).

> 
> thanks!
> 
Thanks.

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-07 17:29       ` Jagan Teki
@ 2017-06-07 18:35         ` Álvaro Fernández Rojas
  2017-06-12  6:02           ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-07 18:35 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

El 07/06/2017 a las 19:29, Jagan Teki escribió:
> On Wed, Jun 7, 2017 at 9:05 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> Hi Jagan,
>>
>> El 7/6/17 a las 9:35, Jagan Teki escribió:
>>> On Fri, May 19, 2017 at 12:59 AM, Álvaro Fernández Rojas
>>> <noltari@gmail.com> wrote:
>>>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>>>> Instead of supporting both HW revisions of the controller in a single build,
>>>> support has been split by the selected config to save space.
>>>>
>>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>>> ---
>>>>  drivers/spi/Kconfig       |  23 +++
>>>>  drivers/spi/Makefile      |   1 +
>>>>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>  3 files changed, 428 insertions(+)
>>>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>>>
>>>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>>>> index a00d401..d458dd7 100644
>>>> --- a/drivers/spi/Kconfig
>>>> +++ b/drivers/spi/Kconfig
>>>> @@ -43,6 +43,29 @@ config ATMEL_SPI
>>>>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>>>>           used to access the SPI Flash, such as AT25DF321.
>>>>
>>>> +choice
>>>> +       prompt "BCM63xx SPI driver"
>>>> +       depends on ARCH_BMIPS
>>>> +       optional
>>>> +
>>>> +config BCM6338_SPI
>>>> +       bool "BCM6338 SPI driver"
>>>> +       select SPI_MAX_WRITE_CMD_BYTES
>>>> +       help
>>>> +         Enable the BCM6338 SPI driver. This driver can be used to
>>>> +         access the SPI NOR flash on platforms embedding this Broadcom
>>>> +         SPI core.
>>>> +
>>>> +config BCM6358_SPI
>>>> +       bool "BCM6358 SPI driver"
>>>> +       select SPI_MAX_WRITE_CMD_BYTES
>>>> +       help
>>>> +         Enable the BCM6358 SPI driver. This driver can be used to
>>>> +         access the SPI NOR flash on platforms embedding this Broadcom
>>>> +         SPI core.
>>>> +
>>>> +endchoice
>>>> +
>>>>  config CADENCE_QSPI
>>>>         bool "Cadence QSPI driver"
>>>>         help
>>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>>> index c090562..c9ba648 100644
>>>> --- a/drivers/spi/Makefile
>>>> +++ b/drivers/spi/Makefile
>>>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>>>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>>>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>>>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>>>> +obj-$(CONFIG_BCM6338_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
>>>>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>>>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>>>>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>>>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>>>> new file mode 100644
>>>> index 0000000..6e64607
>>>> --- /dev/null
>>>> +++ b/drivers/spi/bcm63xx_spi.c
>>>> @@ -0,0 +1,404 @@
>>>> +/*
>>>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>>>> + *
>>>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>>>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>>>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>>>> + *
>>>> + * SPDX-License-Identifier: GPL-2.0+
>>>> + */
>>>> +
>>>> +#include <common.h>
>>>> +#include <clk.h>
>>>> +#include <dm.h>
>>>> +#include <spi.h>
>>>> +#include <reset.h>
>>>> +#include <asm/io.h>
>>>> +
>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>> +
>>>> +#if defined(CONFIG_BCM6338_SPI)
>>>> +
>>>> +# define SPI_DT_ID             "brcm,bcm6338-spi"
>>>> +
>>>> +/* SPI Command register */
>>>> +# define SPI_CMD_REG           0x00
>>>> +
>>>> +/* SPI Interrupt registers */
>>>> +# define SPI_IR_STAT_REG       0x02
>>>> +# define SPI_IR_MASK_REG       0x04
>>>> +
>>>> +/* SPI Clock register */
>>>> +# define SPI_CLK_REG           0x06
>>>> +
>>>> +/* SPI Fill register */
>>>> +# define SPI_FILL_REG          0x07
>>>> +
>>>> +/* SPI Control register (8 bit) */
>>>> +# define SPI_CTL_REG           0x40
>>>> +# define SPI_CTL_BYTES_SHIFT   0
>>>> +# define SPI_CTL_BYTES_MASK    (0x3f << SPI_CTL_BYTES_SHIFT)
>>>> +# define SPI_CTL_TYPE_SHIFT    6
>>>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>>>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>>>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>>>> +
>>>> +# define bcm63xx_spi_wctl(v,a) writeb_be(v, a);
>>>> +
>>>> +/* SPI TX Data registers */
>>>> +# define SPI_TX_DATA_REG       0x41
>>>> +# define SPI_TX_DATA_SIZE      0x3f
>>>> +
>>>> +/* SPI RX Data registers */
>>>> +# define SPI_RX_DATA_REG       0x80
>>>> +# define SPI_RX_DATA_SIZE      0x3f
>>>> +
>>>> +#elif defined(CONFIG_BCM6358_SPI)
>>>> +
>>>> +# define SPI_DT_ID             "brcm,bcm6358-spi"
>>>> +
>>>> +/* SPI Control register (16 bit) */
>>>> +# define SPI_CTL_REG           0x000
>>>> +# define SPI_CTL_BYTES_SHIFT   0
>>>> +# define SPI_CTL_BYTES_MASK    (0x3ff << SPI_CTL_BYTES_SHIFT)
>>>> +# define SPI_CTL_TYPE_SHIFT    14
>>>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>>>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>>>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>>>> +
>>>> +# define bcm63xx_spi_wctl(v,a) writew_be(v, a);
>>>> +
>>>> +/* SPI TX Data registers */
>>>> +# define SPI_TX_DATA_REG       0x002
>>>> +# define SPI_TX_DATA_SIZE      0x21e
>>>> +
>>>> +/* SPI RX Data registers */
>>>> +# define SPI_RX_DATA_REG       0x400
>>>> +# define SPI_RX_DATA_SIZE      0x220
>>>> +
>>>> +/* SPI Command register */
>>>> +# define SPI_CMD_REG           0x700
>>>> +
>>>> +/* SPI Interrupt registers */
>>>> +# define SPI_IR_STAT_REG       0x702
>>>> +# define SPI_IR_MASK_REG       0x704
>>>> +
>>>> +/* SPI Clock register */
>>>> +# define SPI_CLK_REG           0x706
>>>> +
>>>> +/* SPI Fill register */
>>>> +# define SPI_FILL_REG          0x707
>>>> +
>>>> +#endif
>>>> +
>>>> +/* SPI Command register */
>>>> +#define SPI_CMD_OP_SHIFT       0
>>>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>>>> +#define SPI_CMD_SLAVE_SHIFT    4
>>>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>>>> +#define SPI_CMD_PREPEND_SHIFT  8
>>>> +#define SPI_CMD_PREPEND_BYTES  0xf
>>>> +#define SPI_CMD_3WIRE_SHIFT    12
>>>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>>>> +
>>>> +/* SPI Interrupt registers */
>>>> +#define SPI_IR_DONE_SHIFT      0
>>>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>>>> +#define SPI_IR_RXOVER_SHIFT    1
>>>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>>>> +#define SPI_IR_TXUNDER_SHIFT   2
>>>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>>>> +#define SPI_IR_TXOVER_SHIFT    3
>>>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>>>> +#define SPI_IR_RXUNDER_SHIFT   4
>>>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>>>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>>>> +                                SPI_IR_RXOVER_MASK |\
>>>> +                                SPI_IR_TXUNDER_MASK |\
>>>> +                                SPI_IR_TXOVER_MASK |\
>>>> +                                SPI_IR_RXUNDER_MASK)
>>>> +
>>>> +/* SPI Clock register */
>>>> +#define SPI_CLK_SHIFT          0
>>>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>>>> +#define SPI_CLK_SSOFF_SHIFT    3
>>>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>>>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>>>> +#define SPI_CLK_BSWAP_SHIFT    7
>>>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>>>> +
>>>> +#define SPI_CLK_CNT            8
>>>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>>>> +       { 25000000, SPI_CLK_25MHZ },
>>>> +       { 20000000, SPI_CLK_20MHZ },
>>>> +       { 12500000, SPI_CLK_12_50MHZ },
>>>> +       {  6250000, SPI_CLK_6_250MHZ },
>>>> +       {  3125000, SPI_CLK_3_125MHZ },
>>>> +       {  1563000, SPI_CLK_1_563MHZ },
>>>> +       {   781000, SPI_CLK_0_781MHZ },
>>>> +       {   391000, SPI_CLK_0_391MHZ }
>>>> +};
>>>> +
>>>> +struct bcm63xx_spi_priv {
>>>> +       void __iomem *regs;
>>>> +       uint8_t num_cs;
>>>> +       size_t tx_bytes;
>>>> +};
>>>> +
>>>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>>>> +                          struct spi_cs_info *info)
>>>> +{
>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>>> +
>>>> +       if (cs >= priv->num_cs) {
>>>> +               error("no cs %u\n", cs);
>>>> +               return -ENODEV;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>>>> +{
>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>>> +
>>>> +       if (mode & SPI_LSB_FIRST)
>>>> +               setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>>>> +       else
>>>> +               clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>>>> +{
>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>>> +       uint8_t clk_cfg;
>>>> +       int i;
>>>> +
>>>> +       /* default to lowest clock configuration */
>>>> +       clk_cfg = SPI_CLK_0_391MHZ;
>>>> +
>>>> +       /* find the closest clock configuration */
>>>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>>>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>>>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>>>> +                       break;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       /* write clock configuration */
>>>> +       clrsetbits_8(priv->regs + SPI_CLK_REG,
>>>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>>>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +/*
>>>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>>>> + * they are HW controlled.
>>>> + * However, it provides a mechanism to prepend write transfers prior to read
>>>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>>>> + * SPI-connected flashes since reading requires prepending a write transfer of
>>>> + * 5 bytes.
>>>> + *
>>>> + * This implementation takes advantage of the prepend mechanism and combines
>>>> + * multiple transfers into a single one where possible (single/multiple write
>>>> + * transfer(s) followed by a final read/write transfer).
>>>> + * However, it's not possible to buffer reads, which means that read transfers
>>>> + * should always be done as the final ones.
>>>> + * On the other hand, take into account that combining write transfers into
>>>> + * a single one is just buffering and doesn't require prepend mechanism.
>>>> + */
>>>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>>>> +               const void *dout, void *din, unsigned long flags)
>>>> +{
>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>>>> +       size_t data_bytes = bitlen / 8;
>>>> +
>>>> +       if (flags & SPI_XFER_BEGIN) {
>>>> +               /* clear prepends */
>>>> +               priv->tx_bytes = 0;
>>>> +
>>>> +               /* initialize hardware */
>>>> +               writeb_be(0, priv->regs + SPI_IR_MASK_REG);
>>>> +       }
>>>> +
>>>> +       if (din) {
>>>> +               /* buffering reads not possible since cs is hw controlled */
>>>> +               if (!(flags & SPI_XFER_END)) {
>>>> +                       error("unable to buffer reads\n");
>>>> +                       return -EINVAL;
>>>> +               }
>>>> +
>>>> +               /* check rx size */
>>>> +                if (data_bytes > SPI_RX_DATA_SIZE) {
>>>> +                       error("max rx bytes exceeded\n");
>>>> +                       return -EMSGSIZE;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       if (dout) {
>>>> +               /* check tx size */
>>>> +               if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
>>>> +                       error("max tx bytes exceeded\n");
>>>> +                       return -EMSGSIZE;
>>>> +               }
>>>> +
>>>> +               /* copy tx data */
>>>> +               memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
>>>> +                           dout, data_bytes);
>>>> +               priv->tx_bytes += data_bytes;
>>>> +       }
>>>> +
>>>> +       if (flags & SPI_XFER_END) {
>>>> +               struct dm_spi_slave_platdata *plat =
>>>> +                       dev_get_parent_platdata(dev);
>>>> +               uint16_t val = 0;
>>>> +               uint8_t irq;
>>>> +
>>>> +               /* determine control config */
>>>> +               if (dout && !din) {
>>>> +                       /* buffered write transfers */
>>>> +                       val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
>>>> +                       val |= SPI_CTL_TYPE_HD_W;
>>>> +                       priv->tx_bytes = 0;
>>>> +               } else {
>>>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>>>> +                               /* full duplex read/write */
>>>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>>>> +                               val |= SPI_CTL_TYPE_FD_RW;
>>>> +                               priv->tx_bytes = 0;
>>>> +                       } else {
>>>> +                               /* prepended write transfer */
>>>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>>>> +                               val |= SPI_CTL_TYPE_HD_R;
>>>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>>>> +                                       error("max prepend bytes exceeded\n");
>>>> +                                       return -EMSGSIZE;
>>>> +                               }
>>>> +                       }
>>>> +               }
>>>> +               bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
>>>> +
>>>> +               /* clear interrupts */
>>>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
>>>> +
>>>> +               /* issue the transfer */
>>>> +               val = SPI_CMD_OP_START;
>>>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>>>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>>>> +               if (plat->mode & SPI_3WIRE)
>>>> +                       val |= SPI_CMD_3WIRE_MASK;
>>>> +               writew_be(val, priv->regs + SPI_CMD_REG);
>>>> +
>>>> +               /* enable interrupts */
>>>> +               writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
>>>> +
>>>> +               do {
>>>> +                       /* read interupts */
>>>> +                       irq = readb_be(priv->regs + SPI_IR_STAT_REG);
>>>> +
>>>> +                       /* transfer completed */
>>>> +                       if (irq & SPI_IR_DONE_MASK)
>>>> +                               break;
>>>> +               } while (1);
>>>> +
>>>> +               /* copy rx data */
>>>> +               if (din)
>>>> +                       memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
>>>> +                                     data_bytes);
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static const struct dm_spi_ops bcm63xx_spi_ops = {
>>>> +       .cs_info = bcm63xx_spi_cs_info,
>>>> +       .set_mode = bcm63xx_spi_set_mode,
>>>> +       .set_speed = bcm63xx_spi_set_speed,
>>>> +       .xfer = bcm63xx_spi_xfer,
>>>> +};
>>>> +
>>>> +static const struct udevice_id bcm63xx_spi_ids[] = {
>>>> +       { .compatible = SPI_DT_ID, },
>>>> +       { /* sentinel */ }
>>>
>>> Try to add .data with reg_space of respective controller, this will
>>> eventually reduce to driver configs and make it CONFIG_BCM63XX and
>>> reduce unneeded#ifdef.
>> This implies adding considerable bloat to the driver...
>> Is it imperative for the driver to be accepted?
> 
> Yes, as per as recent U-boot developement we're trying to reduce
> defconfig code as possible and even this method can improve code
> quality.
I don't think that method applies here, since u-boot is usally built for each SoC and supporting two cores in the same build makes no sense to me.
These should be done in two different drivers but I merged them into a single one to improve maintainability.
BTW, two u-boot developers already reviewed this patch and didn't complain about it...

> 
> thanks!
> 
Thanks.

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

* [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers
  2017-06-07 17:28         ` Jagan Teki
@ 2017-06-07 18:36           ` Álvaro Fernández Rojas
  0 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-07 18:36 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

El 07/06/2017 a las 19:28, Jagan Teki escribió:
> On Wed, Jun 7, 2017 at 9:03 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> Hi Jagan,
>>
>> El 7/6/17 a las 9:30, Jagan Teki escribió:
>>> On Mon, May 22, 2017 at 11:51 PM, Álvaro Fernández Rojas
>>> <noltari@gmail.com> wrote:
>>>> Command bytes are part of the written bytes and they should be taken into
>>>> account when sending a spi transfer.
>>>>
>>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>>> ---
>>>>  v2: Introduce changes requested by Simon Glass:
>>>>   - Always include command bytes when determining max write size.
>>>>
>>>>  drivers/mtd/spi/spi_flash.c | 2 +-
>>>>  include/spi.h               | 2 +-
>>>>  2 files changed, 2 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
>>>> index e44c10f..5b8cbc9 100644
>>>> --- a/drivers/mtd/spi/spi_flash.c
>>>> +++ b/drivers/mtd/spi/spi_flash.c
>>>> @@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
>>>>
>>>>                 if (spi->max_write_size)
>>>>                         chunk_len = min(chunk_len,
>>>> -                                       (size_t)spi->max_write_size);
>>>> +                                       spi->max_write_size - len);
>>>
>>> This can be squashed with 01/10 with proper commit message?
>> I think it's better if we keep it as two patches, because they are different features...
> 
> Fine, but adding immediate change followed by previous change deletion
> doesn't look feature that exist.
Nope, there's no previous change deletion.
First patch adds support for limited reads and second patch fixes limited writes...

> 
> thanks!
> 
Thanks

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-07 18:35         ` Álvaro Fernández Rojas
@ 2017-06-12  6:02           ` Jagan Teki
  2017-06-12 12:48             ` Simon Glass
  0 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-12  6:02 UTC (permalink / raw)
  To: u-boot

On Thu, Jun 8, 2017 at 12:05 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Hi Jagan,
>
> El 07/06/2017 a las 19:29, Jagan Teki escribió:
>> On Wed, Jun 7, 2017 at 9:05 PM, Álvaro Fernández Rojas
>> <noltari@gmail.com> wrote:
>>> Hi Jagan,
>>>
>>> El 7/6/17 a las 9:35, Jagan Teki escribió:
>>>> On Fri, May 19, 2017 at 12:59 AM, Álvaro Fernández Rojas
>>>> <noltari@gmail.com> wrote:
>>>>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>>>>> Instead of supporting both HW revisions of the controller in a single build,
>>>>> support has been split by the selected config to save space.
>>>>>
>>>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>>>> ---
>>>>>  drivers/spi/Kconfig       |  23 +++
>>>>>  drivers/spi/Makefile      |   1 +
>>>>>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>>  3 files changed, 428 insertions(+)
>>>>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>>>>
>>>>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>>>>> index a00d401..d458dd7 100644
>>>>> --- a/drivers/spi/Kconfig
>>>>> +++ b/drivers/spi/Kconfig
>>>>> @@ -43,6 +43,29 @@ config ATMEL_SPI
>>>>>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>>>>>           used to access the SPI Flash, such as AT25DF321.
>>>>>
>>>>> +choice
>>>>> +       prompt "BCM63xx SPI driver"
>>>>> +       depends on ARCH_BMIPS
>>>>> +       optional
>>>>> +
>>>>> +config BCM6338_SPI
>>>>> +       bool "BCM6338 SPI driver"
>>>>> +       select SPI_MAX_WRITE_CMD_BYTES
>>>>> +       help
>>>>> +         Enable the BCM6338 SPI driver. This driver can be used to
>>>>> +         access the SPI NOR flash on platforms embedding this Broadcom
>>>>> +         SPI core.
>>>>> +
>>>>> +config BCM6358_SPI
>>>>> +       bool "BCM6358 SPI driver"
>>>>> +       select SPI_MAX_WRITE_CMD_BYTES
>>>>> +       help
>>>>> +         Enable the BCM6358 SPI driver. This driver can be used to
>>>>> +         access the SPI NOR flash on platforms embedding this Broadcom
>>>>> +         SPI core.
>>>>> +
>>>>> +endchoice
>>>>> +
>>>>>  config CADENCE_QSPI
>>>>>         bool "Cadence QSPI driver"
>>>>>         help
>>>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>>>> index c090562..c9ba648 100644
>>>>> --- a/drivers/spi/Makefile
>>>>> +++ b/drivers/spi/Makefile
>>>>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>>>>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>>>>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>>>>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>>>>> +obj-$(CONFIG_BCM6338_SPI)$(CONFIG_BCM6358_SPI) += bcm63xx_spi.o
>>>>>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>>>>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>>>>>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>>>>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>>>>> new file mode 100644
>>>>> index 0000000..6e64607
>>>>> --- /dev/null
>>>>> +++ b/drivers/spi/bcm63xx_spi.c
>>>>> @@ -0,0 +1,404 @@
>>>>> +/*
>>>>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>>>>> + *
>>>>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>>>>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>>>>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>>>>> + *
>>>>> + * SPDX-License-Identifier: GPL-2.0+
>>>>> + */
>>>>> +
>>>>> +#include <common.h>
>>>>> +#include <clk.h>
>>>>> +#include <dm.h>
>>>>> +#include <spi.h>
>>>>> +#include <reset.h>
>>>>> +#include <asm/io.h>
>>>>> +
>>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>>> +
>>>>> +#if defined(CONFIG_BCM6338_SPI)
>>>>> +
>>>>> +# define SPI_DT_ID             "brcm,bcm6338-spi"
>>>>> +
>>>>> +/* SPI Command register */
>>>>> +# define SPI_CMD_REG           0x00
>>>>> +
>>>>> +/* SPI Interrupt registers */
>>>>> +# define SPI_IR_STAT_REG       0x02
>>>>> +# define SPI_IR_MASK_REG       0x04
>>>>> +
>>>>> +/* SPI Clock register */
>>>>> +# define SPI_CLK_REG           0x06
>>>>> +
>>>>> +/* SPI Fill register */
>>>>> +# define SPI_FILL_REG          0x07
>>>>> +
>>>>> +/* SPI Control register (8 bit) */
>>>>> +# define SPI_CTL_REG           0x40
>>>>> +# define SPI_CTL_BYTES_SHIFT   0
>>>>> +# define SPI_CTL_BYTES_MASK    (0x3f << SPI_CTL_BYTES_SHIFT)
>>>>> +# define SPI_CTL_TYPE_SHIFT    6
>>>>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>>>>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>>>>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>>>>> +
>>>>> +# define bcm63xx_spi_wctl(v,a) writeb_be(v, a);
>>>>> +
>>>>> +/* SPI TX Data registers */
>>>>> +# define SPI_TX_DATA_REG       0x41
>>>>> +# define SPI_TX_DATA_SIZE      0x3f
>>>>> +
>>>>> +/* SPI RX Data registers */
>>>>> +# define SPI_RX_DATA_REG       0x80
>>>>> +# define SPI_RX_DATA_SIZE      0x3f
>>>>> +
>>>>> +#elif defined(CONFIG_BCM6358_SPI)
>>>>> +
>>>>> +# define SPI_DT_ID             "brcm,bcm6358-spi"
>>>>> +
>>>>> +/* SPI Control register (16 bit) */
>>>>> +# define SPI_CTL_REG           0x000
>>>>> +# define SPI_CTL_BYTES_SHIFT   0
>>>>> +# define SPI_CTL_BYTES_MASK    (0x3ff << SPI_CTL_BYTES_SHIFT)
>>>>> +# define SPI_CTL_TYPE_SHIFT    14
>>>>> +# define SPI_CTL_TYPE_FD_RW    (0 << SPI_CTL_TYPE_SHIFT)
>>>>> +# define SPI_CTL_TYPE_HD_W     (1 << SPI_CTL_TYPE_SHIFT)
>>>>> +# define SPI_CTL_TYPE_HD_R     (2 << SPI_CTL_TYPE_SHIFT)
>>>>> +
>>>>> +# define bcm63xx_spi_wctl(v,a) writew_be(v, a);
>>>>> +
>>>>> +/* SPI TX Data registers */
>>>>> +# define SPI_TX_DATA_REG       0x002
>>>>> +# define SPI_TX_DATA_SIZE      0x21e
>>>>> +
>>>>> +/* SPI RX Data registers */
>>>>> +# define SPI_RX_DATA_REG       0x400
>>>>> +# define SPI_RX_DATA_SIZE      0x220
>>>>> +
>>>>> +/* SPI Command register */
>>>>> +# define SPI_CMD_REG           0x700
>>>>> +
>>>>> +/* SPI Interrupt registers */
>>>>> +# define SPI_IR_STAT_REG       0x702
>>>>> +# define SPI_IR_MASK_REG       0x704
>>>>> +
>>>>> +/* SPI Clock register */
>>>>> +# define SPI_CLK_REG           0x706
>>>>> +
>>>>> +/* SPI Fill register */
>>>>> +# define SPI_FILL_REG          0x707
>>>>> +
>>>>> +#endif
>>>>> +
>>>>> +/* SPI Command register */
>>>>> +#define SPI_CMD_OP_SHIFT       0
>>>>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>>>>> +#define SPI_CMD_SLAVE_SHIFT    4
>>>>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>>>>> +#define SPI_CMD_PREPEND_SHIFT  8
>>>>> +#define SPI_CMD_PREPEND_BYTES  0xf
>>>>> +#define SPI_CMD_3WIRE_SHIFT    12
>>>>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>>>>> +
>>>>> +/* SPI Interrupt registers */
>>>>> +#define SPI_IR_DONE_SHIFT      0
>>>>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>>>>> +#define SPI_IR_RXOVER_SHIFT    1
>>>>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>>>>> +#define SPI_IR_TXUNDER_SHIFT   2
>>>>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>>>>> +#define SPI_IR_TXOVER_SHIFT    3
>>>>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>>>>> +#define SPI_IR_RXUNDER_SHIFT   4
>>>>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>>>>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>>>>> +                                SPI_IR_RXOVER_MASK |\
>>>>> +                                SPI_IR_TXUNDER_MASK |\
>>>>> +                                SPI_IR_TXOVER_MASK |\
>>>>> +                                SPI_IR_RXUNDER_MASK)
>>>>> +
>>>>> +/* SPI Clock register */
>>>>> +#define SPI_CLK_SHIFT          0
>>>>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>>>>> +#define SPI_CLK_SSOFF_SHIFT    3
>>>>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>>>>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>>>>> +#define SPI_CLK_BSWAP_SHIFT    7
>>>>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>>>>> +
>>>>> +#define SPI_CLK_CNT            8
>>>>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>>>>> +       { 25000000, SPI_CLK_25MHZ },
>>>>> +       { 20000000, SPI_CLK_20MHZ },
>>>>> +       { 12500000, SPI_CLK_12_50MHZ },
>>>>> +       {  6250000, SPI_CLK_6_250MHZ },
>>>>> +       {  3125000, SPI_CLK_3_125MHZ },
>>>>> +       {  1563000, SPI_CLK_1_563MHZ },
>>>>> +       {   781000, SPI_CLK_0_781MHZ },
>>>>> +       {   391000, SPI_CLK_0_391MHZ }
>>>>> +};
>>>>> +
>>>>> +struct bcm63xx_spi_priv {
>>>>> +       void __iomem *regs;
>>>>> +       uint8_t num_cs;
>>>>> +       size_t tx_bytes;
>>>>> +};
>>>>> +
>>>>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>>>>> +                          struct spi_cs_info *info)
>>>>> +{
>>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>>>> +
>>>>> +       if (cs >= priv->num_cs) {
>>>>> +               error("no cs %u\n", cs);
>>>>> +               return -ENODEV;
>>>>> +       }
>>>>> +
>>>>> +       return 0;
>>>>> +}
>>>>> +
>>>>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>>>>> +{
>>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>>>> +
>>>>> +       if (mode & SPI_LSB_FIRST)
>>>>> +               setbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>>>>> +       else
>>>>> +               clrbits_8(priv->regs + SPI_CLK_REG, SPI_CLK_BSWAP_MASK);
>>>>> +
>>>>> +       return 0;
>>>>> +}
>>>>> +
>>>>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>>>>> +{
>>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>>>> +       uint8_t clk_cfg;
>>>>> +       int i;
>>>>> +
>>>>> +       /* default to lowest clock configuration */
>>>>> +       clk_cfg = SPI_CLK_0_391MHZ;
>>>>> +
>>>>> +       /* find the closest clock configuration */
>>>>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>>>>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>>>>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>>>>> +                       break;
>>>>> +               }
>>>>> +       }
>>>>> +
>>>>> +       /* write clock configuration */
>>>>> +       clrsetbits_8(priv->regs + SPI_CLK_REG,
>>>>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>>>>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>>>>> +
>>>>> +       return 0;
>>>>> +}
>>>>> +
>>>>> +/*
>>>>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>>>>> + * they are HW controlled.
>>>>> + * However, it provides a mechanism to prepend write transfers prior to read
>>>>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>>>>> + * SPI-connected flashes since reading requires prepending a write transfer of
>>>>> + * 5 bytes.
>>>>> + *
>>>>> + * This implementation takes advantage of the prepend mechanism and combines
>>>>> + * multiple transfers into a single one where possible (single/multiple write
>>>>> + * transfer(s) followed by a final read/write transfer).
>>>>> + * However, it's not possible to buffer reads, which means that read transfers
>>>>> + * should always be done as the final ones.
>>>>> + * On the other hand, take into account that combining write transfers into
>>>>> + * a single one is just buffering and doesn't require prepend mechanism.
>>>>> + */
>>>>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>>>>> +               const void *dout, void *din, unsigned long flags)
>>>>> +{
>>>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>>>>> +       size_t data_bytes = bitlen / 8;
>>>>> +
>>>>> +       if (flags & SPI_XFER_BEGIN) {
>>>>> +               /* clear prepends */
>>>>> +               priv->tx_bytes = 0;
>>>>> +
>>>>> +               /* initialize hardware */
>>>>> +               writeb_be(0, priv->regs + SPI_IR_MASK_REG);
>>>>> +       }
>>>>> +
>>>>> +       if (din) {
>>>>> +               /* buffering reads not possible since cs is hw controlled */
>>>>> +               if (!(flags & SPI_XFER_END)) {
>>>>> +                       error("unable to buffer reads\n");
>>>>> +                       return -EINVAL;
>>>>> +               }
>>>>> +
>>>>> +               /* check rx size */
>>>>> +                if (data_bytes > SPI_RX_DATA_SIZE) {
>>>>> +                       error("max rx bytes exceeded\n");
>>>>> +                       return -EMSGSIZE;
>>>>> +               }
>>>>> +       }
>>>>> +
>>>>> +       if (dout) {
>>>>> +               /* check tx size */
>>>>> +               if (priv->tx_bytes + data_bytes > SPI_TX_DATA_SIZE) {
>>>>> +                       error("max tx bytes exceeded\n");
>>>>> +                       return -EMSGSIZE;
>>>>> +               }
>>>>> +
>>>>> +               /* copy tx data */
>>>>> +               memcpy_toio(priv->regs + SPI_TX_DATA_REG + priv->tx_bytes,
>>>>> +                           dout, data_bytes);
>>>>> +               priv->tx_bytes += data_bytes;
>>>>> +       }
>>>>> +
>>>>> +       if (flags & SPI_XFER_END) {
>>>>> +               struct dm_spi_slave_platdata *plat =
>>>>> +                       dev_get_parent_platdata(dev);
>>>>> +               uint16_t val = 0;
>>>>> +               uint8_t irq;
>>>>> +
>>>>> +               /* determine control config */
>>>>> +               if (dout && !din) {
>>>>> +                       /* buffered write transfers */
>>>>> +                       val |= (priv->tx_bytes << SPI_CTL_BYTES_SHIFT);
>>>>> +                       val |= SPI_CTL_TYPE_HD_W;
>>>>> +                       priv->tx_bytes = 0;
>>>>> +               } else {
>>>>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>>>>> +                               /* full duplex read/write */
>>>>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>>>>> +                               val |= SPI_CTL_TYPE_FD_RW;
>>>>> +                               priv->tx_bytes = 0;
>>>>> +                       } else {
>>>>> +                               /* prepended write transfer */
>>>>> +                               val |= (data_bytes << SPI_CTL_BYTES_SHIFT);
>>>>> +                               val |= SPI_CTL_TYPE_HD_R;
>>>>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>>>>> +                                       error("max prepend bytes exceeded\n");
>>>>> +                                       return -EMSGSIZE;
>>>>> +                               }
>>>>> +                       }
>>>>> +               }
>>>>> +               bcm63xx_spi_wctl(val, priv->regs + SPI_CTL_REG);
>>>>> +
>>>>> +               /* clear interrupts */
>>>>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->regs + SPI_IR_STAT_REG);
>>>>> +
>>>>> +               /* issue the transfer */
>>>>> +               val = SPI_CMD_OP_START;
>>>>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>>>>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>>>>> +               if (plat->mode & SPI_3WIRE)
>>>>> +                       val |= SPI_CMD_3WIRE_MASK;
>>>>> +               writew_be(val, priv->regs + SPI_CMD_REG);
>>>>> +
>>>>> +               /* enable interrupts */
>>>>> +               writeb_be(SPI_IR_DONE_MASK, priv->regs + SPI_IR_MASK_REG);
>>>>> +
>>>>> +               do {
>>>>> +                       /* read interupts */
>>>>> +                       irq = readb_be(priv->regs + SPI_IR_STAT_REG);
>>>>> +
>>>>> +                       /* transfer completed */
>>>>> +                       if (irq & SPI_IR_DONE_MASK)
>>>>> +                               break;
>>>>> +               } while (1);
>>>>> +
>>>>> +               /* copy rx data */
>>>>> +               if (din)
>>>>> +                       memcpy_fromio(din, priv->regs + SPI_RX_DATA_REG,
>>>>> +                                     data_bytes);
>>>>> +       }
>>>>> +
>>>>> +       return 0;
>>>>> +}
>>>>> +
>>>>> +static const struct dm_spi_ops bcm63xx_spi_ops = {
>>>>> +       .cs_info = bcm63xx_spi_cs_info,
>>>>> +       .set_mode = bcm63xx_spi_set_mode,
>>>>> +       .set_speed = bcm63xx_spi_set_speed,
>>>>> +       .xfer = bcm63xx_spi_xfer,
>>>>> +};
>>>>> +
>>>>> +static const struct udevice_id bcm63xx_spi_ids[] = {
>>>>> +       { .compatible = SPI_DT_ID, },
>>>>> +       { /* sentinel */ }
>>>>
>>>> Try to add .data with reg_space of respective controller, this will
>>>> eventually reduce to driver configs and make it CONFIG_BCM63XX and
>>>> reduce unneeded#ifdef.
>>> This implies adding considerable bloat to the driver...
>>> Is it imperative for the driver to be accepted?
>>
>> Yes, as per as recent U-boot developement we're trying to reduce
>> defconfig code as possible and even this method can improve code
>> quality.
> I don't think that method applies here, since u-boot is usally built for each SoC and supporting two cores in the same build makes no sense to me.
> These should be done in two different drivers but I merged them into a single one to improve maintainability.

I don't like the approch of adding ifdef with two controller
reg_space, we have .data that has been used in many dm-driver, let's
have a try.

> BTW, two u-boot developers already reviewed this patch and didn't complain about it...

Wrong statement, it is community project every-body comment need to be
considrable.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-12  6:02           ` Jagan Teki
@ 2017-06-12 12:48             ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2017-06-12 12:48 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 June 2017 at 00:02, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> On Thu, Jun 8, 2017 at 12:05 AM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> Hi Jagan,
>>
>> El 07/06/2017 a las 19:29, Jagan Teki escribió:
>>> On Wed, Jun 7, 2017 at 9:05 PM, Álvaro Fernández Rojas
>>> <noltari@gmail.com> wrote:
>>>> Hi Jagan,
>>>>
>>>> El 7/6/17 a las 9:35, Jagan Teki escribió:
>>>>> On Fri, May 19, 2017 at 12:59 AM, Álvaro Fernández Rojas
>>>>> <noltari@gmail.com> wrote:
>>>>>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>>>>>> Instead of supporting both HW revisions of the controller in a single build,
>>>>>> support has been split by the selected config to save space.
>>>>>>
>>>>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>>>>> ---
>>>>>>  drivers/spi/Kconfig       |  23 +++
>>>>>>  drivers/spi/Makefile      |   1 +
>>>>>>  drivers/spi/bcm63xx_spi.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>>>  3 files changed, 428 insertions(+)
>>>>>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>>>>>
[...]

>>>>>> +static const struct dm_spi_ops bcm63xx_spi_ops = {
>>>>>> +       .cs_info = bcm63xx_spi_cs_info,
>>>>>> +       .set_mode = bcm63xx_spi_set_mode,
>>>>>> +       .set_speed = bcm63xx_spi_set_speed,
>>>>>> +       .xfer = bcm63xx_spi_xfer,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct udevice_id bcm63xx_spi_ids[] = {
>>>>>> +       { .compatible = SPI_DT_ID, },
>>>>>> +       { /* sentinel */ }
>>>>>
>>>>> Try to add .data with reg_space of respective controller, this will
>>>>> eventually reduce to driver configs and make it CONFIG_BCM63XX and
>>>>> reduce unneeded#ifdef.
>>>> This implies adding considerable bloat to the driver...
>>>> Is it imperative for the driver to be accepted?
>>>
>>> Yes, as per as recent U-boot developement we're trying to reduce
>>> defconfig code as possible and even this method can improve code
>>> quality.
>> I don't think that method applies here, since u-boot is usally built for each SoC and supporting two cores in the same build makes no sense to me.
>> These should be done in two different drivers but I merged them into a single one to improve maintainability.
>
> I don't like the approch of adding ifdef with two controller
> reg_space, we have .data that has been used in many dm-driver, let's
> have a try.

I do agree that #ifdefs in the driver are not desirable and it is
better to use the device tree .data field to select the correct
feature. Hopefully this involves not too much refactoring. As an
example of this see ich.c which handles a few different Intel SPI
controllers. It's a complicated driver because of the way the hardware
works but it does show how to do this sort of thing at run-time.

>
>> BTW, two u-boot developers already reviewed this patch and didn't complain about it...
>
> Wrong statement, it is community project every-body comment need to be
> considrable.
>
> thanks!
> --
> Jagan Teki
> Free Software Engineer | www.openedev.com
> U-Boot, Linux | Upstream Maintainer
> Hyderabad, India.

Regards,
Simon

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

* [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (11 preceding siblings ...)
  2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-06-14  9:57 ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (9 more replies)
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (4 subsequent siblings)
  17 siblings, 10 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v4: Introduce changes suggested by Jagan Teki:
- Add data for each HW controller instead of having two separate configs.
v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (10):
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/mips/dts/brcm,bcm3380.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm63268.dtsi      |  17 ++
 arch/mips/dts/brcm,bcm6338.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6358.dtsi       |  17 ++
 arch/mips/dts/netgear,cg3100d.dts     |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 configs/netgear_cg3100d_ram_defconfig |   8 +
 configs/sagem_f at st1704_ram_defconfig  |   8 +
 drivers/mtd/spi/spi_flash.c           |   5 +-
 drivers/spi/Kconfig                   |   8 +
 drivers/spi/Makefile                  |   1 +
 drivers/spi/bcm63xx_spi.c             | 419 ++++++++++++++++++++++++++++++++++
 include/spi.h                         |   5 +-
 14 files changed, 561 insertions(+), 2 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.1.4

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

* [U-Boot] [PATCH v4 01/10] drivers: spi: allow limiting reads
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: no changes
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 0034a28..5ee33d8 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -487,6 +487,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 8c4b882..d0fa537 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 	u8 option;
-- 
2.1.4

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

* [U-Boot] [PATCH v4 02/10] drivers: spi: consider command bytes when sending transfers
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: no changes
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 5ee33d8..1e194ce 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index d0fa537..c4e1da6 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.1.4

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

* [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-15  5:38     ` Jagan Teki
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  9 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
Instead of supporting both HW revisions of the controller in a single build,
support has been split by the selected config to save space.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: Introduce changes suggested by Jagan Teki:
  - Add data for each HW controller instead of having two separate configs.
  - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |   8 +
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 428 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index bef864f..6da78bd 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,14 @@ config ATMEL_SPI
 	  many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
 	  used to access the SPI Flash, such as AT25DF321.
 
+config BCM63XX_SPI
+	bool "BCM6348 SPI driver"
+	depends on ARCH_BMIPS
+	help
+	  Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding these Broadcom
+	  SPI cores.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c090562..260ba06 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000..e1629fa
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Control register */
+# define SPI_CTL_TYPE_FD_RW	0
+# define SPI_CTL_TYPE_HD_W	1
+# define SPI_CTL_TYPE_HD_R	2
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+struct bcm63xx_spi_hw {
+	/* SPI Clock register */
+	uint16_t clk;
+
+	/* SPI Command register */
+	uint16_t cmd;
+
+	/* SPI Control register */
+	uint16_t ctl;
+	uint8_t ctl_shift;
+
+	/* SPI Fill register */
+	uint16_t fill;
+
+	/* SPI Interrupt registers */
+	uint16_t ir_stat;
+	uint16_t ir_mask;
+
+	/* SPI RX Data registers */
+	uint16_t rx;
+	uint16_t rx_size;
+
+	/* SPI TX Data registers */
+	uint16_t tx;
+	uint16_t tx_size;
+};
+
+struct bcm63xx_spi_priv {
+	const struct bcm63xx_spi_hw *hw;
+	void __iomem *base;
+	size_t tx_bytes;
+	uint8_t num_cs;
+};
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		error("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const struct bcm63xx_spi_hw *hw = priv->hw;
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const struct bcm63xx_spi_hw *hw = priv->hw;
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->base + hw->clk,
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const struct bcm63xx_spi_hw *hw = priv->hw;
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->base + hw->ir_mask);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			error("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > hw->rx_size) {
+			error("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > hw->tx_size) {
+			error("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->base + hw->tx + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val;
+		uint8_t irq;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val = priv->tx_bytes;
+			val |= (SPI_CTL_TYPE_HD_W << hw->ctl_shift);
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_FD_RW << hw->ctl_shift);
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_HD_R << hw->ctl_shift);
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					error("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+
+		if (hw->ctl_shift >= 8)
+			writew_be(val, priv->base + hw->ctl);
+		else
+			writeb_be(val, priv->base + hw->ctl);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->base + hw->ir_stat);
+
+		/* issue the transfer */
+		val = SPI_CMD_OP_START;
+		val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			val |= SPI_CMD_3WIRE_MASK;
+		writew_be(val, priv->base + hw->cmd);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->base + hw->ir_mask);
+
+		do {
+			/* read interupts */
+			irq = readb_be(priv->base + hw->ir_stat);
+
+			/* transfer completed */
+			if (irq & SPI_IR_DONE_MASK)
+				break;
+		} while (1);
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->base + hw->rx,
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6348 = {
+	.clk = 0x06,
+	.cmd = 0x00,
+	.ctl = 0x40,
+	.ctl_shift = 6,
+	.fill = 0x07,
+	.ir_stat = 0x02,
+	.ir_mask = 0x04,
+	.rx = 0x80,
+	.rx_size = 0x3f,
+	.tx = 0x41,
+	.tx_size = 0x3f,
+};
+
+static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6358 = {
+	.clk = 0x706,
+	.cmd = 0x700,
+	.ctl = 0x000,
+	.ctl_shift = 14,
+	.fill = 0x707,
+	.ir_stat = 0x702,
+	.ir_mask = 0x704,
+	.rx = 0x400,
+	.rx_size = 0x220,
+	.tx = 0x002,
+	.tx_size = 0x21e,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-spi",
+		.data = (ulong)&bcm63xx_spi_bcm6348,
+	}, {
+		.compatible = "brcm,bcm6358-spi",
+		.data = (ulong)&bcm63xx_spi_bcm6358,
+	}, { /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const struct bcm63xx_spi_hw *hw = priv->hw;
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		error("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = hw->rx_size;
+	slave->max_write_size = hw->tx_size;
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	const struct bcm63xx_spi_hw *hw =
+		(const struct bcm63xx_spi_hw *)dev_get_driver_data(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->hw = hw;
+	priv->base = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_free(&clk);
+	if (ret < 0)
+		return ret;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_free(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	/* initialize hardware */
+	writeb_be(0, priv->base + hw->ir_mask);
+
+	/* set fill register */
+	writeb_be(0xff, priv->base + hw->fill);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.1.4

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

* [U-Boot] [PATCH v4 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a43..0cab44c 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH v4 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643..540b9fe 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.1.4

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

* [U-Boot] [PATCH v4 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf8..1662783 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.1.4

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

* [U-Boot] [PATCH v4 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb..f83a6ea 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.1.4

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

* [U-Boot] [PATCH v4 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96b..6e3d9c3 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.1.4

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

* [U-Boot] [PATCH v4 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: switch to CONFIG_BCM63XX_SPI
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5..dd0e5b8 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 8e89c15..b6f9b74 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -3,6 +3,7 @@ CONFIG_BAUDRATE=115200
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM63XX_SPI=y
 CONFIG_BMIPS_BOOT_RAM=y
 CONFIG_BOARD_SAGEM_FAST1704=y
 # CONFIG_CMD_BOOTD is not set
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
@@ -45,6 +50,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM6338=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH v4 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2017-06-14  9:57   ` Álvaro Fernández Rojas
  9 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-14  9:57 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v4: switch to CONFIG_BCM63XX_SPI
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7..5f85c73 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index a6eff10..dd6044e 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -3,6 +3,7 @@ CONFIG_BAUDRATE=115200
 CONFIG_BCM6345_CLK=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM63XX_SPI=y
 CONFIG_BMIPS_BOOT_RAM=y
 CONFIG_BOARD_NETGEAR_CG3100D=y
 # CONFIG_CMD_BOOTD is not set
@@ -27,6 +28,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_XIMG is not set
 CONFIG_DEFAULT_DEVICE_TREE="netgear,cg3100d"
 CONFIG_DISPLAY_CPUINFO=y
@@ -34,6 +37,8 @@ CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_RESET=y
 CONFIG_DM_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_HUSH_PARSER=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -47,6 +52,9 @@ CONFIG_OF_STDOUT_VIA_ALIAS=y
 CONFIG_RESET=y
 CONFIG_RESET_BCM6345=y
 CONFIG_SOC_BMIPS_BCM3380=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_NO_FLASH=y
-- 
2.1.4

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

* [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-14  9:57   ` [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-06-15  5:38     ` Jagan Teki
  2017-06-15  9:24       ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-06-15  5:38 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 14, 2017 at 3:27 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
> Instead of supporting both HW revisions of the controller in a single build,
> support has been split by the selected config to save space.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---
>  v4: Introduce changes suggested by Jagan Teki:
>   - Add data for each HW controller instead of having two separate configs.
>   - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
>  v3: rename BCM6338 SPI driver to BCM6348
>   switch to devfdt_get_addr_size_index()
>  v2: no changes
>
>  drivers/spi/Kconfig       |   8 +
>  drivers/spi/Makefile      |   1 +
>  drivers/spi/bcm63xx_spi.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 428 insertions(+)
>  create mode 100644 drivers/spi/bcm63xx_spi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index bef864f..6da78bd 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -40,6 +40,14 @@ config ATMEL_SPI
>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>           used to access the SPI Flash, such as AT25DF321.
>
> +config BCM63XX_SPI
> +       bool "BCM6348 SPI driver"
> +       depends on ARCH_BMIPS
> +       help
> +         Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
> +         access the SPI NOR flash on platforms embedding these Broadcom
> +         SPI cores.
> +
>  config CADENCE_QSPI
>         bool "Cadence QSPI driver"
>         help
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index c090562..260ba06 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
> +obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o

Thanks for doing this change.

>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
> new file mode 100644
> index 0000000..e1629fa
> --- /dev/null
> +++ b/drivers/spi/bcm63xx_spi.c
> @@ -0,0 +1,419 @@
> +/*
> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <spi.h>
> +#include <reset.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* SPI Clock register */
> +#define SPI_CLK_SHIFT          0
> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
> +#define SPI_CLK_SSOFF_SHIFT    3
> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
> +#define SPI_CLK_BSWAP_SHIFT    7
> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
> +
> +/* SPI Command register */
> +#define SPI_CMD_OP_SHIFT       0
> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
> +#define SPI_CMD_SLAVE_SHIFT    4
> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
> +#define SPI_CMD_PREPEND_SHIFT  8
> +#define SPI_CMD_PREPEND_BYTES  0xf
> +#define SPI_CMD_3WIRE_SHIFT    12
> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
> +
> +/* SPI Control register */
> +# define SPI_CTL_TYPE_FD_RW    0
> +# define SPI_CTL_TYPE_HD_W     1
> +# define SPI_CTL_TYPE_HD_R     2
> +
> +/* SPI Interrupt registers */
> +#define SPI_IR_DONE_SHIFT      0
> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
> +#define SPI_IR_RXOVER_SHIFT    1
> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
> +#define SPI_IR_TXUNDER_SHIFT   2
> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
> +#define SPI_IR_TXOVER_SHIFT    3
> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
> +#define SPI_IR_RXUNDER_SHIFT   4
> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
> +                                SPI_IR_RXOVER_MASK |\
> +                                SPI_IR_TXUNDER_MASK |\
> +                                SPI_IR_TXOVER_MASK |\
> +                                SPI_IR_RXUNDER_MASK)
> +
> +struct bcm63xx_spi_hw {
> +       /* SPI Clock register */
> +       uint16_t clk;
> +
> +       /* SPI Command register */
> +       uint16_t cmd;
> +
> +       /* SPI Control register */
> +       uint16_t ctl;
> +       uint8_t ctl_shift;
> +
> +       /* SPI Fill register */
> +       uint16_t fill;
> +
> +       /* SPI Interrupt registers */
> +       uint16_t ir_stat;
> +       uint16_t ir_mask;
> +
> +       /* SPI RX Data registers */
> +       uint16_t rx;
> +       uint16_t rx_size;
> +
> +       /* SPI TX Data registers */
> +       uint16_t tx;
> +       uint16_t tx_size;
> +};
> +
> +struct bcm63xx_spi_priv {
> +       const struct bcm63xx_spi_hw *hw;
> +       void __iomem *base;
> +       size_t tx_bytes;
> +       uint8_t num_cs;
> +};
> +
> +#define SPI_CLK_CNT            8
> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
> +       { 25000000, SPI_CLK_25MHZ },
> +       { 20000000, SPI_CLK_20MHZ },
> +       { 12500000, SPI_CLK_12_50MHZ },
> +       {  6250000, SPI_CLK_6_250MHZ },
> +       {  3125000, SPI_CLK_3_125MHZ },
> +       {  1563000, SPI_CLK_1_563MHZ },
> +       {   781000, SPI_CLK_0_781MHZ },
> +       {   391000, SPI_CLK_0_391MHZ }
> +};
> +
> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
> +                          struct spi_cs_info *info)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +
> +       if (cs >= priv->num_cs) {
> +               error("no cs %u\n", cs);
> +               return -ENODEV;
> +       }
> +
> +       return 0;
> +}
> +
> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +       const struct bcm63xx_spi_hw *hw = priv->hw;
> +
> +       if (mode & SPI_LSB_FIRST)
> +               setbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
> +       else
> +               clrbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
> +
> +       return 0;
> +}
> +
> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +       const struct bcm63xx_spi_hw *hw = priv->hw;
> +       uint8_t clk_cfg;
> +       int i;
> +
> +       /* default to lowest clock configuration */
> +       clk_cfg = SPI_CLK_0_391MHZ;
> +
> +       /* find the closest clock configuration */
> +       for (i = 0; i < SPI_CLK_CNT; i++) {
> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
> +                       break;
> +               }
> +       }
> +
> +       /* write clock configuration */
> +       clrsetbits_8(priv->base + hw->clk,
> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
> +                    clk_cfg | SPI_CLK_SSOFF_2);
> +
> +       return 0;
> +}
> +
> +/*
> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
> + * they are HW controlled.
> + * However, it provides a mechanism to prepend write transfers prior to read
> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
> + * SPI-connected flashes since reading requires prepending a write transfer of
> + * 5 bytes.
> + *
> + * This implementation takes advantage of the prepend mechanism and combines
> + * multiple transfers into a single one where possible (single/multiple write
> + * transfer(s) followed by a final read/write transfer).
> + * However, it's not possible to buffer reads, which means that read transfers
> + * should always be done as the final ones.
> + * On the other hand, take into account that combining write transfers into
> + * a single one is just buffering and doesn't require prepend mechanism.
> + */
> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +               const void *dout, void *din, unsigned long flags)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
> +       const struct bcm63xx_spi_hw *hw = priv->hw;
> +       size_t data_bytes = bitlen / 8;
> +
> +       if (flags & SPI_XFER_BEGIN) {
> +               /* clear prepends */
> +               priv->tx_bytes = 0;
> +
> +               /* initialize hardware */
> +               writeb_be(0, priv->base + hw->ir_mask);
> +       }
> +
> +       if (din) {
> +               /* buffering reads not possible since cs is hw controlled */
> +               if (!(flags & SPI_XFER_END)) {
> +                       error("unable to buffer reads\n");
> +                       return -EINVAL;
> +               }
> +
> +               /* check rx size */
> +                if (data_bytes > hw->rx_size) {
> +                       error("max rx bytes exceeded\n");
> +                       return -EMSGSIZE;
> +               }
> +       }
> +
> +       if (dout) {
> +               /* check tx size */
> +               if (priv->tx_bytes + data_bytes > hw->tx_size) {
> +                       error("max tx bytes exceeded\n");
> +                       return -EMSGSIZE;
> +               }
> +
> +               /* copy tx data */
> +               memcpy_toio(priv->base + hw->tx + priv->tx_bytes,
> +                           dout, data_bytes);
> +               priv->tx_bytes += data_bytes;
> +       }
> +
> +       if (flags & SPI_XFER_END) {
> +               struct dm_spi_slave_platdata *plat =
> +                       dev_get_parent_platdata(dev);
> +               uint16_t val;
> +               uint8_t irq;
> +
> +               /* determine control config */
> +               if (dout && !din) {
> +                       /* buffered write transfers */
> +                       val = priv->tx_bytes;
> +                       val |= (SPI_CTL_TYPE_HD_W << hw->ctl_shift);
> +                       priv->tx_bytes = 0;
> +               } else {
> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
> +                               /* full duplex read/write */
> +                               val = data_bytes;
> +                               val |= (SPI_CTL_TYPE_FD_RW << hw->ctl_shift);
> +                               priv->tx_bytes = 0;
> +                       } else {
> +                               /* prepended write transfer */
> +                               val = data_bytes;
> +                               val |= (SPI_CTL_TYPE_HD_R << hw->ctl_shift);
> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
> +                                       error("max prepend bytes exceeded\n");
> +                                       return -EMSGSIZE;
> +                               }
> +                       }
> +               }
> +
> +               if (hw->ctl_shift >= 8)
> +                       writew_be(val, priv->base + hw->ctl);
> +               else
> +                       writeb_be(val, priv->base + hw->ctl);
> +
> +               /* clear interrupts */
> +               writeb_be(SPI_IR_CLEAR_MASK, priv->base + hw->ir_stat);
> +
> +               /* issue the transfer */
> +               val = SPI_CMD_OP_START;
> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
> +               if (plat->mode & SPI_3WIRE)
> +                       val |= SPI_CMD_3WIRE_MASK;
> +               writew_be(val, priv->base + hw->cmd);
> +
> +               /* enable interrupts */
> +               writeb_be(SPI_IR_DONE_MASK, priv->base + hw->ir_mask);
> +
> +               do {
> +                       /* read interupts */
> +                       irq = readb_be(priv->base + hw->ir_stat);
> +
> +                       /* transfer completed */
> +                       if (irq & SPI_IR_DONE_MASK)
> +                               break;
> +               } while (1);
> +
> +               /* copy rx data */
> +               if (din)
> +                       memcpy_fromio(din, priv->base + hw->rx,
> +                                     data_bytes);
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct dm_spi_ops bcm63xx_spi_ops = {
> +       .cs_info = bcm63xx_spi_cs_info,
> +       .set_mode = bcm63xx_spi_set_mode,
> +       .set_speed = bcm63xx_spi_set_speed,
> +       .xfer = bcm63xx_spi_xfer,
> +};
> +
> +static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6348 = {
> +       .clk = 0x06,
> +       .cmd = 0x00,
> +       .ctl = 0x40,
> +       .ctl_shift = 6,
> +       .fill = 0x07,
> +       .ir_stat = 0x02,
> +       .ir_mask = 0x04,
> +       .rx = 0x80,
> +       .rx_size = 0x3f,
> +       .tx = 0x41,
> +       .tx_size = 0x3f,
> +};

Define these hexcodes into macros like SPI_6348_CLK_CFG

> +
> +static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6358 = {
> +       .clk = 0x706,
> +       .cmd = 0x700,
> +       .ctl = 0x000,
> +       .ctl_shift = 14,
> +       .fill = 0x707,
> +       .ir_stat = 0x702,
> +       .ir_mask = 0x704,
> +       .rx = 0x400,
> +       .rx_size = 0x220,
> +       .tx = 0x002,
> +       .tx_size = 0x21e,
> +};

Define these hexcodes into macros like SPI_6358_CLK_CFG

> +
> +static const struct udevice_id bcm63xx_spi_ids[] = {
> +       {
> +               .compatible = "brcm,bcm6348-spi",
> +               .data = (ulong)&bcm63xx_spi_bcm6348,
> +       }, {
> +               .compatible = "brcm,bcm6358-spi",
> +               .data = (ulong)&bcm63xx_spi_bcm6358,
> +       }, { /* sentinel */ }
> +};

I think this can even write more like long value instead making it in
structure, so-that rotating the 'struct bcm63xx_spi_hw' to respective
functions can avoid. like definig members in enum and use these as an
offset along with specific reg_space while doing io ops.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-15  5:38     ` Jagan Teki
@ 2017-06-15  9:24       ` Álvaro Fernández Rojas
  2017-06-19 11:37         ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-06-15  9:24 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

El 15/6/17 a las 7:38, Jagan Teki escribió:
> On Wed, Jun 14, 2017 at 3:27 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>> Instead of supporting both HW revisions of the controller in a single build,
>> support has been split by the selected config to save space.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>> ---
>>  v4: Introduce changes suggested by Jagan Teki:
>>   - Add data for each HW controller instead of having two separate configs.
>>   - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
>>  v3: rename BCM6338 SPI driver to BCM6348
>>   switch to devfdt_get_addr_size_index()
>>  v2: no changes
>>
>>  drivers/spi/Kconfig       |   8 +
>>  drivers/spi/Makefile      |   1 +
>>  drivers/spi/bcm63xx_spi.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 428 insertions(+)
>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index bef864f..6da78bd 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -40,6 +40,14 @@ config ATMEL_SPI
>>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>>           used to access the SPI Flash, such as AT25DF321.
>>
>> +config BCM63XX_SPI
>> +       bool "BCM6348 SPI driver"
>> +       depends on ARCH_BMIPS
>> +       help
>> +         Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
>> +         access the SPI NOR flash on platforms embedding these Broadcom
>> +         SPI cores.
>> +
>>  config CADENCE_QSPI
>>         bool "Cadence QSPI driver"
>>         help
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index c090562..260ba06 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>> +obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
> 
> Thanks for doing this change.
That's what you requested ;).

> 
>>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>> new file mode 100644
>> index 0000000..e1629fa
>> --- /dev/null
>> +++ b/drivers/spi/bcm63xx_spi.c
>> @@ -0,0 +1,419 @@
>> +/*
>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>> + *
>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <spi.h>
>> +#include <reset.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +/* SPI Clock register */
>> +#define SPI_CLK_SHIFT          0
>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_SSOFF_SHIFT    3
>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_BSWAP_SHIFT    7
>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>> +
>> +/* SPI Command register */
>> +#define SPI_CMD_OP_SHIFT       0
>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>> +#define SPI_CMD_SLAVE_SHIFT    4
>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>> +#define SPI_CMD_PREPEND_SHIFT  8
>> +#define SPI_CMD_PREPEND_BYTES  0xf
>> +#define SPI_CMD_3WIRE_SHIFT    12
>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>> +
>> +/* SPI Control register */
>> +# define SPI_CTL_TYPE_FD_RW    0
>> +# define SPI_CTL_TYPE_HD_W     1
>> +# define SPI_CTL_TYPE_HD_R     2
>> +
>> +/* SPI Interrupt registers */
>> +#define SPI_IR_DONE_SHIFT      0
>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>> +#define SPI_IR_RXOVER_SHIFT    1
>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>> +#define SPI_IR_TXUNDER_SHIFT   2
>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>> +#define SPI_IR_TXOVER_SHIFT    3
>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>> +#define SPI_IR_RXUNDER_SHIFT   4
>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>> +                                SPI_IR_RXOVER_MASK |\
>> +                                SPI_IR_TXUNDER_MASK |\
>> +                                SPI_IR_TXOVER_MASK |\
>> +                                SPI_IR_RXUNDER_MASK)
>> +
>> +struct bcm63xx_spi_hw {
>> +       /* SPI Clock register */
>> +       uint16_t clk;
>> +
>> +       /* SPI Command register */
>> +       uint16_t cmd;
>> +
>> +       /* SPI Control register */
>> +       uint16_t ctl;
>> +       uint8_t ctl_shift;
>> +
>> +       /* SPI Fill register */
>> +       uint16_t fill;
>> +
>> +       /* SPI Interrupt registers */
>> +       uint16_t ir_stat;
>> +       uint16_t ir_mask;
>> +
>> +       /* SPI RX Data registers */
>> +       uint16_t rx;
>> +       uint16_t rx_size;
>> +
>> +       /* SPI TX Data registers */
>> +       uint16_t tx;
>> +       uint16_t tx_size;
>> +};
>> +
>> +struct bcm63xx_spi_priv {
>> +       const struct bcm63xx_spi_hw *hw;
>> +       void __iomem *base;
>> +       size_t tx_bytes;
>> +       uint8_t num_cs;
>> +};
>> +
>> +#define SPI_CLK_CNT            8
>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>> +       { 25000000, SPI_CLK_25MHZ },
>> +       { 20000000, SPI_CLK_20MHZ },
>> +       { 12500000, SPI_CLK_12_50MHZ },
>> +       {  6250000, SPI_CLK_6_250MHZ },
>> +       {  3125000, SPI_CLK_3_125MHZ },
>> +       {  1563000, SPI_CLK_1_563MHZ },
>> +       {   781000, SPI_CLK_0_781MHZ },
>> +       {   391000, SPI_CLK_0_391MHZ }
>> +};
>> +
>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>> +                          struct spi_cs_info *info)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +
>> +       if (cs >= priv->num_cs) {
>> +               error("no cs %u\n", cs);
>> +               return -ENODEV;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +       const struct bcm63xx_spi_hw *hw = priv->hw;
>> +
>> +       if (mode & SPI_LSB_FIRST)
>> +               setbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
>> +       else
>> +               clrbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +       const struct bcm63xx_spi_hw *hw = priv->hw;
>> +       uint8_t clk_cfg;
>> +       int i;
>> +
>> +       /* default to lowest clock configuration */
>> +       clk_cfg = SPI_CLK_0_391MHZ;
>> +
>> +       /* find the closest clock configuration */
>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>> +                       break;
>> +               }
>> +       }
>> +
>> +       /* write clock configuration */
>> +       clrsetbits_8(priv->base + hw->clk,
>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>> +
>> +       return 0;
>> +}
>> +
>> +/*
>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>> + * they are HW controlled.
>> + * However, it provides a mechanism to prepend write transfers prior to read
>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>> + * SPI-connected flashes since reading requires prepending a write transfer of
>> + * 5 bytes.
>> + *
>> + * This implementation takes advantage of the prepend mechanism and combines
>> + * multiple transfers into a single one where possible (single/multiple write
>> + * transfer(s) followed by a final read/write transfer).
>> + * However, it's not possible to buffer reads, which means that read transfers
>> + * should always be done as the final ones.
>> + * On the other hand, take into account that combining write transfers into
>> + * a single one is just buffering and doesn't require prepend mechanism.
>> + */
>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>> +               const void *dout, void *din, unsigned long flags)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>> +       const struct bcm63xx_spi_hw *hw = priv->hw;
>> +       size_t data_bytes = bitlen / 8;
>> +
>> +       if (flags & SPI_XFER_BEGIN) {
>> +               /* clear prepends */
>> +               priv->tx_bytes = 0;
>> +
>> +               /* initialize hardware */
>> +               writeb_be(0, priv->base + hw->ir_mask);
>> +       }
>> +
>> +       if (din) {
>> +               /* buffering reads not possible since cs is hw controlled */
>> +               if (!(flags & SPI_XFER_END)) {
>> +                       error("unable to buffer reads\n");
>> +                       return -EINVAL;
>> +               }
>> +
>> +               /* check rx size */
>> +                if (data_bytes > hw->rx_size) {
>> +                       error("max rx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +       }
>> +
>> +       if (dout) {
>> +               /* check tx size */
>> +               if (priv->tx_bytes + data_bytes > hw->tx_size) {
>> +                       error("max tx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +
>> +               /* copy tx data */
>> +               memcpy_toio(priv->base + hw->tx + priv->tx_bytes,
>> +                           dout, data_bytes);
>> +               priv->tx_bytes += data_bytes;
>> +       }
>> +
>> +       if (flags & SPI_XFER_END) {
>> +               struct dm_spi_slave_platdata *plat =
>> +                       dev_get_parent_platdata(dev);
>> +               uint16_t val;
>> +               uint8_t irq;
>> +
>> +               /* determine control config */
>> +               if (dout && !din) {
>> +                       /* buffered write transfers */
>> +                       val = priv->tx_bytes;
>> +                       val |= (SPI_CTL_TYPE_HD_W << hw->ctl_shift);
>> +                       priv->tx_bytes = 0;
>> +               } else {
>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>> +                               /* full duplex read/write */
>> +                               val = data_bytes;
>> +                               val |= (SPI_CTL_TYPE_FD_RW << hw->ctl_shift);
>> +                               priv->tx_bytes = 0;
>> +                       } else {
>> +                               /* prepended write transfer */
>> +                               val = data_bytes;
>> +                               val |= (SPI_CTL_TYPE_HD_R << hw->ctl_shift);
>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>> +                                       error("max prepend bytes exceeded\n");
>> +                                       return -EMSGSIZE;
>> +                               }
>> +                       }
>> +               }
>> +
>> +               if (hw->ctl_shift >= 8)
>> +                       writew_be(val, priv->base + hw->ctl);
>> +               else
>> +                       writeb_be(val, priv->base + hw->ctl);
>> +
>> +               /* clear interrupts */
>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->base + hw->ir_stat);
>> +
>> +               /* issue the transfer */
>> +               val = SPI_CMD_OP_START;
>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>> +               if (plat->mode & SPI_3WIRE)
>> +                       val |= SPI_CMD_3WIRE_MASK;
>> +               writew_be(val, priv->base + hw->cmd);
>> +
>> +               /* enable interrupts */
>> +               writeb_be(SPI_IR_DONE_MASK, priv->base + hw->ir_mask);
>> +
>> +               do {
>> +                       /* read interupts */
>> +                       irq = readb_be(priv->base + hw->ir_stat);
>> +
>> +                       /* transfer completed */
>> +                       if (irq & SPI_IR_DONE_MASK)
>> +                               break;
>> +               } while (1);
>> +
>> +               /* copy rx data */
>> +               if (din)
>> +                       memcpy_fromio(din, priv->base + hw->rx,
>> +                                     data_bytes);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct dm_spi_ops bcm63xx_spi_ops = {
>> +       .cs_info = bcm63xx_spi_cs_info,
>> +       .set_mode = bcm63xx_spi_set_mode,
>> +       .set_speed = bcm63xx_spi_set_speed,
>> +       .xfer = bcm63xx_spi_xfer,
>> +};
>> +
>> +static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6348 = {
>> +       .clk = 0x06,
>> +       .cmd = 0x00,
>> +       .ctl = 0x40,
>> +       .ctl_shift = 6,
>> +       .fill = 0x07,
>> +       .ir_stat = 0x02,
>> +       .ir_mask = 0x04,
>> +       .rx = 0x80,
>> +       .rx_size = 0x3f,
>> +       .tx = 0x41,
>> +       .tx_size = 0x3f,
>> +};
> 
> Define these hexcodes into macros like SPI_6348_CLK_CFG
Ok, I will do that.

> 
>> +
>> +static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6358 = {
>> +       .clk = 0x706,
>> +       .cmd = 0x700,
>> +       .ctl = 0x000,
>> +       .ctl_shift = 14,
>> +       .fill = 0x707,
>> +       .ir_stat = 0x702,
>> +       .ir_mask = 0x704,
>> +       .rx = 0x400,
>> +       .rx_size = 0x220,
>> +       .tx = 0x002,
>> +       .tx_size = 0x21e,
>> +};
> 
> Define these hexcodes into macros like SPI_6358_CLK_CFG
Ok, I will do that.

> 
>> +
>> +static const struct udevice_id bcm63xx_spi_ids[] = {
>> +       {
>> +               .compatible = "brcm,bcm6348-spi",
>> +               .data = (ulong)&bcm63xx_spi_bcm6348,
>> +       }, {
>> +               .compatible = "brcm,bcm6358-spi",
>> +               .data = (ulong)&bcm63xx_spi_bcm6358,
>> +       }, { /* sentinel */ }
>> +};
> 
> I think this can even write more like long value instead making it in
> structure, so-that rotating the 'struct bcm63xx_spi_hw' to respective
> functions can avoid. like definig members in enum and use these as an
> offset along with specific reg_space while doing io ops.
I don't think I'm following, can you provide an example of how you want it done?
Maybe a driver that is doing that in u-boot or something similar...

> 
> thanks!
> 
Thanks!

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

* [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver
  2017-06-15  9:24       ` Álvaro Fernández Rojas
@ 2017-06-19 11:37         ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2017-06-19 11:37 UTC (permalink / raw)
  To: u-boot

On Thu, Jun 15, 2017 at 2:54 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Hi Jagan,
>
> El 15/6/17 a las 7:38, Jagan Teki escribió:
>> On Wed, Jun 14, 2017 at 3:27 PM, Álvaro Fernández Rojas
>> <noltari@gmail.com> wrote:
>>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>>> Instead of supporting both HW revisions of the controller in a single build,
>>> support has been split by the selected config to save space.
>>>
>>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>>> ---
>>>  v4: Introduce changes suggested by Jagan Teki:
>>>   - Add data for each HW controller instead of having two separate configs.
>>>   - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
>>>  v3: rename BCM6338 SPI driver to BCM6348
>>>   switch to devfdt_get_addr_size_index()
>>>  v2: no changes
>>>
>>>  drivers/spi/Kconfig       |   8 +
>>>  drivers/spi/Makefile      |   1 +
>>>  drivers/spi/bcm63xx_spi.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 428 insertions(+)
>>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>>
>>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>>> index bef864f..6da78bd 100644
>>> --- a/drivers/spi/Kconfig
>>> +++ b/drivers/spi/Kconfig
>>> @@ -40,6 +40,14 @@ config ATMEL_SPI
>>>           many AT32 (AVR32) and AT91 (ARM) chips. This driver can be
>>>           used to access the SPI Flash, such as AT25DF321.
>>>
>>> +config BCM63XX_SPI
>>> +       bool "BCM6348 SPI driver"
>>> +       depends on ARCH_BMIPS
>>> +       help
>>> +         Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
>>> +         access the SPI NOR flash on platforms embedding these Broadcom
>>> +         SPI cores.
>>> +
>>>  config CADENCE_QSPI
>>>         bool "Cadence QSPI driver"
>>>         help
>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>> index c090562..260ba06 100644
>>> --- a/drivers/spi/Makefile
>>> +++ b/drivers/spi/Makefile
>>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>>> +obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
>>
>> Thanks for doing this change.
> That's what you requested ;).
>
>>
>>>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>>>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>>> new file mode 100644
>>> index 0000000..e1629fa
>>> --- /dev/null
>>> +++ b/drivers/spi/bcm63xx_spi.c
>>> @@ -0,0 +1,419 @@
>>> +/*
>>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>>> + *
>>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>>> + *
>>> + * SPDX-License-Identifier: GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <clk.h>
>>> +#include <dm.h>
>>> +#include <spi.h>
>>> +#include <reset.h>
>>> +#include <asm/io.h>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +/* SPI Clock register */
>>> +#define SPI_CLK_SHIFT          0
>>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>>> +#define SPI_CLK_SSOFF_SHIFT    3
>>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>>> +#define SPI_CLK_BSWAP_SHIFT    7
>>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>>> +
>>> +/* SPI Command register */
>>> +#define SPI_CMD_OP_SHIFT       0
>>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>>> +#define SPI_CMD_SLAVE_SHIFT    4
>>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>>> +#define SPI_CMD_PREPEND_SHIFT  8
>>> +#define SPI_CMD_PREPEND_BYTES  0xf
>>> +#define SPI_CMD_3WIRE_SHIFT    12
>>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>>> +
>>> +/* SPI Control register */
>>> +# define SPI_CTL_TYPE_FD_RW    0
>>> +# define SPI_CTL_TYPE_HD_W     1
>>> +# define SPI_CTL_TYPE_HD_R     2
>>> +
>>> +/* SPI Interrupt registers */
>>> +#define SPI_IR_DONE_SHIFT      0
>>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>>> +#define SPI_IR_RXOVER_SHIFT    1
>>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>>> +#define SPI_IR_TXUNDER_SHIFT   2
>>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>>> +#define SPI_IR_TXOVER_SHIFT    3
>>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>>> +#define SPI_IR_RXUNDER_SHIFT   4
>>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>>> +                                SPI_IR_RXOVER_MASK |\
>>> +                                SPI_IR_TXUNDER_MASK |\
>>> +                                SPI_IR_TXOVER_MASK |\
>>> +                                SPI_IR_RXUNDER_MASK)
>>> +
>>> +struct bcm63xx_spi_hw {
>>> +       /* SPI Clock register */
>>> +       uint16_t clk;
>>> +
>>> +       /* SPI Command register */
>>> +       uint16_t cmd;
>>> +
>>> +       /* SPI Control register */
>>> +       uint16_t ctl;
>>> +       uint8_t ctl_shift;
>>> +
>>> +       /* SPI Fill register */
>>> +       uint16_t fill;
>>> +
>>> +       /* SPI Interrupt registers */
>>> +       uint16_t ir_stat;
>>> +       uint16_t ir_mask;
>>> +
>>> +       /* SPI RX Data registers */
>>> +       uint16_t rx;
>>> +       uint16_t rx_size;
>>> +
>>> +       /* SPI TX Data registers */
>>> +       uint16_t tx;
>>> +       uint16_t tx_size;
>>> +};
>>> +
>>> +struct bcm63xx_spi_priv {
>>> +       const struct bcm63xx_spi_hw *hw;
>>> +       void __iomem *base;
>>> +       size_t tx_bytes;
>>> +       uint8_t num_cs;
>>> +};
>>> +
>>> +#define SPI_CLK_CNT            8
>>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>>> +       { 25000000, SPI_CLK_25MHZ },
>>> +       { 20000000, SPI_CLK_20MHZ },
>>> +       { 12500000, SPI_CLK_12_50MHZ },
>>> +       {  6250000, SPI_CLK_6_250MHZ },
>>> +       {  3125000, SPI_CLK_3_125MHZ },
>>> +       {  1563000, SPI_CLK_1_563MHZ },
>>> +       {   781000, SPI_CLK_0_781MHZ },
>>> +       {   391000, SPI_CLK_0_391MHZ }
>>> +};
>>> +
>>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>>> +                          struct spi_cs_info *info)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>> +
>>> +       if (cs >= priv->num_cs) {
>>> +               error("no cs %u\n", cs);
>>> +               return -ENODEV;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>> +       const struct bcm63xx_spi_hw *hw = priv->hw;
>>> +
>>> +       if (mode & SPI_LSB_FIRST)
>>> +               setbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
>>> +       else
>>> +               clrbits_8(priv->base + hw->clk, SPI_CLK_BSWAP_MASK);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>>> +       const struct bcm63xx_spi_hw *hw = priv->hw;
>>> +       uint8_t clk_cfg;
>>> +       int i;
>>> +
>>> +       /* default to lowest clock configuration */
>>> +       clk_cfg = SPI_CLK_0_391MHZ;
>>> +
>>> +       /* find the closest clock configuration */
>>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>>> +                       break;
>>> +               }
>>> +       }
>>> +
>>> +       /* write clock configuration */
>>> +       clrsetbits_8(priv->base + hw->clk,
>>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +/*
>>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>>> + * they are HW controlled.
>>> + * However, it provides a mechanism to prepend write transfers prior to read
>>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>>> + * SPI-connected flashes since reading requires prepending a write transfer of
>>> + * 5 bytes.
>>> + *
>>> + * This implementation takes advantage of the prepend mechanism and combines
>>> + * multiple transfers into a single one where possible (single/multiple write
>>> + * transfer(s) followed by a final read/write transfer).
>>> + * However, it's not possible to buffer reads, which means that read transfers
>>> + * should always be done as the final ones.
>>> + * On the other hand, take into account that combining write transfers into
>>> + * a single one is just buffering and doesn't require prepend mechanism.
>>> + */
>>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>>> +               const void *dout, void *din, unsigned long flags)
>>> +{
>>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>>> +       const struct bcm63xx_spi_hw *hw = priv->hw;
>>> +       size_t data_bytes = bitlen / 8;
>>> +
>>> +       if (flags & SPI_XFER_BEGIN) {
>>> +               /* clear prepends */
>>> +               priv->tx_bytes = 0;
>>> +
>>> +               /* initialize hardware */
>>> +               writeb_be(0, priv->base + hw->ir_mask);
>>> +       }
>>> +
>>> +       if (din) {
>>> +               /* buffering reads not possible since cs is hw controlled */
>>> +               if (!(flags & SPI_XFER_END)) {
>>> +                       error("unable to buffer reads\n");
>>> +                       return -EINVAL;
>>> +               }
>>> +
>>> +               /* check rx size */
>>> +                if (data_bytes > hw->rx_size) {
>>> +                       error("max rx bytes exceeded\n");
>>> +                       return -EMSGSIZE;
>>> +               }
>>> +       }
>>> +
>>> +       if (dout) {
>>> +               /* check tx size */
>>> +               if (priv->tx_bytes + data_bytes > hw->tx_size) {
>>> +                       error("max tx bytes exceeded\n");
>>> +                       return -EMSGSIZE;
>>> +               }
>>> +
>>> +               /* copy tx data */
>>> +               memcpy_toio(priv->base + hw->tx + priv->tx_bytes,
>>> +                           dout, data_bytes);
>>> +               priv->tx_bytes += data_bytes;
>>> +       }
>>> +
>>> +       if (flags & SPI_XFER_END) {
>>> +               struct dm_spi_slave_platdata *plat =
>>> +                       dev_get_parent_platdata(dev);
>>> +               uint16_t val;
>>> +               uint8_t irq;
>>> +
>>> +               /* determine control config */
>>> +               if (dout && !din) {
>>> +                       /* buffered write transfers */
>>> +                       val = priv->tx_bytes;
>>> +                       val |= (SPI_CTL_TYPE_HD_W << hw->ctl_shift);
>>> +                       priv->tx_bytes = 0;
>>> +               } else {
>>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>>> +                               /* full duplex read/write */
>>> +                               val = data_bytes;
>>> +                               val |= (SPI_CTL_TYPE_FD_RW << hw->ctl_shift);
>>> +                               priv->tx_bytes = 0;
>>> +                       } else {
>>> +                               /* prepended write transfer */
>>> +                               val = data_bytes;
>>> +                               val |= (SPI_CTL_TYPE_HD_R << hw->ctl_shift);
>>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>>> +                                       error("max prepend bytes exceeded\n");
>>> +                                       return -EMSGSIZE;
>>> +                               }
>>> +                       }
>>> +               }
>>> +
>>> +               if (hw->ctl_shift >= 8)
>>> +                       writew_be(val, priv->base + hw->ctl);
>>> +               else
>>> +                       writeb_be(val, priv->base + hw->ctl);
>>> +
>>> +               /* clear interrupts */
>>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->base + hw->ir_stat);
>>> +
>>> +               /* issue the transfer */
>>> +               val = SPI_CMD_OP_START;
>>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>>> +               if (plat->mode & SPI_3WIRE)
>>> +                       val |= SPI_CMD_3WIRE_MASK;
>>> +               writew_be(val, priv->base + hw->cmd);
>>> +
>>> +               /* enable interrupts */
>>> +               writeb_be(SPI_IR_DONE_MASK, priv->base + hw->ir_mask);
>>> +
>>> +               do {
>>> +                       /* read interupts */
>>> +                       irq = readb_be(priv->base + hw->ir_stat);
>>> +
>>> +                       /* transfer completed */
>>> +                       if (irq & SPI_IR_DONE_MASK)
>>> +                               break;
>>> +               } while (1);
>>> +
>>> +               /* copy rx data */
>>> +               if (din)
>>> +                       memcpy_fromio(din, priv->base + hw->rx,
>>> +                                     data_bytes);
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static const struct dm_spi_ops bcm63xx_spi_ops = {
>>> +       .cs_info = bcm63xx_spi_cs_info,
>>> +       .set_mode = bcm63xx_spi_set_mode,
>>> +       .set_speed = bcm63xx_spi_set_speed,
>>> +       .xfer = bcm63xx_spi_xfer,
>>> +};
>>> +
>>> +static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6348 = {
>>> +       .clk = 0x06,
>>> +       .cmd = 0x00,
>>> +       .ctl = 0x40,
>>> +       .ctl_shift = 6,
>>> +       .fill = 0x07,
>>> +       .ir_stat = 0x02,
>>> +       .ir_mask = 0x04,
>>> +       .rx = 0x80,
>>> +       .rx_size = 0x3f,
>>> +       .tx = 0x41,
>>> +       .tx_size = 0x3f,
>>> +};
>>
>> Define these hexcodes into macros like SPI_6348_CLK_CFG
> Ok, I will do that.
>
>>
>>> +
>>> +static const struct bcm63xx_spi_hw bcm63xx_spi_bcm6358 = {
>>> +       .clk = 0x706,
>>> +       .cmd = 0x700,
>>> +       .ctl = 0x000,
>>> +       .ctl_shift = 14,
>>> +       .fill = 0x707,
>>> +       .ir_stat = 0x702,
>>> +       .ir_mask = 0x704,
>>> +       .rx = 0x400,
>>> +       .rx_size = 0x220,
>>> +       .tx = 0x002,
>>> +       .tx_size = 0x21e,
>>> +};
>>
>> Define these hexcodes into macros like SPI_6358_CLK_CFG
> Ok, I will do that.
>
>>
>>> +
>>> +static const struct udevice_id bcm63xx_spi_ids[] = {
>>> +       {
>>> +               .compatible = "brcm,bcm6348-spi",
>>> +               .data = (ulong)&bcm63xx_spi_bcm6348,
>>> +       }, {
>>> +               .compatible = "brcm,bcm6358-spi",
>>> +               .data = (ulong)&bcm63xx_spi_bcm6358,
>>> +       }, { /* sentinel */ }
>>> +};
>>
>> I think this can even write more like long value instead making it in
>> structure, so-that rotating the 'struct bcm63xx_spi_hw' to respective
>> functions can avoid. like definig members in enum and use these as an
>> offset along with specific reg_space while doing io ops.
> I don't think I'm following, can you provide an example of how you want it done?
> Maybe a driver that is doing that in u-boot or something similar...

static const unsigned log bcm63xx_spi_bcm6348 = {
     [SPI_CMD]                   = SPI_6348_CMD,
     [SPI_INT_STATUS]      = SPI_6348_INT_STATUS,
    .......
    .....
};


*_probe(struct udevice *dev)
{
   const unsigned long *bcm63xx_spireg;

   /* need to assign the probed data to bcm63xx_spireg */
}

For more infor this mught look simialr to Linux drivers/spi/spi-bcm63xx.c

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (12 preceding siblings ...)
  2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-07-30 12:13 ` Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (11 more replies)
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (3 subsequent siblings)
  17 siblings, 12 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v5: Introduce changes suggested by Jagan Teki:
- Use long structs for registers
v4: Introduce changes suggested by Jagan Teki:
- Add data for each HW controller instead of having two separate configs.
v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (10):
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/mips/dts/brcm,bcm3380.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm63268.dtsi      |  17 ++
 arch/mips/dts/brcm,bcm6338.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6358.dtsi       |  17 ++
 arch/mips/dts/netgear,cg3100d.dts     |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 configs/netgear_cg3100d_ram_defconfig |   8 +
 configs/sagem_f at st1704_ram_defconfig  |   8 +
 drivers/mtd/spi/spi_flash.c           |   5 +-
 drivers/spi/Kconfig                   |   8 +
 drivers/spi/Makefile                  |   1 +
 drivers/spi/bcm63xx_spi.c             | 434 ++++++++++++++++++++++++++++++++++
 include/spi.h                         |   5 +-
 14 files changed, 576 insertions(+), 2 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.11.0

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

* [U-Boot] [PATCH v5 01/10] drivers: spi: allow limiting reads
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-08-10  9:12     ` Jagan Teki
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (10 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 0034a28d5f..5ee33d8bb2 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -487,6 +487,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 8c4b882c54..d0fa5379ea 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 	u8 option;
-- 
2.11.0

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

* [U-Boot] [PATCH v5 02/10] drivers: spi: consider command bytes when sending transfers
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-08-10  9:13     ` Jagan Teki
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (9 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: no changes
 v4: no changes
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 5ee33d8bb2..1e194cedd8 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -380,7 +380,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index d0fa5379ea..c4e1da68ab 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.11.0

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

* [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-08-10  9:25     ` Jagan Teki
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: Introduce changes suggested by Jagan Teki:
  - Use long structure instead of a custom bmips_spi_hw structure.
  - Define constants for each SPI core.
 v4: Introduce changes suggested by Jagan Teki:
  - Add data for each HW controller instead of having two separate configs.
  - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |   8 +
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 434 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 443 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 8a8e8e480f..511643607b 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,14 @@ config ATMEL_SPI
 	  many AT91 (ARM) chips. This driver can be used to access
 	  the SPI Flash, such as AT25DF321.
 
+config BCM63XX_SPI
+	bool "BCM6348 SPI driver"
+	depends on ARCH_BMIPS
+	help
+	  Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding these Broadcom
+	  SPI cores.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 9f8b86de76..d9802dd8c3 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000000..904db2b7c7
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* BCM6348 SPI core */
+#define SPI_6348_CLK			0x06
+#define SPI_6348_CMD			0x00
+#define SPI_6348_CTL			0x40
+#define SPI_6348_CTL_SHIFT		6
+#define SPI_6348_FILL			0x07
+#define SPI_6348_IR_MASK		0x04
+#define SPI_6348_IR_STAT		0x02
+#define SPI_6348_RX			0x80
+#define SPI_6348_RX_SIZE		0x3f
+#define SPI_6348_TX			0x41
+#define SPI_6348_TX_SIZE		0x3f
+
+/* BCM6358 SPI core */
+#define SPI_6358_CLK			0x706
+#define SPI_6358_CMD			0x700
+#define SPI_6358_CTL			0x000
+#define SPI_6358_CTL_SHIFT		14
+#define SPI_6358_FILL			0x707
+#define SPI_6358_IR_MASK		0x702
+#define SPI_6358_IR_STAT		0x704
+#define SPI_6358_RX			0x400
+#define SPI_6358_RX_SIZE		0x220
+#define SPI_6358_TX			0x002
+#define SPI_6358_TX_SIZE		0x21e
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Control register */
+#define SPI_CTL_TYPE_FD_RW	0
+#define SPI_CTL_TYPE_HD_W	1
+#define SPI_CTL_TYPE_HD_R	2
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+enum bcm63xx_regs_spi {
+	SPI_CLK,
+	SPI_CMD,
+	SPI_CTL,
+	SPI_CTL_SHIFT,
+	SPI_FILL,
+	SPI_IR_MASK,
+	SPI_IR_STAT,
+	SPI_RX,
+	SPI_RX_SIZE,
+	SPI_TX,
+	SPI_TX_SIZE,
+};
+
+struct bcm63xx_spi_priv {
+	const unsigned long *regs;
+	void __iomem *base;
+	size_t tx_bytes;
+	uint8_t num_cs;
+};
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		error("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->base + regs[SPI_CLK],
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			error("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > regs[SPI_RX_SIZE]) {
+			error("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
+			error("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val;
+		uint8_t irq;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val = priv->tx_bytes;
+			val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_FD_RW <<
+					regs[SPI_CTL_SHIFT]);
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_HD_R <<
+					regs[SPI_CTL_SHIFT]);
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					error("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+
+		if (regs[SPI_CTL_SHIFT] >= 8)
+			writew_be(val, priv->base + regs[SPI_CTL]);
+		else
+			writeb_be(val, priv->base + regs[SPI_CTL]);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
+
+		/* issue the transfer */
+		val = SPI_CMD_OP_START;
+		val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			val |= SPI_CMD_3WIRE_MASK;
+		writew_be(val, priv->base + regs[SPI_CMD]);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
+
+		do {
+			/* read interupts */
+			irq = readb_be(priv->base + regs[SPI_IR_STAT]);
+
+			/* transfer completed */
+			if (irq & SPI_IR_DONE_MASK)
+				break;
+		} while (1);
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->base + regs[SPI_RX],
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const unsigned long bcm6348_spi_regs[] = {
+	[SPI_CLK] = SPI_6348_CLK,
+	[SPI_CMD] = SPI_6348_CMD,
+	[SPI_CTL] = SPI_6348_CTL,
+	[SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT,
+	[SPI_FILL] = SPI_6348_FILL,
+	[SPI_IR_MASK] = SPI_6348_IR_MASK,
+	[SPI_IR_STAT] = SPI_6348_IR_STAT,
+	[SPI_RX] = SPI_6348_RX,
+	[SPI_RX_SIZE] = SPI_6348_RX_SIZE,
+	[SPI_TX] = SPI_6348_TX,
+	[SPI_TX_SIZE] = SPI_6348_TX_SIZE,
+};
+
+static const unsigned long bcm6358_spi_regs[] = {
+	[SPI_CLK] = SPI_6358_CLK,
+	[SPI_CMD] = SPI_6358_CMD,
+	[SPI_CTL] = SPI_6358_CTL,
+	[SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT,
+	[SPI_FILL] = SPI_6358_FILL,
+	[SPI_IR_MASK] = SPI_6358_IR_MASK,
+	[SPI_IR_STAT] = SPI_6358_IR_STAT,
+	[SPI_RX] = SPI_6358_RX,
+	[SPI_RX_SIZE] = SPI_6358_RX_SIZE,
+	[SPI_TX] = SPI_6358_TX,
+	[SPI_TX_SIZE] = SPI_6358_TX_SIZE,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-spi",
+		.data = (ulong)&bcm6348_spi_regs,
+	}, {
+		.compatible = "brcm,bcm6358-spi",
+		.data = (ulong)&bcm6358_spi_regs,
+	}, { /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		error("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = regs[SPI_RX_SIZE];
+	slave->max_write_size = regs[SPI_TX_SIZE];
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	const unsigned long *regs =
+		(const unsigned long *)dev_get_driver_data(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = regs;
+	priv->base = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_free(&clk);
+	if (ret < 0)
+		return ret;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_free(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	/* initialize hardware */
+	writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+
+	/* set fill register */
+	writeb_be(0xff, priv->base + regs[SPI_FILL]);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v5 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a4372b..0cab44cb8d 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v5 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643b5a..540b9fea5b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v5 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf80e0..1662783279 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v5 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb048..f83a6ea8df 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v5 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96bef8..6e3d9c3820 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.11.0

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

* [U-Boot] [PATCH v5 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5551..dd0e5b8b7c 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 8b5d7f4d65..55a3170aa5 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -40,3 +40,11 @@ CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
-- 
2.11.0

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

* [U-Boot] [PATCH v5 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2017-07-30 12:13   ` Álvaro Fernández Rojas
  2017-08-07  8:35   ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Jagan Teki
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-07-30 12:13 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7616..5f85c7346f 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index e3537943e5..1390c9e79c 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -42,3 +42,11 @@ CONFIG_RESET_BCM6345=y
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
 CONFIG_WDT_BCM6345=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
-- 
2.11.0

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

* [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (9 preceding siblings ...)
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
@ 2017-08-07  8:35   ` Jagan Teki
  2017-08-07 10:00     ` Daniel Schwierzeck
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
  11 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2017-08-07  8:35 UTC (permalink / raw)
  To: u-boot

Hi,

On Sun, Jul 30, 2017 at 5:43 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
> active between transfers, so I had to modify the spi_flash driver in order
> to allow limiting reads.
>
> v5: Introduce changes suggested by Jagan Teki:
> - Use long structs for registers
> v4: Introduce changes suggested by Jagan Teki:
> - Add data for each HW controller instead of having two separate configs.
> v3: Fix bug introduced in v2: sizeof(cmd) vs len.
> Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
> down version of the BCM6348.
> Switch to devfdt_get_addr_size_index().
> v2: Introduce changes requested by Simon Glass:
> - Always include command bytes when determining max write size.
> Also move SPI aliases from .dts to .dtsi files.

Did you sent the latest changes? I couldn't find it on patchwork even
with status "any"

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support
  2017-08-07  8:35   ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Jagan Teki
@ 2017-08-07 10:00     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2017-08-07 10:00 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

Am 07.08.2017 um 10:35 schrieb Jagan Teki:
> Hi,
> 
> On Sun, Jul 30, 2017 at 5:43 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
>> active between transfers, so I had to modify the spi_flash driver in order
>> to allow limiting reads.
>>
>> v5: Introduce changes suggested by Jagan Teki:
>> - Use long structs for registers
>> v4: Introduce changes suggested by Jagan Teki:
>> - Add data for each HW controller instead of having two separate configs.
>> v3: Fix bug introduced in v2: sizeof(cmd) vs len.
>> Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
>> down version of the BCM6348.
>> Switch to devfdt_get_addr_size_index().
>> v2: Introduce changes requested by Simon Glass:
>> - Always include command bytes when determining max write size.
>> Also move SPI aliases from .dts to .dtsi files.
> 
> Did you sent the latest changes? I couldn't find it on patchwork even
> with status "any"
> 
> thanks!
> 

someone assigned all patches to me. I reassigned them to you. Please
apply them, thanks.

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170807/e58df34d/attachment.sig>

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

* [U-Boot] [PATCH v5 01/10] drivers: spi: allow limiting reads
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2017-08-10  9:12     ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2017-08-10  9:12 UTC (permalink / raw)
  To: u-boot

On Sun, Jul 30, 2017 at 5:43 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> For some SPI controllers it's not possible to keep the CS active between
> transfers and they are limited to a known number of bytes.
> This splits spi_flash reads into different iterations in order to respect
> the SPI controller limits.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

Reviewed-by: Jagan Teki <jagan@openedev.com>

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v5 02/10] drivers: spi: consider command bytes when sending transfers
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2017-08-10  9:13     ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2017-08-10  9:13 UTC (permalink / raw)
  To: u-boot

On Sun, Jul 30, 2017 at 5:43 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Command bytes are part of the written bytes and they should be taken into
> account when sending a spi transfer.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

Reviewed-by: Jagan Teki <jagan@openedev.com>

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver
  2017-07-30 12:13   ` [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2017-08-10  9:25     ` Jagan Teki
  2017-08-11  9:11       ` Jagan Teki
  2017-12-26 12:21       ` Álvaro Fernández Rojas
  0 siblings, 2 replies; 187+ messages in thread
From: Jagan Teki @ 2017-08-10  9:25 UTC (permalink / raw)
  To: u-boot

On Sun, Jul 30, 2017 at 5:43 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---
>  v5: Introduce changes suggested by Jagan Teki:
>   - Use long structure instead of a custom bmips_spi_hw structure.
>   - Define constants for each SPI core.
>  v4: Introduce changes suggested by Jagan Teki:
>   - Add data for each HW controller instead of having two separate configs.
>   - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
>  v3: rename BCM6338 SPI driver to BCM6348
>   switch to devfdt_get_addr_size_index()
>  v2: no changes
>
>  drivers/spi/Kconfig       |   8 +
>  drivers/spi/Makefile      |   1 +
>  drivers/spi/bcm63xx_spi.c | 434 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 443 insertions(+)
>  create mode 100644 drivers/spi/bcm63xx_spi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 8a8e8e480f..511643607b 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -40,6 +40,14 @@ config ATMEL_SPI
>           many AT91 (ARM) chips. This driver can be used to access
>           the SPI Flash, such as AT25DF321.
>
> +config BCM63XX_SPI
> +       bool "BCM6348 SPI driver"
> +       depends on ARCH_BMIPS
> +       help
> +         Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
> +         access the SPI NOR flash on platforms embedding these Broadcom
> +         SPI cores.
> +
>  config CADENCE_QSPI
>         bool "Cadence QSPI driver"
>         help
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 9f8b86de76..d9802dd8c3 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
> +obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
> new file mode 100644
> index 0000000000..904db2b7c7
> --- /dev/null
> +++ b/drivers/spi/bcm63xx_spi.c
> @@ -0,0 +1,434 @@
> +/*
> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <spi.h>
> +#include <reset.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* BCM6348 SPI core */
> +#define SPI_6348_CLK                   0x06
> +#define SPI_6348_CMD                   0x00
> +#define SPI_6348_CTL                   0x40
> +#define SPI_6348_CTL_SHIFT             6
> +#define SPI_6348_FILL                  0x07
> +#define SPI_6348_IR_MASK               0x04
> +#define SPI_6348_IR_STAT               0x02
> +#define SPI_6348_RX                    0x80
> +#define SPI_6348_RX_SIZE               0x3f
> +#define SPI_6348_TX                    0x41
> +#define SPI_6348_TX_SIZE               0x3f
> +
> +/* BCM6358 SPI core */
> +#define SPI_6358_CLK                   0x706
> +#define SPI_6358_CMD                   0x700
> +#define SPI_6358_CTL                   0x000
> +#define SPI_6358_CTL_SHIFT             14
> +#define SPI_6358_FILL                  0x707
> +#define SPI_6358_IR_MASK               0x702
> +#define SPI_6358_IR_STAT               0x704
> +#define SPI_6358_RX                    0x400
> +#define SPI_6358_RX_SIZE               0x220
> +#define SPI_6358_TX                    0x002
> +#define SPI_6358_TX_SIZE               0x21e
> +
> +/* SPI Clock register */
> +#define SPI_CLK_SHIFT          0
> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
> +#define SPI_CLK_SSOFF_SHIFT    3
> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
> +#define SPI_CLK_BSWAP_SHIFT    7
> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
> +
> +/* SPI Command register */
> +#define SPI_CMD_OP_SHIFT       0
> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
> +#define SPI_CMD_SLAVE_SHIFT    4
> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
> +#define SPI_CMD_PREPEND_SHIFT  8
> +#define SPI_CMD_PREPEND_BYTES  0xf
> +#define SPI_CMD_3WIRE_SHIFT    12
> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
> +
> +/* SPI Control register */
> +#define SPI_CTL_TYPE_FD_RW     0
> +#define SPI_CTL_TYPE_HD_W      1
> +#define SPI_CTL_TYPE_HD_R      2
> +
> +/* SPI Interrupt registers */
> +#define SPI_IR_DONE_SHIFT      0
> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
> +#define SPI_IR_RXOVER_SHIFT    1
> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
> +#define SPI_IR_TXUNDER_SHIFT   2
> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
> +#define SPI_IR_TXOVER_SHIFT    3
> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
> +#define SPI_IR_RXUNDER_SHIFT   4
> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
> +                                SPI_IR_RXOVER_MASK |\
> +                                SPI_IR_TXUNDER_MASK |\
> +                                SPI_IR_TXOVER_MASK |\
> +                                SPI_IR_RXUNDER_MASK)
> +
> +enum bcm63xx_regs_spi {
> +       SPI_CLK,
> +       SPI_CMD,
> +       SPI_CTL,
> +       SPI_CTL_SHIFT,
> +       SPI_FILL,
> +       SPI_IR_MASK,
> +       SPI_IR_STAT,
> +       SPI_RX,
> +       SPI_RX_SIZE,
> +       SPI_TX,
> +       SPI_TX_SIZE,
> +};
> +
> +struct bcm63xx_spi_priv {
> +       const unsigned long *regs;
> +       void __iomem *base;
> +       size_t tx_bytes;
> +       uint8_t num_cs;
> +};
> +
> +#define SPI_CLK_CNT            8
> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
> +       { 25000000, SPI_CLK_25MHZ },
> +       { 20000000, SPI_CLK_20MHZ },
> +       { 12500000, SPI_CLK_12_50MHZ },
> +       {  6250000, SPI_CLK_6_250MHZ },
> +       {  3125000, SPI_CLK_3_125MHZ },
> +       {  1563000, SPI_CLK_1_563MHZ },
> +       {   781000, SPI_CLK_0_781MHZ },
> +       {   391000, SPI_CLK_0_391MHZ }
> +};
> +
> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
> +                          struct spi_cs_info *info)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +
> +       if (cs >= priv->num_cs) {
> +               error("no cs %u\n", cs);
> +               return -ENODEV;
> +       }
> +
> +       return 0;
> +}
> +
> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +       const unsigned long *regs = priv->regs;
> +
> +       if (mode & SPI_LSB_FIRST)
> +               setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
> +       else
> +               clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
> +
> +       return 0;
> +}
> +
> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
> +       const unsigned long *regs = priv->regs;
> +       uint8_t clk_cfg;
> +       int i;
> +
> +       /* default to lowest clock configuration */
> +       clk_cfg = SPI_CLK_0_391MHZ;
> +
> +       /* find the closest clock configuration */
> +       for (i = 0; i < SPI_CLK_CNT; i++) {
> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
> +                       break;
> +               }
> +       }
> +
> +       /* write clock configuration */
> +       clrsetbits_8(priv->base + regs[SPI_CLK],
> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
> +                    clk_cfg | SPI_CLK_SSOFF_2);
> +
> +       return 0;
> +}
> +
> +/*
> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
> + * they are HW controlled.
> + * However, it provides a mechanism to prepend write transfers prior to read
> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
> + * SPI-connected flashes since reading requires prepending a write transfer of
> + * 5 bytes.
> + *
> + * This implementation takes advantage of the prepend mechanism and combines
> + * multiple transfers into a single one where possible (single/multiple write
> + * transfer(s) followed by a final read/write transfer).
> + * However, it's not possible to buffer reads, which means that read transfers
> + * should always be done as the final ones.
> + * On the other hand, take into account that combining write transfers into
> + * a single one is just buffering and doesn't require prepend mechanism.
> + */
> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +               const void *dout, void *din, unsigned long flags)
> +{
> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
> +       const unsigned long *regs = priv->regs;
> +       size_t data_bytes = bitlen / 8;
> +
> +       if (flags & SPI_XFER_BEGIN) {
> +               /* clear prepends */
> +               priv->tx_bytes = 0;
> +
> +               /* initialize hardware */
> +               writeb_be(0, priv->base + regs[SPI_IR_MASK]);
> +       }
> +
> +       if (din) {
> +               /* buffering reads not possible since cs is hw controlled */
> +               if (!(flags & SPI_XFER_END)) {
> +                       error("unable to buffer reads\n");
> +                       return -EINVAL;
> +               }
> +
> +               /* check rx size */
> +                if (data_bytes > regs[SPI_RX_SIZE]) {
> +                       error("max rx bytes exceeded\n");
> +                       return -EMSGSIZE;
> +               }
> +       }
> +
> +       if (dout) {
> +               /* check tx size */
> +               if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
> +                       error("max tx bytes exceeded\n");
> +                       return -EMSGSIZE;
> +               }
> +
> +               /* copy tx data */
> +               memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
> +                           dout, data_bytes);
> +               priv->tx_bytes += data_bytes;
> +       }
> +
> +       if (flags & SPI_XFER_END) {
> +               struct dm_spi_slave_platdata *plat =
> +                       dev_get_parent_platdata(dev);
> +               uint16_t val;
> +               uint8_t irq;
> +
> +               /* determine control config */
> +               if (dout && !din) {
> +                       /* buffered write transfers */
> +                       val = priv->tx_bytes;
> +                       val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
> +                       priv->tx_bytes = 0;
> +               } else {
> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
> +                               /* full duplex read/write */
> +                               val = data_bytes;
> +                               val |= (SPI_CTL_TYPE_FD_RW <<
> +                                       regs[SPI_CTL_SHIFT]);
> +                               priv->tx_bytes = 0;
> +                       } else {
> +                               /* prepended write transfer */
> +                               val = data_bytes;
> +                               val |= (SPI_CTL_TYPE_HD_R <<
> +                                       regs[SPI_CTL_SHIFT]);
> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
> +                                       error("max prepend bytes exceeded\n");
> +                                       return -EMSGSIZE;
> +                               }
> +                       }
> +               }
> +
> +               if (regs[SPI_CTL_SHIFT] >= 8)
> +                       writew_be(val, priv->base + regs[SPI_CTL]);
> +               else
> +                       writeb_be(val, priv->base + regs[SPI_CTL]);
> +
> +               /* clear interrupts */
> +               writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
> +
> +               /* issue the transfer */
> +               val = SPI_CMD_OP_START;
> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
> +               if (plat->mode & SPI_3WIRE)
> +                       val |= SPI_CMD_3WIRE_MASK;

Please use cmd instead of val to avoid confusion for previous register
reads use same val. And for issue the transfer why do we need to
update the mode here? usually transfer will be initiate with OP_START,
CS and prepend length right? and modes are usually altered during
.set_mode.

> +               writew_be(val, priv->base + regs[SPI_CMD]);
> +
> +               /* enable interrupts */
> +               writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
> +
> +               do {
> +                       /* read interupts */
> +                       irq = readb_be(priv->base + regs[SPI_IR_STAT]);
> +
> +                       /* transfer completed */
> +                       if (irq & SPI_IR_DONE_MASK)
> +                               break;
> +               } while (1);

This shouldn't be an infinite, try to use wait_for_bit with necessary timeout.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver
  2017-08-10  9:25     ` Jagan Teki
@ 2017-08-11  9:11       ` Jagan Teki
  2017-12-26 12:21       ` Álvaro Fernández Rojas
  1 sibling, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2017-08-11  9:11 UTC (permalink / raw)
  To: u-boot

On Thu, Aug 10, 2017 at 2:55 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> On Sun, Jul 30, 2017 at 5:43 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>> ---
>>  v5: Introduce changes suggested by Jagan Teki:
>>   - Use long structure instead of a custom bmips_spi_hw structure.
>>   - Define constants for each SPI core.
>>  v4: Introduce changes suggested by Jagan Teki:
>>   - Add data for each HW controller instead of having two separate configs.
>>   - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
>>  v3: rename BCM6338 SPI driver to BCM6348
>>   switch to devfdt_get_addr_size_index()
>>  v2: no changes
>>
>>  drivers/spi/Kconfig       |   8 +
>>  drivers/spi/Makefile      |   1 +
>>  drivers/spi/bcm63xx_spi.c | 434 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 443 insertions(+)
>>  create mode 100644 drivers/spi/bcm63xx_spi.c
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index 8a8e8e480f..511643607b 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -40,6 +40,14 @@ config ATMEL_SPI
>>           many AT91 (ARM) chips. This driver can be used to access
>>           the SPI Flash, such as AT25DF321.
>>
>> +config BCM63XX_SPI
>> +       bool "BCM6348 SPI driver"
>> +       depends on ARCH_BMIPS
>> +       help
>> +         Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
>> +         access the SPI NOR flash on platforms embedding these Broadcom
>> +         SPI cores.
>> +
>>  config CADENCE_QSPI
>>         bool "Cadence QSPI driver"
>>         help
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index 9f8b86de76..d9802dd8c3 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>  obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>  obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>  obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>> +obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
>>  obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>  obj-$(CONFIG_CF_SPI) += cf_spi.o
>>  obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>> new file mode 100644
>> index 0000000000..904db2b7c7
>> --- /dev/null
>> +++ b/drivers/spi/bcm63xx_spi.c
>> @@ -0,0 +1,434 @@
>> +/*
>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>> + *
>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <spi.h>
>> +#include <reset.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +/* BCM6348 SPI core */
>> +#define SPI_6348_CLK                   0x06
>> +#define SPI_6348_CMD                   0x00
>> +#define SPI_6348_CTL                   0x40
>> +#define SPI_6348_CTL_SHIFT             6
>> +#define SPI_6348_FILL                  0x07
>> +#define SPI_6348_IR_MASK               0x04
>> +#define SPI_6348_IR_STAT               0x02
>> +#define SPI_6348_RX                    0x80
>> +#define SPI_6348_RX_SIZE               0x3f
>> +#define SPI_6348_TX                    0x41
>> +#define SPI_6348_TX_SIZE               0x3f
>> +
>> +/* BCM6358 SPI core */
>> +#define SPI_6358_CLK                   0x706
>> +#define SPI_6358_CMD                   0x700
>> +#define SPI_6358_CTL                   0x000
>> +#define SPI_6358_CTL_SHIFT             14
>> +#define SPI_6358_FILL                  0x707
>> +#define SPI_6358_IR_MASK               0x702
>> +#define SPI_6358_IR_STAT               0x704
>> +#define SPI_6358_RX                    0x400
>> +#define SPI_6358_RX_SIZE               0x220
>> +#define SPI_6358_TX                    0x002
>> +#define SPI_6358_TX_SIZE               0x21e
>> +
>> +/* SPI Clock register */
>> +#define SPI_CLK_SHIFT          0
>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_SSOFF_SHIFT    3
>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_BSWAP_SHIFT    7
>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>> +
>> +/* SPI Command register */
>> +#define SPI_CMD_OP_SHIFT       0
>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>> +#define SPI_CMD_SLAVE_SHIFT    4
>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>> +#define SPI_CMD_PREPEND_SHIFT  8
>> +#define SPI_CMD_PREPEND_BYTES  0xf
>> +#define SPI_CMD_3WIRE_SHIFT    12
>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>> +
>> +/* SPI Control register */
>> +#define SPI_CTL_TYPE_FD_RW     0
>> +#define SPI_CTL_TYPE_HD_W      1
>> +#define SPI_CTL_TYPE_HD_R      2
>> +
>> +/* SPI Interrupt registers */
>> +#define SPI_IR_DONE_SHIFT      0
>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>> +#define SPI_IR_RXOVER_SHIFT    1
>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>> +#define SPI_IR_TXUNDER_SHIFT   2
>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>> +#define SPI_IR_TXOVER_SHIFT    3
>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>> +#define SPI_IR_RXUNDER_SHIFT   4
>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>> +                                SPI_IR_RXOVER_MASK |\
>> +                                SPI_IR_TXUNDER_MASK |\
>> +                                SPI_IR_TXOVER_MASK |\
>> +                                SPI_IR_RXUNDER_MASK)
>> +
>> +enum bcm63xx_regs_spi {
>> +       SPI_CLK,
>> +       SPI_CMD,
>> +       SPI_CTL,
>> +       SPI_CTL_SHIFT,
>> +       SPI_FILL,
>> +       SPI_IR_MASK,
>> +       SPI_IR_STAT,
>> +       SPI_RX,
>> +       SPI_RX_SIZE,
>> +       SPI_TX,
>> +       SPI_TX_SIZE,
>> +};
>> +
>> +struct bcm63xx_spi_priv {
>> +       const unsigned long *regs;
>> +       void __iomem *base;
>> +       size_t tx_bytes;
>> +       uint8_t num_cs;
>> +};
>> +
>> +#define SPI_CLK_CNT            8
>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>> +       { 25000000, SPI_CLK_25MHZ },
>> +       { 20000000, SPI_CLK_20MHZ },
>> +       { 12500000, SPI_CLK_12_50MHZ },
>> +       {  6250000, SPI_CLK_6_250MHZ },
>> +       {  3125000, SPI_CLK_3_125MHZ },
>> +       {  1563000, SPI_CLK_1_563MHZ },
>> +       {   781000, SPI_CLK_0_781MHZ },
>> +       {   391000, SPI_CLK_0_391MHZ }
>> +};
>> +
>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>> +                          struct spi_cs_info *info)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +
>> +       if (cs >= priv->num_cs) {
>> +               error("no cs %u\n", cs);
>> +               return -ENODEV;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +       const unsigned long *regs = priv->regs;
>> +
>> +       if (mode & SPI_LSB_FIRST)
>> +               setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
>> +       else
>> +               clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +       const unsigned long *regs = priv->regs;
>> +       uint8_t clk_cfg;
>> +       int i;
>> +
>> +       /* default to lowest clock configuration */
>> +       clk_cfg = SPI_CLK_0_391MHZ;
>> +
>> +       /* find the closest clock configuration */
>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>> +                       break;
>> +               }
>> +       }
>> +
>> +       /* write clock configuration */
>> +       clrsetbits_8(priv->base + regs[SPI_CLK],
>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>> +
>> +       return 0;
>> +}
>> +
>> +/*
>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>> + * they are HW controlled.
>> + * However, it provides a mechanism to prepend write transfers prior to read
>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>> + * SPI-connected flashes since reading requires prepending a write transfer of
>> + * 5 bytes.
>> + *
>> + * This implementation takes advantage of the prepend mechanism and combines
>> + * multiple transfers into a single one where possible (single/multiple write
>> + * transfer(s) followed by a final read/write transfer).
>> + * However, it's not possible to buffer reads, which means that read transfers
>> + * should always be done as the final ones.
>> + * On the other hand, take into account that combining write transfers into
>> + * a single one is just buffering and doesn't require prepend mechanism.
>> + */
>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>> +               const void *dout, void *din, unsigned long flags)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>> +       const unsigned long *regs = priv->regs;
>> +       size_t data_bytes = bitlen / 8;
>> +
>> +       if (flags & SPI_XFER_BEGIN) {
>> +               /* clear prepends */
>> +               priv->tx_bytes = 0;
>> +
>> +               /* initialize hardware */
>> +               writeb_be(0, priv->base + regs[SPI_IR_MASK]);
>> +       }
>> +
>> +       if (din) {
>> +               /* buffering reads not possible since cs is hw controlled */
>> +               if (!(flags & SPI_XFER_END)) {
>> +                       error("unable to buffer reads\n");
>> +                       return -EINVAL;
>> +               }
>> +
>> +               /* check rx size */
>> +                if (data_bytes > regs[SPI_RX_SIZE]) {
>> +                       error("max rx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +       }
>> +
>> +       if (dout) {
>> +               /* check tx size */
>> +               if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
>> +                       error("max tx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +
>> +               /* copy tx data */
>> +               memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
>> +                           dout, data_bytes);
>> +               priv->tx_bytes += data_bytes;
>> +       }
>> +
>> +       if (flags & SPI_XFER_END) {
>> +               struct dm_spi_slave_platdata *plat =
>> +                       dev_get_parent_platdata(dev);
>> +               uint16_t val;
>> +               uint8_t irq;
>> +
>> +               /* determine control config */
>> +               if (dout && !din) {
>> +                       /* buffered write transfers */
>> +                       val = priv->tx_bytes;
>> +                       val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
>> +                       priv->tx_bytes = 0;
>> +               } else {
>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>> +                               /* full duplex read/write */
>> +                               val = data_bytes;
>> +                               val |= (SPI_CTL_TYPE_FD_RW <<
>> +                                       regs[SPI_CTL_SHIFT]);
>> +                               priv->tx_bytes = 0;
>> +                       } else {
>> +                               /* prepended write transfer */
>> +                               val = data_bytes;
>> +                               val |= (SPI_CTL_TYPE_HD_R <<
>> +                                       regs[SPI_CTL_SHIFT]);
>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>> +                                       error("max prepend bytes exceeded\n");
>> +                                       return -EMSGSIZE;
>> +                               }
>> +                       }
>> +               }
>> +
>> +               if (regs[SPI_CTL_SHIFT] >= 8)
>> +                       writew_be(val, priv->base + regs[SPI_CTL]);
>> +               else
>> +                       writeb_be(val, priv->base + regs[SPI_CTL]);
>> +
>> +               /* clear interrupts */
>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
>> +
>> +               /* issue the transfer */
>> +               val = SPI_CMD_OP_START;
>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>> +               if (plat->mode & SPI_3WIRE)
>> +                       val |= SPI_CMD_3WIRE_MASK;
>
> Please use cmd instead of val to avoid confusion for previous register
> reads use same val. And for issue the transfer why do we need to
> update the mode here? usually transfer will be initiate with OP_START,
> CS and prepend length right? and modes are usually altered during
> .set_mode.
>
>> +               writew_be(val, priv->base + regs[SPI_CMD]);
>> +
>> +               /* enable interrupts */
>> +               writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
>> +
>> +               do {
>> +                       /* read interupts */
>> +                       irq = readb_be(priv->base + regs[SPI_IR_STAT]);
>> +
>> +                       /* transfer completed */
>> +                       if (irq & SPI_IR_DONE_MASK)
>> +                               break;
>> +               } while (1);
>
> This shouldn't be an infinite, try to use wait_for_bit with necessary timeout.

Except this patch, all look OK on this series.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

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

* [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver
  2017-08-10  9:25     ` Jagan Teki
  2017-08-11  9:11       ` Jagan Teki
@ 2017-12-26 12:21       ` Álvaro Fernández Rojas
  1 sibling, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2017-12-26 12:21 UTC (permalink / raw)
  To: u-boot

Hello Jagan,


El 10/08/2017 a las 11:25, Jagan Teki escribió:
> On Sun, Jul 30, 2017 at 5:43 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>> ---
>>   v5: Introduce changes suggested by Jagan Teki:
>>    - Use long structure instead of a custom bmips_spi_hw structure.
>>    - Define constants for each SPI core.
>>   v4: Introduce changes suggested by Jagan Teki:
>>    - Add data for each HW controller instead of having two separate configs.
>>    - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
>>   v3: rename BCM6338 SPI driver to BCM6348
>>    switch to devfdt_get_addr_size_index()
>>   v2: no changes
>>
>>   drivers/spi/Kconfig       |   8 +
>>   drivers/spi/Makefile      |   1 +
>>   drivers/spi/bcm63xx_spi.c | 434 ++++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 443 insertions(+)
>>   create mode 100644 drivers/spi/bcm63xx_spi.c
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index 8a8e8e480f..511643607b 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -40,6 +40,14 @@ config ATMEL_SPI
>>            many AT91 (ARM) chips. This driver can be used to access
>>            the SPI Flash, such as AT25DF321.
>>
>> +config BCM63XX_SPI
>> +       bool "BCM6348 SPI driver"
>> +       depends on ARCH_BMIPS
>> +       help
>> +         Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
>> +         access the SPI NOR flash on platforms embedding these Broadcom
>> +         SPI cores.
>> +
>>   config CADENCE_QSPI
>>          bool "Cadence QSPI driver"
>>          help
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index 9f8b86de76..d9802dd8c3 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -19,6 +19,7 @@ obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>>   obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>>   obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
>>   obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>> +obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
>>   obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>>   obj-$(CONFIG_CF_SPI) += cf_spi.o
>>   obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
>> diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
>> new file mode 100644
>> index 0000000000..904db2b7c7
>> --- /dev/null
>> +++ b/drivers/spi/bcm63xx_spi.c
>> @@ -0,0 +1,434 @@
>> +/*
>> + * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
>> + *
>> + * Derived from linux/drivers/spi/spi-bcm63xx.c:
>> + *     Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
>> + *     Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <spi.h>
>> +#include <reset.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +/* BCM6348 SPI core */
>> +#define SPI_6348_CLK                   0x06
>> +#define SPI_6348_CMD                   0x00
>> +#define SPI_6348_CTL                   0x40
>> +#define SPI_6348_CTL_SHIFT             6
>> +#define SPI_6348_FILL                  0x07
>> +#define SPI_6348_IR_MASK               0x04
>> +#define SPI_6348_IR_STAT               0x02
>> +#define SPI_6348_RX                    0x80
>> +#define SPI_6348_RX_SIZE               0x3f
>> +#define SPI_6348_TX                    0x41
>> +#define SPI_6348_TX_SIZE               0x3f
>> +
>> +/* BCM6358 SPI core */
>> +#define SPI_6358_CLK                   0x706
>> +#define SPI_6358_CMD                   0x700
>> +#define SPI_6358_CTL                   0x000
>> +#define SPI_6358_CTL_SHIFT             14
>> +#define SPI_6358_FILL                  0x707
>> +#define SPI_6358_IR_MASK               0x702
>> +#define SPI_6358_IR_STAT               0x704
>> +#define SPI_6358_RX                    0x400
>> +#define SPI_6358_RX_SIZE               0x220
>> +#define SPI_6358_TX                    0x002
>> +#define SPI_6358_TX_SIZE               0x21e
>> +
>> +/* SPI Clock register */
>> +#define SPI_CLK_SHIFT          0
>> +#define SPI_CLK_20MHZ          (0 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_391MHZ       (1 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_0_781MHZ       (2 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_1_563MHZ       (3 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_3_125MHZ       (4 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_6_250MHZ       (5 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_12_50MHZ       (6 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_25MHZ          (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_MASK           (7 << SPI_CLK_SHIFT)
>> +#define SPI_CLK_SSOFF_SHIFT    3
>> +#define SPI_CLK_SSOFF_2                (2 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_SSOFF_MASK     (7 << SPI_CLK_SSOFF_SHIFT)
>> +#define SPI_CLK_BSWAP_SHIFT    7
>> +#define SPI_CLK_BSWAP_MASK     (1 << SPI_CLK_BSWAP_SHIFT)
>> +
>> +/* SPI Command register */
>> +#define SPI_CMD_OP_SHIFT       0
>> +#define SPI_CMD_OP_START       (0x3 << SPI_CMD_OP_SHIFT)
>> +#define SPI_CMD_SLAVE_SHIFT    4
>> +#define SPI_CMD_SLAVE_MASK     (0xf << SPI_CMD_SLAVE_SHIFT)
>> +#define SPI_CMD_PREPEND_SHIFT  8
>> +#define SPI_CMD_PREPEND_BYTES  0xf
>> +#define SPI_CMD_3WIRE_SHIFT    12
>> +#define SPI_CMD_3WIRE_MASK     (1 << SPI_CMD_3WIRE_SHIFT)
>> +
>> +/* SPI Control register */
>> +#define SPI_CTL_TYPE_FD_RW     0
>> +#define SPI_CTL_TYPE_HD_W      1
>> +#define SPI_CTL_TYPE_HD_R      2
>> +
>> +/* SPI Interrupt registers */
>> +#define SPI_IR_DONE_SHIFT      0
>> +#define SPI_IR_DONE_MASK       (1 << SPI_IR_DONE_SHIFT)
>> +#define SPI_IR_RXOVER_SHIFT    1
>> +#define SPI_IR_RXOVER_MASK     (1 << SPI_IR_RXOVER_SHIFT)
>> +#define SPI_IR_TXUNDER_SHIFT   2
>> +#define SPI_IR_TXUNDER_MASK    (1 << SPI_IR_TXUNDER_SHIFT)
>> +#define SPI_IR_TXOVER_SHIFT    3
>> +#define SPI_IR_TXOVER_MASK     (1 << SPI_IR_TXOVER_SHIFT)
>> +#define SPI_IR_RXUNDER_SHIFT   4
>> +#define SPI_IR_RXUNDER_MASK    (1 << SPI_IR_RXUNDER_SHIFT)
>> +#define SPI_IR_CLEAR_MASK      (SPI_IR_DONE_MASK |\
>> +                                SPI_IR_RXOVER_MASK |\
>> +                                SPI_IR_TXUNDER_MASK |\
>> +                                SPI_IR_TXOVER_MASK |\
>> +                                SPI_IR_RXUNDER_MASK)
>> +
>> +enum bcm63xx_regs_spi {
>> +       SPI_CLK,
>> +       SPI_CMD,
>> +       SPI_CTL,
>> +       SPI_CTL_SHIFT,
>> +       SPI_FILL,
>> +       SPI_IR_MASK,
>> +       SPI_IR_STAT,
>> +       SPI_RX,
>> +       SPI_RX_SIZE,
>> +       SPI_TX,
>> +       SPI_TX_SIZE,
>> +};
>> +
>> +struct bcm63xx_spi_priv {
>> +       const unsigned long *regs;
>> +       void __iomem *base;
>> +       size_t tx_bytes;
>> +       uint8_t num_cs;
>> +};
>> +
>> +#define SPI_CLK_CNT            8
>> +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
>> +       { 25000000, SPI_CLK_25MHZ },
>> +       { 20000000, SPI_CLK_20MHZ },
>> +       { 12500000, SPI_CLK_12_50MHZ },
>> +       {  6250000, SPI_CLK_6_250MHZ },
>> +       {  3125000, SPI_CLK_3_125MHZ },
>> +       {  1563000, SPI_CLK_1_563MHZ },
>> +       {   781000, SPI_CLK_0_781MHZ },
>> +       {   391000, SPI_CLK_0_391MHZ }
>> +};
>> +
>> +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
>> +                          struct spi_cs_info *info)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +
>> +       if (cs >= priv->num_cs) {
>> +               error("no cs %u\n", cs);
>> +               return -ENODEV;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +       const unsigned long *regs = priv->regs;
>> +
>> +       if (mode & SPI_LSB_FIRST)
>> +               setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
>> +       else
>> +               clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
>> +
>> +       return 0;
>> +}
>> +
>> +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
>> +       const unsigned long *regs = priv->regs;
>> +       uint8_t clk_cfg;
>> +       int i;
>> +
>> +       /* default to lowest clock configuration */
>> +       clk_cfg = SPI_CLK_0_391MHZ;
>> +
>> +       /* find the closest clock configuration */
>> +       for (i = 0; i < SPI_CLK_CNT; i++) {
>> +               if (speed >= bcm63xx_spi_freq_table[i][0]) {
>> +                       clk_cfg = bcm63xx_spi_freq_table[i][1];
>> +                       break;
>> +               }
>> +       }
>> +
>> +       /* write clock configuration */
>> +       clrsetbits_8(priv->base + regs[SPI_CLK],
>> +                    SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
>> +                    clk_cfg | SPI_CLK_SSOFF_2);
>> +
>> +       return 0;
>> +}
>> +
>> +/*
>> + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
>> + * they are HW controlled.
>> + * However, it provides a mechanism to prepend write transfers prior to read
>> + * transfers (with a maximum prepend of 15 bytes), which is usually enough for
>> + * SPI-connected flashes since reading requires prepending a write transfer of
>> + * 5 bytes.
>> + *
>> + * This implementation takes advantage of the prepend mechanism and combines
>> + * multiple transfers into a single one where possible (single/multiple write
>> + * transfer(s) followed by a final read/write transfer).
>> + * However, it's not possible to buffer reads, which means that read transfers
>> + * should always be done as the final ones.
>> + * On the other hand, take into account that combining write transfers into
>> + * a single one is just buffering and doesn't require prepend mechanism.
>> + */
>> +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
>> +               const void *dout, void *din, unsigned long flags)
>> +{
>> +       struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
>> +       const unsigned long *regs = priv->regs;
>> +       size_t data_bytes = bitlen / 8;
>> +
>> +       if (flags & SPI_XFER_BEGIN) {
>> +               /* clear prepends */
>> +               priv->tx_bytes = 0;
>> +
>> +               /* initialize hardware */
>> +               writeb_be(0, priv->base + regs[SPI_IR_MASK]);
>> +       }
>> +
>> +       if (din) {
>> +               /* buffering reads not possible since cs is hw controlled */
>> +               if (!(flags & SPI_XFER_END)) {
>> +                       error("unable to buffer reads\n");
>> +                       return -EINVAL;
>> +               }
>> +
>> +               /* check rx size */
>> +                if (data_bytes > regs[SPI_RX_SIZE]) {
>> +                       error("max rx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +       }
>> +
>> +       if (dout) {
>> +               /* check tx size */
>> +               if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
>> +                       error("max tx bytes exceeded\n");
>> +                       return -EMSGSIZE;
>> +               }
>> +
>> +               /* copy tx data */
>> +               memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
>> +                           dout, data_bytes);
>> +               priv->tx_bytes += data_bytes;
>> +       }
>> +
>> +       if (flags & SPI_XFER_END) {
>> +               struct dm_spi_slave_platdata *plat =
>> +                       dev_get_parent_platdata(dev);
>> +               uint16_t val;
>> +               uint8_t irq;
>> +
>> +               /* determine control config */
>> +               if (dout && !din) {
>> +                       /* buffered write transfers */
>> +                       val = priv->tx_bytes;
>> +                       val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
>> +                       priv->tx_bytes = 0;
>> +               } else {
>> +                       if (dout && din && (flags & SPI_XFER_ONCE)) {
>> +                               /* full duplex read/write */
>> +                               val = data_bytes;
>> +                               val |= (SPI_CTL_TYPE_FD_RW <<
>> +                                       regs[SPI_CTL_SHIFT]);
>> +                               priv->tx_bytes = 0;
>> +                       } else {
>> +                               /* prepended write transfer */
>> +                               val = data_bytes;
>> +                               val |= (SPI_CTL_TYPE_HD_R <<
>> +                                       regs[SPI_CTL_SHIFT]);
>> +                               if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
>> +                                       error("max prepend bytes exceeded\n");
>> +                                       return -EMSGSIZE;
>> +                               }
>> +                       }
>> +               }
>> +
>> +               if (regs[SPI_CTL_SHIFT] >= 8)
>> +                       writew_be(val, priv->base + regs[SPI_CTL]);
>> +               else
>> +                       writeb_be(val, priv->base + regs[SPI_CTL]);
>> +
>> +               /* clear interrupts */
>> +               writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
>> +
>> +               /* issue the transfer */
>> +               val = SPI_CMD_OP_START;
>> +               val |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
>> +               val |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
>> +               if (plat->mode & SPI_3WIRE)
>> +                       val |= SPI_CMD_3WIRE_MASK;
> Please use cmd instead of val to avoid confusion for previous register
> reads use same val.
OK
> And for issue the transfer why do we need to
> update the mode here? usually transfer will be initiate with OP_START,
> CS and prepend length right? and modes are usually altered during
> .set_mode.
Because 3 wire mode needs to be set on every issued command.
Anyway, I haven't tested this mode, so if you don't want mode altered 
here I can remove it completely.
>
>> +               writew_be(val, priv->base + regs[SPI_CMD]);
>> +
>> +               /* enable interrupts */
>> +               writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
>> +
>> +               do {
>> +                       /* read interupts */
>> +                       irq = readb_be(priv->base + regs[SPI_IR_STAT]);
>> +
>> +                       /* transfer completed */
>> +                       if (irq & SPI_IR_DONE_MASK)
>> +                               break;
>> +               } while (1);
> This shouldn't be an infinite, try to use wait_for_bit with necessary timeout.
I can't use wait_for_bit because reading that address as a 32 bit 
register causes an exception.
However, I could add another version of wait_for_bit such as the following:
https://gist.github.com/Noltari/8ab369cae5f8577255c81e16402b358e
Is that acceptable?

>
> thanks!

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

* [U-Boot] [PATCH v6 00/11] mips: bmips: add SPI support
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (10 preceding siblings ...)
  2017-08-07  8:35   ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Jagan Teki
@ 2018-01-02 19:01   ` Álvaro Fernández Rojas
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function Álvaro Fernández Rojas
                       ` (10 more replies)
  11 siblings, 11 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v6: Introduce changes suggested by Jagan Teki:
- Use cmd instead of val to avoid confusions.
- Switch to wait_for_bit instead of infinite loop.
v5: Introduce changes suggested by Jagan Teki:
- Use long structs for registers
v4: Introduce changes suggested by Jagan Teki:
- Add data for each HW controller instead of having two separate configs.
v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (11):
  wait_bit: add big endian version of wait_for_bit function
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/mips/dts/brcm,bcm3380.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm63268.dtsi      |  17 ++
 arch/mips/dts/brcm,bcm6338.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  17 ++
 arch/mips/dts/brcm,bcm6358.dtsi       |  17 ++
 arch/mips/dts/netgear,cg3100d.dts     |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 configs/netgear_cg3100d_ram_defconfig |   8 +
 configs/sagem_f at st1704_ram_defconfig  |   8 +
 drivers/mtd/spi/spi_flash.c           |   5 +-
 drivers/spi/Kconfig                   |   8 +
 drivers/spi/Makefile                  |   1 +
 drivers/spi/bcm63xx_spi.c             | 433 ++++++++++++++++++++++++++++++++++
 include/spi.h                         |   5 +-
 include/wait_bit.h                    |  44 ++++
 15 files changed, 619 insertions(+), 2 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.11.0

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

* [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-02 20:24       ` Daniel Schwierzeck
  2018-01-07 18:08       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 02/11] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                       ` (9 subsequent siblings)
  10 siblings, 2 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

Add 8/16/32 bits and BE/LE versions of wait_for_bit.
This is needed for reading registers that are not aligned to 32 bits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v6: Introduce changes suggested by Jagan Teki:
 - Switch to wait_for_bit instead of infinite loop.

 include/wait_bit.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/include/wait_bit.h b/include/wait_bit.h
index 06ad43a122..47891fa75c 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -69,5 +69,49 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
 	return -ETIMEDOUT;
 }
 
+#define BUILD_WAIT_FOR_BIT(sfx, type, read)				\
+									\
+static inline int wait_for_bit_##sfx(const char *prefix,		\
+				     const u32 *reg,			\
+				     const type mask,			\
+				     const bool set,			\
+				     const unsigned int timeout_ms,	\
+				     const bool breakable)		\
+{									\
+	type val;							\
+	unsigned long start = get_timer(0);				\
+									\
+	while (1) {							\
+		val = read(reg);					\
+									\
+		if (!set)						\
+			val = ~val;					\
+									\
+		if ((val & mask) == mask)				\
+			return 0;					\
+									\
+		if (get_timer(start) > timeout_ms)			\
+			break;						\
+									\
+		if (breakable && ctrlc()) {				\
+			puts("Abort\n");				\
+			return -EINTR;					\
+		}							\
+									\
+		udelay(1);						\
+		WATCHDOG_RESET();					\
+	}								\
+									\
+	debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", prefix,	\
+	      reg, mask, set);						\
+									\
+	return -ETIMEDOUT;						\
+}
+
+BUILD_WAIT_FOR_BIT(8, u8, readb)
+BUILD_WAIT_FOR_BIT(le16, u16, readw)
+BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
+BUILD_WAIT_FOR_BIT(le32, u32, readl)
+BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
 
 #endif
-- 
2.11.0

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

* [U-Boot] [PATCH v6 02/11] drivers: spi: allow limiting reads
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 03/11] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                       ` (8 subsequent siblings)
  10 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 51e28bf07b..e40e1c01de 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -516,6 +516,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 08c7480fda..4787454e59 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 
-- 
2.11.0

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

* [U-Boot] [PATCH v6 03/11] drivers: spi: consider command bytes when sending transfers
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function Álvaro Fernández Rojas
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 02/11] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 04/11] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v6: no changes
 v5: no changes
 v4: no changes
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e40e1c01de..294d9f9d79 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -405,7 +405,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index 4787454e59..5a7df1c706 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.11.0

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

* [U-Boot] [PATCH v6 04/11] dm: spi: add BCM63xx SPI driver
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (2 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 03/11] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:10       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 05/11] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                       ` (6 subsequent siblings)
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: Introduce changes suggested by Jagan Teki:
 - Use cmd instead of val to avoid confusions.
 - Switch to wait_for_bit instead of infinite loop.
 v5: Introduce changes suggested by Jagan Teki:
  - Use long structure instead of a custom bmips_spi_hw structure.
  - Define constants for each SPI core.
 v4: Introduce changes suggested by Jagan Teki:
  - Add data for each HW controller instead of having two separate configs.
  - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |   8 +
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 442 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 494639fb01..ebc71c2e42 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,14 @@ config ATMEL_SPI
 	  many AT91 (ARM) chips. This driver can be used to access
 	  the SPI Flash, such as AT25DF321.
 
+config BCM63XX_SPI
+	bool "BCM6348 SPI driver"
+	depends on ARCH_BMIPS
+	help
+	  Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding these Broadcom
+	  SPI cores.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e3184db67f..5770b3f7cc 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,6 +18,7 @@ endif
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000000..88257db728
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* BCM6348 SPI core */
+#define SPI_6348_CLK			0x06
+#define SPI_6348_CMD			0x00
+#define SPI_6348_CTL			0x40
+#define SPI_6348_CTL_SHIFT		6
+#define SPI_6348_FILL			0x07
+#define SPI_6348_IR_MASK		0x04
+#define SPI_6348_IR_STAT		0x02
+#define SPI_6348_RX			0x80
+#define SPI_6348_RX_SIZE		0x3f
+#define SPI_6348_TX			0x41
+#define SPI_6348_TX_SIZE		0x3f
+
+/* BCM6358 SPI core */
+#define SPI_6358_CLK			0x706
+#define SPI_6358_CMD			0x700
+#define SPI_6358_CTL			0x000
+#define SPI_6358_CTL_SHIFT		14
+#define SPI_6358_FILL			0x707
+#define SPI_6358_IR_MASK		0x702
+#define SPI_6358_IR_STAT		0x704
+#define SPI_6358_RX			0x400
+#define SPI_6358_RX_SIZE		0x220
+#define SPI_6358_TX			0x002
+#define SPI_6358_TX_SIZE		0x21e
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Control register */
+#define SPI_CTL_TYPE_FD_RW	0
+#define SPI_CTL_TYPE_HD_W	1
+#define SPI_CTL_TYPE_HD_R	2
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+enum bcm63xx_regs_spi {
+	SPI_CLK,
+	SPI_CMD,
+	SPI_CTL,
+	SPI_CTL_SHIFT,
+	SPI_FILL,
+	SPI_IR_MASK,
+	SPI_IR_STAT,
+	SPI_RX,
+	SPI_RX_SIZE,
+	SPI_TX,
+	SPI_TX_SIZE,
+};
+
+struct bcm63xx_spi_priv {
+	const unsigned long *regs;
+	void __iomem *base;
+	size_t tx_bytes;
+	uint8_t num_cs;
+};
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		printf("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->base + regs[SPI_CLK],
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			printf("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > regs[SPI_RX_SIZE]) {
+			printf("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
+			printf("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val, cmd;
+		int ret;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val = priv->tx_bytes;
+			val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_FD_RW <<
+					regs[SPI_CTL_SHIFT]);
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_HD_R <<
+					regs[SPI_CTL_SHIFT]);
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					printf("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+
+		if (regs[SPI_CTL_SHIFT] >= 8)
+			writew_be(val, priv->base + regs[SPI_CTL]);
+		else
+			writeb_be(val, priv->base + regs[SPI_CTL]);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
+
+		/* issue the transfer */
+		cmd = SPI_CMD_OP_START;
+		cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			cmd |= SPI_CMD_3WIRE_MASK;
+		writew_be(cmd, priv->base + regs[SPI_CMD]);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
+
+		ret = wait_for_bit_8(__func__, priv->base + regs[SPI_IR_STAT],
+				     SPI_IR_DONE_MASK, true, 1000, false);
+		if (ret) {
+			printf("interrupt timeout\n");
+			return ret;
+		}
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->base + regs[SPI_RX],
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const unsigned long bcm6348_spi_regs[] = {
+	[SPI_CLK] = SPI_6348_CLK,
+	[SPI_CMD] = SPI_6348_CMD,
+	[SPI_CTL] = SPI_6348_CTL,
+	[SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT,
+	[SPI_FILL] = SPI_6348_FILL,
+	[SPI_IR_MASK] = SPI_6348_IR_MASK,
+	[SPI_IR_STAT] = SPI_6348_IR_STAT,
+	[SPI_RX] = SPI_6348_RX,
+	[SPI_RX_SIZE] = SPI_6348_RX_SIZE,
+	[SPI_TX] = SPI_6348_TX,
+	[SPI_TX_SIZE] = SPI_6348_TX_SIZE,
+};
+
+static const unsigned long bcm6358_spi_regs[] = {
+	[SPI_CLK] = SPI_6358_CLK,
+	[SPI_CMD] = SPI_6358_CMD,
+	[SPI_CTL] = SPI_6358_CTL,
+	[SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT,
+	[SPI_FILL] = SPI_6358_FILL,
+	[SPI_IR_MASK] = SPI_6358_IR_MASK,
+	[SPI_IR_STAT] = SPI_6358_IR_STAT,
+	[SPI_RX] = SPI_6358_RX,
+	[SPI_RX_SIZE] = SPI_6358_RX_SIZE,
+	[SPI_TX] = SPI_6358_TX,
+	[SPI_TX_SIZE] = SPI_6358_TX_SIZE,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-spi",
+		.data = (ulong)&bcm6348_spi_regs,
+	}, {
+		.compatible = "brcm,bcm6358-spi",
+		.data = (ulong)&bcm6358_spi_regs,
+	}, { /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		printf("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = regs[SPI_RX_SIZE];
+	slave->max_write_size = regs[SPI_TX_SIZE];
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	const unsigned long *regs =
+		(const unsigned long *)dev_get_driver_data(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = regs;
+	priv->base = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_free(&clk);
+	if (ret < 0)
+		return ret;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_free(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	/* initialize hardware */
+	writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+
+	/* set fill register */
+	writeb_be(0xff, priv->base + regs[SPI_FILL]);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v6 05/11] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (3 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 04/11] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:11       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 06/11] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                       ` (5 subsequent siblings)
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a4372b..0cab44cb8d 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v6 06/11] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (4 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 05/11] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:12       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 07/11] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                       ` (4 subsequent siblings)
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643b5a..540b9fea5b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v6 07/11] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (5 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 06/11] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:12       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 08/11] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                       ` (3 subsequent siblings)
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf80e0..1662783279 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v6 08/11] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (6 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 07/11] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:13       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 09/11] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                       ` (2 subsequent siblings)
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb048..f83a6ea8df 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v6 09/11] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (7 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 08/11] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:13       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 10/11] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 11/11] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96bef8..6e3d9c3820 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.11.0

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

* [U-Boot] [PATCH v6 10/11] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (8 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 09/11] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:14       ` Jagan Teki
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 11/11] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5551..dd0e5b8b7c 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index cfc56cba37..5c091353e5 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -39,3 +39,11 @@ CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
-- 
2.11.0

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

* [U-Boot] [PATCH v6 11/11] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
                       ` (9 preceding siblings ...)
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 10/11] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2018-01-02 19:01     ` Álvaro Fernández Rojas
  2018-01-07 18:14       ` Jagan Teki
  10 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-02 19:01 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7616..5f85c7346f 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index 7665c78d3f..369c919ac7 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -41,3 +41,11 @@ CONFIG_RESET_BCM6345=y
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
 CONFIG_WDT_BCM6345=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
-- 
2.11.0

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

* [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function Álvaro Fernández Rojas
@ 2018-01-02 20:24       ` Daniel Schwierzeck
  2018-01-07 18:08       ` Jagan Teki
  1 sibling, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2018-01-02 20:24 UTC (permalink / raw)
  To: u-boot



On 02.01.2018 20:01, Álvaro Fernández Rojas wrote:
> Add 8/16/32 bits and BE/LE versions of wait_for_bit.
> This is needed for reading registers that are not aligned to 32 bits.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v6: Introduce changes suggested by Jagan Teki:
>  - Switch to wait_for_bit instead of infinite loop.
> 
>  include/wait_bit.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/include/wait_bit.h b/include/wait_bit.h
> index 06ad43a122..47891fa75c 100644
> --- a/include/wait_bit.h
> +++ b/include/wait_bit.h
> @@ -69,5 +69,49 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
>  	return -ETIMEDOUT;
>  }
>  
> +#define BUILD_WAIT_FOR_BIT(sfx, type, read)				\
> +									\
> +static inline int wait_for_bit_##sfx(const char *prefix,		\
> +				     const u32 *reg,			\

I suggest to use 'const void *reg' for compatibility with 64 bit systems
and to be consistant with the most readl() implementations

> +				     const type mask,			\
> +				     const bool set,			\
> +				     const unsigned int timeout_ms,	\
> +				     const bool breakable)		\
> +{									\
> +	type val;							\
> +	unsigned long start = get_timer(0);				\
> +									\
> +	while (1) {							\
> +		val = read(reg);					\
> +									\
> +		if (!set)						\
> +			val = ~val;					\
> +									\
> +		if ((val & mask) == mask)				\
> +			return 0;					\
> +									\
> +		if (get_timer(start) > timeout_ms)			\
> +			break;						\
> +									\
> +		if (breakable && ctrlc()) {				\
> +			puts("Abort\n");				\
> +			return -EINTR;					\
> +		}							\
> +									\
> +		udelay(1);						\
> +		WATCHDOG_RESET();					\
> +	}								\
> +									\
> +	debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", prefix,	\
> +	      reg, mask, set);						\

almost all users pass __func__ as value for the prefix argument. Since
this is a macro now, we could directly use __func__ in the debug() call
and omit the prefix argument

> +									\
> +	return -ETIMEDOUT;						\
> +}
> +
> +BUILD_WAIT_FOR_BIT(8, u8, readb)
> +BUILD_WAIT_FOR_BIT(le16, u16, readw)
> +BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
> +BUILD_WAIT_FOR_BIT(le32, u32, readl)
> +BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
>  
>  #endif
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180102/6e46116c/attachment.sig>

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

* [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function Álvaro Fernández Rojas
  2018-01-02 20:24       ` Daniel Schwierzeck
@ 2018-01-07 18:08       ` Jagan Teki
  1 sibling, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:08 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Add 8/16/32 bits and BE/LE versions of wait_for_bit.
> This is needed for reading registers that are not aligned to 32 bits.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v6: Introduce changes suggested by Jagan Teki:
>  - Switch to wait_for_bit instead of infinite loop.
>
>  include/wait_bit.h | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
>
> diff --git a/include/wait_bit.h b/include/wait_bit.h
> index 06ad43a122..47891fa75c 100644
> --- a/include/wait_bit.h
> +++ b/include/wait_bit.h
> @@ -69,5 +69,49 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
>         return -ETIMEDOUT;
>  }
>
> +#define BUILD_WAIT_FOR_BIT(sfx, type, read)                            \
> +                                                                       \
> +static inline int wait_for_bit_##sfx(const char *prefix,               \
> +                                    const u32 *reg,                    \
> +                                    const type mask,                   \
> +                                    const bool set,                    \
> +                                    const unsigned int timeout_ms,     \
> +                                    const bool breakable)              \
> +{                                                                      \
> +       type val;                                                       \
> +       unsigned long start = get_timer(0);                             \
> +                                                                       \
> +       while (1) {                                                     \
> +               val = read(reg);                                        \
> +                                                                       \
> +               if (!set)                                               \
> +                       val = ~val;                                     \
> +                                                                       \
> +               if ((val & mask) == mask)                               \
> +                       return 0;                                       \
> +                                                                       \
> +               if (get_timer(start) > timeout_ms)                      \
> +                       break;                                          \
> +                                                                       \
> +               if (breakable && ctrlc()) {                             \
> +                       puts("Abort\n");                                \
> +                       return -EINTR;                                  \
> +               }                                                       \
> +                                                                       \
> +               udelay(1);                                              \
> +               WATCHDOG_RESET();                                       \
> +       }                                                               \
> +                                                                       \
> +       debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", prefix,     \
> +             reg, mask, set);                                          \
> +                                                                       \
> +       return -ETIMEDOUT;                                              \
> +}
> +
> +BUILD_WAIT_FOR_BIT(8, u8, readb)
> +BUILD_WAIT_FOR_BIT(le16, u16, readw)
> +BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
> +BUILD_WAIT_FOR_BIT(le32, u32, readl)

look like existing wait_for_bit is of this type, better add these
macros to existing code and update wait_for_bit from callers if less
changes or add macro to redirect wait_for_bit_le32 but I prefer first
one because this even need to update in future.

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

* [U-Boot] [PATCH v6 04/11] dm: spi: add BCM63xx SPI driver
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 04/11] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2018-01-07 18:10       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:10 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v6 05/11] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 05/11] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2018-01-07 18:11       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:11 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v6 06/11] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 06/11] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2018-01-07 18:12       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:12 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v6 07/11] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 07/11] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2018-01-07 18:12       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:12 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v6 08/11] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 08/11] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2018-01-07 18:13       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:13 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v6 09/11] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 09/11] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2018-01-07 18:13       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:13 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> This driver manages the low speed SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v6 10/11] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 10/11] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2018-01-07 18:14       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:14 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> It's a Winbond (w25x32) 4 MB SPI flash.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v6 11/11] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2018-01-02 19:01     ` [U-Boot] [PATCH v6 11/11] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
@ 2018-01-07 18:14       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-07 18:14 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 3, 2018 at 12:31 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> It's a Spansion (s25fl064a) 8 MB SPI flash.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (13 preceding siblings ...)
  2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2018-01-10 20:26 ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
                     ` (12 more replies)
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (2 subsequent siblings)
  17 siblings, 13 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v7: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
- Use const void* reg for compatibility with 64 bit systems.
- Remove prefix and use __func__ instead.
- Remove wait_for_bit and update callers to wait_for_bit_le32.
v6: Introduce changes suggested by Jagan Teki:
- Use cmd instead of val to avoid confusions.
- Switch to wait_for_bit instead of infinite loop.
v5: Introduce changes suggested by Jagan Teki:
- Use long structs for registers
v4: Introduce changes suggested by Jagan Teki:
- Add data for each HW controller instead of having two separate configs.
v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (13):
  wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  wait_bit: use wait_for_bit_le32 instead of wait_for_bit
  wait_bit: remove old wait_for_bit function
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/arm/mach-imx/mx6/ddr.c                   |  22 +-
 arch/arm/mach-socfpga/clock_manager.c         |   4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |   8 +-
 arch/arm/mach-socfpga/reset_manager_arria10.c |  36 +--
 arch/mips/dts/brcm,bcm3380.dtsi               |  17 +
 arch/mips/dts/brcm,bcm63268.dtsi              |  17 +
 arch/mips/dts/brcm,bcm6338.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6348.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6358.dtsi               |  17 +
 arch/mips/dts/netgear,cg3100d.dts             |  12 +
 arch/mips/dts/sagem,f at st1704.dts              |  12 +
 arch/mips/mach-ath79/ar934x/clk.c             |   2 +-
 board/samtec/vining_2000/vining_2000.c        |   4 +-
 configs/netgear_cg3100d_ram_defconfig         |   8 +
 configs/sagem_f at st1704_ram_defconfig          |   8 +
 drivers/clk/clk_pic32.c                       |  12 +-
 drivers/clk/renesas/clk-rcar-gen3.c           |   4 +-
 drivers/ddr/microchip/ddr2.c                  |   8 +-
 drivers/fpga/socfpga_arria10.c                |  17 +-
 drivers/mmc/msm_sdhci.c                       |   8 +-
 drivers/mtd/pic32_flash.c                     |   4 +-
 drivers/mtd/spi/spi_flash.c                   |   5 +-
 drivers/net/ag7xxx.c                          |  16 +-
 drivers/net/dwc_eth_qos.c                     |  17 +-
 drivers/net/ethoc.c                           |   8 +-
 drivers/net/pic32_eth.c                       |  12 +-
 drivers/net/pic32_mdio.c                      |  28 +-
 drivers/net/ravb.c                            |   4 +-
 drivers/net/xilinx_axi_emac.c                 |   4 +-
 drivers/net/zynq_gem.c                        |  12 +-
 drivers/reset/sti-reset.c                     |   4 +-
 drivers/serial/serial_pic32.c                 |   4 +-
 drivers/spi/Kconfig                           |   8 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/atmel_spi.c                       |   4 +-
 drivers/spi/bcm63xx_spi.c                     | 433 ++++++++++++++++++++++++++
 drivers/spi/cadence_qspi_apb.c                |  14 +-
 drivers/spi/fsl_qspi.c                        |  20 +-
 drivers/spi/mvebu_a3700_spi.c                 |  20 +-
 drivers/usb/host/dwc2.c                       |  24 +-
 drivers/usb/host/ehci-msm.c                   |   3 +-
 drivers/usb/host/ehci-mx6.c                   |   5 +-
 drivers/usb/host/ohci-lpc32xx.c               |  12 +-
 drivers/usb/host/xhci-rcar.c                  |  12 +-
 drivers/video/atmel_hlcdfb.c                  |  64 ++--
 include/spi.h                                 |   5 +-
 include/wait_bit.h                            |  81 ++---
 47 files changed, 826 insertions(+), 248 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.11.0

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

* [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-11  1:50     ` Daniel Schwierzeck
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 02/13] wait_bit: use wait_for_bit_le32 instead " Álvaro Fernández Rojas
                     ` (11 subsequent siblings)
  12 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

Add 8/16/32 bits and BE/LE versions of wait_for_bit.
This is needed for reading registers that are not aligned to 32 bits, and for
Big Endian platforms.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Use const void* reg for compatibility with 64 bit systems.
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Switch to wait_for_bit instead of infinite loop.

 include/wait_bit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/include/wait_bit.h b/include/wait_bit.h
index 06ad43a122..bde6d2cfc3 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -69,5 +69,66 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
 	return -ETIMEDOUT;
 }
 
+/**
+ * wait_for_bit_x()	waits for bit set/cleared in register
+ *
+ * Function polls register waiting for specific bit(s) change
+ * (either 0->1 or 1->0). It can fail under two conditions:
+ * - Timeout
+ * - User interaction (CTRL-C)
+ * Function succeeds only if all bits of masked register are set/cleared
+ * (depending on set option).
+ *
+ * @param reg		Register that will be read (using read_x())
+ * @param mask		Bit(s) of register that must be active
+ * @param set		Selects wait condition (bit set or clear)
+ * @param timeout_ms	Timeout (in milliseconds)
+ * @param breakable	Enables CTRL-C interruption
+ * @return		0 on success, -ETIMEDOUT or -EINTR on failure
+ */
+
+#define BUILD_WAIT_FOR_BIT(sfx, type, read)				\
+									\
+static inline int wait_for_bit_##sfx(const void *reg,			\
+				     const type mask,			\
+				     const bool set,			\
+				     const unsigned int timeout_ms,	\
+				     const bool breakable)		\
+{									\
+	type val;							\
+	unsigned long start = get_timer(0);				\
+									\
+	while (1) {							\
+		val = read(reg);					\
+									\
+		if (!set)						\
+			val = ~val;					\
+									\
+		if ((val & mask) == mask)				\
+			return 0;					\
+									\
+		if (get_timer(start) > timeout_ms)			\
+			break;						\
+									\
+		if (breakable && ctrlc()) {				\
+			puts("Abort\n");				\
+			return -EINTR;					\
+		}							\
+									\
+		udelay(1);						\
+		WATCHDOG_RESET();					\
+	}								\
+									\
+	debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__,	\
+	      reg, mask, set);						\
+									\
+	return -ETIMEDOUT;						\
+}
+
+BUILD_WAIT_FOR_BIT(8, u8, readb)
+BUILD_WAIT_FOR_BIT(le16, u16, readw)
+BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
+BUILD_WAIT_FOR_BIT(le32, u32, readl)
+BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
 
 #endif
-- 
2.11.0

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

* [U-Boot] [PATCH v7 02/13] wait_bit: use wait_for_bit_le32 instead of wait_for_bit
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-11  1:50     ` Daniel Schwierzeck
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 03/13] wait_bit: remove old wait_for_bit function Álvaro Fernández Rojas
                     ` (10 subsequent siblings)
  12 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

wait_for_bit callers use the 32 bit LE version

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v7: Introduce changes suggested by Jagan Teki:
 - Remove wait_for_bit and update callers to wait_for_bit_le32.

 arch/arm/mach-imx/mx6/ddr.c                   | 22 ++++-----
 arch/arm/mach-socfpga/clock_manager.c         |  4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |  8 ++--
 arch/arm/mach-socfpga/reset_manager_arria10.c | 36 +++++++--------
 arch/mips/mach-ath79/ar934x/clk.c             |  2 +-
 board/samtec/vining_2000/vining_2000.c        |  4 +-
 drivers/clk/clk_pic32.c                       | 12 ++---
 drivers/clk/renesas/clk-rcar-gen3.c           |  4 +-
 drivers/ddr/microchip/ddr2.c                  |  8 ++--
 drivers/fpga/socfpga_arria10.c                | 17 +++----
 drivers/mmc/msm_sdhci.c                       |  8 ++--
 drivers/mtd/pic32_flash.c                     |  4 +-
 drivers/net/ag7xxx.c                          | 16 +++----
 drivers/net/dwc_eth_qos.c                     | 17 +++----
 drivers/net/ethoc.c                           |  8 ++--
 drivers/net/pic32_eth.c                       | 12 ++---
 drivers/net/pic32_mdio.c                      | 28 ++++++------
 drivers/net/ravb.c                            |  4 +-
 drivers/net/xilinx_axi_emac.c                 |  4 +-
 drivers/net/zynq_gem.c                        | 12 ++---
 drivers/reset/sti-reset.c                     |  4 +-
 drivers/serial/serial_pic32.c                 |  4 +-
 drivers/spi/atmel_spi.c                       |  4 +-
 drivers/spi/cadence_qspi_apb.c                | 14 +++---
 drivers/spi/fsl_qspi.c                        | 20 ++++-----
 drivers/spi/mvebu_a3700_spi.c                 | 20 +++++----
 drivers/usb/host/dwc2.c                       | 24 +++++-----
 drivers/usb/host/ehci-msm.c                   |  3 +-
 drivers/usb/host/ehci-mx6.c                   |  5 +--
 drivers/usb/host/ohci-lpc32xx.c               | 12 ++---
 drivers/usb/host/xhci-rcar.c                  | 12 ++---
 drivers/video/atmel_hlcdfb.c                  | 64 +++++++++++++--------------
 32 files changed, 207 insertions(+), 209 deletions(-)

diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index 52a9a25904..f07f938c65 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -21,10 +21,10 @@ static void reset_read_data_fifos(void)
 
 	/* Reset data FIFOs twice. */
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 }
 
 static void precharge_all(const bool cs0_enable, const bool cs1_enable)
@@ -39,12 +39,12 @@ static void precharge_all(const bool cs0_enable, const bool cs1_enable)
 	 */
 	if (cs0_enable) { /* CS0 */
 		writel(0x04008050, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 
 	if (cs1_enable) { /* CS1 */
 		writel(0x04008058, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 }
 
@@ -146,7 +146,7 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * 7. Upon completion of this process the MMDC de-asserts
 	 * the MPWLGCR[HW_WL_EN]
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
 
 	/*
 	 * 8. check for any errors: check both PHYs for x64 configuration,
@@ -278,7 +278,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 		writel(0x00008028, &mmdc0->mdscr);
 
 	/* poll to make sure the con_ack bit was asserted */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 
 	/*
 	 * Check MDMISC register CALIB_PER_CS to see which CS calibration
@@ -312,7 +312,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * this bit until it clears to indicate completion of the write access.
 	 */
 	setbits_le32(&mmdc0->mpswdar0, 1);
-	wait_for_bit("MMDC", &mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
 
 	/* Set the RD_DL_ABS# bits to their default values
 	 * (will be calibrated later in the read delay-line calibration).
@@ -359,7 +359,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	setbits_le32(&mmdc0->mpdgctrl0, 5 << 28);
 
 	/* Poll for completion.  MPDGCTRL0[HW_DG_EN] should be 0 */
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
 
 	/*
 	 * Check to see if any errors were encountered during calibration
@@ -423,7 +423,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * setting MPRDDLHWCTL[HW_RD_DL_EN] = 0.   Also, ensure that
 	 * no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
 
 	/* check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mprddlhwctl) & 0x0000000f)
@@ -477,7 +477,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * by setting MPWRDLHWCTL[HW_WR_DL_EN] = 0.
 	 * Also, ensure that no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
 
 	/* Check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mpwrdlhwctl) & 0x0000000f)
@@ -526,7 +526,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	writel(0x0, &mmdc0->mdscr);	/* CS0 */
 
 	/* Poll to make sure the con_ack bit is clear */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 0, 100, 0);
 
 	/*
 	 * Print out the registers that were updated as a result
diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c
index cb6ae03696..42de783217 100644
--- a/arch/arm/mach-socfpga/clock_manager.c
+++ b/arch/arm/mach-socfpga/clock_manager.c
@@ -37,8 +37,8 @@ void cm_wait_for_lock(u32 mask)
 /* function to poll in the fsm busy bit */
 int cm_wait_for_fsm(void)
 {
-	return wait_for_bit(__func__, (const u32 *)&clock_manager_base->stat,
-			    CLKMGR_STAT_BUSY, false, 20000, false);
+	return wait_for_bit_le32((const u32 *)&clock_manager_base->stat,
+				 CLKMGR_STAT_BUSY, false, 20000, false);
 }
 
 int set_cpu_clk_info(void)
diff --git a/arch/arm/mach-socfpga/clock_manager_gen5.c b/arch/arm/mach-socfpga/clock_manager_gen5.c
index 31fd51097a..309ddde0d0 100644
--- a/arch/arm/mach-socfpga/clock_manager_gen5.c
+++ b/arch/arm/mach-socfpga/clock_manager_gen5.c
@@ -37,15 +37,15 @@ static int cm_write_with_phase(u32 value, u32 reg_address, u32 mask)
 	int ret;
 
 	/* poll until phase is zero */
-	ret = wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			   false, 20000, false);
+	ret = wait_for_bit_le32((const u32 *)reg_address, mask,
+				false, 20000, false);
 	if (ret)
 		return ret;
 
 	writel(value, reg_address);
 
-	return wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			    false, 20000, false);
+	return wait_for_bit_le32((const u32 *)reg_address, mask,
+				 false, 20000, false);
 }
 
 /*
diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c
index ae16897494..54f0ddb255 100644
--- a/arch/arm/mach-socfpga/reset_manager_arria10.c
+++ b/arch/arm/mach-socfpga/reset_manager_arria10.c
@@ -222,8 +222,8 @@ int socfpga_reset_deassert_bridges_handoff(void)
 	clrbits_le32(&reset_manager_base->brgmodrst, mask_rstmgr);
 
 	/* Poll until all idleack to 0, timeout at 1000ms */
-	return wait_for_bit(__func__, &sysmgr_regs->noc_idleack, mask_noc,
-			    false, 1000, false);
+	return wait_for_bit_le32(&sysmgr_regs->noc_idleack, mask_noc,
+				 false, 1000, false);
 }
 
 void socfpga_reset_assert_fpga_connected_peripherals(void)
@@ -343,26 +343,26 @@ int socfpga_bridges_reset(void)
 	writel(ALT_SYSMGR_NOC_TMO_EN_SET_MSK, &sysmgr_regs->noc_timeout);
 
 	/* Poll until all idleack to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idleack,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idleack,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
 	/* Poll until all idlestatus to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idlestatus,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idlestatus,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/arch/mips/mach-ath79/ar934x/clk.c b/arch/mips/mach-ath79/ar934x/clk.c
index 9b41d3de60..ba2243c9be 100644
--- a/arch/mips/mach-ath79/ar934x/clk.c
+++ b/arch/mips/mach-ath79/ar934x/clk.c
@@ -90,7 +90,7 @@ static void ar934x_srif_pll_cfg(void __iomem *pll_reg_base, const u32 srif_val)
 		setbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
 
-		wait_for_bit("clk", pll_reg_base + 0xc, BIT(3), 1, 10, 0);
+		wait_for_bit_le32(pll_reg_base + 0xc, BIT(3), 1, 10, 0);
 
 		clrbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
diff --git a/board/samtec/vining_2000/vining_2000.c b/board/samtec/vining_2000/vining_2000.c
index af1a3e75cb..cced08b8b8 100644
--- a/board/samtec/vining_2000/vining_2000.c
+++ b/board/samtec/vining_2000/vining_2000.c
@@ -378,7 +378,7 @@ static int read_adc(u32 *val)
 
 	/* start auto calibration */
 	setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
-	ret = wait_for_bit("ADC", b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
 	if (ret)
 		goto adc_exit;
 
@@ -386,7 +386,7 @@ static int read_adc(u32 *val)
 	writel(0, b + ADCx_HC0);
 
 	/* wait for conversion */
-	ret = wait_for_bit("ADC", b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
 	if (ret)
 		goto adc_exit;
 
diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
index f6eef314ec..177803943d 100644
--- a/drivers/clk/clk_pic32.c
+++ b/drivers/clk/clk_pic32.c
@@ -197,8 +197,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_ON | REFO_OE, reg + _CLR_OFFSET);
 
 	/* wait till previous src change is active */
-	wait_for_bit(__func__, reg, REFO_DIVSW_EN | REFO_ACTIVE,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(reg, REFO_DIVSW_EN | REFO_ACTIVE,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* parent_id */
 	v = readl(reg);
@@ -223,8 +223,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_DIVSW_EN, reg + _SET_OFFSET);
 
 	/* wait for divider switching to complete */
-	return wait_for_bit(__func__, reg, REFO_DIVSW_EN, false,
-			    CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(reg, REFO_DIVSW_EN, false,
+				 CONFIG_SYS_HZ, false);
 }
 
 static ulong pic32_get_refclk(struct pic32_clk_priv *priv, int periph)
@@ -311,8 +311,8 @@ static int pic32_mpll_init(struct pic32_clk_priv *priv)
 
 	/* Wait for ready */
 	mask = MPLL_RDY | MPLL_VREG_RDY;
-	return wait_for_bit(__func__, priv->syscfg_base + CFGMPLL, mask,
-			    true, get_tbclk(), false);
+	return wait_for_bit_le32(priv->syscfg_base + CFGMPLL, mask,
+				 true, get_tbclk(), false);
 }
 
 static void pic32_clk_init(struct udevice *dev)
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index b26bbcc59f..22828fd470 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -1046,8 +1046,8 @@ static int gen3_clk_endisable(struct clk *clk, bool enable)
 		if (ret)
 			return ret;
 		clrbits_le32(priv->base + SMSTPCR(reg), bitmask);
-		return wait_for_bit("MSTP", priv->base + MSTPSR(reg),
-				    bitmask, 0, 100, 0);
+		return wait_for_bit_le32(priv->base + MSTPSR(reg),
+					 bitmask, 0, 100, 0);
 	} else {
 		setbits_le32(priv->base + SMSTPCR(reg), bitmask);
 		return 0;
diff --git a/drivers/ddr/microchip/ddr2.c b/drivers/ddr/microchip/ddr2.c
index 6056418588..a52427c3d6 100644
--- a/drivers/ddr/microchip/ddr2.c
+++ b/drivers/ddr/microchip/ddr2.c
@@ -57,8 +57,8 @@ static int ddr2_phy_calib_start(void)
 	writel(SCL_START | SCL_EN, &ddr2_phy->scl_start);
 
 	/* Wait for SCL for data byte to pass */
-	return wait_for_bit(__func__, &ddr2_phy->scl_start, SCL_LUBPASS,
-			    true, CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(&ddr2_phy->scl_start, SCL_LUBPASS,
+				 true, CONFIG_SYS_HZ, false);
 }
 
 /* DDR2 Controller initialization */
@@ -256,8 +256,8 @@ void ddr2_ctrl_init(void)
 	writel(INIT_START, &ctrl->memcon);
 
 	/* wait for all host cmds to be transmitted */
-	wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ctrl->cmdissue, CMD_VALID, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* inform all cmds issued, ready for normal operation */
 	writel(INIT_START | INIT_DONE, &ctrl->memcon);
diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
index 5c1a68a009..d5763965dd 100644
--- a/drivers/fpga/socfpga_arria10.c
+++ b/drivers/fpga/socfpga_arria10.c
@@ -62,8 +62,7 @@ int is_fpgamgr_user_mode(void)
 
 static int wait_for_user_mode(void)
 {
-	return wait_for_bit(__func__,
-		&fpga_manager_base->imgcfg_stat,
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
 		ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK,
 		1, FPGA_TIMEOUT_MSEC, false);
 }
@@ -115,19 +114,17 @@ static int wait_for_nconfig_pin_and_nstatus_pin(void)
 	/* Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted,
 	 * timeout at 1000ms
 	 */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    mask,
-			    false, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		mask,
+		false, FPGA_TIMEOUT_MSEC, false);
 }
 
 static int wait_for_f2s_nstatus_pin(unsigned long value)
 {
 	/* Poll until f2s to specific value, timeout at 1000ms */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
-			    value, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
+		value, FPGA_TIMEOUT_MSEC, false);
 }
 
 /* set CD ratio */
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 9117ab6bf9..f0661bd96c 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -109,15 +109,15 @@ static int msm_sdc_probe(struct udevice *dev)
 
 
 	/* Wait for reset to be written to register */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_STATUS2,
-			 SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_STATUS2,
+			      SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
 		printf("msm_sdhci: reset request failed\n");
 		return -EIO;
 	}
 
 	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_POWER,
-			 SDCC_MCI_POWER_SW_RST, false, 2, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_POWER,
+			      SDCC_MCI_POWER_SW_RST, false, 2, false)) {
 		printf("msm_sdhci: stuck in reset\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c
index e1a8d3bc4b..8bbf2fa9a2 100644
--- a/drivers/mtd/pic32_flash.c
+++ b/drivers/mtd/pic32_flash.c
@@ -66,8 +66,8 @@ static inline void flash_initiate_operation(u32 nvmop)
 
 static int flash_wait_till_busy(const char *func, ulong timeout)
 {
-	int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw,
-			       NVM_WR, false, timeout, false);
+	int ret = wait_for_bit_le32(&nvm_regs_p->ctrl.raw,
+				    NVM_WR, false, timeout, false);
 
 	return ret ? ERR_TIMOUT : ERR_OK;
 }
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index 00e6806892..f28187058e 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -164,8 +164,8 @@ static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
 	writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
 	       regs + AG7XXX_ETH_MII_MGMT_CMD);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 	if (ret)
 		return ret;
 
@@ -185,8 +185,8 @@ static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
 	       regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
 	writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 
 	return ret;
 }
@@ -510,13 +510,13 @@ static void ag7xxx_eth_stop(struct udevice *dev)
 
 	/* Stop the TX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
+			  1000, 0);
 
 	/* Stop the RX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
+			  1000, 0);
 }
 
 /*
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 00076cffbe..232e8034df 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -361,8 +361,9 @@ static void eqos_flush_buffer(void *buf, size_t size)
 
 static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
 {
-	return wait_for_bit(__func__, &eqos->mac_regs->mdio_address,
-			    EQOS_MAC_MDIO_ADDRESS_GB, false, 1000000, true);
+	return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
+				 EQOS_MAC_MDIO_ADDRESS_GB, false,
+				 1000000, true);
 }
 
 static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
@@ -588,15 +589,15 @@ static int eqos_calibrate_pads_tegra186(struct udevice *dev)
 	setbits_le32(&eqos->tegra186_regs->auto_cal_config,
 		     EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE);
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't start");
 		goto failed;
 	}
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't finish");
 		goto failed;
@@ -862,8 +863,8 @@ static int eqos_start(struct udevice *dev)
 
 	eqos->reg_access_ok = true;
 
-	ret = wait_for_bit(__func__, &eqos->dma_regs->mode,
-			   EQOS_DMA_MODE_SWR, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->dma_regs->mode,
+				EQOS_DMA_MODE_SWR, false, 10, false);
 	if (ret) {
 		pr_err("EQOS_DMA_MODE_SWR stuck");
 		goto err_stop_resets;
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a6df950081..51a6c97550 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -548,8 +548,8 @@ static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		u32 data = ethoc_read(priv, MIIRX_DATA);
@@ -571,8 +571,8 @@ static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
 	ethoc_write(priv, MIITX_DATA, val);
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		/* reset MII command register */
diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
index 0b89911f04..7129372790 100644
--- a/drivers/net/pic32_eth.c
+++ b/drivers/net/pic32_eth.c
@@ -64,8 +64,8 @@ static int pic32_mii_init(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* turn controller ON to access PHY over MII */
 	writel(ETHCON_ON, &ectl_p->con1.set);
@@ -239,8 +239,8 @@ static void pic32_ctrl_reset(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 	/* decrement received buffcnt to zero. */
 	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
 		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
@@ -375,8 +375,8 @@ static void pic32_eth_stop(struct udevice *dev)
 	mdelay(10);
 
 	/* wait until everything is down */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     2 * CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  2 * CONFIG_SYS_HZ, false);
 
 	/* clear any existing interrupt event */
 	writel(0xffffffff, &ectl_p->irq.clr);
diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
index 578fc96905..6ae5c40fa3 100644
--- a/drivers/net/pic32_mdio.c
+++ b/drivers/net/pic32_mdio.c
@@ -22,8 +22,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -36,8 +36,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	udelay(12);
 
 	/* Wait for write to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	return 0;
 }
@@ -48,8 +48,8 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -62,9 +62,9 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	udelay(12);
 
 	/* Wait for read to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw,
-		     MIIMIND_NOTVALID | MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&mii_regs->mind.raw,
+			  MIIMIND_NOTVALID | MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* Clear the command register */
 	writel(0, &mii_regs->mcmd.raw);
@@ -82,22 +82,22 @@ static int pic32_mdio_reset(struct mii_dev *bus)
 	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
 		     false, CONFIG_SYS_HZ, true);
 
 	/* Clear reset bit */
 	writel(0, &mii_regs->mcfg);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
 	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 	return 0;
 }
 
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index dc743e113d..a39f9c5c86 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -222,8 +222,8 @@ static int ravb_reset(struct udevice *dev)
 	writel(CCC_OPC_CONFIG, eth->iobase + RAVB_REG_CCC);
 
 	/* Check the operating mode is changed to the config mode. */
-	return wait_for_bit(dev->name, (void *)eth->iobase + RAVB_REG_CSR,
-			    CSR_OPS_CONFIG, true, 100, true);
+	return wait_for_bit_le32((void *)eth->iobase + RAVB_REG_CSR,
+				 CSR_OPS_CONFIG, true, 100, true);
 }
 
 static void ravb_base_desc_init(struct ravb_priv *eth)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 9a2a578ff9..55fa1e49d5 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -366,8 +366,8 @@ static int axi_ethernet_init(struct axidma_priv *priv)
 	 * processor mode and hence bypass in this mode
 	 */
 	if (!priv->eth_hasnobuf) {
-		err = wait_for_bit(__func__, (const u32 *)&regs->is,
-				   XAE_INT_MGTRDY_MASK, true, 200, false);
+		err = wait_for_bit_le32((const u32 *)&regs->is,
+					XAE_INT_MGTRDY_MASK, true, 200, false);
 		if (err) {
 			printf("%s: Timeout\n", __func__);
 			return 1;
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 1dfd631e1a..2cc49bca92 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -192,8 +192,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	struct zynq_gem_regs *regs = priv->iobase;
 	int err;
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -205,8 +205,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	/* Write mgtcr and wait for completion */
 	writel(mgtcr, &regs->phymntnc);
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -514,8 +514,8 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
 	if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
 		printf("TX buffers exhausted in mid frame\n");
 
-	return wait_for_bit(__func__, &regs->txsr, ZYNQ_GEM_TSR_DONE,
-			    true, 20000, true);
+	return wait_for_bit_le32(&regs->txsr, ZYNQ_GEM_TSR_DONE,
+				 true, 20000, true);
 }
 
 /* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c
index 17786f976a..0fc5a28802 100644
--- a/drivers/reset/sti-reset.c
+++ b/drivers/reset/sti-reset.c
@@ -266,8 +266,8 @@ static int sti_reset_program_hw(struct reset_ctl *reset_ctl, int assert)
 		return 0;
 
 	reg = (void __iomem *)base + ch->ack_offset;
-	if (wait_for_bit(__func__, reg, BIT(ch->ack_bit), ctrl_val,
-			 1000, false)) {
+	if (wait_for_bit_le32(reg, BIT(ch->ack_bit), ctrl_val,
+			      1000, false)) {
 		pr_err("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n",
 		      reset_ctl, reset_ctl->dev, reset_ctl->id);
 
diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c
index b0e01aa0e5..0632d26211 100644
--- a/drivers/serial/serial_pic32.c
+++ b/drivers/serial/serial_pic32.c
@@ -51,8 +51,8 @@ static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
 	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
 
 	/* wait for TX FIFO to empty */
-	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
-		     true, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(base + U_STA, UART_TX_EMPTY,
+			  true, CONFIG_SYS_HZ, false);
 
 	/* send break */
 	writel(UART_TX_BRK, base + U_STASET);
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 228e714e09..8010ab434c 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -394,8 +394,8 @@ out:
 		 * Wait until the transfer is completely done before
 		 * we deactivate CS.
 		 */
-		wait_for_bit(__func__, &reg_base->sr,
-			     ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
+		wait_for_bit_le32(&reg_base->sr,
+				  ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
 
 		atmel_spi_cs_deactivate(dev);
 	}
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index e02f2217f4..dca3fdfdea 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -675,8 +675,8 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTRD,
-			   CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD,
+				CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect read completion error (%i)\n", ret);
 		goto failrd;
@@ -762,9 +762,9 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 				bb_txbuf + rounddown(write_bytes, 4),
 				write_bytes % 4);
 
-		ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL,
-				   CQSPI_REG_SDRAMLEVEL_WR_MASK <<
-				   CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
+		ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL,
+					CQSPI_REG_SDRAMLEVEL_WR_MASK <<
+					CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
 		if (ret) {
 			printf("Indirect write timed out (%i)\n", ret);
 			goto failwr;
@@ -775,8 +775,8 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTWR,
-			   CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR,
+				CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect write completion error (%i)\n", ret);
 		goto failwr;
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 0f3f7d97f0..eed52c15c8 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -1011,11 +1011,11 @@ static int fsl_qspi_probe(struct udevice *bus)
 	priv->num_chipselect = plat->num_chipselect;
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
@@ -1173,11 +1173,11 @@ static int fsl_qspi_claim_bus(struct udevice *dev)
 	priv = dev_get_priv(bus);
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
index ec4907391c..d1708a8d56 100644
--- a/drivers/spi/mvebu_a3700_spi.c
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -95,8 +95,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 	din_8 = din;
 
 	while (bytelen) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true,100, false);
 		if (ret)
 			return ret;
 
@@ -109,9 +110,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 		writel(pending_dout, &reg->dout);
 
 		if (din) {
-			ret = wait_for_bit(__func__, &reg->ctrl,
-					   MVEBU_SPI_A3700_XFER_RDY,
-					   true, 100, false);
+			ret = wait_for_bit_le32(&reg->ctrl,
+						MVEBU_SPI_A3700_XFER_RDY,
+						true, 100, false);
 			if (ret)
 				return ret;
 
@@ -160,8 +161,9 @@ static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 	/* Deactivate CS */
 	if (flags & SPI_XFER_END) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true, 100, false);
 		if (ret)
 			return ret;
 
@@ -231,8 +233,8 @@ static int mvebu_spi_probe(struct udevice *bus)
 	/* Flush read/write FIFO */
 	data = readl(&reg->cfg);
 	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
-	ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+				false, 1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 1293e18f75..540c016412 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -108,8 +108,8 @@ static void dwc_otg_flush_tx_fifo(struct dwc2_core_regs *regs, const int num)
 
 	writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET),
 	       &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -127,8 +127,8 @@ static void dwc_otg_flush_rx_fifo(struct dwc2_core_regs *regs)
 	int ret;
 
 	writel(DWC2_GRSTCTL_RXFFLSH, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -145,15 +145,15 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs)
 	int ret;
 
 	/* Wait for AHB master IDLE state. */
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
+				true, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
 	/* Core Soft Reset */
 	writel(DWC2_GRSTCTL_CSFTRST, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_CSFTRST,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_CSFTRST,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -267,8 +267,8 @@ static void dwc_otg_core_host_init(struct udevice *dev,
 		clrsetbits_le32(&regs->hc_regs[i].hcchar,
 				DWC2_HCCHAR_EPDIR,
 				DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS);
-		ret = wait_for_bit(__func__, &regs->hc_regs[i].hcchar,
-				   DWC2_HCCHAR_CHEN, false, 1000, false);
+		ret = wait_for_bit_le32(&regs->hc_regs[i].hcchar,
+					DWC2_HCCHAR_CHEN, false, 1000, false);
 		if (ret)
 			printf("%s: Timeout!\n", __func__);
 	}
@@ -783,8 +783,8 @@ int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle)
 	int ret;
 	uint32_t hcint, hctsiz;
 
-	ret = wait_for_bit(__func__, &hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
-			   1000, false);
+	ret = wait_for_bit_le32(&hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
+				1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 2c0c63322c..f5320ca298 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -133,8 +133,7 @@ static int ehci_usb_remove(struct udevice *dev)
 	setbits_le32(&ehci->usbcmd, CMD_RESET);
 
 	/* Wait for reset */
-	if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30,
-			 false)) {
+	if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) {
 		printf("Stuck on USB reset.\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index fe2627ea93..2c8fc3c4b1 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -142,13 +142,12 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci)
 
 	/* Stop then Reset */
 	clrbits_le32(usb_cmd, UCMD_RUN_STOP);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RUN_STOP, false, 10000,
-			   false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false);
 	if (ret)
 		return ret;
 
 	setbits_le32(usb_cmd, UCMD_RESET);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RESET, false, 10000, false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ohci-lpc32xx.c b/drivers/usb/host/ohci-lpc32xx.c
index 2f2b4b90de..44a49807a4 100644
--- a/drivers/usb/host/ohci-lpc32xx.c
+++ b/drivers/usb/host/ohci-lpc32xx.c
@@ -143,8 +143,8 @@ static int usbpll_setup(void)
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_POSTDIV_2POW(0x01));
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_PWRUP);
 
-	ret = wait_for_bit(__func__, &clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
-			   true, CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
+				true, CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -178,8 +178,8 @@ int usb_cpu_init(void)
 
 	/* enable I2C clock */
 	writel(OTG_CLK_I2C_EN, &otg->otg_clk_ctrl);
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -199,8 +199,8 @@ int usb_cpu_init(void)
 			 OTG_CLK_I2C_EN | OTG_CLK_HOST_EN;
 	writel(mask, &otg->otg_clk_ctrl);
 
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, mask, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, mask, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index d47c99644d..71202d7b03 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -55,18 +55,18 @@ static int xhci_rcar_download_fw(struct rcar_xhci *ctx, const u32 *fw_data,
 		setbits_le32(regs + RCAR_USB3_DL_CTRL,
 			     RCAR_USB3_DL_CTRL_FW_SET_DATA0);
 
-		ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-				   RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
-				   10, false);
+		ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+					RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
+					10, false);
 		if (ret)
 			break;
 	}
 
 	clrbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
 
-	ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-			   RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
-			   10, false);
+	ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+				RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
+				10, false);
 
 	return ret;
 }
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index f77da2ec97..c0dd689e7c 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -70,26 +70,26 @@ void lcd_ctrl_init(void *lcdbase)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -215,26 +215,26 @@ void lcd_ctrl_init(void *lcdbase)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -299,26 +299,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -451,26 +451,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 }
-- 
2.11.0

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

* [U-Boot] [PATCH v7 03/13] wait_bit: remove old wait_for_bit function
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 02/13] wait_bit: use wait_for_bit_le32 instead " Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-11  1:51     ` Daniel Schwierzeck
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 04/13] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (9 subsequent siblings)
  12 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

Since wait_for_bit callers have been updated to use wait_for_bit_le32,
wait_for_bit is no longer needed.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v7: Introduce changes suggested by Jagan Teki:
 - Remove wait_for_bit and update callers to wait_for_bit_le32.

 include/wait_bit.h | 54 ------------------------------------------------------
 1 file changed, 54 deletions(-)

diff --git a/include/wait_bit.h b/include/wait_bit.h
index bde6d2cfc3..9f00e54e50 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -16,60 +16,6 @@
 #include <asm/io.h>
 
 /**
- * wait_for_bit()	waits for bit set/cleared in register
- *
- * Function polls register waiting for specific bit(s) change
- * (either 0->1 or 1->0). It can fail under two conditions:
- * - Timeout
- * - User interaction (CTRL-C)
- * Function succeeds only if all bits of masked register are set/cleared
- * (depending on set option).
- *
- * @param prefix	Prefix added to timeout messagge (message visible only
- *			with debug enabled)
- * @param reg		Register that will be read (using readl())
- * @param mask		Bit(s) of register that must be active
- * @param set		Selects wait condition (bit set or clear)
- * @param timeout_ms	Timeout (in miliseconds)
- * @param breakable	Enables CTRL-C interruption
- * @return		0 on success, -ETIMEDOUT or -EINTR on failure
- */
-static inline int wait_for_bit(const char *prefix, const u32 *reg,
-			       const u32 mask, const bool set,
-			       const unsigned int timeout_ms,
-			       const bool breakable)
-{
-	u32 val;
-	unsigned long start = get_timer(0);
-
-	while (1) {
-		val = readl(reg);
-
-		if (!set)
-			val = ~val;
-
-		if ((val & mask) == mask)
-			return 0;
-
-		if (get_timer(start) > timeout_ms)
-			break;
-
-		if (breakable && ctrlc()) {
-			puts("Abort\n");
-			return -EINTR;
-		}
-
-		udelay(1);
-		WATCHDOG_RESET();
-	}
-
-	debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", prefix, reg, mask,
-	      set);
-
-	return -ETIMEDOUT;
-}
-
-/**
  * wait_for_bit_x()	waits for bit set/cleared in register
  *
  * Function polls register waiting for specific bit(s) change
-- 
2.11.0

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

* [U-Boot] [PATCH v7 04/13] drivers: spi: allow limiting reads
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 03/13] wait_bit: remove old wait_for_bit function Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 05/13] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 51e28bf07b..e40e1c01de 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -516,6 +516,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 08c7480fda..4787454e59 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 
-- 
2.11.0

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

* [U-Boot] [PATCH v7 05/13] drivers: spi: consider command bytes when sending transfers
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 04/13] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 06/13] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e40e1c01de..294d9f9d79 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -405,7 +405,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index 4787454e59..5a7df1c706 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.11.0

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

* [U-Boot] [PATCH v7 06/13] dm: spi: add BCM63xx SPI driver
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 05/13] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 07/13] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Use cmd instead of val to avoid confusions.
 - Switch to wait_for_bit instead of infinite loop.
 v5: Introduce changes suggested by Jagan Teki:
  - Use long structure instead of a custom bmips_spi_hw structure.
  - Define constants for each SPI core.
 v4: Introduce changes suggested by Jagan Teki:
  - Add data for each HW controller instead of having two separate configs.
  - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |   8 +
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 442 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 494639fb01..ebc71c2e42 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,14 @@ config ATMEL_SPI
 	  many AT91 (ARM) chips. This driver can be used to access
 	  the SPI Flash, such as AT25DF321.
 
+config BCM63XX_SPI
+	bool "BCM6348 SPI driver"
+	depends on ARCH_BMIPS
+	help
+	  Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding these Broadcom
+	  SPI cores.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e3184db67f..5770b3f7cc 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,6 +18,7 @@ endif
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000000..f0df6871d8
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* BCM6348 SPI core */
+#define SPI_6348_CLK			0x06
+#define SPI_6348_CMD			0x00
+#define SPI_6348_CTL			0x40
+#define SPI_6348_CTL_SHIFT		6
+#define SPI_6348_FILL			0x07
+#define SPI_6348_IR_MASK		0x04
+#define SPI_6348_IR_STAT		0x02
+#define SPI_6348_RX			0x80
+#define SPI_6348_RX_SIZE		0x3f
+#define SPI_6348_TX			0x41
+#define SPI_6348_TX_SIZE		0x3f
+
+/* BCM6358 SPI core */
+#define SPI_6358_CLK			0x706
+#define SPI_6358_CMD			0x700
+#define SPI_6358_CTL			0x000
+#define SPI_6358_CTL_SHIFT		14
+#define SPI_6358_FILL			0x707
+#define SPI_6358_IR_MASK		0x702
+#define SPI_6358_IR_STAT		0x704
+#define SPI_6358_RX			0x400
+#define SPI_6358_RX_SIZE		0x220
+#define SPI_6358_TX			0x002
+#define SPI_6358_TX_SIZE		0x21e
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Control register */
+#define SPI_CTL_TYPE_FD_RW	0
+#define SPI_CTL_TYPE_HD_W	1
+#define SPI_CTL_TYPE_HD_R	2
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+enum bcm63xx_regs_spi {
+	SPI_CLK,
+	SPI_CMD,
+	SPI_CTL,
+	SPI_CTL_SHIFT,
+	SPI_FILL,
+	SPI_IR_MASK,
+	SPI_IR_STAT,
+	SPI_RX,
+	SPI_RX_SIZE,
+	SPI_TX,
+	SPI_TX_SIZE,
+};
+
+struct bcm63xx_spi_priv {
+	const unsigned long *regs;
+	void __iomem *base;
+	size_t tx_bytes;
+	uint8_t num_cs;
+};
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		printf("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->base + regs[SPI_CLK],
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			printf("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > regs[SPI_RX_SIZE]) {
+			printf("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
+			printf("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val, cmd;
+		int ret;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val = priv->tx_bytes;
+			val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_FD_RW <<
+					regs[SPI_CTL_SHIFT]);
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_HD_R <<
+					regs[SPI_CTL_SHIFT]);
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					printf("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+
+		if (regs[SPI_CTL_SHIFT] >= 8)
+			writew_be(val, priv->base + regs[SPI_CTL]);
+		else
+			writeb_be(val, priv->base + regs[SPI_CTL]);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
+
+		/* issue the transfer */
+		cmd = SPI_CMD_OP_START;
+		cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			cmd |= SPI_CMD_3WIRE_MASK;
+		writew_be(cmd, priv->base + regs[SPI_CMD]);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
+
+		ret = wait_for_bit_8(priv->base + regs[SPI_IR_STAT],
+				     SPI_IR_DONE_MASK, true, 1000, false);
+		if (ret) {
+			printf("interrupt timeout\n");
+			return ret;
+		}
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->base + regs[SPI_RX],
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const unsigned long bcm6348_spi_regs[] = {
+	[SPI_CLK] = SPI_6348_CLK,
+	[SPI_CMD] = SPI_6348_CMD,
+	[SPI_CTL] = SPI_6348_CTL,
+	[SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT,
+	[SPI_FILL] = SPI_6348_FILL,
+	[SPI_IR_MASK] = SPI_6348_IR_MASK,
+	[SPI_IR_STAT] = SPI_6348_IR_STAT,
+	[SPI_RX] = SPI_6348_RX,
+	[SPI_RX_SIZE] = SPI_6348_RX_SIZE,
+	[SPI_TX] = SPI_6348_TX,
+	[SPI_TX_SIZE] = SPI_6348_TX_SIZE,
+};
+
+static const unsigned long bcm6358_spi_regs[] = {
+	[SPI_CLK] = SPI_6358_CLK,
+	[SPI_CMD] = SPI_6358_CMD,
+	[SPI_CTL] = SPI_6358_CTL,
+	[SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT,
+	[SPI_FILL] = SPI_6358_FILL,
+	[SPI_IR_MASK] = SPI_6358_IR_MASK,
+	[SPI_IR_STAT] = SPI_6358_IR_STAT,
+	[SPI_RX] = SPI_6358_RX,
+	[SPI_RX_SIZE] = SPI_6358_RX_SIZE,
+	[SPI_TX] = SPI_6358_TX,
+	[SPI_TX_SIZE] = SPI_6358_TX_SIZE,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-spi",
+		.data = (ulong)&bcm6348_spi_regs,
+	}, {
+		.compatible = "brcm,bcm6358-spi",
+		.data = (ulong)&bcm6358_spi_regs,
+	}, { /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		printf("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = regs[SPI_RX_SIZE];
+	slave->max_write_size = regs[SPI_TX_SIZE];
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	const unsigned long *regs =
+		(const unsigned long *)dev_get_driver_data(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = regs;
+	priv->base = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_free(&clk);
+	if (ret < 0)
+		return ret;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_free(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	/* initialize hardware */
+	writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+
+	/* set fill register */
+	writeb_be(0xff, priv->base + regs[SPI_FILL]);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v7 07/13] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 06/13] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 08/13] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a4372b..0cab44cb8d 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v7 08/13] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 07/13] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 09/13] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643b5a..540b9fea5b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v7 09/13] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 08/13] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 10/13] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf80e0..1662783279 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v7 10/13] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 09/13] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 11/13] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb048..f83a6ea8df 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v7 11/13] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (9 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 10/13] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 12/13] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 13/13] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96bef8..6e3d9c3820 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.11.0

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

* [U-Boot] [PATCH v7 12/13] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (10 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 11/13] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 13/13] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5551..dd0e5b8b7c 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index cfc56cba37..5c091353e5 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -39,3 +39,11 @@ CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
-- 
2.11.0

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

* [U-Boot] [PATCH v7 13/13] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (11 preceding siblings ...)
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 12/13] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2018-01-10 20:26   ` Álvaro Fernández Rojas
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-10 20:26 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7616..5f85c7346f 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index 7665c78d3f..369c919ac7 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -41,3 +41,11 @@ CONFIG_RESET_BCM6345=y
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
 CONFIG_WDT_BCM6345=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
-- 
2.11.0

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

* [U-Boot] [PATCH v7 02/13] wait_bit: use wait_for_bit_le32 instead of wait_for_bit
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 02/13] wait_bit: use wait_for_bit_le32 instead " Álvaro Fernández Rojas
@ 2018-01-11  1:50     ` Daniel Schwierzeck
  2018-01-11  7:14       ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Daniel Schwierzeck @ 2018-01-11  1:50 UTC (permalink / raw)
  To: u-boot



On 10.01.2018 21:26, Álvaro Fernández Rojas wrote:
> wait_for_bit callers use the 32 bit LE version
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v7: Introduce changes suggested by Jagan Teki:
>  - Remove wait_for_bit and update callers to wait_for_bit_le32.
> 
>  arch/arm/mach-imx/mx6/ddr.c                   | 22 ++++-----
>  arch/arm/mach-socfpga/clock_manager.c         |  4 +-
>  arch/arm/mach-socfpga/clock_manager_gen5.c    |  8 ++--
>  arch/arm/mach-socfpga/reset_manager_arria10.c | 36 +++++++--------
>  arch/mips/mach-ath79/ar934x/clk.c             |  2 +-
>  board/samtec/vining_2000/vining_2000.c        |  4 +-
>  drivers/clk/clk_pic32.c                       | 12 ++---
>  drivers/clk/renesas/clk-rcar-gen3.c           |  4 +-
>  drivers/ddr/microchip/ddr2.c                  |  8 ++--
>  drivers/fpga/socfpga_arria10.c                | 17 +++----
>  drivers/mmc/msm_sdhci.c                       |  8 ++--
>  drivers/mtd/pic32_flash.c                     |  4 +-
>  drivers/net/ag7xxx.c                          | 16 +++----
>  drivers/net/dwc_eth_qos.c                     | 17 +++----
>  drivers/net/ethoc.c                           |  8 ++--
>  drivers/net/pic32_eth.c                       | 12 ++---
>  drivers/net/pic32_mdio.c                      | 28 ++++++------
>  drivers/net/ravb.c                            |  4 +-
>  drivers/net/xilinx_axi_emac.c                 |  4 +-
>  drivers/net/zynq_gem.c                        | 12 ++---
>  drivers/reset/sti-reset.c                     |  4 +-
>  drivers/serial/serial_pic32.c                 |  4 +-
>  drivers/spi/atmel_spi.c                       |  4 +-
>  drivers/spi/cadence_qspi_apb.c                | 14 +++---
>  drivers/spi/fsl_qspi.c                        | 20 ++++-----
>  drivers/spi/mvebu_a3700_spi.c                 | 20 +++++----
>  drivers/usb/host/dwc2.c                       | 24 +++++-----
>  drivers/usb/host/ehci-msm.c                   |  3 +-
>  drivers/usb/host/ehci-mx6.c                   |  5 +--
>  drivers/usb/host/ohci-lpc32xx.c               | 12 ++---
>  drivers/usb/host/xhci-rcar.c                  | 12 ++---
>  drivers/video/atmel_hlcdfb.c                  | 64 +++++++++++++--------------
>  32 files changed, 207 insertions(+), 209 deletions(-)
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

nits below

>  
> diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
> index dc743e113d..a39f9c5c86 100644
> --- a/drivers/net/ravb.c
> +++ b/drivers/net/ravb.c
> @@ -222,8 +222,8 @@ static int ravb_reset(struct udevice *dev)
>  	writel(CCC_OPC_CONFIG, eth->iobase + RAVB_REG_CCC);
>  
>  	/* Check the operating mode is changed to the config mode. */
> -	return wait_for_bit(dev->name, (void *)eth->iobase + RAVB_REG_CSR,
> -			    CSR_OPS_CONFIG, true, 100, true);
> +	return wait_for_bit_le32((void *)eth->iobase + RAVB_REG_CSR,
> +				 CSR_OPS_CONFIG, true, 100, true);

the cast to (void *) is not necessary anymore

>  }
>  
>  static void ravb_base_desc_init(struct ravb_priv *eth)
> diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
> index 9a2a578ff9..55fa1e49d5 100644
> --- a/drivers/net/xilinx_axi_emac.c
> +++ b/drivers/net/xilinx_axi_emac.c
> @@ -366,8 +366,8 @@ static int axi_ethernet_init(struct axidma_priv *priv)
>  	 * processor mode and hence bypass in this mode
>  	 */
>  	if (!priv->eth_hasnobuf) {
> -		err = wait_for_bit(__func__, (const u32 *)&regs->is,
> -				   XAE_INT_MGTRDY_MASK, true, 200, false);
> +		err = wait_for_bit_le32((const u32 *)&regs->is,
> +					XAE_INT_MGTRDY_MASK, true, 200, false);

the cast to (const u32 *) is not necessary anymore

>  		if (err) {
>  			printf("%s: Timeout\n", __func__);
>  			return 1;


-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180111/1220465e/attachment.sig>

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

* [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
@ 2018-01-11  1:50     ` Daniel Schwierzeck
  2018-01-11  7:13       ` Jagan Teki
  0 siblings, 1 reply; 187+ messages in thread
From: Daniel Schwierzeck @ 2018-01-11  1:50 UTC (permalink / raw)
  To: u-boot



On 10.01.2018 21:26, Álvaro Fernández Rojas wrote:
> Add 8/16/32 bits and BE/LE versions of wait_for_bit.
> This is needed for reading registers that are not aligned to 32 bits, and for
> Big Endian platforms.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v7: Introduce changes suggested by Daniel Schwierzeck:
>  - Use const void* reg for compatibility with 64 bit systems.
>  - Remove prefix and use __func__ instead.
>  v6: Introduce changes suggested by Jagan Teki:
>  - Switch to wait_for_bit instead of infinite loop.
> 
>  include/wait_bit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180111/6a1d6f52/attachment.sig>

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

* [U-Boot] [PATCH v7 03/13] wait_bit: remove old wait_for_bit function
  2018-01-10 20:26   ` [U-Boot] [PATCH v7 03/13] wait_bit: remove old wait_for_bit function Álvaro Fernández Rojas
@ 2018-01-11  1:51     ` Daniel Schwierzeck
  0 siblings, 0 replies; 187+ messages in thread
From: Daniel Schwierzeck @ 2018-01-11  1:51 UTC (permalink / raw)
  To: u-boot



On 10.01.2018 21:26, Álvaro Fernández Rojas wrote:
> Since wait_for_bit callers have been updated to use wait_for_bit_le32,
> wait_for_bit is no longer needed.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v7: Introduce changes suggested by Jagan Teki:
>  - Remove wait_for_bit and update callers to wait_for_bit_le32.
> 
>  include/wait_bit.h | 54 ------------------------------------------------------
>  1 file changed, 54 deletions(-)
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180111/b6bb3f6f/attachment.sig>

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

* [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-11  1:50     ` Daniel Schwierzeck
@ 2018-01-11  7:13       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-11  7:13 UTC (permalink / raw)
  To: u-boot

On Thu, Jan 11, 2018 at 7:20 AM, Daniel Schwierzeck
<daniel.schwierzeck@gmail.com> wrote:
>
>
> On 10.01.2018 21:26, Álvaro Fernández Rojas wrote:
>> Add 8/16/32 bits and BE/LE versions of wait_for_bit.
>> This is needed for reading registers that are not aligned to 32 bits, and for
>> Big Endian platforms.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> ---
>>  v7: Introduce changes suggested by Daniel Schwierzeck:
>>  - Use const void* reg for compatibility with 64 bit systems.
>>  - Remove prefix and use __func__ instead.
>>  v6: Introduce changes suggested by Jagan Teki:
>>  - Switch to wait_for_bit instead of infinite loop.
>>
>>  include/wait_bit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 61 insertions(+)
>>
>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v7 02/13] wait_bit: use wait_for_bit_le32 instead of wait_for_bit
  2018-01-11  1:50     ` Daniel Schwierzeck
@ 2018-01-11  7:14       ` Jagan Teki
  0 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-11  7:14 UTC (permalink / raw)
  To: u-boot

On Thu, Jan 11, 2018 at 7:20 AM, Daniel Schwierzeck
<daniel.schwierzeck@gmail.com> wrote:
>
>
> On 10.01.2018 21:26, Álvaro Fernández Rojas wrote:
>> wait_for_bit callers use the 32 bit LE version
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> ---
>>  v7: Introduce changes suggested by Jagan Teki:
>>  - Remove wait_for_bit and update callers to wait_for_bit_le32.
>>
>>  arch/arm/mach-imx/mx6/ddr.c                   | 22 ++++-----
>>  arch/arm/mach-socfpga/clock_manager.c         |  4 +-
>>  arch/arm/mach-socfpga/clock_manager_gen5.c    |  8 ++--
>>  arch/arm/mach-socfpga/reset_manager_arria10.c | 36 +++++++--------
>>  arch/mips/mach-ath79/ar934x/clk.c             |  2 +-
>>  board/samtec/vining_2000/vining_2000.c        |  4 +-
>>  drivers/clk/clk_pic32.c                       | 12 ++---
>>  drivers/clk/renesas/clk-rcar-gen3.c           |  4 +-
>>  drivers/ddr/microchip/ddr2.c                  |  8 ++--
>>  drivers/fpga/socfpga_arria10.c                | 17 +++----
>>  drivers/mmc/msm_sdhci.c                       |  8 ++--
>>  drivers/mtd/pic32_flash.c                     |  4 +-
>>  drivers/net/ag7xxx.c                          | 16 +++----
>>  drivers/net/dwc_eth_qos.c                     | 17 +++----
>>  drivers/net/ethoc.c                           |  8 ++--
>>  drivers/net/pic32_eth.c                       | 12 ++---
>>  drivers/net/pic32_mdio.c                      | 28 ++++++------
>>  drivers/net/ravb.c                            |  4 +-
>>  drivers/net/xilinx_axi_emac.c                 |  4 +-
>>  drivers/net/zynq_gem.c                        | 12 ++---
>>  drivers/reset/sti-reset.c                     |  4 +-
>>  drivers/serial/serial_pic32.c                 |  4 +-
>>  drivers/spi/atmel_spi.c                       |  4 +-
>>  drivers/spi/cadence_qspi_apb.c                | 14 +++---
>>  drivers/spi/fsl_qspi.c                        | 20 ++++-----
>>  drivers/spi/mvebu_a3700_spi.c                 | 20 +++++----
>>  drivers/usb/host/dwc2.c                       | 24 +++++-----
>>  drivers/usb/host/ehci-msm.c                   |  3 +-
>>  drivers/usb/host/ehci-mx6.c                   |  5 +--
>>  drivers/usb/host/ohci-lpc32xx.c               | 12 ++---
>>  drivers/usb/host/xhci-rcar.c                  | 12 ++---
>>  drivers/video/atmel_hlcdfb.c                  | 64 +++++++++++++--------------
>>  32 files changed, 207 insertions(+), 209 deletions(-)
>>
>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

squash this with 03/13

Reviewed-by: Jagan Teki <jagan@openedev.com>

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

* [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (14 preceding siblings ...)
  2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2018-01-11 17:11 ` Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
                     ` (11 more replies)
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
  17 siblings, 12 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
- Squash wait_bit commits.
- Remove register param castings.
v7: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
- Use const void* reg for compatibility with 64 bit systems.
- Remove prefix and use __func__ instead.
- Remove wait_for_bit and update callers to wait_for_bit_le32.
v6: Introduce changes suggested by Jagan Teki:
- Use cmd instead of val to avoid confusions.
- Switch to wait_for_bit instead of infinite loop.
v5: Introduce changes suggested by Jagan Teki:
- Use long structs for registers
v4: Introduce changes suggested by Jagan Teki:
- Add data for each HW controller instead of having two separate configs.
v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (12):
  wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  wait_bit: use wait_for_bit_le32 and remove wait_for_bit
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/arm/mach-imx/mx6/ddr.c                   |  22 +-
 arch/arm/mach-socfpga/clock_manager.c         |   4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |   6 +-
 arch/arm/mach-socfpga/reset_manager_arria10.c |  36 +--
 arch/mips/dts/brcm,bcm3380.dtsi               |  17 +
 arch/mips/dts/brcm,bcm63268.dtsi              |  17 +
 arch/mips/dts/brcm,bcm6338.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6348.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6358.dtsi               |  17 +
 arch/mips/dts/netgear,cg3100d.dts             |  12 +
 arch/mips/dts/sagem,f at st1704.dts              |  12 +
 arch/mips/mach-ath79/ar934x/clk.c             |   2 +-
 board/samtec/vining_2000/vining_2000.c        |   4 +-
 configs/netgear_cg3100d_ram_defconfig         |   8 +
 configs/sagem_f at st1704_ram_defconfig          |   8 +
 drivers/clk/clk_pic32.c                       |  12 +-
 drivers/clk/renesas/clk-rcar-gen3.c           |   4 +-
 drivers/ddr/microchip/ddr2.c                  |   8 +-
 drivers/fpga/socfpga_arria10.c                |  17 +-
 drivers/mmc/msm_sdhci.c                       |   8 +-
 drivers/mtd/pic32_flash.c                     |   4 +-
 drivers/mtd/spi/spi_flash.c                   |   5 +-
 drivers/net/ag7xxx.c                          |  16 +-
 drivers/net/dwc_eth_qos.c                     |  17 +-
 drivers/net/ethoc.c                           |   8 +-
 drivers/net/pic32_eth.c                       |  12 +-
 drivers/net/pic32_mdio.c                      |  28 +-
 drivers/net/ravb.c                            |   4 +-
 drivers/net/xilinx_axi_emac.c                 |   4 +-
 drivers/net/zynq_gem.c                        |  12 +-
 drivers/reset/sti-reset.c                     |   4 +-
 drivers/serial/serial_pic32.c                 |   4 +-
 drivers/spi/Kconfig                           |   8 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/atmel_spi.c                       |   4 +-
 drivers/spi/bcm63xx_spi.c                     | 433 ++++++++++++++++++++++++++
 drivers/spi/cadence_qspi_apb.c                |  14 +-
 drivers/spi/fsl_qspi.c                        |  20 +-
 drivers/spi/mvebu_a3700_spi.c                 |  20 +-
 drivers/usb/host/dwc2.c                       |  24 +-
 drivers/usb/host/ehci-msm.c                   |   3 +-
 drivers/usb/host/ehci-mx6.c                   |   5 +-
 drivers/usb/host/ohci-lpc32xx.c               |  12 +-
 drivers/usb/host/xhci-rcar.c                  |  12 +-
 drivers/video/atmel_hlcdfb.c                  |  64 ++--
 include/spi.h                                 |   5 +-
 include/wait_bit.h                            |  81 ++---
 47 files changed, 824 insertions(+), 248 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.11.0

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

* [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-11 17:17     ` Jagan Teki
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
                     ` (10 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

Add 8/16/32 bits and BE/LE versions of wait_for_bit.
This is needed for reading registers that are not aligned to 32 bits, and for
Big Endian platforms.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes.
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Use const void* reg for compatibility with 64 bit systems.
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Switch to wait_for_bit instead of infinite loop.

 include/wait_bit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/include/wait_bit.h b/include/wait_bit.h
index 06ad43a122..bde6d2cfc3 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -69,5 +69,66 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
 	return -ETIMEDOUT;
 }
 
+/**
+ * wait_for_bit_x()	waits for bit set/cleared in register
+ *
+ * Function polls register waiting for specific bit(s) change
+ * (either 0->1 or 1->0). It can fail under two conditions:
+ * - Timeout
+ * - User interaction (CTRL-C)
+ * Function succeeds only if all bits of masked register are set/cleared
+ * (depending on set option).
+ *
+ * @param reg		Register that will be read (using read_x())
+ * @param mask		Bit(s) of register that must be active
+ * @param set		Selects wait condition (bit set or clear)
+ * @param timeout_ms	Timeout (in milliseconds)
+ * @param breakable	Enables CTRL-C interruption
+ * @return		0 on success, -ETIMEDOUT or -EINTR on failure
+ */
+
+#define BUILD_WAIT_FOR_BIT(sfx, type, read)				\
+									\
+static inline int wait_for_bit_##sfx(const void *reg,			\
+				     const type mask,			\
+				     const bool set,			\
+				     const unsigned int timeout_ms,	\
+				     const bool breakable)		\
+{									\
+	type val;							\
+	unsigned long start = get_timer(0);				\
+									\
+	while (1) {							\
+		val = read(reg);					\
+									\
+		if (!set)						\
+			val = ~val;					\
+									\
+		if ((val & mask) == mask)				\
+			return 0;					\
+									\
+		if (get_timer(start) > timeout_ms)			\
+			break;						\
+									\
+		if (breakable && ctrlc()) {				\
+			puts("Abort\n");				\
+			return -EINTR;					\
+		}							\
+									\
+		udelay(1);						\
+		WATCHDOG_RESET();					\
+	}								\
+									\
+	debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__,	\
+	      reg, mask, set);						\
+									\
+	return -ETIMEDOUT;						\
+}
+
+BUILD_WAIT_FOR_BIT(8, u8, readb)
+BUILD_WAIT_FOR_BIT(le16, u16, readw)
+BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
+BUILD_WAIT_FOR_BIT(le32, u32, readl)
+BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
 
 #endif
-- 
2.11.0

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

* [U-Boot] [PATCH v8 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (9 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

wait_for_bit callers use the 32 bit LE version

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
 - Squash wait_bit commits.
 - Remove register param castings.
 v7: Introduce changes suggested by Jagan Teki:
 - Remove wait_for_bit and update callers to wait_for_bit_le32.

 arch/arm/mach-imx/mx6/ddr.c                   | 22 ++++-----
 arch/arm/mach-socfpga/clock_manager.c         |  4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |  6 +--
 arch/arm/mach-socfpga/reset_manager_arria10.c | 36 +++++++--------
 arch/mips/mach-ath79/ar934x/clk.c             |  2 +-
 board/samtec/vining_2000/vining_2000.c        |  4 +-
 drivers/clk/clk_pic32.c                       | 12 ++---
 drivers/clk/renesas/clk-rcar-gen3.c           |  4 +-
 drivers/ddr/microchip/ddr2.c                  |  8 ++--
 drivers/fpga/socfpga_arria10.c                | 17 +++----
 drivers/mmc/msm_sdhci.c                       |  8 ++--
 drivers/mtd/pic32_flash.c                     |  4 +-
 drivers/net/ag7xxx.c                          | 16 +++----
 drivers/net/dwc_eth_qos.c                     | 17 +++----
 drivers/net/ethoc.c                           |  8 ++--
 drivers/net/pic32_eth.c                       | 12 ++---
 drivers/net/pic32_mdio.c                      | 28 ++++++------
 drivers/net/ravb.c                            |  4 +-
 drivers/net/xilinx_axi_emac.c                 |  4 +-
 drivers/net/zynq_gem.c                        | 12 ++---
 drivers/reset/sti-reset.c                     |  4 +-
 drivers/serial/serial_pic32.c                 |  4 +-
 drivers/spi/atmel_spi.c                       |  4 +-
 drivers/spi/cadence_qspi_apb.c                | 14 +++---
 drivers/spi/fsl_qspi.c                        | 20 ++++-----
 drivers/spi/mvebu_a3700_spi.c                 | 20 +++++----
 drivers/usb/host/dwc2.c                       | 24 +++++-----
 drivers/usb/host/ehci-msm.c                   |  3 +-
 drivers/usb/host/ehci-mx6.c                   |  5 +--
 drivers/usb/host/ohci-lpc32xx.c               | 12 ++---
 drivers/usb/host/xhci-rcar.c                  | 12 ++---
 drivers/video/atmel_hlcdfb.c                  | 64 +++++++++++++--------------
 include/wait_bit.h                            | 54 ----------------------
 33 files changed, 205 insertions(+), 263 deletions(-)

diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index 52a9a25904..f07f938c65 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -21,10 +21,10 @@ static void reset_read_data_fifos(void)
 
 	/* Reset data FIFOs twice. */
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 }
 
 static void precharge_all(const bool cs0_enable, const bool cs1_enable)
@@ -39,12 +39,12 @@ static void precharge_all(const bool cs0_enable, const bool cs1_enable)
 	 */
 	if (cs0_enable) { /* CS0 */
 		writel(0x04008050, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 
 	if (cs1_enable) { /* CS1 */
 		writel(0x04008058, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 }
 
@@ -146,7 +146,7 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * 7. Upon completion of this process the MMDC de-asserts
 	 * the MPWLGCR[HW_WL_EN]
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
 
 	/*
 	 * 8. check for any errors: check both PHYs for x64 configuration,
@@ -278,7 +278,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 		writel(0x00008028, &mmdc0->mdscr);
 
 	/* poll to make sure the con_ack bit was asserted */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 
 	/*
 	 * Check MDMISC register CALIB_PER_CS to see which CS calibration
@@ -312,7 +312,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * this bit until it clears to indicate completion of the write access.
 	 */
 	setbits_le32(&mmdc0->mpswdar0, 1);
-	wait_for_bit("MMDC", &mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
 
 	/* Set the RD_DL_ABS# bits to their default values
 	 * (will be calibrated later in the read delay-line calibration).
@@ -359,7 +359,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	setbits_le32(&mmdc0->mpdgctrl0, 5 << 28);
 
 	/* Poll for completion.  MPDGCTRL0[HW_DG_EN] should be 0 */
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
 
 	/*
 	 * Check to see if any errors were encountered during calibration
@@ -423,7 +423,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * setting MPRDDLHWCTL[HW_RD_DL_EN] = 0.   Also, ensure that
 	 * no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
 
 	/* check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mprddlhwctl) & 0x0000000f)
@@ -477,7 +477,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * by setting MPWRDLHWCTL[HW_WR_DL_EN] = 0.
 	 * Also, ensure that no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
 
 	/* Check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mpwrdlhwctl) & 0x0000000f)
@@ -526,7 +526,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	writel(0x0, &mmdc0->mdscr);	/* CS0 */
 
 	/* Poll to make sure the con_ack bit is clear */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 0, 100, 0);
 
 	/*
 	 * Print out the registers that were updated as a result
diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c
index cb6ae03696..c740c9f648 100644
--- a/arch/arm/mach-socfpga/clock_manager.c
+++ b/arch/arm/mach-socfpga/clock_manager.c
@@ -37,8 +37,8 @@ void cm_wait_for_lock(u32 mask)
 /* function to poll in the fsm busy bit */
 int cm_wait_for_fsm(void)
 {
-	return wait_for_bit(__func__, (const u32 *)&clock_manager_base->stat,
-			    CLKMGR_STAT_BUSY, false, 20000, false);
+	return wait_for_bit_le32(&clock_manager_base->stat,
+				 CLKMGR_STAT_BUSY, false, 20000, false);
 }
 
 int set_cpu_clk_info(void)
diff --git a/arch/arm/mach-socfpga/clock_manager_gen5.c b/arch/arm/mach-socfpga/clock_manager_gen5.c
index 31fd51097a..a23f3fc5d0 100644
--- a/arch/arm/mach-socfpga/clock_manager_gen5.c
+++ b/arch/arm/mach-socfpga/clock_manager_gen5.c
@@ -37,15 +37,13 @@ static int cm_write_with_phase(u32 value, u32 reg_address, u32 mask)
 	int ret;
 
 	/* poll until phase is zero */
-	ret = wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			   false, 20000, false);
+	ret = wait_for_bit_le32(reg_address, mask, false, 20000, false);
 	if (ret)
 		return ret;
 
 	writel(value, reg_address);
 
-	return wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			    false, 20000, false);
+	return wait_for_bit_le32(reg_address, mask, false, 20000, false);
 }
 
 /*
diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c
index ae16897494..54f0ddb255 100644
--- a/arch/arm/mach-socfpga/reset_manager_arria10.c
+++ b/arch/arm/mach-socfpga/reset_manager_arria10.c
@@ -222,8 +222,8 @@ int socfpga_reset_deassert_bridges_handoff(void)
 	clrbits_le32(&reset_manager_base->brgmodrst, mask_rstmgr);
 
 	/* Poll until all idleack to 0, timeout at 1000ms */
-	return wait_for_bit(__func__, &sysmgr_regs->noc_idleack, mask_noc,
-			    false, 1000, false);
+	return wait_for_bit_le32(&sysmgr_regs->noc_idleack, mask_noc,
+				 false, 1000, false);
 }
 
 void socfpga_reset_assert_fpga_connected_peripherals(void)
@@ -343,26 +343,26 @@ int socfpga_bridges_reset(void)
 	writel(ALT_SYSMGR_NOC_TMO_EN_SET_MSK, &sysmgr_regs->noc_timeout);
 
 	/* Poll until all idleack to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idleack,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idleack,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
 	/* Poll until all idlestatus to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idlestatus,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idlestatus,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/arch/mips/mach-ath79/ar934x/clk.c b/arch/mips/mach-ath79/ar934x/clk.c
index 9b41d3de60..ba2243c9be 100644
--- a/arch/mips/mach-ath79/ar934x/clk.c
+++ b/arch/mips/mach-ath79/ar934x/clk.c
@@ -90,7 +90,7 @@ static void ar934x_srif_pll_cfg(void __iomem *pll_reg_base, const u32 srif_val)
 		setbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
 
-		wait_for_bit("clk", pll_reg_base + 0xc, BIT(3), 1, 10, 0);
+		wait_for_bit_le32(pll_reg_base + 0xc, BIT(3), 1, 10, 0);
 
 		clrbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
diff --git a/board/samtec/vining_2000/vining_2000.c b/board/samtec/vining_2000/vining_2000.c
index af1a3e75cb..cced08b8b8 100644
--- a/board/samtec/vining_2000/vining_2000.c
+++ b/board/samtec/vining_2000/vining_2000.c
@@ -378,7 +378,7 @@ static int read_adc(u32 *val)
 
 	/* start auto calibration */
 	setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
-	ret = wait_for_bit("ADC", b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
 	if (ret)
 		goto adc_exit;
 
@@ -386,7 +386,7 @@ static int read_adc(u32 *val)
 	writel(0, b + ADCx_HC0);
 
 	/* wait for conversion */
-	ret = wait_for_bit("ADC", b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
 	if (ret)
 		goto adc_exit;
 
diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
index f6eef314ec..177803943d 100644
--- a/drivers/clk/clk_pic32.c
+++ b/drivers/clk/clk_pic32.c
@@ -197,8 +197,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_ON | REFO_OE, reg + _CLR_OFFSET);
 
 	/* wait till previous src change is active */
-	wait_for_bit(__func__, reg, REFO_DIVSW_EN | REFO_ACTIVE,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(reg, REFO_DIVSW_EN | REFO_ACTIVE,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* parent_id */
 	v = readl(reg);
@@ -223,8 +223,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_DIVSW_EN, reg + _SET_OFFSET);
 
 	/* wait for divider switching to complete */
-	return wait_for_bit(__func__, reg, REFO_DIVSW_EN, false,
-			    CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(reg, REFO_DIVSW_EN, false,
+				 CONFIG_SYS_HZ, false);
 }
 
 static ulong pic32_get_refclk(struct pic32_clk_priv *priv, int periph)
@@ -311,8 +311,8 @@ static int pic32_mpll_init(struct pic32_clk_priv *priv)
 
 	/* Wait for ready */
 	mask = MPLL_RDY | MPLL_VREG_RDY;
-	return wait_for_bit(__func__, priv->syscfg_base + CFGMPLL, mask,
-			    true, get_tbclk(), false);
+	return wait_for_bit_le32(priv->syscfg_base + CFGMPLL, mask,
+				 true, get_tbclk(), false);
 }
 
 static void pic32_clk_init(struct udevice *dev)
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index b26bbcc59f..22828fd470 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -1046,8 +1046,8 @@ static int gen3_clk_endisable(struct clk *clk, bool enable)
 		if (ret)
 			return ret;
 		clrbits_le32(priv->base + SMSTPCR(reg), bitmask);
-		return wait_for_bit("MSTP", priv->base + MSTPSR(reg),
-				    bitmask, 0, 100, 0);
+		return wait_for_bit_le32(priv->base + MSTPSR(reg),
+					 bitmask, 0, 100, 0);
 	} else {
 		setbits_le32(priv->base + SMSTPCR(reg), bitmask);
 		return 0;
diff --git a/drivers/ddr/microchip/ddr2.c b/drivers/ddr/microchip/ddr2.c
index 6056418588..a52427c3d6 100644
--- a/drivers/ddr/microchip/ddr2.c
+++ b/drivers/ddr/microchip/ddr2.c
@@ -57,8 +57,8 @@ static int ddr2_phy_calib_start(void)
 	writel(SCL_START | SCL_EN, &ddr2_phy->scl_start);
 
 	/* Wait for SCL for data byte to pass */
-	return wait_for_bit(__func__, &ddr2_phy->scl_start, SCL_LUBPASS,
-			    true, CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(&ddr2_phy->scl_start, SCL_LUBPASS,
+				 true, CONFIG_SYS_HZ, false);
 }
 
 /* DDR2 Controller initialization */
@@ -256,8 +256,8 @@ void ddr2_ctrl_init(void)
 	writel(INIT_START, &ctrl->memcon);
 
 	/* wait for all host cmds to be transmitted */
-	wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ctrl->cmdissue, CMD_VALID, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* inform all cmds issued, ready for normal operation */
 	writel(INIT_START | INIT_DONE, &ctrl->memcon);
diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
index 5c1a68a009..d5763965dd 100644
--- a/drivers/fpga/socfpga_arria10.c
+++ b/drivers/fpga/socfpga_arria10.c
@@ -62,8 +62,7 @@ int is_fpgamgr_user_mode(void)
 
 static int wait_for_user_mode(void)
 {
-	return wait_for_bit(__func__,
-		&fpga_manager_base->imgcfg_stat,
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
 		ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK,
 		1, FPGA_TIMEOUT_MSEC, false);
 }
@@ -115,19 +114,17 @@ static int wait_for_nconfig_pin_and_nstatus_pin(void)
 	/* Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted,
 	 * timeout at 1000ms
 	 */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    mask,
-			    false, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		mask,
+		false, FPGA_TIMEOUT_MSEC, false);
 }
 
 static int wait_for_f2s_nstatus_pin(unsigned long value)
 {
 	/* Poll until f2s to specific value, timeout at 1000ms */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
-			    value, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
+		value, FPGA_TIMEOUT_MSEC, false);
 }
 
 /* set CD ratio */
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 9117ab6bf9..f0661bd96c 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -109,15 +109,15 @@ static int msm_sdc_probe(struct udevice *dev)
 
 
 	/* Wait for reset to be written to register */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_STATUS2,
-			 SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_STATUS2,
+			      SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
 		printf("msm_sdhci: reset request failed\n");
 		return -EIO;
 	}
 
 	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_POWER,
-			 SDCC_MCI_POWER_SW_RST, false, 2, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_POWER,
+			      SDCC_MCI_POWER_SW_RST, false, 2, false)) {
 		printf("msm_sdhci: stuck in reset\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c
index e1a8d3bc4b..8bbf2fa9a2 100644
--- a/drivers/mtd/pic32_flash.c
+++ b/drivers/mtd/pic32_flash.c
@@ -66,8 +66,8 @@ static inline void flash_initiate_operation(u32 nvmop)
 
 static int flash_wait_till_busy(const char *func, ulong timeout)
 {
-	int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw,
-			       NVM_WR, false, timeout, false);
+	int ret = wait_for_bit_le32(&nvm_regs_p->ctrl.raw,
+				    NVM_WR, false, timeout, false);
 
 	return ret ? ERR_TIMOUT : ERR_OK;
 }
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index 00e6806892..f28187058e 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -164,8 +164,8 @@ static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
 	writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
 	       regs + AG7XXX_ETH_MII_MGMT_CMD);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 	if (ret)
 		return ret;
 
@@ -185,8 +185,8 @@ static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
 	       regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
 	writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 
 	return ret;
 }
@@ -510,13 +510,13 @@ static void ag7xxx_eth_stop(struct udevice *dev)
 
 	/* Stop the TX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
+			  1000, 0);
 
 	/* Stop the RX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
+			  1000, 0);
 }
 
 /*
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 00076cffbe..232e8034df 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -361,8 +361,9 @@ static void eqos_flush_buffer(void *buf, size_t size)
 
 static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
 {
-	return wait_for_bit(__func__, &eqos->mac_regs->mdio_address,
-			    EQOS_MAC_MDIO_ADDRESS_GB, false, 1000000, true);
+	return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
+				 EQOS_MAC_MDIO_ADDRESS_GB, false,
+				 1000000, true);
 }
 
 static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
@@ -588,15 +589,15 @@ static int eqos_calibrate_pads_tegra186(struct udevice *dev)
 	setbits_le32(&eqos->tegra186_regs->auto_cal_config,
 		     EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE);
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't start");
 		goto failed;
 	}
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't finish");
 		goto failed;
@@ -862,8 +863,8 @@ static int eqos_start(struct udevice *dev)
 
 	eqos->reg_access_ok = true;
 
-	ret = wait_for_bit(__func__, &eqos->dma_regs->mode,
-			   EQOS_DMA_MODE_SWR, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->dma_regs->mode,
+				EQOS_DMA_MODE_SWR, false, 10, false);
 	if (ret) {
 		pr_err("EQOS_DMA_MODE_SWR stuck");
 		goto err_stop_resets;
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a6df950081..51a6c97550 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -548,8 +548,8 @@ static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		u32 data = ethoc_read(priv, MIIRX_DATA);
@@ -571,8 +571,8 @@ static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
 	ethoc_write(priv, MIITX_DATA, val);
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		/* reset MII command register */
diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
index 0b89911f04..7129372790 100644
--- a/drivers/net/pic32_eth.c
+++ b/drivers/net/pic32_eth.c
@@ -64,8 +64,8 @@ static int pic32_mii_init(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* turn controller ON to access PHY over MII */
 	writel(ETHCON_ON, &ectl_p->con1.set);
@@ -239,8 +239,8 @@ static void pic32_ctrl_reset(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 	/* decrement received buffcnt to zero. */
 	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
 		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
@@ -375,8 +375,8 @@ static void pic32_eth_stop(struct udevice *dev)
 	mdelay(10);
 
 	/* wait until everything is down */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     2 * CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  2 * CONFIG_SYS_HZ, false);
 
 	/* clear any existing interrupt event */
 	writel(0xffffffff, &ectl_p->irq.clr);
diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
index 578fc96905..6ae5c40fa3 100644
--- a/drivers/net/pic32_mdio.c
+++ b/drivers/net/pic32_mdio.c
@@ -22,8 +22,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -36,8 +36,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	udelay(12);
 
 	/* Wait for write to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	return 0;
 }
@@ -48,8 +48,8 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -62,9 +62,9 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	udelay(12);
 
 	/* Wait for read to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw,
-		     MIIMIND_NOTVALID | MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&mii_regs->mind.raw,
+			  MIIMIND_NOTVALID | MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* Clear the command register */
 	writel(0, &mii_regs->mcmd.raw);
@@ -82,22 +82,22 @@ static int pic32_mdio_reset(struct mii_dev *bus)
 	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
 		     false, CONFIG_SYS_HZ, true);
 
 	/* Clear reset bit */
 	writel(0, &mii_regs->mcfg);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
 	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 	return 0;
 }
 
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index dc743e113d..26bd915291 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -222,8 +222,8 @@ static int ravb_reset(struct udevice *dev)
 	writel(CCC_OPC_CONFIG, eth->iobase + RAVB_REG_CCC);
 
 	/* Check the operating mode is changed to the config mode. */
-	return wait_for_bit(dev->name, (void *)eth->iobase + RAVB_REG_CSR,
-			    CSR_OPS_CONFIG, true, 100, true);
+	return wait_for_bit_le32(eth->iobase + RAVB_REG_CSR,
+				 CSR_OPS_CONFIG, true, 100, true);
 }
 
 static void ravb_base_desc_init(struct ravb_priv *eth)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 9a2a578ff9..70a2e95a8e 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -366,8 +366,8 @@ static int axi_ethernet_init(struct axidma_priv *priv)
 	 * processor mode and hence bypass in this mode
 	 */
 	if (!priv->eth_hasnobuf) {
-		err = wait_for_bit(__func__, (const u32 *)&regs->is,
-				   XAE_INT_MGTRDY_MASK, true, 200, false);
+		err = wait_for_bit_le32(&regs->is, XAE_INT_MGTRDY_MASK,
+					true, 200, false);
 		if (err) {
 			printf("%s: Timeout\n", __func__);
 			return 1;
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 1dfd631e1a..2cc49bca92 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -192,8 +192,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	struct zynq_gem_regs *regs = priv->iobase;
 	int err;
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -205,8 +205,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	/* Write mgtcr and wait for completion */
 	writel(mgtcr, &regs->phymntnc);
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -514,8 +514,8 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
 	if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
 		printf("TX buffers exhausted in mid frame\n");
 
-	return wait_for_bit(__func__, &regs->txsr, ZYNQ_GEM_TSR_DONE,
-			    true, 20000, true);
+	return wait_for_bit_le32(&regs->txsr, ZYNQ_GEM_TSR_DONE,
+				 true, 20000, true);
 }
 
 /* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c
index 17786f976a..0fc5a28802 100644
--- a/drivers/reset/sti-reset.c
+++ b/drivers/reset/sti-reset.c
@@ -266,8 +266,8 @@ static int sti_reset_program_hw(struct reset_ctl *reset_ctl, int assert)
 		return 0;
 
 	reg = (void __iomem *)base + ch->ack_offset;
-	if (wait_for_bit(__func__, reg, BIT(ch->ack_bit), ctrl_val,
-			 1000, false)) {
+	if (wait_for_bit_le32(reg, BIT(ch->ack_bit), ctrl_val,
+			      1000, false)) {
 		pr_err("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n",
 		      reset_ctl, reset_ctl->dev, reset_ctl->id);
 
diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c
index b0e01aa0e5..0632d26211 100644
--- a/drivers/serial/serial_pic32.c
+++ b/drivers/serial/serial_pic32.c
@@ -51,8 +51,8 @@ static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
 	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
 
 	/* wait for TX FIFO to empty */
-	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
-		     true, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(base + U_STA, UART_TX_EMPTY,
+			  true, CONFIG_SYS_HZ, false);
 
 	/* send break */
 	writel(UART_TX_BRK, base + U_STASET);
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 228e714e09..8010ab434c 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -394,8 +394,8 @@ out:
 		 * Wait until the transfer is completely done before
 		 * we deactivate CS.
 		 */
-		wait_for_bit(__func__, &reg_base->sr,
-			     ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
+		wait_for_bit_le32(&reg_base->sr,
+				  ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
 
 		atmel_spi_cs_deactivate(dev);
 	}
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index e02f2217f4..dca3fdfdea 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -675,8 +675,8 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTRD,
-			   CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD,
+				CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect read completion error (%i)\n", ret);
 		goto failrd;
@@ -762,9 +762,9 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 				bb_txbuf + rounddown(write_bytes, 4),
 				write_bytes % 4);
 
-		ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL,
-				   CQSPI_REG_SDRAMLEVEL_WR_MASK <<
-				   CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
+		ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL,
+					CQSPI_REG_SDRAMLEVEL_WR_MASK <<
+					CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
 		if (ret) {
 			printf("Indirect write timed out (%i)\n", ret);
 			goto failwr;
@@ -775,8 +775,8 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTWR,
-			   CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR,
+				CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect write completion error (%i)\n", ret);
 		goto failwr;
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 0f3f7d97f0..eed52c15c8 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -1011,11 +1011,11 @@ static int fsl_qspi_probe(struct udevice *bus)
 	priv->num_chipselect = plat->num_chipselect;
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
@@ -1173,11 +1173,11 @@ static int fsl_qspi_claim_bus(struct udevice *dev)
 	priv = dev_get_priv(bus);
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
index ec4907391c..d1708a8d56 100644
--- a/drivers/spi/mvebu_a3700_spi.c
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -95,8 +95,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 	din_8 = din;
 
 	while (bytelen) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true,100, false);
 		if (ret)
 			return ret;
 
@@ -109,9 +110,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 		writel(pending_dout, &reg->dout);
 
 		if (din) {
-			ret = wait_for_bit(__func__, &reg->ctrl,
-					   MVEBU_SPI_A3700_XFER_RDY,
-					   true, 100, false);
+			ret = wait_for_bit_le32(&reg->ctrl,
+						MVEBU_SPI_A3700_XFER_RDY,
+						true, 100, false);
 			if (ret)
 				return ret;
 
@@ -160,8 +161,9 @@ static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 	/* Deactivate CS */
 	if (flags & SPI_XFER_END) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true, 100, false);
 		if (ret)
 			return ret;
 
@@ -231,8 +233,8 @@ static int mvebu_spi_probe(struct udevice *bus)
 	/* Flush read/write FIFO */
 	data = readl(&reg->cfg);
 	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
-	ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+				false, 1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 1293e18f75..540c016412 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -108,8 +108,8 @@ static void dwc_otg_flush_tx_fifo(struct dwc2_core_regs *regs, const int num)
 
 	writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET),
 	       &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -127,8 +127,8 @@ static void dwc_otg_flush_rx_fifo(struct dwc2_core_regs *regs)
 	int ret;
 
 	writel(DWC2_GRSTCTL_RXFFLSH, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -145,15 +145,15 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs)
 	int ret;
 
 	/* Wait for AHB master IDLE state. */
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
+				true, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
 	/* Core Soft Reset */
 	writel(DWC2_GRSTCTL_CSFTRST, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_CSFTRST,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_CSFTRST,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -267,8 +267,8 @@ static void dwc_otg_core_host_init(struct udevice *dev,
 		clrsetbits_le32(&regs->hc_regs[i].hcchar,
 				DWC2_HCCHAR_EPDIR,
 				DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS);
-		ret = wait_for_bit(__func__, &regs->hc_regs[i].hcchar,
-				   DWC2_HCCHAR_CHEN, false, 1000, false);
+		ret = wait_for_bit_le32(&regs->hc_regs[i].hcchar,
+					DWC2_HCCHAR_CHEN, false, 1000, false);
 		if (ret)
 			printf("%s: Timeout!\n", __func__);
 	}
@@ -783,8 +783,8 @@ int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle)
 	int ret;
 	uint32_t hcint, hctsiz;
 
-	ret = wait_for_bit(__func__, &hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
-			   1000, false);
+	ret = wait_for_bit_le32(&hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
+				1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 2c0c63322c..f5320ca298 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -133,8 +133,7 @@ static int ehci_usb_remove(struct udevice *dev)
 	setbits_le32(&ehci->usbcmd, CMD_RESET);
 
 	/* Wait for reset */
-	if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30,
-			 false)) {
+	if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) {
 		printf("Stuck on USB reset.\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index fe2627ea93..2c8fc3c4b1 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -142,13 +142,12 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci)
 
 	/* Stop then Reset */
 	clrbits_le32(usb_cmd, UCMD_RUN_STOP);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RUN_STOP, false, 10000,
-			   false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false);
 	if (ret)
 		return ret;
 
 	setbits_le32(usb_cmd, UCMD_RESET);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RESET, false, 10000, false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ohci-lpc32xx.c b/drivers/usb/host/ohci-lpc32xx.c
index 2f2b4b90de..44a49807a4 100644
--- a/drivers/usb/host/ohci-lpc32xx.c
+++ b/drivers/usb/host/ohci-lpc32xx.c
@@ -143,8 +143,8 @@ static int usbpll_setup(void)
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_POSTDIV_2POW(0x01));
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_PWRUP);
 
-	ret = wait_for_bit(__func__, &clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
-			   true, CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
+				true, CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -178,8 +178,8 @@ int usb_cpu_init(void)
 
 	/* enable I2C clock */
 	writel(OTG_CLK_I2C_EN, &otg->otg_clk_ctrl);
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -199,8 +199,8 @@ int usb_cpu_init(void)
 			 OTG_CLK_I2C_EN | OTG_CLK_HOST_EN;
 	writel(mask, &otg->otg_clk_ctrl);
 
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, mask, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, mask, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index d47c99644d..71202d7b03 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -55,18 +55,18 @@ static int xhci_rcar_download_fw(struct rcar_xhci *ctx, const u32 *fw_data,
 		setbits_le32(regs + RCAR_USB3_DL_CTRL,
 			     RCAR_USB3_DL_CTRL_FW_SET_DATA0);
 
-		ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-				   RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
-				   10, false);
+		ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+					RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
+					10, false);
 		if (ret)
 			break;
 	}
 
 	clrbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
 
-	ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-			   RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
-			   10, false);
+	ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+				RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
+				10, false);
 
 	return ret;
 }
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index f77da2ec97..c0dd689e7c 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -70,26 +70,26 @@ void lcd_ctrl_init(void *lcdbase)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -215,26 +215,26 @@ void lcd_ctrl_init(void *lcdbase)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -299,26 +299,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -451,26 +451,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 }
diff --git a/include/wait_bit.h b/include/wait_bit.h
index bde6d2cfc3..9f00e54e50 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -16,60 +16,6 @@
 #include <asm/io.h>
 
 /**
- * wait_for_bit()	waits for bit set/cleared in register
- *
- * Function polls register waiting for specific bit(s) change
- * (either 0->1 or 1->0). It can fail under two conditions:
- * - Timeout
- * - User interaction (CTRL-C)
- * Function succeeds only if all bits of masked register are set/cleared
- * (depending on set option).
- *
- * @param prefix	Prefix added to timeout messagge (message visible only
- *			with debug enabled)
- * @param reg		Register that will be read (using readl())
- * @param mask		Bit(s) of register that must be active
- * @param set		Selects wait condition (bit set or clear)
- * @param timeout_ms	Timeout (in miliseconds)
- * @param breakable	Enables CTRL-C interruption
- * @return		0 on success, -ETIMEDOUT or -EINTR on failure
- */
-static inline int wait_for_bit(const char *prefix, const u32 *reg,
-			       const u32 mask, const bool set,
-			       const unsigned int timeout_ms,
-			       const bool breakable)
-{
-	u32 val;
-	unsigned long start = get_timer(0);
-
-	while (1) {
-		val = readl(reg);
-
-		if (!set)
-			val = ~val;
-
-		if ((val & mask) == mask)
-			return 0;
-
-		if (get_timer(start) > timeout_ms)
-			break;
-
-		if (breakable && ctrlc()) {
-			puts("Abort\n");
-			return -EINTR;
-		}
-
-		udelay(1);
-		WATCHDOG_RESET();
-	}
-
-	debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", prefix, reg, mask,
-	      set);
-
-	return -ETIMEDOUT;
-}
-
-/**
  * wait_for_bit_x()	waits for bit set/cleared in register
  *
  * Function polls register waiting for specific bit(s) change
-- 
2.11.0

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

* [U-Boot] [PATCH v8 03/12] drivers: spi: allow limiting reads
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 51e28bf07b..e40e1c01de 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -516,6 +516,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 08c7480fda..4787454e59 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 
-- 
2.11.0

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

* [U-Boot] [PATCH v8 04/12] drivers: spi: consider command bytes when sending transfers
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e40e1c01de..294d9f9d79 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -405,7 +405,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index 4787454e59..5a7df1c706 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 05/12] dm: spi: add BCM63xx SPI driver
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  11 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Use cmd instead of val to avoid confusions.
 - Switch to wait_for_bit instead of infinite loop.
 v5: Introduce changes suggested by Jagan Teki:
  - Use long structure instead of a custom bmips_spi_hw structure.
  - Define constants for each SPI core.
 v4: Introduce changes suggested by Jagan Teki:
  - Add data for each HW controller instead of having two separate configs.
  - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |   8 +
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 442 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 494639fb01..ebc71c2e42 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,14 @@ config ATMEL_SPI
 	  many AT91 (ARM) chips. This driver can be used to access
 	  the SPI Flash, such as AT25DF321.
 
+config BCM63XX_SPI
+	bool "BCM6348 SPI driver"
+	depends on ARCH_BMIPS
+	help
+	  Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding these Broadcom
+	  SPI cores.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e3184db67f..5770b3f7cc 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,6 +18,7 @@ endif
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000000..f0df6871d8
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* BCM6348 SPI core */
+#define SPI_6348_CLK			0x06
+#define SPI_6348_CMD			0x00
+#define SPI_6348_CTL			0x40
+#define SPI_6348_CTL_SHIFT		6
+#define SPI_6348_FILL			0x07
+#define SPI_6348_IR_MASK		0x04
+#define SPI_6348_IR_STAT		0x02
+#define SPI_6348_RX			0x80
+#define SPI_6348_RX_SIZE		0x3f
+#define SPI_6348_TX			0x41
+#define SPI_6348_TX_SIZE		0x3f
+
+/* BCM6358 SPI core */
+#define SPI_6358_CLK			0x706
+#define SPI_6358_CMD			0x700
+#define SPI_6358_CTL			0x000
+#define SPI_6358_CTL_SHIFT		14
+#define SPI_6358_FILL			0x707
+#define SPI_6358_IR_MASK		0x702
+#define SPI_6358_IR_STAT		0x704
+#define SPI_6358_RX			0x400
+#define SPI_6358_RX_SIZE		0x220
+#define SPI_6358_TX			0x002
+#define SPI_6358_TX_SIZE		0x21e
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Control register */
+#define SPI_CTL_TYPE_FD_RW	0
+#define SPI_CTL_TYPE_HD_W	1
+#define SPI_CTL_TYPE_HD_R	2
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+enum bcm63xx_regs_spi {
+	SPI_CLK,
+	SPI_CMD,
+	SPI_CTL,
+	SPI_CTL_SHIFT,
+	SPI_FILL,
+	SPI_IR_MASK,
+	SPI_IR_STAT,
+	SPI_RX,
+	SPI_RX_SIZE,
+	SPI_TX,
+	SPI_TX_SIZE,
+};
+
+struct bcm63xx_spi_priv {
+	const unsigned long *regs;
+	void __iomem *base;
+	size_t tx_bytes;
+	uint8_t num_cs;
+};
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		printf("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->base + regs[SPI_CLK],
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			printf("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > regs[SPI_RX_SIZE]) {
+			printf("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
+			printf("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val, cmd;
+		int ret;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val = priv->tx_bytes;
+			val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_FD_RW <<
+					regs[SPI_CTL_SHIFT]);
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_HD_R <<
+					regs[SPI_CTL_SHIFT]);
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					printf("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+
+		if (regs[SPI_CTL_SHIFT] >= 8)
+			writew_be(val, priv->base + regs[SPI_CTL]);
+		else
+			writeb_be(val, priv->base + regs[SPI_CTL]);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
+
+		/* issue the transfer */
+		cmd = SPI_CMD_OP_START;
+		cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			cmd |= SPI_CMD_3WIRE_MASK;
+		writew_be(cmd, priv->base + regs[SPI_CMD]);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
+
+		ret = wait_for_bit_8(priv->base + regs[SPI_IR_STAT],
+				     SPI_IR_DONE_MASK, true, 1000, false);
+		if (ret) {
+			printf("interrupt timeout\n");
+			return ret;
+		}
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->base + regs[SPI_RX],
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const unsigned long bcm6348_spi_regs[] = {
+	[SPI_CLK] = SPI_6348_CLK,
+	[SPI_CMD] = SPI_6348_CMD,
+	[SPI_CTL] = SPI_6348_CTL,
+	[SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT,
+	[SPI_FILL] = SPI_6348_FILL,
+	[SPI_IR_MASK] = SPI_6348_IR_MASK,
+	[SPI_IR_STAT] = SPI_6348_IR_STAT,
+	[SPI_RX] = SPI_6348_RX,
+	[SPI_RX_SIZE] = SPI_6348_RX_SIZE,
+	[SPI_TX] = SPI_6348_TX,
+	[SPI_TX_SIZE] = SPI_6348_TX_SIZE,
+};
+
+static const unsigned long bcm6358_spi_regs[] = {
+	[SPI_CLK] = SPI_6358_CLK,
+	[SPI_CMD] = SPI_6358_CMD,
+	[SPI_CTL] = SPI_6358_CTL,
+	[SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT,
+	[SPI_FILL] = SPI_6358_FILL,
+	[SPI_IR_MASK] = SPI_6358_IR_MASK,
+	[SPI_IR_STAT] = SPI_6358_IR_STAT,
+	[SPI_RX] = SPI_6358_RX,
+	[SPI_RX_SIZE] = SPI_6358_RX_SIZE,
+	[SPI_TX] = SPI_6358_TX,
+	[SPI_TX_SIZE] = SPI_6358_TX_SIZE,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-spi",
+		.data = (ulong)&bcm6348_spi_regs,
+	}, {
+		.compatible = "brcm,bcm6358-spi",
+		.data = (ulong)&bcm6358_spi_regs,
+	}, { /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		printf("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = regs[SPI_RX_SIZE];
+	slave->max_write_size = regs[SPI_TX_SIZE];
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	const unsigned long *regs =
+		(const unsigned long *)dev_get_driver_data(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = regs;
+	priv->base = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_free(&clk);
+	if (ret < 0)
+		return ret;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_free(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	/* initialize hardware */
+	writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+
+	/* set fill register */
+	writeb_be(0xff, priv->base + regs[SPI_FILL]);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v8 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-16 14:56     ` Simon Glass
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a4372b..0cab44cb8d 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v8 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-16 14:57     ` Simon Glass
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643b5a..540b9fea5b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v8 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-16 14:57     ` Simon Glass
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf80e0..1662783279 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v8 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-16 14:57     ` Simon Glass
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb048..f83a6ea8df 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v8 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-16 14:57     ` Simon Glass
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96bef8..6e3d9c3820 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.11.0

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

* [U-Boot] [PATCH v8 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (9 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-16 14:57     ` Simon Glass
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5551..dd0e5b8b7c 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index cfc56cba37..5c091353e5 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -39,3 +39,11 @@ CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_WINBOND=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (10 preceding siblings ...)
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2018-01-11 17:11   ` Álvaro Fernández Rojas
  2018-01-16 14:57     ` Simon Glass
  11 siblings, 1 reply; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:11 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v8: no changes
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7616..5f85c7346f 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index 7665c78d3f..369c919ac7 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -41,3 +41,11 @@ CONFIG_RESET_BCM6345=y
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
 CONFIG_WDT_BCM6345=y
+CONFIG_BCM63XX_SPI=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPI_FLASH_SPANSION=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
@ 2018-01-11 17:17     ` Jagan Teki
  2018-01-11 17:42       ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 187+ messages in thread
From: Jagan Teki @ 2018-01-11 17:17 UTC (permalink / raw)
  To: u-boot

On Thu, Jan 11, 2018 at 10:41 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> Add 8/16/32 bits and BE/LE versions of wait_for_bit.
> This is needed for reading registers that are not aligned to 32 bits, and for
> Big Endian platforms.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes.
>  v7: Introduce changes suggested by Daniel Schwierzeck:
>  - Use const void* reg for compatibility with 64 bit systems.
>  - Remove prefix and use __func__ instead.
>  v6: Introduce changes suggested by Jagan Teki:
>  - Switch to wait_for_bit instead of infinite loop.
>
>  include/wait_bit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
>
> diff --git a/include/wait_bit.h b/include/wait_bit.h
> index 06ad43a122..bde6d2cfc3 100644
> --- a/include/wait_bit.h
> +++ b/include/wait_bit.h
> @@ -69,5 +69,66 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
>         return -ETIMEDOUT;
>  }
>
> +/**
> + * wait_for_bit_x()    waits for bit set/cleared in register
> + *
> + * Function polls register waiting for specific bit(s) change
> + * (either 0->1 or 1->0). It can fail under two conditions:
> + * - Timeout
> + * - User interaction (CTRL-C)
> + * Function succeeds only if all bits of masked register are set/cleared
> + * (depending on set option).
> + *
> + * @param reg          Register that will be read (using read_x())
> + * @param mask         Bit(s) of register that must be active
> + * @param set          Selects wait condition (bit set or clear)
> + * @param timeout_ms   Timeout (in milliseconds)
> + * @param breakable    Enables CTRL-C interruption
> + * @return             0 on success, -ETIMEDOUT or -EINTR on failure
> + */
> +
> +#define BUILD_WAIT_FOR_BIT(sfx, type, read)                            \
> +                                                                       \
> +static inline int wait_for_bit_##sfx(const void *reg,                  \
> +                                    const type mask,                   \
> +                                    const bool set,                    \
> +                                    const unsigned int timeout_ms,     \
> +                                    const bool breakable)              \
> +{                                                                      \
> +       type val;                                                       \
> +       unsigned long start = get_timer(0);                             \
> +                                                                       \
> +       while (1) {                                                     \
> +               val = read(reg);                                        \
> +                                                                       \
> +               if (!set)                                               \
> +                       val = ~val;                                     \
> +                                                                       \
> +               if ((val & mask) == mask)                               \
> +                       return 0;                                       \
> +                                                                       \
> +               if (get_timer(start) > timeout_ms)                      \
> +                       break;                                          \
> +                                                                       \
> +               if (breakable && ctrlc()) {                             \
> +                       puts("Abort\n");                                \
> +                       return -EINTR;                                  \
> +               }                                                       \
> +                                                                       \
> +               udelay(1);                                              \
> +               WATCHDOG_RESET();                                       \
> +       }                                                               \
> +                                                                       \
> +       debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__,   \
> +             reg, mask, set);                                          \
> +                                                                       \
> +       return -ETIMEDOUT;                                              \
> +}
> +
> +BUILD_WAIT_FOR_BIT(8, u8, readb)
> +BUILD_WAIT_FOR_BIT(le16, u16, readw)
> +BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
> +BUILD_WAIT_FOR_BIT(le32, u32, readl)
> +BUILD_WAIT_FOR_BIT(be32, u32, readl_be)

I'm still thinking here, can't we try to use typeof and get rid of
these endianess and macros? did you tried that?

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

* [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-11 17:17     ` Jagan Teki
@ 2018-01-11 17:42       ` Álvaro Fernández Rojas
  0 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-11 17:42 UTC (permalink / raw)
  To: u-boot

El 11/01/2018 a las 18:17, Jagan Teki escribió:
> On Thu, Jan 11, 2018 at 10:41 PM, Álvaro Fernández Rojas
> <noltari@gmail.com> wrote:
>> Add 8/16/32 bits and BE/LE versions of wait_for_bit.
>> This is needed for reading registers that are not aligned to 32 bits, and for
>> Big Endian platforms.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>> Reviewed-by: Jagan Teki <jagan@openedev.com>
>> ---
>>   v8: no changes.
>>   v7: Introduce changes suggested by Daniel Schwierzeck:
>>   - Use const void* reg for compatibility with 64 bit systems.
>>   - Remove prefix and use __func__ instead.
>>   v6: Introduce changes suggested by Jagan Teki:
>>   - Switch to wait_for_bit instead of infinite loop.
>>
>>   include/wait_bit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 61 insertions(+)
>>
>> diff --git a/include/wait_bit.h b/include/wait_bit.h
>> index 06ad43a122..bde6d2cfc3 100644
>> --- a/include/wait_bit.h
>> +++ b/include/wait_bit.h
>> @@ -69,5 +69,66 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
>>          return -ETIMEDOUT;
>>   }
>>
>> +/**
>> + * wait_for_bit_x()    waits for bit set/cleared in register
>> + *
>> + * Function polls register waiting for specific bit(s) change
>> + * (either 0->1 or 1->0). It can fail under two conditions:
>> + * - Timeout
>> + * - User interaction (CTRL-C)
>> + * Function succeeds only if all bits of masked register are set/cleared
>> + * (depending on set option).
>> + *
>> + * @param reg          Register that will be read (using read_x())
>> + * @param mask         Bit(s) of register that must be active
>> + * @param set          Selects wait condition (bit set or clear)
>> + * @param timeout_ms   Timeout (in milliseconds)
>> + * @param breakable    Enables CTRL-C interruption
>> + * @return             0 on success, -ETIMEDOUT or -EINTR on failure
>> + */
>> +
>> +#define BUILD_WAIT_FOR_BIT(sfx, type, read)                            \
>> +                                                                       \
>> +static inline int wait_for_bit_##sfx(const void *reg,                  \
>> +                                    const type mask,                   \
>> +                                    const bool set,                    \
>> +                                    const unsigned int timeout_ms,     \
>> +                                    const bool breakable)              \
>> +{                                                                      \
>> +       type val;                                                       \
>> +       unsigned long start = get_timer(0);                             \
>> +                                                                       \
>> +       while (1) {                                                     \
>> +               val = read(reg);                                        \
>> +                                                                       \
>> +               if (!set)                                               \
>> +                       val = ~val;                                     \
>> +                                                                       \
>> +               if ((val & mask) == mask)                               \
>> +                       return 0;                                       \
>> +                                                                       \
>> +               if (get_timer(start) > timeout_ms)                      \
>> +                       break;                                          \
>> +                                                                       \
>> +               if (breakable && ctrlc()) {                             \
>> +                       puts("Abort\n");                                \
>> +                       return -EINTR;                                  \
>> +               }                                                       \
>> +                                                                       \
>> +               udelay(1);                                              \
>> +               WATCHDOG_RESET();                                       \
>> +       }                                                               \
>> +                                                                       \
>> +       debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__,   \
>> +             reg, mask, set);                                          \
>> +                                                                       \
>> +       return -ETIMEDOUT;                                              \
>> +}
>> +
>> +BUILD_WAIT_FOR_BIT(8, u8, readb)
>> +BUILD_WAIT_FOR_BIT(le16, u16, readw)
>> +BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
>> +BUILD_WAIT_FOR_BIT(le32, u32, readl)
>> +BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
> I'm still thinking here, can't we try to use typeof and get rid of
> these endianess and macros? did you tried that?
No, I didn't try that.
Can you provide an example of that?

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

* [U-Boot] [PATCH v8 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2018-01-16 14:56     ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2018-01-16 14:56 UTC (permalink / raw)
  To: u-boot

On 11 January 2018 at 09:11, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes
>  v7: no changes
>  v6: no changes
>  v5: no changes
>  v4: no changes
>  v3: rename BCM6338 SPI driver to BCM6348
>  v2: add spi alias
>
>  arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v8 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2018-01-16 14:57     ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2018-01-16 14:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2018 at 09:11, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes
>  v7: no changes
>  v6: no changes
>  v5: no changes
>  v4: no changes
>  v3: rename BCM6338 SPI driver to BCM6348
>  v2: add spi alias
>
>  arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v8 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2018-01-16 14:57     ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2018-01-16 14:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2018 at 09:11, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes
>  v7: no changes
>  v6: no changes
>  v5: no changes
>  v4: no changes
>  v3: no changes
>  v2: add spi alias
>
>  arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v8 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2018-01-16 14:57     ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2018-01-16 14:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2018 at 09:11, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> This driver manages the SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes
>  v7: no changes
>  v6: no changes
>  v5: no changes
>  v4: no changes
>  v3: no changes
>  v2: add spi alias
>
>  arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v8 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2018-01-16 14:57     ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2018-01-16 14:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2018 at 09:11, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> This driver manages the low speed SPI controller present on this SoC.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes
>  v7: no changes
>  v6: no changes
>  v5: no changes
>  v4: no changes
>  v3: no changes
>  v2: add spi alias
>
>  arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v8 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2018-01-16 14:57     ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2018-01-16 14:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2018 at 09:11, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> It's a Winbond (w25x32) 4 MB SPI flash.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes
>  v7: no changes
>  v6: no changes
>  v5: sync with master
>  v4: switch to CONFIG_BCM63XX_SPI
>  v3: rename BCM6338 SPI driver to BCM6348
>  v2: remove spi alias
>
>  arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
>  configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
>  2 files changed, 20 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

Please see below.

> diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
> index be15fe5551..dd0e5b8b7c 100644
> --- a/arch/mips/dts/sagem,f at st1704.dts
> +++ b/arch/mips/dts/sagem,f at st1704.dts
> @@ -44,6 +44,18 @@
>         status = "okay";
>  };
>
> +&spi {
> +       status = "okay";
> +
> +       spi-flash at 0 {
> +               compatible = "spi-flash";
> +               reg = <0>;
> +               #address-cells = <1>;
> +               #size-cells = <1>;
> +               spi-max-frequency = <20000000>;
> +       };
> +};
> +
>  &uart0 {
>         u-boot,dm-pre-reloc;
>         status = "okay";
> diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
> index cfc56cba37..5c091353e5 100644
> --- a/configs/sagem_f at st1704_ram_defconfig
> +++ b/configs/sagem_f at st1704_ram_defconfig
> @@ -39,3 +39,11 @@ CONFIG_RESET_BCM6345=y
>  # CONFIG_SPL_SERIAL_PRESENT is not set
>  CONFIG_DM_SERIAL=y
>  CONFIG_BCM6345_SERIAL=y
> +CONFIG_BCM63XX_SPI=y
> +CONFIG_CMD_SF=y
> +CONFIG_CMD_SPI=y
> +CONFIG_DM_SPI=y
> +CONFIG_DM_SPI_FLASH=y
> +CONFIG_SPI_FLASH=y
> +CONFIG_SPI_FLASH_MTD=y
> +CONFIG_SPI_FLASH_WINBOND=y

Are these definitely in the right order?

> --
> 2.11.0
>

Regards,
Simon

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

* [U-Boot] [PATCH v8 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2018-01-11 17:11   ` [U-Boot] [PATCH v8 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
@ 2018-01-16 14:57     ` Simon Glass
  0 siblings, 0 replies; 187+ messages in thread
From: Simon Glass @ 2018-01-16 14:57 UTC (permalink / raw)
  To: u-boot

On 11 January 2018 at 09:11, Álvaro Fernández Rojas <noltari@gmail.com> wrote:
> It's a Spansion (s25fl064a) 8 MB SPI flash.
>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> Reviewed-by: Jagan Teki <jagan@openedev.com>
> ---
>  v8: no changes
>  v7: no changes
>  v6: no changes
>  v5: sync with master
>  v4: switch to CONFIG_BCM63XX_SPI
>  v3: no changes
>  v2: remove spi alias
>
>  arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
>  configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
>  2 files changed, 20 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (15 preceding siblings ...)
  2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2018-01-20  1:11 ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
                     ` (12 more replies)
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
  17 siblings, 13 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v9: Introduce changes suggested by Simon Glass:
- Fix defconfig order.
v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
- Squash wait_bit commits.
- Remove register param castings.
v7: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
- Use const void* reg for compatibility with 64 bit systems.
- Remove prefix and use __func__ instead.
- Remove wait_for_bit and update callers to wait_for_bit_le32.
v6: Introduce changes suggested by Jagan Teki:
- Use cmd instead of val to avoid confusions.
- Switch to wait_for_bit instead of infinite loop.
v5: Introduce changes suggested by Jagan Teki:
- Use long structs for registers
v4: Introduce changes suggested by Jagan Teki:
- Add data for each HW controller instead of having two separate configs.
v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (12):
  wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  wait_bit: use wait_for_bit_le32 and remove wait_for_bit
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/arm/mach-imx/mx6/ddr.c                   |  22 +-
 arch/arm/mach-socfpga/clock_manager.c         |   4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |   6 +-
 arch/arm/mach-socfpga/reset_manager_arria10.c |  36 +--
 arch/mips/dts/brcm,bcm3380.dtsi               |  17 +
 arch/mips/dts/brcm,bcm63268.dtsi              |  17 +
 arch/mips/dts/brcm,bcm6338.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6348.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6358.dtsi               |  17 +
 arch/mips/dts/netgear,cg3100d.dts             |  12 +
 arch/mips/dts/sagem,f at st1704.dts              |  12 +
 arch/mips/mach-ath79/ar934x/clk.c             |   2 +-
 board/samtec/vining_2000/vining_2000.c        |   4 +-
 configs/netgear_cg3100d_ram_defconfig         |   8 +
 configs/sagem_f at st1704_ram_defconfig          |   8 +
 drivers/clk/clk_pic32.c                       |  12 +-
 drivers/clk/renesas/clk-rcar-gen3.c           |   4 +-
 drivers/ddr/microchip/ddr2.c                  |   8 +-
 drivers/fpga/socfpga_arria10.c                |  17 +-
 drivers/mmc/msm_sdhci.c                       |   8 +-
 drivers/mtd/pic32_flash.c                     |   4 +-
 drivers/mtd/spi/spi_flash.c                   |   5 +-
 drivers/net/ag7xxx.c                          |  16 +-
 drivers/net/dwc_eth_qos.c                     |  17 +-
 drivers/net/ethoc.c                           |   8 +-
 drivers/net/pic32_eth.c                       |  12 +-
 drivers/net/pic32_mdio.c                      |  28 +-
 drivers/net/ravb.c                            |   4 +-
 drivers/net/xilinx_axi_emac.c                 |   4 +-
 drivers/net/zynq_gem.c                        |  12 +-
 drivers/reset/sti-reset.c                     |   4 +-
 drivers/serial/serial_pic32.c                 |   4 +-
 drivers/spi/Kconfig                           |   8 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/atmel_spi.c                       |   4 +-
 drivers/spi/bcm63xx_spi.c                     | 433 ++++++++++++++++++++++++++
 drivers/spi/cadence_qspi_apb.c                |  14 +-
 drivers/spi/fsl_qspi.c                        |  20 +-
 drivers/spi/mvebu_a3700_spi.c                 |  20 +-
 drivers/usb/host/dwc2.c                       |  24 +-
 drivers/usb/host/ehci-msm.c                   |   3 +-
 drivers/usb/host/ehci-mx6.c                   |   5 +-
 drivers/usb/host/ohci-lpc32xx.c               |  12 +-
 drivers/usb/host/xhci-rcar.c                  |  12 +-
 drivers/video/atmel_hlcdfb.c                  |  64 ++--
 include/spi.h                                 |   5 +-
 include/wait_bit.h                            |  81 ++---
 47 files changed, 824 insertions(+), 248 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.11.0

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

* [U-Boot] [PATCH v9 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

Add 8/16/32 bits and BE/LE versions of wait_for_bit.
This is needed for reading registers that are not aligned to 32 bits, and for
Big Endian platforms.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v9: no changes.
 v8: no changes.
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Use const void* reg for compatibility with 64 bit systems.
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Switch to wait_for_bit instead of infinite loop.

 include/wait_bit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/include/wait_bit.h b/include/wait_bit.h
index 06ad43a122..bde6d2cfc3 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -69,5 +69,66 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
 	return -ETIMEDOUT;
 }
 
+/**
+ * wait_for_bit_x()	waits for bit set/cleared in register
+ *
+ * Function polls register waiting for specific bit(s) change
+ * (either 0->1 or 1->0). It can fail under two conditions:
+ * - Timeout
+ * - User interaction (CTRL-C)
+ * Function succeeds only if all bits of masked register are set/cleared
+ * (depending on set option).
+ *
+ * @param reg		Register that will be read (using read_x())
+ * @param mask		Bit(s) of register that must be active
+ * @param set		Selects wait condition (bit set or clear)
+ * @param timeout_ms	Timeout (in milliseconds)
+ * @param breakable	Enables CTRL-C interruption
+ * @return		0 on success, -ETIMEDOUT or -EINTR on failure
+ */
+
+#define BUILD_WAIT_FOR_BIT(sfx, type, read)				\
+									\
+static inline int wait_for_bit_##sfx(const void *reg,			\
+				     const type mask,			\
+				     const bool set,			\
+				     const unsigned int timeout_ms,	\
+				     const bool breakable)		\
+{									\
+	type val;							\
+	unsigned long start = get_timer(0);				\
+									\
+	while (1) {							\
+		val = read(reg);					\
+									\
+		if (!set)						\
+			val = ~val;					\
+									\
+		if ((val & mask) == mask)				\
+			return 0;					\
+									\
+		if (get_timer(start) > timeout_ms)			\
+			break;						\
+									\
+		if (breakable && ctrlc()) {				\
+			puts("Abort\n");				\
+			return -EINTR;					\
+		}							\
+									\
+		udelay(1);						\
+		WATCHDOG_RESET();					\
+	}								\
+									\
+	debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__,	\
+	      reg, mask, set);						\
+									\
+	return -ETIMEDOUT;						\
+}
+
+BUILD_WAIT_FOR_BIT(8, u8, readb)
+BUILD_WAIT_FOR_BIT(le16, u16, readw)
+BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
+BUILD_WAIT_FOR_BIT(le32, u32, readl)
+BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
 
 #endif
-- 
2.11.0

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

* [U-Boot] [PATCH v9 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

wait_for_bit callers use the 32 bit LE version

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v9: no changes
 v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
 - Squash wait_bit commits.
 - Remove register param castings.
 v7: Introduce changes suggested by Jagan Teki:
 - Remove wait_for_bit and update callers to wait_for_bit_le32.

 arch/arm/mach-imx/mx6/ddr.c                   | 22 ++++-----
 arch/arm/mach-socfpga/clock_manager.c         |  4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |  6 +--
 arch/arm/mach-socfpga/reset_manager_arria10.c | 36 +++++++--------
 arch/mips/mach-ath79/ar934x/clk.c             |  2 +-
 board/samtec/vining_2000/vining_2000.c        |  4 +-
 drivers/clk/clk_pic32.c                       | 12 ++---
 drivers/clk/renesas/clk-rcar-gen3.c           |  4 +-
 drivers/ddr/microchip/ddr2.c                  |  8 ++--
 drivers/fpga/socfpga_arria10.c                | 17 +++----
 drivers/mmc/msm_sdhci.c                       |  8 ++--
 drivers/mtd/pic32_flash.c                     |  4 +-
 drivers/net/ag7xxx.c                          | 16 +++----
 drivers/net/dwc_eth_qos.c                     | 17 +++----
 drivers/net/ethoc.c                           |  8 ++--
 drivers/net/pic32_eth.c                       | 12 ++---
 drivers/net/pic32_mdio.c                      | 28 ++++++------
 drivers/net/ravb.c                            |  4 +-
 drivers/net/xilinx_axi_emac.c                 |  4 +-
 drivers/net/zynq_gem.c                        | 12 ++---
 drivers/reset/sti-reset.c                     |  4 +-
 drivers/serial/serial_pic32.c                 |  4 +-
 drivers/spi/atmel_spi.c                       |  4 +-
 drivers/spi/cadence_qspi_apb.c                | 14 +++---
 drivers/spi/fsl_qspi.c                        | 20 ++++-----
 drivers/spi/mvebu_a3700_spi.c                 | 20 +++++----
 drivers/usb/host/dwc2.c                       | 24 +++++-----
 drivers/usb/host/ehci-msm.c                   |  3 +-
 drivers/usb/host/ehci-mx6.c                   |  5 +--
 drivers/usb/host/ohci-lpc32xx.c               | 12 ++---
 drivers/usb/host/xhci-rcar.c                  | 12 ++---
 drivers/video/atmel_hlcdfb.c                  | 64 +++++++++++++--------------
 include/wait_bit.h                            | 54 ----------------------
 33 files changed, 205 insertions(+), 263 deletions(-)

diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index 39dbd2f607..43b77cfa41 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -21,10 +21,10 @@ static void reset_read_data_fifos(void)
 
 	/* Reset data FIFOs twice. */
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 }
 
 static void precharge_all(const bool cs0_enable, const bool cs1_enable)
@@ -39,12 +39,12 @@ static void precharge_all(const bool cs0_enable, const bool cs1_enable)
 	 */
 	if (cs0_enable) { /* CS0 */
 		writel(0x04008050, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 
 	if (cs1_enable) { /* CS1 */
 		writel(0x04008058, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 }
 
@@ -146,7 +146,7 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * 7. Upon completion of this process the MMDC de-asserts
 	 * the MPWLGCR[HW_WL_EN]
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
 
 	/*
 	 * 8. check for any errors: check both PHYs for x64 configuration,
@@ -278,7 +278,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 		writel(0x00008028, &mmdc0->mdscr);
 
 	/* poll to make sure the con_ack bit was asserted */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 
 	/*
 	 * Check MDMISC register CALIB_PER_CS to see which CS calibration
@@ -312,7 +312,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * this bit until it clears to indicate completion of the write access.
 	 */
 	setbits_le32(&mmdc0->mpswdar0, 1);
-	wait_for_bit("MMDC", &mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
 
 	/* Set the RD_DL_ABS# bits to their default values
 	 * (will be calibrated later in the read delay-line calibration).
@@ -359,7 +359,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	setbits_le32(&mmdc0->mpdgctrl0, 5 << 28);
 
 	/* Poll for completion.  MPDGCTRL0[HW_DG_EN] should be 0 */
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
 
 	/*
 	 * Check to see if any errors were encountered during calibration
@@ -423,7 +423,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * setting MPRDDLHWCTL[HW_RD_DL_EN] = 0.   Also, ensure that
 	 * no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
 
 	/* check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mprddlhwctl) & 0x0000000f)
@@ -477,7 +477,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * by setting MPWRDLHWCTL[HW_WR_DL_EN] = 0.
 	 * Also, ensure that no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
 
 	/* Check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mpwrdlhwctl) & 0x0000000f)
@@ -526,7 +526,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	writel(0x0, &mmdc0->mdscr);	/* CS0 */
 
 	/* Poll to make sure the con_ack bit is clear */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 0, 100, 0);
 
 	/*
 	 * Print out the registers that were updated as a result
diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c
index 6b76221025..43e72a8b55 100644
--- a/arch/arm/mach-socfpga/clock_manager.c
+++ b/arch/arm/mach-socfpga/clock_manager.c
@@ -37,8 +37,8 @@ void cm_wait_for_lock(u32 mask)
 /* function to poll in the fsm busy bit */
 int cm_wait_for_fsm(void)
 {
-	return wait_for_bit(__func__, (const u32 *)&clock_manager_base->stat,
-			    CLKMGR_STAT_BUSY, false, 20000, false);
+	return wait_for_bit_le32(&clock_manager_base->stat,
+				 CLKMGR_STAT_BUSY, false, 20000, false);
 }
 
 int set_cpu_clk_info(void)
diff --git a/arch/arm/mach-socfpga/clock_manager_gen5.c b/arch/arm/mach-socfpga/clock_manager_gen5.c
index 31fd51097a..a23f3fc5d0 100644
--- a/arch/arm/mach-socfpga/clock_manager_gen5.c
+++ b/arch/arm/mach-socfpga/clock_manager_gen5.c
@@ -37,15 +37,13 @@ static int cm_write_with_phase(u32 value, u32 reg_address, u32 mask)
 	int ret;
 
 	/* poll until phase is zero */
-	ret = wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			   false, 20000, false);
+	ret = wait_for_bit_le32(reg_address, mask, false, 20000, false);
 	if (ret)
 		return ret;
 
 	writel(value, reg_address);
 
-	return wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			    false, 20000, false);
+	return wait_for_bit_le32(reg_address, mask, false, 20000, false);
 }
 
 /*
diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c
index ae16897494..54f0ddb255 100644
--- a/arch/arm/mach-socfpga/reset_manager_arria10.c
+++ b/arch/arm/mach-socfpga/reset_manager_arria10.c
@@ -222,8 +222,8 @@ int socfpga_reset_deassert_bridges_handoff(void)
 	clrbits_le32(&reset_manager_base->brgmodrst, mask_rstmgr);
 
 	/* Poll until all idleack to 0, timeout at 1000ms */
-	return wait_for_bit(__func__, &sysmgr_regs->noc_idleack, mask_noc,
-			    false, 1000, false);
+	return wait_for_bit_le32(&sysmgr_regs->noc_idleack, mask_noc,
+				 false, 1000, false);
 }
 
 void socfpga_reset_assert_fpga_connected_peripherals(void)
@@ -343,26 +343,26 @@ int socfpga_bridges_reset(void)
 	writel(ALT_SYSMGR_NOC_TMO_EN_SET_MSK, &sysmgr_regs->noc_timeout);
 
 	/* Poll until all idleack to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idleack,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idleack,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
 	/* Poll until all idlestatus to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idlestatus,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idlestatus,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/arch/mips/mach-ath79/ar934x/clk.c b/arch/mips/mach-ath79/ar934x/clk.c
index 9b41d3de60..ba2243c9be 100644
--- a/arch/mips/mach-ath79/ar934x/clk.c
+++ b/arch/mips/mach-ath79/ar934x/clk.c
@@ -90,7 +90,7 @@ static void ar934x_srif_pll_cfg(void __iomem *pll_reg_base, const u32 srif_val)
 		setbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
 
-		wait_for_bit("clk", pll_reg_base + 0xc, BIT(3), 1, 10, 0);
+		wait_for_bit_le32(pll_reg_base + 0xc, BIT(3), 1, 10, 0);
 
 		clrbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
diff --git a/board/samtec/vining_2000/vining_2000.c b/board/samtec/vining_2000/vining_2000.c
index af1a3e75cb..cced08b8b8 100644
--- a/board/samtec/vining_2000/vining_2000.c
+++ b/board/samtec/vining_2000/vining_2000.c
@@ -378,7 +378,7 @@ static int read_adc(u32 *val)
 
 	/* start auto calibration */
 	setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
-	ret = wait_for_bit("ADC", b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
 	if (ret)
 		goto adc_exit;
 
@@ -386,7 +386,7 @@ static int read_adc(u32 *val)
 	writel(0, b + ADCx_HC0);
 
 	/* wait for conversion */
-	ret = wait_for_bit("ADC", b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
 	if (ret)
 		goto adc_exit;
 
diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
index f6eef314ec..177803943d 100644
--- a/drivers/clk/clk_pic32.c
+++ b/drivers/clk/clk_pic32.c
@@ -197,8 +197,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_ON | REFO_OE, reg + _CLR_OFFSET);
 
 	/* wait till previous src change is active */
-	wait_for_bit(__func__, reg, REFO_DIVSW_EN | REFO_ACTIVE,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(reg, REFO_DIVSW_EN | REFO_ACTIVE,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* parent_id */
 	v = readl(reg);
@@ -223,8 +223,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_DIVSW_EN, reg + _SET_OFFSET);
 
 	/* wait for divider switching to complete */
-	return wait_for_bit(__func__, reg, REFO_DIVSW_EN, false,
-			    CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(reg, REFO_DIVSW_EN, false,
+				 CONFIG_SYS_HZ, false);
 }
 
 static ulong pic32_get_refclk(struct pic32_clk_priv *priv, int periph)
@@ -311,8 +311,8 @@ static int pic32_mpll_init(struct pic32_clk_priv *priv)
 
 	/* Wait for ready */
 	mask = MPLL_RDY | MPLL_VREG_RDY;
-	return wait_for_bit(__func__, priv->syscfg_base + CFGMPLL, mask,
-			    true, get_tbclk(), false);
+	return wait_for_bit_le32(priv->syscfg_base + CFGMPLL, mask,
+				 true, get_tbclk(), false);
 }
 
 static void pic32_clk_init(struct udevice *dev)
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index b26bbcc59f..22828fd470 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -1046,8 +1046,8 @@ static int gen3_clk_endisable(struct clk *clk, bool enable)
 		if (ret)
 			return ret;
 		clrbits_le32(priv->base + SMSTPCR(reg), bitmask);
-		return wait_for_bit("MSTP", priv->base + MSTPSR(reg),
-				    bitmask, 0, 100, 0);
+		return wait_for_bit_le32(priv->base + MSTPSR(reg),
+					 bitmask, 0, 100, 0);
 	} else {
 		setbits_le32(priv->base + SMSTPCR(reg), bitmask);
 		return 0;
diff --git a/drivers/ddr/microchip/ddr2.c b/drivers/ddr/microchip/ddr2.c
index 6056418588..a52427c3d6 100644
--- a/drivers/ddr/microchip/ddr2.c
+++ b/drivers/ddr/microchip/ddr2.c
@@ -57,8 +57,8 @@ static int ddr2_phy_calib_start(void)
 	writel(SCL_START | SCL_EN, &ddr2_phy->scl_start);
 
 	/* Wait for SCL for data byte to pass */
-	return wait_for_bit(__func__, &ddr2_phy->scl_start, SCL_LUBPASS,
-			    true, CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(&ddr2_phy->scl_start, SCL_LUBPASS,
+				 true, CONFIG_SYS_HZ, false);
 }
 
 /* DDR2 Controller initialization */
@@ -256,8 +256,8 @@ void ddr2_ctrl_init(void)
 	writel(INIT_START, &ctrl->memcon);
 
 	/* wait for all host cmds to be transmitted */
-	wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ctrl->cmdissue, CMD_VALID, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* inform all cmds issued, ready for normal operation */
 	writel(INIT_START | INIT_DONE, &ctrl->memcon);
diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
index 5c1a68a009..d5763965dd 100644
--- a/drivers/fpga/socfpga_arria10.c
+++ b/drivers/fpga/socfpga_arria10.c
@@ -62,8 +62,7 @@ int is_fpgamgr_user_mode(void)
 
 static int wait_for_user_mode(void)
 {
-	return wait_for_bit(__func__,
-		&fpga_manager_base->imgcfg_stat,
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
 		ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK,
 		1, FPGA_TIMEOUT_MSEC, false);
 }
@@ -115,19 +114,17 @@ static int wait_for_nconfig_pin_and_nstatus_pin(void)
 	/* Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted,
 	 * timeout at 1000ms
 	 */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    mask,
-			    false, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		mask,
+		false, FPGA_TIMEOUT_MSEC, false);
 }
 
 static int wait_for_f2s_nstatus_pin(unsigned long value)
 {
 	/* Poll until f2s to specific value, timeout at 1000ms */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
-			    value, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
+		value, FPGA_TIMEOUT_MSEC, false);
 }
 
 /* set CD ratio */
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 9117ab6bf9..f0661bd96c 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -109,15 +109,15 @@ static int msm_sdc_probe(struct udevice *dev)
 
 
 	/* Wait for reset to be written to register */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_STATUS2,
-			 SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_STATUS2,
+			      SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
 		printf("msm_sdhci: reset request failed\n");
 		return -EIO;
 	}
 
 	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_POWER,
-			 SDCC_MCI_POWER_SW_RST, false, 2, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_POWER,
+			      SDCC_MCI_POWER_SW_RST, false, 2, false)) {
 		printf("msm_sdhci: stuck in reset\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c
index e1a8d3bc4b..8bbf2fa9a2 100644
--- a/drivers/mtd/pic32_flash.c
+++ b/drivers/mtd/pic32_flash.c
@@ -66,8 +66,8 @@ static inline void flash_initiate_operation(u32 nvmop)
 
 static int flash_wait_till_busy(const char *func, ulong timeout)
 {
-	int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw,
-			       NVM_WR, false, timeout, false);
+	int ret = wait_for_bit_le32(&nvm_regs_p->ctrl.raw,
+				    NVM_WR, false, timeout, false);
 
 	return ret ? ERR_TIMOUT : ERR_OK;
 }
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index 00e6806892..f28187058e 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -164,8 +164,8 @@ static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
 	writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
 	       regs + AG7XXX_ETH_MII_MGMT_CMD);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 	if (ret)
 		return ret;
 
@@ -185,8 +185,8 @@ static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
 	       regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
 	writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 
 	return ret;
 }
@@ -510,13 +510,13 @@ static void ag7xxx_eth_stop(struct udevice *dev)
 
 	/* Stop the TX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
+			  1000, 0);
 
 	/* Stop the RX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
+			  1000, 0);
 }
 
 /*
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 00076cffbe..232e8034df 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -361,8 +361,9 @@ static void eqos_flush_buffer(void *buf, size_t size)
 
 static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
 {
-	return wait_for_bit(__func__, &eqos->mac_regs->mdio_address,
-			    EQOS_MAC_MDIO_ADDRESS_GB, false, 1000000, true);
+	return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
+				 EQOS_MAC_MDIO_ADDRESS_GB, false,
+				 1000000, true);
 }
 
 static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
@@ -588,15 +589,15 @@ static int eqos_calibrate_pads_tegra186(struct udevice *dev)
 	setbits_le32(&eqos->tegra186_regs->auto_cal_config,
 		     EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE);
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't start");
 		goto failed;
 	}
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't finish");
 		goto failed;
@@ -862,8 +863,8 @@ static int eqos_start(struct udevice *dev)
 
 	eqos->reg_access_ok = true;
 
-	ret = wait_for_bit(__func__, &eqos->dma_regs->mode,
-			   EQOS_DMA_MODE_SWR, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->dma_regs->mode,
+				EQOS_DMA_MODE_SWR, false, 10, false);
 	if (ret) {
 		pr_err("EQOS_DMA_MODE_SWR stuck");
 		goto err_stop_resets;
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a6df950081..51a6c97550 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -548,8 +548,8 @@ static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		u32 data = ethoc_read(priv, MIIRX_DATA);
@@ -571,8 +571,8 @@ static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
 	ethoc_write(priv, MIITX_DATA, val);
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		/* reset MII command register */
diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
index 0b89911f04..7129372790 100644
--- a/drivers/net/pic32_eth.c
+++ b/drivers/net/pic32_eth.c
@@ -64,8 +64,8 @@ static int pic32_mii_init(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* turn controller ON to access PHY over MII */
 	writel(ETHCON_ON, &ectl_p->con1.set);
@@ -239,8 +239,8 @@ static void pic32_ctrl_reset(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 	/* decrement received buffcnt to zero. */
 	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
 		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
@@ -375,8 +375,8 @@ static void pic32_eth_stop(struct udevice *dev)
 	mdelay(10);
 
 	/* wait until everything is down */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     2 * CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  2 * CONFIG_SYS_HZ, false);
 
 	/* clear any existing interrupt event */
 	writel(0xffffffff, &ectl_p->irq.clr);
diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
index 578fc96905..6ae5c40fa3 100644
--- a/drivers/net/pic32_mdio.c
+++ b/drivers/net/pic32_mdio.c
@@ -22,8 +22,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -36,8 +36,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	udelay(12);
 
 	/* Wait for write to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	return 0;
 }
@@ -48,8 +48,8 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -62,9 +62,9 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	udelay(12);
 
 	/* Wait for read to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw,
-		     MIIMIND_NOTVALID | MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&mii_regs->mind.raw,
+			  MIIMIND_NOTVALID | MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* Clear the command register */
 	writel(0, &mii_regs->mcmd.raw);
@@ -82,22 +82,22 @@ static int pic32_mdio_reset(struct mii_dev *bus)
 	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
 		     false, CONFIG_SYS_HZ, true);
 
 	/* Clear reset bit */
 	writel(0, &mii_regs->mcfg);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
 	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 	return 0;
 }
 
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index dc743e113d..26bd915291 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -222,8 +222,8 @@ static int ravb_reset(struct udevice *dev)
 	writel(CCC_OPC_CONFIG, eth->iobase + RAVB_REG_CCC);
 
 	/* Check the operating mode is changed to the config mode. */
-	return wait_for_bit(dev->name, (void *)eth->iobase + RAVB_REG_CSR,
-			    CSR_OPS_CONFIG, true, 100, true);
+	return wait_for_bit_le32(eth->iobase + RAVB_REG_CSR,
+				 CSR_OPS_CONFIG, true, 100, true);
 }
 
 static void ravb_base_desc_init(struct ravb_priv *eth)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 9a2a578ff9..70a2e95a8e 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -366,8 +366,8 @@ static int axi_ethernet_init(struct axidma_priv *priv)
 	 * processor mode and hence bypass in this mode
 	 */
 	if (!priv->eth_hasnobuf) {
-		err = wait_for_bit(__func__, (const u32 *)&regs->is,
-				   XAE_INT_MGTRDY_MASK, true, 200, false);
+		err = wait_for_bit_le32(&regs->is, XAE_INT_MGTRDY_MASK,
+					true, 200, false);
 		if (err) {
 			printf("%s: Timeout\n", __func__);
 			return 1;
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 1dfd631e1a..2cc49bca92 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -192,8 +192,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	struct zynq_gem_regs *regs = priv->iobase;
 	int err;
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -205,8 +205,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	/* Write mgtcr and wait for completion */
 	writel(mgtcr, &regs->phymntnc);
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -514,8 +514,8 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
 	if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
 		printf("TX buffers exhausted in mid frame\n");
 
-	return wait_for_bit(__func__, &regs->txsr, ZYNQ_GEM_TSR_DONE,
-			    true, 20000, true);
+	return wait_for_bit_le32(&regs->txsr, ZYNQ_GEM_TSR_DONE,
+				 true, 20000, true);
 }
 
 /* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c
index 17786f976a..0fc5a28802 100644
--- a/drivers/reset/sti-reset.c
+++ b/drivers/reset/sti-reset.c
@@ -266,8 +266,8 @@ static int sti_reset_program_hw(struct reset_ctl *reset_ctl, int assert)
 		return 0;
 
 	reg = (void __iomem *)base + ch->ack_offset;
-	if (wait_for_bit(__func__, reg, BIT(ch->ack_bit), ctrl_val,
-			 1000, false)) {
+	if (wait_for_bit_le32(reg, BIT(ch->ack_bit), ctrl_val,
+			      1000, false)) {
 		pr_err("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n",
 		      reset_ctl, reset_ctl->dev, reset_ctl->id);
 
diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c
index b0e01aa0e5..0632d26211 100644
--- a/drivers/serial/serial_pic32.c
+++ b/drivers/serial/serial_pic32.c
@@ -51,8 +51,8 @@ static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
 	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
 
 	/* wait for TX FIFO to empty */
-	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
-		     true, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(base + U_STA, UART_TX_EMPTY,
+			  true, CONFIG_SYS_HZ, false);
 
 	/* send break */
 	writel(UART_TX_BRK, base + U_STASET);
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 228e714e09..8010ab434c 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -394,8 +394,8 @@ out:
 		 * Wait until the transfer is completely done before
 		 * we deactivate CS.
 		 */
-		wait_for_bit(__func__, &reg_base->sr,
-			     ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
+		wait_for_bit_le32(&reg_base->sr,
+				  ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
 
 		atmel_spi_cs_deactivate(dev);
 	}
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index e02f2217f4..dca3fdfdea 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -675,8 +675,8 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTRD,
-			   CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD,
+				CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect read completion error (%i)\n", ret);
 		goto failrd;
@@ -762,9 +762,9 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 				bb_txbuf + rounddown(write_bytes, 4),
 				write_bytes % 4);
 
-		ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL,
-				   CQSPI_REG_SDRAMLEVEL_WR_MASK <<
-				   CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
+		ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL,
+					CQSPI_REG_SDRAMLEVEL_WR_MASK <<
+					CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
 		if (ret) {
 			printf("Indirect write timed out (%i)\n", ret);
 			goto failwr;
@@ -775,8 +775,8 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTWR,
-			   CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR,
+				CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect write completion error (%i)\n", ret);
 		goto failwr;
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 2f5345f1cf..5dc69a6865 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -1018,11 +1018,11 @@ static int fsl_qspi_probe(struct udevice *bus)
 	priv->num_chipselect = plat->num_chipselect;
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
@@ -1185,11 +1185,11 @@ static int fsl_qspi_claim_bus(struct udevice *dev)
 	priv = dev_get_priv(bus);
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
index ec4907391c..d1708a8d56 100644
--- a/drivers/spi/mvebu_a3700_spi.c
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -95,8 +95,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 	din_8 = din;
 
 	while (bytelen) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true,100, false);
 		if (ret)
 			return ret;
 
@@ -109,9 +110,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 		writel(pending_dout, &reg->dout);
 
 		if (din) {
-			ret = wait_for_bit(__func__, &reg->ctrl,
-					   MVEBU_SPI_A3700_XFER_RDY,
-					   true, 100, false);
+			ret = wait_for_bit_le32(&reg->ctrl,
+						MVEBU_SPI_A3700_XFER_RDY,
+						true, 100, false);
 			if (ret)
 				return ret;
 
@@ -160,8 +161,9 @@ static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 	/* Deactivate CS */
 	if (flags & SPI_XFER_END) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true, 100, false);
 		if (ret)
 			return ret;
 
@@ -231,8 +233,8 @@ static int mvebu_spi_probe(struct udevice *bus)
 	/* Flush read/write FIFO */
 	data = readl(&reg->cfg);
 	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
-	ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+				false, 1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 1293e18f75..540c016412 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -108,8 +108,8 @@ static void dwc_otg_flush_tx_fifo(struct dwc2_core_regs *regs, const int num)
 
 	writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET),
 	       &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -127,8 +127,8 @@ static void dwc_otg_flush_rx_fifo(struct dwc2_core_regs *regs)
 	int ret;
 
 	writel(DWC2_GRSTCTL_RXFFLSH, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -145,15 +145,15 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs)
 	int ret;
 
 	/* Wait for AHB master IDLE state. */
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
+				true, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
 	/* Core Soft Reset */
 	writel(DWC2_GRSTCTL_CSFTRST, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_CSFTRST,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_CSFTRST,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -267,8 +267,8 @@ static void dwc_otg_core_host_init(struct udevice *dev,
 		clrsetbits_le32(&regs->hc_regs[i].hcchar,
 				DWC2_HCCHAR_EPDIR,
 				DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS);
-		ret = wait_for_bit(__func__, &regs->hc_regs[i].hcchar,
-				   DWC2_HCCHAR_CHEN, false, 1000, false);
+		ret = wait_for_bit_le32(&regs->hc_regs[i].hcchar,
+					DWC2_HCCHAR_CHEN, false, 1000, false);
 		if (ret)
 			printf("%s: Timeout!\n", __func__);
 	}
@@ -783,8 +783,8 @@ int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle)
 	int ret;
 	uint32_t hcint, hctsiz;
 
-	ret = wait_for_bit(__func__, &hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
-			   1000, false);
+	ret = wait_for_bit_le32(&hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
+				1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 2c0c63322c..f5320ca298 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -133,8 +133,7 @@ static int ehci_usb_remove(struct udevice *dev)
 	setbits_le32(&ehci->usbcmd, CMD_RESET);
 
 	/* Wait for reset */
-	if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30,
-			 false)) {
+	if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) {
 		printf("Stuck on USB reset.\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index fe2627ea93..2c8fc3c4b1 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -142,13 +142,12 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci)
 
 	/* Stop then Reset */
 	clrbits_le32(usb_cmd, UCMD_RUN_STOP);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RUN_STOP, false, 10000,
-			   false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false);
 	if (ret)
 		return ret;
 
 	setbits_le32(usb_cmd, UCMD_RESET);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RESET, false, 10000, false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ohci-lpc32xx.c b/drivers/usb/host/ohci-lpc32xx.c
index 2f2b4b90de..44a49807a4 100644
--- a/drivers/usb/host/ohci-lpc32xx.c
+++ b/drivers/usb/host/ohci-lpc32xx.c
@@ -143,8 +143,8 @@ static int usbpll_setup(void)
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_POSTDIV_2POW(0x01));
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_PWRUP);
 
-	ret = wait_for_bit(__func__, &clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
-			   true, CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
+				true, CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -178,8 +178,8 @@ int usb_cpu_init(void)
 
 	/* enable I2C clock */
 	writel(OTG_CLK_I2C_EN, &otg->otg_clk_ctrl);
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -199,8 +199,8 @@ int usb_cpu_init(void)
 			 OTG_CLK_I2C_EN | OTG_CLK_HOST_EN;
 	writel(mask, &otg->otg_clk_ctrl);
 
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, mask, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, mask, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index d47c99644d..71202d7b03 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -55,18 +55,18 @@ static int xhci_rcar_download_fw(struct rcar_xhci *ctx, const u32 *fw_data,
 		setbits_le32(regs + RCAR_USB3_DL_CTRL,
 			     RCAR_USB3_DL_CTRL_FW_SET_DATA0);
 
-		ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-				   RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
-				   10, false);
+		ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+					RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
+					10, false);
 		if (ret)
 			break;
 	}
 
 	clrbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
 
-	ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-			   RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
-			   10, false);
+	ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+				RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
+				10, false);
 
 	return ret;
 }
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index f77da2ec97..c0dd689e7c 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -70,26 +70,26 @@ void lcd_ctrl_init(void *lcdbase)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -215,26 +215,26 @@ void lcd_ctrl_init(void *lcdbase)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -299,26 +299,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -451,26 +451,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 }
diff --git a/include/wait_bit.h b/include/wait_bit.h
index bde6d2cfc3..9f00e54e50 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -16,60 +16,6 @@
 #include <asm/io.h>
 
 /**
- * wait_for_bit()	waits for bit set/cleared in register
- *
- * Function polls register waiting for specific bit(s) change
- * (either 0->1 or 1->0). It can fail under two conditions:
- * - Timeout
- * - User interaction (CTRL-C)
- * Function succeeds only if all bits of masked register are set/cleared
- * (depending on set option).
- *
- * @param prefix	Prefix added to timeout messagge (message visible only
- *			with debug enabled)
- * @param reg		Register that will be read (using readl())
- * @param mask		Bit(s) of register that must be active
- * @param set		Selects wait condition (bit set or clear)
- * @param timeout_ms	Timeout (in miliseconds)
- * @param breakable	Enables CTRL-C interruption
- * @return		0 on success, -ETIMEDOUT or -EINTR on failure
- */
-static inline int wait_for_bit(const char *prefix, const u32 *reg,
-			       const u32 mask, const bool set,
-			       const unsigned int timeout_ms,
-			       const bool breakable)
-{
-	u32 val;
-	unsigned long start = get_timer(0);
-
-	while (1) {
-		val = readl(reg);
-
-		if (!set)
-			val = ~val;
-
-		if ((val & mask) == mask)
-			return 0;
-
-		if (get_timer(start) > timeout_ms)
-			break;
-
-		if (breakable && ctrlc()) {
-			puts("Abort\n");
-			return -EINTR;
-		}
-
-		udelay(1);
-		WATCHDOG_RESET();
-	}
-
-	debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", prefix, reg, mask,
-	      set);
-
-	return -ETIMEDOUT;
-}
-
-/**
  * wait_for_bit_x()	waits for bit set/cleared in register
  *
  * Function polls register waiting for specific bit(s) change
-- 
2.11.0

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

* [U-Boot] [PATCH v9 03/12] drivers: spi: allow limiting reads
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (9 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 51e28bf07b..e40e1c01de 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -516,6 +516,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 08c7480fda..4787454e59 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 
-- 
2.11.0

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

* [U-Boot] [PATCH v9 04/12] drivers: spi: consider command bytes when sending transfers
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e40e1c01de..294d9f9d79 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -405,7 +405,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index 4787454e59..5a7df1c706 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 05/12] dm: spi: add BCM63xx SPI driver
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v9: no changes
 v8: no changes
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Use cmd instead of val to avoid confusions.
 - Switch to wait_for_bit instead of infinite loop.
 v5: Introduce changes suggested by Jagan Teki:
  - Use long structure instead of a custom bmips_spi_hw structure.
  - Define constants for each SPI core.
 v4: Introduce changes suggested by Jagan Teki:
  - Add data for each HW controller instead of having two separate configs.
  - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |   8 +
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 442 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 494639fb01..ebc71c2e42 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,14 @@ config ATMEL_SPI
 	  many AT91 (ARM) chips. This driver can be used to access
 	  the SPI Flash, such as AT25DF321.
 
+config BCM63XX_SPI
+	bool "BCM6348 SPI driver"
+	depends on ARCH_BMIPS
+	help
+	  Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding these Broadcom
+	  SPI cores.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e3184db67f..5770b3f7cc 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,6 +18,7 @@ endif
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000000..f0df6871d8
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* BCM6348 SPI core */
+#define SPI_6348_CLK			0x06
+#define SPI_6348_CMD			0x00
+#define SPI_6348_CTL			0x40
+#define SPI_6348_CTL_SHIFT		6
+#define SPI_6348_FILL			0x07
+#define SPI_6348_IR_MASK		0x04
+#define SPI_6348_IR_STAT		0x02
+#define SPI_6348_RX			0x80
+#define SPI_6348_RX_SIZE		0x3f
+#define SPI_6348_TX			0x41
+#define SPI_6348_TX_SIZE		0x3f
+
+/* BCM6358 SPI core */
+#define SPI_6358_CLK			0x706
+#define SPI_6358_CMD			0x700
+#define SPI_6358_CTL			0x000
+#define SPI_6358_CTL_SHIFT		14
+#define SPI_6358_FILL			0x707
+#define SPI_6358_IR_MASK		0x702
+#define SPI_6358_IR_STAT		0x704
+#define SPI_6358_RX			0x400
+#define SPI_6358_RX_SIZE		0x220
+#define SPI_6358_TX			0x002
+#define SPI_6358_TX_SIZE		0x21e
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Control register */
+#define SPI_CTL_TYPE_FD_RW	0
+#define SPI_CTL_TYPE_HD_W	1
+#define SPI_CTL_TYPE_HD_R	2
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+enum bcm63xx_regs_spi {
+	SPI_CLK,
+	SPI_CMD,
+	SPI_CTL,
+	SPI_CTL_SHIFT,
+	SPI_FILL,
+	SPI_IR_MASK,
+	SPI_IR_STAT,
+	SPI_RX,
+	SPI_RX_SIZE,
+	SPI_TX,
+	SPI_TX_SIZE,
+};
+
+struct bcm63xx_spi_priv {
+	const unsigned long *regs;
+	void __iomem *base;
+	size_t tx_bytes;
+	uint8_t num_cs;
+};
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		printf("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->base + regs[SPI_CLK],
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			printf("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > regs[SPI_RX_SIZE]) {
+			printf("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
+			printf("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val, cmd;
+		int ret;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val = priv->tx_bytes;
+			val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_FD_RW <<
+					regs[SPI_CTL_SHIFT]);
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_HD_R <<
+					regs[SPI_CTL_SHIFT]);
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					printf("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+
+		if (regs[SPI_CTL_SHIFT] >= 8)
+			writew_be(val, priv->base + regs[SPI_CTL]);
+		else
+			writeb_be(val, priv->base + regs[SPI_CTL]);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
+
+		/* issue the transfer */
+		cmd = SPI_CMD_OP_START;
+		cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			cmd |= SPI_CMD_3WIRE_MASK;
+		writew_be(cmd, priv->base + regs[SPI_CMD]);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
+
+		ret = wait_for_bit_8(priv->base + regs[SPI_IR_STAT],
+				     SPI_IR_DONE_MASK, true, 1000, false);
+		if (ret) {
+			printf("interrupt timeout\n");
+			return ret;
+		}
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->base + regs[SPI_RX],
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const unsigned long bcm6348_spi_regs[] = {
+	[SPI_CLK] = SPI_6348_CLK,
+	[SPI_CMD] = SPI_6348_CMD,
+	[SPI_CTL] = SPI_6348_CTL,
+	[SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT,
+	[SPI_FILL] = SPI_6348_FILL,
+	[SPI_IR_MASK] = SPI_6348_IR_MASK,
+	[SPI_IR_STAT] = SPI_6348_IR_STAT,
+	[SPI_RX] = SPI_6348_RX,
+	[SPI_RX_SIZE] = SPI_6348_RX_SIZE,
+	[SPI_TX] = SPI_6348_TX,
+	[SPI_TX_SIZE] = SPI_6348_TX_SIZE,
+};
+
+static const unsigned long bcm6358_spi_regs[] = {
+	[SPI_CLK] = SPI_6358_CLK,
+	[SPI_CMD] = SPI_6358_CMD,
+	[SPI_CTL] = SPI_6358_CTL,
+	[SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT,
+	[SPI_FILL] = SPI_6358_FILL,
+	[SPI_IR_MASK] = SPI_6358_IR_MASK,
+	[SPI_IR_STAT] = SPI_6358_IR_STAT,
+	[SPI_RX] = SPI_6358_RX,
+	[SPI_RX_SIZE] = SPI_6358_RX_SIZE,
+	[SPI_TX] = SPI_6358_TX,
+	[SPI_TX_SIZE] = SPI_6358_TX_SIZE,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-spi",
+		.data = (ulong)&bcm6348_spi_regs,
+	}, {
+		.compatible = "brcm,bcm6358-spi",
+		.data = (ulong)&bcm6358_spi_regs,
+	}, { /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		printf("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = regs[SPI_RX_SIZE];
+	slave->max_write_size = regs[SPI_TX_SIZE];
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	const unsigned long *regs =
+		(const unsigned long *)dev_get_driver_data(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = regs;
+	priv->base = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_free(&clk);
+	if (ret < 0)
+		return ret;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_free(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	/* initialize hardware */
+	writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+
+	/* set fill register */
+	writeb_be(0xff, priv->base + regs[SPI_FILL]);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v9 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a4372b..0cab44cb8d 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v9 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643b5a..540b9fea5b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v9 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf80e0..1662783279 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v9 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb048..f83a6ea8df 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v9 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96bef8..6e3d9c3820 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.11.0

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

* [U-Boot] [PATCH v9 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (9 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  2018-01-22  5:07   ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Jagan Teki
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: Introduce changes suggested by Simon Glass:
  - Fix defconfig order.
 v8: no changes
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5551..dd0e5b8b7c 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index cfc56cba37..07a125cec6 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -26,6 +26,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_MISC is not set
@@ -34,8 +36,14 @@ CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_BCM63XX_SPI=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (10 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2018-01-20  1:11   ` Álvaro Fernández Rojas
  2018-01-22  5:07   ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Jagan Teki
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-20  1:11 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: Introduce changes suggested by Simon Glass:
  - Fix defconfig order.
 v8: no changes
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7616..5f85c7346f 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index 7665c78d3f..fb998f03bf 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -25,6 +25,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_MISC is not set
@@ -35,9 +37,15 @@ CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_BCM63XX_SPI=y
 CONFIG_WDT_BCM6345=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
                     ` (11 preceding siblings ...)
  2018-01-20  1:11   ` [U-Boot] [PATCH v9 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
@ 2018-01-22  5:07   ` Jagan Teki
  12 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-22  5:07 UTC (permalink / raw)
  To: u-boot

On Sat, Jan 20, 2018 at 6:41 AM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
> active between transfers, so I had to modify the spi_flash driver in order
> to allow limiting reads.
>
> v9: Introduce changes suggested by Simon Glass:
> - Fix defconfig order.
> v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
> - Squash wait_bit commits.
> - Remove register param castings.
> v7: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
> - Use const void* reg for compatibility with 64 bit systems.
> - Remove prefix and use __func__ instead.
> - Remove wait_for_bit and update callers to wait_for_bit_le32.
> v6: Introduce changes suggested by Jagan Teki:
> - Use cmd instead of val to avoid confusions.
> - Switch to wait_for_bit instead of infinite loop.
> v5: Introduce changes suggested by Jagan Teki:
> - Use long structs for registers
> v4: Introduce changes suggested by Jagan Teki:
> - Add data for each HW controller instead of having two separate configs.
> v3: Fix bug introduced in v2: sizeof(cmd) vs len.
> Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
> down version of the BCM6348.
> Switch to devfdt_get_addr_size_index().
> v2: Introduce changes requested by Simon Glass:
> - Always include command bytes when determining max write size.
> Also move SPI aliases from .dts to .dtsi files.
>
> Álvaro Fernández Rojas (12):
>   wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
>   wait_bit: use wait_for_bit_le32 and remove wait_for_bit
>   drivers: spi: allow limiting reads
>   drivers: spi: consider command bytes when sending transfers
>   dm: spi: add BCM63xx SPI driver
>   mips: bmips: add bcm63xx-spi driver support for BCM6338
>   mips: bmips: add bcm63xx-spi driver support for BCM6348
>   mips: bmips: add bcm63xx-spi driver support for BCM6358
>   mips: bmips: add bcm63xx-spi driver support for BCM3380
>   mips: bmips: add bcm63xx-spi driver support for BCM63268
>   mips: bmips: enable the SPI flash on the Sagem F at ST1704
>   mips: bmips: enable the SPI flash on the Netgear CG3100D

Applied to u-boot-spi/master, thanks!

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

* [U-Boot] [PATCH v10 00/12] mips: bmips: add SPI support
  2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
                   ` (16 preceding siblings ...)
  2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
@ 2018-01-23 16:14 ` Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
                     ` (12 more replies)
  17 siblings, 13 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:14 UTC (permalink / raw)
  To: u-boot

BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
active between transfers, so I had to modify the spi_flash driver in order
to allow limiting reads.

v10: Introduce changes reported by Tom Rini & Daniel Schwierzeck:
- Fix undefined BE read functions
v9: Introduce changes suggested by Simon Glass:
- Fix defconfig order.
v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
- Squash wait_bit commits.
- Remove register param castings.
v7: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
- Use const void* reg for compatibility with 64 bit systems.
- Remove prefix and use __func__ instead.
- Remove wait_for_bit and update callers to wait_for_bit_le32.
v6: Introduce changes suggested by Jagan Teki:
- Use cmd instead of val to avoid confusions.
- Switch to wait_for_bit instead of infinite loop.
v5: Introduce changes suggested by Jagan Teki:
- Use long structs for registers
v4: Introduce changes suggested by Jagan Teki:
- Add data for each HW controller instead of having two separate configs.
v3: Fix bug introduced in v2: sizeof(cmd) vs len.
Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
down version of the BCM6348.
Switch to devfdt_get_addr_size_index().
v2: Introduce changes requested by Simon Glass:
- Always include command bytes when determining max write size.
Also move SPI aliases from .dts to .dtsi files.

Álvaro Fernández Rojas (12):
  wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  wait_bit: use wait_for_bit_le32 and remove wait_for_bit
  drivers: spi: allow limiting reads
  drivers: spi: consider command bytes when sending transfers
  dm: spi: add BCM63xx SPI driver
  mips: bmips: add bcm63xx-spi driver support for BCM6338
  mips: bmips: add bcm63xx-spi driver support for BCM6348
  mips: bmips: add bcm63xx-spi driver support for BCM6358
  mips: bmips: add bcm63xx-spi driver support for BCM3380
  mips: bmips: add bcm63xx-spi driver support for BCM63268
  mips: bmips: enable the SPI flash on the Sagem F at ST1704
  mips: bmips: enable the SPI flash on the Netgear CG3100D

 arch/arm/mach-imx/mx6/ddr.c                   |  22 +-
 arch/arm/mach-socfpga/clock_manager.c         |   4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |   6 +-
 arch/arm/mach-socfpga/reset_manager_arria10.c |  36 +--
 arch/mips/dts/brcm,bcm3380.dtsi               |  17 +
 arch/mips/dts/brcm,bcm63268.dtsi              |  17 +
 arch/mips/dts/brcm,bcm6338.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6348.dtsi               |  17 +
 arch/mips/dts/brcm,bcm6358.dtsi               |  17 +
 arch/mips/dts/netgear,cg3100d.dts             |  12 +
 arch/mips/dts/sagem,f at st1704.dts              |  12 +
 arch/mips/mach-ath79/ar934x/clk.c             |   2 +-
 board/samtec/vining_2000/vining_2000.c        |   4 +-
 configs/netgear_cg3100d_ram_defconfig         |   8 +
 configs/sagem_f at st1704_ram_defconfig          |   8 +
 drivers/clk/clk_pic32.c                       |  12 +-
 drivers/clk/renesas/clk-rcar-gen3.c           |   4 +-
 drivers/ddr/microchip/ddr2.c                  |   8 +-
 drivers/fpga/socfpga_arria10.c                |  17 +-
 drivers/mmc/msm_sdhci.c                       |   8 +-
 drivers/mtd/pic32_flash.c                     |   4 +-
 drivers/mtd/spi/spi_flash.c                   |   5 +-
 drivers/net/ag7xxx.c                          |  16 +-
 drivers/net/dwc_eth_qos.c                     |  17 +-
 drivers/net/ethoc.c                           |   8 +-
 drivers/net/pic32_eth.c                       |  12 +-
 drivers/net/pic32_mdio.c                      |  28 +-
 drivers/net/ravb.c                            |   4 +-
 drivers/net/xilinx_axi_emac.c                 |   4 +-
 drivers/net/zynq_gem.c                        |  12 +-
 drivers/reset/sti-reset.c                     |   4 +-
 drivers/serial/serial_pic32.c                 |   4 +-
 drivers/spi/Kconfig                           |   8 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/atmel_spi.c                       |   4 +-
 drivers/spi/bcm63xx_spi.c                     | 433 ++++++++++++++++++++++++++
 drivers/spi/cadence_qspi_apb.c                |  14 +-
 drivers/spi/fsl_qspi.c                        |  20 +-
 drivers/spi/mvebu_a3700_spi.c                 |  20 +-
 drivers/usb/host/dwc2.c                       |  24 +-
 drivers/usb/host/ehci-msm.c                   |   3 +-
 drivers/usb/host/ehci-mx6.c                   |   5 +-
 drivers/usb/host/ohci-lpc32xx.c               |  12 +-
 drivers/usb/host/xhci-rcar.c                  |  12 +-
 drivers/video/atmel_hlcdfb.c                  |  64 ++--
 include/spi.h                                 |   5 +-
 include/wait_bit.h                            |  85 ++---
 47 files changed, 828 insertions(+), 248 deletions(-)
 create mode 100644 drivers/spi/bcm63xx_spi.c

-- 
2.11.0

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

* [U-Boot] [PATCH v10 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
@ 2018-01-23 16:14   ` Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:14 UTC (permalink / raw)
  To: u-boot

Add 8/16/32 bits and BE/LE versions of wait_for_bit.
This is needed for reading registers that are not aligned to 32 bits, and for
Big Endian platforms.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v10: Introduce changes reported by Tom Rini & Daniel Schwierzeck:
 - Fix undefined BE read functions
 v9: no changes.
 v8: no changes.
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Use const void* reg for compatibility with 64 bit systems.
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Switch to wait_for_bit instead of infinite loop.

 include/wait_bit.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/include/wait_bit.h b/include/wait_bit.h
index 06ad43a122..e8acfa5776 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -69,5 +69,70 @@ static inline int wait_for_bit(const char *prefix, const u32 *reg,
 	return -ETIMEDOUT;
 }
 
+/**
+ * wait_for_bit_x()	waits for bit set/cleared in register
+ *
+ * Function polls register waiting for specific bit(s) change
+ * (either 0->1 or 1->0). It can fail under two conditions:
+ * - Timeout
+ * - User interaction (CTRL-C)
+ * Function succeeds only if all bits of masked register are set/cleared
+ * (depending on set option).
+ *
+ * @param reg		Register that will be read (using read_x())
+ * @param mask		Bit(s) of register that must be active
+ * @param set		Selects wait condition (bit set or clear)
+ * @param timeout_ms	Timeout (in milliseconds)
+ * @param breakable	Enables CTRL-C interruption
+ * @return		0 on success, -ETIMEDOUT or -EINTR on failure
+ */
+
+#define BUILD_WAIT_FOR_BIT(sfx, type, read)				\
+									\
+static inline int wait_for_bit_##sfx(const void *reg,			\
+				     const type mask,			\
+				     const bool set,			\
+				     const unsigned int timeout_ms,	\
+				     const bool breakable)		\
+{									\
+	type val;							\
+	unsigned long start = get_timer(0);				\
+									\
+	while (1) {							\
+		val = read(reg);					\
+									\
+		if (!set)						\
+			val = ~val;					\
+									\
+		if ((val & mask) == mask)				\
+			return 0;					\
+									\
+		if (get_timer(start) > timeout_ms)			\
+			break;						\
+									\
+		if (breakable && ctrlc()) {				\
+			puts("Abort\n");				\
+			return -EINTR;					\
+		}							\
+									\
+		udelay(1);						\
+		WATCHDOG_RESET();					\
+	}								\
+									\
+	debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__,	\
+	      reg, mask, set);						\
+									\
+	return -ETIMEDOUT;						\
+}
+
+BUILD_WAIT_FOR_BIT(8, u8, readb)
+BUILD_WAIT_FOR_BIT(le16, u16, readw)
+#ifdef readw_be
+BUILD_WAIT_FOR_BIT(be16, u16, readw_be)
+#endif
+BUILD_WAIT_FOR_BIT(le32, u32, readl)
+#ifdef readl_be
+BUILD_WAIT_FOR_BIT(be32, u32, readl_be)
+#endif
 
 #endif
-- 
2.11.0

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

* [U-Boot] [PATCH v10 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
@ 2018-01-23 16:14   ` Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:14 UTC (permalink / raw)
  To: u-boot

wait_for_bit callers use the 32 bit LE version

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v10: no changes
 v9: no changes
 v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
 - Squash wait_bit commits.
 - Remove register param castings.
 v7: Introduce changes suggested by Jagan Teki:
 - Remove wait_for_bit and update callers to wait_for_bit_le32.

 arch/arm/mach-imx/mx6/ddr.c                   | 22 ++++-----
 arch/arm/mach-socfpga/clock_manager.c         |  4 +-
 arch/arm/mach-socfpga/clock_manager_gen5.c    |  6 +--
 arch/arm/mach-socfpga/reset_manager_arria10.c | 36 +++++++--------
 arch/mips/mach-ath79/ar934x/clk.c             |  2 +-
 board/samtec/vining_2000/vining_2000.c        |  4 +-
 drivers/clk/clk_pic32.c                       | 12 ++---
 drivers/clk/renesas/clk-rcar-gen3.c           |  4 +-
 drivers/ddr/microchip/ddr2.c                  |  8 ++--
 drivers/fpga/socfpga_arria10.c                | 17 +++----
 drivers/mmc/msm_sdhci.c                       |  8 ++--
 drivers/mtd/pic32_flash.c                     |  4 +-
 drivers/net/ag7xxx.c                          | 16 +++----
 drivers/net/dwc_eth_qos.c                     | 17 +++----
 drivers/net/ethoc.c                           |  8 ++--
 drivers/net/pic32_eth.c                       | 12 ++---
 drivers/net/pic32_mdio.c                      | 28 ++++++------
 drivers/net/ravb.c                            |  4 +-
 drivers/net/xilinx_axi_emac.c                 |  4 +-
 drivers/net/zynq_gem.c                        | 12 ++---
 drivers/reset/sti-reset.c                     |  4 +-
 drivers/serial/serial_pic32.c                 |  4 +-
 drivers/spi/atmel_spi.c                       |  4 +-
 drivers/spi/cadence_qspi_apb.c                | 14 +++---
 drivers/spi/fsl_qspi.c                        | 20 ++++-----
 drivers/spi/mvebu_a3700_spi.c                 | 20 +++++----
 drivers/usb/host/dwc2.c                       | 24 +++++-----
 drivers/usb/host/ehci-msm.c                   |  3 +-
 drivers/usb/host/ehci-mx6.c                   |  5 +--
 drivers/usb/host/ohci-lpc32xx.c               | 12 ++---
 drivers/usb/host/xhci-rcar.c                  | 12 ++---
 drivers/video/atmel_hlcdfb.c                  | 64 +++++++++++++--------------
 include/wait_bit.h                            | 54 ----------------------
 33 files changed, 205 insertions(+), 263 deletions(-)

diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index 39dbd2f607..43b77cfa41 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -21,10 +21,10 @@ static void reset_read_data_fifos(void)
 
 	/* Reset data FIFOs twice. */
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 
 	setbits_le32(&mmdc0->mpdgctrl0, 1 << 31);
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 31, 0, 100, 0);
 }
 
 static void precharge_all(const bool cs0_enable, const bool cs1_enable)
@@ -39,12 +39,12 @@ static void precharge_all(const bool cs0_enable, const bool cs1_enable)
 	 */
 	if (cs0_enable) { /* CS0 */
 		writel(0x04008050, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 
 	if (cs1_enable) { /* CS1 */
 		writel(0x04008058, &mmdc0->mdscr);
-		wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+		wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 	}
 }
 
@@ -146,7 +146,7 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * 7. Upon completion of this process the MMDC de-asserts
 	 * the MPWLGCR[HW_WL_EN]
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwlgcr, 1 << 0, 0, 100, 0);
 
 	/*
 	 * 8. check for any errors: check both PHYs for x64 configuration,
@@ -278,7 +278,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 		writel(0x00008028, &mmdc0->mdscr);
 
 	/* poll to make sure the con_ack bit was asserted */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 1, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 1, 100, 0);
 
 	/*
 	 * Check MDMISC register CALIB_PER_CS to see which CS calibration
@@ -312,7 +312,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * this bit until it clears to indicate completion of the write access.
 	 */
 	setbits_le32(&mmdc0->mpswdar0, 1);
-	wait_for_bit("MMDC", &mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpswdar0, 1 << 0, 0, 100, 0);
 
 	/* Set the RD_DL_ABS# bits to their default values
 	 * (will be calibrated later in the read delay-line calibration).
@@ -359,7 +359,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	setbits_le32(&mmdc0->mpdgctrl0, 5 << 28);
 
 	/* Poll for completion.  MPDGCTRL0[HW_DG_EN] should be 0 */
-	wait_for_bit("MMDC", &mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpdgctrl0, 1 << 28, 0, 100, 0);
 
 	/*
 	 * Check to see if any errors were encountered during calibration
@@ -423,7 +423,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * setting MPRDDLHWCTL[HW_RD_DL_EN] = 0.   Also, ensure that
 	 * no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mprddlhwctl, 1 << 4, 0, 100, 0);
 
 	/* check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mprddlhwctl) & 0x0000000f)
@@ -477,7 +477,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	 * by setting MPWRDLHWCTL[HW_WR_DL_EN] = 0.
 	 * Also, ensure that no error bits were set.
 	 */
-	wait_for_bit("MMDC", &mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mpwrdlhwctl, 1 << 4, 0, 100, 0);
 
 	/* Check both PHYs for x64 configuration, if x32, check only PHY0 */
 	if (readl(&mmdc0->mpwrdlhwctl) & 0x0000000f)
@@ -526,7 +526,7 @@ int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	writel(0x0, &mmdc0->mdscr);	/* CS0 */
 
 	/* Poll to make sure the con_ack bit is clear */
-	wait_for_bit("MMDC", &mmdc0->mdscr, 1 << 14, 0, 100, 0);
+	wait_for_bit_le32(&mmdc0->mdscr, 1 << 14, 0, 100, 0);
 
 	/*
 	 * Print out the registers that were updated as a result
diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c
index 6b76221025..43e72a8b55 100644
--- a/arch/arm/mach-socfpga/clock_manager.c
+++ b/arch/arm/mach-socfpga/clock_manager.c
@@ -37,8 +37,8 @@ void cm_wait_for_lock(u32 mask)
 /* function to poll in the fsm busy bit */
 int cm_wait_for_fsm(void)
 {
-	return wait_for_bit(__func__, (const u32 *)&clock_manager_base->stat,
-			    CLKMGR_STAT_BUSY, false, 20000, false);
+	return wait_for_bit_le32(&clock_manager_base->stat,
+				 CLKMGR_STAT_BUSY, false, 20000, false);
 }
 
 int set_cpu_clk_info(void)
diff --git a/arch/arm/mach-socfpga/clock_manager_gen5.c b/arch/arm/mach-socfpga/clock_manager_gen5.c
index 31fd51097a..a23f3fc5d0 100644
--- a/arch/arm/mach-socfpga/clock_manager_gen5.c
+++ b/arch/arm/mach-socfpga/clock_manager_gen5.c
@@ -37,15 +37,13 @@ static int cm_write_with_phase(u32 value, u32 reg_address, u32 mask)
 	int ret;
 
 	/* poll until phase is zero */
-	ret = wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			   false, 20000, false);
+	ret = wait_for_bit_le32(reg_address, mask, false, 20000, false);
 	if (ret)
 		return ret;
 
 	writel(value, reg_address);
 
-	return wait_for_bit(__func__, (const u32 *)reg_address, mask,
-			    false, 20000, false);
+	return wait_for_bit_le32(reg_address, mask, false, 20000, false);
 }
 
 /*
diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c
index ae16897494..54f0ddb255 100644
--- a/arch/arm/mach-socfpga/reset_manager_arria10.c
+++ b/arch/arm/mach-socfpga/reset_manager_arria10.c
@@ -222,8 +222,8 @@ int socfpga_reset_deassert_bridges_handoff(void)
 	clrbits_le32(&reset_manager_base->brgmodrst, mask_rstmgr);
 
 	/* Poll until all idleack to 0, timeout at 1000ms */
-	return wait_for_bit(__func__, &sysmgr_regs->noc_idleack, mask_noc,
-			    false, 1000, false);
+	return wait_for_bit_le32(&sysmgr_regs->noc_idleack, mask_noc,
+				 false, 1000, false);
 }
 
 void socfpga_reset_assert_fpga_connected_peripherals(void)
@@ -343,26 +343,26 @@ int socfpga_bridges_reset(void)
 	writel(ALT_SYSMGR_NOC_TMO_EN_SET_MSK, &sysmgr_regs->noc_timeout);
 
 	/* Poll until all idleack to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idleack,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idleack,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
 	/* Poll until all idlestatus to 1 */
-	ret = wait_for_bit(__func__, &sysmgr_regs->noc_idlestatus,
-		     ALT_SYSMGR_NOC_H2F_SET_MSK |
-		     ALT_SYSMGR_NOC_LWH2F_SET_MSK |
-		     ALT_SYSMGR_NOC_F2H_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
-		     ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
-		     true, 10000, false);
+	ret = wait_for_bit_le32(&sysmgr_regs->noc_idlestatus,
+				ALT_SYSMGR_NOC_H2F_SET_MSK |
+				ALT_SYSMGR_NOC_LWH2F_SET_MSK |
+				ALT_SYSMGR_NOC_F2H_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR0_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR1_SET_MSK |
+				ALT_SYSMGR_NOC_F2SDR2_SET_MSK,
+				true, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/arch/mips/mach-ath79/ar934x/clk.c b/arch/mips/mach-ath79/ar934x/clk.c
index 9b41d3de60..ba2243c9be 100644
--- a/arch/mips/mach-ath79/ar934x/clk.c
+++ b/arch/mips/mach-ath79/ar934x/clk.c
@@ -90,7 +90,7 @@ static void ar934x_srif_pll_cfg(void __iomem *pll_reg_base, const u32 srif_val)
 		setbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
 
-		wait_for_bit("clk", pll_reg_base + 0xc, BIT(3), 1, 10, 0);
+		wait_for_bit_le32(pll_reg_base + 0xc, BIT(3), 1, 10, 0);
 
 		clrbits_be32(pll_reg_base + 0x8, BIT(30));
 		udelay(5);
diff --git a/board/samtec/vining_2000/vining_2000.c b/board/samtec/vining_2000/vining_2000.c
index af1a3e75cb..cced08b8b8 100644
--- a/board/samtec/vining_2000/vining_2000.c
+++ b/board/samtec/vining_2000/vining_2000.c
@@ -378,7 +378,7 @@ static int read_adc(u32 *val)
 
 	/* start auto calibration */
 	setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
-	ret = wait_for_bit("ADC", b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
 	if (ret)
 		goto adc_exit;
 
@@ -386,7 +386,7 @@ static int read_adc(u32 *val)
 	writel(0, b + ADCx_HC0);
 
 	/* wait for conversion */
-	ret = wait_for_bit("ADC", b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
+	ret = wait_for_bit_le32(b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
 	if (ret)
 		goto adc_exit;
 
diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
index f6eef314ec..177803943d 100644
--- a/drivers/clk/clk_pic32.c
+++ b/drivers/clk/clk_pic32.c
@@ -197,8 +197,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_ON | REFO_OE, reg + _CLR_OFFSET);
 
 	/* wait till previous src change is active */
-	wait_for_bit(__func__, reg, REFO_DIVSW_EN | REFO_ACTIVE,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(reg, REFO_DIVSW_EN | REFO_ACTIVE,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* parent_id */
 	v = readl(reg);
@@ -223,8 +223,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph,
 	writel(REFO_DIVSW_EN, reg + _SET_OFFSET);
 
 	/* wait for divider switching to complete */
-	return wait_for_bit(__func__, reg, REFO_DIVSW_EN, false,
-			    CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(reg, REFO_DIVSW_EN, false,
+				 CONFIG_SYS_HZ, false);
 }
 
 static ulong pic32_get_refclk(struct pic32_clk_priv *priv, int periph)
@@ -311,8 +311,8 @@ static int pic32_mpll_init(struct pic32_clk_priv *priv)
 
 	/* Wait for ready */
 	mask = MPLL_RDY | MPLL_VREG_RDY;
-	return wait_for_bit(__func__, priv->syscfg_base + CFGMPLL, mask,
-			    true, get_tbclk(), false);
+	return wait_for_bit_le32(priv->syscfg_base + CFGMPLL, mask,
+				 true, get_tbclk(), false);
 }
 
 static void pic32_clk_init(struct udevice *dev)
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index b26bbcc59f..22828fd470 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -1046,8 +1046,8 @@ static int gen3_clk_endisable(struct clk *clk, bool enable)
 		if (ret)
 			return ret;
 		clrbits_le32(priv->base + SMSTPCR(reg), bitmask);
-		return wait_for_bit("MSTP", priv->base + MSTPSR(reg),
-				    bitmask, 0, 100, 0);
+		return wait_for_bit_le32(priv->base + MSTPSR(reg),
+					 bitmask, 0, 100, 0);
 	} else {
 		setbits_le32(priv->base + SMSTPCR(reg), bitmask);
 		return 0;
diff --git a/drivers/ddr/microchip/ddr2.c b/drivers/ddr/microchip/ddr2.c
index 6056418588..a52427c3d6 100644
--- a/drivers/ddr/microchip/ddr2.c
+++ b/drivers/ddr/microchip/ddr2.c
@@ -57,8 +57,8 @@ static int ddr2_phy_calib_start(void)
 	writel(SCL_START | SCL_EN, &ddr2_phy->scl_start);
 
 	/* Wait for SCL for data byte to pass */
-	return wait_for_bit(__func__, &ddr2_phy->scl_start, SCL_LUBPASS,
-			    true, CONFIG_SYS_HZ, false);
+	return wait_for_bit_le32(&ddr2_phy->scl_start, SCL_LUBPASS,
+				 true, CONFIG_SYS_HZ, false);
 }
 
 /* DDR2 Controller initialization */
@@ -256,8 +256,8 @@ void ddr2_ctrl_init(void)
 	writel(INIT_START, &ctrl->memcon);
 
 	/* wait for all host cmds to be transmitted */
-	wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ctrl->cmdissue, CMD_VALID, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* inform all cmds issued, ready for normal operation */
 	writel(INIT_START | INIT_DONE, &ctrl->memcon);
diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
index 5c1a68a009..d5763965dd 100644
--- a/drivers/fpga/socfpga_arria10.c
+++ b/drivers/fpga/socfpga_arria10.c
@@ -62,8 +62,7 @@ int is_fpgamgr_user_mode(void)
 
 static int wait_for_user_mode(void)
 {
-	return wait_for_bit(__func__,
-		&fpga_manager_base->imgcfg_stat,
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
 		ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK,
 		1, FPGA_TIMEOUT_MSEC, false);
 }
@@ -115,19 +114,17 @@ static int wait_for_nconfig_pin_and_nstatus_pin(void)
 	/* Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted,
 	 * timeout at 1000ms
 	 */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    mask,
-			    false, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		mask,
+		false, FPGA_TIMEOUT_MSEC, false);
 }
 
 static int wait_for_f2s_nstatus_pin(unsigned long value)
 {
 	/* Poll until f2s to specific value, timeout at 1000ms */
-	return wait_for_bit(__func__,
-			    &fpga_manager_base->imgcfg_stat,
-			    ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
-			    value, FPGA_TIMEOUT_MSEC, false);
+	return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat,
+		ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK,
+		value, FPGA_TIMEOUT_MSEC, false);
 }
 
 /* set CD ratio */
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 9117ab6bf9..f0661bd96c 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -109,15 +109,15 @@ static int msm_sdc_probe(struct udevice *dev)
 
 
 	/* Wait for reset to be written to register */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_STATUS2,
-			 SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_STATUS2,
+			      SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
 		printf("msm_sdhci: reset request failed\n");
 		return -EIO;
 	}
 
 	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
-	if (wait_for_bit(__func__, prv->base + SDCC_MCI_POWER,
-			 SDCC_MCI_POWER_SW_RST, false, 2, false)) {
+	if (wait_for_bit_le32(prv->base + SDCC_MCI_POWER,
+			      SDCC_MCI_POWER_SW_RST, false, 2, false)) {
 		printf("msm_sdhci: stuck in reset\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c
index e1a8d3bc4b..8bbf2fa9a2 100644
--- a/drivers/mtd/pic32_flash.c
+++ b/drivers/mtd/pic32_flash.c
@@ -66,8 +66,8 @@ static inline void flash_initiate_operation(u32 nvmop)
 
 static int flash_wait_till_busy(const char *func, ulong timeout)
 {
-	int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw,
-			       NVM_WR, false, timeout, false);
+	int ret = wait_for_bit_le32(&nvm_regs_p->ctrl.raw,
+				    NVM_WR, false, timeout, false);
 
 	return ret ? ERR_TIMOUT : ERR_OK;
 }
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index 00e6806892..f28187058e 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -164,8 +164,8 @@ static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
 	writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
 	       regs + AG7XXX_ETH_MII_MGMT_CMD);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 	if (ret)
 		return ret;
 
@@ -185,8 +185,8 @@ static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
 	       regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
 	writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
 
-	ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
-			   AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
+	ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND,
+				AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
 
 	return ret;
 }
@@ -510,13 +510,13 @@ static void ag7xxx_eth_stop(struct udevice *dev)
 
 	/* Stop the TX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
+			  1000, 0);
 
 	/* Stop the RX DMA. */
 	writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
-	wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
-		     1000, 0);
+	wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
+			  1000, 0);
 }
 
 /*
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 00076cffbe..232e8034df 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -361,8 +361,9 @@ static void eqos_flush_buffer(void *buf, size_t size)
 
 static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
 {
-	return wait_for_bit(__func__, &eqos->mac_regs->mdio_address,
-			    EQOS_MAC_MDIO_ADDRESS_GB, false, 1000000, true);
+	return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
+				 EQOS_MAC_MDIO_ADDRESS_GB, false,
+				 1000000, true);
 }
 
 static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
@@ -588,15 +589,15 @@ static int eqos_calibrate_pads_tegra186(struct udevice *dev)
 	setbits_le32(&eqos->tegra186_regs->auto_cal_config,
 		     EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE);
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't start");
 		goto failed;
 	}
 
-	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
-			   EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status,
+				EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
 	if (ret) {
 		pr_err("calibrate didn't finish");
 		goto failed;
@@ -862,8 +863,8 @@ static int eqos_start(struct udevice *dev)
 
 	eqos->reg_access_ok = true;
 
-	ret = wait_for_bit(__func__, &eqos->dma_regs->mode,
-			   EQOS_DMA_MODE_SWR, false, 10, false);
+	ret = wait_for_bit_le32(&eqos->dma_regs->mode,
+				EQOS_DMA_MODE_SWR, false, 10, false);
 	if (ret) {
 		pr_err("EQOS_DMA_MODE_SWR stuck");
 		goto err_stop_resets;
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a6df950081..51a6c97550 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -548,8 +548,8 @@ static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		u32 data = ethoc_read(priv, MIIRX_DATA);
@@ -571,8 +571,8 @@ static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
 	ethoc_write(priv, MIITX_DATA, val);
 	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
 
-	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
-			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+	rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS),
+			       MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
 
 	if (rc == 0) {
 		/* reset MII command register */
diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
index 0b89911f04..7129372790 100644
--- a/drivers/net/pic32_eth.c
+++ b/drivers/net/pic32_eth.c
@@ -64,8 +64,8 @@ static int pic32_mii_init(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 
 	/* turn controller ON to access PHY over MII */
 	writel(ETHCON_ON, &ectl_p->con1.set);
@@ -239,8 +239,8 @@ static void pic32_ctrl_reset(struct pic32eth_dev *priv)
 	writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 
 	/* wait till busy */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  CONFIG_SYS_HZ, false);
 	/* decrement received buffcnt to zero. */
 	while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
 		writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
@@ -375,8 +375,8 @@ static void pic32_eth_stop(struct udevice *dev)
 	mdelay(10);
 
 	/* wait until everything is down */
-	wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false,
-		     2 * CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
+			  2 * CONFIG_SYS_HZ, false);
 
 	/* clear any existing interrupt event */
 	writel(0xffffffff, &ectl_p->irq.clr);
diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c
index 578fc96905..6ae5c40fa3 100644
--- a/drivers/net/pic32_mdio.c
+++ b/drivers/net/pic32_mdio.c
@@ -22,8 +22,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -36,8 +36,8 @@ static int pic32_mdio_write(struct mii_dev *bus,
 	udelay(12);
 
 	/* Wait for write to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	return 0;
 }
@@ -48,8 +48,8 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	struct pic32_mii_regs *mii_regs = bus->priv;
 
 	/* Wait for the previous operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Put phyaddr and regaddr into MIIMADD */
 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
@@ -62,9 +62,9 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
 	udelay(12);
 
 	/* Wait for read to complete */
-	wait_for_bit(__func__, &mii_regs->mind.raw,
-		     MIIMIND_NOTVALID | MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(&mii_regs->mind.raw,
+			  MIIMIND_NOTVALID | MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, false);
 
 	/* Clear the command register */
 	writel(0, &mii_regs->mcmd.raw);
@@ -82,22 +82,22 @@ static int pic32_mdio_reset(struct mii_dev *bus)
 	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
 		     false, CONFIG_SYS_HZ, true);
 
 	/* Clear reset bit */
 	writel(0, &mii_regs->mcfg);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 
 	/* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
 	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
 
 	/* Wait for the operation to finish */
-	wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
-		     false, CONFIG_SYS_HZ, true);
+	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
+			  false, CONFIG_SYS_HZ, true);
 	return 0;
 }
 
diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c
index dc743e113d..26bd915291 100644
--- a/drivers/net/ravb.c
+++ b/drivers/net/ravb.c
@@ -222,8 +222,8 @@ static int ravb_reset(struct udevice *dev)
 	writel(CCC_OPC_CONFIG, eth->iobase + RAVB_REG_CCC);
 
 	/* Check the operating mode is changed to the config mode. */
-	return wait_for_bit(dev->name, (void *)eth->iobase + RAVB_REG_CSR,
-			    CSR_OPS_CONFIG, true, 100, true);
+	return wait_for_bit_le32(eth->iobase + RAVB_REG_CSR,
+				 CSR_OPS_CONFIG, true, 100, true);
 }
 
 static void ravb_base_desc_init(struct ravb_priv *eth)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 9a2a578ff9..70a2e95a8e 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -366,8 +366,8 @@ static int axi_ethernet_init(struct axidma_priv *priv)
 	 * processor mode and hence bypass in this mode
 	 */
 	if (!priv->eth_hasnobuf) {
-		err = wait_for_bit(__func__, (const u32 *)&regs->is,
-				   XAE_INT_MGTRDY_MASK, true, 200, false);
+		err = wait_for_bit_le32(&regs->is, XAE_INT_MGTRDY_MASK,
+					true, 200, false);
 		if (err) {
 			printf("%s: Timeout\n", __func__);
 			return 1;
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 1dfd631e1a..2cc49bca92 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -192,8 +192,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	struct zynq_gem_regs *regs = priv->iobase;
 	int err;
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -205,8 +205,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
 	/* Write mgtcr and wait for completion */
 	writel(mgtcr, &regs->phymntnc);
 
-	err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
-			    true, 20000, false);
+	err = wait_for_bit_le32(&regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+				true, 20000, false);
 	if (err)
 		return err;
 
@@ -514,8 +514,8 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
 	if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
 		printf("TX buffers exhausted in mid frame\n");
 
-	return wait_for_bit(__func__, &regs->txsr, ZYNQ_GEM_TSR_DONE,
-			    true, 20000, true);
+	return wait_for_bit_le32(&regs->txsr, ZYNQ_GEM_TSR_DONE,
+				 true, 20000, true);
 }
 
 /* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c
index 17786f976a..0fc5a28802 100644
--- a/drivers/reset/sti-reset.c
+++ b/drivers/reset/sti-reset.c
@@ -266,8 +266,8 @@ static int sti_reset_program_hw(struct reset_ctl *reset_ctl, int assert)
 		return 0;
 
 	reg = (void __iomem *)base + ch->ack_offset;
-	if (wait_for_bit(__func__, reg, BIT(ch->ack_bit), ctrl_val,
-			 1000, false)) {
+	if (wait_for_bit_le32(reg, BIT(ch->ack_bit), ctrl_val,
+			      1000, false)) {
 		pr_err("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n",
 		      reset_ctl, reset_ctl->dev, reset_ctl->id);
 
diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c
index b0e01aa0e5..0632d26211 100644
--- a/drivers/serial/serial_pic32.c
+++ b/drivers/serial/serial_pic32.c
@@ -51,8 +51,8 @@ static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
 	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
 
 	/* wait for TX FIFO to empty */
-	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
-		     true, CONFIG_SYS_HZ, false);
+	wait_for_bit_le32(base + U_STA, UART_TX_EMPTY,
+			  true, CONFIG_SYS_HZ, false);
 
 	/* send break */
 	writel(UART_TX_BRK, base + U_STASET);
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 228e714e09..8010ab434c 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -394,8 +394,8 @@ out:
 		 * Wait until the transfer is completely done before
 		 * we deactivate CS.
 		 */
-		wait_for_bit(__func__, &reg_base->sr,
-			     ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
+		wait_for_bit_le32(&reg_base->sr,
+				  ATMEL_SPI_SR_TXEMPTY, true, 1000, false);
 
 		atmel_spi_cs_deactivate(dev);
 	}
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index e02f2217f4..dca3fdfdea 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -675,8 +675,8 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTRD,
-			   CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD,
+				CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect read completion error (%i)\n", ret);
 		goto failrd;
@@ -762,9 +762,9 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 				bb_txbuf + rounddown(write_bytes, 4),
 				write_bytes % 4);
 
-		ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL,
-				   CQSPI_REG_SDRAMLEVEL_WR_MASK <<
-				   CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
+		ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL,
+					CQSPI_REG_SDRAMLEVEL_WR_MASK <<
+					CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0);
 		if (ret) {
 			printf("Indirect write timed out (%i)\n", ret);
 			goto failwr;
@@ -775,8 +775,8 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 	}
 
 	/* Check indirect done status */
-	ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTWR,
-			   CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
+	ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR,
+				CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0);
 	if (ret) {
 		printf("Indirect write completion error (%i)\n", ret);
 		goto failwr;
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 2f5345f1cf..5dc69a6865 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -1018,11 +1018,11 @@ static int fsl_qspi_probe(struct udevice *bus)
 	priv->num_chipselect = plat->num_chipselect;
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
@@ -1185,11 +1185,11 @@ static int fsl_qspi_claim_bus(struct udevice *dev)
 	priv = dev_get_priv(bus);
 
 	/* make sure controller is not busy anywhere */
-	ret = wait_for_bit(__func__, &priv->regs->sr,
-			   QSPI_SR_BUSY_MASK |
-			   QSPI_SR_AHB_ACC_MASK |
-			   QSPI_SR_IP_ACC_MASK,
-			   false, 100, false);
+	ret = wait_for_bit_le32(&priv->regs->sr,
+				QSPI_SR_BUSY_MASK |
+				QSPI_SR_AHB_ACC_MASK |
+				QSPI_SR_IP_ACC_MASK,
+				false, 100, false);
 
 	if (ret) {
 		debug("ERROR : The controller is busy\n");
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
index ec4907391c..d1708a8d56 100644
--- a/drivers/spi/mvebu_a3700_spi.c
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -95,8 +95,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 	din_8 = din;
 
 	while (bytelen) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true,100, false);
 		if (ret)
 			return ret;
 
@@ -109,9 +110,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
 		writel(pending_dout, &reg->dout);
 
 		if (din) {
-			ret = wait_for_bit(__func__, &reg->ctrl,
-					   MVEBU_SPI_A3700_XFER_RDY,
-					   true, 100, false);
+			ret = wait_for_bit_le32(&reg->ctrl,
+						MVEBU_SPI_A3700_XFER_RDY,
+						true, 100, false);
 			if (ret)
 				return ret;
 
@@ -160,8 +161,9 @@ static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 	/* Deactivate CS */
 	if (flags & SPI_XFER_END) {
-		ret = wait_for_bit(__func__, &reg->ctrl,
-				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		ret = wait_for_bit_le32(&reg->ctrl,
+					MVEBU_SPI_A3700_XFER_RDY,
+					true, 100, false);
 		if (ret)
 			return ret;
 
@@ -231,8 +233,8 @@ static int mvebu_spi_probe(struct udevice *bus)
 	/* Flush read/write FIFO */
 	data = readl(&reg->cfg);
 	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
-	ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+				false, 1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 1293e18f75..540c016412 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -108,8 +108,8 @@ static void dwc_otg_flush_tx_fifo(struct dwc2_core_regs *regs, const int num)
 
 	writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET),
 	       &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_TXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -127,8 +127,8 @@ static void dwc_otg_flush_rx_fifo(struct dwc2_core_regs *regs)
 	int ret;
 
 	writel(DWC2_GRSTCTL_RXFFLSH, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_RXFFLSH,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -145,15 +145,15 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs)
 	int ret;
 
 	/* Wait for AHB master IDLE state. */
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_AHBIDLE,
+				true, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
 	/* Core Soft Reset */
 	writel(DWC2_GRSTCTL_CSFTRST, &regs->grstctl);
-	ret = wait_for_bit(__func__, &regs->grstctl, DWC2_GRSTCTL_CSFTRST,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->grstctl, DWC2_GRSTCTL_CSFTRST,
+				false, 1000, false);
 	if (ret)
 		printf("%s: Timeout!\n", __func__);
 
@@ -267,8 +267,8 @@ static void dwc_otg_core_host_init(struct udevice *dev,
 		clrsetbits_le32(&regs->hc_regs[i].hcchar,
 				DWC2_HCCHAR_EPDIR,
 				DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS);
-		ret = wait_for_bit(__func__, &regs->hc_regs[i].hcchar,
-				   DWC2_HCCHAR_CHEN, false, 1000, false);
+		ret = wait_for_bit_le32(&regs->hc_regs[i].hcchar,
+					DWC2_HCCHAR_CHEN, false, 1000, false);
 		if (ret)
 			printf("%s: Timeout!\n", __func__);
 	}
@@ -783,8 +783,8 @@ int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle)
 	int ret;
 	uint32_t hcint, hctsiz;
 
-	ret = wait_for_bit(__func__, &hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
-			   1000, false);
+	ret = wait_for_bit_le32(&hc_regs->hcint, DWC2_HCINT_CHHLTD, true,
+				1000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 2c0c63322c..f5320ca298 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -133,8 +133,7 @@ static int ehci_usb_remove(struct udevice *dev)
 	setbits_le32(&ehci->usbcmd, CMD_RESET);
 
 	/* Wait for reset */
-	if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30,
-			 false)) {
+	if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) {
 		printf("Stuck on USB reset.\n");
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index fe2627ea93..2c8fc3c4b1 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -142,13 +142,12 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci)
 
 	/* Stop then Reset */
 	clrbits_le32(usb_cmd, UCMD_RUN_STOP);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RUN_STOP, false, 10000,
-			   false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false);
 	if (ret)
 		return ret;
 
 	setbits_le32(usb_cmd, UCMD_RESET);
-	ret = wait_for_bit(__func__, usb_cmd, UCMD_RESET, false, 10000, false);
+	ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/ohci-lpc32xx.c b/drivers/usb/host/ohci-lpc32xx.c
index 2f2b4b90de..44a49807a4 100644
--- a/drivers/usb/host/ohci-lpc32xx.c
+++ b/drivers/usb/host/ohci-lpc32xx.c
@@ -143,8 +143,8 @@ static int usbpll_setup(void)
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_POSTDIV_2POW(0x01));
 	setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_PWRUP);
 
-	ret = wait_for_bit(__func__, &clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
-			   true, CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS,
+				true, CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -178,8 +178,8 @@ int usb_cpu_init(void)
 
 	/* enable I2C clock */
 	writel(OTG_CLK_I2C_EN, &otg->otg_clk_ctrl);
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, OTG_CLK_I2C_EN, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
@@ -199,8 +199,8 @@ int usb_cpu_init(void)
 			 OTG_CLK_I2C_EN | OTG_CLK_HOST_EN;
 	writel(mask, &otg->otg_clk_ctrl);
 
-	ret = wait_for_bit(__func__, &otg->otg_clk_sts, mask, true,
-			   CONFIG_SYS_HZ, false);
+	ret = wait_for_bit_le32(&otg->otg_clk_sts, mask, true,
+				CONFIG_SYS_HZ, false);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index d47c99644d..71202d7b03 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -55,18 +55,18 @@ static int xhci_rcar_download_fw(struct rcar_xhci *ctx, const u32 *fw_data,
 		setbits_le32(regs + RCAR_USB3_DL_CTRL,
 			     RCAR_USB3_DL_CTRL_FW_SET_DATA0);
 
-		ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-				   RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
-				   10, false);
+		ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+					RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
+					10, false);
 		if (ret)
 			break;
 	}
 
 	clrbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
 
-	ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
-			   RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
-			   10, false);
+	ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
+				RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
+				10, false);
 
 	return ret;
 }
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index f77da2ec97..c0dd689e7c 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -70,26 +70,26 @@ void lcd_ctrl_init(void *lcdbase)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -215,26 +215,26 @@ void lcd_ctrl_init(void *lcdbase)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -299,26 +299,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 
 	/* Disable DISP signal */
 	writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable synchronization */
 	writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable pixel clock */
 	writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	/* Disable PWM */
 	writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   false, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				false, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 
@@ -451,26 +451,26 @@ static void atmel_hlcdc_init(struct udevice *dev)
 	/* Enable LCD */
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 	value = readl(&regs->lcdc_lcden);
 	writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
-	ret = wait_for_bit(__func__, &regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
-			   true, 1000, false);
+	ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
+				true, 1000, false);
 	if (ret)
 		printf("%s: %d: Timeout!\n", __func__, __LINE__);
 }
diff --git a/include/wait_bit.h b/include/wait_bit.h
index e8acfa5776..bd021baa48 100644
--- a/include/wait_bit.h
+++ b/include/wait_bit.h
@@ -16,60 +16,6 @@
 #include <asm/io.h>
 
 /**
- * wait_for_bit()	waits for bit set/cleared in register
- *
- * Function polls register waiting for specific bit(s) change
- * (either 0->1 or 1->0). It can fail under two conditions:
- * - Timeout
- * - User interaction (CTRL-C)
- * Function succeeds only if all bits of masked register are set/cleared
- * (depending on set option).
- *
- * @param prefix	Prefix added to timeout messagge (message visible only
- *			with debug enabled)
- * @param reg		Register that will be read (using readl())
- * @param mask		Bit(s) of register that must be active
- * @param set		Selects wait condition (bit set or clear)
- * @param timeout_ms	Timeout (in miliseconds)
- * @param breakable	Enables CTRL-C interruption
- * @return		0 on success, -ETIMEDOUT or -EINTR on failure
- */
-static inline int wait_for_bit(const char *prefix, const u32 *reg,
-			       const u32 mask, const bool set,
-			       const unsigned int timeout_ms,
-			       const bool breakable)
-{
-	u32 val;
-	unsigned long start = get_timer(0);
-
-	while (1) {
-		val = readl(reg);
-
-		if (!set)
-			val = ~val;
-
-		if ((val & mask) == mask)
-			return 0;
-
-		if (get_timer(start) > timeout_ms)
-			break;
-
-		if (breakable && ctrlc()) {
-			puts("Abort\n");
-			return -EINTR;
-		}
-
-		udelay(1);
-		WATCHDOG_RESET();
-	}
-
-	debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", prefix, reg, mask,
-	      set);
-
-	return -ETIMEDOUT;
-}
-
-/**
  * wait_for_bit_x()	waits for bit set/cleared in register
  *
  * Function polls register waiting for specific bit(s) change
-- 
2.11.0

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

* [U-Boot] [PATCH v10 03/12] drivers: spi: allow limiting reads
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
@ 2018-01-23 16:14   ` Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
                     ` (9 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:14 UTC (permalink / raw)
  To: u-boot

For some SPI controllers it's not possible to keep the CS active between
transfers and they are limited to a known number of bytes.
This splits spi_flash reads into different iterations in order to respect
the SPI controller limits.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 drivers/mtd/spi/spi_flash.c | 3 +++
 include/spi.h               | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 51e28bf07b..e40e1c01de 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -516,6 +516,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 		else
 			read_len = remain_len;
 
+		if (spi->max_read_size)
+			read_len = min(read_len, spi->max_read_size);
+
 		spi_flash_addr(read_addr, cmd);
 
 		ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
diff --git a/include/spi.h b/include/spi.h
index 08c7480fda..4787454e59 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -86,6 +86,8 @@ struct dm_spi_slave_platdata {
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
  * @wordlen:		Size of SPI word in number of bits
+ * @max_read_size:	If non-zero, the maximum number of bytes which can
+ *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
  * @memory_map:		Address of read-only SPI flash access.
@@ -102,6 +104,7 @@ struct spi_slave {
 #endif
 	uint mode;
 	unsigned int wordlen;
+	unsigned int max_read_size;
 	unsigned int max_write_size;
 	void *memory_map;
 
-- 
2.11.0

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

* [U-Boot] [PATCH v10 04/12] drivers: spi: consider command bytes when sending transfers
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
@ 2018-01-23 16:14   ` Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:14 UTC (permalink / raw)
  To: u-boot

Command bytes are part of the written bytes and they should be taken into
account when sending a spi transfer.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: Fix bug introduced in v2: sizeof(cmd) vs len
 v2: Introduce changes requested by Simon Glass:
  - Always include command bytes when determining max write size.

 drivers/mtd/spi/spi_flash.c | 2 +-
 include/spi.h               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index e40e1c01de..294d9f9d79 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -405,7 +405,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 
 		if (spi->max_write_size)
 			chunk_len = min(chunk_len,
-					(size_t)spi->max_write_size);
+					spi->max_write_size - sizeof(cmd));
 
 		spi_flash_addr(write_addr, cmd);
 
diff --git a/include/spi.h b/include/spi.h
index 4787454e59..5a7df1c706 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -89,7 +89,7 @@ struct dm_spi_slave_platdata {
  * @max_read_size:	If non-zero, the maximum number of bytes which can
  *			be read at once.
  * @max_write_size:	If non-zero, the maximum number of bytes which can
- *			be written at once, excluding command bytes.
+ *			be written at once.
  * @memory_map:		Address of read-only SPI flash access.
  * @flags:		Indication of SPI flags.
  */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 05/12] dm: spi: add BCM63xx SPI driver
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
@ 2018-01-23 16:14   ` Álvaro Fernández Rojas
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:14 UTC (permalink / raw)
  To: u-boot

This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: Introduce changes suggested by Daniel Schwierzeck:
 - Remove prefix and use __func__ instead.
 v6: Introduce changes suggested by Jagan Teki:
 - Use cmd instead of val to avoid confusions.
 - Switch to wait_for_bit instead of infinite loop.
 v5: Introduce changes suggested by Jagan Teki:
  - Use long structure instead of a custom bmips_spi_hw structure.
  - Define constants for each SPI core.
 v4: Introduce changes suggested by Jagan Teki:
  - Add data for each HW controller instead of having two separate configs.
  - Also check clock and reset returns as suggested by Simon Glass for HSSPI.
 v3: rename BCM6338 SPI driver to BCM6348
  switch to devfdt_get_addr_size_index()
 v2: no changes

 drivers/spi/Kconfig       |   8 +
 drivers/spi/Makefile      |   1 +
 drivers/spi/bcm63xx_spi.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 442 insertions(+)
 create mode 100644 drivers/spi/bcm63xx_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 494639fb01..ebc71c2e42 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -40,6 +40,14 @@ config ATMEL_SPI
 	  many AT91 (ARM) chips. This driver can be used to access
 	  the SPI Flash, such as AT25DF321.
 
+config BCM63XX_SPI
+	bool "BCM6348 SPI driver"
+	depends on ARCH_BMIPS
+	help
+	  Enable the BCM6348/BCM6358 SPI driver. This driver can be used to
+	  access the SPI NOR flash on platforms embedding these Broadcom
+	  SPI cores.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e3184db67f..5770b3f7cc 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,6 +18,7 @@ endif
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c
new file mode 100644
index 0000000000..f0df6871d8
--- /dev/null
+++ b/drivers/spi/bcm63xx_spi.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/spi/spi-bcm63xx.c:
+ *	Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ *	Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* BCM6348 SPI core */
+#define SPI_6348_CLK			0x06
+#define SPI_6348_CMD			0x00
+#define SPI_6348_CTL			0x40
+#define SPI_6348_CTL_SHIFT		6
+#define SPI_6348_FILL			0x07
+#define SPI_6348_IR_MASK		0x04
+#define SPI_6348_IR_STAT		0x02
+#define SPI_6348_RX			0x80
+#define SPI_6348_RX_SIZE		0x3f
+#define SPI_6348_TX			0x41
+#define SPI_6348_TX_SIZE		0x3f
+
+/* BCM6358 SPI core */
+#define SPI_6358_CLK			0x706
+#define SPI_6358_CMD			0x700
+#define SPI_6358_CTL			0x000
+#define SPI_6358_CTL_SHIFT		14
+#define SPI_6358_FILL			0x707
+#define SPI_6358_IR_MASK		0x702
+#define SPI_6358_IR_STAT		0x704
+#define SPI_6358_RX			0x400
+#define SPI_6358_RX_SIZE		0x220
+#define SPI_6358_TX			0x002
+#define SPI_6358_TX_SIZE		0x21e
+
+/* SPI Clock register */
+#define SPI_CLK_SHIFT		0
+#define SPI_CLK_20MHZ		(0 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_391MHZ	(1 << SPI_CLK_SHIFT)
+#define SPI_CLK_0_781MHZ	(2 << SPI_CLK_SHIFT)
+#define SPI_CLK_1_563MHZ	(3 << SPI_CLK_SHIFT)
+#define SPI_CLK_3_125MHZ	(4 << SPI_CLK_SHIFT)
+#define SPI_CLK_6_250MHZ	(5 << SPI_CLK_SHIFT)
+#define SPI_CLK_12_50MHZ	(6 << SPI_CLK_SHIFT)
+#define SPI_CLK_25MHZ		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_MASK		(7 << SPI_CLK_SHIFT)
+#define SPI_CLK_SSOFF_SHIFT	3
+#define SPI_CLK_SSOFF_2		(2 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_SSOFF_MASK	(7 << SPI_CLK_SSOFF_SHIFT)
+#define SPI_CLK_BSWAP_SHIFT	7
+#define SPI_CLK_BSWAP_MASK	(1 << SPI_CLK_BSWAP_SHIFT)
+
+/* SPI Command register */
+#define SPI_CMD_OP_SHIFT	0
+#define SPI_CMD_OP_START	(0x3 << SPI_CMD_OP_SHIFT)
+#define SPI_CMD_SLAVE_SHIFT	4
+#define SPI_CMD_SLAVE_MASK	(0xf << SPI_CMD_SLAVE_SHIFT)
+#define SPI_CMD_PREPEND_SHIFT	8
+#define SPI_CMD_PREPEND_BYTES	0xf
+#define SPI_CMD_3WIRE_SHIFT	12
+#define SPI_CMD_3WIRE_MASK	(1 << SPI_CMD_3WIRE_SHIFT)
+
+/* SPI Control register */
+#define SPI_CTL_TYPE_FD_RW	0
+#define SPI_CTL_TYPE_HD_W	1
+#define SPI_CTL_TYPE_HD_R	2
+
+/* SPI Interrupt registers */
+#define SPI_IR_DONE_SHIFT	0
+#define SPI_IR_DONE_MASK	(1 << SPI_IR_DONE_SHIFT)
+#define SPI_IR_RXOVER_SHIFT	1
+#define SPI_IR_RXOVER_MASK	(1 << SPI_IR_RXOVER_SHIFT)
+#define SPI_IR_TXUNDER_SHIFT	2
+#define SPI_IR_TXUNDER_MASK	(1 << SPI_IR_TXUNDER_SHIFT)
+#define SPI_IR_TXOVER_SHIFT	3
+#define SPI_IR_TXOVER_MASK	(1 << SPI_IR_TXOVER_SHIFT)
+#define SPI_IR_RXUNDER_SHIFT	4
+#define SPI_IR_RXUNDER_MASK	(1 << SPI_IR_RXUNDER_SHIFT)
+#define SPI_IR_CLEAR_MASK	(SPI_IR_DONE_MASK |\
+				 SPI_IR_RXOVER_MASK |\
+				 SPI_IR_TXUNDER_MASK |\
+				 SPI_IR_TXOVER_MASK |\
+				 SPI_IR_RXUNDER_MASK)
+
+enum bcm63xx_regs_spi {
+	SPI_CLK,
+	SPI_CMD,
+	SPI_CTL,
+	SPI_CTL_SHIFT,
+	SPI_FILL,
+	SPI_IR_MASK,
+	SPI_IR_STAT,
+	SPI_RX,
+	SPI_RX_SIZE,
+	SPI_TX,
+	SPI_TX_SIZE,
+};
+
+struct bcm63xx_spi_priv {
+	const unsigned long *regs;
+	void __iomem *base;
+	size_t tx_bytes;
+	uint8_t num_cs;
+};
+
+#define SPI_CLK_CNT		8
+static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = {
+	{ 25000000, SPI_CLK_25MHZ },
+	{ 20000000, SPI_CLK_20MHZ },
+	{ 12500000, SPI_CLK_12_50MHZ },
+	{  6250000, SPI_CLK_6_250MHZ },
+	{  3125000, SPI_CLK_3_125MHZ },
+	{  1563000, SPI_CLK_1_563MHZ },
+	{   781000, SPI_CLK_0_781MHZ },
+	{   391000, SPI_CLK_0_391MHZ }
+};
+
+static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs,
+			   struct spi_cs_info *info)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+
+	if (cs >= priv->num_cs) {
+		printf("no cs %u\n", cs);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+
+	if (mode & SPI_LSB_FIRST)
+		setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+	else
+		clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK);
+
+	return 0;
+}
+
+static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(bus);
+	const unsigned long *regs = priv->regs;
+	uint8_t clk_cfg;
+	int i;
+
+	/* default to lowest clock configuration */
+	clk_cfg = SPI_CLK_0_391MHZ;
+
+	/* find the closest clock configuration */
+	for (i = 0; i < SPI_CLK_CNT; i++) {
+		if (speed >= bcm63xx_spi_freq_table[i][0]) {
+			clk_cfg = bcm63xx_spi_freq_table[i][1];
+			break;
+		}
+	}
+
+	/* write clock configuration */
+	clrsetbits_8(priv->base + regs[SPI_CLK],
+		     SPI_CLK_SSOFF_MASK | SPI_CLK_MASK,
+		     clk_cfg | SPI_CLK_SSOFF_2);
+
+	return 0;
+}
+
+/*
+ * BCM63xx SPI driver doesn't allow keeping CS active between transfers since
+ * they are HW controlled.
+ * However, it provides a mechanism to prepend write transfers prior to read
+ * transfers (with a maximum prepend of 15 bytes), which is usually enough for
+ * SPI-connected flashes since reading requires prepending a write transfer of
+ * 5 bytes.
+ *
+ * This implementation takes advantage of the prepend mechanism and combines
+ * multiple transfers into a single one where possible (single/multiple write
+ * transfer(s) followed by a final read/write transfer).
+ * However, it's not possible to buffer reads, which means that read transfers
+ * should always be done as the final ones.
+ * On the other hand, take into account that combining write transfers into
+ * a single one is just buffering and doesn't require prepend mechanism.
+ */
+static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	size_t data_bytes = bitlen / 8;
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* clear prepends */
+		priv->tx_bytes = 0;
+
+		/* initialize hardware */
+		writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+	}
+
+	if (din) {
+		/* buffering reads not possible since cs is hw controlled */
+		if (!(flags & SPI_XFER_END)) {
+			printf("unable to buffer reads\n");
+			return -EINVAL;
+		}
+
+		/* check rx size */
+		 if (data_bytes > regs[SPI_RX_SIZE]) {
+			printf("max rx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+	}
+
+	if (dout) {
+		/* check tx size */
+		if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) {
+			printf("max tx bytes exceeded\n");
+			return -EMSGSIZE;
+		}
+
+		/* copy tx data */
+		memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes,
+			    dout, data_bytes);
+		priv->tx_bytes += data_bytes;
+	}
+
+	if (flags & SPI_XFER_END) {
+		struct dm_spi_slave_platdata *plat =
+			dev_get_parent_platdata(dev);
+		uint16_t val, cmd;
+		int ret;
+
+		/* determine control config */
+		if (dout && !din) {
+			/* buffered write transfers */
+			val = priv->tx_bytes;
+			val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]);
+			priv->tx_bytes = 0;
+		} else {
+			if (dout && din && (flags & SPI_XFER_ONCE)) {
+				/* full duplex read/write */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_FD_RW <<
+					regs[SPI_CTL_SHIFT]);
+				priv->tx_bytes = 0;
+			} else {
+				/* prepended write transfer */
+				val = data_bytes;
+				val |= (SPI_CTL_TYPE_HD_R <<
+					regs[SPI_CTL_SHIFT]);
+				if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) {
+					printf("max prepend bytes exceeded\n");
+					return -EMSGSIZE;
+				}
+			}
+		}
+
+		if (regs[SPI_CTL_SHIFT] >= 8)
+			writew_be(val, priv->base + regs[SPI_CTL]);
+		else
+			writeb_be(val, priv->base + regs[SPI_CTL]);
+
+		/* clear interrupts */
+		writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]);
+
+		/* issue the transfer */
+		cmd = SPI_CMD_OP_START;
+		cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK;
+		cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT);
+		if (plat->mode & SPI_3WIRE)
+			cmd |= SPI_CMD_3WIRE_MASK;
+		writew_be(cmd, priv->base + regs[SPI_CMD]);
+
+		/* enable interrupts */
+		writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]);
+
+		ret = wait_for_bit_8(priv->base + regs[SPI_IR_STAT],
+				     SPI_IR_DONE_MASK, true, 1000, false);
+		if (ret) {
+			printf("interrupt timeout\n");
+			return ret;
+		}
+
+		/* copy rx data */
+		if (din)
+			memcpy_fromio(din, priv->base + regs[SPI_RX],
+				      data_bytes);
+	}
+
+	return 0;
+}
+
+static const struct dm_spi_ops bcm63xx_spi_ops = {
+	.cs_info = bcm63xx_spi_cs_info,
+	.set_mode = bcm63xx_spi_set_mode,
+	.set_speed = bcm63xx_spi_set_speed,
+	.xfer = bcm63xx_spi_xfer,
+};
+
+static const unsigned long bcm6348_spi_regs[] = {
+	[SPI_CLK] = SPI_6348_CLK,
+	[SPI_CMD] = SPI_6348_CMD,
+	[SPI_CTL] = SPI_6348_CTL,
+	[SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT,
+	[SPI_FILL] = SPI_6348_FILL,
+	[SPI_IR_MASK] = SPI_6348_IR_MASK,
+	[SPI_IR_STAT] = SPI_6348_IR_STAT,
+	[SPI_RX] = SPI_6348_RX,
+	[SPI_RX_SIZE] = SPI_6348_RX_SIZE,
+	[SPI_TX] = SPI_6348_TX,
+	[SPI_TX_SIZE] = SPI_6348_TX_SIZE,
+};
+
+static const unsigned long bcm6358_spi_regs[] = {
+	[SPI_CLK] = SPI_6358_CLK,
+	[SPI_CMD] = SPI_6358_CMD,
+	[SPI_CTL] = SPI_6358_CTL,
+	[SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT,
+	[SPI_FILL] = SPI_6358_FILL,
+	[SPI_IR_MASK] = SPI_6358_IR_MASK,
+	[SPI_IR_STAT] = SPI_6358_IR_STAT,
+	[SPI_RX] = SPI_6358_RX,
+	[SPI_RX_SIZE] = SPI_6358_RX_SIZE,
+	[SPI_TX] = SPI_6358_TX,
+	[SPI_TX_SIZE] = SPI_6358_TX_SIZE,
+};
+
+static const struct udevice_id bcm63xx_spi_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-spi",
+		.data = (ulong)&bcm6348_spi_regs,
+	}, {
+		.compatible = "brcm,bcm6358-spi",
+		.data = (ulong)&bcm6358_spi_regs,
+	}, { /* sentinel */ }
+};
+
+static int bcm63xx_spi_child_pre_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent);
+	const unsigned long *regs = priv->regs;
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+
+	/* check cs */
+	if (plat->cs >= priv->num_cs) {
+		printf("no cs %u\n", plat->cs);
+		return -ENODEV;
+	}
+
+	/* max read/write sizes */
+	slave->max_read_size = regs[SPI_RX_SIZE];
+	slave->max_write_size = regs[SPI_TX_SIZE];
+
+	return 0;
+}
+
+static int bcm63xx_spi_probe(struct udevice *dev)
+{
+	struct bcm63xx_spi_priv *priv = dev_get_priv(dev);
+	const unsigned long *regs =
+		(const unsigned long *)dev_get_driver_data(dev);
+	struct reset_ctl rst_ctl;
+	struct clk clk;
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int ret;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = regs;
+	priv->base = ioremap(addr, size);
+	priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "num-cs", 8);
+
+	/* enable clock */
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_free(&clk);
+	if (ret < 0)
+		return ret;
+
+	/* perform reset */
+	ret = reset_get_by_index(dev, 0, &rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_deassert(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	ret = reset_free(&rst_ctl);
+	if (ret < 0)
+		return ret;
+
+	/* initialize hardware */
+	writeb_be(0, priv->base + regs[SPI_IR_MASK]);
+
+	/* set fill register */
+	writeb_be(0xff, priv->base + regs[SPI_FILL]);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm63xx_spi) = {
+	.name = "bcm63xx_spi",
+	.id = UCLASS_SPI,
+	.of_match = bcm63xx_spi_ids,
+	.ops = &bcm63xx_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv),
+	.child_pre_probe = bcm63xx_spi_child_pre_probe,
+	.probe = bcm63xx_spi_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v10 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
@ 2018-01-23 16:14   ` Álvaro Fernández Rojas
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:14 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6338.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index eb51a4372b..0cab44cb8d 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6338";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -109,6 +113,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6338_CLK_SPI>;
+			resets = <&periph_rst BCM6338_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe3100 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe3100 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v10 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2018-01-23 16:14   ` [U-Boot] [PATCH v10 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
@ 2018-01-23 16:15   ` Álvaro Fernández Rojas
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:15 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: rename BCM6338 SPI driver to BCM6348
 v2: add spi alias

 arch/mips/dts/brcm,bcm6348.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 711b643b5a..540b9fea5b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6348";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -118,6 +122,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0c00 {
+			compatible = "brcm,bcm6348-spi";
+			reg = <0xfffe0c00 0xc0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6348_CLK_SPI>;
+			resets = <&periph_rst BCM6348_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe2300 {
 			compatible = "brcm,bcm6338-mc";
 			reg = <0xfffe2300 0x38>;
-- 
2.11.0

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

* [U-Boot] [PATCH v10 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
@ 2018-01-23 16:15   ` Álvaro Fernández Rojas
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:15 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm6358.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 4f63cf80e0..1662783279 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm6358";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0xfffe0000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at fffe0800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0xfffe0800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM6358_CLK_SPI>;
+			resets = <&periph_rst BCM6358_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <4>;
+
+			status = "disabled";
+		};
+
 		memory-controller at fffe1200 {
 			compatible = "brcm,bcm6358-mc";
 			reg = <0xfffe1200 0x4c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v10 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
@ 2018-01-23 16:15   ` Álvaro Fernández Rojas
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:15 UTC (permalink / raw)
  To: u-boot

This driver manages the SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm3380.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
index 64245eb048..f83a6ea8df 100644
--- a/arch/mips/dts/brcm,bcm3380.dtsi
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -12,6 +12,10 @@
 / {
 	compatible = "brcm,bcm3380";
 
+	aliases {
+		spi0 = &spi;
+	};
+
 	cpus {
 		reg = <0x14e00000 0x4>;
 		#address-cells = <1>;
@@ -142,6 +146,19 @@
 			status = "disabled";
 		};
 
+		spi: spi at 14e02000 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x14e02000 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk0 BCM3380_CLK0_SPI>;
+			resets = <&periph_rst0 BCM3380_RST0_SPI>;
+			spi-max-frequency = <25000000>;
+			num-cs = <6>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 14e00f00 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x14e00f00 0x1c>;
-- 
2.11.0

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

* [U-Boot] [PATCH v10 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
@ 2018-01-23 16:15   ` Álvaro Fernández Rojas
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:15 UTC (permalink / raw)
  To: u-boot

This driver manages the low speed SPI controller present on this SoC.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v7: no changes
 v6: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: add spi alias

 arch/mips/dts/brcm,bcm63268.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 113a96bef8..6e3d9c3820 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -13,6 +13,10 @@
 / {
 	compatible = "brcm,bcm63268";
 
+	aliases {
+		spi0 = &lsspi;
+	};
+
 	cpus {
 		reg = <0x10000000 0x4>;
 		#address-cells = <1>;
@@ -136,6 +140,19 @@
 			#power-domain-cells = <1>;
 		};
 
+		lsspi: spi at 10000800 {
+			compatible = "brcm,bcm6358-spi";
+			reg = <0x10000800 0x70c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&periph_clk BCM63268_CLK_SPI>;
+			resets = <&periph_rst BCM63268_RST_SPI>;
+			spi-max-frequency = <20000000>;
+			num-cs = <8>;
+
+			status = "disabled";
+		};
+
 		leds: led-controller at 10001900 {
 			compatible = "brcm,bcm6328-leds";
 			reg = <0x10001900 0x24>;
-- 
2.11.0

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

* [U-Boot] [PATCH v10 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (9 preceding siblings ...)
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
@ 2018-01-23 16:15   ` Álvaro Fernández Rojas
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
  2018-01-26  6:04   ` [U-Boot] [PATCH v10 00/12] mips: bmips: add SPI support Jagan Teki
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:15 UTC (permalink / raw)
  To: u-boot

It's a Winbond (w25x32) 4 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v10: no changes
 v9: Introduce changes suggested by Simon Glass:
  - Fix defconfig order.
 v8: no changes
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: rename BCM6338 SPI driver to BCM6348
 v2: remove spi alias

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index be15fe5551..dd0e5b8b7c 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -44,6 +44,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index cfc56cba37..07a125cec6 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -26,6 +26,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_MISC is not set
@@ -34,8 +36,14 @@ CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_BCM63XX_SPI=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (10 preceding siblings ...)
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
@ 2018-01-23 16:15   ` Álvaro Fernández Rojas
  2018-01-26  6:04   ` [U-Boot] [PATCH v10 00/12] mips: bmips: add SPI support Jagan Teki
  12 siblings, 0 replies; 187+ messages in thread
From: Álvaro Fernández Rojas @ 2018-01-23 16:15 UTC (permalink / raw)
  To: u-boot

It's a Spansion (s25fl064a) 8 MB SPI flash.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Reviewed-by: Jagan Teki <jagan@openedev.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v10: no changes
 v9: Introduce changes suggested by Simon Glass:
  - Fix defconfig order.
 v8: no changes
 v7: no changes
 v6: no changes
 v5: sync with master
 v4: switch to CONFIG_BCM63XX_SPI
 v3: no changes
 v2: remove spi alias

 arch/mips/dts/netgear,cg3100d.dts     | 12 ++++++++++++
 configs/netgear_cg3100d_ram_defconfig |  8 ++++++++
 2 files changed, 20 insertions(+)

diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index db1e2e7616..5f85c7346f 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -90,6 +90,18 @@
 	status = "okay";
 };
 
+&spi {
+	status = "okay";
+
+	spi-flash at 0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
 &uart0 {
 	u-boot,dm-pre-reloc;
 	status = "okay";
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
index 7665c78d3f..fb998f03bf 100644
--- a/configs/netgear_cg3100d_ram_defconfig
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -25,6 +25,8 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 # CONFIG_CMD_MISC is not set
@@ -35,9 +37,15 @@ CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_MTD=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DM_SERIAL=y
 CONFIG_BCM6345_SERIAL=y
+CONFIG_DM_SPI=y
+CONFIG_BCM63XX_SPI=y
 CONFIG_WDT_BCM6345=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 00/12] mips: bmips: add SPI support
  2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
                     ` (11 preceding siblings ...)
  2018-01-23 16:15   ` [U-Boot] [PATCH v10 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
@ 2018-01-26  6:04   ` Jagan Teki
  12 siblings, 0 replies; 187+ messages in thread
From: Jagan Teki @ 2018-01-26  6:04 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 23, 2018 at 9:44 PM, Álvaro Fernández Rojas
<noltari@gmail.com> wrote:
> BCM63xx SPI controller is a bit tricky since it doesn't allow keeping CS
> active between transfers, so I had to modify the spi_flash driver in order
> to allow limiting reads.
>
> v10: Introduce changes reported by Tom Rini & Daniel Schwierzeck:
> - Fix undefined BE read functions
> v9: Introduce changes suggested by Simon Glass:
> - Fix defconfig order.
> v8: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
> - Squash wait_bit commits.
> - Remove register param castings.
> v7: Introduce changes suggested by Jagan Teki & Daniel Schwierzeck:
> - Use const void* reg for compatibility with 64 bit systems.
> - Remove prefix and use __func__ instead.
> - Remove wait_for_bit and update callers to wait_for_bit_le32.
> v6: Introduce changes suggested by Jagan Teki:
> - Use cmd instead of val to avoid confusions.
> - Switch to wait_for_bit instead of infinite loop.
> v5: Introduce changes suggested by Jagan Teki:
> - Use long structs for registers
> v4: Introduce changes suggested by Jagan Teki:
> - Add data for each HW controller instead of having two separate configs.
> v3: Fix bug introduced in v2: sizeof(cmd) vs len.
> Also rename BCM6338 SPI driver to BCM6348 SPI since BCM6338 is a stripped
> down version of the BCM6348.
> Switch to devfdt_get_addr_size_index().
> v2: Introduce changes requested by Simon Glass:
> - Always include command bytes when determining max write size.
> Also move SPI aliases from .dts to .dtsi files.
>
> Álvaro Fernández Rojas (12):
>   wait_bit: add 8/16/32 BE/LE versions of wait_for_bit
>   wait_bit: use wait_for_bit_le32 and remove wait_for_bit
>   drivers: spi: allow limiting reads
>   drivers: spi: consider command bytes when sending transfers
>   dm: spi: add BCM63xx SPI driver
>   mips: bmips: add bcm63xx-spi driver support for BCM6338
>   mips: bmips: add bcm63xx-spi driver support for BCM6348
>   mips: bmips: add bcm63xx-spi driver support for BCM6358
>   mips: bmips: add bcm63xx-spi driver support for BCM3380
>   mips: bmips: add bcm63xx-spi driver support for BCM63268
>   mips: bmips: enable the SPI flash on the Sagem F at ST1704
>   mips: bmips: enable the SPI flash on the Netgear CG3100D

Applied to u-boot-spi/master, thanks!

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

end of thread, other threads:[~2018-01-26  6:04 UTC | newest]

Thread overview: 187+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-18 19:29 [U-Boot] [PATCH 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2017-05-20  2:29   ` Simon Glass
2017-05-18 19:29 ` [U-Boot] [PATCH 02/10] drivers: spi: add config to consider command bytes when writting to flash Álvaro Fernández Rojas
2017-05-20  2:29   ` Simon Glass
2017-05-20  8:06     ` Álvaro Fernández Rojas
2017-05-30  5:04       ` Jagan Teki
2017-05-30 17:34         ` Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2017-05-20  2:29   ` Simon Glass
2017-06-07  7:35   ` Jagan Teki
2017-06-07 15:35     ` Álvaro Fernández Rojas
2017-06-07 17:29       ` Jagan Teki
2017-06-07 18:35         ` Álvaro Fernández Rojas
2017-06-12  6:02           ` Jagan Teki
2017-06-12 12:48             ` Simon Glass
2017-05-18 19:29 ` [U-Boot] [PATCH 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2017-05-18 19:29 ` [U-Boot] [PATCH 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2017-05-22 18:21 ` [U-Boot] [PATCH v2 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2017-05-22 20:27     ` Simon Glass
2017-06-07  7:30     ` Jagan Teki
2017-06-07 15:33       ` Álvaro Fernández Rojas
2017-06-07 17:28         ` Jagan Teki
2017-06-07 18:36           ` Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2017-05-22 18:21   ` [U-Boot] [PATCH v2 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2017-06-03  9:57 ` [U-Boot] [PATCH v3 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
2017-06-03  9:57   ` [U-Boot] [PATCH v3 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2017-06-04  9:06     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2017-06-04  9:08     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2017-06-04  9:12     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2017-06-04  9:13     ` Daniel Schwierzeck
2017-06-07  8:00     ` Jagan Teki
2017-06-07 15:38       ` Álvaro Fernández Rojas
2017-06-07 17:30         ` Jagan Teki
2017-06-07 18:29           ` Álvaro Fernández Rojas
2017-06-03  9:57   ` [U-Boot] [PATCH v3 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2017-06-04  9:14     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2017-06-04  9:14     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2017-06-04  9:15     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2017-06-04  9:15     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2017-06-04  9:16     ` Daniel Schwierzeck
2017-06-03  9:57   ` [U-Boot] [PATCH v3 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2017-06-04  9:17     ` Daniel Schwierzeck
2017-06-14  9:57 ` [U-Boot] [PATCH v4 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2017-06-15  5:38     ` Jagan Teki
2017-06-15  9:24       ` Álvaro Fernández Rojas
2017-06-19 11:37         ` Jagan Teki
2017-06-14  9:57   ` [U-Boot] [PATCH v4 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2017-06-14  9:57   ` [U-Boot] [PATCH v4 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2017-07-30 12:13 ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 01/10] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2017-08-10  9:12     ` Jagan Teki
2017-07-30 12:13   ` [U-Boot] [PATCH v5 02/10] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2017-08-10  9:13     ` Jagan Teki
2017-07-30 12:13   ` [U-Boot] [PATCH v5 03/10] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2017-08-10  9:25     ` Jagan Teki
2017-08-11  9:11       ` Jagan Teki
2017-12-26 12:21       ` Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 04/10] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 05/10] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 06/10] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 07/10] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 08/10] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 09/10] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2017-07-30 12:13   ` [U-Boot] [PATCH v5 10/10] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2017-08-07  8:35   ` [U-Boot] [PATCH v5 00/10] mips: bmips: add SPI support Jagan Teki
2017-08-07 10:00     ` Daniel Schwierzeck
2018-01-02 19:01   ` [U-Boot] [PATCH v6 00/11] " Álvaro Fernández Rojas
2018-01-02 19:01     ` [U-Boot] [PATCH v6 01/11] wait_bit: add big endian version of wait_for_bit function Álvaro Fernández Rojas
2018-01-02 20:24       ` Daniel Schwierzeck
2018-01-07 18:08       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 02/11] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2018-01-02 19:01     ` [U-Boot] [PATCH v6 03/11] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2018-01-02 19:01     ` [U-Boot] [PATCH v6 04/11] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2018-01-07 18:10       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 05/11] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2018-01-07 18:11       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 06/11] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2018-01-07 18:12       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 07/11] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2018-01-07 18:12       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 08/11] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2018-01-07 18:13       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 09/11] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2018-01-07 18:13       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 10/11] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2018-01-07 18:14       ` Jagan Teki
2018-01-02 19:01     ` [U-Boot] [PATCH v6 11/11] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2018-01-07 18:14       ` Jagan Teki
2018-01-10 20:26 ` [U-Boot] [PATCH v7 00/13] mips: bmips: add SPI support Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 01/13] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
2018-01-11  1:50     ` Daniel Schwierzeck
2018-01-11  7:13       ` Jagan Teki
2018-01-10 20:26   ` [U-Boot] [PATCH v7 02/13] wait_bit: use wait_for_bit_le32 instead " Álvaro Fernández Rojas
2018-01-11  1:50     ` Daniel Schwierzeck
2018-01-11  7:14       ` Jagan Teki
2018-01-10 20:26   ` [U-Boot] [PATCH v7 03/13] wait_bit: remove old wait_for_bit function Álvaro Fernández Rojas
2018-01-11  1:51     ` Daniel Schwierzeck
2018-01-10 20:26   ` [U-Boot] [PATCH v7 04/13] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 05/13] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 06/13] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 07/13] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 08/13] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 09/13] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 10/13] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 11/13] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 12/13] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2018-01-10 20:26   ` [U-Boot] [PATCH v7 13/13] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2018-01-11 17:11 ` [U-Boot] [PATCH v8 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
2018-01-11 17:11   ` [U-Boot] [PATCH v8 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
2018-01-11 17:17     ` Jagan Teki
2018-01-11 17:42       ` Álvaro Fernández Rojas
2018-01-11 17:11   ` [U-Boot] [PATCH v8 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
2018-01-11 17:11   ` [U-Boot] [PATCH v8 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2018-01-11 17:11   ` [U-Boot] [PATCH v8 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2018-01-11 17:11   ` [U-Boot] [PATCH v8 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2018-01-11 17:11   ` [U-Boot] [PATCH v8 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2018-01-16 14:56     ` Simon Glass
2018-01-11 17:11   ` [U-Boot] [PATCH v8 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2018-01-16 14:57     ` Simon Glass
2018-01-11 17:11   ` [U-Boot] [PATCH v8 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2018-01-16 14:57     ` Simon Glass
2018-01-11 17:11   ` [U-Boot] [PATCH v8 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2018-01-16 14:57     ` Simon Glass
2018-01-11 17:11   ` [U-Boot] [PATCH v8 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2018-01-16 14:57     ` Simon Glass
2018-01-11 17:11   ` [U-Boot] [PATCH v8 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2018-01-16 14:57     ` Simon Glass
2018-01-11 17:11   ` [U-Boot] [PATCH v8 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2018-01-16 14:57     ` Simon Glass
2018-01-20  1:11 ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2018-01-20  1:11   ` [U-Boot] [PATCH v9 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2018-01-22  5:07   ` [U-Boot] [PATCH v9 00/12] mips: bmips: add SPI support Jagan Teki
2018-01-23 16:14 ` [U-Boot] [PATCH v10 " Álvaro Fernández Rojas
2018-01-23 16:14   ` [U-Boot] [PATCH v10 01/12] wait_bit: add 8/16/32 BE/LE versions of wait_for_bit Álvaro Fernández Rojas
2018-01-23 16:14   ` [U-Boot] [PATCH v10 02/12] wait_bit: use wait_for_bit_le32 and remove wait_for_bit Álvaro Fernández Rojas
2018-01-23 16:14   ` [U-Boot] [PATCH v10 03/12] drivers: spi: allow limiting reads Álvaro Fernández Rojas
2018-01-23 16:14   ` [U-Boot] [PATCH v10 04/12] drivers: spi: consider command bytes when sending transfers Álvaro Fernández Rojas
2018-01-23 16:14   ` [U-Boot] [PATCH v10 05/12] dm: spi: add BCM63xx SPI driver Álvaro Fernández Rojas
2018-01-23 16:14   ` [U-Boot] [PATCH v10 06/12] mips: bmips: add bcm63xx-spi driver support for BCM6338 Álvaro Fernández Rojas
2018-01-23 16:15   ` [U-Boot] [PATCH v10 07/12] mips: bmips: add bcm63xx-spi driver support for BCM6348 Álvaro Fernández Rojas
2018-01-23 16:15   ` [U-Boot] [PATCH v10 08/12] mips: bmips: add bcm63xx-spi driver support for BCM6358 Álvaro Fernández Rojas
2018-01-23 16:15   ` [U-Boot] [PATCH v10 09/12] mips: bmips: add bcm63xx-spi driver support for BCM3380 Álvaro Fernández Rojas
2018-01-23 16:15   ` [U-Boot] [PATCH v10 10/12] mips: bmips: add bcm63xx-spi driver support for BCM63268 Álvaro Fernández Rojas
2018-01-23 16:15   ` [U-Boot] [PATCH v10 11/12] mips: bmips: enable the SPI flash on the Sagem F@ST1704 Álvaro Fernández Rojas
2018-01-23 16:15   ` [U-Boot] [PATCH v10 12/12] mips: bmips: enable the SPI flash on the Netgear CG3100D Álvaro Fernández Rojas
2018-01-26  6:04   ` [U-Boot] [PATCH v10 00/12] mips: bmips: add SPI support Jagan Teki

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.